1 //! Helper for writing ELF files.
2 use alloc
::string
::String
;
8 use crate::write
::string
::{StringId, StringTable}
;
9 use crate::write
::util
;
10 use crate::write
::{Error, Result, WritableBuffer}
;
12 /// The index of an ELF section.
13 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
14 pub struct SectionIndex(pub u32);
16 /// The index of an ELF symbol.
17 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
18 pub struct SymbolIndex(pub u32);
20 /// A helper for writing ELF files.
22 /// Writing uses a two phase approach. The first phase builds up all of the information
23 /// that may need to be known ahead of time:
24 /// - build string tables
25 /// - reserve section indices
26 /// - reserve symbol indices
27 /// - reserve file ranges for headers and sections
29 /// Some of the information has ordering requirements. For example, strings must be added
30 /// to string tables before reserving the file range for the string table. Symbol indices
31 /// must be reserved after reserving the section indices they reference. There are debug
32 /// asserts to check some of these requirements.
34 /// The second phase writes everything out in order. Thus the caller must ensure writing
35 /// is in the same order that file ranges were reserved. There are debug asserts to assist
36 /// with checking this.
37 #[allow(missing_debug_implementations)]
38 pub struct Writer
<'a
> {
44 buffer
: &'a
mut dyn WritableBuffer
,
47 segment_offset
: usize,
50 section_offset
: usize,
53 shstrtab
: StringTable
<'a
>,
54 shstrtab_str_id
: Option
<StringId
>,
55 shstrtab_index
: SectionIndex
,
56 shstrtab_offset
: usize,
57 shstrtab_data
: Vec
<u8>,
60 strtab
: StringTable
<'a
>,
61 strtab_str_id
: Option
<StringId
>,
62 strtab_index
: SectionIndex
,
66 symtab_str_id
: Option
<StringId
>,
67 symtab_index
: SectionIndex
,
71 need_symtab_shndx
: bool
,
72 symtab_shndx_str_id
: Option
<StringId
>,
73 symtab_shndx_offset
: usize,
74 symtab_shndx_data
: Vec
<u8>,
77 dynstr
: StringTable
<'a
>,
78 dynstr_str_id
: Option
<StringId
>,
79 dynstr_index
: SectionIndex
,
83 dynsym_str_id
: Option
<StringId
>,
84 dynsym_index
: SectionIndex
,
88 dynamic_str_id
: Option
<StringId
>,
89 dynamic_offset
: usize,
92 hash_str_id
: Option
<StringId
>,
96 gnu_hash_str_id
: Option
<StringId
>,
97 gnu_hash_offset
: usize,
100 gnu_versym_str_id
: Option
<StringId
>,
101 gnu_versym_offset
: usize,
103 gnu_verdef_str_id
: Option
<StringId
>,
104 gnu_verdef_offset
: usize,
105 gnu_verdef_size
: usize,
106 gnu_verdef_count
: u16,
107 gnu_verdef_remaining
: u16,
108 gnu_verdaux_remaining
: u16,
110 gnu_verneed_str_id
: Option
<StringId
>,
111 gnu_verneed_offset
: usize,
112 gnu_verneed_size
: usize,
113 gnu_verneed_count
: u16,
114 gnu_verneed_remaining
: u16,
115 gnu_vernaux_remaining
: u16,
118 impl<'a
> Writer
<'a
> {
119 /// Create a new `Writer` for the given endianness and ELF class.
120 pub fn new(endian
: Endianness
, is_64
: bool
, buffer
: &'a
mut dyn WritableBuffer
) -> Self {
121 let elf_align
= if is_64 { 8 }
else { 4 }
;
138 shstrtab
: StringTable
::default(),
139 shstrtab_str_id
: None
,
140 shstrtab_index
: SectionIndex(0),
142 shstrtab_data
: Vec
::new(),
145 strtab
: StringTable
::default(),
147 strtab_index
: SectionIndex(0),
149 strtab_data
: Vec
::new(),
152 symtab_index
: SectionIndex(0),
156 need_symtab_shndx
: false,
157 symtab_shndx_str_id
: None
,
158 symtab_shndx_offset
: 0,
159 symtab_shndx_data
: Vec
::new(),
162 dynstr
: StringTable
::default(),
164 dynstr_index
: SectionIndex(0),
166 dynstr_data
: Vec
::new(),
169 dynsym_index
: SectionIndex(0),
173 dynamic_str_id
: None
,
181 gnu_hash_str_id
: None
,
185 gnu_versym_str_id
: None
,
186 gnu_versym_offset
: 0,
188 gnu_verdef_str_id
: None
,
189 gnu_verdef_offset
: 0,
192 gnu_verdef_remaining
: 0,
193 gnu_verdaux_remaining
: 0,
195 gnu_verneed_str_id
: None
,
196 gnu_verneed_offset
: 0,
198 gnu_verneed_count
: 0,
199 gnu_verneed_remaining
: 0,
200 gnu_vernaux_remaining
: 0,
204 /// Return the current file length that has been reserved.
205 pub fn reserved_len(&self) -> usize {
209 /// Return the current file length that has been written.
210 #[allow(clippy::len_without_is_empty)]
211 pub fn len(&self) -> usize {
215 /// Reserve a file range with the given size and starting alignment.
217 /// Returns the aligned offset of the start of the range.
218 pub fn reserve(&mut self, len
: usize, align_start
: usize) -> usize {
222 self.len
= util
::align(self.len
, align_start
);
223 let offset
= self.len
;
228 /// Write alignment padding bytes.
229 pub fn write_align(&mut self, align_start
: usize) {
230 util
::write_align(self.buffer
, align_start
);
235 /// This is typically used to write section data.
236 pub fn write(&mut self, data
: &[u8]) {
237 self.buffer
.write_bytes(data
);
240 /// Reserve the file range up to the given file offset.
241 pub fn reserve_until(&mut self, offset
: usize) {
242 debug_assert
!(self.len
<= offset
);
246 /// Write padding up to the given file offset.
247 pub fn pad_until(&mut self, offset
: usize) {
248 debug_assert
!(self.buffer
.len() <= offset
);
249 self.buffer
.resize(offset
);
252 fn file_header_size(&self) -> usize {
254 mem
::size_of
::<elf
::FileHeader64
<Endianness
>>()
256 mem
::size_of
::<elf
::FileHeader32
<Endianness
>>()
260 /// Reserve the range for the file header.
262 /// This must be at the start of the file.
263 pub fn reserve_file_header(&mut self) {
264 debug_assert_eq
!(self.len
, 0);
265 self.reserve(self.file_header_size(), 1);
268 /// Write the file header.
270 /// This must be at the start of the file.
272 /// Fields that can be derived from known information are automatically set by this function.
273 pub fn write_file_header(&mut self, header
: &FileHeader
) -> Result
<()> {
274 debug_assert_eq
!(self.buffer
.len(), 0);
277 self.is_64
&& self.endian
.is_little_endian() && header
.e_machine
== elf
::EM_MIPS
;
282 .map_err(|_
| Error(String
::from("Cannot allocate buffer")))?
;
284 // Write file header.
285 let e_ident
= elf
::Ident
{
287 class
: if self.is_64
{
292 data
: if self.endian
.is_little_endian() {
297 version
: elf
::EV_CURRENT
,
298 os_abi
: header
.os_abi
,
299 abi_version
: header
.abi_version
,
303 let e_ehsize
= self.file_header_size() as u16;
305 let e_phoff
= self.segment_offset
as u64;
306 let e_phentsize
= if self.segment_num
== 0 {
309 self.program_header_size() as u16
312 let e_phnum
= self.segment_num
as u16;
314 let e_shoff
= self.section_offset
as u64;
315 let e_shentsize
= if self.section_num
== 0 {
318 self.section_header_size() as u16
320 let e_shnum
= if self.section_num
>= elf
::SHN_LORESERVE
.into() {
323 self.section_num
as u16
325 let e_shstrndx
= if self.shstrtab_index
.0 >= elf
::SHN_LORESERVE
.into() {
328 self.shstrtab_index
.0 as u16
331 let endian
= self.endian
;
333 let file
= elf
::FileHeader64
{
335 e_type
: U16
::new(endian
, header
.e_type
),
336 e_machine
: U16
::new(endian
, header
.e_machine
),
337 e_version
: U32
::new(endian
, elf
::EV_CURRENT
.into()),
338 e_entry
: U64
::new(endian
, header
.e_entry
),
339 e_phoff
: U64
::new(endian
, e_phoff
),
340 e_shoff
: U64
::new(endian
, e_shoff
),
341 e_flags
: U32
::new(endian
, header
.e_flags
),
342 e_ehsize
: U16
::new(endian
, e_ehsize
),
343 e_phentsize
: U16
::new(endian
, e_phentsize
),
344 e_phnum
: U16
::new(endian
, e_phnum
),
345 e_shentsize
: U16
::new(endian
, e_shentsize
),
346 e_shnum
: U16
::new(endian
, e_shnum
),
347 e_shstrndx
: U16
::new(endian
, e_shstrndx
),
349 self.buffer
.write(&file
)
351 let file
= elf
::FileHeader32
{
353 e_type
: U16
::new(endian
, header
.e_type
),
354 e_machine
: U16
::new(endian
, header
.e_machine
),
355 e_version
: U32
::new(endian
, elf
::EV_CURRENT
.into()),
356 e_entry
: U32
::new(endian
, header
.e_entry
as u32),
357 e_phoff
: U32
::new(endian
, e_phoff
as u32),
358 e_shoff
: U32
::new(endian
, e_shoff
as u32),
359 e_flags
: U32
::new(endian
, header
.e_flags
),
360 e_ehsize
: U16
::new(endian
, e_ehsize
),
361 e_phentsize
: U16
::new(endian
, e_phentsize
),
362 e_phnum
: U16
::new(endian
, e_phnum
),
363 e_shentsize
: U16
::new(endian
, e_shentsize
),
364 e_shnum
: U16
::new(endian
, e_shnum
),
365 e_shstrndx
: U16
::new(endian
, e_shstrndx
),
367 self.buffer
.write(&file
);
373 fn program_header_size(&self) -> usize {
375 mem
::size_of
::<elf
::ProgramHeader64
<Endianness
>>()
377 mem
::size_of
::<elf
::ProgramHeader32
<Endianness
>>()
381 /// Reserve the range for the program headers.
382 pub fn reserve_program_headers(&mut self, num
: u32) {
383 debug_assert_eq
!(self.segment_offset
, 0);
387 self.segment_num
= num
;
388 self.segment_offset
=
389 self.reserve(num
as usize * self.program_header_size(), self.elf_align
);
392 /// Write alignment padding bytes prior to the program headers.
393 pub fn write_align_program_headers(&mut self) {
394 if self.segment_offset
== 0 {
397 util
::write_align(self.buffer
, self.elf_align
);
398 debug_assert_eq
!(self.segment_offset
, self.buffer
.len());
401 /// Write a program header.
402 pub fn write_program_header(&mut self, header
: &ProgramHeader
) {
403 let endian
= self.endian
;
405 let header
= elf
::ProgramHeader64
{
406 p_type
: U32
::new(endian
, header
.p_type
),
407 p_flags
: U32
::new(endian
, header
.p_flags
),
408 p_offset
: U64
::new(endian
, header
.p_offset
),
409 p_vaddr
: U64
::new(endian
, header
.p_vaddr
),
410 p_paddr
: U64
::new(endian
, header
.p_paddr
),
411 p_filesz
: U64
::new(endian
, header
.p_filesz
),
412 p_memsz
: U64
::new(endian
, header
.p_memsz
),
413 p_align
: U64
::new(endian
, header
.p_align
),
415 self.buffer
.write(&header
);
417 let header
= elf
::ProgramHeader32
{
418 p_type
: U32
::new(endian
, header
.p_type
),
419 p_offset
: U32
::new(endian
, header
.p_offset
as u32),
420 p_vaddr
: U32
::new(endian
, header
.p_vaddr
as u32),
421 p_paddr
: U32
::new(endian
, header
.p_paddr
as u32),
422 p_filesz
: U32
::new(endian
, header
.p_filesz
as u32),
423 p_memsz
: U32
::new(endian
, header
.p_memsz
as u32),
424 p_flags
: U32
::new(endian
, header
.p_flags
),
425 p_align
: U32
::new(endian
, header
.p_align
as u32),
427 self.buffer
.write(&header
);
431 /// Reserve the section index for the null section header.
433 /// The null section header is usually automatically reserved,
434 /// but this can be used to force an empty section table.
436 /// This must be called before [`Self::reserve_section_headers`].
437 pub fn reserve_null_section_index(&mut self) -> SectionIndex
{
438 debug_assert_eq
!(self.section_num
, 0);
439 if self.section_num
== 0 {
440 self.section_num
= 1;
445 /// Reserve a section table index.
447 /// Automatically also reserves the null section header if required.
449 /// This must be called before [`Self::reserve_section_headers`].
450 pub fn reserve_section_index(&mut self) -> SectionIndex
{
451 debug_assert_eq
!(self.section_offset
, 0);
452 if self.section_num
== 0 {
453 self.section_num
= 1;
455 let index
= self.section_num
;
456 self.section_num
+= 1;
460 fn section_header_size(&self) -> usize {
462 mem
::size_of
::<elf
::SectionHeader64
<Endianness
>>()
464 mem
::size_of
::<elf
::SectionHeader32
<Endianness
>>()
468 /// Reserve the range for the section headers.
470 /// This function does nothing if no sections were reserved.
471 /// This must be called after [`Self::reserve_section_index`]
472 /// and other functions that reserve section indices.
473 pub fn reserve_section_headers(&mut self) {
474 debug_assert_eq
!(self.section_offset
, 0);
475 if self.section_num
== 0 {
478 self.section_offset
= self.reserve(
479 self.section_num
as usize * self.section_header_size(),
484 /// Write the null section header.
486 /// This must be the first section header that is written.
487 /// This function does nothing if no sections were reserved.
488 pub fn write_null_section_header(&mut self) {
489 if self.section_num
== 0 {
492 util
::write_align(self.buffer
, self.elf_align
);
493 debug_assert_eq
!(self.section_offset
, self.buffer
.len());
494 self.write_section_header(&SectionHeader
{
500 sh_size
: if self.section_num
>= elf
::SHN_LORESERVE
.into() {
501 self.section_num
.into()
505 sh_link
: if self.shstrtab_index
.0 >= elf
::SHN_LORESERVE
.into() {
506 self.shstrtab_index
.0
510 // TODO: e_phnum overflow
517 /// Write a section header.
518 pub fn write_section_header(&mut self, section
: &SectionHeader
) {
519 let sh_name
= if let Some(name
) = section
.name
{
520 self.shstrtab
.get_offset(name
) as u32
524 let endian
= self.endian
;
526 let section
= elf
::SectionHeader64
{
527 sh_name
: U32
::new(endian
, sh_name
),
528 sh_type
: U32
::new(endian
, section
.sh_type
),
529 sh_flags
: U64
::new(endian
, section
.sh_flags
),
530 sh_addr
: U64
::new(endian
, section
.sh_addr
),
531 sh_offset
: U64
::new(endian
, section
.sh_offset
),
532 sh_size
: U64
::new(endian
, section
.sh_size
),
533 sh_link
: U32
::new(endian
, section
.sh_link
),
534 sh_info
: U32
::new(endian
, section
.sh_info
),
535 sh_addralign
: U64
::new(endian
, section
.sh_addralign
),
536 sh_entsize
: U64
::new(endian
, section
.sh_entsize
),
538 self.buffer
.write(§ion
);
540 let section
= elf
::SectionHeader32
{
541 sh_name
: U32
::new(endian
, sh_name
),
542 sh_type
: U32
::new(endian
, section
.sh_type
),
543 sh_flags
: U32
::new(endian
, section
.sh_flags
as u32),
544 sh_addr
: U32
::new(endian
, section
.sh_addr
as u32),
545 sh_offset
: U32
::new(endian
, section
.sh_offset
as u32),
546 sh_size
: U32
::new(endian
, section
.sh_size
as u32),
547 sh_link
: U32
::new(endian
, section
.sh_link
),
548 sh_info
: U32
::new(endian
, section
.sh_info
),
549 sh_addralign
: U32
::new(endian
, section
.sh_addralign
as u32),
550 sh_entsize
: U32
::new(endian
, section
.sh_entsize
as u32),
552 self.buffer
.write(§ion
);
556 /// Add a section name to the section header string table.
558 /// This will be stored in the `.shstrtab` section.
560 /// This must be called before [`Self::reserve_shstrtab`].
561 pub fn add_section_name(&mut self, name
: &'a
[u8]) -> StringId
{
562 debug_assert_eq
!(self.shstrtab_offset
, 0);
563 self.shstrtab
.add(name
)
566 /// Reserve the range for the section header string table.
568 /// This range is used for a section named `.shstrtab`.
570 /// This function does nothing if no sections were reserved.
571 /// This must be called after [`Self::add_section_name`].
572 /// and other functions that reserve section names and indices.
573 pub fn reserve_shstrtab(&mut self) {
574 debug_assert_eq
!(self.shstrtab_offset
, 0);
575 if self.section_num
== 0 {
578 // Start with null section name.
579 self.shstrtab_data
= vec
![0];
580 self.shstrtab
.write(1, &mut self.shstrtab_data
);
581 self.shstrtab_offset
= self.reserve(self.shstrtab_data
.len(), 1);
584 /// Write the section header string table.
586 /// This function does nothing if the section was not reserved.
587 pub fn write_shstrtab(&mut self) {
588 if self.shstrtab_offset
== 0 {
591 debug_assert_eq
!(self.shstrtab_offset
, self.buffer
.len());
592 self.buffer
.write_bytes(&self.shstrtab_data
);
595 /// Reserve the section index for the section header string table.
597 /// This must be called before [`Self::reserve_shstrtab`]
598 /// and [`Self::reserve_section_headers`].
599 pub fn reserve_shstrtab_section_index(&mut self) -> SectionIndex
{
600 debug_assert_eq
!(self.shstrtab_index
, SectionIndex(0));
601 self.shstrtab_str_id
= Some(self.add_section_name(&b
".shstrtab"[..]));
602 self.shstrtab_index
= self.reserve_section_index();
606 /// Write the section header for the section header string table.
608 /// This function does nothing if the section index was not reserved.
609 pub fn write_shstrtab_section_header(&mut self) {
610 if self.shstrtab_index
== SectionIndex(0) {
613 self.write_section_header(&SectionHeader
{
614 name
: self.shstrtab_str_id
,
615 sh_type
: elf
::SHT_STRTAB
,
618 sh_offset
: self.shstrtab_offset
as u64,
619 sh_size
: self.shstrtab_data
.len() as u64,
627 /// Add a string to the string table.
629 /// This will be stored in the `.strtab` section.
631 /// This must be called before [`Self::reserve_strtab`].
632 pub fn add_string(&mut self, name
: &'a
[u8]) -> StringId
{
633 debug_assert_eq
!(self.strtab_offset
, 0);
634 self.need_strtab
= true;
635 self.strtab
.add(name
)
638 /// Return true if `.strtab` is needed.
639 pub fn strtab_needed(&self) -> bool
{
643 /// Reserve the range for the string table.
645 /// This range is used for a section named `.strtab`.
647 /// This function does nothing if no strings or symbols were defined.
648 /// This must be called after [`Self::add_string`].
649 pub fn reserve_strtab(&mut self) {
650 debug_assert_eq
!(self.strtab_offset
, 0);
651 if !self.need_strtab
{
654 // Start with null string.
655 self.strtab_data
= vec
![0];
656 self.strtab
.write(1, &mut self.strtab_data
);
657 self.strtab_offset
= self.reserve(self.strtab_data
.len(), 1);
660 /// Write the string table.
662 /// This function does nothing if the section was not reserved.
663 pub fn write_strtab(&mut self) {
664 if self.strtab_offset
== 0 {
667 debug_assert_eq
!(self.strtab_offset
, self.buffer
.len());
668 self.buffer
.write_bytes(&self.strtab_data
);
671 /// Reserve the section index for the string table.
673 /// This must be called before [`Self::reserve_section_headers`].
674 pub fn reserve_strtab_section_index(&mut self) -> SectionIndex
{
675 debug_assert_eq
!(self.strtab_index
, SectionIndex(0));
676 self.strtab_str_id
= Some(self.add_section_name(&b
".strtab"[..]));
677 self.strtab_index
= self.reserve_section_index();
681 /// Write the section header for the string table.
683 /// This function does nothing if the section index was not reserved.
684 pub fn write_strtab_section_header(&mut self) {
685 if self.strtab_index
== SectionIndex(0) {
688 self.write_section_header(&SectionHeader
{
689 name
: self.strtab_str_id
,
690 sh_type
: elf
::SHT_STRTAB
,
693 sh_offset
: self.strtab_offset
as u64,
694 sh_size
: self.strtab_data
.len() as u64,
702 /// Reserve the null symbol table entry.
704 /// This will be stored in the `.symtab` section.
706 /// The null symbol table entry is usually automatically reserved,
707 /// but this can be used to force an empty symbol table.
709 /// This must be called before [`Self::reserve_symtab`].
710 pub fn reserve_null_symbol_index(&mut self) -> SymbolIndex
{
711 debug_assert_eq
!(self.symtab_offset
, 0);
712 debug_assert_eq
!(self.symtab_num
, 0);
714 // The symtab must link to a strtab.
715 self.need_strtab
= true;
719 /// Reserve a symbol table entry.
721 /// This will be stored in the `.symtab` section.
723 /// `section_index` is used to determine whether `.symtab_shndx` is required.
725 /// Automatically also reserves the null symbol if required.
726 /// Callers may assume that the returned indices will be sequential
729 /// This must be called before [`Self::reserve_symtab`] and
730 /// [`Self::reserve_symtab_shndx`].
731 pub fn reserve_symbol_index(&mut self, section_index
: Option
<SectionIndex
>) -> SymbolIndex
{
732 debug_assert_eq
!(self.symtab_offset
, 0);
733 debug_assert_eq
!(self.symtab_shndx_offset
, 0);
734 if self.symtab_num
== 0 {
736 // The symtab must link to a strtab.
737 self.need_strtab
= true;
739 let index
= self.symtab_num
;
740 self.symtab_num
+= 1;
741 if let Some(section_index
) = section_index
{
742 if section_index
.0 >= elf
::SHN_LORESERVE
.into() {
743 self.need_symtab_shndx
= true;
749 /// Return the number of reserved symbol table entries.
751 /// Includes the null symbol.
752 pub fn symbol_count(&self) -> u32 {
756 fn symbol_size(&self) -> usize {
758 mem
::size_of
::<elf
::Sym64
<Endianness
>>()
760 mem
::size_of
::<elf
::Sym32
<Endianness
>>()
764 /// Reserve the range for the symbol table.
766 /// This range is used for a section named `.symtab`.
767 /// This function does nothing if no symbols were reserved.
768 /// This must be called after [`Self::reserve_symbol_index`].
769 pub fn reserve_symtab(&mut self) {
770 debug_assert_eq
!(self.symtab_offset
, 0);
771 if self.symtab_num
== 0 {
774 self.symtab_offset
= self.reserve(
775 self.symtab_num
as usize * self.symbol_size(),
780 /// Write the null symbol.
782 /// This must be the first symbol that is written.
783 /// This function does nothing if no symbols were reserved.
784 pub fn write_null_symbol(&mut self) {
785 if self.symtab_num
== 0 {
788 util
::write_align(self.buffer
, self.elf_align
);
789 debug_assert_eq
!(self.symtab_offset
, self.buffer
.len());
791 self.buffer
.write(&elf
::Sym64
::<Endianness
>::default());
793 self.buffer
.write(&elf
::Sym32
::<Endianness
>::default());
796 if self.need_symtab_shndx
{
797 self.symtab_shndx_data
.write_pod(&U32
::new(self.endian
, 0));
802 pub fn write_symbol(&mut self, sym
: &Sym
) {
803 let st_name
= if let Some(name
) = sym
.name
{
804 self.strtab
.get_offset(name
) as u32
808 let st_shndx
= if let Some(section
) = sym
.section
{
809 if section
.0 >= elf
::SHN_LORESERVE
as u32 {
818 let endian
= self.endian
;
820 let sym
= elf
::Sym64
{
821 st_name
: U32
::new(endian
, st_name
),
822 st_info
: sym
.st_info
,
823 st_other
: sym
.st_other
,
824 st_shndx
: U16
::new(endian
, st_shndx
),
825 st_value
: U64
::new(endian
, sym
.st_value
),
826 st_size
: U64
::new(endian
, sym
.st_size
),
828 self.buffer
.write(&sym
);
830 let sym
= elf
::Sym32
{
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
: U32
::new(endian
, sym
.st_value
as u32),
836 st_size
: U32
::new(endian
, sym
.st_size
as u32),
838 self.buffer
.write(&sym
);
841 if self.need_symtab_shndx
{
842 let section_index
= sym
.section
.unwrap_or(SectionIndex(0));
843 self.symtab_shndx_data
844 .write_pod(&U32
::new(self.endian
, section_index
.0));
848 /// Reserve the section index for the symbol table.
850 /// This must be called before [`Self::reserve_section_headers`].
851 pub fn reserve_symtab_section_index(&mut self) -> SectionIndex
{
852 debug_assert_eq
!(self.symtab_index
, SectionIndex(0));
853 self.symtab_str_id
= Some(self.add_section_name(&b
".symtab"[..]));
854 self.symtab_index
= self.reserve_section_index();
858 /// Return the section index of the symbol table.
859 pub fn symtab_index(&mut self) -> SectionIndex
{
863 /// Write the section header for the symbol table.
865 /// This function does nothing if the section index was not reserved.
866 pub fn write_symtab_section_header(&mut self, num_local
: u32) {
867 if self.symtab_index
== SectionIndex(0) {
870 self.write_section_header(&SectionHeader
{
871 name
: self.symtab_str_id
,
872 sh_type
: elf
::SHT_SYMTAB
,
875 sh_offset
: self.symtab_offset
as u64,
876 sh_size
: self.symtab_num
as u64 * self.symbol_size() as u64,
877 sh_link
: self.strtab_index
.0,
879 sh_addralign
: self.elf_align
as u64,
880 sh_entsize
: self.symbol_size() as u64,
884 /// Return true if `.symtab_shndx` is needed.
885 pub fn symtab_shndx_needed(&self) -> bool
{
886 self.need_symtab_shndx
889 /// Reserve the range for the extended section indices for the symbol table.
891 /// This range is used for a section named `.symtab_shndx`.
892 /// This also reserves a section index.
894 /// This function does nothing if extended section indices are not needed.
895 /// This must be called after [`Self::reserve_symbol_index`].
896 pub fn reserve_symtab_shndx(&mut self) {
897 debug_assert_eq
!(self.symtab_shndx_offset
, 0);
898 if !self.need_symtab_shndx
{
901 self.symtab_shndx_offset
= self.reserve(self.symtab_num
as usize * 4, 4);
902 self.symtab_shndx_data
.reserve(self.symtab_num
as usize * 4);
905 /// Write the extended section indices for the symbol table.
907 /// This function does nothing if the section was not reserved.
908 pub fn write_symtab_shndx(&mut self) {
909 if self.symtab_shndx_offset
== 0 {
912 debug_assert_eq
!(self.symtab_shndx_offset
, self.buffer
.len());
913 debug_assert_eq
!(self.symtab_num
as usize * 4, self.symtab_shndx_data
.len());
914 self.buffer
.write_bytes(&self.symtab_shndx_data
);
917 /// Reserve the section index for the extended section indices symbol table.
919 /// You should check [`Self::symtab_shndx_needed`] before calling this
920 /// unless you have other means of knowing if this section is needed.
922 /// This must be called before [`Self::reserve_section_headers`].
923 pub fn reserve_symtab_shndx_section_index(&mut self) -> SectionIndex
{
924 debug_assert
!(self.symtab_shndx_str_id
.is_none());
925 self.symtab_shndx_str_id
= Some(self.add_section_name(&b
".symtab_shndx"[..]));
926 self.reserve_section_index()
929 /// Write the section header for the extended section indices for the symbol table.
931 /// This function does nothing if the section index was not reserved.
932 pub fn write_symtab_shndx_section_header(&mut self) {
933 if self.symtab_shndx_str_id
.is_none() {
936 let sh_size
= if self.symtab_shndx_offset
== 0 {
939 (self.symtab_num
* 4) as u64
941 self.write_section_header(&SectionHeader
{
942 name
: self.symtab_shndx_str_id
,
943 sh_type
: elf
::SHT_SYMTAB_SHNDX
,
946 sh_offset
: self.symtab_shndx_offset
as u64,
948 sh_link
: self.symtab_index
.0,
955 /// Add a string to the dynamic string table.
957 /// This will be stored in the `.dynstr` section.
959 /// This must be called before [`Self::reserve_dynstr`].
960 pub fn add_dynamic_string(&mut self, name
: &'a
[u8]) -> StringId
{
961 debug_assert_eq
!(self.dynstr_offset
, 0);
962 self.need_dynstr
= true;
963 self.dynstr
.add(name
)
966 /// Get a string that was previously added to the dynamic string table.
968 /// Panics if the string was not added.
969 pub fn get_dynamic_string(&self, name
: &'a
[u8]) -> StringId
{
970 self.dynstr
.get_id(name
)
973 /// Return true if `.dynstr` is needed.
974 pub fn dynstr_needed(&self) -> bool
{
978 /// Reserve the range for the dynamic string table.
980 /// This range is used for a section named `.dynstr`.
982 /// This function does nothing if no dynamic strings or symbols were defined.
983 /// This must be called after [`Self::add_dynamic_string`].
984 pub fn reserve_dynstr(&mut self) {
985 debug_assert_eq
!(self.dynstr_offset
, 0);
986 if !self.need_dynstr
{
989 // Start with null string.
990 self.dynstr_data
= vec
![0];
991 self.dynstr
.write(1, &mut self.dynstr_data
);
992 self.dynstr_offset
= self.reserve(self.dynstr_data
.len(), 1);
995 /// Write the dynamic string table.
997 /// This function does nothing if the section was not reserved.
998 pub fn write_dynstr(&mut self) {
999 if self.dynstr_offset
== 0 {
1002 debug_assert_eq
!(self.dynstr_offset
, self.buffer
.len());
1003 self.buffer
.write_bytes(&self.dynstr_data
);
1006 /// Reserve the section index for the dynamic string table.
1008 /// This must be called before [`Self::reserve_section_headers`].
1009 pub fn reserve_dynstr_section_index(&mut self) -> SectionIndex
{
1010 debug_assert_eq
!(self.dynstr_index
, SectionIndex(0));
1011 self.dynstr_str_id
= Some(self.add_section_name(&b
".dynstr"[..]));
1012 self.dynstr_index
= self.reserve_section_index();
1016 /// Return the section index of the dynamic string table.
1017 pub fn dynstr_index(&mut self) -> SectionIndex
{
1021 /// Write the section header for the dynamic string table.
1023 /// This function does nothing if the section index was not reserved.
1024 pub fn write_dynstr_section_header(&mut self, sh_addr
: u64) {
1025 if self.dynstr_index
== SectionIndex(0) {
1028 self.write_section_header(&SectionHeader
{
1029 name
: self.dynstr_str_id
,
1030 sh_type
: elf
::SHT_STRTAB
,
1031 sh_flags
: elf
::SHF_ALLOC
.into(),
1033 sh_offset
: self.dynstr_offset
as u64,
1034 sh_size
: self.dynstr_data
.len() as u64,
1042 /// Reserve the null dynamic symbol table entry.
1044 /// This will be stored in the `.dynsym` section.
1046 /// The null dynamic symbol table entry is usually automatically reserved,
1047 /// but this can be used to force an empty dynamic symbol table.
1049 /// This must be called before [`Self::reserve_dynsym`].
1050 pub fn reserve_null_dynamic_symbol_index(&mut self) -> SymbolIndex
{
1051 debug_assert_eq
!(self.dynsym_offset
, 0);
1052 debug_assert_eq
!(self.dynsym_num
, 0);
1053 self.dynsym_num
= 1;
1054 // The symtab must link to a strtab.
1055 self.need_dynstr
= true;
1059 /// Reserve a dynamic symbol table entry.
1061 /// This will be stored in the `.dynsym` section.
1063 /// Automatically also reserves the null symbol if required.
1064 /// Callers may assume that the returned indices will be sequential
1067 /// This must be called before [`Self::reserve_dynsym`].
1068 pub fn reserve_dynamic_symbol_index(&mut self) -> SymbolIndex
{
1069 debug_assert_eq
!(self.dynsym_offset
, 0);
1070 if self.dynsym_num
== 0 {
1071 self.dynsym_num
= 1;
1072 // The symtab must link to a strtab.
1073 self.need_dynstr
= true;
1075 let index
= self.dynsym_num
;
1076 self.dynsym_num
+= 1;
1080 /// Return the number of reserved dynamic symbols.
1082 /// Includes the null symbol.
1083 pub fn dynamic_symbol_count(&mut self) -> u32 {
1087 /// Reserve the range for the dynamic symbol table.
1089 /// This range is used for a section named `.dynsym`.
1091 /// This function does nothing if no dynamic symbols were reserved.
1092 /// This must be called after [`Self::reserve_dynamic_symbol_index`].
1093 pub fn reserve_dynsym(&mut self) {
1094 debug_assert_eq
!(self.dynsym_offset
, 0);
1095 if self.dynsym_num
== 0 {
1098 self.dynsym_offset
= self.reserve(
1099 self.dynsym_num
as usize * self.symbol_size(),
1104 /// Write the null dynamic symbol.
1106 /// This must be the first dynamic symbol that is written.
1107 /// This function does nothing if no dynamic symbols were reserved.
1108 pub fn write_null_dynamic_symbol(&mut self) {
1109 if self.dynsym_num
== 0 {
1112 util
::write_align(self.buffer
, self.elf_align
);
1113 debug_assert_eq
!(self.dynsym_offset
, self.buffer
.len());
1115 self.buffer
.write(&elf
::Sym64
::<Endianness
>::default());
1117 self.buffer
.write(&elf
::Sym32
::<Endianness
>::default());
1121 /// Write a dynamic symbol.
1122 pub fn write_dynamic_symbol(&mut self, sym
: &Sym
) {
1123 let st_name
= if let Some(name
) = sym
.name
{
1124 self.dynstr
.get_offset(name
) as u32
1129 let st_shndx
= if let Some(section
) = sym
.section
{
1130 if section
.0 >= elf
::SHN_LORESERVE
as u32 {
1131 // TODO: we don't actually write out .dynsym_shndx yet.
1132 // This is unlikely to be needed though.
1141 let endian
= self.endian
;
1143 let sym
= elf
::Sym64
{
1144 st_name
: U32
::new(endian
, st_name
),
1145 st_info
: sym
.st_info
,
1146 st_other
: sym
.st_other
,
1147 st_shndx
: U16
::new(endian
, st_shndx
),
1148 st_value
: U64
::new(endian
, sym
.st_value
),
1149 st_size
: U64
::new(endian
, sym
.st_size
),
1151 self.buffer
.write(&sym
);
1153 let sym
= elf
::Sym32
{
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
: U32
::new(endian
, sym
.st_value
as u32),
1159 st_size
: U32
::new(endian
, sym
.st_size
as u32),
1161 self.buffer
.write(&sym
);
1165 /// Reserve the section index for the dynamic symbol table.
1167 /// This must be called before [`Self::reserve_section_headers`].
1168 pub fn reserve_dynsym_section_index(&mut self) -> SectionIndex
{
1169 debug_assert_eq
!(self.dynsym_index
, SectionIndex(0));
1170 self.dynsym_str_id
= Some(self.add_section_name(&b
".dynsym"[..]));
1171 self.dynsym_index
= self.reserve_section_index();
1175 /// Return the section index of the dynamic symbol table.
1176 pub fn dynsym_index(&mut self) -> SectionIndex
{
1180 /// Write the section header for the dynamic symbol table.
1182 /// This function does nothing if the section index was not reserved.
1183 pub fn write_dynsym_section_header(&mut self, sh_addr
: u64, num_local
: u32) {
1184 if self.dynsym_index
== SectionIndex(0) {
1187 self.write_section_header(&SectionHeader
{
1188 name
: self.dynsym_str_id
,
1189 sh_type
: elf
::SHT_DYNSYM
,
1190 sh_flags
: elf
::SHF_ALLOC
.into(),
1192 sh_offset
: self.dynsym_offset
as u64,
1193 sh_size
: self.dynsym_num
as u64 * self.symbol_size() as u64,
1194 sh_link
: self.dynstr_index
.0,
1196 sh_addralign
: self.elf_align
as u64,
1197 sh_entsize
: self.symbol_size() as u64,
1201 fn dyn_size(&self) -> usize {
1203 mem
::size_of
::<elf
::Dyn64
<Endianness
>>()
1205 mem
::size_of
::<elf
::Dyn32
<Endianness
>>()
1209 /// Reserve the range for the `.dynamic` section.
1211 /// This function does nothing if `dynamic_num` is zero.
1212 pub fn reserve_dynamic(&mut self, dynamic_num
: usize) {
1213 debug_assert_eq
!(self.dynamic_offset
, 0);
1214 if dynamic_num
== 0 {
1217 self.dynamic_num
= dynamic_num
;
1218 self.dynamic_offset
= self.reserve(dynamic_num
* self.dyn_size(), self.elf_align
);
1221 /// Write alignment padding bytes prior to the `.dynamic` section.
1223 /// This function does nothing if the section was not reserved.
1224 pub fn write_align_dynamic(&mut self) {
1225 if self.dynamic_offset
== 0 {
1228 util
::write_align(self.buffer
, self.elf_align
);
1229 debug_assert_eq
!(self.dynamic_offset
, self.buffer
.len());
1232 /// Write a dynamic string entry.
1233 pub fn write_dynamic_string(&mut self, tag
: u32, id
: StringId
) {
1234 self.write_dynamic(tag
, self.dynstr
.get_offset(id
) as u64);
1237 /// Write a dynamic value entry.
1238 pub fn write_dynamic(&mut self, d_tag
: u32, d_val
: u64) {
1239 debug_assert
!(self.dynamic_offset
<= self.buffer
.len());
1240 let endian
= self.endian
;
1242 let d
= elf
::Dyn64
{
1243 d_tag
: U64
::new(endian
, d_tag
.into()),
1244 d_val
: U64
::new(endian
, d_val
),
1246 self.buffer
.write(&d
);
1248 let d
= elf
::Dyn32
{
1249 d_tag
: U32
::new(endian
, d_tag
),
1250 d_val
: U32
::new(endian
, d_val
as u32),
1252 self.buffer
.write(&d
);
1255 self.dynamic_offset
+ self.dynamic_num
* self.dyn_size() >= self.buffer
.len()
1259 /// Reserve the section index for the dynamic table.
1260 pub fn reserve_dynamic_section_index(&mut self) -> SectionIndex
{
1261 debug_assert
!(self.dynamic_str_id
.is_none());
1262 self.dynamic_str_id
= Some(self.add_section_name(&b
".dynamic"[..]));
1263 self.reserve_section_index()
1266 /// Write the section header for the dynamic table.
1268 /// This function does nothing if the section index was not reserved.
1269 pub fn write_dynamic_section_header(&mut self, sh_addr
: u64) {
1270 if self.dynamic_str_id
.is_none() {
1273 self.write_section_header(&SectionHeader
{
1274 name
: self.dynamic_str_id
,
1275 sh_type
: elf
::SHT_DYNAMIC
,
1276 sh_flags
: (elf
::SHF_WRITE
| elf
::SHF_ALLOC
).into(),
1278 sh_offset
: self.dynamic_offset
as u64,
1279 sh_size
: (self.dynamic_num
* self.dyn_size()) as u64,
1280 sh_link
: self.dynstr_index
.0,
1282 sh_addralign
: self.elf_align
as u64,
1283 sh_entsize
: self.dyn_size() as u64,
1287 fn rel_size(&self, is_rela
: bool
) -> usize {
1290 mem
::size_of
::<elf
::Rela64
<Endianness
>>()
1292 mem
::size_of
::<elf
::Rel64
<Endianness
>>()
1296 mem
::size_of
::<elf
::Rela32
<Endianness
>>()
1298 mem
::size_of
::<elf
::Rel32
<Endianness
>>()
1303 /// Reserve a file range for a SysV hash section.
1305 /// `symbol_count` is the number of symbols in the hash,
1306 /// not the total number of symbols.
1307 pub fn reserve_hash(&mut self, bucket_count
: u32, chain_count
: u32) {
1308 self.hash_size
= mem
::size_of
::<elf
::HashHeader
<Endianness
>>()
1309 + bucket_count
as usize * 4
1310 + chain_count
as usize * 4;
1311 self.hash_offset
= self.reserve(self.hash_size
, self.elf_align
);
1314 /// Write a SysV hash section.
1316 /// `chain_count` is the number of symbols in the hash.
1317 /// The argument to `hash` will be in the range `0..chain_count`.
1318 pub fn write_hash
<F
>(&mut self, bucket_count
: u32, chain_count
: u32, hash
: F
)
1320 F
: Fn(u32) -> Option
<u32>,
1322 let mut buckets
= vec
![U32
::new(self.endian
, 0); bucket_count
as usize];
1323 let mut chains
= vec
![U32
::new(self.endian
, 0); chain_count
as usize];
1324 for i
in 0..chain_count
{
1325 if let Some(hash
) = hash(i
) {
1326 let bucket
= hash
% bucket_count
;
1327 chains
[i
as usize] = buckets
[bucket
as usize];
1328 buckets
[bucket
as usize] = U32
::new(self.endian
, i
);
1332 util
::write_align(self.buffer
, self.elf_align
);
1333 debug_assert_eq
!(self.hash_offset
, self.buffer
.len());
1334 self.buffer
.write(&elf
::HashHeader
{
1335 bucket_count
: U32
::new(self.endian
, bucket_count
),
1336 chain_count
: U32
::new(self.endian
, chain_count
),
1338 self.buffer
.write_slice(&buckets
);
1339 self.buffer
.write_slice(&chains
);
1342 /// Reserve the section index for the SysV hash table.
1343 pub fn reserve_hash_section_index(&mut self) -> SectionIndex
{
1344 debug_assert
!(self.hash_str_id
.is_none());
1345 self.hash_str_id
= Some(self.add_section_name(&b
".hash"[..]));
1346 self.reserve_section_index()
1349 /// Write the section header for the SysV hash table.
1351 /// This function does nothing if the section index was not reserved.
1352 pub fn write_hash_section_header(&mut self, sh_addr
: u64) {
1353 if self.hash_str_id
.is_none() {
1356 self.write_section_header(&SectionHeader
{
1357 name
: self.hash_str_id
,
1358 sh_type
: elf
::SHT_HASH
,
1359 sh_flags
: elf
::SHF_ALLOC
.into(),
1361 sh_offset
: self.hash_offset
as u64,
1362 sh_size
: self.hash_size
as u64,
1363 sh_link
: self.dynsym_index
.0,
1365 sh_addralign
: self.elf_align
as u64,
1370 /// Reserve a file range for a GNU hash section.
1372 /// `symbol_count` is the number of symbols in the hash,
1373 /// not the total number of symbols.
1374 pub fn reserve_gnu_hash(&mut self, bloom_count
: u32, bucket_count
: u32, symbol_count
: u32) {
1375 self.gnu_hash_size
= mem
::size_of
::<elf
::GnuHashHeader
<Endianness
>>()
1376 + bloom_count
as usize * self.elf_align
1377 + bucket_count
as usize * 4
1378 + symbol_count
as usize * 4;
1379 self.gnu_hash_offset
= self.reserve(self.gnu_hash_size
, self.elf_align
);
1382 /// Write a GNU hash section.
1384 /// `symbol_count` is the number of symbols in the hash.
1385 /// The argument to `hash` will be in the range `0..symbol_count`.
1387 /// This requires that symbols are already sorted by bucket.
1388 pub fn write_gnu_hash
<F
>(
1399 util
::write_align(self.buffer
, self.elf_align
);
1400 debug_assert_eq
!(self.gnu_hash_offset
, self.buffer
.len());
1401 self.buffer
.write(&elf
::GnuHashHeader
{
1402 bucket_count
: U32
::new(self.endian
, bucket_count
),
1403 symbol_base
: U32
::new(self.endian
, symbol_base
),
1404 bloom_count
: U32
::new(self.endian
, bloom_count
),
1405 bloom_shift
: U32
::new(self.endian
, bloom_shift
),
1408 // Calculate and write bloom filter.
1410 let mut bloom_filters
= vec
![0; bloom_count
as usize];
1411 for i
in 0..symbol_count
{
1413 bloom_filters
[((h
/ 64) & (bloom_count
- 1)) as usize] |=
1414 1 << (h
% 64) | 1 << ((h
>> bloom_shift
) % 64);
1416 for bloom_filter
in bloom_filters
{
1417 self.buffer
.write(&U64
::new(self.endian
, bloom_filter
));
1420 let mut bloom_filters
= vec
![0; bloom_count
as usize];
1421 for i
in 0..symbol_count
{
1423 bloom_filters
[((h
/ 32) & (bloom_count
- 1)) as usize] |=
1424 1 << (h
% 32) | 1 << ((h
>> bloom_shift
) % 32);
1426 for bloom_filter
in bloom_filters
{
1427 self.buffer
.write(&U32
::new(self.endian
, bloom_filter
));
1433 // This requires that symbols are already sorted by bucket.
1435 for i
in 0..symbol_count
{
1436 let symbol_bucket
= hash(i
) % bucket_count
;
1437 while bucket
< symbol_bucket
{
1438 self.buffer
.write(&U32
::new(self.endian
, 0));
1441 if bucket
== symbol_bucket
{
1442 self.buffer
.write(&U32
::new(self.endian
, symbol_base
+ i
));
1446 while bucket
< bucket_count
{
1447 self.buffer
.write(&U32
::new(self.endian
, 0));
1451 // Write hash values.
1452 for i
in 0..symbol_count
{
1453 let mut h
= hash(i
);
1454 if i
== symbol_count
- 1 || h
% bucket_count
!= hash(i
+ 1) % bucket_count
{
1459 self.buffer
.write(&U32
::new(self.endian
, h
));
1463 /// Reserve the section index for the GNU hash table.
1464 pub fn reserve_gnu_hash_section_index(&mut self) -> SectionIndex
{
1465 debug_assert
!(self.gnu_hash_str_id
.is_none());
1466 self.gnu_hash_str_id
= Some(self.add_section_name(&b
".gnu.hash"[..]));
1467 self.reserve_section_index()
1470 /// Write the section header for the GNU hash table.
1472 /// This function does nothing if the section index was not reserved.
1473 pub fn write_gnu_hash_section_header(&mut self, sh_addr
: u64) {
1474 if self.gnu_hash_str_id
.is_none() {
1477 self.write_section_header(&SectionHeader
{
1478 name
: self.gnu_hash_str_id
,
1479 sh_type
: elf
::SHT_GNU_HASH
,
1480 sh_flags
: elf
::SHF_ALLOC
.into(),
1482 sh_offset
: self.gnu_hash_offset
as u64,
1483 sh_size
: self.gnu_hash_size
as u64,
1484 sh_link
: self.dynsym_index
.0,
1486 sh_addralign
: self.elf_align
as u64,
1491 /// Reserve the range for the `.gnu.version` section.
1493 /// This function does nothing if no dynamic symbols were reserved.
1494 pub fn reserve_gnu_versym(&mut self) {
1495 debug_assert_eq
!(self.gnu_versym_offset
, 0);
1496 if self.dynsym_num
== 0 {
1499 self.gnu_versym_offset
= self.reserve(self.dynsym_num
as usize * 2, 2);
1502 /// Write the null symbol version entry.
1504 /// This must be the first symbol version that is written.
1505 /// This function does nothing if no dynamic symbols were reserved.
1506 pub fn write_null_gnu_versym(&mut self) {
1507 if self.dynsym_num
== 0 {
1510 util
::write_align(self.buffer
, 2);
1511 debug_assert_eq
!(self.gnu_versym_offset
, self.buffer
.len());
1512 self.write_gnu_versym(0);
1515 /// Write a symbol version entry.
1516 pub fn write_gnu_versym(&mut self, versym
: u16) {
1517 self.buffer
.write(&U16
::new(self.endian
, versym
));
1520 /// Reserve the section index for the `.gnu.version` section.
1521 pub fn reserve_gnu_versym_section_index(&mut self) -> SectionIndex
{
1522 debug_assert
!(self.gnu_versym_str_id
.is_none());
1523 self.gnu_versym_str_id
= Some(self.add_section_name(&b
".gnu.version"[..]));
1524 self.reserve_section_index()
1527 /// Write the section header for the `.gnu.version` section.
1529 /// This function does nothing if the section index was not reserved.
1530 pub fn write_gnu_versym_section_header(&mut self, sh_addr
: u64) {
1531 if self.gnu_versym_str_id
.is_none() {
1534 self.write_section_header(&SectionHeader
{
1535 name
: self.gnu_versym_str_id
,
1536 sh_type
: elf
::SHT_GNU_VERSYM
,
1537 sh_flags
: elf
::SHF_ALLOC
.into(),
1539 sh_offset
: self.gnu_versym_offset
as u64,
1540 sh_size
: self.dynsym_num
as u64 * 2,
1541 sh_link
: self.dynsym_index
.0,
1548 /// Reserve the range for the `.gnu.version_d` section.
1549 pub fn reserve_gnu_verdef(&mut self, verdef_count
: usize, verdaux_count
: usize) {
1550 debug_assert_eq
!(self.gnu_verdef_offset
, 0);
1551 if verdef_count
== 0 {
1554 self.gnu_verdef_size
= verdef_count
* mem
::size_of
::<elf
::Verdef
<Endianness
>>()
1555 + verdaux_count
* mem
::size_of
::<elf
::Verdaux
<Endianness
>>();
1556 self.gnu_verdef_offset
= self.reserve(self.gnu_verdef_size
, self.elf_align
);
1557 self.gnu_verdef_count
= verdef_count
as u16;
1558 self.gnu_verdef_remaining
= self.gnu_verdef_count
;
1561 /// Write alignment padding bytes prior to a `.gnu.version_d` section.
1562 pub fn write_align_gnu_verdef(&mut self) {
1563 if self.gnu_verdef_offset
== 0 {
1566 util
::write_align(self.buffer
, self.elf_align
);
1567 debug_assert_eq
!(self.gnu_verdef_offset
, self.buffer
.len());
1570 /// Write a version definition entry.
1571 pub fn write_gnu_verdef(&mut self, verdef
: &Verdef
) {
1572 debug_assert_ne
!(self.gnu_verdef_remaining
, 0);
1573 self.gnu_verdef_remaining
-= 1;
1574 let vd_next
= if self.gnu_verdef_remaining
== 0 {
1577 mem
::size_of
::<elf
::Verdef
<Endianness
>>() as u32
1578 + verdef
.aux_count
as u32 * mem
::size_of
::<elf
::Verdaux
<Endianness
>>() as u32
1581 self.gnu_verdaux_remaining
= verdef
.aux_count
;
1582 let vd_aux
= if verdef
.aux_count
== 0 {
1585 mem
::size_of
::<elf
::Verdef
<Endianness
>>() as u32
1588 self.buffer
.write(&elf
::Verdef
{
1589 vd_version
: U16
::new(self.endian
, verdef
.version
),
1590 vd_flags
: U16
::new(self.endian
, verdef
.flags
),
1591 vd_ndx
: U16
::new(self.endian
, verdef
.index
),
1592 vd_cnt
: U16
::new(self.endian
, verdef
.aux_count
),
1593 vd_hash
: U32
::new(self.endian
, elf
::hash(self.dynstr
.get_string(verdef
.name
))),
1594 vd_aux
: U32
::new(self.endian
, vd_aux
),
1595 vd_next
: U32
::new(self.endian
, vd_next
),
1597 self.write_gnu_verdaux(verdef
.name
);
1600 /// Write a version definition auxiliary entry.
1601 pub fn write_gnu_verdaux(&mut self, name
: StringId
) {
1602 debug_assert_ne
!(self.gnu_verdaux_remaining
, 0);
1603 self.gnu_verdaux_remaining
-= 1;
1604 let vda_next
= if self.gnu_verdaux_remaining
== 0 {
1607 mem
::size_of
::<elf
::Verdaux
<Endianness
>>() as u32
1609 self.buffer
.write(&elf
::Verdaux
{
1610 vda_name
: U32
::new(self.endian
, self.dynstr
.get_offset(name
) as u32),
1611 vda_next
: U32
::new(self.endian
, vda_next
),
1615 /// Reserve the section index for the `.gnu.version_d` section.
1616 pub fn reserve_gnu_verdef_section_index(&mut self) -> SectionIndex
{
1617 debug_assert
!(self.gnu_verdef_str_id
.is_none());
1618 self.gnu_verdef_str_id
= Some(self.add_section_name(&b
".gnu.version_d"[..]));
1619 self.reserve_section_index()
1622 /// Write the section header for the `.gnu.version_d` section.
1624 /// This function does nothing if the section index was not reserved.
1625 pub fn write_gnu_verdef_section_header(&mut self, sh_addr
: u64) {
1626 if self.gnu_verdef_str_id
.is_none() {
1629 self.write_section_header(&SectionHeader
{
1630 name
: self.gnu_verdef_str_id
,
1631 sh_type
: elf
::SHT_GNU_VERDEF
,
1632 sh_flags
: elf
::SHF_ALLOC
.into(),
1634 sh_offset
: self.gnu_verdef_offset
as u64,
1635 sh_size
: self.gnu_verdef_size
as u64,
1636 sh_link
: self.dynstr_index
.0,
1637 sh_info
: self.gnu_verdef_count
.into(),
1638 sh_addralign
: self.elf_align
as u64,
1643 /// Reserve the range for the `.gnu.version_r` section.
1644 pub fn reserve_gnu_verneed(&mut self, verneed_count
: usize, vernaux_count
: usize) {
1645 debug_assert_eq
!(self.gnu_verneed_offset
, 0);
1646 if verneed_count
== 0 {
1649 self.gnu_verneed_size
= verneed_count
* mem
::size_of
::<elf
::Verneed
<Endianness
>>()
1650 + vernaux_count
* mem
::size_of
::<elf
::Vernaux
<Endianness
>>();
1651 self.gnu_verneed_offset
= self.reserve(self.gnu_verneed_size
, self.elf_align
);
1652 self.gnu_verneed_count
= verneed_count
as u16;
1653 self.gnu_verneed_remaining
= self.gnu_verneed_count
;
1656 /// Write alignment padding bytes prior to a `.gnu.version_r` section.
1657 pub fn write_align_gnu_verneed(&mut self) {
1658 if self.gnu_verneed_offset
== 0 {
1661 util
::write_align(self.buffer
, self.elf_align
);
1662 debug_assert_eq
!(self.gnu_verneed_offset
, self.buffer
.len());
1665 /// Write a version need entry.
1666 pub fn write_gnu_verneed(&mut self, verneed
: &Verneed
) {
1667 debug_assert_ne
!(self.gnu_verneed_remaining
, 0);
1668 self.gnu_verneed_remaining
-= 1;
1669 let vn_next
= if self.gnu_verneed_remaining
== 0 {
1672 mem
::size_of
::<elf
::Verneed
<Endianness
>>() as u32
1673 + verneed
.aux_count
as u32 * mem
::size_of
::<elf
::Vernaux
<Endianness
>>() as u32
1676 self.gnu_vernaux_remaining
= verneed
.aux_count
;
1677 let vn_aux
= if verneed
.aux_count
== 0 {
1680 mem
::size_of
::<elf
::Verneed
<Endianness
>>() as u32
1683 self.buffer
.write(&elf
::Verneed
{
1684 vn_version
: U16
::new(self.endian
, verneed
.version
),
1685 vn_cnt
: U16
::new(self.endian
, verneed
.aux_count
),
1686 vn_file
: U32
::new(self.endian
, self.dynstr
.get_offset(verneed
.file
) as u32),
1687 vn_aux
: U32
::new(self.endian
, vn_aux
),
1688 vn_next
: U32
::new(self.endian
, vn_next
),
1692 /// Write a version need auxiliary entry.
1693 pub fn write_gnu_vernaux(&mut self, vernaux
: &Vernaux
) {
1694 debug_assert_ne
!(self.gnu_vernaux_remaining
, 0);
1695 self.gnu_vernaux_remaining
-= 1;
1696 let vna_next
= if self.gnu_vernaux_remaining
== 0 {
1699 mem
::size_of
::<elf
::Vernaux
<Endianness
>>() as u32
1701 self.buffer
.write(&elf
::Vernaux
{
1702 vna_hash
: U32
::new(self.endian
, elf
::hash(self.dynstr
.get_string(vernaux
.name
))),
1703 vna_flags
: U16
::new(self.endian
, vernaux
.flags
),
1704 vna_other
: U16
::new(self.endian
, vernaux
.index
),
1705 vna_name
: U32
::new(self.endian
, self.dynstr
.get_offset(vernaux
.name
) as u32),
1706 vna_next
: U32
::new(self.endian
, vna_next
),
1710 /// Reserve the section index for the `.gnu.version_r` section.
1711 pub fn reserve_gnu_verneed_section_index(&mut self) -> SectionIndex
{
1712 debug_assert
!(self.gnu_verneed_str_id
.is_none());
1713 self.gnu_verneed_str_id
= Some(self.add_section_name(&b
".gnu.version_r"[..]));
1714 self.reserve_section_index()
1717 /// Write the section header for the `.gnu.version_r` section.
1719 /// This function does nothing if the section index was not reserved.
1720 pub fn write_gnu_verneed_section_header(&mut self, sh_addr
: u64) {
1721 if self.gnu_verneed_str_id
.is_none() {
1724 self.write_section_header(&SectionHeader
{
1725 name
: self.gnu_verneed_str_id
,
1726 sh_type
: elf
::SHT_GNU_VERNEED
,
1727 sh_flags
: elf
::SHF_ALLOC
.into(),
1729 sh_offset
: self.gnu_verneed_offset
as u64,
1730 sh_size
: self.gnu_verneed_size
as u64,
1731 sh_link
: self.dynstr_index
.0,
1732 sh_info
: self.gnu_verneed_count
.into(),
1733 sh_addralign
: self.elf_align
as u64,
1738 /// Reserve a file range for the given number of relocations.
1740 /// Returns the offset of the range.
1741 pub fn reserve_relocations(&mut self, count
: usize, is_rela
: bool
) -> usize {
1742 self.reserve(count
* self.rel_size(is_rela
), self.elf_align
)
1745 /// Write alignment padding bytes prior to a relocation section.
1746 pub fn write_align_relocation(&mut self) {
1747 util
::write_align(self.buffer
, self.elf_align
);
1750 /// Write a relocation.
1751 pub fn write_relocation(&mut self, is_rela
: bool
, rel
: &Rel
) {
1752 let endian
= self.endian
;
1755 let rel
= elf
::Rela64
{
1756 r_offset
: U64
::new(endian
, rel
.r_offset
),
1757 r_info
: elf
::Rela64
::r_info(endian
, self.is_mips64el
, rel
.r_sym
, rel
.r_type
),
1758 r_addend
: I64
::new(endian
, rel
.r_addend
),
1760 self.buffer
.write(&rel
);
1762 let rel
= elf
::Rel64
{
1763 r_offset
: U64
::new(endian
, rel
.r_offset
),
1764 r_info
: elf
::Rel64
::r_info(endian
, rel
.r_sym
, rel
.r_type
),
1766 self.buffer
.write(&rel
);
1770 let rel
= elf
::Rela32
{
1771 r_offset
: U32
::new(endian
, rel
.r_offset
as u32),
1772 r_info
: elf
::Rel32
::r_info(endian
, rel
.r_sym
, rel
.r_type
as u8),
1773 r_addend
: I32
::new(endian
, rel
.r_addend
as i32),
1775 self.buffer
.write(&rel
);
1777 let rel
= elf
::Rel32
{
1778 r_offset
: U32
::new(endian
, rel
.r_offset
as u32),
1779 r_info
: elf
::Rel32
::r_info(endian
, rel
.r_sym
, rel
.r_type
as u8),
1781 self.buffer
.write(&rel
);
1786 /// Write the section header for a relocation section.
1788 /// `section` is the index of the section the relocations apply to,
1791 /// `symtab` is the index of the symbol table the relocations refer to,
1794 /// `offset` is the file offset of the relocations.
1795 pub fn write_relocation_section_header(
1798 section
: SectionIndex
,
1799 symtab
: SectionIndex
,
1804 self.write_section_header(&SectionHeader
{
1806 sh_type
: if is_rela { elf::SHT_RELA }
else { elf::SHT_REL }
,
1807 sh_flags
: elf
::SHF_INFO_LINK
.into(),
1809 sh_offset
: offset
as u64,
1810 sh_size
: (count
* self.rel_size(is_rela
)) as u64,
1813 sh_addralign
: self.elf_align
as u64,
1814 sh_entsize
: self.rel_size(is_rela
) as u64,
1818 /// Reserve a file range for a COMDAT section.
1820 /// `count` is the number of sections in the COMDAT group.
1822 /// Returns the offset of the range.
1823 pub fn reserve_comdat(&mut self, count
: usize) -> usize {
1824 self.reserve((count
+ 1) * 4, 4)
1827 /// Write `GRP_COMDAT` at the start of the COMDAT section.
1828 pub fn write_comdat_header(&mut self) {
1829 util
::write_align(self.buffer
, 4);
1830 self.buffer
.write(&U32
::new(self.endian
, elf
::GRP_COMDAT
));
1833 /// Write an entry in a COMDAT section.
1834 pub fn write_comdat_entry(&mut self, entry
: SectionIndex
) {
1835 self.buffer
.write(&U32
::new(self.endian
, entry
.0));
1838 /// Write the section header for a COMDAT section.
1839 pub fn write_comdat_section_header(
1842 symtab
: SectionIndex
,
1843 symbol
: SymbolIndex
,
1847 self.write_section_header(&SectionHeader
{
1849 sh_type
: elf
::SHT_GROUP
,
1852 sh_offset
: offset
as u64,
1853 sh_size
: ((count
+ 1) * 4) as u64,
1862 /// Native endian version of [`elf::FileHeader64`].
1863 #[allow(missing_docs)]
1864 #[derive(Debug, Clone)]
1865 pub struct FileHeader
{
1867 pub abi_version
: u8,
1874 /// Native endian version of [`elf::ProgramHeader64`].
1875 #[allow(missing_docs)]
1876 #[derive(Debug, Clone)]
1877 pub struct ProgramHeader
{
1888 /// Native endian version of [`elf::SectionHeader64`].
1889 #[allow(missing_docs)]
1890 #[derive(Debug, Clone)]
1891 pub struct SectionHeader
{
1892 pub name
: Option
<StringId
>,
1900 pub sh_addralign
: u64,
1901 pub sh_entsize
: u64,
1904 /// Native endian version of [`elf::Sym64`].
1905 #[allow(missing_docs)]
1906 #[derive(Debug, Clone)]
1908 pub name
: Option
<StringId
>,
1909 pub section
: Option
<SectionIndex
>,
1917 /// Unified native endian version of [`elf::Rel64`] and [`elf::Rela64`].
1918 #[allow(missing_docs)]
1919 #[derive(Debug, Clone)]
1927 /// Information required for writing [`elf::Verdef`].
1928 #[allow(missing_docs)]
1929 #[derive(Debug, Clone)]
1935 /// The name for the first [`elf::Verdaux`] entry.
1939 /// Information required for writing [`elf::Verneed`].
1940 #[allow(missing_docs)]
1941 #[derive(Debug, Clone)]
1942 pub struct Verneed
{
1948 /// Information required for writing [`elf::Vernaux`].
1949 #[allow(missing_docs)]
1950 #[derive(Debug, Clone)]
1951 pub struct Vernaux
{