1 //! Helper for writing ELF files.
2 use std::mem;
3 use std::string::String;
4 use std::vec::Vec;
5 
6 use crate::elf;
7 use crate::endian::*;
8 use crate::write::string::{StringId, StringTable};
9 use crate::write::util;
10 use crate::write::{Error, Result, WritableBuffer};
11 
12 /// The index of an ELF section.
13 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
14 pub struct SectionIndex(pub u32);
15 
16 /// The index of an ELF symbol.
17 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
18 pub struct SymbolIndex(pub u32);
19 
20 /// A helper for writing ELF files.
21 ///
22 /// Writing uses a two phase approach. The first phase builds up all of the information
23 /// that may need to be known ahead of time:
24 /// - build string tables
25 /// - reserve section indices
26 /// - reserve symbol indices
27 /// - reserve file ranges for headers and sections
28 ///
29 /// Some of the information has ordering requirements. For example, strings must be added
30 /// to string tables before reserving the file range for the string table. Symbol indices
31 /// must be reserved after reserving the section indices they reference. There are debug
32 /// asserts to check some of these requirements.
33 ///
34 /// The second phase writes everything out in order. Thus the caller must ensure writing
35 /// is in the same order that file ranges were reserved. There are debug asserts to assist
36 /// with checking this.
37 #[allow(missing_debug_implementations)]
38 pub struct Writer<'a> {
39     endian: Endianness,
40     is_64: bool,
41     is_mips64el: bool,
42     elf_align: usize,
43 
44     buffer: &'a mut dyn WritableBuffer,
45     len: usize,
46 
47     segment_offset: usize,
48     segment_num: u32,
49 
50     section_offset: usize,
51     section_num: u32,
52 
53     shstrtab: StringTable<'a>,
54     shstrtab_str_id: Option<StringId>,
55     shstrtab_index: SectionIndex,
56     shstrtab_offset: usize,
57     shstrtab_data: Vec<u8>,
58 
59     need_strtab: bool,
60     strtab: StringTable<'a>,
61     strtab_str_id: Option<StringId>,
62     strtab_index: SectionIndex,
63     strtab_offset: usize,
64     strtab_data: Vec<u8>,
65 
66     symtab_str_id: Option<StringId>,
67     symtab_index: SectionIndex,
68     symtab_offset: usize,
69     symtab_num: u32,
70 
71     need_symtab_shndx: bool,
72     symtab_shndx_str_id: Option<StringId>,
73     symtab_shndx_offset: usize,
74     symtab_shndx_data: Vec<u8>,
75 
76     need_dynstr: bool,
77     dynstr: StringTable<'a>,
78     dynstr_str_id: Option<StringId>,
79     dynstr_index: SectionIndex,
80     dynstr_offset: usize,
81     dynstr_data: Vec<u8>,
82 
83     dynsym_str_id: Option<StringId>,
84     dynsym_index: SectionIndex,
85     dynsym_offset: usize,
86     dynsym_num: u32,
87 
88     dynamic_str_id: Option<StringId>,
89     dynamic_offset: usize,
90     dynamic_num: usize,
91 
92     hash_str_id: Option<StringId>,
93     hash_offset: usize,
94     hash_size: usize,
95 
96     gnu_hash_str_id: Option<StringId>,
97     gnu_hash_offset: usize,
98     gnu_hash_size: usize,
99 
100     gnu_versym_str_id: Option<StringId>,
101     gnu_versym_offset: usize,
102 
103     gnu_verdef_str_id: Option<StringId>,
104     gnu_verdef_offset: usize,
105     gnu_verdef_size: usize,
106     gnu_verdef_count: u16,
107     gnu_verdef_remaining: u16,
108     gnu_verdaux_remaining: u16,
109 
110     gnu_verneed_str_id: Option<StringId>,
111     gnu_verneed_offset: usize,
112     gnu_verneed_size: usize,
113     gnu_verneed_count: u16,
114     gnu_verneed_remaining: u16,
115     gnu_vernaux_remaining: u16,
116 }
117 
118 impl<'a> Writer<'a> {
119     /// Create a new `Writer` for the given endianness and ELF class.
new(endian: Endianness, is_64: bool, buffer: &'a mut dyn WritableBuffer) -> Self120     pub fn new(endian: Endianness, is_64: bool, buffer: &'a mut dyn WritableBuffer) -> Self {
121         let elf_align = if is_64 { 8 } else { 4 };
122         Writer {
123             endian,
124             is_64,
125             // Determined later.
126             is_mips64el: false,
127             elf_align,
128 
129             buffer,
130             len: 0,
131 
132             segment_offset: 0,
133             segment_num: 0,
134 
135             section_offset: 0,
136             section_num: 0,
137 
138             shstrtab: StringTable::default(),
139             shstrtab_str_id: None,
140             shstrtab_index: SectionIndex(0),
141             shstrtab_offset: 0,
142             shstrtab_data: Vec::new(),
143 
144             need_strtab: false,
145             strtab: StringTable::default(),
146             strtab_str_id: None,
147             strtab_index: SectionIndex(0),
148             strtab_offset: 0,
149             strtab_data: Vec::new(),
150 
151             symtab_str_id: None,
152             symtab_index: SectionIndex(0),
153             symtab_offset: 0,
154             symtab_num: 0,
155 
156             need_symtab_shndx: false,
157             symtab_shndx_str_id: None,
158             symtab_shndx_offset: 0,
159             symtab_shndx_data: Vec::new(),
160 
161             need_dynstr: false,
162             dynstr: StringTable::default(),
163             dynstr_str_id: None,
164             dynstr_index: SectionIndex(0),
165             dynstr_offset: 0,
166             dynstr_data: Vec::new(),
167 
168             dynsym_str_id: None,
169             dynsym_index: SectionIndex(0),
170             dynsym_offset: 0,
171             dynsym_num: 0,
172 
173             dynamic_str_id: None,
174             dynamic_offset: 0,
175             dynamic_num: 0,
176 
177             hash_str_id: None,
178             hash_offset: 0,
179             hash_size: 0,
180 
181             gnu_hash_str_id: None,
182             gnu_hash_offset: 0,
183             gnu_hash_size: 0,
184 
185             gnu_versym_str_id: None,
186             gnu_versym_offset: 0,
187 
188             gnu_verdef_str_id: None,
189             gnu_verdef_offset: 0,
190             gnu_verdef_size: 0,
191             gnu_verdef_count: 0,
192             gnu_verdef_remaining: 0,
193             gnu_verdaux_remaining: 0,
194 
195             gnu_verneed_str_id: None,
196             gnu_verneed_offset: 0,
197             gnu_verneed_size: 0,
198             gnu_verneed_count: 0,
199             gnu_verneed_remaining: 0,
200             gnu_vernaux_remaining: 0,
201         }
202     }
203 
204     /// Return the current file length that has been reserved.
reserved_len(&self) -> usize205     pub fn reserved_len(&self) -> usize {
206         self.len
207     }
208 
209     /// Return the current file length that has been written.
210     #[allow(clippy::len_without_is_empty)]
len(&self) -> usize211     pub fn len(&self) -> usize {
212         self.buffer.len()
213     }
214 
215     /// Reserve a file range with the given size and starting alignment.
216     ///
217     /// Returns the aligned offset of the start of the range.
reserve(&mut self, len: usize, align_start: usize) -> usize218     pub fn reserve(&mut self, len: usize, align_start: usize) -> usize {
219         if len == 0 {
220             return self.len;
221         }
222         self.len = util::align(self.len, align_start);
223         let offset = self.len;
224         self.len += len;
225         offset
226     }
227 
228     /// Write alignment padding bytes.
write_align(&mut self, align_start: usize)229     pub fn write_align(&mut self, align_start: usize) {
230         util::write_align(self.buffer, align_start);
231     }
232 
233     /// Write data.
234     ///
235     /// This is typically used to write section data.
write(&mut self, data: &[u8])236     pub fn write(&mut self, data: &[u8]) {
237         self.buffer.write_bytes(data);
238     }
239 
240     /// Reserve the file range up to the given file offset.
reserve_until(&mut self, offset: usize)241     pub fn reserve_until(&mut self, offset: usize) {
242         debug_assert!(self.len <= offset);
243         self.len = offset;
244     }
245 
246     /// Write padding up to the given file offset.
pad_until(&mut self, offset: usize)247     pub fn pad_until(&mut self, offset: usize) {
248         debug_assert!(self.buffer.len() <= offset);
249         self.buffer.resize(offset);
250     }
251 
file_header_size(&self) -> usize252     fn file_header_size(&self) -> usize {
253         if self.is_64 {
254             mem::size_of::<elf::FileHeader64<Endianness>>()
255         } else {
256             mem::size_of::<elf::FileHeader32<Endianness>>()
257         }
258     }
259 
260     /// Reserve the range for the file header.
261     ///
262     /// This must be at the start of the file.
reserve_file_header(&mut self)263     pub fn reserve_file_header(&mut self) {
264         debug_assert_eq!(self.len, 0);
265         self.reserve(self.file_header_size(), 1);
266     }
267 
268     /// Write the file header.
269     ///
270     /// This must be at the start of the file.
271     ///
272     /// Fields that can be derived from known information are automatically set by this function.
write_file_header(&mut self, header: &FileHeader) -> Result<()>273     pub fn write_file_header(&mut self, header: &FileHeader) -> Result<()> {
274         debug_assert_eq!(self.buffer.len(), 0);
275 
276         self.is_mips64el =
277             self.is_64 && self.endian.is_little_endian() && header.e_machine == elf::EM_MIPS;
278 
279         // Start writing.
280         self.buffer
281             .reserve(self.len)
282             .map_err(|_| Error(String::from("Cannot allocate buffer")))?;
283 
284         // Write file header.
285         let e_ident = elf::Ident {
286             magic: elf::ELFMAG,
287             class: if self.is_64 {
288                 elf::ELFCLASS64
289             } else {
290                 elf::ELFCLASS32
291             },
292             data: if self.endian.is_little_endian() {
293                 elf::ELFDATA2LSB
294             } else {
295                 elf::ELFDATA2MSB
296             },
297             version: elf::EV_CURRENT,
298             os_abi: header.os_abi,
299             abi_version: header.abi_version,
300             padding: [0; 7],
301         };
302 
303         let e_ehsize = self.file_header_size() as u16;
304 
305         let e_phoff = self.segment_offset as u64;
306         let e_phentsize = if self.segment_num == 0 {
307             0
308         } else {
309             self.program_header_size() as u16
310         };
311         // TODO: overflow
312         let e_phnum = self.segment_num as u16;
313 
314         let e_shoff = self.section_offset as u64;
315         let e_shentsize = if self.section_num == 0 {
316             0
317         } else {
318             self.section_header_size() as u16
319         };
320         let e_shnum = if self.section_num >= elf::SHN_LORESERVE.into() {
321             0
322         } else {
323             self.section_num as u16
324         };
325         let e_shstrndx = if self.shstrtab_index.0 >= elf::SHN_LORESERVE.into() {
326             elf::SHN_XINDEX
327         } else {
328             self.shstrtab_index.0 as u16
329         };
330 
331         let endian = self.endian;
332         if self.is_64 {
333             let file = elf::FileHeader64 {
334                 e_ident,
335                 e_type: U16::new(endian, header.e_type),
336                 e_machine: U16::new(endian, header.e_machine),
337                 e_version: U32::new(endian, elf::EV_CURRENT.into()),
338                 e_entry: U64::new(endian, header.e_entry),
339                 e_phoff: U64::new(endian, e_phoff),
340                 e_shoff: U64::new(endian, e_shoff),
341                 e_flags: U32::new(endian, header.e_flags),
342                 e_ehsize: U16::new(endian, e_ehsize),
343                 e_phentsize: U16::new(endian, e_phentsize),
344                 e_phnum: U16::new(endian, e_phnum),
345                 e_shentsize: U16::new(endian, e_shentsize),
346                 e_shnum: U16::new(endian, e_shnum),
347                 e_shstrndx: U16::new(endian, e_shstrndx),
348             };
349             self.buffer.write(&file)
350         } else {
351             let file = elf::FileHeader32 {
352                 e_ident,
353                 e_type: U16::new(endian, header.e_type),
354                 e_machine: U16::new(endian, header.e_machine),
355                 e_version: U32::new(endian, elf::EV_CURRENT.into()),
356                 e_entry: U32::new(endian, header.e_entry as u32),
357                 e_phoff: U32::new(endian, e_phoff as u32),
358                 e_shoff: U32::new(endian, e_shoff as u32),
359                 e_flags: U32::new(endian, header.e_flags),
360                 e_ehsize: U16::new(endian, e_ehsize),
361                 e_phentsize: U16::new(endian, e_phentsize),
362                 e_phnum: U16::new(endian, e_phnum),
363                 e_shentsize: U16::new(endian, e_shentsize),
364                 e_shnum: U16::new(endian, e_shnum),
365                 e_shstrndx: U16::new(endian, e_shstrndx),
366             };
367             self.buffer.write(&file);
368         }
369 
370         Ok(())
371     }
372 
program_header_size(&self) -> usize373     fn program_header_size(&self) -> usize {
374         if self.is_64 {
375             mem::size_of::<elf::ProgramHeader64<Endianness>>()
376         } else {
377             mem::size_of::<elf::ProgramHeader32<Endianness>>()
378         }
379     }
380 
381     /// Reserve the range for the program headers.
reserve_program_headers(&mut self, num: u32)382     pub fn reserve_program_headers(&mut self, num: u32) {
383         debug_assert_eq!(self.segment_offset, 0);
384         if num == 0 {
385             return;
386         }
387         self.segment_num = num;
388         self.segment_offset =
389             self.reserve(num as usize * self.program_header_size(), self.elf_align);
390     }
391 
392     /// Write alignment padding bytes prior to the program headers.
write_align_program_headers(&mut self)393     pub fn write_align_program_headers(&mut self) {
394         if self.segment_offset == 0 {
395             return;
396         }
397         util::write_align(self.buffer, self.elf_align);
398         debug_assert_eq!(self.segment_offset, self.buffer.len());
399     }
400 
401     /// Write a program header.
write_program_header(&mut self, header: &ProgramHeader)402     pub fn write_program_header(&mut self, header: &ProgramHeader) {
403         let endian = self.endian;
404         if self.is_64 {
405             let header = elf::ProgramHeader64 {
406                 p_type: U32::new(endian, header.p_type),
407                 p_flags: U32::new(endian, header.p_flags),
408                 p_offset: U64::new(endian, header.p_offset),
409                 p_vaddr: U64::new(endian, header.p_vaddr),
410                 p_paddr: U64::new(endian, header.p_paddr),
411                 p_filesz: U64::new(endian, header.p_filesz),
412                 p_memsz: U64::new(endian, header.p_memsz),
413                 p_align: U64::new(endian, header.p_align),
414             };
415             self.buffer.write(&header);
416         } else {
417             let header = elf::ProgramHeader32 {
418                 p_type: U32::new(endian, header.p_type),
419                 p_offset: U32::new(endian, header.p_offset as u32),
420                 p_vaddr: U32::new(endian, header.p_vaddr as u32),
421                 p_paddr: U32::new(endian, header.p_paddr as u32),
422                 p_filesz: U32::new(endian, header.p_filesz as u32),
423                 p_memsz: U32::new(endian, header.p_memsz as u32),
424                 p_flags: U32::new(endian, header.p_flags),
425                 p_align: U32::new(endian, header.p_align as u32),
426             };
427             self.buffer.write(&header);
428         }
429     }
430 
431     /// Reserve the section index for the null section header.
432     ///
433     /// The null section header is usually automatically reserved,
434     /// but this can be used to force an empty section table.
435     ///
436     /// This must be called before [`Self::reserve_section_headers`].
reserve_null_section_index(&mut self) -> SectionIndex437     pub fn reserve_null_section_index(&mut self) -> SectionIndex {
438         debug_assert_eq!(self.section_num, 0);
439         if self.section_num == 0 {
440             self.section_num = 1;
441         }
442         SectionIndex(0)
443     }
444 
445     /// Reserve a section table index.
446     ///
447     /// Automatically also reserves the null section header if required.
448     ///
449     /// This must be called before [`Self::reserve_section_headers`].
reserve_section_index(&mut self) -> SectionIndex450     pub fn reserve_section_index(&mut self) -> SectionIndex {
451         debug_assert_eq!(self.section_offset, 0);
452         if self.section_num == 0 {
453             self.section_num = 1;
454         }
455         let index = self.section_num;
456         self.section_num += 1;
457         SectionIndex(index)
458     }
459 
section_header_size(&self) -> usize460     fn section_header_size(&self) -> usize {
461         if self.is_64 {
462             mem::size_of::<elf::SectionHeader64<Endianness>>()
463         } else {
464             mem::size_of::<elf::SectionHeader32<Endianness>>()
465         }
466     }
467 
468     /// Reserve the range for the section headers.
469     ///
470     /// This function does nothing if no sections were reserved.
471     /// This must be called after [`Self::reserve_section_index`]
472     /// and other functions that reserve section indices.
reserve_section_headers(&mut self)473     pub fn reserve_section_headers(&mut self) {
474         debug_assert_eq!(self.section_offset, 0);
475         if self.section_num == 0 {
476             return;
477         }
478         self.section_offset = self.reserve(
479             self.section_num as usize * self.section_header_size(),
480             self.elf_align,
481         );
482     }
483 
484     /// Write the null section header.
485     ///
486     /// This must be the first section header that is written.
487     /// This function does nothing if no sections were reserved.
write_null_section_header(&mut self)488     pub fn write_null_section_header(&mut self) {
489         if self.section_num == 0 {
490             return;
491         }
492         util::write_align(self.buffer, self.elf_align);
493         debug_assert_eq!(self.section_offset, self.buffer.len());
494         self.write_section_header(&SectionHeader {
495             name: None,
496             sh_type: 0,
497             sh_flags: 0,
498             sh_addr: 0,
499             sh_offset: 0,
500             sh_size: if self.section_num >= elf::SHN_LORESERVE.into() {
501                 self.section_num.into()
502             } else {
503                 0
504             },
505             sh_link: if self.shstrtab_index.0 >= elf::SHN_LORESERVE.into() {
506                 self.shstrtab_index.0
507             } else {
508                 0
509             },
510             // TODO: e_phnum overflow
511             sh_info: 0,
512             sh_addralign: 0,
513             sh_entsize: 0,
514         });
515     }
516 
517     /// Write a section header.
write_section_header(&mut self, section: &SectionHeader)518     pub fn write_section_header(&mut self, section: &SectionHeader) {
519         let sh_name = if let Some(name) = section.name {
520             self.shstrtab.get_offset(name) as u32
521         } else {
522             0
523         };
524         let endian = self.endian;
525         if self.is_64 {
526             let section = elf::SectionHeader64 {
527                 sh_name: U32::new(endian, sh_name),
528                 sh_type: U32::new(endian, section.sh_type),
529                 sh_flags: U64::new(endian, section.sh_flags),
530                 sh_addr: U64::new(endian, section.sh_addr),
531                 sh_offset: U64::new(endian, section.sh_offset),
532                 sh_size: U64::new(endian, section.sh_size),
533                 sh_link: U32::new(endian, section.sh_link),
534                 sh_info: U32::new(endian, section.sh_info),
535                 sh_addralign: U64::new(endian, section.sh_addralign),
536                 sh_entsize: U64::new(endian, section.sh_entsize),
537             };
538             self.buffer.write(&section);
539         } else {
540             let section = elf::SectionHeader32 {
541                 sh_name: U32::new(endian, sh_name),
542                 sh_type: U32::new(endian, section.sh_type),
543                 sh_flags: U32::new(endian, section.sh_flags as u32),
544                 sh_addr: U32::new(endian, section.sh_addr as u32),
545                 sh_offset: U32::new(endian, section.sh_offset as u32),
546                 sh_size: U32::new(endian, section.sh_size as u32),
547                 sh_link: U32::new(endian, section.sh_link),
548                 sh_info: U32::new(endian, section.sh_info),
549                 sh_addralign: U32::new(endian, section.sh_addralign as u32),
550                 sh_entsize: U32::new(endian, section.sh_entsize as u32),
551             };
552             self.buffer.write(&section);
553         }
554     }
555 
556     /// Add a section name to the section header string table.
557     ///
558     /// This will be stored in the `.shstrtab` section.
559     ///
560     /// This must be called before [`Self::reserve_shstrtab`].
add_section_name(&mut self, name: &'a [u8]) -> StringId561     pub fn add_section_name(&mut self, name: &'a [u8]) -> StringId {
562         debug_assert_eq!(self.shstrtab_offset, 0);
563         self.shstrtab.add(name)
564     }
565 
566     /// Reserve the range for the section header string table.
567     ///
568     /// This range is used for a section named `.shstrtab`.
569     ///
570     /// This function does nothing if no sections were reserved.
571     /// This must be called after [`Self::add_section_name`].
572     /// and other functions that reserve section names and indices.
reserve_shstrtab(&mut self)573     pub fn reserve_shstrtab(&mut self) {
574         debug_assert_eq!(self.shstrtab_offset, 0);
575         if self.section_num == 0 {
576             return;
577         }
578         // Start with null section name.
579         self.shstrtab_data = vec![0];
580         self.shstrtab.write(1, &mut self.shstrtab_data);
581         self.shstrtab_offset = self.reserve(self.shstrtab_data.len(), 1);
582     }
583 
584     /// Write the section header string table.
585     ///
586     /// This function does nothing if the section was not reserved.
write_shstrtab(&mut self)587     pub fn write_shstrtab(&mut self) {
588         if self.shstrtab_offset == 0 {
589             return;
590         }
591         debug_assert_eq!(self.shstrtab_offset, self.buffer.len());
592         self.buffer.write_bytes(&self.shstrtab_data);
593     }
594 
595     /// Reserve the section index for the section header string table.
596     ///
597     /// This must be called before [`Self::reserve_shstrtab`]
598     /// and [`Self::reserve_section_headers`].
reserve_shstrtab_section_index(&mut self) -> SectionIndex599     pub fn reserve_shstrtab_section_index(&mut self) -> SectionIndex {
600         debug_assert_eq!(self.shstrtab_index, SectionIndex(0));
601         self.shstrtab_str_id = Some(self.add_section_name(&b".shstrtab"[..]));
602         self.shstrtab_index = self.reserve_section_index();
603         self.shstrtab_index
604     }
605 
606     /// Write the section header for the section header string table.
607     ///
608     /// This function does nothing if the section index was not reserved.
write_shstrtab_section_header(&mut self)609     pub fn write_shstrtab_section_header(&mut self) {
610         if self.shstrtab_index == SectionIndex(0) {
611             return;
612         }
613         self.write_section_header(&SectionHeader {
614             name: self.shstrtab_str_id,
615             sh_type: elf::SHT_STRTAB,
616             sh_flags: 0,
617             sh_addr: 0,
618             sh_offset: self.shstrtab_offset as u64,
619             sh_size: self.shstrtab_data.len() as u64,
620             sh_link: 0,
621             sh_info: 0,
622             sh_addralign: 1,
623             sh_entsize: 0,
624         });
625     }
626 
627     /// Add a string to the string table.
628     ///
629     /// This will be stored in the `.strtab` section.
630     ///
631     /// This must be called before [`Self::reserve_strtab`].
add_string(&mut self, name: &'a [u8]) -> StringId632     pub fn add_string(&mut self, name: &'a [u8]) -> StringId {
633         debug_assert_eq!(self.strtab_offset, 0);
634         self.need_strtab = true;
635         self.strtab.add(name)
636     }
637 
638     /// Return true if `.strtab` is needed.
strtab_needed(&self) -> bool639     pub fn strtab_needed(&self) -> bool {
640         self.need_strtab
641     }
642 
643     /// Reserve the range for the string table.
644     ///
645     /// This range is used for a section named `.strtab`.
646     ///
647     /// This function does nothing if no strings or symbols were defined.
648     /// This must be called after [`Self::add_string`].
reserve_strtab(&mut self)649     pub fn reserve_strtab(&mut self) {
650         debug_assert_eq!(self.strtab_offset, 0);
651         if !self.need_strtab {
652             return;
653         }
654         // Start with null string.
655         self.strtab_data = vec![0];
656         self.strtab.write(1, &mut self.strtab_data);
657         self.strtab_offset = self.reserve(self.strtab_data.len(), 1);
658     }
659 
660     /// Write the string table.
661     ///
662     /// This function does nothing if the section was not reserved.
write_strtab(&mut self)663     pub fn write_strtab(&mut self) {
664         if self.strtab_offset == 0 {
665             return;
666         }
667         debug_assert_eq!(self.strtab_offset, self.buffer.len());
668         self.buffer.write_bytes(&self.strtab_data);
669     }
670 
671     /// Reserve the section index for the string table.
672     ///
673     /// This must be called before [`Self::reserve_section_headers`].
reserve_strtab_section_index(&mut self) -> SectionIndex674     pub fn reserve_strtab_section_index(&mut self) -> SectionIndex {
675         debug_assert_eq!(self.strtab_index, SectionIndex(0));
676         self.strtab_str_id = Some(self.add_section_name(&b".strtab"[..]));
677         self.strtab_index = self.reserve_section_index();
678         self.strtab_index
679     }
680 
681     /// Write the section header for the string table.
682     ///
683     /// This function does nothing if the section index was not reserved.
write_strtab_section_header(&mut self)684     pub fn write_strtab_section_header(&mut self) {
685         if self.strtab_index == SectionIndex(0) {
686             return;
687         }
688         self.write_section_header(&SectionHeader {
689             name: self.strtab_str_id,
690             sh_type: elf::SHT_STRTAB,
691             sh_flags: 0,
692             sh_addr: 0,
693             sh_offset: self.strtab_offset as u64,
694             sh_size: self.strtab_data.len() as u64,
695             sh_link: 0,
696             sh_info: 0,
697             sh_addralign: 1,
698             sh_entsize: 0,
699         });
700     }
701 
702     /// Reserve a symbol table entry.
703     ///
704     /// This will be stored in the `.symtab` section.
705     ///
706     /// `section_index` is used to determine whether `.symtab_shndx` is required.
707     ///
708     /// Automatically also reserves the null symbol if required.
709     /// Callers may assume that the returned indices will be sequential
710     /// starting at 1.
711     ///
712     /// This must be called before [`Self::reserve_symtab`] and
713     /// [`Self::reserve_symtab_shndx`].
reserve_symbol_index(&mut self, section_index: Option<SectionIndex>) -> SymbolIndex714     pub fn reserve_symbol_index(&mut self, section_index: Option<SectionIndex>) -> SymbolIndex {
715         debug_assert_eq!(self.symtab_offset, 0);
716         debug_assert_eq!(self.symtab_shndx_offset, 0);
717         if self.symtab_num == 0 {
718             self.symtab_num = 1;
719             // The symtab must link to a strtab.
720             self.need_strtab = true;
721         }
722         let index = self.symtab_num;
723         self.symtab_num += 1;
724         if let Some(section_index) = section_index {
725             if section_index.0 >= elf::SHN_LORESERVE.into() {
726                 self.need_symtab_shndx = true;
727             }
728         }
729         SymbolIndex(index)
730     }
731 
732     /// Return the number of reserved symbol table entries.
733     ///
734     /// Includes the null symbol.
symbol_count(&self) -> u32735     pub fn symbol_count(&self) -> u32 {
736         self.symtab_num
737     }
738 
symbol_size(&self) -> usize739     fn symbol_size(&self) -> usize {
740         if self.is_64 {
741             mem::size_of::<elf::Sym64<Endianness>>()
742         } else {
743             mem::size_of::<elf::Sym32<Endianness>>()
744         }
745     }
746 
747     /// Reserve the range for the symbol table.
748     ///
749     /// This range is used for a section named `.symtab`.
750     /// This function does nothing if no symbols were reserved.
751     /// This must be called after [`Self::reserve_symbol_index`].
reserve_symtab(&mut self)752     pub fn reserve_symtab(&mut self) {
753         debug_assert_eq!(self.symtab_offset, 0);
754         if self.symtab_num == 0 {
755             return;
756         }
757         self.symtab_offset = self.reserve(
758             self.symtab_num as usize * self.symbol_size(),
759             self.elf_align,
760         );
761     }
762 
763     /// Write the null symbol.
764     ///
765     /// This must be the first symbol that is written.
766     /// This function does nothing if no symbols were reserved.
write_null_symbol(&mut self)767     pub fn write_null_symbol(&mut self) {
768         if self.symtab_num == 0 {
769             return;
770         }
771         util::write_align(self.buffer, self.elf_align);
772         debug_assert_eq!(self.symtab_offset, self.buffer.len());
773         if self.is_64 {
774             self.buffer.write(&elf::Sym64::<Endianness>::default());
775         } else {
776             self.buffer.write(&elf::Sym32::<Endianness>::default());
777         }
778 
779         if self.need_symtab_shndx {
780             self.symtab_shndx_data.write_pod(&U32::new(self.endian, 0));
781         }
782     }
783 
784     /// Write a symbol.
write_symbol(&mut self, sym: &Sym)785     pub fn write_symbol(&mut self, sym: &Sym) {
786         let st_name = if let Some(name) = sym.name {
787             self.strtab.get_offset(name) as u32
788         } else {
789             0
790         };
791         let st_shndx = if let Some(section) = sym.section {
792             if section.0 >= elf::SHN_LORESERVE as u32 {
793                 elf::SHN_XINDEX
794             } else {
795                 section.0 as u16
796             }
797         } else {
798             sym.st_shndx
799         };
800 
801         let endian = self.endian;
802         if self.is_64 {
803             let sym = elf::Sym64 {
804                 st_name: U32::new(endian, st_name),
805                 st_info: sym.st_info,
806                 st_other: sym.st_other,
807                 st_shndx: U16::new(endian, st_shndx),
808                 st_value: U64::new(endian, sym.st_value),
809                 st_size: U64::new(endian, sym.st_size),
810             };
811             self.buffer.write(&sym);
812         } else {
813             let sym = elf::Sym32 {
814                 st_name: U32::new(endian, st_name),
815                 st_info: sym.st_info,
816                 st_other: sym.st_other,
817                 st_shndx: U16::new(endian, st_shndx),
818                 st_value: U32::new(endian, sym.st_value as u32),
819                 st_size: U32::new(endian, sym.st_size as u32),
820             };
821             self.buffer.write(&sym);
822         }
823 
824         if self.need_symtab_shndx {
825             let section_index = sym.section.unwrap_or(SectionIndex(0));
826             self.symtab_shndx_data
827                 .write_pod(&U32::new(self.endian, section_index.0));
828         }
829     }
830 
831     /// Reserve the section index for the symbol table.
832     ///
833     /// This must be called before [`Self::reserve_section_headers`].
reserve_symtab_section_index(&mut self) -> SectionIndex834     pub fn reserve_symtab_section_index(&mut self) -> SectionIndex {
835         debug_assert_eq!(self.symtab_index, SectionIndex(0));
836         self.symtab_str_id = Some(self.add_section_name(&b".symtab"[..]));
837         self.symtab_index = self.reserve_section_index();
838         self.symtab_index
839     }
840 
841     /// Return the section index of the symbol table.
symtab_index(&mut self) -> SectionIndex842     pub fn symtab_index(&mut self) -> SectionIndex {
843         self.symtab_index
844     }
845 
846     /// Write the section header for the symbol table.
847     ///
848     /// This function does nothing if the section index was not reserved.
write_symtab_section_header(&mut self, num_local: u32)849     pub fn write_symtab_section_header(&mut self, num_local: u32) {
850         if self.symtab_index == SectionIndex(0) {
851             return;
852         }
853         self.write_section_header(&SectionHeader {
854             name: self.symtab_str_id,
855             sh_type: elf::SHT_SYMTAB,
856             sh_flags: 0,
857             sh_addr: 0,
858             sh_offset: self.symtab_offset as u64,
859             sh_size: self.symtab_num as u64 * self.symbol_size() as u64,
860             sh_link: self.strtab_index.0,
861             sh_info: num_local,
862             sh_addralign: self.elf_align as u64,
863             sh_entsize: self.symbol_size() as u64,
864         });
865     }
866 
867     /// Return true if `.symtab_shndx` is needed.
symtab_shndx_needed(&self) -> bool868     pub fn symtab_shndx_needed(&self) -> bool {
869         self.need_symtab_shndx
870     }
871 
872     /// Reserve the range for the extended section indices for the symbol table.
873     ///
874     /// This range is used for a section named `.symtab_shndx`.
875     /// This also reserves a section index.
876     ///
877     /// This function does nothing if extended section indices are not needed.
878     /// This must be called after [`Self::reserve_symbol_index`].
reserve_symtab_shndx(&mut self)879     pub fn reserve_symtab_shndx(&mut self) {
880         debug_assert_eq!(self.symtab_shndx_offset, 0);
881         if !self.need_symtab_shndx {
882             return;
883         }
884         self.symtab_shndx_offset = self.reserve(self.symtab_num as usize * 4, 4);
885         self.symtab_shndx_data.reserve(self.symtab_num as usize * 4);
886     }
887 
888     /// Write the extended section indices for the symbol table.
889     ///
890     /// This function does nothing if the section was not reserved.
write_symtab_shndx(&mut self)891     pub fn write_symtab_shndx(&mut self) {
892         if self.symtab_shndx_offset == 0 {
893             return;
894         }
895         debug_assert_eq!(self.symtab_shndx_offset, self.buffer.len());
896         debug_assert_eq!(self.symtab_num as usize * 4, self.symtab_shndx_data.len());
897         self.buffer.write_bytes(&self.symtab_shndx_data);
898     }
899 
900     /// Reserve the section index for the extended section indices symbol table.
901     ///
902     /// You should check [`Self::symtab_shndx_needed`] before calling this
903     /// unless you have other means of knowing if this section is needed.
904     ///
905     /// This must be called before [`Self::reserve_section_headers`].
reserve_symtab_shndx_section_index(&mut self) -> SectionIndex906     pub fn reserve_symtab_shndx_section_index(&mut self) -> SectionIndex {
907         debug_assert!(self.symtab_shndx_str_id.is_none());
908         self.symtab_shndx_str_id = Some(self.add_section_name(&b".symtab_shndx"[..]));
909         self.reserve_section_index()
910     }
911 
912     /// Write the section header for the extended section indices for the symbol table.
913     ///
914     /// This function does nothing if the section index was not reserved.
write_symtab_shndx_section_header(&mut self)915     pub fn write_symtab_shndx_section_header(&mut self) {
916         if self.symtab_shndx_str_id.is_none() {
917             return;
918         }
919         let sh_size = if self.symtab_shndx_offset == 0 {
920             0
921         } else {
922             (self.symtab_num * 4) as u64
923         };
924         self.write_section_header(&SectionHeader {
925             name: self.symtab_shndx_str_id,
926             sh_type: elf::SHT_SYMTAB_SHNDX,
927             sh_flags: 0,
928             sh_addr: 0,
929             sh_offset: self.symtab_shndx_offset as u64,
930             sh_size,
931             sh_link: self.symtab_index.0,
932             sh_info: 0,
933             sh_addralign: 4,
934             sh_entsize: 4,
935         });
936     }
937 
938     /// Add a string to the dynamic string table.
939     ///
940     /// This will be stored in the `.dynstr` section.
941     ///
942     /// This must be called before [`Self::reserve_dynstr`].
add_dynamic_string(&mut self, name: &'a [u8]) -> StringId943     pub fn add_dynamic_string(&mut self, name: &'a [u8]) -> StringId {
944         debug_assert_eq!(self.dynstr_offset, 0);
945         self.need_dynstr = true;
946         self.dynstr.add(name)
947     }
948 
949     /// Get a string that was previously added to the dynamic string table.
950     ///
951     /// Panics if the string was not added.
get_dynamic_string(&self, name: &'a [u8]) -> StringId952     pub fn get_dynamic_string(&self, name: &'a [u8]) -> StringId {
953         self.dynstr.get_id(name)
954     }
955 
956     /// Return true if `.dynstr` is needed.
dynstr_needed(&self) -> bool957     pub fn dynstr_needed(&self) -> bool {
958         self.need_dynstr
959     }
960 
961     /// Reserve the range for the dynamic string table.
962     ///
963     /// This range is used for a section named `.dynstr`.
964     ///
965     /// This function does nothing if no dynamic strings or symbols were defined.
966     /// This must be called after [`Self::add_dynamic_string`].
reserve_dynstr(&mut self)967     pub fn reserve_dynstr(&mut self) {
968         debug_assert_eq!(self.dynstr_offset, 0);
969         if !self.need_dynstr {
970             return;
971         }
972         // Start with null string.
973         self.dynstr_data = vec![0];
974         self.dynstr.write(1, &mut self.dynstr_data);
975         self.dynstr_offset = self.reserve(self.dynstr_data.len(), 1);
976     }
977 
978     /// Write the dynamic string table.
979     ///
980     /// This function does nothing if the section was not reserved.
write_dynstr(&mut self)981     pub fn write_dynstr(&mut self) {
982         if self.dynstr_offset == 0 {
983             return;
984         }
985         debug_assert_eq!(self.dynstr_offset, self.buffer.len());
986         self.buffer.write_bytes(&self.dynstr_data);
987     }
988 
989     /// Reserve the section index for the dynamic string table.
990     ///
991     /// This must be called before [`Self::reserve_section_headers`].
reserve_dynstr_section_index(&mut self) -> SectionIndex992     pub fn reserve_dynstr_section_index(&mut self) -> SectionIndex {
993         debug_assert_eq!(self.dynstr_index, SectionIndex(0));
994         self.dynstr_str_id = Some(self.add_section_name(&b".dynstr"[..]));
995         self.dynstr_index = self.reserve_section_index();
996         self.dynstr_index
997     }
998 
999     /// Return the section index of the dynamic string table.
dynstr_index(&mut self) -> SectionIndex1000     pub fn dynstr_index(&mut self) -> SectionIndex {
1001         self.dynstr_index
1002     }
1003 
1004     /// Write the section header for the dynamic string table.
1005     ///
1006     /// This function does nothing if the section index was not reserved.
write_dynstr_section_header(&mut self, sh_addr: u64)1007     pub fn write_dynstr_section_header(&mut self, sh_addr: u64) {
1008         if self.dynstr_index == SectionIndex(0) {
1009             return;
1010         }
1011         self.write_section_header(&SectionHeader {
1012             name: self.dynstr_str_id,
1013             sh_type: elf::SHT_STRTAB,
1014             sh_flags: elf::SHF_ALLOC.into(),
1015             sh_addr,
1016             sh_offset: self.dynstr_offset as u64,
1017             sh_size: self.dynstr_data.len() as u64,
1018             sh_link: 0,
1019             sh_info: 0,
1020             sh_addralign: 1,
1021             sh_entsize: 0,
1022         });
1023     }
1024 
1025     /// Reserve the null dynamic symbol table entry.
1026     ///
1027     /// This will be stored in the `.dynsym` section.
1028     ///
1029     /// The null dynamic symbol table entry is usually automatically reserved,
1030     /// but this can be used to force an empty dynamic symbol table.
1031     ///
1032     /// This must be called before [`Self::reserve_dynsym`].
reserve_null_dynamic_symbol_index(&mut self) -> SymbolIndex1033     pub fn reserve_null_dynamic_symbol_index(&mut self) -> SymbolIndex {
1034         debug_assert_eq!(self.dynsym_offset, 0);
1035         debug_assert_eq!(self.dynsym_num, 0);
1036         self.dynsym_num = 1;
1037         // The symtab must link to a strtab.
1038         self.need_dynstr = true;
1039         SymbolIndex(0)
1040     }
1041 
1042     /// Reserve a dynamic symbol table entry.
1043     ///
1044     /// This will be stored in the `.dynsym` section.
1045     ///
1046     /// Automatically also reserves the null symbol if required.
1047     /// Callers may assume that the returned indices will be sequential
1048     /// starting at 1.
1049     ///
1050     /// This must be called before [`Self::reserve_dynsym`].
reserve_dynamic_symbol_index(&mut self) -> SymbolIndex1051     pub fn reserve_dynamic_symbol_index(&mut self) -> SymbolIndex {
1052         debug_assert_eq!(self.dynsym_offset, 0);
1053         if self.dynsym_num == 0 {
1054             self.dynsym_num = 1;
1055             // The symtab must link to a strtab.
1056             self.need_dynstr = true;
1057         }
1058         let index = self.dynsym_num;
1059         self.dynsym_num += 1;
1060         SymbolIndex(index)
1061     }
1062 
1063     /// Return the number of reserved dynamic symbols.
1064     ///
1065     /// Includes the null symbol.
dynamic_symbol_count(&mut self) -> u321066     pub fn dynamic_symbol_count(&mut self) -> u32 {
1067         self.dynsym_num
1068     }
1069 
1070     /// Reserve the range for the dynamic symbol table.
1071     ///
1072     /// This range is used for a section named `.dynsym`.
1073     ///
1074     /// This function does nothing if no dynamic symbols were reserved.
1075     /// This must be called after [`Self::reserve_dynamic_symbol_index`].
reserve_dynsym(&mut self)1076     pub fn reserve_dynsym(&mut self) {
1077         debug_assert_eq!(self.dynsym_offset, 0);
1078         if self.dynsym_num == 0 {
1079             return;
1080         }
1081         self.dynsym_offset = self.reserve(
1082             self.dynsym_num as usize * self.symbol_size(),
1083             self.elf_align,
1084         );
1085     }
1086 
1087     /// Write the null dynamic symbol.
1088     ///
1089     /// This must be the first dynamic symbol that is written.
1090     /// This function does nothing if no dynamic symbols were reserved.
write_null_dynamic_symbol(&mut self)1091     pub fn write_null_dynamic_symbol(&mut self) {
1092         if self.dynsym_num == 0 {
1093             return;
1094         }
1095         util::write_align(self.buffer, self.elf_align);
1096         debug_assert_eq!(self.dynsym_offset, self.buffer.len());
1097         if self.is_64 {
1098             self.buffer.write(&elf::Sym64::<Endianness>::default());
1099         } else {
1100             self.buffer.write(&elf::Sym32::<Endianness>::default());
1101         }
1102     }
1103 
1104     /// Write a dynamic symbol.
write_dynamic_symbol(&mut self, sym: &Sym)1105     pub fn write_dynamic_symbol(&mut self, sym: &Sym) {
1106         let st_name = if let Some(name) = sym.name {
1107             self.dynstr.get_offset(name) as u32
1108         } else {
1109             0
1110         };
1111 
1112         let st_shndx = if let Some(section) = sym.section {
1113             if section.0 >= elf::SHN_LORESERVE as u32 {
1114                 // TODO: we don't actually write out .dynsym_shndx yet.
1115                 // This is unlikely to be needed though.
1116                 elf::SHN_XINDEX
1117             } else {
1118                 section.0 as u16
1119             }
1120         } else {
1121             sym.st_shndx
1122         };
1123 
1124         let endian = self.endian;
1125         if self.is_64 {
1126             let sym = elf::Sym64 {
1127                 st_name: U32::new(endian, st_name),
1128                 st_info: sym.st_info,
1129                 st_other: sym.st_other,
1130                 st_shndx: U16::new(endian, st_shndx),
1131                 st_value: U64::new(endian, sym.st_value),
1132                 st_size: U64::new(endian, sym.st_size),
1133             };
1134             self.buffer.write(&sym);
1135         } else {
1136             let sym = elf::Sym32 {
1137                 st_name: U32::new(endian, st_name),
1138                 st_info: sym.st_info,
1139                 st_other: sym.st_other,
1140                 st_shndx: U16::new(endian, st_shndx),
1141                 st_value: U32::new(endian, sym.st_value as u32),
1142                 st_size: U32::new(endian, sym.st_size as u32),
1143             };
1144             self.buffer.write(&sym);
1145         }
1146     }
1147 
1148     /// Reserve the section index for the dynamic symbol table.
1149     ///
1150     /// This must be called before [`Self::reserve_section_headers`].
reserve_dynsym_section_index(&mut self) -> SectionIndex1151     pub fn reserve_dynsym_section_index(&mut self) -> SectionIndex {
1152         debug_assert_eq!(self.dynsym_index, SectionIndex(0));
1153         self.dynsym_str_id = Some(self.add_section_name(&b".dynsym"[..]));
1154         self.dynsym_index = self.reserve_section_index();
1155         self.dynsym_index
1156     }
1157 
1158     /// Return the section index of the dynamic symbol table.
dynsym_index(&mut self) -> SectionIndex1159     pub fn dynsym_index(&mut self) -> SectionIndex {
1160         self.dynsym_index
1161     }
1162 
1163     /// Write the section header for the dynamic symbol table.
1164     ///
1165     /// This function does nothing if the section index was not reserved.
write_dynsym_section_header(&mut self, sh_addr: u64, num_local: u32)1166     pub fn write_dynsym_section_header(&mut self, sh_addr: u64, num_local: u32) {
1167         if self.dynsym_index == SectionIndex(0) {
1168             return;
1169         }
1170         self.write_section_header(&SectionHeader {
1171             name: self.dynsym_str_id,
1172             sh_type: elf::SHT_DYNSYM,
1173             sh_flags: elf::SHF_ALLOC.into(),
1174             sh_addr,
1175             sh_offset: self.dynsym_offset as u64,
1176             sh_size: self.dynsym_num as u64 * self.symbol_size() as u64,
1177             sh_link: self.dynstr_index.0,
1178             sh_info: num_local,
1179             sh_addralign: self.elf_align as u64,
1180             sh_entsize: self.symbol_size() as u64,
1181         });
1182     }
1183 
dyn_size(&self) -> usize1184     fn dyn_size(&self) -> usize {
1185         if self.is_64 {
1186             mem::size_of::<elf::Dyn64<Endianness>>()
1187         } else {
1188             mem::size_of::<elf::Dyn32<Endianness>>()
1189         }
1190     }
1191 
1192     /// Reserve the range for the `.dynamic` section.
1193     ///
1194     /// This function does nothing if `dynamic_num` is zero.
reserve_dynamic(&mut self, dynamic_num: usize)1195     pub fn reserve_dynamic(&mut self, dynamic_num: usize) {
1196         debug_assert_eq!(self.dynamic_offset, 0);
1197         if dynamic_num == 0 {
1198             return;
1199         }
1200         self.dynamic_num = dynamic_num;
1201         self.dynamic_offset = self.reserve(dynamic_num * self.dyn_size(), self.elf_align);
1202     }
1203 
1204     /// Write alignment padding bytes prior to the `.dynamic` section.
1205     ///
1206     /// This function does nothing if the section was not reserved.
write_align_dynamic(&mut self)1207     pub fn write_align_dynamic(&mut self) {
1208         if self.dynamic_offset == 0 {
1209             return;
1210         }
1211         util::write_align(self.buffer, self.elf_align);
1212         debug_assert_eq!(self.dynamic_offset, self.buffer.len());
1213     }
1214 
1215     /// Write a dynamic string entry.
write_dynamic_string(&mut self, tag: u32, id: StringId)1216     pub fn write_dynamic_string(&mut self, tag: u32, id: StringId) {
1217         self.write_dynamic(tag, self.dynstr.get_offset(id) as u64);
1218     }
1219 
1220     /// Write a dynamic value entry.
write_dynamic(&mut self, d_tag: u32, d_val: u64)1221     pub fn write_dynamic(&mut self, d_tag: u32, d_val: u64) {
1222         debug_assert!(self.dynamic_offset <= self.buffer.len());
1223         let endian = self.endian;
1224         if self.is_64 {
1225             let d = elf::Dyn64 {
1226                 d_tag: U64::new(endian, d_tag.into()),
1227                 d_val: U64::new(endian, d_val),
1228             };
1229             self.buffer.write(&d);
1230         } else {
1231             let d = elf::Dyn32 {
1232                 d_tag: U32::new(endian, d_tag),
1233                 d_val: U32::new(endian, d_val as u32),
1234             };
1235             self.buffer.write(&d);
1236         }
1237         debug_assert!(
1238             self.dynamic_offset + self.dynamic_num * self.dyn_size() >= self.buffer.len()
1239         );
1240     }
1241 
1242     /// Reserve the section index for the dynamic table.
reserve_dynamic_section_index(&mut self) -> SectionIndex1243     pub fn reserve_dynamic_section_index(&mut self) -> SectionIndex {
1244         debug_assert!(self.dynamic_str_id.is_none());
1245         self.dynamic_str_id = Some(self.add_section_name(&b".dynamic"[..]));
1246         self.reserve_section_index()
1247     }
1248 
1249     /// Write the section header for the dynamic table.
1250     ///
1251     /// This function does nothing if the section index was not reserved.
write_dynamic_section_header(&mut self, sh_addr: u64)1252     pub fn write_dynamic_section_header(&mut self, sh_addr: u64) {
1253         if self.dynamic_str_id.is_none() {
1254             return;
1255         }
1256         self.write_section_header(&SectionHeader {
1257             name: self.dynamic_str_id,
1258             sh_type: elf::SHT_DYNAMIC,
1259             sh_flags: (elf::SHF_WRITE | elf::SHF_ALLOC).into(),
1260             sh_addr,
1261             sh_offset: self.dynamic_offset as u64,
1262             sh_size: (self.dynamic_num * self.dyn_size()) as u64,
1263             sh_link: self.dynstr_index.0,
1264             sh_info: 0,
1265             sh_addralign: self.elf_align as u64,
1266             sh_entsize: self.dyn_size() as u64,
1267         });
1268     }
1269 
rel_size(&self, is_rela: bool) -> usize1270     fn rel_size(&self, is_rela: bool) -> usize {
1271         if self.is_64 {
1272             if is_rela {
1273                 mem::size_of::<elf::Rela64<Endianness>>()
1274             } else {
1275                 mem::size_of::<elf::Rel64<Endianness>>()
1276             }
1277         } else {
1278             if is_rela {
1279                 mem::size_of::<elf::Rela32<Endianness>>()
1280             } else {
1281                 mem::size_of::<elf::Rel32<Endianness>>()
1282             }
1283         }
1284     }
1285 
1286     /// Reserve a file range for a SysV hash section.
1287     ///
1288     /// `symbol_count` is the number of symbols in the hash,
1289     /// not the total number of symbols.
reserve_hash(&mut self, bucket_count: u32, chain_count: u32)1290     pub fn reserve_hash(&mut self, bucket_count: u32, chain_count: u32) {
1291         self.hash_size = mem::size_of::<elf::HashHeader<Endianness>>()
1292             + bucket_count as usize * 4
1293             + chain_count as usize * 4;
1294         self.hash_offset = self.reserve(self.hash_size, self.elf_align);
1295     }
1296 
1297     /// Write a SysV hash section.
1298     ///
1299     /// `chain_count` is the number of symbols in the hash.
1300     /// The argument to `hash` will be in the range `0..chain_count`.
write_hash<F>(&mut self, bucket_count: u32, chain_count: u32, hash: F) where F: Fn(u32) -> Option<u32>,1301     pub fn write_hash<F>(&mut self, bucket_count: u32, chain_count: u32, hash: F)
1302     where
1303         F: Fn(u32) -> Option<u32>,
1304     {
1305         let mut buckets = vec![U32::new(self.endian, 0); bucket_count as usize];
1306         let mut chains = vec![U32::new(self.endian, 0); chain_count as usize];
1307         for i in 0..chain_count {
1308             if let Some(hash) = hash(i) {
1309                 let bucket = hash % bucket_count;
1310                 chains[i as usize] = buckets[bucket as usize];
1311                 buckets[bucket as usize] = U32::new(self.endian, i);
1312             }
1313         }
1314 
1315         util::write_align(self.buffer, self.elf_align);
1316         debug_assert_eq!(self.hash_offset, self.buffer.len());
1317         self.buffer.write(&elf::HashHeader {
1318             bucket_count: U32::new(self.endian, bucket_count),
1319             chain_count: U32::new(self.endian, chain_count),
1320         });
1321         self.buffer.write_slice(&buckets);
1322         self.buffer.write_slice(&chains);
1323     }
1324 
1325     /// Reserve the section index for the SysV hash table.
reserve_hash_section_index(&mut self) -> SectionIndex1326     pub fn reserve_hash_section_index(&mut self) -> SectionIndex {
1327         debug_assert!(self.hash_str_id.is_none());
1328         self.hash_str_id = Some(self.add_section_name(&b".hash"[..]));
1329         self.reserve_section_index()
1330     }
1331 
1332     /// Write the section header for the SysV hash table.
1333     ///
1334     /// This function does nothing if the section index was not reserved.
write_hash_section_header(&mut self, sh_addr: u64)1335     pub fn write_hash_section_header(&mut self, sh_addr: u64) {
1336         if self.hash_str_id.is_none() {
1337             return;
1338         }
1339         self.write_section_header(&SectionHeader {
1340             name: self.hash_str_id,
1341             sh_type: elf::SHT_HASH,
1342             sh_flags: elf::SHF_ALLOC.into(),
1343             sh_addr,
1344             sh_offset: self.hash_offset as u64,
1345             sh_size: self.hash_size as u64,
1346             sh_link: self.dynsym_index.0,
1347             sh_info: 0,
1348             sh_addralign: self.elf_align as u64,
1349             sh_entsize: 4,
1350         });
1351     }
1352 
1353     /// Reserve a file range for a GNU hash section.
1354     ///
1355     /// `symbol_count` is the number of symbols in the hash,
1356     /// not the total number of symbols.
reserve_gnu_hash(&mut self, bloom_count: u32, bucket_count: u32, symbol_count: u32)1357     pub fn reserve_gnu_hash(&mut self, bloom_count: u32, bucket_count: u32, symbol_count: u32) {
1358         self.gnu_hash_size = mem::size_of::<elf::GnuHashHeader<Endianness>>()
1359             + bloom_count as usize * self.elf_align
1360             + bucket_count as usize * 4
1361             + symbol_count as usize * 4;
1362         self.gnu_hash_offset = self.reserve(self.gnu_hash_size, self.elf_align);
1363     }
1364 
1365     /// Write a GNU hash section.
1366     ///
1367     /// `symbol_count` is the number of symbols in the hash.
1368     /// The argument to `hash` will be in the range `0..symbol_count`.
1369     ///
1370     /// This requires that symbols are already sorted by bucket.
write_gnu_hash<F>( &mut self, symbol_base: u32, bloom_shift: u32, bloom_count: u32, bucket_count: u32, symbol_count: u32, hash: F, ) where F: Fn(u32) -> u32,1371     pub fn write_gnu_hash<F>(
1372         &mut self,
1373         symbol_base: u32,
1374         bloom_shift: u32,
1375         bloom_count: u32,
1376         bucket_count: u32,
1377         symbol_count: u32,
1378         hash: F,
1379     ) where
1380         F: Fn(u32) -> u32,
1381     {
1382         util::write_align(self.buffer, self.elf_align);
1383         debug_assert_eq!(self.gnu_hash_offset, self.buffer.len());
1384         self.buffer.write(&elf::GnuHashHeader {
1385             bucket_count: U32::new(self.endian, bucket_count),
1386             symbol_base: U32::new(self.endian, symbol_base),
1387             bloom_count: U32::new(self.endian, bloom_count),
1388             bloom_shift: U32::new(self.endian, bloom_shift),
1389         });
1390 
1391         // Calculate and write bloom filter.
1392         if self.is_64 {
1393             let mut bloom_filters = vec![0; bloom_count as usize];
1394             for i in 0..symbol_count {
1395                 let h = hash(i);
1396                 bloom_filters[((h / 64) & (bloom_count - 1)) as usize] |=
1397                     1 << (h % 64) | 1 << ((h >> bloom_shift) % 64);
1398             }
1399             for bloom_filter in bloom_filters {
1400                 self.buffer.write(&U64::new(self.endian, bloom_filter));
1401             }
1402         } else {
1403             let mut bloom_filters = vec![0; bloom_count as usize];
1404             for i in 0..symbol_count {
1405                 let h = hash(i);
1406                 bloom_filters[((h / 32) & (bloom_count - 1)) as usize] |=
1407                     1 << (h % 32) | 1 << ((h >> bloom_shift) % 32);
1408             }
1409             for bloom_filter in bloom_filters {
1410                 self.buffer.write(&U32::new(self.endian, bloom_filter));
1411             }
1412         }
1413 
1414         // Write buckets.
1415         //
1416         // This requires that symbols are already sorted by bucket.
1417         let mut bucket = 0;
1418         for i in 0..symbol_count {
1419             let symbol_bucket = hash(i) % bucket_count;
1420             while bucket < symbol_bucket {
1421                 self.buffer.write(&U32::new(self.endian, 0));
1422                 bucket += 1;
1423             }
1424             if bucket == symbol_bucket {
1425                 self.buffer.write(&U32::new(self.endian, symbol_base + i));
1426                 bucket += 1;
1427             }
1428         }
1429         while bucket < bucket_count {
1430             self.buffer.write(&U32::new(self.endian, 0));
1431             bucket += 1;
1432         }
1433 
1434         // Write hash values.
1435         for i in 0..symbol_count {
1436             let mut h = hash(i);
1437             if i == symbol_count - 1 || h % bucket_count != hash(i + 1) % bucket_count {
1438                 h |= 1;
1439             } else {
1440                 h &= !1;
1441             }
1442             self.buffer.write(&U32::new(self.endian, h));
1443         }
1444     }
1445 
1446     /// Reserve the section index for the GNU hash table.
reserve_gnu_hash_section_index(&mut self) -> SectionIndex1447     pub fn reserve_gnu_hash_section_index(&mut self) -> SectionIndex {
1448         debug_assert!(self.gnu_hash_str_id.is_none());
1449         self.gnu_hash_str_id = Some(self.add_section_name(&b".gnu.hash"[..]));
1450         self.reserve_section_index()
1451     }
1452 
1453     /// Write the section header for the GNU hash table.
1454     ///
1455     /// This function does nothing if the section index was not reserved.
write_gnu_hash_section_header(&mut self, sh_addr: u64)1456     pub fn write_gnu_hash_section_header(&mut self, sh_addr: u64) {
1457         if self.gnu_hash_str_id.is_none() {
1458             return;
1459         }
1460         self.write_section_header(&SectionHeader {
1461             name: self.gnu_hash_str_id,
1462             sh_type: elf::SHT_GNU_HASH,
1463             sh_flags: elf::SHF_ALLOC.into(),
1464             sh_addr,
1465             sh_offset: self.gnu_hash_offset as u64,
1466             sh_size: self.gnu_hash_size as u64,
1467             sh_link: self.dynsym_index.0,
1468             sh_info: 0,
1469             sh_addralign: self.elf_align as u64,
1470             sh_entsize: 0,
1471         });
1472     }
1473 
1474     /// Reserve the range for the `.gnu.version` section.
1475     ///
1476     /// This function does nothing if no dynamic symbols were reserved.
reserve_gnu_versym(&mut self)1477     pub fn reserve_gnu_versym(&mut self) {
1478         debug_assert_eq!(self.gnu_versym_offset, 0);
1479         if self.dynsym_num == 0 {
1480             return;
1481         }
1482         self.gnu_versym_offset = self.reserve(self.dynsym_num as usize * 2, 2);
1483     }
1484 
1485     /// Write the null symbol version entry.
1486     ///
1487     /// This must be the first symbol version that is written.
1488     /// This function does nothing if no dynamic symbols were reserved.
write_null_gnu_versym(&mut self)1489     pub fn write_null_gnu_versym(&mut self) {
1490         if self.dynsym_num == 0 {
1491             return;
1492         }
1493         util::write_align(self.buffer, 2);
1494         debug_assert_eq!(self.gnu_versym_offset, self.buffer.len());
1495         self.write_gnu_versym(0);
1496     }
1497 
1498     /// Write a symbol version entry.
write_gnu_versym(&mut self, versym: u16)1499     pub fn write_gnu_versym(&mut self, versym: u16) {
1500         self.buffer.write(&U16::new(self.endian, versym));
1501     }
1502 
1503     /// Reserve the section index for the `.gnu.version` section.
reserve_gnu_versym_section_index(&mut self) -> SectionIndex1504     pub fn reserve_gnu_versym_section_index(&mut self) -> SectionIndex {
1505         debug_assert!(self.gnu_versym_str_id.is_none());
1506         self.gnu_versym_str_id = Some(self.add_section_name(&b".gnu.version"[..]));
1507         self.reserve_section_index()
1508     }
1509 
1510     /// Write the section header for the `.gnu.version` section.
1511     ///
1512     /// This function does nothing if the section index was not reserved.
write_gnu_versym_section_header(&mut self, sh_addr: u64)1513     pub fn write_gnu_versym_section_header(&mut self, sh_addr: u64) {
1514         if self.gnu_versym_str_id.is_none() {
1515             return;
1516         }
1517         self.write_section_header(&SectionHeader {
1518             name: self.gnu_versym_str_id,
1519             sh_type: elf::SHT_GNU_VERSYM,
1520             sh_flags: elf::SHF_ALLOC.into(),
1521             sh_addr,
1522             sh_offset: self.gnu_versym_offset as u64,
1523             sh_size: self.dynsym_num as u64 * 2,
1524             sh_link: self.dynsym_index.0,
1525             sh_info: 0,
1526             sh_addralign: 2,
1527             sh_entsize: 2,
1528         });
1529     }
1530 
1531     /// Reserve the range for the `.gnu.version_d` section.
reserve_gnu_verdef(&mut self, verdef_count: usize, verdaux_count: usize)1532     pub fn reserve_gnu_verdef(&mut self, verdef_count: usize, verdaux_count: usize) {
1533         debug_assert_eq!(self.gnu_verdef_offset, 0);
1534         if verdef_count == 0 {
1535             return;
1536         }
1537         self.gnu_verdef_size = verdef_count * mem::size_of::<elf::Verdef<Endianness>>()
1538             + verdaux_count * mem::size_of::<elf::Verdaux<Endianness>>();
1539         self.gnu_verdef_offset = self.reserve(self.gnu_verdef_size, self.elf_align);
1540         self.gnu_verdef_count = verdef_count as u16;
1541         self.gnu_verdef_remaining = self.gnu_verdef_count;
1542     }
1543 
1544     /// Write alignment padding bytes prior to a `.gnu.version_d` section.
write_align_gnu_verdef(&mut self)1545     pub fn write_align_gnu_verdef(&mut self) {
1546         if self.gnu_verdef_offset == 0 {
1547             return;
1548         }
1549         util::write_align(self.buffer, self.elf_align);
1550         debug_assert_eq!(self.gnu_verdef_offset, self.buffer.len());
1551     }
1552 
1553     /// Write a version definition entry.
write_gnu_verdef(&mut self, verdef: &Verdef)1554     pub fn write_gnu_verdef(&mut self, verdef: &Verdef) {
1555         debug_assert_ne!(self.gnu_verdef_remaining, 0);
1556         self.gnu_verdef_remaining -= 1;
1557         let vd_next = if self.gnu_verdef_remaining == 0 {
1558             0
1559         } else {
1560             mem::size_of::<elf::Verdef<Endianness>>() as u32
1561                 + verdef.aux_count as u32 * mem::size_of::<elf::Verdaux<Endianness>>() as u32
1562         };
1563 
1564         self.gnu_verdaux_remaining = verdef.aux_count;
1565         let vd_aux = if verdef.aux_count == 0 {
1566             0
1567         } else {
1568             mem::size_of::<elf::Verdef<Endianness>>() as u32
1569         };
1570 
1571         self.buffer.write(&elf::Verdef {
1572             vd_version: U16::new(self.endian, verdef.version),
1573             vd_flags: U16::new(self.endian, verdef.flags),
1574             vd_ndx: U16::new(self.endian, verdef.index),
1575             vd_cnt: U16::new(self.endian, verdef.aux_count),
1576             vd_hash: U32::new(self.endian, elf::hash(self.dynstr.get_string(verdef.name))),
1577             vd_aux: U32::new(self.endian, vd_aux),
1578             vd_next: U32::new(self.endian, vd_next),
1579         });
1580         self.write_gnu_verdaux(verdef.name);
1581     }
1582 
1583     /// Write a version definition auxiliary entry.
write_gnu_verdaux(&mut self, name: StringId)1584     pub fn write_gnu_verdaux(&mut self, name: StringId) {
1585         debug_assert_ne!(self.gnu_verdaux_remaining, 0);
1586         self.gnu_verdaux_remaining -= 1;
1587         let vda_next = if self.gnu_verdaux_remaining == 0 {
1588             0
1589         } else {
1590             mem::size_of::<elf::Verdaux<Endianness>>() as u32
1591         };
1592         self.buffer.write(&elf::Verdaux {
1593             vda_name: U32::new(self.endian, self.dynstr.get_offset(name) as u32),
1594             vda_next: U32::new(self.endian, vda_next),
1595         });
1596     }
1597 
1598     /// Reserve the section index for the `.gnu.version_d` section.
reserve_gnu_verdef_section_index(&mut self) -> SectionIndex1599     pub fn reserve_gnu_verdef_section_index(&mut self) -> SectionIndex {
1600         debug_assert!(self.gnu_verdef_str_id.is_none());
1601         self.gnu_verdef_str_id = Some(self.add_section_name(&b".gnu.version_d"[..]));
1602         self.reserve_section_index()
1603     }
1604 
1605     /// Write the section header for the `.gnu.version_d` section.
1606     ///
1607     /// This function does nothing if the section index was not reserved.
write_gnu_verdef_section_header(&mut self, sh_addr: u64)1608     pub fn write_gnu_verdef_section_header(&mut self, sh_addr: u64) {
1609         if self.gnu_verdef_str_id.is_none() {
1610             return;
1611         }
1612         self.write_section_header(&SectionHeader {
1613             name: self.gnu_verdef_str_id,
1614             sh_type: elf::SHT_GNU_VERDEF,
1615             sh_flags: elf::SHF_ALLOC.into(),
1616             sh_addr,
1617             sh_offset: self.gnu_verdef_offset as u64,
1618             sh_size: self.gnu_verdef_size as u64,
1619             sh_link: self.dynstr_index.0,
1620             sh_info: self.gnu_verdef_count.into(),
1621             sh_addralign: self.elf_align as u64,
1622             sh_entsize: 0,
1623         });
1624     }
1625 
1626     /// Reserve the range for the `.gnu.version_r` section.
reserve_gnu_verneed(&mut self, verneed_count: usize, vernaux_count: usize)1627     pub fn reserve_gnu_verneed(&mut self, verneed_count: usize, vernaux_count: usize) {
1628         debug_assert_eq!(self.gnu_verneed_offset, 0);
1629         if verneed_count == 0 {
1630             return;
1631         }
1632         self.gnu_verneed_size = verneed_count * mem::size_of::<elf::Verneed<Endianness>>()
1633             + vernaux_count * mem::size_of::<elf::Vernaux<Endianness>>();
1634         self.gnu_verneed_offset = self.reserve(self.gnu_verneed_size, self.elf_align);
1635         self.gnu_verneed_count = verneed_count as u16;
1636         self.gnu_verneed_remaining = self.gnu_verneed_count;
1637     }
1638 
1639     /// Write alignment padding bytes prior to a `.gnu.version_r` section.
write_align_gnu_verneed(&mut self)1640     pub fn write_align_gnu_verneed(&mut self) {
1641         if self.gnu_verneed_offset == 0 {
1642             return;
1643         }
1644         util::write_align(self.buffer, self.elf_align);
1645         debug_assert_eq!(self.gnu_verneed_offset, self.buffer.len());
1646     }
1647 
1648     /// Write a version need entry.
write_gnu_verneed(&mut self, verneed: &Verneed)1649     pub fn write_gnu_verneed(&mut self, verneed: &Verneed) {
1650         debug_assert_ne!(self.gnu_verneed_remaining, 0);
1651         self.gnu_verneed_remaining -= 1;
1652         let vn_next = if self.gnu_verneed_remaining == 0 {
1653             0
1654         } else {
1655             mem::size_of::<elf::Verneed<Endianness>>() as u32
1656                 + verneed.aux_count as u32 * mem::size_of::<elf::Vernaux<Endianness>>() as u32
1657         };
1658 
1659         self.gnu_vernaux_remaining = verneed.aux_count;
1660         let vn_aux = if verneed.aux_count == 0 {
1661             0
1662         } else {
1663             mem::size_of::<elf::Verneed<Endianness>>() as u32
1664         };
1665 
1666         self.buffer.write(&elf::Verneed {
1667             vn_version: U16::new(self.endian, verneed.version),
1668             vn_cnt: U16::new(self.endian, verneed.aux_count),
1669             vn_file: U32::new(self.endian, self.dynstr.get_offset(verneed.file) as u32),
1670             vn_aux: U32::new(self.endian, vn_aux),
1671             vn_next: U32::new(self.endian, vn_next),
1672         });
1673     }
1674 
1675     /// Write a version need auxiliary entry.
write_gnu_vernaux(&mut self, vernaux: &Vernaux)1676     pub fn write_gnu_vernaux(&mut self, vernaux: &Vernaux) {
1677         debug_assert_ne!(self.gnu_vernaux_remaining, 0);
1678         self.gnu_vernaux_remaining -= 1;
1679         let vna_next = if self.gnu_vernaux_remaining == 0 {
1680             0
1681         } else {
1682             mem::size_of::<elf::Vernaux<Endianness>>() as u32
1683         };
1684         self.buffer.write(&elf::Vernaux {
1685             vna_hash: U32::new(self.endian, elf::hash(self.dynstr.get_string(vernaux.name))),
1686             vna_flags: U16::new(self.endian, vernaux.flags),
1687             vna_other: U16::new(self.endian, vernaux.index),
1688             vna_name: U32::new(self.endian, self.dynstr.get_offset(vernaux.name) as u32),
1689             vna_next: U32::new(self.endian, vna_next),
1690         });
1691     }
1692 
1693     /// Reserve the section index for the `.gnu.version_r` section.
reserve_gnu_verneed_section_index(&mut self) -> SectionIndex1694     pub fn reserve_gnu_verneed_section_index(&mut self) -> SectionIndex {
1695         debug_assert!(self.gnu_verneed_str_id.is_none());
1696         self.gnu_verneed_str_id = Some(self.add_section_name(&b".gnu.version_r"[..]));
1697         self.reserve_section_index()
1698     }
1699 
1700     /// Write the section header for the `.gnu.version_r` section.
1701     ///
1702     /// This function does nothing if the section index was not reserved.
write_gnu_verneed_section_header(&mut self, sh_addr: u64)1703     pub fn write_gnu_verneed_section_header(&mut self, sh_addr: u64) {
1704         if self.gnu_verneed_str_id.is_none() {
1705             return;
1706         }
1707         self.write_section_header(&SectionHeader {
1708             name: self.gnu_verneed_str_id,
1709             sh_type: elf::SHT_GNU_VERNEED,
1710             sh_flags: elf::SHF_ALLOC.into(),
1711             sh_addr,
1712             sh_offset: self.gnu_verneed_offset as u64,
1713             sh_size: self.gnu_verneed_size as u64,
1714             sh_link: self.dynstr_index.0,
1715             sh_info: self.gnu_verneed_count.into(),
1716             sh_addralign: self.elf_align as u64,
1717             sh_entsize: 0,
1718         });
1719     }
1720 
1721     /// Reserve a file range for the given number of relocations.
1722     ///
1723     /// Returns the offset of the range.
reserve_relocations(&mut self, count: usize, is_rela: bool) -> usize1724     pub fn reserve_relocations(&mut self, count: usize, is_rela: bool) -> usize {
1725         self.reserve(count * self.rel_size(is_rela), self.elf_align)
1726     }
1727 
1728     /// Write alignment padding bytes prior to a relocation section.
write_align_relocation(&mut self)1729     pub fn write_align_relocation(&mut self) {
1730         util::write_align(self.buffer, self.elf_align);
1731     }
1732 
1733     /// Write a relocation.
write_relocation(&mut self, is_rela: bool, rel: &Rel)1734     pub fn write_relocation(&mut self, is_rela: bool, rel: &Rel) {
1735         let endian = self.endian;
1736         if self.is_64 {
1737             if is_rela {
1738                 let rel = elf::Rela64 {
1739                     r_offset: U64::new(endian, rel.r_offset),
1740                     r_info: elf::Rela64::r_info(endian, self.is_mips64el, rel.r_sym, rel.r_type),
1741                     r_addend: I64::new(endian, rel.r_addend),
1742                 };
1743                 self.buffer.write(&rel);
1744             } else {
1745                 let rel = elf::Rel64 {
1746                     r_offset: U64::new(endian, rel.r_offset),
1747                     r_info: elf::Rel64::r_info(endian, rel.r_sym, rel.r_type),
1748                 };
1749                 self.buffer.write(&rel);
1750             }
1751         } else {
1752             if is_rela {
1753                 let rel = elf::Rela32 {
1754                     r_offset: U32::new(endian, rel.r_offset as u32),
1755                     r_info: elf::Rel32::r_info(endian, rel.r_sym, rel.r_type as u8),
1756                     r_addend: I32::new(endian, rel.r_addend as i32),
1757                 };
1758                 self.buffer.write(&rel);
1759             } else {
1760                 let rel = elf::Rel32 {
1761                     r_offset: U32::new(endian, rel.r_offset as u32),
1762                     r_info: elf::Rel32::r_info(endian, rel.r_sym, rel.r_type as u8),
1763                 };
1764                 self.buffer.write(&rel);
1765             }
1766         }
1767     }
1768 
1769     /// Write the section header for a relocation section.
1770     ///
1771     /// `section` is the index of the section the relocations apply to,
1772     /// or 0 if none.
1773     ///
1774     /// `symtab` is the index of the symbol table the relocations refer to,
1775     /// or 0 if none.
1776     ///
1777     /// `offset` is the file offset of the relocations.
write_relocation_section_header( &mut self, name: StringId, section: SectionIndex, symtab: SectionIndex, offset: usize, count: usize, is_rela: bool, )1778     pub fn write_relocation_section_header(
1779         &mut self,
1780         name: StringId,
1781         section: SectionIndex,
1782         symtab: SectionIndex,
1783         offset: usize,
1784         count: usize,
1785         is_rela: bool,
1786     ) {
1787         self.write_section_header(&SectionHeader {
1788             name: Some(name),
1789             sh_type: if is_rela { elf::SHT_RELA } else { elf::SHT_REL },
1790             sh_flags: elf::SHF_INFO_LINK.into(),
1791             sh_addr: 0,
1792             sh_offset: offset as u64,
1793             sh_size: (count * self.rel_size(is_rela)) as u64,
1794             sh_link: symtab.0,
1795             sh_info: section.0,
1796             sh_addralign: self.elf_align as u64,
1797             sh_entsize: self.rel_size(is_rela) as u64,
1798         });
1799     }
1800 
1801     /// Reserve a file range for a COMDAT section.
1802     ///
1803     /// `count` is the number of sections in the COMDAT group.
1804     ///
1805     /// Returns the offset of the range.
reserve_comdat(&mut self, count: usize) -> usize1806     pub fn reserve_comdat(&mut self, count: usize) -> usize {
1807         self.reserve((count + 1) * 4, 4)
1808     }
1809 
1810     /// Write `GRP_COMDAT` at the start of the COMDAT section.
write_comdat_header(&mut self)1811     pub fn write_comdat_header(&mut self) {
1812         util::write_align(self.buffer, 4);
1813         self.buffer.write(&U32::new(self.endian, elf::GRP_COMDAT));
1814     }
1815 
1816     /// Write an entry in a COMDAT section.
write_comdat_entry(&mut self, entry: SectionIndex)1817     pub fn write_comdat_entry(&mut self, entry: SectionIndex) {
1818         self.buffer.write(&U32::new(self.endian, entry.0));
1819     }
1820 
1821     /// Write the section header for a COMDAT section.
write_comdat_section_header( &mut self, name: StringId, symtab: SectionIndex, symbol: SymbolIndex, offset: usize, count: usize, )1822     pub fn write_comdat_section_header(
1823         &mut self,
1824         name: StringId,
1825         symtab: SectionIndex,
1826         symbol: SymbolIndex,
1827         offset: usize,
1828         count: usize,
1829     ) {
1830         self.write_section_header(&SectionHeader {
1831             name: Some(name),
1832             sh_type: elf::SHT_GROUP,
1833             sh_flags: 0,
1834             sh_addr: 0,
1835             sh_offset: offset as u64,
1836             sh_size: ((count + 1) * 4) as u64,
1837             sh_link: symtab.0,
1838             sh_info: symbol.0,
1839             sh_addralign: 4,
1840             sh_entsize: 4,
1841         });
1842     }
1843 }
1844 
1845 /// Native endian version of [`elf::FileHeader64`].
1846 #[allow(missing_docs)]
1847 #[derive(Debug, Clone)]
1848 pub struct FileHeader {
1849     pub os_abi: u8,
1850     pub abi_version: u8,
1851     pub e_type: u16,
1852     pub e_machine: u16,
1853     pub e_entry: u64,
1854     pub e_flags: u32,
1855 }
1856 
1857 /// Native endian version of [`elf::ProgramHeader64`].
1858 #[allow(missing_docs)]
1859 #[derive(Debug, Clone)]
1860 pub struct ProgramHeader {
1861     pub p_type: u32,
1862     pub p_flags: u32,
1863     pub p_offset: u64,
1864     pub p_vaddr: u64,
1865     pub p_paddr: u64,
1866     pub p_filesz: u64,
1867     pub p_memsz: u64,
1868     pub p_align: u64,
1869 }
1870 
1871 /// Native endian version of [`elf::SectionHeader64`].
1872 #[allow(missing_docs)]
1873 #[derive(Debug, Clone)]
1874 pub struct SectionHeader {
1875     pub name: Option<StringId>,
1876     pub sh_type: u32,
1877     pub sh_flags: u64,
1878     pub sh_addr: u64,
1879     pub sh_offset: u64,
1880     pub sh_size: u64,
1881     pub sh_link: u32,
1882     pub sh_info: u32,
1883     pub sh_addralign: u64,
1884     pub sh_entsize: u64,
1885 }
1886 
1887 /// Native endian version of [`elf::Sym64`].
1888 #[allow(missing_docs)]
1889 #[derive(Debug, Clone)]
1890 pub struct Sym {
1891     pub name: Option<StringId>,
1892     pub section: Option<SectionIndex>,
1893     pub st_info: u8,
1894     pub st_other: u8,
1895     pub st_shndx: u16,
1896     pub st_value: u64,
1897     pub st_size: u64,
1898 }
1899 
1900 /// Unified native endian version of [`elf::Rel64`] and [`elf::Rela64`].
1901 #[allow(missing_docs)]
1902 #[derive(Debug, Clone)]
1903 pub struct Rel {
1904     pub r_offset: u64,
1905     pub r_sym: u32,
1906     pub r_type: u32,
1907     pub r_addend: i64,
1908 }
1909 
1910 /// Information required for writing [`elf::Verdef`].
1911 #[allow(missing_docs)]
1912 #[derive(Debug, Clone)]
1913 pub struct Verdef {
1914     pub version: u16,
1915     pub flags: u16,
1916     pub index: u16,
1917     pub aux_count: u16,
1918     /// The name for the first [`elf::Verdaux`] entry.
1919     pub name: StringId,
1920 }
1921 
1922 /// Information required for writing [`elf::Verneed`].
1923 #[allow(missing_docs)]
1924 #[derive(Debug, Clone)]
1925 pub struct Verneed {
1926     pub version: u16,
1927     pub aux_count: u16,
1928     pub file: StringId,
1929 }
1930 
1931 /// Information required for writing [`elf::Vernaux`].
1932 #[allow(missing_docs)]
1933 #[derive(Debug, Clone)]
1934 pub struct Vernaux {
1935     pub flags: u16,
1936     pub index: u16,
1937     pub name: StringId,
1938 }
1939