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