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