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