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