6 use crate::write
::string
::*;
7 use crate::write
::util
::*;
9 use crate::AddressSize
;
11 #[derive(Default, Clone, Copy)]
12 struct ComdatOffsets
{
14 str_id
: Option
<StringId
>,
18 #[derive(Default, Clone, Copy)]
19 struct SectionOffsets
{
22 str_id
: Option
<StringId
>,
26 reloc_str_id
: Option
<StringId
>,
29 #[derive(Default, Clone, Copy)]
30 struct SymbolOffsets
{
32 str_id
: Option
<StringId
>,
36 pub(crate) fn elf_section_info(
38 section
: StandardSection
,
39 ) -> (&'
static [u8], &'
static [u8], SectionKind
) {
41 StandardSection
::Text
=> (&[], &b
".text"[..], SectionKind
::Text
),
42 StandardSection
::Data
=> (&[], &b
".data"[..], SectionKind
::Data
),
43 StandardSection
::ReadOnlyData
| StandardSection
::ReadOnlyString
=> {
44 (&[], &b
".rodata"[..], SectionKind
::ReadOnlyData
)
46 StandardSection
::ReadOnlyDataWithRel
=> (&[], b
".data.rel.ro", SectionKind
::Data
),
47 StandardSection
::UninitializedData
=> {
48 (&[], &b
".bss"[..], SectionKind
::UninitializedData
)
50 StandardSection
::Tls
=> (&[], &b
".tdata"[..], SectionKind
::Tls
),
51 StandardSection
::UninitializedTls
=> {
52 (&[], &b
".tbss"[..], SectionKind
::UninitializedTls
)
54 StandardSection
::TlsVariables
=> {
55 // Unsupported section.
56 (&[], &[], SectionKind
::TlsVariables
)
58 StandardSection
::Common
=> {
59 // Unsupported section.
60 (&[], &[], SectionKind
::Common
)
65 pub(crate) fn elf_subsection_name(&self, section
: &[u8], value
: &[u8]) -> Vec
<u8> {
66 let mut name
= section
.to_vec();
68 name
.extend_from_slice(value
);
72 fn elf_has_relocation_addend(&self) -> Result
<bool
> {
73 Ok(match self.architecture
{
74 Architecture
::Aarch64
=> true,
75 Architecture
::Arm
=> false,
76 Architecture
::Avr
=> true,
77 Architecture
::Bpf
=> false,
78 Architecture
::I386
=> false,
79 Architecture
::X86_64
=> true,
80 Architecture
::X86_64_X32
=> true,
81 Architecture
::Hexagon
=> true,
82 Architecture
::Mips
=> false,
83 Architecture
::Mips64
=> true,
84 Architecture
::Msp430
=> true,
85 Architecture
::PowerPc
=> true,
86 Architecture
::PowerPc64
=> true,
87 Architecture
::Riscv64
=> true,
88 Architecture
::Riscv32
=> true,
89 Architecture
::S390x
=> true,
90 Architecture
::Sparc64
=> true,
92 return Err(Error(format
!(
93 "unimplemented architecture {:?}",
100 pub(crate) fn elf_fixup_relocation(&mut self, mut relocation
: &mut Relocation
) -> Result
<i64> {
101 // Return true if we should use a section symbol to avoid preemption.
102 fn want_section_symbol(relocation
: &Relocation
, symbol
: &Symbol
) -> bool
{
103 if symbol
.scope
!= SymbolScope
::Dynamic
{
104 // Only dynamic symbols can be preemptible.
108 SymbolKind
::Text
| SymbolKind
::Data
=> {}
111 match relocation
.kind
{
112 // Anything using GOT or PLT is preemptible.
113 // We also require that `Other` relocations must already be correct.
115 | RelocationKind
::GotRelative
116 | RelocationKind
::GotBaseRelative
117 | RelocationKind
::PltRelative
118 | RelocationKind
::Elf(_
) => return false,
119 // Absolute relocations are preemptible for non-local data.
120 // TODO: not sure if this rule is exactly correct
121 // This rule was added to handle global data references in debuginfo.
122 // Maybe this should be a new relocation kind so that the caller can decide.
123 RelocationKind
::Absolute
=> {
124 if symbol
.kind
== SymbolKind
::Data
{
133 // Use section symbols for relocations where required to avoid preemption.
134 // Otherwise, the linker will fail with:
135 // relocation R_X86_64_PC32 against symbol `SomeSymbolName' can not be used when
136 // making a shared object; recompile with -fPIC
137 let symbol
= &self.symbols
[relocation
.symbol
.0];
138 if want_section_symbol(relocation
, symbol
) {
139 if let Some(section
) = symbol
.section
.id() {
140 relocation
.addend
+= symbol
.value
as i64;
141 relocation
.symbol
= self.section_symbol(section
);
145 // Determine whether the addend is stored in the relocation or the data.
146 if self.elf_has_relocation_addend()?
{
149 let constant
= relocation
.addend
;
150 relocation
.addend
= 0;
155 pub(crate) fn elf_write(&self, buffer
: &mut dyn WritableBuffer
) -> Result
<()> {
156 let address_size
= self.architecture
.address_size().unwrap();
157 let endian
= self.endian
;
158 let elf32
= Elf32 { endian }
;
159 let elf64
= Elf64 { endian }
;
160 let elf
: &dyn Elf
= match address_size
{
161 AddressSize
::U8
| AddressSize
::U16
| AddressSize
::U32
=> &elf32
,
162 AddressSize
::U64
=> &elf64
,
164 let pointer_align
= address_size
.bytes() as usize;
166 self.architecture
== Architecture
::Mips64
&& self.endian
== Endianness
::Little
;
168 // Calculate offsets of everything.
172 let e_ehsize
= elf
.file_header_size();
175 // Create reloc section header names.
176 let is_rela
= self.elf_has_relocation_addend()?
;
177 let reloc_names
: Vec
<_
> = self
181 let mut reloc_name
= Vec
::new();
182 if !section
.relocations
.is_empty() {
183 reloc_name
.extend_from_slice(if is_rela
{
188 reloc_name
.extend_from_slice(§ion
.name
);
194 // Calculate size of section data.
195 let mut shstrtab
= StringTable
::default();
196 let mut comdat_offsets
= vec
![ComdatOffsets
::default(); self.comdats
.len()];
197 let mut section_offsets
= vec
![SectionOffsets
::default(); self.sections
.len()];
199 let mut section_num
= 1;
200 for (index
, comdat
) in self.comdats
.iter().enumerate() {
201 if comdat
.kind
!= ComdatKind
::Any
{
202 return Err(Error(format
!(
203 "unsupported COMDAT symbol `{}` kind {:?}",
204 self.symbols
[comdat
.symbol
.0].name().unwrap_or(""),
209 comdat_offsets
[index
].str_id
= Some(shstrtab
.add(b
".group"));
211 offset
= align(offset
, 4);
212 comdat_offsets
[index
].offset
= offset
;
213 let len
= (comdat
.sections
.len() + 1) * 4;
214 comdat_offsets
[index
].len
= len
;
217 for (index
, section
) in self.sections
.iter().enumerate() {
218 section_offsets
[index
].str_id
= Some(shstrtab
.add(§ion
.name
));
219 section_offsets
[index
].index
= section_num
;
222 let len
= section
.data
.len();
224 offset
= align(offset
, section
.align
as usize);
225 section_offsets
[index
].offset
= offset
;
228 section_offsets
[index
].offset
= offset
;
231 if !section
.relocations
.is_empty() {
232 section_offsets
[index
].reloc_str_id
= Some(shstrtab
.add(&reloc_names
[index
]));
233 section_offsets
[index
].reloc_index
= section_num
;
238 // Calculate index of symbols and add symbol strings to strtab.
239 let mut strtab
= StringTable
::default();
240 let mut symbol_offsets
= vec
![SymbolOffsets
::default(); self.symbols
.len()];
242 let mut symtab_count
= 1;
243 // Local symbols must come before global.
244 for (index
, symbol
) in self.symbols
.iter().enumerate() {
245 if symbol
.is_local() {
246 symbol_offsets
[index
].index
= symtab_count
;
250 let symtab_count_local
= symtab_count
;
251 for (index
, symbol
) in self.symbols
.iter().enumerate() {
252 if !symbol
.is_local() {
253 symbol_offsets
[index
].index
= symtab_count
;
257 for (index
, symbol
) in self.symbols
.iter().enumerate() {
258 if symbol
.kind
!= SymbolKind
::Section
&& !symbol
.name
.is_empty() {
259 symbol_offsets
[index
].str_id
= Some(strtab
.add(&symbol
.name
));
263 // Calculate size of symtab.
264 let symtab_str_id
= shstrtab
.add(&b
".symtab"[..]);
265 offset
= align(offset
, pointer_align
);
266 let symtab_offset
= offset
;
267 let symtab_len
= symtab_count
* elf
.symbol_size();
268 offset
+= symtab_len
;
269 let symtab_index
= section_num
;
272 // Calculate size of symtab_shndx.
273 let mut need_symtab_shndx
= false;
274 for symbol
in &self.symbols
{
278 .map(|s
| section_offsets
[s
.0].index
)
280 if index
>= elf
::SHN_LORESERVE
as usize {
281 need_symtab_shndx
= true;
285 let symtab_shndx_offset
= offset
;
286 let mut symtab_shndx_str_id
= None
;
287 let mut symtab_shndx_len
= 0;
288 if need_symtab_shndx
{
289 symtab_shndx_str_id
= Some(shstrtab
.add(&b
".symtab_shndx"[..]));
290 symtab_shndx_len
= symtab_count
* 4;
291 offset
+= symtab_shndx_len
;
295 // Calculate size of strtab.
296 let strtab_str_id
= shstrtab
.add(&b
".strtab"[..]);
297 let strtab_offset
= offset
;
298 // Start with null name.
299 let mut strtab_data
= vec
![0];
300 strtab
.write(1, &mut strtab_data
);
301 offset
+= strtab_data
.len();
302 let strtab_index
= section_num
;
305 // Calculate size of relocations.
306 for (index
, section
) in self.sections
.iter().enumerate() {
307 let count
= section
.relocations
.len();
309 offset
= align(offset
, pointer_align
);
310 section_offsets
[index
].reloc_offset
= offset
;
311 let len
= count
* elf
.rel_size(is_rela
);
312 section_offsets
[index
].reloc_len
= len
;
317 // Calculate size of shstrtab.
318 let shstrtab_str_id
= shstrtab
.add(&b
".shstrtab"[..]);
319 let shstrtab_offset
= offset
;
320 // Start with null section name.
321 let mut shstrtab_data
= vec
![0];
322 shstrtab
.write(1, &mut shstrtab_data
);
323 offset
+= shstrtab_data
.len();
324 let shstrtab_index
= section_num
;
327 // Calculate size of section headers.
328 offset
= align(offset
, pointer_align
);
329 let e_shoff
= offset
;
330 let e_shentsize
= elf
.section_header_size();
331 offset
+= section_num
* e_shentsize
;
336 .map_err(|_
| Error(String
::from("Cannot allocate buffer")))?
;
338 // Write file header.
339 let e_ident
= elf
::Ident
{
341 class
: match address_size
{
342 AddressSize
::U8
| AddressSize
::U16
| AddressSize
::U32
=> elf
::ELFCLASS32
,
343 AddressSize
::U64
=> elf
::ELFCLASS64
,
345 data
: if endian
.is_little_endian() {
350 version
: elf
::EV_CURRENT
,
351 os_abi
: elf
::ELFOSABI_NONE
,
355 let e_type
= elf
::ET_REL
;
356 let e_machine
= match self.architecture
{
357 Architecture
::Aarch64
=> elf
::EM_AARCH64
,
358 Architecture
::Arm
=> elf
::EM_ARM
,
359 Architecture
::Avr
=> elf
::EM_AVR
,
360 Architecture
::Bpf
=> elf
::EM_BPF
,
361 Architecture
::I386
=> elf
::EM_386
,
362 Architecture
::X86_64
=> elf
::EM_X86_64
,
363 Architecture
::X86_64_X32
=> elf
::EM_X86_64
,
364 Architecture
::Hexagon
=> elf
::EM_HEXAGON
,
365 Architecture
::Mips
=> elf
::EM_MIPS
,
366 Architecture
::Mips64
=> elf
::EM_MIPS
,
367 Architecture
::Msp430
=> elf
::EM_MSP430
,
368 Architecture
::PowerPc
=> elf
::EM_PPC
,
369 Architecture
::PowerPc64
=> elf
::EM_PPC64
,
370 Architecture
::Riscv32
=> elf
::EM_RISCV
,
371 Architecture
::Riscv64
=> elf
::EM_RISCV
,
372 Architecture
::S390x
=> elf
::EM_S390
,
373 Architecture
::Sparc64
=> elf
::EM_SPARCV9
,
375 return Err(Error(format
!(
376 "unimplemented architecture {:?}",
381 let e_flags
= if let FileFlags
::Elf { e_flags }
= self.flags
{
386 let e_shnum
= if section_num
>= elf
::SHN_LORESERVE
as usize {
391 let e_shstrndx
= if shstrtab_index
>= elf
::SHN_LORESERVE
as usize {
394 shstrtab_index
as u16
397 elf
.write_file_header(
403 e_version
: elf
::EV_CURRENT
.into(),
406 e_shoff
: e_shoff
as u64,
408 e_ehsize
: e_ehsize
as u16,
411 e_shentsize
: e_shentsize
as u16,
417 // Write section data.
418 for (index
, comdat
) in self.comdats
.iter().enumerate() {
419 let mut data
= Vec
::new();
420 data
.write_pod(&U32
::new(self.endian
, elf
::GRP_COMDAT
));
421 for section
in &comdat
.sections
{
422 data
.write_pod(&U32
::new(
424 section_offsets
[section
.0].index
as u32,
428 write_align(buffer
, 4);
429 debug_assert_eq
!(comdat_offsets
[index
].offset
, buffer
.len());
430 debug_assert_eq
!(comdat_offsets
[index
].len
, data
.len());
431 buffer
.write_bytes(&data
);
433 for (index
, section
) in self.sections
.iter().enumerate() {
434 let len
= section
.data
.len();
436 write_align(buffer
, section
.align
as usize);
437 debug_assert_eq
!(section_offsets
[index
].offset
, buffer
.len());
438 buffer
.write_bytes(§ion
.data
);
443 write_align(buffer
, pointer_align
);
444 debug_assert_eq
!(symtab_offset
, buffer
.len());
456 let mut symtab_shndx
= Vec
::new();
457 if need_symtab_shndx
{
458 symtab_shndx
.write_pod(&U32
::new(endian
, 0));
460 let mut write_symbol
= |index
: usize, symbol
: &Symbol
| -> Result
<()> {
461 let st_info
= if let SymbolFlags
::Elf { st_info, .. }
= symbol
.flags
{
464 let st_type
= match symbol
.kind
{
465 SymbolKind
::Null
=> elf
::STT_NOTYPE
,
466 SymbolKind
::Text
=> {
467 if symbol
.is_undefined() {
473 SymbolKind
::Data
=> {
474 if symbol
.is_undefined() {
476 } else if symbol
.is_common() {
482 SymbolKind
::Section
=> elf
::STT_SECTION
,
483 SymbolKind
::File
=> elf
::STT_FILE
,
484 SymbolKind
::Tls
=> elf
::STT_TLS
,
485 SymbolKind
::Label
=> elf
::STT_NOTYPE
,
486 SymbolKind
::Unknown
=> {
487 if symbol
.is_undefined() {
490 return Err(Error(format
!(
491 "unimplemented symbol `{}` kind {:?}",
492 symbol
.name().unwrap_or(""),
498 let st_bind
= if symbol
.weak
{
500 } else if symbol
.is_undefined() {
502 } else if symbol
.is_local() {
507 (st_bind
<< 4) + st_type
509 let st_other
= if let SymbolFlags
::Elf { st_other, .. }
= symbol
.flags
{
511 } else if symbol
.scope
== SymbolScope
::Linkage
{
516 let (st_shndx
, xindex
) = match symbol
.section
{
517 SymbolSection
::None
=> {
518 debug_assert_eq
!(symbol
.kind
, SymbolKind
::File
);
521 SymbolSection
::Undefined
=> (elf
::SHN_UNDEF
, 0),
522 SymbolSection
::Absolute
=> (elf
::SHN_ABS
, 0),
523 SymbolSection
::Common
=> (elf
::SHN_COMMON
, 0),
524 SymbolSection
::Section(id
) => {
525 let index
= section_offsets
[id
.0].index
as u32;
527 if index
>= elf
::SHN_LORESERVE
as u32 {
536 let st_name
= symbol_offsets
[index
]
538 .map(|id
| strtab
.get_offset(id
))
539 .unwrap_or(0) as u32;
547 st_value
: symbol
.value
,
548 st_size
: symbol
.size
,
551 if need_symtab_shndx
{
552 symtab_shndx
.write_pod(&U32
::new(endian
, xindex
));
556 for (index
, symbol
) in self.symbols
.iter().enumerate() {
557 if symbol
.is_local() {
558 write_symbol(index
, symbol
)?
;
561 for (index
, symbol
) in self.symbols
.iter().enumerate() {
562 if !symbol
.is_local() {
563 write_symbol(index
, symbol
)?
;
566 if need_symtab_shndx
{
567 debug_assert_eq
!(symtab_shndx_offset
, buffer
.len());
568 debug_assert_eq
!(symtab_shndx_len
, symtab_shndx
.len());
569 buffer
.write_bytes(&symtab_shndx
);
572 // Write strtab section.
573 debug_assert_eq
!(strtab_offset
, buffer
.len());
574 buffer
.write_bytes(&strtab_data
);
576 // Write relocations.
577 for (index
, section
) in self.sections
.iter().enumerate() {
578 if !section
.relocations
.is_empty() {
579 write_align(buffer
, pointer_align
);
580 debug_assert_eq
!(section_offsets
[index
].reloc_offset
, buffer
.len());
581 for reloc
in §ion
.relocations
{
582 let r_type
= match self.architecture
{
583 Architecture
::Aarch64
=> match (reloc
.kind
, reloc
.encoding
, reloc
.size
) {
584 (RelocationKind
::Absolute
, RelocationEncoding
::Generic
, 64) => {
587 (RelocationKind
::Absolute
, RelocationEncoding
::Generic
, 32) => {
590 (RelocationKind
::Absolute
, RelocationEncoding
::Generic
, 16) => {
593 (RelocationKind
::Relative
, RelocationEncoding
::Generic
, 64) => {
594 elf
::R_AARCH64_PREL64
596 (RelocationKind
::Relative
, RelocationEncoding
::Generic
, 32) => {
597 elf
::R_AARCH64_PREL32
599 (RelocationKind
::Relative
, RelocationEncoding
::Generic
, 16) => {
600 elf
::R_AARCH64_PREL16
602 (RelocationKind
::Relative
, RelocationEncoding
::AArch64Call
, 26)
603 | (RelocationKind
::PltRelative
, RelocationEncoding
::AArch64Call
, 26) => {
604 elf
::R_AARCH64_CALL26
606 (RelocationKind
::Elf(x
), _
, _
) => x
,
608 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
611 Architecture
::Arm
=> match (reloc
.kind
, reloc
.encoding
, reloc
.size
) {
612 (RelocationKind
::Absolute
, _
, 32) => elf
::R_ARM_ABS32
,
613 (RelocationKind
::Elf(x
), _
, _
) => x
,
615 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
618 Architecture
::Avr
=> match (reloc
.kind
, reloc
.encoding
, reloc
.size
) {
619 (RelocationKind
::Absolute
, _
, 32) => elf
::R_AVR_32
,
620 (RelocationKind
::Absolute
, _
, 16) => elf
::R_AVR_16
,
621 (RelocationKind
::Elf(x
), _
, _
) => x
,
623 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
626 Architecture
::Bpf
=> match (reloc
.kind
, reloc
.encoding
, reloc
.size
) {
627 (RelocationKind
::Absolute
, _
, 64) => elf
::R_BPF_64_64
,
628 (RelocationKind
::Absolute
, _
, 32) => elf
::R_BPF_64_32
,
629 (RelocationKind
::Elf(x
), _
, _
) => x
,
631 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
634 Architecture
::I386
=> match (reloc
.kind
, reloc
.size
) {
635 (RelocationKind
::Absolute
, 32) => elf
::R_386_32
,
636 (RelocationKind
::Relative
, 32) => elf
::R_386_PC32
,
637 (RelocationKind
::Got
, 32) => elf
::R_386_GOT32
,
638 (RelocationKind
::PltRelative
, 32) => elf
::R_386_PLT32
,
639 (RelocationKind
::GotBaseOffset
, 32) => elf
::R_386_GOTOFF
,
640 (RelocationKind
::GotBaseRelative
, 32) => elf
::R_386_GOTPC
,
641 (RelocationKind
::Absolute
, 16) => elf
::R_386_16
,
642 (RelocationKind
::Relative
, 16) => elf
::R_386_PC16
,
643 (RelocationKind
::Absolute
, 8) => elf
::R_386_8
,
644 (RelocationKind
::Relative
, 8) => elf
::R_386_PC8
,
645 (RelocationKind
::Elf(x
), _
) => x
,
647 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
650 Architecture
::X86_64
| Architecture
::X86_64_X32
=> {
651 match (reloc
.kind
, reloc
.encoding
, reloc
.size
) {
652 (RelocationKind
::Absolute
, RelocationEncoding
::Generic
, 64) => {
655 (RelocationKind
::Relative
, _
, 32) => elf
::R_X86_64_PC32
,
656 (RelocationKind
::Got
, _
, 32) => elf
::R_X86_64_GOT32
,
657 (RelocationKind
::PltRelative
, _
, 32) => elf
::R_X86_64_PLT32
,
658 (RelocationKind
::GotRelative
, _
, 32) => elf
::R_X86_64_GOTPCREL
,
659 (RelocationKind
::Absolute
, RelocationEncoding
::Generic
, 32) => {
662 (RelocationKind
::Absolute
, RelocationEncoding
::X86Signed
, 32) => {
665 (RelocationKind
::Absolute
, _
, 16) => elf
::R_X86_64_16
,
666 (RelocationKind
::Relative
, _
, 16) => elf
::R_X86_64_PC16
,
667 (RelocationKind
::Absolute
, _
, 8) => elf
::R_X86_64_8
,
668 (RelocationKind
::Relative
, _
, 8) => elf
::R_X86_64_PC8
,
669 (RelocationKind
::Elf(x
), _
, _
) => x
,
671 return Err(Error(format
!(
672 "unimplemented relocation {:?}",
678 Architecture
::Hexagon
=> match (reloc
.kind
, reloc
.encoding
, reloc
.size
) {
679 (RelocationKind
::Absolute
, _
, 32) => elf
::R_HEX_32
,
680 (RelocationKind
::Elf(x
), _
, _
) => x
,
682 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
685 Architecture
::Mips
| Architecture
::Mips64
=> {
686 match (reloc
.kind
, reloc
.encoding
, reloc
.size
) {
687 (RelocationKind
::Absolute
, _
, 16) => elf
::R_MIPS_16
,
688 (RelocationKind
::Absolute
, _
, 32) => elf
::R_MIPS_32
,
689 (RelocationKind
::Absolute
, _
, 64) => elf
::R_MIPS_64
,
690 (RelocationKind
::Elf(x
), _
, _
) => x
,
692 return Err(Error(format
!(
693 "unimplemented relocation {:?}",
699 Architecture
::Msp430
=> match (reloc
.kind
, reloc
.encoding
, reloc
.size
) {
700 (RelocationKind
::Absolute
, _
, 32) => elf
::R_MSP430_32
,
701 (RelocationKind
::Absolute
, _
, 16) => elf
::R_MSP430_16_BYTE
,
702 (RelocationKind
::Elf(x
), _
, _
) => x
,
704 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
707 Architecture
::PowerPc
=> match (reloc
.kind
, reloc
.encoding
, reloc
.size
) {
708 (RelocationKind
::Absolute
, _
, 32) => elf
::R_PPC_ADDR32
,
709 (RelocationKind
::Elf(x
), _
, _
) => x
,
711 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
714 Architecture
::PowerPc64
=> match (reloc
.kind
, reloc
.encoding
, reloc
.size
) {
715 (RelocationKind
::Absolute
, _
, 32) => elf
::R_PPC64_ADDR32
,
716 (RelocationKind
::Absolute
, _
, 64) => elf
::R_PPC64_ADDR64
,
717 (RelocationKind
::Elf(x
), _
, _
) => x
,
719 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
722 Architecture
::Riscv32
| Architecture
::Riscv64
=> {
723 match (reloc
.kind
, reloc
.encoding
, reloc
.size
) {
724 (RelocationKind
::Absolute
, _
, 32) => elf
::R_RISCV_32
,
725 (RelocationKind
::Absolute
, _
, 64) => elf
::R_RISCV_64
,
726 (RelocationKind
::Elf(x
), _
, _
) => x
,
728 return Err(Error(format
!(
729 "unimplemented relocation {:?}",
735 Architecture
::S390x
=> match (reloc
.kind
, reloc
.encoding
, reloc
.size
) {
736 (RelocationKind
::Absolute
, RelocationEncoding
::Generic
, 8) => {
739 (RelocationKind
::Absolute
, RelocationEncoding
::Generic
, 16) => {
742 (RelocationKind
::Absolute
, RelocationEncoding
::Generic
, 32) => {
745 (RelocationKind
::Absolute
, RelocationEncoding
::Generic
, 64) => {
748 (RelocationKind
::Relative
, RelocationEncoding
::Generic
, 16) => {
751 (RelocationKind
::Relative
, RelocationEncoding
::Generic
, 32) => {
754 (RelocationKind
::Relative
, RelocationEncoding
::Generic
, 64) => {
757 (RelocationKind
::Relative
, RelocationEncoding
::S390xDbl
, 16) => {
760 (RelocationKind
::Relative
, RelocationEncoding
::S390xDbl
, 32) => {
763 (RelocationKind
::PltRelative
, RelocationEncoding
::S390xDbl
, 16) => {
766 (RelocationKind
::PltRelative
, RelocationEncoding
::S390xDbl
, 32) => {
769 (RelocationKind
::Got
, RelocationEncoding
::Generic
, 16) => {
772 (RelocationKind
::Got
, RelocationEncoding
::Generic
, 32) => {
775 (RelocationKind
::Got
, RelocationEncoding
::Generic
, 64) => {
778 (RelocationKind
::GotRelative
, RelocationEncoding
::S390xDbl
, 32) => {
781 (RelocationKind
::GotBaseOffset
, RelocationEncoding
::Generic
, 16) => {
784 (RelocationKind
::GotBaseOffset
, RelocationEncoding
::Generic
, 32) => {
787 (RelocationKind
::GotBaseOffset
, RelocationEncoding
::Generic
, 64) => {
790 (RelocationKind
::GotBaseRelative
, RelocationEncoding
::Generic
, 64) => {
793 (RelocationKind
::GotBaseRelative
, RelocationEncoding
::S390xDbl
, 32) => {
796 (RelocationKind
::Elf(x
), _
, _
) => x
,
798 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
801 Architecture
::Sparc64
=> match (reloc
.kind
, reloc
.encoding
, reloc
.size
) {
802 // TODO: use R_SPARC_32/R_SPARC_64 if aligned.
803 (RelocationKind
::Absolute
, _
, 32) => elf
::R_SPARC_UA32
,
804 (RelocationKind
::Absolute
, _
, 64) => elf
::R_SPARC_UA64
,
805 (RelocationKind
::Elf(x
), _
, _
) => x
,
807 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
811 if let RelocationKind
::Elf(x
) = reloc
.kind
{
814 return Err(Error(format
!("unimplemented relocation {:?}", reloc
)));
818 let r_sym
= symbol_offsets
[reloc
.symbol
.0].index
as u32;
824 r_offset
: reloc
.offset
,
827 r_addend
: reloc
.addend
,
834 // Write shstrtab section.
835 debug_assert_eq
!(shstrtab_offset
, buffer
.len());
836 buffer
.write_bytes(&shstrtab_data
);
838 // Write section headers.
839 write_align(buffer
, pointer_align
);
840 debug_assert_eq
!(e_shoff
, buffer
.len());
841 elf
.write_section_header(
849 sh_size
: if section_num
>= elf
::SHN_LORESERVE
as usize {
854 sh_link
: if shstrtab_index
>= elf
::SHN_LORESERVE
as usize {
855 shstrtab_index
as u32
859 // TODO: e_phnum overflow
865 for (index
, comdat
) in self.comdats
.iter().enumerate() {
866 let sh_name
= comdat_offsets
[index
]
868 .map(|id
| shstrtab
.get_offset(id
))
869 .unwrap_or(0) as u32;
870 elf
.write_section_header(
874 sh_type
: elf
::SHT_GROUP
,
877 sh_offset
: comdat_offsets
[index
].offset
as u64,
878 sh_size
: comdat_offsets
[index
].len
as u64,
879 sh_link
: symtab_index
as u32,
880 sh_info
: symbol_offsets
[comdat
.symbol
.0].index
as u32,
886 for (index
, section
) in self.sections
.iter().enumerate() {
887 let sh_type
= match section
.kind
{
888 SectionKind
::UninitializedData
| SectionKind
::UninitializedTls
=> elf
::SHT_NOBITS
,
889 SectionKind
::Note
=> elf
::SHT_NOTE
,
890 SectionKind
::Elf(sh_type
) => sh_type
,
891 _
=> elf
::SHT_PROGBITS
,
893 let sh_flags
= if let SectionFlags
::Elf { sh_flags }
= section
.flags
{
897 SectionKind
::Text
=> elf
::SHF_ALLOC
| elf
::SHF_EXECINSTR
,
898 SectionKind
::Data
=> elf
::SHF_ALLOC
| elf
::SHF_WRITE
,
899 SectionKind
::Tls
=> elf
::SHF_ALLOC
| elf
::SHF_WRITE
| elf
::SHF_TLS
,
900 SectionKind
::UninitializedData
=> elf
::SHF_ALLOC
| elf
::SHF_WRITE
,
901 SectionKind
::UninitializedTls
=> elf
::SHF_ALLOC
| elf
::SHF_WRITE
| elf
::SHF_TLS
,
902 SectionKind
::ReadOnlyData
=> elf
::SHF_ALLOC
,
903 SectionKind
::ReadOnlyString
=> {
904 elf
::SHF_ALLOC
| elf
::SHF_STRINGS
| elf
::SHF_MERGE
906 SectionKind
::OtherString
=> elf
::SHF_STRINGS
| elf
::SHF_MERGE
,
909 | SectionKind
::Metadata
910 | SectionKind
::Linker
912 | SectionKind
::Elf(_
) => 0,
913 SectionKind
::Unknown
| SectionKind
::Common
| SectionKind
::TlsVariables
=> {
914 return Err(Error(format
!(
915 "unimplemented section `{}` kind {:?}",
916 section
.name().unwrap_or(""),
923 // TODO: not sure if this is correct, maybe user should determine this
924 let sh_entsize
= match section
.kind
{
925 SectionKind
::ReadOnlyString
| SectionKind
::OtherString
=> 1,
928 let sh_name
= section_offsets
[index
]
930 .map(|id
| shstrtab
.get_offset(id
))
931 .unwrap_or(0) as u32;
932 elf
.write_section_header(
939 sh_offset
: section_offsets
[index
].offset
as u64,
940 sh_size
: section
.size
,
943 sh_addralign
: section
.align
,
948 if !section
.relocations
.is_empty() {
949 let sh_name
= section_offsets
[index
]
951 .map(|id
| shstrtab
.get_offset(id
))
953 elf
.write_section_header(
956 sh_name
: sh_name
as u32,
957 sh_type
: if is_rela { elf::SHT_RELA }
else { elf::SHT_REL }
,
958 sh_flags
: elf
::SHF_INFO_LINK
.into(),
960 sh_offset
: section_offsets
[index
].reloc_offset
as u64,
961 sh_size
: section_offsets
[index
].reloc_len
as u64,
962 sh_link
: symtab_index
as u32,
963 sh_info
: section_offsets
[index
].index
as u32,
964 sh_addralign
: pointer_align
as u64,
965 sh_entsize
: elf
.rel_size(is_rela
) as u64,
971 // Write symtab section header.
972 elf
.write_section_header(
975 sh_name
: shstrtab
.get_offset(symtab_str_id
) as u32,
976 sh_type
: elf
::SHT_SYMTAB
,
979 sh_offset
: symtab_offset
as u64,
980 sh_size
: symtab_len
as u64,
981 sh_link
: strtab_index
as u32,
982 sh_info
: symtab_count_local
as u32,
983 sh_addralign
: pointer_align
as u64,
984 sh_entsize
: elf
.symbol_size() as u64,
988 // Write symtab_shndx section header.
989 if need_symtab_shndx
{
990 elf
.write_section_header(
993 sh_name
: shstrtab
.get_offset(symtab_shndx_str_id
.unwrap()) as u32,
994 sh_type
: elf
::SHT_SYMTAB_SHNDX
,
997 sh_offset
: symtab_shndx_offset
as u64,
998 sh_size
: symtab_shndx_len
as u64,
999 sh_link
: symtab_index
as u32,
1000 sh_info
: symtab_count_local
as u32,
1007 // Write strtab section header.
1008 elf
.write_section_header(
1011 sh_name
: shstrtab
.get_offset(strtab_str_id
) as u32,
1012 sh_type
: elf
::SHT_STRTAB
,
1015 sh_offset
: strtab_offset
as u64,
1016 sh_size
: strtab_data
.len() as u64,
1024 // Write shstrtab section header.
1025 elf
.write_section_header(
1028 sh_name
: shstrtab
.get_offset(shstrtab_str_id
) as u32,
1029 sh_type
: elf
::SHT_STRTAB
,
1032 sh_offset
: shstrtab_offset
as u64,
1033 sh_size
: shstrtab_data
.len() as u64,
1041 debug_assert_eq
!(offset
, buffer
.len());
1047 /// Native endian version of `FileHeader64`.
1049 e_ident
: elf
::Ident
,
1065 /// Native endian version of `SectionHeader64`.
1066 struct SectionHeader
{
1079 /// Native endian version of `Sym64`.
1089 /// Unified native endian version of `Rel*`.
1098 fn file_header_size(&self) -> usize;
1099 fn section_header_size(&self) -> usize;
1100 fn symbol_size(&self) -> usize;
1101 fn rel_size(&self, is_rela
: bool
) -> usize;
1102 fn write_file_header(&self, buffer
: &mut dyn WritableBuffer
, section
: FileHeader
);
1103 fn write_section_header(&self, buffer
: &mut dyn WritableBuffer
, section
: SectionHeader
);
1104 fn write_symbol(&self, buffer
: &mut dyn WritableBuffer
, symbol
: Sym
);
1107 buffer
: &mut dyn WritableBuffer
,
1118 impl<E
: Endian
> Elf
for Elf32
<E
> {
1119 fn file_header_size(&self) -> usize {
1120 mem
::size_of
::<elf
::FileHeader32
<E
>>()
1123 fn section_header_size(&self) -> usize {
1124 mem
::size_of
::<elf
::SectionHeader32
<E
>>()
1127 fn symbol_size(&self) -> usize {
1128 mem
::size_of
::<elf
::Sym32
<E
>>()
1131 fn rel_size(&self, is_rela
: bool
) -> usize {
1133 mem
::size_of
::<elf
::Rela32
<E
>>()
1135 mem
::size_of
::<elf
::Rel32
<E
>>()
1139 fn write_file_header(&self, buffer
: &mut dyn WritableBuffer
, file
: FileHeader
) {
1140 let endian
= self.endian
;
1141 let file
= elf
::FileHeader32
{
1142 e_ident
: file
.e_ident
,
1143 e_type
: U16
::new(endian
, file
.e_type
),
1144 e_machine
: U16
::new(endian
, file
.e_machine
),
1145 e_version
: U32
::new(endian
, file
.e_version
),
1146 e_entry
: U32
::new(endian
, file
.e_entry
as u32),
1147 e_phoff
: U32
::new(endian
, file
.e_phoff
as u32),
1148 e_shoff
: U32
::new(endian
, file
.e_shoff
as u32),
1149 e_flags
: U32
::new(endian
, file
.e_flags
),
1150 e_ehsize
: U16
::new(endian
, file
.e_ehsize
),
1151 e_phentsize
: U16
::new(endian
, file
.e_phentsize
),
1152 e_phnum
: U16
::new(endian
, file
.e_phnum
),
1153 e_shentsize
: U16
::new(endian
, file
.e_shentsize
),
1154 e_shnum
: U16
::new(endian
, file
.e_shnum
),
1155 e_shstrndx
: U16
::new(endian
, file
.e_shstrndx
),
1157 buffer
.write(&file
);
1160 fn write_section_header(&self, buffer
: &mut dyn WritableBuffer
, section
: SectionHeader
) {
1161 let endian
= self.endian
;
1162 let section
= elf
::SectionHeader32
{
1163 sh_name
: U32
::new(endian
, section
.sh_name
),
1164 sh_type
: U32
::new(endian
, section
.sh_type
),
1165 sh_flags
: U32
::new(endian
, section
.sh_flags
as u32),
1166 sh_addr
: U32
::new(endian
, section
.sh_addr
as u32),
1167 sh_offset
: U32
::new(endian
, section
.sh_offset
as u32),
1168 sh_size
: U32
::new(endian
, section
.sh_size
as u32),
1169 sh_link
: U32
::new(endian
, section
.sh_link
),
1170 sh_info
: U32
::new(endian
, section
.sh_info
),
1171 sh_addralign
: U32
::new(endian
, section
.sh_addralign
as u32),
1172 sh_entsize
: U32
::new(endian
, section
.sh_entsize
as u32),
1174 buffer
.write(§ion
);
1177 fn write_symbol(&self, buffer
: &mut dyn WritableBuffer
, symbol
: Sym
) {
1178 let endian
= self.endian
;
1179 let symbol
= elf
::Sym32
{
1180 st_name
: U32
::new(endian
, symbol
.st_name
),
1181 st_info
: symbol
.st_info
,
1182 st_other
: symbol
.st_other
,
1183 st_shndx
: U16
::new(endian
, symbol
.st_shndx
),
1184 st_value
: U32
::new(endian
, symbol
.st_value
as u32),
1185 st_size
: U32
::new(endian
, symbol
.st_size
as u32),
1187 buffer
.write(&symbol
);
1192 buffer
: &mut dyn WritableBuffer
,
1197 let endian
= self.endian
;
1199 let rel
= elf
::Rela32
{
1200 r_offset
: U32
::new(endian
, rel
.r_offset
as u32),
1201 r_info
: elf
::Rel32
::r_info(endian
, rel
.r_sym
, rel
.r_type
as u8),
1202 r_addend
: I32
::new(endian
, rel
.r_addend
as i32),
1206 let rel
= elf
::Rel32
{
1207 r_offset
: U32
::new(endian
, rel
.r_offset
as u32),
1208 r_info
: elf
::Rel32
::r_info(endian
, rel
.r_sym
, rel
.r_type
as u8),
1219 impl<E
: Endian
> Elf
for Elf64
<E
> {
1220 fn file_header_size(&self) -> usize {
1221 mem
::size_of
::<elf
::FileHeader64
<E
>>()
1224 fn section_header_size(&self) -> usize {
1225 mem
::size_of
::<elf
::SectionHeader64
<E
>>()
1228 fn symbol_size(&self) -> usize {
1229 mem
::size_of
::<elf
::Sym64
<E
>>()
1232 fn rel_size(&self, is_rela
: bool
) -> usize {
1234 mem
::size_of
::<elf
::Rela64
<E
>>()
1236 mem
::size_of
::<elf
::Rel64
<E
>>()
1240 fn write_file_header(&self, buffer
: &mut dyn WritableBuffer
, file
: FileHeader
) {
1241 let endian
= self.endian
;
1242 let file
= elf
::FileHeader64
{
1243 e_ident
: file
.e_ident
,
1244 e_type
: U16
::new(endian
, file
.e_type
),
1245 e_machine
: U16
::new(endian
, file
.e_machine
),
1246 e_version
: U32
::new(endian
, file
.e_version
),
1247 e_entry
: U64
::new(endian
, file
.e_entry
),
1248 e_phoff
: U64
::new(endian
, file
.e_phoff
),
1249 e_shoff
: U64
::new(endian
, file
.e_shoff
),
1250 e_flags
: U32
::new(endian
, file
.e_flags
),
1251 e_ehsize
: U16
::new(endian
, file
.e_ehsize
),
1252 e_phentsize
: U16
::new(endian
, file
.e_phentsize
),
1253 e_phnum
: U16
::new(endian
, file
.e_phnum
),
1254 e_shentsize
: U16
::new(endian
, file
.e_shentsize
),
1255 e_shnum
: U16
::new(endian
, file
.e_shnum
),
1256 e_shstrndx
: U16
::new(endian
, file
.e_shstrndx
),
1261 fn write_section_header(&self, buffer
: &mut dyn WritableBuffer
, section
: SectionHeader
) {
1262 let endian
= self.endian
;
1263 let section
= elf
::SectionHeader64
{
1264 sh_name
: U32
::new(endian
, section
.sh_name
),
1265 sh_type
: U32
::new(endian
, section
.sh_type
),
1266 sh_flags
: U64
::new(endian
, section
.sh_flags
),
1267 sh_addr
: U64
::new(endian
, section
.sh_addr
),
1268 sh_offset
: U64
::new(endian
, section
.sh_offset
),
1269 sh_size
: U64
::new(endian
, section
.sh_size
),
1270 sh_link
: U32
::new(endian
, section
.sh_link
),
1271 sh_info
: U32
::new(endian
, section
.sh_info
),
1272 sh_addralign
: U64
::new(endian
, section
.sh_addralign
),
1273 sh_entsize
: U64
::new(endian
, section
.sh_entsize
),
1275 buffer
.write(§ion
);
1278 fn write_symbol(&self, buffer
: &mut dyn WritableBuffer
, symbol
: Sym
) {
1279 let endian
= self.endian
;
1280 let symbol
= elf
::Sym64
{
1281 st_name
: U32
::new(endian
, symbol
.st_name
),
1282 st_info
: symbol
.st_info
,
1283 st_other
: symbol
.st_other
,
1284 st_shndx
: U16
::new(endian
, symbol
.st_shndx
),
1285 st_value
: U64
::new(endian
, symbol
.st_value
),
1286 st_size
: U64
::new(endian
, symbol
.st_size
),
1288 buffer
.write(&symbol
);
1293 buffer
: &mut dyn WritableBuffer
,
1298 let endian
= self.endian
;
1300 let rel
= elf
::Rela64
{
1301 r_offset
: U64
::new(endian
, rel
.r_offset
),
1302 r_info
: elf
::Rela64
::r_info(endian
, is_mips64el
, rel
.r_sym
, rel
.r_type
),
1303 r_addend
: I64
::new(endian
, rel
.r_addend
),
1307 let rel
= elf
::Rel64
{
1308 r_offset
: U64
::new(endian
, rel
.r_offset
),
1309 r_info
: elf
::Rel64
::r_info(endian
, rel
.r_sym
, rel
.r_type
),