]> git.proxmox.com Git - rustc.git/blame - vendor/object-0.31.1/src/write/elf/object.rs
New upstream version 1.73.0+dfsg1
[rustc.git] / vendor / object-0.31.1 / src / write / elf / object.rs
CommitLineData
9c376795
FG
1use alloc::vec::Vec;
2
9c376795
FG
3use crate::write::elf::writer::*;
4use crate::write::string::StringId;
5use crate::write::*;
6use crate::AddressSize;
fe692bf9 7use crate::{elf, pod};
9c376795
FG
8
9#[derive(Clone, Copy)]
10struct ComdatOffsets {
11 offset: usize,
12 str_id: StringId,
13}
14
15#[derive(Clone, Copy)]
16struct SectionOffsets {
17 index: SectionIndex,
18 offset: usize,
19 str_id: StringId,
20 reloc_offset: usize,
21 reloc_str_id: Option<StringId>,
22}
23
24#[derive(Default, Clone, Copy)]
25struct SymbolOffsets {
26 index: SymbolIndex,
27 str_id: Option<StringId>,
28}
29
fe692bf9
FG
30// Public methods.
31impl<'a> Object<'a> {
32 /// Add a property with a u32 value to the ELF ".note.gnu.property" section.
33 ///
34 /// Requires `feature = "elf"`.
35 pub fn add_elf_gnu_property_u32(&mut self, property: u32, value: u32) {
36 if self.format != BinaryFormat::Elf {
37 return;
38 }
39
40 let align = if self.elf_is_64() { 8 } else { 4 };
41 let mut data = Vec::with_capacity(32);
42 let n_name = b"GNU\0";
43 data.extend_from_slice(pod::bytes_of(&elf::NoteHeader32 {
44 n_namesz: U32::new(self.endian, n_name.len() as u32),
45 n_descsz: U32::new(self.endian, util::align(3 * 4, align) as u32),
46 n_type: U32::new(self.endian, elf::NT_GNU_PROPERTY_TYPE_0),
47 }));
48 data.extend_from_slice(n_name);
49 // This happens to already be aligned correctly.
50 debug_assert_eq!(util::align(data.len(), align), data.len());
51 data.extend_from_slice(pod::bytes_of(&U32::new(self.endian, property)));
52 // Value size
53 data.extend_from_slice(pod::bytes_of(&U32::new(self.endian, 4)));
54 data.extend_from_slice(pod::bytes_of(&U32::new(self.endian, value)));
55 util::write_align(&mut data, align);
56
57 let section = self.section_id(StandardSection::GnuProperty);
58 self.append_section_data(section, &data, align as u64);
59 }
60}
61
62// Private methods.
9c376795
FG
63impl<'a> Object<'a> {
64 pub(crate) fn elf_section_info(
65 &self,
66 section: StandardSection,
fe692bf9 67 ) -> (&'static [u8], &'static [u8], SectionKind, SectionFlags) {
9c376795 68 match section {
fe692bf9
FG
69 StandardSection::Text => (&[], &b".text"[..], SectionKind::Text, SectionFlags::None),
70 StandardSection::Data => (&[], &b".data"[..], SectionKind::Data, SectionFlags::None),
71 StandardSection::ReadOnlyData | StandardSection::ReadOnlyString => (
72 &[],
73 &b".rodata"[..],
74 SectionKind::ReadOnlyData,
75 SectionFlags::None,
76 ),
77 StandardSection::ReadOnlyDataWithRel => (
78 &[],
79 b".data.rel.ro",
80 SectionKind::ReadOnlyDataWithRel,
81 SectionFlags::None,
82 ),
83 StandardSection::UninitializedData => (
84 &[],
85 &b".bss"[..],
86 SectionKind::UninitializedData,
87 SectionFlags::None,
88 ),
89 StandardSection::Tls => (&[], &b".tdata"[..], SectionKind::Tls, SectionFlags::None),
90 StandardSection::UninitializedTls => (
91 &[],
92 &b".tbss"[..],
93 SectionKind::UninitializedTls,
94 SectionFlags::None,
95 ),
9c376795
FG
96 StandardSection::TlsVariables => {
97 // Unsupported section.
fe692bf9 98 (&[], &[], SectionKind::TlsVariables, SectionFlags::None)
9c376795
FG
99 }
100 StandardSection::Common => {
101 // Unsupported section.
fe692bf9 102 (&[], &[], SectionKind::Common, SectionFlags::None)
9c376795 103 }
fe692bf9
FG
104 StandardSection::GnuProperty => (
105 &[],
106 &b".note.gnu.property"[..],
107 SectionKind::Note,
108 SectionFlags::Elf {
109 sh_flags: u64::from(elf::SHF_ALLOC),
110 },
111 ),
9c376795
FG
112 }
113 }
114
115 pub(crate) fn elf_subsection_name(&self, section: &[u8], value: &[u8]) -> Vec<u8> {
116 let mut name = section.to_vec();
117 name.push(b'.');
118 name.extend_from_slice(value);
119 name
120 }
121
122 fn elf_has_relocation_addend(&self) -> Result<bool> {
123 Ok(match self.architecture {
124 Architecture::Aarch64 => true,
49aad941 125 Architecture::Aarch64_Ilp32 => true,
9c376795
FG
126 Architecture::Arm => false,
127 Architecture::Avr => true,
128 Architecture::Bpf => false,
129 Architecture::I386 => false,
130 Architecture::X86_64 => true,
131 Architecture::X86_64_X32 => true,
132 Architecture::Hexagon => true,
133 Architecture::LoongArch64 => true,
134 Architecture::Mips => false,
135 Architecture::Mips64 => true,
136 Architecture::Msp430 => true,
137 Architecture::PowerPc => true,
138 Architecture::PowerPc64 => true,
139 Architecture::Riscv64 => true,
140 Architecture::Riscv32 => true,
141 Architecture::S390x => true,
49aad941 142 Architecture::Sbf => false,
9c376795 143 Architecture::Sparc64 => true,
49aad941 144 Architecture::Xtensa => true,
9c376795
FG
145 _ => {
146 return Err(Error(format!(
147 "unimplemented architecture {:?}",
148 self.architecture
149 )));
150 }
151 })
152 }
153
154 pub(crate) fn elf_fixup_relocation(&mut self, mut relocation: &mut Relocation) -> Result<i64> {
155 // Return true if we should use a section symbol to avoid preemption.
156 fn want_section_symbol(relocation: &Relocation, symbol: &Symbol) -> bool {
157 if symbol.scope != SymbolScope::Dynamic {
158 // Only dynamic symbols can be preemptible.
159 return false;
160 }
161 match symbol.kind {
162 SymbolKind::Text | SymbolKind::Data => {}
163 _ => return false,
164 }
165 match relocation.kind {
166 // Anything using GOT or PLT is preemptible.
167 // We also require that `Other` relocations must already be correct.
168 RelocationKind::Got
169 | RelocationKind::GotRelative
170 | RelocationKind::GotBaseRelative
171 | RelocationKind::PltRelative
172 | RelocationKind::Elf(_) => return false,
173 // Absolute relocations are preemptible for non-local data.
174 // TODO: not sure if this rule is exactly correct
175 // This rule was added to handle global data references in debuginfo.
176 // Maybe this should be a new relocation kind so that the caller can decide.
177 RelocationKind::Absolute => {
178 if symbol.kind == SymbolKind::Data {
179 return false;
180 }
181 }
182 _ => {}
183 }
184 true
185 }
186
187 // Use section symbols for relocations where required to avoid preemption.
188 // Otherwise, the linker will fail with:
189 // relocation R_X86_64_PC32 against symbol `SomeSymbolName' can not be used when
190 // making a shared object; recompile with -fPIC
191 let symbol = &self.symbols[relocation.symbol.0];
192 if want_section_symbol(relocation, symbol) {
193 if let Some(section) = symbol.section.id() {
194 relocation.addend += symbol.value as i64;
195 relocation.symbol = self.section_symbol(section);
196 }
197 }
198
199 // Determine whether the addend is stored in the relocation or the data.
200 if self.elf_has_relocation_addend()? {
201 Ok(0)
202 } else {
203 let constant = relocation.addend;
204 relocation.addend = 0;
205 Ok(constant)
206 }
207 }
208
fe692bf9
FG
209 pub(crate) fn elf_is_64(&self) -> bool {
210 match self.architecture.address_size().unwrap() {
211 AddressSize::U8 | AddressSize::U16 | AddressSize::U32 => false,
212 AddressSize::U64 => true,
213 }
214 }
215
9c376795
FG
216 pub(crate) fn elf_write(&self, buffer: &mut dyn WritableBuffer) -> Result<()> {
217 // Create reloc section header names so we can reference them.
218 let is_rela = self.elf_has_relocation_addend()?;
219 let reloc_names: Vec<_> = self
220 .sections
221 .iter()
222 .map(|section| {
223 let mut reloc_name = Vec::with_capacity(
224 if is_rela { ".rela".len() } else { ".rel".len() } + section.name.len(),
225 );
226 if !section.relocations.is_empty() {
227 reloc_name.extend_from_slice(if is_rela {
228 &b".rela"[..]
229 } else {
230 &b".rel"[..]
231 });
232 reloc_name.extend_from_slice(&section.name);
233 }
234 reloc_name
235 })
236 .collect();
237
238 // Start calculating offsets of everything.
fe692bf9 239 let mut writer = Writer::new(self.endian, self.elf_is_64(), buffer);
9c376795
FG
240 writer.reserve_file_header();
241
242 // Calculate size of section data.
243 let mut comdat_offsets = Vec::with_capacity(self.comdats.len());
244 for comdat in &self.comdats {
245 if comdat.kind != ComdatKind::Any {
246 return Err(Error(format!(
247 "unsupported COMDAT symbol `{}` kind {:?}",
248 self.symbols[comdat.symbol.0].name().unwrap_or(""),
249 comdat.kind
250 )));
251 }
252
253 writer.reserve_section_index();
254 let offset = writer.reserve_comdat(comdat.sections.len());
255 let str_id = writer.add_section_name(b".group");
256 comdat_offsets.push(ComdatOffsets { offset, str_id });
257 }
258 let mut section_offsets = Vec::with_capacity(self.sections.len());
259 for (section, reloc_name) in self.sections.iter().zip(reloc_names.iter()) {
260 let index = writer.reserve_section_index();
261 let offset = writer.reserve(section.data.len(), section.align as usize);
262 let str_id = writer.add_section_name(&section.name);
263 let mut reloc_str_id = None;
264 if !section.relocations.is_empty() {
265 writer.reserve_section_index();
266 reloc_str_id = Some(writer.add_section_name(reloc_name));
267 }
268 section_offsets.push(SectionOffsets {
269 index,
270 offset,
271 str_id,
272 // Relocation data is reserved later.
273 reloc_offset: 0,
274 reloc_str_id,
275 });
276 }
277
278 // Calculate index of symbols and add symbol strings to strtab.
279 let mut symbol_offsets = vec![SymbolOffsets::default(); self.symbols.len()];
280 writer.reserve_null_symbol_index();
281 // Local symbols must come before global.
282 for (index, symbol) in self.symbols.iter().enumerate() {
283 if symbol.is_local() {
284 let section_index = symbol.section.id().map(|s| section_offsets[s.0].index);
285 symbol_offsets[index].index = writer.reserve_symbol_index(section_index);
286 }
287 }
288 let symtab_num_local = writer.symbol_count();
289 for (index, symbol) in self.symbols.iter().enumerate() {
290 if !symbol.is_local() {
291 let section_index = symbol.section.id().map(|s| section_offsets[s.0].index);
292 symbol_offsets[index].index = writer.reserve_symbol_index(section_index);
293 }
294 }
295 for (index, symbol) in self.symbols.iter().enumerate() {
296 if symbol.kind != SymbolKind::Section && !symbol.name.is_empty() {
297 symbol_offsets[index].str_id = Some(writer.add_string(&symbol.name));
298 }
299 }
300
301 // Calculate size of symbols.
302 writer.reserve_symtab_section_index();
303 writer.reserve_symtab();
304 if writer.symtab_shndx_needed() {
305 writer.reserve_symtab_shndx_section_index();
306 }
307 writer.reserve_symtab_shndx();
308 writer.reserve_strtab_section_index();
309 writer.reserve_strtab();
310
311 // Calculate size of relocations.
312 for (index, section) in self.sections.iter().enumerate() {
313 let count = section.relocations.len();
314 if count != 0 {
315 section_offsets[index].reloc_offset = writer.reserve_relocations(count, is_rela);
316 }
317 }
318
319 // Calculate size of section headers.
320 writer.reserve_shstrtab_section_index();
321 writer.reserve_shstrtab();
322 writer.reserve_section_headers();
323
324 // Start writing.
325 let e_type = elf::ET_REL;
326 let e_machine = match self.architecture {
327 Architecture::Aarch64 => elf::EM_AARCH64,
49aad941 328 Architecture::Aarch64_Ilp32 => elf::EM_AARCH64,
9c376795
FG
329 Architecture::Arm => elf::EM_ARM,
330 Architecture::Avr => elf::EM_AVR,
331 Architecture::Bpf => elf::EM_BPF,
332 Architecture::I386 => elf::EM_386,
333 Architecture::X86_64 => elf::EM_X86_64,
334 Architecture::X86_64_X32 => elf::EM_X86_64,
335 Architecture::Hexagon => elf::EM_HEXAGON,
336 Architecture::LoongArch64 => elf::EM_LOONGARCH,
337 Architecture::Mips => elf::EM_MIPS,
338 Architecture::Mips64 => elf::EM_MIPS,
339 Architecture::Msp430 => elf::EM_MSP430,
340 Architecture::PowerPc => elf::EM_PPC,
341 Architecture::PowerPc64 => elf::EM_PPC64,
342 Architecture::Riscv32 => elf::EM_RISCV,
343 Architecture::Riscv64 => elf::EM_RISCV,
344 Architecture::S390x => elf::EM_S390,
49aad941 345 Architecture::Sbf => elf::EM_SBF,
9c376795 346 Architecture::Sparc64 => elf::EM_SPARCV9,
49aad941 347 Architecture::Xtensa => elf::EM_XTENSA,
9c376795
FG
348 _ => {
349 return Err(Error(format!(
350 "unimplemented architecture {:?}",
351 self.architecture
352 )));
353 }
354 };
355 let (os_abi, abi_version, e_flags) = if let FileFlags::Elf {
356 os_abi,
357 abi_version,
358 e_flags,
359 } = self.flags
360 {
361 (os_abi, abi_version, e_flags)
362 } else {
363 (elf::ELFOSABI_NONE, 0, 0)
364 };
365 writer.write_file_header(&FileHeader {
366 os_abi,
367 abi_version,
368 e_type,
369 e_machine,
370 e_entry: 0,
371 e_flags,
372 })?;
373
374 // Write section data.
375 for comdat in &self.comdats {
376 writer.write_comdat_header();
377 for section in &comdat.sections {
378 writer.write_comdat_entry(section_offsets[section.0].index);
379 }
380 }
381 for (index, section) in self.sections.iter().enumerate() {
fe692bf9
FG
382 writer.write_align(section.align as usize);
383 debug_assert_eq!(section_offsets[index].offset, writer.len());
384 writer.write(&section.data);
9c376795
FG
385 }
386
387 // Write symbols.
388 writer.write_null_symbol();
389 let mut write_symbol = |index: usize, symbol: &Symbol| -> Result<()> {
390 let st_info = if let SymbolFlags::Elf { st_info, .. } = symbol.flags {
391 st_info
392 } else {
393 let st_type = match symbol.kind {
394 SymbolKind::Null => elf::STT_NOTYPE,
395 SymbolKind::Text => {
396 if symbol.is_undefined() {
397 elf::STT_NOTYPE
398 } else {
399 elf::STT_FUNC
400 }
401 }
402 SymbolKind::Data => {
403 if symbol.is_undefined() {
404 elf::STT_NOTYPE
405 } else if symbol.is_common() {
406 elf::STT_COMMON
407 } else {
408 elf::STT_OBJECT
409 }
410 }
411 SymbolKind::Section => elf::STT_SECTION,
412 SymbolKind::File => elf::STT_FILE,
413 SymbolKind::Tls => elf::STT_TLS,
414 SymbolKind::Label => elf::STT_NOTYPE,
415 SymbolKind::Unknown => {
416 if symbol.is_undefined() {
417 elf::STT_NOTYPE
418 } else {
419 return Err(Error(format!(
420 "unimplemented symbol `{}` kind {:?}",
421 symbol.name().unwrap_or(""),
422 symbol.kind
423 )));
424 }
425 }
426 };
427 let st_bind = if symbol.weak {
428 elf::STB_WEAK
429 } else if symbol.is_undefined() {
430 elf::STB_GLOBAL
431 } else if symbol.is_local() {
432 elf::STB_LOCAL
433 } else {
434 elf::STB_GLOBAL
435 };
436 (st_bind << 4) + st_type
437 };
438 let st_other = if let SymbolFlags::Elf { st_other, .. } = symbol.flags {
439 st_other
440 } else if symbol.scope == SymbolScope::Linkage {
441 elf::STV_HIDDEN
442 } else {
443 elf::STV_DEFAULT
444 };
445 let (st_shndx, section) = match symbol.section {
446 SymbolSection::None => {
447 debug_assert_eq!(symbol.kind, SymbolKind::File);
448 (elf::SHN_ABS, None)
449 }
450 SymbolSection::Undefined => (elf::SHN_UNDEF, None),
451 SymbolSection::Absolute => (elf::SHN_ABS, None),
452 SymbolSection::Common => (elf::SHN_COMMON, None),
453 SymbolSection::Section(id) => (0, Some(section_offsets[id.0].index)),
454 };
455 writer.write_symbol(&Sym {
456 name: symbol_offsets[index].str_id,
457 section,
458 st_info,
459 st_other,
460 st_shndx,
461 st_value: symbol.value,
462 st_size: symbol.size,
463 });
464 Ok(())
465 };
466 for (index, symbol) in self.symbols.iter().enumerate() {
467 if symbol.is_local() {
468 write_symbol(index, symbol)?;
469 }
470 }
471 for (index, symbol) in self.symbols.iter().enumerate() {
472 if !symbol.is_local() {
473 write_symbol(index, symbol)?;
474 }
475 }
476 writer.write_symtab_shndx();
477 writer.write_strtab();
478
479 // Write relocations.
480 for (index, section) in self.sections.iter().enumerate() {
481 if !section.relocations.is_empty() {
482 writer.write_align_relocation();
483 debug_assert_eq!(section_offsets[index].reloc_offset, writer.len());
484 for reloc in &section.relocations {
485 let r_type = match self.architecture {
486 Architecture::Aarch64 => match (reloc.kind, reloc.encoding, reloc.size) {
487 (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => {
488 elf::R_AARCH64_ABS64
489 }
490 (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => {
491 elf::R_AARCH64_ABS32
492 }
493 (RelocationKind::Absolute, RelocationEncoding::Generic, 16) => {
494 elf::R_AARCH64_ABS16
495 }
496 (RelocationKind::Relative, RelocationEncoding::Generic, 64) => {
497 elf::R_AARCH64_PREL64
498 }
499 (RelocationKind::Relative, RelocationEncoding::Generic, 32) => {
500 elf::R_AARCH64_PREL32
501 }
502 (RelocationKind::Relative, RelocationEncoding::Generic, 16) => {
503 elf::R_AARCH64_PREL16
504 }
505 (RelocationKind::Relative, RelocationEncoding::AArch64Call, 26)
506 | (RelocationKind::PltRelative, RelocationEncoding::AArch64Call, 26) => {
507 elf::R_AARCH64_CALL26
508 }
509 (RelocationKind::Elf(x), _, _) => x,
510 _ => {
511 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
512 }
513 },
49aad941
FG
514 Architecture::Aarch64_Ilp32 => {
515 match (reloc.kind, reloc.encoding, reloc.size) {
516 (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => {
517 elf::R_AARCH64_P32_ABS32
518 }
519 (RelocationKind::Elf(x), _, _) => x,
520 _ => {
521 return Err(Error(format!(
522 "unimplemented relocation {:?}",
523 reloc
524 )));
525 }
526 }
527 }
9c376795
FG
528 Architecture::Arm => match (reloc.kind, reloc.encoding, reloc.size) {
529 (RelocationKind::Absolute, _, 32) => elf::R_ARM_ABS32,
530 (RelocationKind::Elf(x), _, _) => x,
531 _ => {
532 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
533 }
534 },
535 Architecture::Avr => match (reloc.kind, reloc.encoding, reloc.size) {
536 (RelocationKind::Absolute, _, 32) => elf::R_AVR_32,
537 (RelocationKind::Absolute, _, 16) => elf::R_AVR_16,
538 (RelocationKind::Elf(x), _, _) => x,
539 _ => {
540 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
541 }
542 },
543 Architecture::Bpf => match (reloc.kind, reloc.encoding, reloc.size) {
544 (RelocationKind::Absolute, _, 64) => elf::R_BPF_64_64,
545 (RelocationKind::Absolute, _, 32) => elf::R_BPF_64_32,
546 (RelocationKind::Elf(x), _, _) => x,
547 _ => {
548 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
549 }
550 },
551 Architecture::I386 => match (reloc.kind, reloc.size) {
552 (RelocationKind::Absolute, 32) => elf::R_386_32,
553 (RelocationKind::Relative, 32) => elf::R_386_PC32,
554 (RelocationKind::Got, 32) => elf::R_386_GOT32,
555 (RelocationKind::PltRelative, 32) => elf::R_386_PLT32,
556 (RelocationKind::GotBaseOffset, 32) => elf::R_386_GOTOFF,
557 (RelocationKind::GotBaseRelative, 32) => elf::R_386_GOTPC,
558 (RelocationKind::Absolute, 16) => elf::R_386_16,
559 (RelocationKind::Relative, 16) => elf::R_386_PC16,
560 (RelocationKind::Absolute, 8) => elf::R_386_8,
561 (RelocationKind::Relative, 8) => elf::R_386_PC8,
562 (RelocationKind::Elf(x), _) => x,
563 _ => {
564 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
565 }
566 },
567 Architecture::X86_64 | Architecture::X86_64_X32 => {
568 match (reloc.kind, reloc.encoding, reloc.size) {
569 (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => {
570 elf::R_X86_64_64
571 }
572 (RelocationKind::Relative, _, 32) => elf::R_X86_64_PC32,
573 (RelocationKind::Got, _, 32) => elf::R_X86_64_GOT32,
574 (RelocationKind::PltRelative, _, 32) => elf::R_X86_64_PLT32,
575 (RelocationKind::GotRelative, _, 32) => elf::R_X86_64_GOTPCREL,
576 (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => {
577 elf::R_X86_64_32
578 }
579 (RelocationKind::Absolute, RelocationEncoding::X86Signed, 32) => {
580 elf::R_X86_64_32S
581 }
582 (RelocationKind::Absolute, _, 16) => elf::R_X86_64_16,
583 (RelocationKind::Relative, _, 16) => elf::R_X86_64_PC16,
584 (RelocationKind::Absolute, _, 8) => elf::R_X86_64_8,
585 (RelocationKind::Relative, _, 8) => elf::R_X86_64_PC8,
586 (RelocationKind::Elf(x), _, _) => x,
587 _ => {
588 return Err(Error(format!(
589 "unimplemented relocation {:?}",
590 reloc
591 )));
592 }
593 }
594 }
595 Architecture::Hexagon => match (reloc.kind, reloc.encoding, reloc.size) {
596 (RelocationKind::Absolute, _, 32) => elf::R_HEX_32,
597 (RelocationKind::Elf(x), _, _) => x,
598 _ => {
599 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
600 }
601 },
602 Architecture::LoongArch64 => match (reloc.kind, reloc.encoding, reloc.size)
603 {
604 (RelocationKind::Absolute, _, 32) => elf::R_LARCH_32,
605 (RelocationKind::Absolute, _, 64) => elf::R_LARCH_64,
49aad941
FG
606 (RelocationKind::Relative, _, 32) => elf::R_LARCH_32_PCREL,
607 (RelocationKind::Relative, RelocationEncoding::LoongArchBranch, 16)
608 | (
609 RelocationKind::PltRelative,
610 RelocationEncoding::LoongArchBranch,
611 16,
612 ) => elf::R_LARCH_B16,
613 (RelocationKind::Relative, RelocationEncoding::LoongArchBranch, 21)
614 | (
615 RelocationKind::PltRelative,
616 RelocationEncoding::LoongArchBranch,
617 21,
618 ) => elf::R_LARCH_B21,
619 (RelocationKind::Relative, RelocationEncoding::LoongArchBranch, 26)
620 | (
621 RelocationKind::PltRelative,
622 RelocationEncoding::LoongArchBranch,
623 26,
624 ) => elf::R_LARCH_B26,
9c376795
FG
625 (RelocationKind::Elf(x), _, _) => x,
626 _ => {
627 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
628 }
629 },
630 Architecture::Mips | Architecture::Mips64 => {
631 match (reloc.kind, reloc.encoding, reloc.size) {
632 (RelocationKind::Absolute, _, 16) => elf::R_MIPS_16,
633 (RelocationKind::Absolute, _, 32) => elf::R_MIPS_32,
634 (RelocationKind::Absolute, _, 64) => elf::R_MIPS_64,
635 (RelocationKind::Elf(x), _, _) => x,
636 _ => {
637 return Err(Error(format!(
638 "unimplemented relocation {:?}",
639 reloc
640 )));
641 }
642 }
643 }
644 Architecture::Msp430 => match (reloc.kind, reloc.encoding, reloc.size) {
645 (RelocationKind::Absolute, _, 32) => elf::R_MSP430_32,
646 (RelocationKind::Absolute, _, 16) => elf::R_MSP430_16_BYTE,
647 (RelocationKind::Elf(x), _, _) => x,
648 _ => {
649 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
650 }
651 },
652 Architecture::PowerPc => match (reloc.kind, reloc.encoding, reloc.size) {
653 (RelocationKind::Absolute, _, 32) => elf::R_PPC_ADDR32,
654 (RelocationKind::Elf(x), _, _) => x,
655 _ => {
656 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
657 }
658 },
659 Architecture::PowerPc64 => match (reloc.kind, reloc.encoding, reloc.size) {
660 (RelocationKind::Absolute, _, 32) => elf::R_PPC64_ADDR32,
661 (RelocationKind::Absolute, _, 64) => elf::R_PPC64_ADDR64,
662 (RelocationKind::Elf(x), _, _) => x,
663 _ => {
664 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
665 }
666 },
667 Architecture::Riscv32 | Architecture::Riscv64 => {
668 match (reloc.kind, reloc.encoding, reloc.size) {
669 (RelocationKind::Absolute, _, 32) => elf::R_RISCV_32,
670 (RelocationKind::Absolute, _, 64) => elf::R_RISCV_64,
49aad941
FG
671 (RelocationKind::Relative, RelocationEncoding::Generic, 32) => {
672 elf::R_RISCV_32_PCREL
673 }
9c376795
FG
674 (RelocationKind::Elf(x), _, _) => x,
675 _ => {
676 return Err(Error(format!(
677 "unimplemented relocation {:?}",
678 reloc
679 )));
680 }
681 }
682 }
683 Architecture::S390x => match (reloc.kind, reloc.encoding, reloc.size) {
684 (RelocationKind::Absolute, RelocationEncoding::Generic, 8) => {
685 elf::R_390_8
686 }
687 (RelocationKind::Absolute, RelocationEncoding::Generic, 16) => {
688 elf::R_390_16
689 }
690 (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => {
691 elf::R_390_32
692 }
693 (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => {
694 elf::R_390_64
695 }
696 (RelocationKind::Relative, RelocationEncoding::Generic, 16) => {
697 elf::R_390_PC16
698 }
699 (RelocationKind::Relative, RelocationEncoding::Generic, 32) => {
700 elf::R_390_PC32
701 }
702 (RelocationKind::Relative, RelocationEncoding::Generic, 64) => {
703 elf::R_390_PC64
704 }
705 (RelocationKind::Relative, RelocationEncoding::S390xDbl, 16) => {
706 elf::R_390_PC16DBL
707 }
708 (RelocationKind::Relative, RelocationEncoding::S390xDbl, 32) => {
709 elf::R_390_PC32DBL
710 }
711 (RelocationKind::PltRelative, RelocationEncoding::S390xDbl, 16) => {
712 elf::R_390_PLT16DBL
713 }
714 (RelocationKind::PltRelative, RelocationEncoding::S390xDbl, 32) => {
715 elf::R_390_PLT32DBL
716 }
717 (RelocationKind::Got, RelocationEncoding::Generic, 16) => {
718 elf::R_390_GOT16
719 }
720 (RelocationKind::Got, RelocationEncoding::Generic, 32) => {
721 elf::R_390_GOT32
722 }
723 (RelocationKind::Got, RelocationEncoding::Generic, 64) => {
724 elf::R_390_GOT64
725 }
726 (RelocationKind::GotRelative, RelocationEncoding::S390xDbl, 32) => {
727 elf::R_390_GOTENT
728 }
729 (RelocationKind::GotBaseOffset, RelocationEncoding::Generic, 16) => {
730 elf::R_390_GOTOFF16
731 }
732 (RelocationKind::GotBaseOffset, RelocationEncoding::Generic, 32) => {
733 elf::R_390_GOTOFF32
734 }
735 (RelocationKind::GotBaseOffset, RelocationEncoding::Generic, 64) => {
736 elf::R_390_GOTOFF64
737 }
738 (RelocationKind::GotBaseRelative, RelocationEncoding::Generic, 64) => {
739 elf::R_390_GOTPC
740 }
741 (RelocationKind::GotBaseRelative, RelocationEncoding::S390xDbl, 32) => {
742 elf::R_390_GOTPCDBL
743 }
744 (RelocationKind::Elf(x), _, _) => x,
745 _ => {
746 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
747 }
748 },
49aad941
FG
749 Architecture::Sbf => match (reloc.kind, reloc.encoding, reloc.size) {
750 (RelocationKind::Absolute, _, 64) => elf::R_SBF_64_64,
751 (RelocationKind::Absolute, _, 32) => elf::R_SBF_64_32,
752 (RelocationKind::Elf(x), _, _) => x,
753 _ => {
754 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
755 }
756 },
9c376795
FG
757 Architecture::Sparc64 => match (reloc.kind, reloc.encoding, reloc.size) {
758 // TODO: use R_SPARC_32/R_SPARC_64 if aligned.
759 (RelocationKind::Absolute, _, 32) => elf::R_SPARC_UA32,
760 (RelocationKind::Absolute, _, 64) => elf::R_SPARC_UA64,
761 (RelocationKind::Elf(x), _, _) => x,
762 _ => {
763 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
764 }
765 },
49aad941
FG
766 Architecture::Xtensa => match (reloc.kind, reloc.encoding, reloc.size) {
767 (RelocationKind::Absolute, _, 32) => elf::R_XTENSA_32,
768 (RelocationKind::Relative, RelocationEncoding::Generic, 32) => {
769 elf::R_XTENSA_32_PCREL
770 }
771 (RelocationKind::Elf(x), _, _) => x,
772 _ => {
773 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
774 }
775 },
9c376795
FG
776 _ => {
777 if let RelocationKind::Elf(x) = reloc.kind {
778 x
779 } else {
780 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
781 }
782 }
783 };
784 let r_sym = symbol_offsets[reloc.symbol.0].index.0;
785 writer.write_relocation(
786 is_rela,
787 &Rel {
788 r_offset: reloc.offset,
789 r_sym,
790 r_type,
791 r_addend: reloc.addend,
792 },
793 );
794 }
795 }
796 }
797
798 writer.write_shstrtab();
799
800 // Write section headers.
801 writer.write_null_section_header();
802
803 let symtab_index = writer.symtab_index();
804 for (comdat, comdat_offset) in self.comdats.iter().zip(comdat_offsets.iter()) {
805 writer.write_comdat_section_header(
806 comdat_offset.str_id,
807 symtab_index,
808 symbol_offsets[comdat.symbol.0].index,
809 comdat_offset.offset,
810 comdat.sections.len(),
811 );
812 }
813 for (index, section) in self.sections.iter().enumerate() {
814 let sh_type = match section.kind {
815 SectionKind::UninitializedData | SectionKind::UninitializedTls => elf::SHT_NOBITS,
816 SectionKind::Note => elf::SHT_NOTE,
817 SectionKind::Elf(sh_type) => sh_type,
818 _ => elf::SHT_PROGBITS,
819 };
820 let sh_flags = if let SectionFlags::Elf { sh_flags } = section.flags {
821 sh_flags
822 } else {
823 match section.kind {
824 SectionKind::Text => elf::SHF_ALLOC | elf::SHF_EXECINSTR,
49aad941
FG
825 SectionKind::Data | SectionKind::ReadOnlyDataWithRel => {
826 elf::SHF_ALLOC | elf::SHF_WRITE
827 }
9c376795
FG
828 SectionKind::Tls => elf::SHF_ALLOC | elf::SHF_WRITE | elf::SHF_TLS,
829 SectionKind::UninitializedData => elf::SHF_ALLOC | elf::SHF_WRITE,
830 SectionKind::UninitializedTls => elf::SHF_ALLOC | elf::SHF_WRITE | elf::SHF_TLS,
831 SectionKind::ReadOnlyData => elf::SHF_ALLOC,
832 SectionKind::ReadOnlyString => {
833 elf::SHF_ALLOC | elf::SHF_STRINGS | elf::SHF_MERGE
834 }
835 SectionKind::OtherString => elf::SHF_STRINGS | elf::SHF_MERGE,
836 SectionKind::Other
837 | SectionKind::Debug
838 | SectionKind::Metadata
839 | SectionKind::Linker
840 | SectionKind::Note
841 | SectionKind::Elf(_) => 0,
842 SectionKind::Unknown | SectionKind::Common | SectionKind::TlsVariables => {
843 return Err(Error(format!(
844 "unimplemented section `{}` kind {:?}",
845 section.name().unwrap_or(""),
846 section.kind
847 )));
848 }
849 }
850 .into()
851 };
852 // TODO: not sure if this is correct, maybe user should determine this
853 let sh_entsize = match section.kind {
854 SectionKind::ReadOnlyString | SectionKind::OtherString => 1,
855 _ => 0,
856 };
857 writer.write_section_header(&SectionHeader {
858 name: Some(section_offsets[index].str_id),
859 sh_type,
860 sh_flags,
861 sh_addr: 0,
862 sh_offset: section_offsets[index].offset as u64,
863 sh_size: section.size,
864 sh_link: 0,
865 sh_info: 0,
866 sh_addralign: section.align,
867 sh_entsize,
868 });
869
870 if !section.relocations.is_empty() {
871 writer.write_relocation_section_header(
872 section_offsets[index].reloc_str_id.unwrap(),
873 section_offsets[index].index,
874 symtab_index,
875 section_offsets[index].reloc_offset,
876 section.relocations.len(),
877 is_rela,
878 );
879 }
880 }
881
882 writer.write_symtab_section_header(symtab_num_local);
883 writer.write_symtab_shndx_section_header();
884 writer.write_strtab_section_header();
885 writer.write_shstrtab_section_header();
886
887 debug_assert_eq!(writer.reserved_len(), writer.len());
888
889 Ok(())
890 }
891}