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