]>
Commit | Line | Data |
---|---|---|
f035d41b XL |
1 | use std::mem; |
2 | use std::vec::Vec; | |
3 | ||
4 | use crate::elf; | |
5 | use crate::endian::*; | |
fc512014 | 6 | use crate::pod::{bytes_of, BytesMut, WritableBuffer}; |
f035d41b XL |
7 | use crate::write::string::*; |
8 | use crate::write::util::*; | |
9 | use crate::write::*; | |
10 | ||
fc512014 XL |
11 | #[derive(Default, Clone, Copy)] |
12 | struct ComdatOffsets { | |
13 | offset: usize, | |
14 | str_id: Option<StringId>, | |
15 | len: usize, | |
16 | } | |
17 | ||
f035d41b XL |
18 | #[derive(Default, Clone, Copy)] |
19 | struct SectionOffsets { | |
20 | index: usize, | |
21 | offset: usize, | |
22 | str_id: Option<StringId>, | |
23 | reloc_index: usize, | |
24 | reloc_offset: usize, | |
25 | reloc_len: usize, | |
26 | reloc_str_id: Option<StringId>, | |
27 | } | |
28 | ||
29 | #[derive(Default, Clone, Copy)] | |
30 | struct SymbolOffsets { | |
31 | index: usize, | |
32 | str_id: Option<StringId>, | |
33 | } | |
34 | ||
35 | impl Object { | |
36 | pub(crate) fn elf_section_info( | |
37 | &self, | |
38 | section: StandardSection, | |
39 | ) -> (&'static [u8], &'static [u8], SectionKind) { | |
40 | match section { | |
41 | StandardSection::Text => (&[], &b".text"[..], SectionKind::Text), | |
42 | StandardSection::Data => (&[], &b".data"[..], SectionKind::Data), | |
43 | StandardSection::ReadOnlyData | StandardSection::ReadOnlyString => { | |
44 | (&[], &b".rodata"[..], SectionKind::ReadOnlyData) | |
45 | } | |
46 | StandardSection::ReadOnlyDataWithRel => (&[], b".data.rel.ro", SectionKind::Data), | |
47 | StandardSection::UninitializedData => { | |
48 | (&[], &b".bss"[..], SectionKind::UninitializedData) | |
49 | } | |
50 | StandardSection::Tls => (&[], &b".tdata"[..], SectionKind::Tls), | |
51 | StandardSection::UninitializedTls => { | |
52 | (&[], &b".tbss"[..], SectionKind::UninitializedTls) | |
53 | } | |
54 | StandardSection::TlsVariables => { | |
55 | // Unsupported section. | |
56 | (&[], &[], SectionKind::TlsVariables) | |
57 | } | |
58 | StandardSection::Common => { | |
59 | // Unsupported section. | |
60 | (&[], &[], SectionKind::Common) | |
61 | } | |
62 | } | |
63 | } | |
64 | ||
65 | pub(crate) fn elf_subsection_name(&self, section: &[u8], value: &[u8]) -> Vec<u8> { | |
66 | let mut name = section.to_vec(); | |
67 | name.push(b'.'); | |
68 | name.extend(value); | |
69 | name | |
70 | } | |
71 | ||
72 | fn elf_has_relocation_addend(&self) -> Result<bool> { | |
73 | Ok(match self.architecture { | |
74 | Architecture::Arm => false, | |
75 | Architecture::Aarch64 => true, | |
76 | Architecture::I386 => false, | |
77 | Architecture::X86_64 => true, | |
fc512014 | 78 | Architecture::S390x => true, |
f035d41b XL |
79 | _ => { |
80 | return Err(Error(format!( | |
81 | "unimplemented architecture {:?}", | |
82 | self.architecture | |
83 | ))); | |
84 | } | |
85 | }) | |
86 | } | |
87 | ||
88 | pub(crate) fn elf_fixup_relocation(&mut self, mut relocation: &mut Relocation) -> Result<i64> { | |
89 | // Return true if we should use a section symbol to avoid preemption. | |
90 | fn want_section_symbol(relocation: &Relocation, symbol: &Symbol) -> bool { | |
91 | if symbol.scope != SymbolScope::Dynamic { | |
92 | // Only dynamic symbols can be preemptible. | |
93 | return false; | |
94 | } | |
95 | match symbol.kind { | |
96 | SymbolKind::Text | SymbolKind::Data => {} | |
97 | _ => return false, | |
98 | } | |
99 | match relocation.kind { | |
100 | // Anything using GOT or PLT is preemptible. | |
101 | // We also require that `Other` relocations must already be correct. | |
102 | RelocationKind::Got | |
103 | | RelocationKind::GotRelative | |
104 | | RelocationKind::GotBaseRelative | |
105 | | RelocationKind::PltRelative | |
106 | | RelocationKind::Elf(_) => return false, | |
107 | // Absolute relocations are preemptible for non-local data. | |
108 | // TODO: not sure if this rule is exactly correct | |
109 | // This rule was added to handle global data references in debuginfo. | |
110 | // Maybe this should be a new relocation kind so that the caller can decide. | |
111 | RelocationKind::Absolute => { | |
112 | if symbol.kind == SymbolKind::Data { | |
113 | return false; | |
114 | } | |
115 | } | |
116 | _ => {} | |
117 | } | |
118 | true | |
119 | } | |
120 | ||
121 | // Use section symbols for relocations where required to avoid preemption. | |
122 | // Otherwise, the linker will fail with: | |
123 | // relocation R_X86_64_PC32 against symbol `SomeSymbolName' can not be used when | |
124 | // making a shared object; recompile with -fPIC | |
125 | let symbol = &self.symbols[relocation.symbol.0]; | |
126 | if want_section_symbol(relocation, symbol) { | |
127 | if let Some(section) = symbol.section.id() { | |
128 | relocation.addend += symbol.value as i64; | |
129 | relocation.symbol = self.section_symbol(section); | |
130 | } | |
131 | } | |
132 | ||
133 | // Determine whether the addend is stored in the relocation or the data. | |
134 | if self.elf_has_relocation_addend()? { | |
135 | Ok(0) | |
136 | } else { | |
137 | let constant = relocation.addend; | |
138 | relocation.addend = 0; | |
139 | Ok(constant) | |
140 | } | |
141 | } | |
142 | ||
fc512014 | 143 | pub(crate) fn elf_write(&self, buffer: &mut dyn WritableBuffer) -> Result<()> { |
f035d41b XL |
144 | let address_size = self.architecture.address_size().unwrap(); |
145 | let endian = self.endian; | |
146 | let elf32 = Elf32 { endian }; | |
147 | let elf64 = Elf64 { endian }; | |
148 | let elf: &dyn Elf = match address_size { | |
149 | AddressSize::U32 => &elf32, | |
150 | AddressSize::U64 => &elf64, | |
151 | }; | |
152 | let pointer_align = address_size.bytes() as usize; | |
153 | ||
154 | // Calculate offsets of everything. | |
155 | let mut offset = 0; | |
156 | ||
157 | // ELF header. | |
158 | let e_ehsize = elf.file_header_size(); | |
159 | offset += e_ehsize; | |
160 | ||
161 | // Create reloc section header names. | |
162 | let is_rela = self.elf_has_relocation_addend()?; | |
163 | let reloc_names: Vec<_> = self | |
164 | .sections | |
165 | .iter() | |
166 | .map(|section| { | |
167 | let mut reloc_name = Vec::new(); | |
168 | if !section.relocations.is_empty() { | |
169 | reloc_name.extend_from_slice(if is_rela { | |
170 | &b".rela"[..] | |
171 | } else { | |
172 | &b".rel"[..] | |
173 | }); | |
174 | reloc_name.extend_from_slice(§ion.name); | |
175 | } | |
176 | reloc_name | |
177 | }) | |
178 | .collect(); | |
179 | ||
180 | // Calculate size of section data. | |
181 | let mut shstrtab = StringTable::default(); | |
fc512014 | 182 | let mut comdat_offsets = vec![ComdatOffsets::default(); self.comdats.len()]; |
f035d41b XL |
183 | let mut section_offsets = vec![SectionOffsets::default(); self.sections.len()]; |
184 | // Null section. | |
185 | let mut section_num = 1; | |
fc512014 XL |
186 | for (index, comdat) in self.comdats.iter().enumerate() { |
187 | if comdat.kind != ComdatKind::Any { | |
188 | return Err(Error(format!( | |
189 | "unsupported COMDAT symbol `{}` kind {:?}", | |
190 | self.symbols[comdat.symbol.0].name().unwrap_or(""), | |
191 | comdat.kind | |
192 | ))); | |
193 | } | |
194 | ||
195 | comdat_offsets[index].str_id = Some(shstrtab.add(b".group")); | |
196 | section_num += 1; | |
197 | offset = align(offset, 4); | |
198 | comdat_offsets[index].offset = offset; | |
199 | let len = (comdat.sections.len() + 1) * 4; | |
200 | comdat_offsets[index].len = len; | |
201 | offset += len; | |
202 | } | |
f035d41b XL |
203 | for (index, section) in self.sections.iter().enumerate() { |
204 | section_offsets[index].str_id = Some(shstrtab.add(§ion.name)); | |
205 | section_offsets[index].index = section_num; | |
206 | section_num += 1; | |
207 | ||
208 | let len = section.data.len(); | |
209 | if len != 0 { | |
210 | offset = align(offset, section.align as usize); | |
211 | section_offsets[index].offset = offset; | |
212 | offset += len; | |
213 | } else { | |
214 | section_offsets[index].offset = offset; | |
215 | } | |
216 | ||
217 | if !section.relocations.is_empty() { | |
218 | section_offsets[index].reloc_str_id = Some(shstrtab.add(&reloc_names[index])); | |
219 | section_offsets[index].reloc_index = section_num; | |
220 | section_num += 1; | |
221 | } | |
222 | } | |
223 | ||
224 | // Calculate index of symbols and add symbol strings to strtab. | |
225 | let mut strtab = StringTable::default(); | |
226 | let mut symbol_offsets = vec![SymbolOffsets::default(); self.symbols.len()]; | |
227 | // Null symbol. | |
228 | let mut symtab_count = 1; | |
229 | // Local symbols must come before global. | |
230 | for (index, symbol) in self.symbols.iter().enumerate() { | |
231 | if symbol.is_local() { | |
232 | symbol_offsets[index].index = symtab_count; | |
233 | symtab_count += 1; | |
234 | } | |
235 | } | |
236 | let symtab_count_local = symtab_count; | |
237 | for (index, symbol) in self.symbols.iter().enumerate() { | |
238 | if !symbol.is_local() { | |
239 | symbol_offsets[index].index = symtab_count; | |
240 | symtab_count += 1; | |
241 | } | |
242 | } | |
243 | for (index, symbol) in self.symbols.iter().enumerate() { | |
244 | if symbol.kind != SymbolKind::Section { | |
245 | symbol_offsets[index].str_id = Some(strtab.add(&symbol.name)); | |
246 | } | |
247 | } | |
248 | ||
249 | // Calculate size of symtab. | |
250 | let symtab_str_id = shstrtab.add(&b".symtab"[..]); | |
251 | offset = align(offset, pointer_align); | |
252 | let symtab_offset = offset; | |
253 | let symtab_len = symtab_count * elf.symbol_size(); | |
254 | offset += symtab_len; | |
255 | let symtab_index = section_num; | |
256 | section_num += 1; | |
257 | ||
258 | // Calculate size of symtab_shndx. | |
259 | let mut need_symtab_shndx = false; | |
260 | for symbol in &self.symbols { | |
261 | let index = symbol | |
262 | .section | |
263 | .id() | |
264 | .map(|s| section_offsets[s.0].index) | |
265 | .unwrap_or(0); | |
266 | if index >= elf::SHN_LORESERVE as usize { | |
267 | need_symtab_shndx = true; | |
268 | break; | |
269 | } | |
270 | } | |
271 | let symtab_shndx_offset = offset; | |
272 | let mut symtab_shndx_str_id = None; | |
273 | let mut symtab_shndx_len = 0; | |
274 | if need_symtab_shndx { | |
275 | symtab_shndx_str_id = Some(shstrtab.add(&b".symtab_shndx"[..])); | |
276 | symtab_shndx_len = symtab_count * 4; | |
277 | offset += symtab_shndx_len; | |
278 | section_num += 1; | |
279 | } | |
280 | ||
281 | // Calculate size of strtab. | |
282 | let strtab_str_id = shstrtab.add(&b".strtab"[..]); | |
283 | let strtab_offset = offset; | |
284 | let mut strtab_data = Vec::new(); | |
285 | // Null name. | |
286 | strtab_data.push(0); | |
287 | strtab.write(1, &mut strtab_data); | |
288 | offset += strtab_data.len(); | |
289 | let strtab_index = section_num; | |
290 | section_num += 1; | |
291 | ||
292 | // Calculate size of relocations. | |
293 | for (index, section) in self.sections.iter().enumerate() { | |
294 | let count = section.relocations.len(); | |
295 | if count != 0 { | |
296 | offset = align(offset, pointer_align); | |
297 | section_offsets[index].reloc_offset = offset; | |
298 | let len = count * elf.rel_size(is_rela); | |
299 | section_offsets[index].reloc_len = len; | |
300 | offset += len; | |
301 | } | |
302 | } | |
303 | ||
304 | // Calculate size of shstrtab. | |
305 | let shstrtab_str_id = shstrtab.add(&b".shstrtab"[..]); | |
306 | let shstrtab_offset = offset; | |
307 | let mut shstrtab_data = Vec::new(); | |
308 | // Null section name. | |
309 | shstrtab_data.push(0); | |
310 | shstrtab.write(1, &mut shstrtab_data); | |
311 | offset += shstrtab_data.len(); | |
312 | let shstrtab_index = section_num; | |
313 | section_num += 1; | |
314 | ||
315 | // Calculate size of section headers. | |
316 | offset = align(offset, pointer_align); | |
317 | let e_shoff = offset; | |
318 | let e_shentsize = elf.section_header_size(); | |
319 | offset += section_num * e_shentsize; | |
320 | ||
321 | // Start writing. | |
fc512014 XL |
322 | buffer |
323 | .reserve(offset) | |
324 | .map_err(|_| Error(String::from("Cannot allocate buffer")))?; | |
f035d41b XL |
325 | |
326 | // Write file header. | |
327 | let e_ident = elf::Ident { | |
328 | magic: elf::ELFMAG, | |
329 | class: match address_size { | |
330 | AddressSize::U32 => elf::ELFCLASS32, | |
331 | AddressSize::U64 => elf::ELFCLASS64, | |
332 | }, | |
333 | data: if endian.is_little_endian() { | |
334 | elf::ELFDATA2LSB | |
335 | } else { | |
336 | elf::ELFDATA2MSB | |
337 | }, | |
338 | version: elf::EV_CURRENT, | |
339 | os_abi: elf::ELFOSABI_NONE, | |
340 | abi_version: 0, | |
341 | padding: [0; 7], | |
342 | }; | |
343 | let e_type = elf::ET_REL; | |
344 | let e_machine = match self.architecture { | |
345 | Architecture::Arm => elf::EM_ARM, | |
346 | Architecture::Aarch64 => elf::EM_AARCH64, | |
347 | Architecture::I386 => elf::EM_386, | |
348 | Architecture::X86_64 => elf::EM_X86_64, | |
fc512014 | 349 | Architecture::S390x => elf::EM_S390, |
f035d41b XL |
350 | _ => { |
351 | return Err(Error(format!( | |
352 | "unimplemented architecture {:?}", | |
353 | self.architecture | |
354 | ))); | |
355 | } | |
356 | }; | |
357 | let e_flags = if let FileFlags::Elf { e_flags } = self.flags { | |
358 | e_flags | |
359 | } else { | |
360 | 0 | |
361 | }; | |
362 | let e_shnum = if section_num >= elf::SHN_LORESERVE as usize { | |
363 | 0 | |
364 | } else { | |
365 | section_num as u16 | |
366 | }; | |
367 | let e_shstrndx = if shstrtab_index >= elf::SHN_LORESERVE as usize { | |
368 | elf::SHN_XINDEX | |
369 | } else { | |
370 | shstrtab_index as u16 | |
371 | }; | |
372 | ||
373 | elf.write_file_header( | |
fc512014 | 374 | buffer, |
f035d41b XL |
375 | FileHeader { |
376 | e_ident, | |
377 | e_type, | |
378 | e_machine, | |
379 | e_version: elf::EV_CURRENT.into(), | |
380 | e_entry: 0, | |
381 | e_phoff: 0, | |
382 | e_shoff: e_shoff as u64, | |
383 | e_flags, | |
384 | e_ehsize: e_ehsize as u16, | |
385 | e_phentsize: 0, | |
386 | e_phnum: 0, | |
387 | e_shentsize: e_shentsize as u16, | |
388 | e_shnum, | |
389 | e_shstrndx, | |
390 | }, | |
391 | ); | |
392 | ||
393 | // Write section data. | |
fc512014 XL |
394 | for (index, comdat) in self.comdats.iter().enumerate() { |
395 | let mut data = BytesMut::new(); | |
396 | data.write(&U32::new(endian, elf::GRP_COMDAT)); | |
397 | for section in &comdat.sections { | |
398 | data.write(&U32::new(endian, section_offsets[section.0].index as u32)); | |
399 | } | |
400 | ||
401 | write_align(buffer, 4); | |
402 | debug_assert_eq!(comdat_offsets[index].offset, buffer.len()); | |
403 | debug_assert_eq!(comdat_offsets[index].len, data.len()); | |
404 | buffer.extend(data.as_slice()); | |
405 | } | |
f035d41b XL |
406 | for (index, section) in self.sections.iter().enumerate() { |
407 | let len = section.data.len(); | |
408 | if len != 0 { | |
fc512014 | 409 | write_align(buffer, section.align as usize); |
f035d41b | 410 | debug_assert_eq!(section_offsets[index].offset, buffer.len()); |
fc512014 | 411 | buffer.extend(section.data.as_slice()); |
f035d41b XL |
412 | } |
413 | } | |
414 | ||
415 | // Write symbols. | |
fc512014 | 416 | write_align(buffer, pointer_align); |
f035d41b XL |
417 | debug_assert_eq!(symtab_offset, buffer.len()); |
418 | elf.write_symbol( | |
fc512014 | 419 | buffer, |
f035d41b XL |
420 | Sym { |
421 | st_name: 0, | |
422 | st_info: 0, | |
423 | st_other: 0, | |
424 | st_shndx: 0, | |
425 | st_value: 0, | |
426 | st_size: 0, | |
427 | }, | |
428 | ); | |
429 | let mut symtab_shndx = BytesMut::new(); | |
430 | if need_symtab_shndx { | |
431 | symtab_shndx.write(&U32::new(endian, 0)); | |
432 | } | |
433 | let mut write_symbol = |index: usize, symbol: &Symbol| -> Result<()> { | |
434 | let st_info = if let SymbolFlags::Elf { st_info, .. } = symbol.flags { | |
435 | st_info | |
436 | } else { | |
437 | let st_type = match symbol.kind { | |
438 | SymbolKind::Null => elf::STT_NOTYPE, | |
439 | SymbolKind::Text => { | |
440 | if symbol.is_undefined() { | |
441 | elf::STT_NOTYPE | |
442 | } else { | |
443 | elf::STT_FUNC | |
444 | } | |
445 | } | |
446 | SymbolKind::Data => { | |
447 | if symbol.is_undefined() { | |
448 | elf::STT_NOTYPE | |
449 | } else if symbol.is_common() { | |
450 | elf::STT_COMMON | |
451 | } else { | |
452 | elf::STT_OBJECT | |
453 | } | |
454 | } | |
455 | SymbolKind::Section => elf::STT_SECTION, | |
456 | SymbolKind::File => elf::STT_FILE, | |
457 | SymbolKind::Tls => elf::STT_TLS, | |
458 | SymbolKind::Label => elf::STT_NOTYPE, | |
459 | SymbolKind::Unknown => { | |
460 | if symbol.is_undefined() { | |
461 | elf::STT_NOTYPE | |
462 | } else { | |
463 | return Err(Error(format!( | |
464 | "unimplemented symbol `{}` kind {:?}", | |
465 | symbol.name().unwrap_or(""), | |
466 | symbol.kind | |
467 | ))); | |
468 | } | |
469 | } | |
470 | }; | |
fc512014 XL |
471 | let st_bind = if symbol.weak { |
472 | elf::STB_WEAK | |
473 | } else if symbol.is_undefined() { | |
f035d41b XL |
474 | elf::STB_GLOBAL |
475 | } else if symbol.is_local() { | |
476 | elf::STB_LOCAL | |
f035d41b XL |
477 | } else { |
478 | elf::STB_GLOBAL | |
479 | }; | |
480 | (st_bind << 4) + st_type | |
481 | }; | |
482 | let st_other = if let SymbolFlags::Elf { st_other, .. } = symbol.flags { | |
483 | st_other | |
484 | } else if symbol.scope == SymbolScope::Linkage { | |
485 | elf::STV_HIDDEN | |
486 | } else { | |
487 | elf::STV_DEFAULT | |
488 | }; | |
489 | let (st_shndx, xindex) = match symbol.section { | |
490 | SymbolSection::None => { | |
491 | debug_assert_eq!(symbol.kind, SymbolKind::File); | |
492 | (elf::SHN_ABS, 0) | |
493 | } | |
494 | SymbolSection::Undefined => (elf::SHN_UNDEF, 0), | |
495 | SymbolSection::Absolute => (elf::SHN_ABS, 0), | |
496 | SymbolSection::Common => (elf::SHN_COMMON, 0), | |
497 | SymbolSection::Section(id) => { | |
498 | let index = section_offsets[id.0].index as u32; | |
499 | ( | |
500 | if index >= elf::SHN_LORESERVE as u32 { | |
501 | elf::SHN_XINDEX | |
502 | } else { | |
503 | index as u16 | |
504 | }, | |
505 | index, | |
506 | ) | |
507 | } | |
508 | }; | |
509 | let st_name = symbol_offsets[index] | |
510 | .str_id | |
511 | .map(|id| strtab.get_offset(id)) | |
512 | .unwrap_or(0) as u32; | |
513 | elf.write_symbol( | |
fc512014 | 514 | buffer, |
f035d41b XL |
515 | Sym { |
516 | st_name, | |
517 | st_info, | |
518 | st_other, | |
519 | st_shndx, | |
520 | st_value: symbol.value, | |
521 | st_size: symbol.size, | |
522 | }, | |
523 | ); | |
524 | if need_symtab_shndx { | |
525 | symtab_shndx.write(&U32::new(endian, xindex)); | |
526 | } | |
527 | Ok(()) | |
528 | }; | |
529 | for (index, symbol) in self.symbols.iter().enumerate() { | |
530 | if symbol.is_local() { | |
531 | write_symbol(index, symbol)?; | |
532 | } | |
533 | } | |
534 | for (index, symbol) in self.symbols.iter().enumerate() { | |
535 | if !symbol.is_local() { | |
536 | write_symbol(index, symbol)?; | |
537 | } | |
538 | } | |
539 | if need_symtab_shndx { | |
540 | debug_assert_eq!(symtab_shndx_offset, buffer.len()); | |
541 | debug_assert_eq!(symtab_shndx_len, symtab_shndx.len()); | |
fc512014 | 542 | buffer.extend(symtab_shndx.as_slice()); |
f035d41b XL |
543 | } |
544 | ||
545 | // Write strtab section. | |
546 | debug_assert_eq!(strtab_offset, buffer.len()); | |
547 | buffer.extend(&strtab_data); | |
548 | ||
549 | // Write relocations. | |
550 | for (index, section) in self.sections.iter().enumerate() { | |
551 | if !section.relocations.is_empty() { | |
fc512014 | 552 | write_align(buffer, pointer_align); |
f035d41b XL |
553 | debug_assert_eq!(section_offsets[index].reloc_offset, buffer.len()); |
554 | for reloc in §ion.relocations { | |
555 | let r_type = match self.architecture { | |
556 | Architecture::I386 => match (reloc.kind, reloc.size) { | |
557 | (RelocationKind::Absolute, 32) => elf::R_386_32, | |
558 | (RelocationKind::Relative, 32) => elf::R_386_PC32, | |
559 | (RelocationKind::Got, 32) => elf::R_386_GOT32, | |
560 | (RelocationKind::PltRelative, 32) => elf::R_386_PLT32, | |
561 | (RelocationKind::GotBaseOffset, 32) => elf::R_386_GOTOFF, | |
562 | (RelocationKind::GotBaseRelative, 32) => elf::R_386_GOTPC, | |
563 | (RelocationKind::Absolute, 16) => elf::R_386_16, | |
564 | (RelocationKind::Relative, 16) => elf::R_386_PC16, | |
565 | (RelocationKind::Absolute, 8) => elf::R_386_8, | |
566 | (RelocationKind::Relative, 8) => elf::R_386_PC8, | |
567 | (RelocationKind::Elf(x), _) => x, | |
568 | _ => { | |
569 | return Err(Error(format!("unimplemented relocation {:?}", reloc))); | |
570 | } | |
571 | }, | |
572 | Architecture::X86_64 => match (reloc.kind, reloc.encoding, reloc.size) { | |
573 | (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => { | |
574 | elf::R_X86_64_64 | |
575 | } | |
576 | (RelocationKind::Relative, _, 32) => elf::R_X86_64_PC32, | |
577 | (RelocationKind::Got, _, 32) => elf::R_X86_64_GOT32, | |
578 | (RelocationKind::PltRelative, _, 32) => elf::R_X86_64_PLT32, | |
579 | (RelocationKind::GotRelative, _, 32) => elf::R_X86_64_GOTPCREL, | |
580 | (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => { | |
581 | elf::R_X86_64_32 | |
582 | } | |
583 | (RelocationKind::Absolute, RelocationEncoding::X86Signed, 32) => { | |
584 | elf::R_X86_64_32S | |
585 | } | |
586 | (RelocationKind::Absolute, _, 16) => elf::R_X86_64_16, | |
587 | (RelocationKind::Relative, _, 16) => elf::R_X86_64_PC16, | |
588 | (RelocationKind::Absolute, _, 8) => elf::R_X86_64_8, | |
589 | (RelocationKind::Relative, _, 8) => elf::R_X86_64_PC8, | |
590 | (RelocationKind::Elf(x), _, _) => x, | |
591 | _ => { | |
592 | return Err(Error(format!("unimplemented relocation {:?}", reloc))); | |
593 | } | |
594 | }, | |
595 | Architecture::Aarch64 => match (reloc.kind, reloc.encoding, reloc.size) { | |
596 | (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => { | |
597 | elf::R_AARCH64_ABS32 | |
598 | } | |
599 | (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => { | |
600 | elf::R_AARCH64_ABS64 | |
601 | } | |
602 | (RelocationKind::Elf(x), _, _) => x, | |
603 | _ => { | |
604 | return Err(Error(format!("unimplemented relocation {:?}", reloc))); | |
605 | } | |
606 | }, | |
fc512014 XL |
607 | Architecture::S390x => match (reloc.kind, reloc.encoding, reloc.size) { |
608 | (RelocationKind::Absolute, RelocationEncoding::Generic, 8) => { | |
609 | elf::R_390_8 | |
610 | } | |
611 | (RelocationKind::Absolute, RelocationEncoding::Generic, 16) => { | |
612 | elf::R_390_16 | |
613 | } | |
614 | (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => { | |
615 | elf::R_390_32 | |
616 | } | |
617 | (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => { | |
618 | elf::R_390_64 | |
619 | } | |
620 | (RelocationKind::Relative, RelocationEncoding::Generic, 16) => { | |
621 | elf::R_390_PC16 | |
622 | } | |
623 | (RelocationKind::Relative, RelocationEncoding::Generic, 32) => { | |
624 | elf::R_390_PC32 | |
625 | } | |
626 | (RelocationKind::Relative, RelocationEncoding::Generic, 64) => { | |
627 | elf::R_390_PC64 | |
628 | } | |
629 | (RelocationKind::Relative, RelocationEncoding::S390xDbl, 16) => { | |
630 | elf::R_390_PC16DBL | |
631 | } | |
632 | (RelocationKind::Relative, RelocationEncoding::S390xDbl, 32) => { | |
633 | elf::R_390_PC32DBL | |
634 | } | |
635 | (RelocationKind::PltRelative, RelocationEncoding::S390xDbl, 16) => { | |
636 | elf::R_390_PLT16DBL | |
637 | } | |
638 | (RelocationKind::PltRelative, RelocationEncoding::S390xDbl, 32) => { | |
639 | elf::R_390_PLT32DBL | |
640 | } | |
641 | (RelocationKind::Got, RelocationEncoding::Generic, 16) => { | |
642 | elf::R_390_GOT16 | |
643 | } | |
644 | (RelocationKind::Got, RelocationEncoding::Generic, 32) => { | |
645 | elf::R_390_GOT32 | |
646 | } | |
647 | (RelocationKind::Got, RelocationEncoding::Generic, 64) => { | |
648 | elf::R_390_GOT64 | |
649 | } | |
650 | (RelocationKind::GotRelative, RelocationEncoding::S390xDbl, 32) => { | |
651 | elf::R_390_GOTENT | |
652 | } | |
653 | (RelocationKind::GotBaseOffset, RelocationEncoding::Generic, 16) => { | |
654 | elf::R_390_GOTOFF16 | |
655 | } | |
656 | (RelocationKind::GotBaseOffset, RelocationEncoding::Generic, 32) => { | |
657 | elf::R_390_GOTOFF32 | |
658 | } | |
659 | (RelocationKind::GotBaseOffset, RelocationEncoding::Generic, 64) => { | |
660 | elf::R_390_GOTOFF64 | |
661 | } | |
662 | (RelocationKind::GotBaseRelative, RelocationEncoding::Generic, 64) => { | |
663 | elf::R_390_GOTPC | |
664 | } | |
665 | (RelocationKind::GotBaseRelative, RelocationEncoding::S390xDbl, 32) => { | |
666 | elf::R_390_GOTPCDBL | |
667 | } | |
668 | (RelocationKind::Elf(x), _, _) => x, | |
669 | _ => { | |
670 | return Err(Error(format!("unimplemented relocation {:?}", reloc))); | |
671 | } | |
672 | }, | |
f035d41b XL |
673 | _ => { |
674 | return Err(Error(format!( | |
675 | "unimplemented architecture {:?}", | |
676 | self.architecture | |
677 | ))); | |
678 | } | |
679 | }; | |
680 | let r_sym = symbol_offsets[reloc.symbol.0].index as u32; | |
681 | elf.write_rel( | |
fc512014 | 682 | buffer, |
f035d41b XL |
683 | is_rela, |
684 | Rel { | |
685 | r_offset: reloc.offset, | |
686 | r_sym, | |
687 | r_type, | |
688 | r_addend: reloc.addend, | |
689 | }, | |
690 | ); | |
691 | } | |
692 | } | |
693 | } | |
694 | ||
695 | // Write shstrtab section. | |
696 | debug_assert_eq!(shstrtab_offset, buffer.len()); | |
697 | buffer.extend(&shstrtab_data); | |
698 | ||
699 | // Write section headers. | |
fc512014 | 700 | write_align(buffer, pointer_align); |
f035d41b XL |
701 | debug_assert_eq!(e_shoff, buffer.len()); |
702 | elf.write_section_header( | |
fc512014 | 703 | buffer, |
f035d41b XL |
704 | SectionHeader { |
705 | sh_name: 0, | |
706 | sh_type: 0, | |
707 | sh_flags: 0, | |
708 | sh_addr: 0, | |
709 | sh_offset: 0, | |
710 | sh_size: if section_num >= elf::SHN_LORESERVE as usize { | |
711 | section_num as u64 | |
712 | } else { | |
713 | 0 | |
714 | }, | |
715 | sh_link: if shstrtab_index >= elf::SHN_LORESERVE as usize { | |
716 | shstrtab_index as u32 | |
717 | } else { | |
718 | 0 | |
719 | }, | |
720 | // TODO: e_phnum overflow | |
721 | sh_info: 0, | |
722 | sh_addralign: 0, | |
723 | sh_entsize: 0, | |
724 | }, | |
725 | ); | |
fc512014 XL |
726 | for (index, comdat) in self.comdats.iter().enumerate() { |
727 | let sh_name = comdat_offsets[index] | |
728 | .str_id | |
729 | .map(|id| shstrtab.get_offset(id)) | |
730 | .unwrap_or(0) as u32; | |
731 | elf.write_section_header( | |
732 | buffer, | |
733 | SectionHeader { | |
734 | sh_name, | |
735 | sh_type: elf::SHT_GROUP, | |
736 | sh_flags: 0, | |
737 | sh_addr: 0, | |
738 | sh_offset: comdat_offsets[index].offset as u64, | |
739 | sh_size: comdat_offsets[index].len as u64, | |
740 | sh_link: symtab_index as u32, | |
741 | sh_info: symbol_offsets[comdat.symbol.0].index as u32, | |
742 | sh_addralign: 4, | |
743 | sh_entsize: 4, | |
744 | }, | |
745 | ); | |
746 | } | |
f035d41b XL |
747 | for (index, section) in self.sections.iter().enumerate() { |
748 | let sh_type = match section.kind { | |
749 | SectionKind::UninitializedData | SectionKind::UninitializedTls => elf::SHT_NOBITS, | |
750 | SectionKind::Note => elf::SHT_NOTE, | |
751 | _ => elf::SHT_PROGBITS, | |
752 | }; | |
753 | let sh_flags = if let SectionFlags::Elf { sh_flags } = section.flags { | |
754 | sh_flags | |
755 | } else { | |
756 | match section.kind { | |
757 | SectionKind::Text => elf::SHF_ALLOC | elf::SHF_EXECINSTR, | |
758 | SectionKind::Data => elf::SHF_ALLOC | elf::SHF_WRITE, | |
759 | SectionKind::Tls => elf::SHF_ALLOC | elf::SHF_WRITE | elf::SHF_TLS, | |
760 | SectionKind::UninitializedData => elf::SHF_ALLOC | elf::SHF_WRITE, | |
761 | SectionKind::UninitializedTls => elf::SHF_ALLOC | elf::SHF_WRITE | elf::SHF_TLS, | |
762 | SectionKind::ReadOnlyData => elf::SHF_ALLOC, | |
763 | SectionKind::ReadOnlyString => { | |
764 | elf::SHF_ALLOC | elf::SHF_STRINGS | elf::SHF_MERGE | |
765 | } | |
766 | SectionKind::OtherString => elf::SHF_STRINGS | elf::SHF_MERGE, | |
767 | SectionKind::Other | |
768 | | SectionKind::Debug | |
769 | | SectionKind::Metadata | |
770 | | SectionKind::Linker | |
771 | | SectionKind::Note => 0, | |
772 | SectionKind::Unknown | SectionKind::Common | SectionKind::TlsVariables => { | |
773 | return Err(Error(format!( | |
774 | "unimplemented section `{}` kind {:?}", | |
775 | section.name().unwrap_or(""), | |
776 | section.kind | |
777 | ))); | |
778 | } | |
779 | } | |
780 | .into() | |
781 | }; | |
782 | // TODO: not sure if this is correct, maybe user should determine this | |
783 | let sh_entsize = match section.kind { | |
784 | SectionKind::ReadOnlyString | SectionKind::OtherString => 1, | |
785 | _ => 0, | |
786 | }; | |
787 | let sh_name = section_offsets[index] | |
788 | .str_id | |
789 | .map(|id| shstrtab.get_offset(id)) | |
790 | .unwrap_or(0) as u32; | |
791 | elf.write_section_header( | |
fc512014 | 792 | buffer, |
f035d41b XL |
793 | SectionHeader { |
794 | sh_name, | |
795 | sh_type, | |
796 | sh_flags, | |
797 | sh_addr: 0, | |
798 | sh_offset: section_offsets[index].offset as u64, | |
799 | sh_size: section.size, | |
800 | sh_link: 0, | |
801 | sh_info: 0, | |
802 | sh_addralign: section.align, | |
803 | sh_entsize, | |
804 | }, | |
805 | ); | |
806 | ||
807 | if !section.relocations.is_empty() { | |
808 | let sh_name = section_offsets[index] | |
809 | .reloc_str_id | |
810 | .map(|id| shstrtab.get_offset(id)) | |
811 | .unwrap_or(0); | |
812 | elf.write_section_header( | |
fc512014 | 813 | buffer, |
f035d41b XL |
814 | SectionHeader { |
815 | sh_name: sh_name as u32, | |
816 | sh_type: if is_rela { elf::SHT_RELA } else { elf::SHT_REL }, | |
817 | sh_flags: elf::SHF_INFO_LINK.into(), | |
818 | sh_addr: 0, | |
819 | sh_offset: section_offsets[index].reloc_offset as u64, | |
820 | sh_size: section_offsets[index].reloc_len as u64, | |
821 | sh_link: symtab_index as u32, | |
822 | sh_info: section_offsets[index].index as u32, | |
823 | sh_addralign: pointer_align as u64, | |
824 | sh_entsize: elf.rel_size(is_rela) as u64, | |
825 | }, | |
826 | ); | |
827 | } | |
828 | } | |
829 | ||
830 | // Write symtab section header. | |
831 | elf.write_section_header( | |
fc512014 | 832 | buffer, |
f035d41b XL |
833 | SectionHeader { |
834 | sh_name: shstrtab.get_offset(symtab_str_id) as u32, | |
835 | sh_type: elf::SHT_SYMTAB, | |
836 | sh_flags: 0, | |
837 | sh_addr: 0, | |
838 | sh_offset: symtab_offset as u64, | |
839 | sh_size: symtab_len as u64, | |
840 | sh_link: strtab_index as u32, | |
841 | sh_info: symtab_count_local as u32, | |
842 | sh_addralign: pointer_align as u64, | |
843 | sh_entsize: elf.symbol_size() as u64, | |
844 | }, | |
845 | ); | |
846 | ||
847 | // Write symtab_shndx section header. | |
848 | if need_symtab_shndx { | |
849 | elf.write_section_header( | |
fc512014 | 850 | buffer, |
f035d41b XL |
851 | SectionHeader { |
852 | sh_name: shstrtab.get_offset(symtab_shndx_str_id.unwrap()) as u32, | |
853 | sh_type: elf::SHT_SYMTAB_SHNDX, | |
854 | sh_flags: 0, | |
855 | sh_addr: 0, | |
856 | sh_offset: symtab_shndx_offset as u64, | |
857 | sh_size: symtab_shndx_len as u64, | |
858 | sh_link: symtab_index as u32, | |
859 | sh_info: symtab_count_local as u32, | |
860 | sh_addralign: 4, | |
861 | sh_entsize: 4, | |
862 | }, | |
863 | ); | |
864 | } | |
865 | ||
866 | // Write strtab section header. | |
867 | elf.write_section_header( | |
fc512014 | 868 | buffer, |
f035d41b XL |
869 | SectionHeader { |
870 | sh_name: shstrtab.get_offset(strtab_str_id) as u32, | |
871 | sh_type: elf::SHT_STRTAB, | |
872 | sh_flags: 0, | |
873 | sh_addr: 0, | |
874 | sh_offset: strtab_offset as u64, | |
875 | sh_size: strtab_data.len() as u64, | |
876 | sh_link: 0, | |
877 | sh_info: 0, | |
878 | sh_addralign: 1, | |
879 | sh_entsize: 0, | |
880 | }, | |
881 | ); | |
882 | ||
883 | // Write shstrtab section header. | |
884 | elf.write_section_header( | |
fc512014 | 885 | buffer, |
f035d41b XL |
886 | SectionHeader { |
887 | sh_name: shstrtab.get_offset(shstrtab_str_id) as u32, | |
888 | sh_type: elf::SHT_STRTAB, | |
889 | sh_flags: 0, | |
890 | sh_addr: 0, | |
891 | sh_offset: shstrtab_offset as u64, | |
892 | sh_size: shstrtab_data.len() as u64, | |
893 | sh_link: 0, | |
894 | sh_info: 0, | |
895 | sh_addralign: 1, | |
896 | sh_entsize: 0, | |
897 | }, | |
898 | ); | |
899 | ||
fc512014 XL |
900 | debug_assert_eq!(offset, buffer.len()); |
901 | ||
902 | Ok(()) | |
f035d41b XL |
903 | } |
904 | } | |
905 | ||
906 | /// Native endian version of `FileHeader64`. | |
907 | struct FileHeader { | |
908 | e_ident: elf::Ident, | |
909 | e_type: u16, | |
910 | e_machine: u16, | |
911 | e_version: u32, | |
912 | e_entry: u64, | |
913 | e_phoff: u64, | |
914 | e_shoff: u64, | |
915 | e_flags: u32, | |
916 | e_ehsize: u16, | |
917 | e_phentsize: u16, | |
918 | e_phnum: u16, | |
919 | e_shentsize: u16, | |
920 | e_shnum: u16, | |
921 | e_shstrndx: u16, | |
922 | } | |
923 | ||
924 | /// Native endian version of `SectionHeader64`. | |
925 | struct SectionHeader { | |
926 | sh_name: u32, | |
927 | sh_type: u32, | |
928 | sh_flags: u64, | |
929 | sh_addr: u64, | |
930 | sh_offset: u64, | |
931 | sh_size: u64, | |
932 | sh_link: u32, | |
933 | sh_info: u32, | |
934 | sh_addralign: u64, | |
935 | sh_entsize: u64, | |
936 | } | |
937 | ||
938 | /// Native endian version of `Sym64`. | |
939 | struct Sym { | |
940 | st_name: u32, | |
941 | st_info: u8, | |
942 | st_other: u8, | |
943 | st_shndx: u16, | |
944 | st_value: u64, | |
945 | st_size: u64, | |
946 | } | |
947 | ||
948 | /// Unified native endian version of `Rel*`. | |
949 | struct Rel { | |
950 | r_offset: u64, | |
951 | r_sym: u32, | |
952 | r_type: u32, | |
953 | r_addend: i64, | |
954 | } | |
955 | ||
956 | trait Elf { | |
957 | fn file_header_size(&self) -> usize; | |
958 | fn section_header_size(&self) -> usize; | |
959 | fn symbol_size(&self) -> usize; | |
960 | fn rel_size(&self, is_rela: bool) -> usize; | |
fc512014 XL |
961 | fn write_file_header(&self, buffer: &mut dyn WritableBuffer, section: FileHeader); |
962 | fn write_section_header(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader); | |
963 | fn write_symbol(&self, buffer: &mut dyn WritableBuffer, symbol: Sym); | |
964 | fn write_rel(&self, buffer: &mut dyn WritableBuffer, is_rela: bool, rel: Rel); | |
f035d41b XL |
965 | } |
966 | ||
967 | struct Elf32<E> { | |
968 | endian: E, | |
969 | } | |
970 | ||
971 | impl<E: Endian> Elf for Elf32<E> { | |
972 | fn file_header_size(&self) -> usize { | |
973 | mem::size_of::<elf::FileHeader32<E>>() | |
974 | } | |
975 | ||
976 | fn section_header_size(&self) -> usize { | |
977 | mem::size_of::<elf::SectionHeader32<E>>() | |
978 | } | |
979 | ||
980 | fn symbol_size(&self) -> usize { | |
981 | mem::size_of::<elf::Sym32<E>>() | |
982 | } | |
983 | ||
984 | fn rel_size(&self, is_rela: bool) -> usize { | |
985 | if is_rela { | |
986 | mem::size_of::<elf::Rela32<E>>() | |
987 | } else { | |
988 | mem::size_of::<elf::Rel32<E>>() | |
989 | } | |
990 | } | |
991 | ||
fc512014 | 992 | fn write_file_header(&self, buffer: &mut dyn WritableBuffer, file: FileHeader) { |
f035d41b XL |
993 | let endian = self.endian; |
994 | let file = elf::FileHeader32 { | |
995 | e_ident: file.e_ident, | |
996 | e_type: U16::new(endian, file.e_type), | |
997 | e_machine: U16::new(endian, file.e_machine), | |
998 | e_version: U32::new(endian, file.e_version), | |
999 | e_entry: U32::new(endian, file.e_entry as u32), | |
1000 | e_phoff: U32::new(endian, file.e_phoff as u32), | |
1001 | e_shoff: U32::new(endian, file.e_shoff as u32), | |
1002 | e_flags: U32::new(endian, file.e_flags), | |
1003 | e_ehsize: U16::new(endian, file.e_ehsize), | |
1004 | e_phentsize: U16::new(endian, file.e_phentsize), | |
1005 | e_phnum: U16::new(endian, file.e_phnum), | |
1006 | e_shentsize: U16::new(endian, file.e_shentsize), | |
1007 | e_shnum: U16::new(endian, file.e_shnum), | |
1008 | e_shstrndx: U16::new(endian, file.e_shstrndx), | |
1009 | }; | |
fc512014 | 1010 | buffer.extend(bytes_of(&file)); |
f035d41b XL |
1011 | } |
1012 | ||
fc512014 | 1013 | fn write_section_header(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader) { |
f035d41b XL |
1014 | let endian = self.endian; |
1015 | let section = elf::SectionHeader32 { | |
1016 | sh_name: U32::new(endian, section.sh_name), | |
1017 | sh_type: U32::new(endian, section.sh_type), | |
1018 | sh_flags: U32::new(endian, section.sh_flags as u32), | |
1019 | sh_addr: U32::new(endian, section.sh_addr as u32), | |
1020 | sh_offset: U32::new(endian, section.sh_offset as u32), | |
1021 | sh_size: U32::new(endian, section.sh_size as u32), | |
1022 | sh_link: U32::new(endian, section.sh_link), | |
1023 | sh_info: U32::new(endian, section.sh_info), | |
1024 | sh_addralign: U32::new(endian, section.sh_addralign as u32), | |
1025 | sh_entsize: U32::new(endian, section.sh_entsize as u32), | |
1026 | }; | |
fc512014 | 1027 | buffer.extend(bytes_of(§ion)); |
f035d41b XL |
1028 | } |
1029 | ||
fc512014 | 1030 | fn write_symbol(&self, buffer: &mut dyn WritableBuffer, symbol: Sym) { |
f035d41b XL |
1031 | let endian = self.endian; |
1032 | let symbol = elf::Sym32 { | |
1033 | st_name: U32::new(endian, symbol.st_name), | |
1034 | st_info: symbol.st_info, | |
1035 | st_other: symbol.st_other, | |
1036 | st_shndx: U16::new(endian, symbol.st_shndx), | |
1037 | st_value: U32::new(endian, symbol.st_value as u32), | |
1038 | st_size: U32::new(endian, symbol.st_size as u32), | |
1039 | }; | |
fc512014 | 1040 | buffer.extend(bytes_of(&symbol)); |
f035d41b XL |
1041 | } |
1042 | ||
fc512014 | 1043 | fn write_rel(&self, buffer: &mut dyn WritableBuffer, is_rela: bool, rel: Rel) { |
f035d41b XL |
1044 | let endian = self.endian; |
1045 | if is_rela { | |
1046 | let rel = elf::Rela32 { | |
1047 | r_offset: U32::new(endian, rel.r_offset as u32), | |
1048 | r_info: elf::Rel32::r_info(endian, rel.r_sym, rel.r_type as u8), | |
1049 | r_addend: I32::new(endian, rel.r_addend as i32), | |
1050 | }; | |
fc512014 | 1051 | buffer.extend(bytes_of(&rel)); |
f035d41b XL |
1052 | } else { |
1053 | let rel = elf::Rel32 { | |
1054 | r_offset: U32::new(endian, rel.r_offset as u32), | |
1055 | r_info: elf::Rel32::r_info(endian, rel.r_sym, rel.r_type as u8), | |
1056 | }; | |
fc512014 | 1057 | buffer.extend(bytes_of(&rel)); |
f035d41b XL |
1058 | } |
1059 | } | |
1060 | } | |
1061 | ||
1062 | struct Elf64<E> { | |
1063 | endian: E, | |
1064 | } | |
1065 | ||
1066 | impl<E: Endian> Elf for Elf64<E> { | |
1067 | fn file_header_size(&self) -> usize { | |
1068 | mem::size_of::<elf::FileHeader64<E>>() | |
1069 | } | |
1070 | ||
1071 | fn section_header_size(&self) -> usize { | |
1072 | mem::size_of::<elf::SectionHeader64<E>>() | |
1073 | } | |
1074 | ||
1075 | fn symbol_size(&self) -> usize { | |
1076 | mem::size_of::<elf::Sym64<E>>() | |
1077 | } | |
1078 | ||
1079 | fn rel_size(&self, is_rela: bool) -> usize { | |
1080 | if is_rela { | |
1081 | mem::size_of::<elf::Rela64<E>>() | |
1082 | } else { | |
1083 | mem::size_of::<elf::Rel64<E>>() | |
1084 | } | |
1085 | } | |
1086 | ||
fc512014 | 1087 | fn write_file_header(&self, buffer: &mut dyn WritableBuffer, file: FileHeader) { |
f035d41b XL |
1088 | let endian = self.endian; |
1089 | let file = elf::FileHeader64 { | |
1090 | e_ident: file.e_ident, | |
1091 | e_type: U16::new(endian, file.e_type), | |
1092 | e_machine: U16::new(endian, file.e_machine), | |
1093 | e_version: U32::new(endian, file.e_version), | |
1094 | e_entry: U64::new(endian, file.e_entry), | |
1095 | e_phoff: U64::new(endian, file.e_phoff), | |
1096 | e_shoff: U64::new(endian, file.e_shoff), | |
1097 | e_flags: U32::new(endian, file.e_flags), | |
1098 | e_ehsize: U16::new(endian, file.e_ehsize), | |
1099 | e_phentsize: U16::new(endian, file.e_phentsize), | |
1100 | e_phnum: U16::new(endian, file.e_phnum), | |
1101 | e_shentsize: U16::new(endian, file.e_shentsize), | |
1102 | e_shnum: U16::new(endian, file.e_shnum), | |
1103 | e_shstrndx: U16::new(endian, file.e_shstrndx), | |
1104 | }; | |
fc512014 | 1105 | buffer.extend(bytes_of(&file)) |
f035d41b XL |
1106 | } |
1107 | ||
fc512014 | 1108 | fn write_section_header(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader) { |
f035d41b XL |
1109 | let endian = self.endian; |
1110 | let section = elf::SectionHeader64 { | |
1111 | sh_name: U32::new(endian, section.sh_name), | |
1112 | sh_type: U32::new(endian, section.sh_type), | |
1113 | sh_flags: U64::new(endian, section.sh_flags), | |
1114 | sh_addr: U64::new(endian, section.sh_addr), | |
1115 | sh_offset: U64::new(endian, section.sh_offset), | |
1116 | sh_size: U64::new(endian, section.sh_size), | |
1117 | sh_link: U32::new(endian, section.sh_link), | |
1118 | sh_info: U32::new(endian, section.sh_info), | |
1119 | sh_addralign: U64::new(endian, section.sh_addralign), | |
1120 | sh_entsize: U64::new(endian, section.sh_entsize), | |
1121 | }; | |
fc512014 | 1122 | buffer.extend(bytes_of(§ion)); |
f035d41b XL |
1123 | } |
1124 | ||
fc512014 | 1125 | fn write_symbol(&self, buffer: &mut dyn WritableBuffer, symbol: Sym) { |
f035d41b XL |
1126 | let endian = self.endian; |
1127 | let symbol = elf::Sym64 { | |
1128 | st_name: U32::new(endian, symbol.st_name), | |
1129 | st_info: symbol.st_info, | |
1130 | st_other: symbol.st_other, | |
1131 | st_shndx: U16::new(endian, symbol.st_shndx), | |
1132 | st_value: U64::new(endian, symbol.st_value), | |
1133 | st_size: U64::new(endian, symbol.st_size), | |
1134 | }; | |
fc512014 | 1135 | buffer.extend(bytes_of(&symbol)); |
f035d41b XL |
1136 | } |
1137 | ||
fc512014 | 1138 | fn write_rel(&self, buffer: &mut dyn WritableBuffer, is_rela: bool, rel: Rel) { |
f035d41b XL |
1139 | let endian = self.endian; |
1140 | if is_rela { | |
1141 | let rel = elf::Rela64 { | |
1142 | r_offset: U64::new(endian, rel.r_offset), | |
1143 | r_info: elf::Rela64::r_info(endian, rel.r_sym, rel.r_type), | |
1144 | r_addend: I64::new(endian, rel.r_addend), | |
1145 | }; | |
fc512014 | 1146 | buffer.extend(bytes_of(&rel)); |
f035d41b XL |
1147 | } else { |
1148 | let rel = elf::Rel64 { | |
1149 | r_offset: U64::new(endian, rel.r_offset), | |
1150 | r_info: elf::Rel64::r_info(endian, rel.r_sym, rel.r_type), | |
1151 | }; | |
fc512014 | 1152 | buffer.extend(bytes_of(&rel)); |
f035d41b XL |
1153 | } |
1154 | } | |
1155 | } |