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