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