1use 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
13const ALIGN_SYMTAB_SHNDX: usize = 4;
14const ALIGN_HASH: usize = 4;
15const ALIGN_GNU_VERSYM: usize = 2;
16const ALIGN_GNU_VERDEF: usize = 4;
17const ALIGN_GNU_VERNEED: usize = 4;
18
19#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
21pub struct SectionIndex(pub u32);
22
23#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
25pub struct SymbolIndex(pub u32);
26
27#[allow(missing_debug_implementations)]
45pub struct Writer<'a> {
46 endian: Endianness,
47 is_64: bool,
48 is_mips64el: bool,
49 elf_align: usize,
50
51 buffer: &'a mut dyn WritableBuffer,
52 len: usize,
53
54 segment_offset: usize,
55 segment_num: u32,
56
57 section_offset: usize,
58 section_num: u32,
59
60 shstrtab: StringTable<'a>,
61 shstrtab_str_id: Option<StringId>,
62 shstrtab_index: SectionIndex,
63 shstrtab_offset: usize,
64 shstrtab_data: Vec<u8>,
65
66 need_strtab: bool,
67 strtab: StringTable<'a>,
68 strtab_str_id: Option<StringId>,
69 strtab_index: SectionIndex,
70 strtab_offset: usize,
71 strtab_data: Vec<u8>,
72
73 symtab_str_id: Option<StringId>,
74 symtab_index: SectionIndex,
75 symtab_offset: usize,
76 symtab_num: u32,
77
78 need_symtab_shndx: bool,
79 symtab_shndx_str_id: Option<StringId>,
80 symtab_shndx_offset: usize,
81 symtab_shndx_data: Vec<u8>,
82
83 need_dynstr: bool,
84 dynstr: StringTable<'a>,
85 dynstr_str_id: Option<StringId>,
86 dynstr_index: SectionIndex,
87 dynstr_offset: usize,
88 dynstr_data: Vec<u8>,
89
90 dynsym_str_id: Option<StringId>,
91 dynsym_index: SectionIndex,
92 dynsym_offset: usize,
93 dynsym_num: u32,
94
95 dynamic_str_id: Option<StringId>,
96 dynamic_offset: usize,
97 dynamic_num: usize,
98
99 hash_str_id: Option<StringId>,
100 hash_offset: usize,
101 hash_size: usize,
102
103 gnu_hash_str_id: Option<StringId>,
104 gnu_hash_offset: usize,
105 gnu_hash_size: usize,
106
107 gnu_versym_str_id: Option<StringId>,
108 gnu_versym_offset: usize,
109
110 gnu_verdef_str_id: Option<StringId>,
111 gnu_verdef_offset: usize,
112 gnu_verdef_size: usize,
113 gnu_verdef_count: u16,
114 gnu_verdef_remaining: u16,
115 gnu_verdaux_remaining: u16,
116
117 gnu_verneed_str_id: Option<StringId>,
118 gnu_verneed_offset: usize,
119 gnu_verneed_size: usize,
120 gnu_verneed_count: u16,
121 gnu_verneed_remaining: u16,
122 gnu_vernaux_remaining: u16,
123
124 gnu_attributes_str_id: Option<StringId>,
125 gnu_attributes_offset: usize,
126 gnu_attributes_size: usize,
127}
128
129impl<'a> Writer<'a> {
130 pub fn new(endian: Endianness, is_64: bool, buffer: &'a mut dyn WritableBuffer) -> Self {
132 let elf_align = if is_64 { 8 } else { 4 };
133 Writer {
134 endian,
135 is_64,
136 is_mips64el: false,
138 elf_align,
139
140 buffer,
141 len: 0,
142
143 segment_offset: 0,
144 segment_num: 0,
145
146 section_offset: 0,
147 section_num: 0,
148
149 shstrtab: StringTable::default(),
150 shstrtab_str_id: None,
151 shstrtab_index: SectionIndex(0),
152 shstrtab_offset: 0,
153 shstrtab_data: Vec::new(),
154
155 need_strtab: false,
156 strtab: StringTable::default(),
157 strtab_str_id: None,
158 strtab_index: SectionIndex(0),
159 strtab_offset: 0,
160 strtab_data: Vec::new(),
161
162 symtab_str_id: None,
163 symtab_index: SectionIndex(0),
164 symtab_offset: 0,
165 symtab_num: 0,
166
167 need_symtab_shndx: false,
168 symtab_shndx_str_id: None,
169 symtab_shndx_offset: 0,
170 symtab_shndx_data: Vec::new(),
171
172 need_dynstr: false,
173 dynstr: StringTable::default(),
174 dynstr_str_id: None,
175 dynstr_index: SectionIndex(0),
176 dynstr_offset: 0,
177 dynstr_data: Vec::new(),
178
179 dynsym_str_id: None,
180 dynsym_index: SectionIndex(0),
181 dynsym_offset: 0,
182 dynsym_num: 0,
183
184 dynamic_str_id: None,
185 dynamic_offset: 0,
186 dynamic_num: 0,
187
188 hash_str_id: None,
189 hash_offset: 0,
190 hash_size: 0,
191
192 gnu_hash_str_id: None,
193 gnu_hash_offset: 0,
194 gnu_hash_size: 0,
195
196 gnu_versym_str_id: None,
197 gnu_versym_offset: 0,
198
199 gnu_verdef_str_id: None,
200 gnu_verdef_offset: 0,
201 gnu_verdef_size: 0,
202 gnu_verdef_count: 0,
203 gnu_verdef_remaining: 0,
204 gnu_verdaux_remaining: 0,
205
206 gnu_verneed_str_id: None,
207 gnu_verneed_offset: 0,
208 gnu_verneed_size: 0,
209 gnu_verneed_count: 0,
210 gnu_verneed_remaining: 0,
211 gnu_vernaux_remaining: 0,
212
213 gnu_attributes_str_id: None,
214 gnu_attributes_offset: 0,
215 gnu_attributes_size: 0,
216 }
217 }
218
219 fn class(&self) -> Class {
221 Class { is_64: self.is_64 }
222 }
223
224 pub fn reserved_len(&self) -> usize {
226 self.len
227 }
228
229 #[allow(clippy::len_without_is_empty)]
231 pub fn len(&self) -> usize {
232 self.buffer.len()
233 }
234
235 pub fn reserve(&mut self, len: usize, align_start: usize) -> usize {
241 if align_start > 1 {
242 self.len = util::align(self.len, align_start);
243 }
244 let offset = self.len;
245 self.len += len;
246 offset
247 }
248
249 pub fn write_align(&mut self, align_start: usize) {
251 if align_start > 1 {
252 util::write_align(self.buffer, align_start);
253 }
254 }
255
256 pub fn write(&mut self, data: &[u8]) {
260 self.buffer.write_bytes(data);
261 }
262
263 pub fn reserve_until(&mut self, offset: usize) {
265 debug_assert!(self.len <= offset);
266 self.len = offset;
267 }
268
269 pub fn pad_until(&mut self, offset: usize) {
271 debug_assert!(self.buffer.len() <= offset);
272 self.buffer.resize(offset);
273 }
274
275 pub fn reserve_file_header(&mut self) {
279 debug_assert_eq!(self.len, 0);
280 self.reserve(self.class().file_header_size(), 1);
281 }
282
283 pub fn write_file_header(&mut self, header: &FileHeader) -> Result<()> {
289 debug_assert_eq!(self.buffer.len(), 0);
290
291 self.is_mips64el =
292 self.is_64 && self.endian.is_little_endian() && header.e_machine == elf::EM_MIPS;
293
294 self.buffer
296 .reserve(self.len)
297 .map_err(|_| Error(String::from("Cannot allocate buffer")))?;
298
299 let e_ident = elf::Ident {
301 magic: elf::ELFMAG,
302 class: if self.is_64 {
303 elf::ELFCLASS64
304 } else {
305 elf::ELFCLASS32
306 },
307 data: if self.endian.is_little_endian() {
308 elf::ELFDATA2LSB
309 } else {
310 elf::ELFDATA2MSB
311 },
312 version: elf::EV_CURRENT,
313 os_abi: header.os_abi,
314 abi_version: header.abi_version,
315 padding: [0; 7],
316 };
317
318 let e_ehsize = self.class().file_header_size() as u16;
319
320 let e_phoff = self.segment_offset as u64;
321 let e_phentsize = if self.segment_num == 0 {
322 0
323 } else {
324 self.class().program_header_size() as u16
325 };
326 let e_phnum = self.segment_num as u16;
328
329 let e_shoff = self.section_offset as u64;
330 let e_shentsize = if self.section_num == 0 {
331 0
332 } else {
333 self.class().section_header_size() as u16
334 };
335 let e_shnum = if self.section_num >= elf::SHN_LORESERVE.into() {
336 0
337 } else {
338 self.section_num as u16
339 };
340 let e_shstrndx = if self.shstrtab_index.0 >= elf::SHN_LORESERVE.into() {
341 elf::SHN_XINDEX
342 } else {
343 self.shstrtab_index.0 as u16
344 };
345
346 let endian = self.endian;
347 if self.is_64 {
348 let file = elf::FileHeader64 {
349 e_ident,
350 e_type: U16::new(endian, header.e_type),
351 e_machine: U16::new(endian, header.e_machine),
352 e_version: U32::new(endian, elf::EV_CURRENT.into()),
353 e_entry: U64::new(endian, header.e_entry),
354 e_phoff: U64::new(endian, e_phoff),
355 e_shoff: U64::new(endian, e_shoff),
356 e_flags: U32::new(endian, header.e_flags),
357 e_ehsize: U16::new(endian, e_ehsize),
358 e_phentsize: U16::new(endian, e_phentsize),
359 e_phnum: U16::new(endian, e_phnum),
360 e_shentsize: U16::new(endian, e_shentsize),
361 e_shnum: U16::new(endian, e_shnum),
362 e_shstrndx: U16::new(endian, e_shstrndx),
363 };
364 self.buffer.write(&file)
365 } else {
366 let file = elf::FileHeader32 {
367 e_ident,
368 e_type: U16::new(endian, header.e_type),
369 e_machine: U16::new(endian, header.e_machine),
370 e_version: U32::new(endian, elf::EV_CURRENT.into()),
371 e_entry: U32::new(endian, header.e_entry as u32),
372 e_phoff: U32::new(endian, e_phoff as u32),
373 e_shoff: U32::new(endian, e_shoff as u32),
374 e_flags: U32::new(endian, header.e_flags),
375 e_ehsize: U16::new(endian, e_ehsize),
376 e_phentsize: U16::new(endian, e_phentsize),
377 e_phnum: U16::new(endian, e_phnum),
378 e_shentsize: U16::new(endian, e_shentsize),
379 e_shnum: U16::new(endian, e_shnum),
380 e_shstrndx: U16::new(endian, e_shstrndx),
381 };
382 self.buffer.write(&file);
383 }
384
385 Ok(())
386 }
387
388 pub fn reserve_program_headers(&mut self, num: u32) {
390 debug_assert_eq!(self.segment_offset, 0);
391 if num == 0 {
392 return;
393 }
394 self.segment_num = num;
395 self.segment_offset = self.reserve(
396 num as usize * self.class().program_header_size(),
397 self.elf_align,
398 );
399 }
400
401 pub fn write_align_program_headers(&mut self) {
403 if self.segment_offset == 0 {
404 return;
405 }
406 util::write_align(self.buffer, self.elf_align);
407 debug_assert_eq!(self.segment_offset, self.buffer.len());
408 }
409
410 pub fn write_program_header(&mut self, header: &ProgramHeader) {
412 let endian = self.endian;
413 if self.is_64 {
414 let header = elf::ProgramHeader64 {
415 p_type: U32::new(endian, header.p_type),
416 p_flags: U32::new(endian, header.p_flags),
417 p_offset: U64::new(endian, header.p_offset),
418 p_vaddr: U64::new(endian, header.p_vaddr),
419 p_paddr: U64::new(endian, header.p_paddr),
420 p_filesz: U64::new(endian, header.p_filesz),
421 p_memsz: U64::new(endian, header.p_memsz),
422 p_align: U64::new(endian, header.p_align),
423 };
424 self.buffer.write(&header);
425 } else {
426 let header = elf::ProgramHeader32 {
427 p_type: U32::new(endian, header.p_type),
428 p_offset: U32::new(endian, header.p_offset as u32),
429 p_vaddr: U32::new(endian, header.p_vaddr as u32),
430 p_paddr: U32::new(endian, header.p_paddr as u32),
431 p_filesz: U32::new(endian, header.p_filesz as u32),
432 p_memsz: U32::new(endian, header.p_memsz as u32),
433 p_flags: U32::new(endian, header.p_flags),
434 p_align: U32::new(endian, header.p_align as u32),
435 };
436 self.buffer.write(&header);
437 }
438 }
439
440 pub fn reserve_null_section_index(&mut self) -> SectionIndex {
447 debug_assert_eq!(self.section_num, 0);
448 if self.section_num == 0 {
449 self.section_num = 1;
450 }
451 SectionIndex(0)
452 }
453
454 pub fn reserve_section_index(&mut self) -> SectionIndex {
460 debug_assert_eq!(self.section_offset, 0);
461 if self.section_num == 0 {
462 self.section_num = 1;
463 }
464 let index = self.section_num;
465 self.section_num += 1;
466 SectionIndex(index)
467 }
468
469 pub fn reserve_section_headers(&mut self) {
475 debug_assert_eq!(self.section_offset, 0);
476 if self.section_num == 0 {
477 return;
478 }
479 self.section_offset = self.reserve(
480 self.section_num as usize * self.class().section_header_size(),
481 self.elf_align,
482 );
483 }
484
485 pub fn write_null_section_header(&mut self) {
490 if self.section_num == 0 {
491 return;
492 }
493 util::write_align(self.buffer, self.elf_align);
494 debug_assert_eq!(self.section_offset, self.buffer.len());
495 self.write_section_header(&SectionHeader {
496 name: None,
497 sh_type: 0,
498 sh_flags: 0,
499 sh_addr: 0,
500 sh_offset: 0,
501 sh_size: if self.section_num >= elf::SHN_LORESERVE.into() {
502 self.section_num.into()
503 } else {
504 0
505 },
506 sh_link: if self.shstrtab_index.0 >= elf::SHN_LORESERVE.into() {
507 self.shstrtab_index.0
508 } else {
509 0
510 },
511 sh_info: 0,
513 sh_addralign: 0,
514 sh_entsize: 0,
515 });
516 }
517
518 pub fn write_section_header(&mut self, section: &SectionHeader) {
520 let sh_name = if let Some(name) = section.name {
521 self.shstrtab.get_offset(name) as u32
522 } else {
523 0
524 };
525 let endian = self.endian;
526 if self.is_64 {
527 let section = elf::SectionHeader64 {
528 sh_name: U32::new(endian, sh_name),
529 sh_type: U32::new(endian, section.sh_type),
530 sh_flags: U64::new(endian, section.sh_flags),
531 sh_addr: U64::new(endian, section.sh_addr),
532 sh_offset: U64::new(endian, section.sh_offset),
533 sh_size: U64::new(endian, section.sh_size),
534 sh_link: U32::new(endian, section.sh_link),
535 sh_info: U32::new(endian, section.sh_info),
536 sh_addralign: U64::new(endian, section.sh_addralign),
537 sh_entsize: U64::new(endian, section.sh_entsize),
538 };
539 self.buffer.write(§ion);
540 } else {
541 let section = elf::SectionHeader32 {
542 sh_name: U32::new(endian, sh_name),
543 sh_type: U32::new(endian, section.sh_type),
544 sh_flags: U32::new(endian, section.sh_flags as u32),
545 sh_addr: U32::new(endian, section.sh_addr as u32),
546 sh_offset: U32::new(endian, section.sh_offset as u32),
547 sh_size: U32::new(endian, section.sh_size as u32),
548 sh_link: U32::new(endian, section.sh_link),
549 sh_info: U32::new(endian, section.sh_info),
550 sh_addralign: U32::new(endian, section.sh_addralign as u32),
551 sh_entsize: U32::new(endian, section.sh_entsize as u32),
552 };
553 self.buffer.write(§ion);
554 }
555 }
556
557 pub fn add_section_name(&mut self, name: &'a [u8]) -> StringId {
563 debug_assert_eq!(self.shstrtab_offset, 0);
564 self.shstrtab.add(name)
565 }
566
567 pub fn reserve_shstrtab(&mut self) {
575 debug_assert_eq!(self.shstrtab_offset, 0);
576 if self.section_num == 0 {
577 return;
578 }
579 self.shstrtab_data = vec![0];
581 self.shstrtab.write(1, &mut self.shstrtab_data);
582 self.shstrtab_offset = self.reserve(self.shstrtab_data.len(), 1);
583 }
584
585 pub fn write_shstrtab(&mut self) {
589 if self.shstrtab_offset == 0 {
590 return;
591 }
592 debug_assert_eq!(self.shstrtab_offset, self.buffer.len());
593 self.buffer.write_bytes(&self.shstrtab_data);
594 }
595
596 pub fn reserve_shstrtab_section_index(&mut self) -> SectionIndex {
601 self.reserve_shstrtab_section_index_with_name(&b".shstrtab"[..])
602 }
603
604 pub fn reserve_shstrtab_section_index_with_name(&mut self, name: &'a [u8]) -> SectionIndex {
609 debug_assert_eq!(self.shstrtab_index, SectionIndex(0));
610 self.shstrtab_str_id = Some(self.add_section_name(name));
611 self.shstrtab_index = self.reserve_section_index();
612 self.shstrtab_index
613 }
614
615 pub fn write_shstrtab_section_header(&mut self) {
619 if self.shstrtab_index == SectionIndex(0) {
620 return;
621 }
622 self.write_section_header(&SectionHeader {
623 name: self.shstrtab_str_id,
624 sh_type: elf::SHT_STRTAB,
625 sh_flags: 0,
626 sh_addr: 0,
627 sh_offset: self.shstrtab_offset as u64,
628 sh_size: self.shstrtab_data.len() as u64,
629 sh_link: 0,
630 sh_info: 0,
631 sh_addralign: 1,
632 sh_entsize: 0,
633 });
634 }
635
636 pub fn add_string(&mut self, name: &'a [u8]) -> StringId {
642 debug_assert_eq!(self.strtab_offset, 0);
643 self.need_strtab = true;
644 self.strtab.add(name)
645 }
646
647 pub fn strtab_needed(&self) -> bool {
649 self.need_strtab
650 }
651
652 pub fn require_strtab(&mut self) {
654 self.need_strtab = true;
655 }
656
657 pub fn reserve_strtab(&mut self) {
664 debug_assert_eq!(self.strtab_offset, 0);
665 if !self.need_strtab {
666 return;
667 }
668 self.strtab_data = vec![0];
670 self.strtab.write(1, &mut self.strtab_data);
671 self.strtab_offset = self.reserve(self.strtab_data.len(), 1);
672 }
673
674 pub fn write_strtab(&mut self) {
678 if self.strtab_offset == 0 {
679 return;
680 }
681 debug_assert_eq!(self.strtab_offset, self.buffer.len());
682 self.buffer.write_bytes(&self.strtab_data);
683 }
684
685 pub fn reserve_strtab_section_index(&mut self) -> SectionIndex {
692 self.reserve_strtab_section_index_with_name(&b".strtab"[..])
693 }
694
695 pub fn reserve_strtab_section_index_with_name(&mut self, name: &'a [u8]) -> SectionIndex {
702 debug_assert_eq!(self.strtab_index, SectionIndex(0));
703 self.strtab_str_id = Some(self.add_section_name(name));
704 self.strtab_index = self.reserve_section_index();
705 self.strtab_index
706 }
707
708 pub fn write_strtab_section_header(&mut self) {
712 if self.strtab_index == SectionIndex(0) {
713 return;
714 }
715 self.write_section_header(&SectionHeader {
716 name: self.strtab_str_id,
717 sh_type: elf::SHT_STRTAB,
718 sh_flags: 0,
719 sh_addr: 0,
720 sh_offset: self.strtab_offset as u64,
721 sh_size: self.strtab_data.len() as u64,
722 sh_link: 0,
723 sh_info: 0,
724 sh_addralign: 1,
725 sh_entsize: 0,
726 });
727 }
728
729 pub fn reserve_null_symbol_index(&mut self) -> SymbolIndex {
738 debug_assert_eq!(self.symtab_offset, 0);
739 debug_assert_eq!(self.symtab_num, 0);
740 self.symtab_num = 1;
741 self.need_strtab = true;
743 SymbolIndex(0)
744 }
745
746 pub fn reserve_symbol_index(&mut self, section_index: Option<SectionIndex>) -> SymbolIndex {
759 debug_assert_eq!(self.symtab_offset, 0);
760 debug_assert_eq!(self.symtab_shndx_offset, 0);
761 if self.symtab_num == 0 {
762 self.symtab_num = 1;
763 self.need_strtab = true;
765 }
766 let index = self.symtab_num;
767 self.symtab_num += 1;
768 if let Some(section_index) = section_index {
769 if section_index.0 >= elf::SHN_LORESERVE.into() {
770 self.need_symtab_shndx = true;
771 }
772 }
773 SymbolIndex(index)
774 }
775
776 pub fn symbol_count(&self) -> u32 {
780 self.symtab_num
781 }
782
783 pub fn reserve_symtab(&mut self) {
789 debug_assert_eq!(self.symtab_offset, 0);
790 if self.symtab_num == 0 {
791 return;
792 }
793 self.symtab_offset = self.reserve(
794 self.symtab_num as usize * self.class().sym_size(),
795 self.elf_align,
796 );
797 }
798
799 pub fn write_null_symbol(&mut self) {
804 if self.symtab_num == 0 {
805 return;
806 }
807 util::write_align(self.buffer, self.elf_align);
808 debug_assert_eq!(self.symtab_offset, self.buffer.len());
809 if self.is_64 {
810 self.buffer.write(&elf::Sym64::<Endianness>::default());
811 } else {
812 self.buffer.write(&elf::Sym32::<Endianness>::default());
813 }
814
815 if self.need_symtab_shndx {
816 self.symtab_shndx_data.write_pod(&U32::new(self.endian, 0));
817 }
818 }
819
820 pub fn write_symbol(&mut self, sym: &Sym) {
822 let st_name = if let Some(name) = sym.name {
823 self.strtab.get_offset(name) as u32
824 } else {
825 0
826 };
827 let st_shndx = if let Some(section) = sym.section {
828 if section.0 >= elf::SHN_LORESERVE as u32 {
829 elf::SHN_XINDEX
830 } else {
831 section.0 as u16
832 }
833 } else {
834 sym.st_shndx
835 };
836
837 let endian = self.endian;
838 if self.is_64 {
839 let sym = elf::Sym64 {
840 st_name: U32::new(endian, st_name),
841 st_info: sym.st_info,
842 st_other: sym.st_other,
843 st_shndx: U16::new(endian, st_shndx),
844 st_value: U64::new(endian, sym.st_value),
845 st_size: U64::new(endian, sym.st_size),
846 };
847 self.buffer.write(&sym);
848 } else {
849 let sym = elf::Sym32 {
850 st_name: U32::new(endian, st_name),
851 st_info: sym.st_info,
852 st_other: sym.st_other,
853 st_shndx: U16::new(endian, st_shndx),
854 st_value: U32::new(endian, sym.st_value as u32),
855 st_size: U32::new(endian, sym.st_size as u32),
856 };
857 self.buffer.write(&sym);
858 }
859
860 if self.need_symtab_shndx {
861 let section_index = sym.section.unwrap_or(SectionIndex(0));
862 self.symtab_shndx_data
863 .write_pod(&U32::new(self.endian, section_index.0));
864 }
865 }
866
867 pub fn reserve_symtab_section_index(&mut self) -> SectionIndex {
871 self.reserve_symtab_section_index_with_name(&b".symtab"[..])
872 }
873
874 pub fn reserve_symtab_section_index_with_name(&mut self, name: &'a [u8]) -> SectionIndex {
878 debug_assert_eq!(self.symtab_index, SectionIndex(0));
879 self.symtab_str_id = Some(self.add_section_name(name));
880 self.symtab_index = self.reserve_section_index();
881 self.symtab_index
882 }
883
884 pub fn symtab_index(&mut self) -> SectionIndex {
886 self.symtab_index
887 }
888
889 pub fn write_symtab_section_header(&mut self, num_local: u32) {
893 if self.symtab_index == SectionIndex(0) {
894 return;
895 }
896 self.write_section_header(&SectionHeader {
897 name: self.symtab_str_id,
898 sh_type: elf::SHT_SYMTAB,
899 sh_flags: 0,
900 sh_addr: 0,
901 sh_offset: self.symtab_offset as u64,
902 sh_size: self.symtab_num as u64 * self.class().sym_size() as u64,
903 sh_link: self.strtab_index.0,
904 sh_info: num_local,
905 sh_addralign: self.elf_align as u64,
906 sh_entsize: self.class().sym_size() as u64,
907 });
908 }
909
910 pub fn symtab_shndx_needed(&self) -> bool {
912 self.need_symtab_shndx
913 }
914
915 pub fn require_symtab_shndx(&mut self) {
918 self.need_symtab_shndx = true;
919 }
920
921 pub fn reserve_symtab_shndx(&mut self) {
929 debug_assert_eq!(self.symtab_shndx_offset, 0);
930 if !self.need_symtab_shndx {
931 return;
932 }
933 self.symtab_shndx_offset = self.reserve(self.symtab_num as usize * 4, ALIGN_SYMTAB_SHNDX);
934 self.symtab_shndx_data.reserve(self.symtab_num as usize * 4);
935 }
936
937 pub fn write_symtab_shndx(&mut self) {
941 if self.symtab_shndx_offset == 0 {
942 return;
943 }
944 util::write_align(self.buffer, ALIGN_SYMTAB_SHNDX);
945 debug_assert_eq!(self.symtab_shndx_offset, self.buffer.len());
946 debug_assert_eq!(self.symtab_num as usize * 4, self.symtab_shndx_data.len());
947 self.buffer.write_bytes(&self.symtab_shndx_data);
948 }
949
950 pub fn reserve_symtab_shndx_section_index(&mut self) -> SectionIndex {
957 self.reserve_symtab_shndx_section_index_with_name(&b".symtab_shndx"[..])
958 }
959
960 pub fn reserve_symtab_shndx_section_index_with_name(&mut self, name: &'a [u8]) -> SectionIndex {
967 debug_assert!(self.symtab_shndx_str_id.is_none());
968 self.symtab_shndx_str_id = Some(self.add_section_name(name));
969 self.reserve_section_index()
970 }
971
972 pub fn write_symtab_shndx_section_header(&mut self) {
976 if self.symtab_shndx_str_id.is_none() {
977 return;
978 }
979 let sh_size = if self.symtab_shndx_offset == 0 {
980 0
981 } else {
982 (self.symtab_num * 4) as u64
983 };
984 self.write_section_header(&SectionHeader {
985 name: self.symtab_shndx_str_id,
986 sh_type: elf::SHT_SYMTAB_SHNDX,
987 sh_flags: 0,
988 sh_addr: 0,
989 sh_offset: self.symtab_shndx_offset as u64,
990 sh_size,
991 sh_link: self.symtab_index.0,
992 sh_info: 0,
993 sh_addralign: ALIGN_SYMTAB_SHNDX as u64,
994 sh_entsize: 4,
995 });
996 }
997
998 pub fn add_dynamic_string(&mut self, name: &'a [u8]) -> StringId {
1004 debug_assert_eq!(self.dynstr_offset, 0);
1005 self.need_dynstr = true;
1006 self.dynstr.add(name)
1007 }
1008
1009 pub fn get_dynamic_string(&self, name: &'a [u8]) -> StringId {
1013 self.dynstr.get_id(name)
1014 }
1015
1016 pub fn dynstr_needed(&self) -> bool {
1018 self.need_dynstr
1019 }
1020
1021 pub fn require_dynstr(&mut self) {
1023 self.need_dynstr = true;
1024 }
1025
1026 pub fn reserve_dynstr(&mut self) -> usize {
1033 debug_assert_eq!(self.dynstr_offset, 0);
1034 if !self.need_dynstr {
1035 return 0;
1036 }
1037 self.dynstr_data = vec![0];
1039 self.dynstr.write(1, &mut self.dynstr_data);
1040 self.dynstr_offset = self.reserve(self.dynstr_data.len(), 1);
1041 self.dynstr_offset
1042 }
1043
1044 pub fn dynstr_len(&mut self) -> usize {
1048 debug_assert_ne!(self.dynstr_offset, 0);
1049 self.dynstr_data.len()
1050 }
1051
1052 pub fn write_dynstr(&mut self) {
1056 if self.dynstr_offset == 0 {
1057 return;
1058 }
1059 debug_assert_eq!(self.dynstr_offset, self.buffer.len());
1060 self.buffer.write_bytes(&self.dynstr_data);
1061 }
1062
1063 pub fn reserve_dynstr_section_index(&mut self) -> SectionIndex {
1070 self.reserve_dynstr_section_index_with_name(&b".dynstr"[..])
1071 }
1072
1073 pub fn reserve_dynstr_section_index_with_name(&mut self, name: &'a [u8]) -> SectionIndex {
1080 debug_assert_eq!(self.dynstr_index, SectionIndex(0));
1081 self.dynstr_str_id = Some(self.add_section_name(name));
1082 self.dynstr_index = self.reserve_section_index();
1083 self.dynstr_index
1084 }
1085
1086 pub fn dynstr_index(&mut self) -> SectionIndex {
1088 self.dynstr_index
1089 }
1090
1091 pub fn write_dynstr_section_header(&mut self, sh_addr: u64) {
1095 if self.dynstr_index == SectionIndex(0) {
1096 return;
1097 }
1098 self.write_section_header(&SectionHeader {
1099 name: self.dynstr_str_id,
1100 sh_type: elf::SHT_STRTAB,
1101 sh_flags: elf::SHF_ALLOC.into(),
1102 sh_addr,
1103 sh_offset: self.dynstr_offset as u64,
1104 sh_size: self.dynstr_data.len() as u64,
1105 sh_link: 0,
1106 sh_info: 0,
1107 sh_addralign: 1,
1108 sh_entsize: 0,
1109 });
1110 }
1111
1112 pub fn reserve_null_dynamic_symbol_index(&mut self) -> SymbolIndex {
1121 debug_assert_eq!(self.dynsym_offset, 0);
1122 debug_assert_eq!(self.dynsym_num, 0);
1123 self.dynsym_num = 1;
1124 SymbolIndex(0)
1125 }
1126
1127 pub fn reserve_dynamic_symbol_index(&mut self) -> SymbolIndex {
1137 debug_assert_eq!(self.dynsym_offset, 0);
1138 if self.dynsym_num == 0 {
1139 self.dynsym_num = 1;
1140 }
1141 let index = self.dynsym_num;
1142 self.dynsym_num += 1;
1143 SymbolIndex(index)
1144 }
1145
1146 pub fn dynamic_symbol_count(&mut self) -> u32 {
1150 self.dynsym_num
1151 }
1152
1153 pub fn reserve_dynsym(&mut self) -> usize {
1160 debug_assert_eq!(self.dynsym_offset, 0);
1161 if self.dynsym_num == 0 {
1162 return 0;
1163 }
1164 self.dynsym_offset = self.reserve(
1165 self.dynsym_num as usize * self.class().sym_size(),
1166 self.elf_align,
1167 );
1168 self.dynsym_offset
1169 }
1170
1171 pub fn write_null_dynamic_symbol(&mut self) {
1176 if self.dynsym_num == 0 {
1177 return;
1178 }
1179 util::write_align(self.buffer, self.elf_align);
1180 debug_assert_eq!(self.dynsym_offset, self.buffer.len());
1181 if self.is_64 {
1182 self.buffer.write(&elf::Sym64::<Endianness>::default());
1183 } else {
1184 self.buffer.write(&elf::Sym32::<Endianness>::default());
1185 }
1186 }
1187
1188 pub fn write_dynamic_symbol(&mut self, sym: &Sym) {
1190 let st_name = if let Some(name) = sym.name {
1191 self.dynstr.get_offset(name) as u32
1192 } else {
1193 0
1194 };
1195
1196 let st_shndx = if let Some(section) = sym.section {
1197 if section.0 >= elf::SHN_LORESERVE as u32 {
1198 elf::SHN_XINDEX
1201 } else {
1202 section.0 as u16
1203 }
1204 } else {
1205 sym.st_shndx
1206 };
1207
1208 let endian = self.endian;
1209 if self.is_64 {
1210 let sym = elf::Sym64 {
1211 st_name: U32::new(endian, st_name),
1212 st_info: sym.st_info,
1213 st_other: sym.st_other,
1214 st_shndx: U16::new(endian, st_shndx),
1215 st_value: U64::new(endian, sym.st_value),
1216 st_size: U64::new(endian, sym.st_size),
1217 };
1218 self.buffer.write(&sym);
1219 } else {
1220 let sym = elf::Sym32 {
1221 st_name: U32::new(endian, st_name),
1222 st_info: sym.st_info,
1223 st_other: sym.st_other,
1224 st_shndx: U16::new(endian, st_shndx),
1225 st_value: U32::new(endian, sym.st_value as u32),
1226 st_size: U32::new(endian, sym.st_size as u32),
1227 };
1228 self.buffer.write(&sym);
1229 }
1230 }
1231
1232 pub fn reserve_dynsym_section_index(&mut self) -> SectionIndex {
1236 self.reserve_dynsym_section_index_with_name(&b".dynsym"[..])
1237 }
1238
1239 pub fn reserve_dynsym_section_index_with_name(&mut self, name: &'a [u8]) -> SectionIndex {
1243 debug_assert_eq!(self.dynsym_index, SectionIndex(0));
1244 self.dynsym_str_id = Some(self.add_section_name(name));
1245 self.dynsym_index = self.reserve_section_index();
1246 self.dynsym_index
1247 }
1248
1249 pub fn dynsym_index(&mut self) -> SectionIndex {
1251 self.dynsym_index
1252 }
1253
1254 pub fn write_dynsym_section_header(&mut self, sh_addr: u64, num_local: u32) {
1258 if self.dynsym_index == SectionIndex(0) {
1259 return;
1260 }
1261 self.write_section_header(&SectionHeader {
1262 name: self.dynsym_str_id,
1263 sh_type: elf::SHT_DYNSYM,
1264 sh_flags: elf::SHF_ALLOC.into(),
1265 sh_addr,
1266 sh_offset: self.dynsym_offset as u64,
1267 sh_size: self.dynsym_num as u64 * self.class().sym_size() as u64,
1268 sh_link: self.dynstr_index.0,
1269 sh_info: num_local,
1270 sh_addralign: self.elf_align as u64,
1271 sh_entsize: self.class().sym_size() as u64,
1272 });
1273 }
1274
1275 pub fn reserve_dynamic(&mut self, dynamic_num: usize) -> usize {
1279 debug_assert_eq!(self.dynamic_offset, 0);
1280 if dynamic_num == 0 {
1281 return 0;
1282 }
1283 self.dynamic_num = dynamic_num;
1284 self.dynamic_offset = self.reserve_dynamics(dynamic_num);
1285 self.dynamic_offset
1286 }
1287
1288 pub fn write_align_dynamic(&mut self) {
1292 if self.dynamic_offset == 0 {
1293 return;
1294 }
1295 util::write_align(self.buffer, self.elf_align);
1296 debug_assert_eq!(self.dynamic_offset, self.buffer.len());
1297 }
1298
1299 pub fn reserve_dynamics(&mut self, dynamic_num: usize) -> usize {
1303 self.reserve(dynamic_num * self.class().dyn_size(), self.elf_align)
1304 }
1305
1306 pub fn write_dynamic_string(&mut self, tag: u32, id: StringId) {
1308 self.write_dynamic(tag, self.dynstr.get_offset(id) as u64);
1309 }
1310
1311 pub fn write_dynamic(&mut self, d_tag: u32, d_val: u64) {
1313 let endian = self.endian;
1314 if self.is_64 {
1315 let d = elf::Dyn64 {
1316 d_tag: U64::new(endian, d_tag.into()),
1317 d_val: U64::new(endian, d_val),
1318 };
1319 self.buffer.write(&d);
1320 } else {
1321 let d = elf::Dyn32 {
1322 d_tag: U32::new(endian, d_tag),
1323 d_val: U32::new(endian, d_val as u32),
1324 };
1325 self.buffer.write(&d);
1326 }
1327 }
1328
1329 pub fn reserve_dynamic_section_index(&mut self) -> SectionIndex {
1331 debug_assert!(self.dynamic_str_id.is_none());
1332 self.dynamic_str_id = Some(self.add_section_name(&b".dynamic"[..]));
1333 self.reserve_section_index()
1334 }
1335
1336 pub fn write_dynamic_section_header(&mut self, sh_addr: u64) {
1340 if self.dynamic_str_id.is_none() {
1341 return;
1342 }
1343 self.write_section_header(&SectionHeader {
1344 name: self.dynamic_str_id,
1345 sh_type: elf::SHT_DYNAMIC,
1346 sh_flags: (elf::SHF_WRITE | elf::SHF_ALLOC).into(),
1347 sh_addr,
1348 sh_offset: self.dynamic_offset as u64,
1349 sh_size: (self.dynamic_num * self.class().dyn_size()) as u64,
1350 sh_link: self.dynstr_index.0,
1351 sh_info: 0,
1352 sh_addralign: self.elf_align as u64,
1353 sh_entsize: self.class().dyn_size() as u64,
1354 });
1355 }
1356
1357 pub fn reserve_hash(&mut self, bucket_count: u32, chain_count: u32) -> usize {
1362 self.hash_size = self.class().hash_size(bucket_count, chain_count);
1363 self.hash_offset = self.reserve(self.hash_size, ALIGN_HASH);
1364 self.hash_offset
1365 }
1366
1367 pub fn write_hash<F>(&mut self, bucket_count: u32, chain_count: u32, hash: F)
1372 where
1373 F: Fn(u32) -> Option<u32>,
1374 {
1375 let mut buckets = vec![U32::new(self.endian, 0); bucket_count as usize];
1376 let mut chains = vec![U32::new(self.endian, 0); chain_count as usize];
1377 for i in 0..chain_count {
1378 if let Some(hash) = hash(i) {
1379 let bucket = hash % bucket_count;
1380 chains[i as usize] = buckets[bucket as usize];
1381 buckets[bucket as usize] = U32::new(self.endian, i);
1382 }
1383 }
1384
1385 util::write_align(self.buffer, ALIGN_HASH);
1386 debug_assert_eq!(self.hash_offset, self.buffer.len());
1387 self.buffer.write(&elf::HashHeader {
1388 bucket_count: U32::new(self.endian, bucket_count),
1389 chain_count: U32::new(self.endian, chain_count),
1390 });
1391 self.buffer.write_slice(&buckets);
1392 self.buffer.write_slice(&chains);
1393 }
1394
1395 pub fn reserve_hash_section_index(&mut self) -> SectionIndex {
1397 self.reserve_hash_section_index_with_name(&b".hash"[..])
1398 }
1399
1400 pub fn reserve_hash_section_index_with_name(&mut self, name: &'a [u8]) -> SectionIndex {
1402 debug_assert!(self.hash_str_id.is_none());
1403 self.hash_str_id = Some(self.add_section_name(name));
1404 self.reserve_section_index()
1405 }
1406
1407 pub fn write_hash_section_header(&mut self, sh_addr: u64) {
1411 if self.hash_str_id.is_none() {
1412 return;
1413 }
1414 self.write_section_header(&SectionHeader {
1415 name: self.hash_str_id,
1416 sh_type: elf::SHT_HASH,
1417 sh_flags: elf::SHF_ALLOC.into(),
1418 sh_addr,
1419 sh_offset: self.hash_offset as u64,
1420 sh_size: self.hash_size as u64,
1421 sh_link: self.dynsym_index.0,
1422 sh_info: 0,
1423 sh_addralign: ALIGN_HASH as u64,
1424 sh_entsize: 4,
1425 });
1426 }
1427
1428 pub fn reserve_gnu_hash(
1433 &mut self,
1434 bloom_count: u32,
1435 bucket_count: u32,
1436 symbol_count: u32,
1437 ) -> usize {
1438 self.gnu_hash_size = self
1439 .class()
1440 .gnu_hash_size(bloom_count, bucket_count, symbol_count);
1441 self.gnu_hash_offset = self.reserve(self.gnu_hash_size, self.elf_align);
1442 self.gnu_hash_offset
1443 }
1444
1445 pub fn write_gnu_hash<F>(
1452 &mut self,
1453 symbol_base: u32,
1454 bloom_shift: u32,
1455 bloom_count: u32,
1456 bucket_count: u32,
1457 symbol_count: u32,
1458 hash: F,
1459 ) where
1460 F: Fn(u32) -> u32,
1461 {
1462 util::write_align(self.buffer, self.elf_align);
1463 debug_assert_eq!(self.gnu_hash_offset, self.buffer.len());
1464 self.buffer.write(&elf::GnuHashHeader {
1465 bucket_count: U32::new(self.endian, bucket_count),
1466 symbol_base: U32::new(self.endian, symbol_base),
1467 bloom_count: U32::new(self.endian, bloom_count),
1468 bloom_shift: U32::new(self.endian, bloom_shift),
1469 });
1470
1471 if self.is_64 {
1473 let mut bloom_filters = vec![0; bloom_count as usize];
1474 for i in 0..symbol_count {
1475 let h = hash(i);
1476 bloom_filters[((h / 64) & (bloom_count - 1)) as usize] |=
1477 1 << (h % 64) | 1 << ((h >> bloom_shift) % 64);
1478 }
1479 for bloom_filter in bloom_filters {
1480 self.buffer.write(&U64::new(self.endian, bloom_filter));
1481 }
1482 } else {
1483 let mut bloom_filters = vec![0; bloom_count as usize];
1484 for i in 0..symbol_count {
1485 let h = hash(i);
1486 bloom_filters[((h / 32) & (bloom_count - 1)) as usize] |=
1487 1 << (h % 32) | 1 << ((h >> bloom_shift) % 32);
1488 }
1489 for bloom_filter in bloom_filters {
1490 self.buffer.write(&U32::new(self.endian, bloom_filter));
1491 }
1492 }
1493
1494 let mut bucket = 0;
1498 for i in 0..symbol_count {
1499 let symbol_bucket = hash(i) % bucket_count;
1500 while bucket < symbol_bucket {
1501 self.buffer.write(&U32::new(self.endian, 0));
1502 bucket += 1;
1503 }
1504 if bucket == symbol_bucket {
1505 self.buffer.write(&U32::new(self.endian, symbol_base + i));
1506 bucket += 1;
1507 }
1508 }
1509 while bucket < bucket_count {
1510 self.buffer.write(&U32::new(self.endian, 0));
1511 bucket += 1;
1512 }
1513
1514 for i in 0..symbol_count {
1516 let mut h = hash(i);
1517 if i == symbol_count - 1 || h % bucket_count != hash(i + 1) % bucket_count {
1518 h |= 1;
1519 } else {
1520 h &= !1;
1521 }
1522 self.buffer.write(&U32::new(self.endian, h));
1523 }
1524 }
1525
1526 pub fn reserve_gnu_hash_section_index(&mut self) -> SectionIndex {
1528 self.reserve_gnu_hash_section_index_with_name(&b".gnu.hash"[..])
1529 }
1530
1531 pub fn reserve_gnu_hash_section_index_with_name(&mut self, name: &'a [u8]) -> SectionIndex {
1533 debug_assert!(self.gnu_hash_str_id.is_none());
1534 self.gnu_hash_str_id = Some(self.add_section_name(name));
1535 self.reserve_section_index()
1536 }
1537
1538 pub fn write_gnu_hash_section_header(&mut self, sh_addr: u64) {
1542 if self.gnu_hash_str_id.is_none() {
1543 return;
1544 }
1545 self.write_section_header(&SectionHeader {
1546 name: self.gnu_hash_str_id,
1547 sh_type: elf::SHT_GNU_HASH,
1548 sh_flags: elf::SHF_ALLOC.into(),
1549 sh_addr,
1550 sh_offset: self.gnu_hash_offset as u64,
1551 sh_size: self.gnu_hash_size as u64,
1552 sh_link: self.dynsym_index.0,
1553 sh_info: 0,
1554 sh_addralign: self.elf_align as u64,
1555 sh_entsize: if self.is_64 { 0 } else { 4 },
1556 });
1557 }
1558
1559 pub fn reserve_gnu_versym(&mut self) -> usize {
1563 debug_assert_eq!(self.gnu_versym_offset, 0);
1564 if self.dynsym_num == 0 {
1565 return 0;
1566 }
1567 self.gnu_versym_offset = self.reserve(self.dynsym_num as usize * 2, ALIGN_GNU_VERSYM);
1568 self.gnu_versym_offset
1569 }
1570
1571 pub fn write_null_gnu_versym(&mut self) {
1576 if self.dynsym_num == 0 {
1577 return;
1578 }
1579 util::write_align(self.buffer, ALIGN_GNU_VERSYM);
1580 debug_assert_eq!(self.gnu_versym_offset, self.buffer.len());
1581 self.write_gnu_versym(0);
1582 }
1583
1584 pub fn write_gnu_versym(&mut self, versym: u16) {
1586 self.buffer.write(&U16::new(self.endian, versym));
1587 }
1588
1589 pub fn reserve_gnu_versym_section_index(&mut self) -> SectionIndex {
1591 self.reserve_gnu_versym_section_index_with_name(&b".gnu.version"[..])
1592 }
1593
1594 pub fn reserve_gnu_versym_section_index_with_name(&mut self, name: &'a [u8]) -> SectionIndex {
1596 debug_assert!(self.gnu_versym_str_id.is_none());
1597 self.gnu_versym_str_id = Some(self.add_section_name(name));
1598 self.reserve_section_index()
1599 }
1600
1601 pub fn write_gnu_versym_section_header(&mut self, sh_addr: u64) {
1605 if self.gnu_versym_str_id.is_none() {
1606 return;
1607 }
1608 self.write_section_header(&SectionHeader {
1609 name: self.gnu_versym_str_id,
1610 sh_type: elf::SHT_GNU_VERSYM,
1611 sh_flags: elf::SHF_ALLOC.into(),
1612 sh_addr,
1613 sh_offset: self.gnu_versym_offset as u64,
1614 sh_size: self.class().gnu_versym_size(self.dynsym_num as usize) as u64,
1615 sh_link: self.dynsym_index.0,
1616 sh_info: 0,
1617 sh_addralign: ALIGN_GNU_VERSYM as u64,
1618 sh_entsize: 2,
1619 });
1620 }
1621
1622 pub fn reserve_gnu_verdef(&mut self, verdef_count: usize, verdaux_count: usize) -> usize {
1624 debug_assert_eq!(self.gnu_verdef_offset, 0);
1625 if verdef_count == 0 {
1626 return 0;
1627 }
1628 self.gnu_verdef_size = self.class().gnu_verdef_size(verdef_count, verdaux_count);
1629 self.gnu_verdef_offset = self.reserve(self.gnu_verdef_size, ALIGN_GNU_VERDEF);
1630 self.gnu_verdef_count = verdef_count as u16;
1631 self.gnu_verdef_remaining = self.gnu_verdef_count;
1632 self.gnu_verdef_offset
1633 }
1634
1635 pub fn write_align_gnu_verdef(&mut self) {
1637 if self.gnu_verdef_offset == 0 {
1638 return;
1639 }
1640 util::write_align(self.buffer, ALIGN_GNU_VERDEF);
1641 debug_assert_eq!(self.gnu_verdef_offset, self.buffer.len());
1642 }
1643
1644 pub fn write_gnu_verdef(&mut self, verdef: &Verdef) {
1646 debug_assert_ne!(self.gnu_verdef_remaining, 0);
1647 self.gnu_verdef_remaining -= 1;
1648 let vd_next = if self.gnu_verdef_remaining == 0 {
1649 0
1650 } else {
1651 mem::size_of::<elf::Verdef<Endianness>>() as u32
1652 + verdef.aux_count as u32 * mem::size_of::<elf::Verdaux<Endianness>>() as u32
1653 };
1654
1655 debug_assert_ne!(verdef.aux_count, 0);
1656 self.gnu_verdaux_remaining = verdef.aux_count;
1657 let vd_aux = mem::size_of::<elf::Verdef<Endianness>>() as u32;
1658
1659 self.buffer.write(&elf::Verdef {
1660 vd_version: U16::new(self.endian, verdef.version),
1661 vd_flags: U16::new(self.endian, verdef.flags),
1662 vd_ndx: U16::new(self.endian, verdef.index),
1663 vd_cnt: U16::new(self.endian, verdef.aux_count),
1664 vd_hash: U32::new(self.endian, elf::hash(self.dynstr.get_string(verdef.name))),
1665 vd_aux: U32::new(self.endian, vd_aux),
1666 vd_next: U32::new(self.endian, vd_next),
1667 });
1668 self.write_gnu_verdaux(verdef.name);
1669 }
1670
1671 pub fn write_gnu_verdef_shared(&mut self, verdef: &Verdef) {
1676 debug_assert_ne!(self.gnu_verdef_remaining, 0);
1677 self.gnu_verdef_remaining -= 1;
1678 debug_assert_ne!(self.gnu_verdef_remaining, 0);
1679 let vd_next = mem::size_of::<elf::Verdef<Endianness>>() as u32;
1680
1681 debug_assert_ne!(verdef.aux_count, 0);
1682 self.gnu_verdaux_remaining = 0;
1683 let vd_aux = 2 * mem::size_of::<elf::Verdef<Endianness>>() as u32;
1684
1685 self.buffer.write(&elf::Verdef {
1686 vd_version: U16::new(self.endian, verdef.version),
1687 vd_flags: U16::new(self.endian, verdef.flags),
1688 vd_ndx: U16::new(self.endian, verdef.index),
1689 vd_cnt: U16::new(self.endian, verdef.aux_count),
1690 vd_hash: U32::new(self.endian, elf::hash(self.dynstr.get_string(verdef.name))),
1691 vd_aux: U32::new(self.endian, vd_aux),
1692 vd_next: U32::new(self.endian, vd_next),
1693 });
1694 }
1695
1696 pub fn write_gnu_verdaux(&mut self, name: StringId) {
1698 debug_assert_ne!(self.gnu_verdaux_remaining, 0);
1699 self.gnu_verdaux_remaining -= 1;
1700 let vda_next = if self.gnu_verdaux_remaining == 0 {
1701 0
1702 } else {
1703 mem::size_of::<elf::Verdaux<Endianness>>() as u32
1704 };
1705 self.buffer.write(&elf::Verdaux {
1706 vda_name: U32::new(self.endian, self.dynstr.get_offset(name) as u32),
1707 vda_next: U32::new(self.endian, vda_next),
1708 });
1709 }
1710
1711 pub fn reserve_gnu_verdef_section_index(&mut self) -> SectionIndex {
1713 self.reserve_gnu_verdef_section_index_with_name(&b".gnu.version_d"[..])
1714 }
1715
1716 pub fn reserve_gnu_verdef_section_index_with_name(&mut self, name: &'a [u8]) -> SectionIndex {
1718 debug_assert!(self.gnu_verdef_str_id.is_none());
1719 self.gnu_verdef_str_id = Some(self.add_section_name(name));
1720 self.reserve_section_index()
1721 }
1722
1723 pub fn write_gnu_verdef_section_header(&mut self, sh_addr: u64) {
1727 if self.gnu_verdef_str_id.is_none() {
1728 return;
1729 }
1730 self.write_section_header(&SectionHeader {
1731 name: self.gnu_verdef_str_id,
1732 sh_type: elf::SHT_GNU_VERDEF,
1733 sh_flags: elf::SHF_ALLOC.into(),
1734 sh_addr,
1735 sh_offset: self.gnu_verdef_offset as u64,
1736 sh_size: self.gnu_verdef_size as u64,
1737 sh_link: self.dynstr_index.0,
1738 sh_info: self.gnu_verdef_count.into(),
1739 sh_addralign: ALIGN_GNU_VERDEF as u64,
1740 sh_entsize: 0,
1741 });
1742 }
1743
1744 pub fn reserve_gnu_verneed(&mut self, verneed_count: usize, vernaux_count: usize) -> usize {
1746 debug_assert_eq!(self.gnu_verneed_offset, 0);
1747 if verneed_count == 0 {
1748 return 0;
1749 }
1750 self.gnu_verneed_size = self.class().gnu_verneed_size(verneed_count, vernaux_count);
1751 self.gnu_verneed_offset = self.reserve(self.gnu_verneed_size, ALIGN_GNU_VERNEED);
1752 self.gnu_verneed_count = verneed_count as u16;
1753 self.gnu_verneed_remaining = self.gnu_verneed_count;
1754 self.gnu_verneed_offset
1755 }
1756
1757 pub fn write_align_gnu_verneed(&mut self) {
1759 if self.gnu_verneed_offset == 0 {
1760 return;
1761 }
1762 util::write_align(self.buffer, ALIGN_GNU_VERNEED);
1763 debug_assert_eq!(self.gnu_verneed_offset, self.buffer.len());
1764 }
1765
1766 pub fn write_gnu_verneed(&mut self, verneed: &Verneed) {
1768 debug_assert_ne!(self.gnu_verneed_remaining, 0);
1769 self.gnu_verneed_remaining -= 1;
1770 let vn_next = if self.gnu_verneed_remaining == 0 {
1771 0
1772 } else {
1773 mem::size_of::<elf::Verneed<Endianness>>() as u32
1774 + verneed.aux_count as u32 * mem::size_of::<elf::Vernaux<Endianness>>() as u32
1775 };
1776
1777 self.gnu_vernaux_remaining = verneed.aux_count;
1778 let vn_aux = if verneed.aux_count == 0 {
1779 0
1780 } else {
1781 mem::size_of::<elf::Verneed<Endianness>>() as u32
1782 };
1783
1784 self.buffer.write(&elf::Verneed {
1785 vn_version: U16::new(self.endian, verneed.version),
1786 vn_cnt: U16::new(self.endian, verneed.aux_count),
1787 vn_file: U32::new(self.endian, self.dynstr.get_offset(verneed.file) as u32),
1788 vn_aux: U32::new(self.endian, vn_aux),
1789 vn_next: U32::new(self.endian, vn_next),
1790 });
1791 }
1792
1793 pub fn write_gnu_vernaux(&mut self, vernaux: &Vernaux) {
1795 debug_assert_ne!(self.gnu_vernaux_remaining, 0);
1796 self.gnu_vernaux_remaining -= 1;
1797 let vna_next = if self.gnu_vernaux_remaining == 0 {
1798 0
1799 } else {
1800 mem::size_of::<elf::Vernaux<Endianness>>() as u32
1801 };
1802 self.buffer.write(&elf::Vernaux {
1803 vna_hash: U32::new(self.endian, elf::hash(self.dynstr.get_string(vernaux.name))),
1804 vna_flags: U16::new(self.endian, vernaux.flags),
1805 vna_other: U16::new(self.endian, vernaux.index),
1806 vna_name: U32::new(self.endian, self.dynstr.get_offset(vernaux.name) as u32),
1807 vna_next: U32::new(self.endian, vna_next),
1808 });
1809 }
1810
1811 pub fn reserve_gnu_verneed_section_index(&mut self) -> SectionIndex {
1813 self.reserve_gnu_verneed_section_index_with_name(&b".gnu.version_r"[..])
1814 }
1815
1816 pub fn reserve_gnu_verneed_section_index_with_name(&mut self, name: &'a [u8]) -> SectionIndex {
1818 debug_assert!(self.gnu_verneed_str_id.is_none());
1819 self.gnu_verneed_str_id = Some(self.add_section_name(name));
1820 self.reserve_section_index()
1821 }
1822
1823 pub fn write_gnu_verneed_section_header(&mut self, sh_addr: u64) {
1827 if self.gnu_verneed_str_id.is_none() {
1828 return;
1829 }
1830 self.write_section_header(&SectionHeader {
1831 name: self.gnu_verneed_str_id,
1832 sh_type: elf::SHT_GNU_VERNEED,
1833 sh_flags: elf::SHF_ALLOC.into(),
1834 sh_addr,
1835 sh_offset: self.gnu_verneed_offset as u64,
1836 sh_size: self.gnu_verneed_size as u64,
1837 sh_link: self.dynstr_index.0,
1838 sh_info: self.gnu_verneed_count.into(),
1839 sh_addralign: ALIGN_GNU_VERNEED as u64,
1840 sh_entsize: 0,
1841 });
1842 }
1843
1844 pub fn reserve_gnu_attributes_section_index(&mut self) -> SectionIndex {
1846 self.reserve_gnu_attributes_section_index_with_name(&b".gnu.attributes"[..])
1847 }
1848
1849 pub fn reserve_gnu_attributes_section_index_with_name(
1851 &mut self,
1852 name: &'a [u8],
1853 ) -> SectionIndex {
1854 debug_assert!(self.gnu_attributes_str_id.is_none());
1855 self.gnu_attributes_str_id = Some(self.add_section_name(name));
1856 self.reserve_section_index()
1857 }
1858
1859 pub fn reserve_gnu_attributes(&mut self, gnu_attributes_size: usize) -> usize {
1861 debug_assert_eq!(self.gnu_attributes_offset, 0);
1862 if gnu_attributes_size == 0 {
1863 return 0;
1864 }
1865 self.gnu_attributes_size = gnu_attributes_size;
1866 self.gnu_attributes_offset = self.reserve(self.gnu_attributes_size, self.elf_align);
1867 self.gnu_attributes_offset
1868 }
1869
1870 pub fn write_gnu_attributes_section_header(&mut self) {
1874 if self.gnu_attributes_str_id.is_none() {
1875 return;
1876 }
1877 self.write_section_header(&SectionHeader {
1878 name: self.gnu_attributes_str_id,
1879 sh_type: elf::SHT_GNU_ATTRIBUTES,
1880 sh_flags: 0,
1881 sh_addr: 0,
1882 sh_offset: self.gnu_attributes_offset as u64,
1883 sh_size: self.gnu_attributes_size as u64,
1884 sh_link: self.dynstr_index.0,
1885 sh_info: 0, sh_addralign: self.elf_align as u64,
1887 sh_entsize: 0,
1888 });
1889 }
1890
1891 pub fn write_gnu_attributes(&mut self, data: &[u8]) {
1893 if self.gnu_attributes_offset == 0 {
1894 return;
1895 }
1896 util::write_align(self.buffer, self.elf_align);
1897 debug_assert_eq!(self.gnu_attributes_offset, self.buffer.len());
1898 self.buffer.write_bytes(data);
1899 }
1900
1901 pub fn reserve_relocations(&mut self, count: usize, is_rela: bool) -> usize {
1905 self.reserve(count * self.class().rel_size(is_rela), self.elf_align)
1906 }
1907
1908 pub fn write_align_relocation(&mut self) {
1910 util::write_align(self.buffer, self.elf_align);
1911 }
1912
1913 pub fn write_relocation(&mut self, is_rela: bool, rel: &Rel) {
1915 let endian = self.endian;
1916 if self.is_64 {
1917 if is_rela {
1918 let rel = elf::Rela64 {
1919 r_offset: U64::new(endian, rel.r_offset),
1920 r_info: elf::Rela64::r_info(endian, self.is_mips64el, rel.r_sym, rel.r_type),
1921 r_addend: I64::new(endian, rel.r_addend),
1922 };
1923 self.buffer.write(&rel);
1924 } else {
1925 let rel = elf::Rel64 {
1926 r_offset: U64::new(endian, rel.r_offset),
1927 r_info: elf::Rel64::r_info(endian, rel.r_sym, rel.r_type),
1928 };
1929 self.buffer.write(&rel);
1930 }
1931 } else {
1932 if is_rela {
1933 let rel = elf::Rela32 {
1934 r_offset: U32::new(endian, rel.r_offset as u32),
1935 r_info: elf::Rel32::r_info(endian, rel.r_sym, rel.r_type as u8),
1936 r_addend: I32::new(endian, rel.r_addend as i32),
1937 };
1938 self.buffer.write(&rel);
1939 } else {
1940 let rel = elf::Rel32 {
1941 r_offset: U32::new(endian, rel.r_offset as u32),
1942 r_info: elf::Rel32::r_info(endian, rel.r_sym, rel.r_type as u8),
1943 };
1944 self.buffer.write(&rel);
1945 }
1946 }
1947 }
1948
1949 pub fn write_relocation_section_header(
1959 &mut self,
1960 name: StringId,
1961 section: SectionIndex,
1962 symtab: SectionIndex,
1963 offset: usize,
1964 count: usize,
1965 is_rela: bool,
1966 ) {
1967 self.write_section_header(&SectionHeader {
1968 name: Some(name),
1969 sh_type: if is_rela { elf::SHT_RELA } else { elf::SHT_REL },
1970 sh_flags: elf::SHF_INFO_LINK.into(),
1971 sh_addr: 0,
1972 sh_offset: offset as u64,
1973 sh_size: (count * self.class().rel_size(is_rela)) as u64,
1974 sh_link: symtab.0,
1975 sh_info: section.0,
1976 sh_addralign: self.elf_align as u64,
1977 sh_entsize: self.class().rel_size(is_rela) as u64,
1978 });
1979 }
1980
1981 pub fn write_relative_relocation_section_header(
1986 &mut self,
1987 name: StringId,
1988 offset: usize,
1989 size: usize,
1990 ) {
1991 self.write_section_header(&SectionHeader {
1992 name: Some(name),
1993 sh_type: elf::SHT_RELA,
1994 sh_flags: 0,
1995 sh_addr: 0,
1996 sh_offset: offset as u64,
1997 sh_size: size as u64,
1998 sh_link: 0,
1999 sh_info: 0,
2000 sh_addralign: self.elf_align as u64,
2001 sh_entsize: self.class().relr_size() as u64,
2002 });
2003 }
2004
2005 pub fn reserve_comdat(&mut self, count: usize) -> usize {
2011 self.reserve((count + 1) * 4, 4)
2012 }
2013
2014 pub fn write_comdat_header(&mut self) {
2016 util::write_align(self.buffer, 4);
2017 self.buffer.write(&U32::new(self.endian, elf::GRP_COMDAT));
2018 }
2019
2020 pub fn write_comdat_entry(&mut self, entry: SectionIndex) {
2022 self.buffer.write(&U32::new(self.endian, entry.0));
2023 }
2024
2025 pub fn write_comdat_section_header(
2027 &mut self,
2028 name: StringId,
2029 symtab: SectionIndex,
2030 symbol: SymbolIndex,
2031 offset: usize,
2032 count: usize,
2033 ) {
2034 self.write_section_header(&SectionHeader {
2035 name: Some(name),
2036 sh_type: elf::SHT_GROUP,
2037 sh_flags: 0,
2038 sh_addr: 0,
2039 sh_offset: offset as u64,
2040 sh_size: ((count + 1) * 4) as u64,
2041 sh_link: symtab.0,
2042 sh_info: symbol.0,
2043 sh_addralign: 4,
2044 sh_entsize: 4,
2045 });
2046 }
2047
2048 pub fn attributes_writer(&self) -> AttributesWriter {
2050 AttributesWriter::new(self.endian)
2051 }
2052}
2053
2054#[allow(missing_debug_implementations)]
2060pub struct AttributesWriter {
2061 endian: Endianness,
2062 data: Vec<u8>,
2063 subsection_offset: usize,
2064 subsubsection_offset: usize,
2065}
2066
2067impl AttributesWriter {
2068 pub fn new(endian: Endianness) -> Self {
2070 AttributesWriter {
2071 endian,
2072 data: vec![0x41],
2073 subsection_offset: 0,
2074 subsubsection_offset: 0,
2075 }
2076 }
2077
2078 pub fn start_subsection(&mut self, vendor: &[u8]) {
2080 debug_assert_eq!(self.subsection_offset, 0);
2081 debug_assert_eq!(self.subsubsection_offset, 0);
2082 self.subsection_offset = self.data.len();
2083 self.data.extend_from_slice(&[0; 4]);
2084 self.data.extend_from_slice(vendor);
2085 self.data.push(0);
2086 }
2087
2088 pub fn end_subsection(&mut self) {
2092 debug_assert_ne!(self.subsection_offset, 0);
2093 debug_assert_eq!(self.subsubsection_offset, 0);
2094 let length = self.data.len() - self.subsection_offset;
2095 self.data[self.subsection_offset..][..4]
2096 .copy_from_slice(pod::bytes_of(&U32::new(self.endian, length as u32)));
2097 self.subsection_offset = 0;
2098 }
2099
2100 pub fn start_subsubsection(&mut self, tag: u8) {
2102 debug_assert_ne!(self.subsection_offset, 0);
2103 debug_assert_eq!(self.subsubsection_offset, 0);
2104 self.subsubsection_offset = self.data.len();
2105 self.data.push(tag);
2106 self.data.extend_from_slice(&[0; 4]);
2107 }
2108
2109 pub fn write_subsubsection_index(&mut self, index: u32) {
2113 debug_assert_ne!(self.subsection_offset, 0);
2114 debug_assert_ne!(self.subsubsection_offset, 0);
2115 util::write_uleb128(&mut self.data, u64::from(index));
2116 }
2117
2118 pub fn write_subsubsection_indices(&mut self, indices: &[u8]) {
2122 debug_assert_ne!(self.subsection_offset, 0);
2123 debug_assert_ne!(self.subsubsection_offset, 0);
2124 self.data.extend_from_slice(indices);
2125 self.data.push(0);
2126 }
2127
2128 pub fn write_attribute_tag(&mut self, tag: u64) {
2130 debug_assert_ne!(self.subsection_offset, 0);
2131 debug_assert_ne!(self.subsubsection_offset, 0);
2132 util::write_uleb128(&mut self.data, tag);
2133 }
2134
2135 pub fn write_attribute_integer(&mut self, value: u64) {
2137 debug_assert_ne!(self.subsection_offset, 0);
2138 debug_assert_ne!(self.subsubsection_offset, 0);
2139 util::write_uleb128(&mut self.data, value);
2140 }
2141
2142 pub fn write_attribute_string(&mut self, value: &[u8]) {
2146 debug_assert_ne!(self.subsection_offset, 0);
2147 debug_assert_ne!(self.subsubsection_offset, 0);
2148 self.data.extend_from_slice(value);
2149 self.data.push(0);
2150 }
2151
2152 pub fn write_subsubsection_attributes(&mut self, attributes: &[u8]) {
2154 debug_assert_ne!(self.subsection_offset, 0);
2155 debug_assert_ne!(self.subsubsection_offset, 0);
2156 self.data.extend_from_slice(attributes);
2157 }
2158
2159 pub fn end_subsubsection(&mut self) {
2163 debug_assert_ne!(self.subsection_offset, 0);
2164 debug_assert_ne!(self.subsubsection_offset, 0);
2165 let length = self.data.len() - self.subsubsection_offset;
2166 self.data[self.subsubsection_offset + 1..][..4]
2167 .copy_from_slice(pod::bytes_of(&U32::new(self.endian, length as u32)));
2168 self.subsubsection_offset = 0;
2169 }
2170
2171 pub fn data(self) -> Vec<u8> {
2173 debug_assert_eq!(self.subsection_offset, 0);
2174 debug_assert_eq!(self.subsubsection_offset, 0);
2175 self.data
2176 }
2177}
2178
2179#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
2181pub struct Class {
2182 pub is_64: bool,
2184}
2185
2186impl Class {
2187 pub fn align(self) -> usize {
2189 if self.is_64 {
2190 8
2191 } else {
2192 4
2193 }
2194 }
2195
2196 pub fn file_header_size(self) -> usize {
2198 if self.is_64 {
2199 mem::size_of::<elf::FileHeader64<Endianness>>()
2200 } else {
2201 mem::size_of::<elf::FileHeader32<Endianness>>()
2202 }
2203 }
2204
2205 pub fn program_header_size(self) -> usize {
2207 if self.is_64 {
2208 mem::size_of::<elf::ProgramHeader64<Endianness>>()
2209 } else {
2210 mem::size_of::<elf::ProgramHeader32<Endianness>>()
2211 }
2212 }
2213
2214 pub fn section_header_size(self) -> usize {
2216 if self.is_64 {
2217 mem::size_of::<elf::SectionHeader64<Endianness>>()
2218 } else {
2219 mem::size_of::<elf::SectionHeader32<Endianness>>()
2220 }
2221 }
2222
2223 pub fn sym_size(self) -> usize {
2225 if self.is_64 {
2226 mem::size_of::<elf::Sym64<Endianness>>()
2227 } else {
2228 mem::size_of::<elf::Sym32<Endianness>>()
2229 }
2230 }
2231
2232 pub fn rel_size(self, is_rela: bool) -> usize {
2234 if self.is_64 {
2235 if is_rela {
2236 mem::size_of::<elf::Rela64<Endianness>>()
2237 } else {
2238 mem::size_of::<elf::Rel64<Endianness>>()
2239 }
2240 } else {
2241 if is_rela {
2242 mem::size_of::<elf::Rela32<Endianness>>()
2243 } else {
2244 mem::size_of::<elf::Rel32<Endianness>>()
2245 }
2246 }
2247 }
2248
2249 pub fn relr_size(self) -> usize {
2251 if self.is_64 {
2252 mem::size_of::<elf::Relr64<Endianness>>()
2253 } else {
2254 mem::size_of::<elf::Relr32<Endianness>>()
2255 }
2256 }
2257
2258 pub fn dyn_size(self) -> usize {
2260 if self.is_64 {
2261 mem::size_of::<elf::Dyn64<Endianness>>()
2262 } else {
2263 mem::size_of::<elf::Dyn32<Endianness>>()
2264 }
2265 }
2266
2267 pub fn hash_size(self, bucket_count: u32, chain_count: u32) -> usize {
2269 mem::size_of::<elf::HashHeader<Endianness>>()
2270 + bucket_count as usize * 4
2271 + chain_count as usize * 4
2272 }
2273
2274 pub fn gnu_hash_size(self, bloom_count: u32, bucket_count: u32, symbol_count: u32) -> usize {
2276 let bloom_size = if self.is_64 { 8 } else { 4 };
2277 mem::size_of::<elf::GnuHashHeader<Endianness>>()
2278 + bloom_count as usize * bloom_size
2279 + bucket_count as usize * 4
2280 + symbol_count as usize * 4
2281 }
2282
2283 pub fn gnu_versym_size(self, symbol_count: usize) -> usize {
2285 symbol_count * 2
2286 }
2287
2288 pub fn gnu_verdef_size(self, verdef_count: usize, verdaux_count: usize) -> usize {
2290 verdef_count * mem::size_of::<elf::Verdef<Endianness>>()
2291 + verdaux_count * mem::size_of::<elf::Verdaux<Endianness>>()
2292 }
2293
2294 pub fn gnu_verneed_size(self, verneed_count: usize, vernaux_count: usize) -> usize {
2296 verneed_count * mem::size_of::<elf::Verneed<Endianness>>()
2297 + vernaux_count * mem::size_of::<elf::Vernaux<Endianness>>()
2298 }
2299}
2300
2301#[allow(missing_docs)]
2303#[derive(Debug, Clone)]
2304pub struct FileHeader {
2305 pub os_abi: u8,
2306 pub abi_version: u8,
2307 pub e_type: u16,
2308 pub e_machine: u16,
2309 pub e_entry: u64,
2310 pub e_flags: u32,
2311}
2312
2313#[allow(missing_docs)]
2315#[derive(Debug, Clone)]
2316pub struct ProgramHeader {
2317 pub p_type: u32,
2318 pub p_flags: u32,
2319 pub p_offset: u64,
2320 pub p_vaddr: u64,
2321 pub p_paddr: u64,
2322 pub p_filesz: u64,
2323 pub p_memsz: u64,
2324 pub p_align: u64,
2325}
2326
2327#[allow(missing_docs)]
2329#[derive(Debug, Clone)]
2330pub struct SectionHeader {
2331 pub name: Option<StringId>,
2332 pub sh_type: u32,
2333 pub sh_flags: u64,
2334 pub sh_addr: u64,
2335 pub sh_offset: u64,
2336 pub sh_size: u64,
2337 pub sh_link: u32,
2338 pub sh_info: u32,
2339 pub sh_addralign: u64,
2340 pub sh_entsize: u64,
2341}
2342
2343#[allow(missing_docs)]
2345#[derive(Debug, Clone)]
2346pub struct Sym {
2347 pub name: Option<StringId>,
2348 pub section: Option<SectionIndex>,
2349 pub st_info: u8,
2350 pub st_other: u8,
2351 pub st_shndx: u16,
2352 pub st_value: u64,
2353 pub st_size: u64,
2354}
2355
2356#[allow(missing_docs)]
2358#[derive(Debug, Clone)]
2359pub struct Rel {
2360 pub r_offset: u64,
2361 pub r_sym: u32,
2362 pub r_type: u32,
2363 pub r_addend: i64,
2364}
2365
2366#[allow(missing_docs)]
2368#[derive(Debug, Clone)]
2369pub struct Verdef {
2370 pub version: u16,
2371 pub flags: u16,
2372 pub index: u16,
2373 pub aux_count: u16,
2374 pub name: StringId,
2376}
2377
2378#[allow(missing_docs)]
2380#[derive(Debug, Clone)]
2381pub struct Verneed {
2382 pub version: u16,
2383 pub aux_count: u16,
2384 pub file: StringId,
2385}
2386
2387#[allow(missing_docs)]
2389#[derive(Debug, Clone)]
2390pub struct Vernaux {
2391 pub flags: u16,
2392 pub index: u16,
2393 pub name: StringId,
2394}