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