]> git.proxmox.com Git - rustc.git/blob - vendor/object/src/write/elf.rs
New upstream version 1.55.0+dfsg1
[rustc.git] / vendor / object / src / write / elf.rs
1 use std::mem;
2 use std::vec::Vec;
3
4 use crate::elf;
5 use crate::endian::*;
6 use crate::write::string::*;
7 use crate::write::util::*;
8 use crate::write::*;
9 use crate::AddressSize;
10
11 #[derive(Default, Clone, Copy)]
12 struct ComdatOffsets {
13 offset: usize,
14 str_id: Option<StringId>,
15 len: usize,
16 }
17
18 #[derive(Default, Clone, Copy)]
19 struct SectionOffsets {
20 index: usize,
21 offset: usize,
22 str_id: Option<StringId>,
23 reloc_index: usize,
24 reloc_offset: usize,
25 reloc_len: usize,
26 reloc_str_id: Option<StringId>,
27 }
28
29 #[derive(Default, Clone, Copy)]
30 struct SymbolOffsets {
31 index: usize,
32 str_id: Option<StringId>,
33 }
34
35 impl Object {
36 pub(crate) fn elf_section_info(
37 &self,
38 section: StandardSection,
39 ) -> (&'static [u8], &'static [u8], SectionKind) {
40 match section {
41 StandardSection::Text => (&[], &b".text"[..], SectionKind::Text),
42 StandardSection::Data => (&[], &b".data"[..], SectionKind::Data),
43 StandardSection::ReadOnlyData | StandardSection::ReadOnlyString => {
44 (&[], &b".rodata"[..], SectionKind::ReadOnlyData)
45 }
46 StandardSection::ReadOnlyDataWithRel => (&[], b".data.rel.ro", SectionKind::Data),
47 StandardSection::UninitializedData => {
48 (&[], &b".bss"[..], SectionKind::UninitializedData)
49 }
50 StandardSection::Tls => (&[], &b".tdata"[..], SectionKind::Tls),
51 StandardSection::UninitializedTls => {
52 (&[], &b".tbss"[..], SectionKind::UninitializedTls)
53 }
54 StandardSection::TlsVariables => {
55 // Unsupported section.
56 (&[], &[], SectionKind::TlsVariables)
57 }
58 StandardSection::Common => {
59 // Unsupported section.
60 (&[], &[], SectionKind::Common)
61 }
62 }
63 }
64
65 pub(crate) fn elf_subsection_name(&self, section: &[u8], value: &[u8]) -> Vec<u8> {
66 let mut name = section.to_vec();
67 name.push(b'.');
68 name.extend_from_slice(value);
69 name
70 }
71
72 fn elf_has_relocation_addend(&self) -> Result<bool> {
73 Ok(match self.architecture {
74 Architecture::Aarch64 => true,
75 Architecture::Arm => false,
76 Architecture::Avr => true,
77 Architecture::Bpf => false,
78 Architecture::I386 => false,
79 Architecture::X86_64 => true,
80 Architecture::X86_64_X32 => true,
81 Architecture::Hexagon => true,
82 Architecture::Mips => false,
83 Architecture::Mips64 => true,
84 Architecture::Msp430 => true,
85 Architecture::PowerPc => true,
86 Architecture::PowerPc64 => true,
87 Architecture::Riscv64 => true,
88 Architecture::Riscv32 => true,
89 Architecture::S390x => true,
90 Architecture::Sparc64 => true,
91 _ => {
92 return Err(Error(format!(
93 "unimplemented architecture {:?}",
94 self.architecture
95 )));
96 }
97 })
98 }
99
100 pub(crate) fn elf_fixup_relocation(&mut self, mut relocation: &mut Relocation) -> Result<i64> {
101 // Return true if we should use a section symbol to avoid preemption.
102 fn want_section_symbol(relocation: &Relocation, symbol: &Symbol) -> bool {
103 if symbol.scope != SymbolScope::Dynamic {
104 // Only dynamic symbols can be preemptible.
105 return false;
106 }
107 match symbol.kind {
108 SymbolKind::Text | SymbolKind::Data => {}
109 _ => return false,
110 }
111 match relocation.kind {
112 // Anything using GOT or PLT is preemptible.
113 // We also require that `Other` relocations must already be correct.
114 RelocationKind::Got
115 | RelocationKind::GotRelative
116 | RelocationKind::GotBaseRelative
117 | RelocationKind::PltRelative
118 | RelocationKind::Elf(_) => return false,
119 // Absolute relocations are preemptible for non-local data.
120 // TODO: not sure if this rule is exactly correct
121 // This rule was added to handle global data references in debuginfo.
122 // Maybe this should be a new relocation kind so that the caller can decide.
123 RelocationKind::Absolute => {
124 if symbol.kind == SymbolKind::Data {
125 return false;
126 }
127 }
128 _ => {}
129 }
130 true
131 }
132
133 // Use section symbols for relocations where required to avoid preemption.
134 // Otherwise, the linker will fail with:
135 // relocation R_X86_64_PC32 against symbol `SomeSymbolName' can not be used when
136 // making a shared object; recompile with -fPIC
137 let symbol = &self.symbols[relocation.symbol.0];
138 if want_section_symbol(relocation, symbol) {
139 if let Some(section) = symbol.section.id() {
140 relocation.addend += symbol.value as i64;
141 relocation.symbol = self.section_symbol(section);
142 }
143 }
144
145 // Determine whether the addend is stored in the relocation or the data.
146 if self.elf_has_relocation_addend()? {
147 Ok(0)
148 } else {
149 let constant = relocation.addend;
150 relocation.addend = 0;
151 Ok(constant)
152 }
153 }
154
155 pub(crate) fn elf_write(&self, buffer: &mut dyn WritableBuffer) -> Result<()> {
156 let address_size = self.architecture.address_size().unwrap();
157 let endian = self.endian;
158 let elf32 = Elf32 { endian };
159 let elf64 = Elf64 { endian };
160 let elf: &dyn Elf = match address_size {
161 AddressSize::U8 | AddressSize::U16 | AddressSize::U32 => &elf32,
162 AddressSize::U64 => &elf64,
163 };
164 let pointer_align = address_size.bytes() as usize;
165 let is_mips64el =
166 self.architecture == Architecture::Mips64 && self.endian == Endianness::Little;
167
168 // Calculate offsets of everything.
169 let mut offset = 0;
170
171 // ELF header.
172 let e_ehsize = elf.file_header_size();
173 offset += e_ehsize;
174
175 // Create reloc section header names.
176 let is_rela = self.elf_has_relocation_addend()?;
177 let reloc_names: Vec<_> = self
178 .sections
179 .iter()
180 .map(|section| {
181 let mut reloc_name = Vec::new();
182 if !section.relocations.is_empty() {
183 reloc_name.extend_from_slice(if is_rela {
184 &b".rela"[..]
185 } else {
186 &b".rel"[..]
187 });
188 reloc_name.extend_from_slice(&section.name);
189 }
190 reloc_name
191 })
192 .collect();
193
194 // Calculate size of section data.
195 let mut shstrtab = StringTable::default();
196 let mut comdat_offsets = vec![ComdatOffsets::default(); self.comdats.len()];
197 let mut section_offsets = vec![SectionOffsets::default(); self.sections.len()];
198 // Null section.
199 let mut section_num = 1;
200 for (index, comdat) in self.comdats.iter().enumerate() {
201 if comdat.kind != ComdatKind::Any {
202 return Err(Error(format!(
203 "unsupported COMDAT symbol `{}` kind {:?}",
204 self.symbols[comdat.symbol.0].name().unwrap_or(""),
205 comdat.kind
206 )));
207 }
208
209 comdat_offsets[index].str_id = Some(shstrtab.add(b".group"));
210 section_num += 1;
211 offset = align(offset, 4);
212 comdat_offsets[index].offset = offset;
213 let len = (comdat.sections.len() + 1) * 4;
214 comdat_offsets[index].len = len;
215 offset += len;
216 }
217 for (index, section) in self.sections.iter().enumerate() {
218 section_offsets[index].str_id = Some(shstrtab.add(&section.name));
219 section_offsets[index].index = section_num;
220 section_num += 1;
221
222 let len = section.data.len();
223 if len != 0 {
224 offset = align(offset, section.align as usize);
225 section_offsets[index].offset = offset;
226 offset += len;
227 } else {
228 section_offsets[index].offset = offset;
229 }
230
231 if !section.relocations.is_empty() {
232 section_offsets[index].reloc_str_id = Some(shstrtab.add(&reloc_names[index]));
233 section_offsets[index].reloc_index = section_num;
234 section_num += 1;
235 }
236 }
237
238 // Calculate index of symbols and add symbol strings to strtab.
239 let mut strtab = StringTable::default();
240 let mut symbol_offsets = vec![SymbolOffsets::default(); self.symbols.len()];
241 // Null symbol.
242 let mut symtab_count = 1;
243 // Local symbols must come before global.
244 for (index, symbol) in self.symbols.iter().enumerate() {
245 if symbol.is_local() {
246 symbol_offsets[index].index = symtab_count;
247 symtab_count += 1;
248 }
249 }
250 let symtab_count_local = symtab_count;
251 for (index, symbol) in self.symbols.iter().enumerate() {
252 if !symbol.is_local() {
253 symbol_offsets[index].index = symtab_count;
254 symtab_count += 1;
255 }
256 }
257 for (index, symbol) in self.symbols.iter().enumerate() {
258 if symbol.kind != SymbolKind::Section && !symbol.name.is_empty() {
259 symbol_offsets[index].str_id = Some(strtab.add(&symbol.name));
260 }
261 }
262
263 // Calculate size of symtab.
264 let symtab_str_id = shstrtab.add(&b".symtab"[..]);
265 offset = align(offset, pointer_align);
266 let symtab_offset = offset;
267 let symtab_len = symtab_count * elf.symbol_size();
268 offset += symtab_len;
269 let symtab_index = section_num;
270 section_num += 1;
271
272 // Calculate size of symtab_shndx.
273 let mut need_symtab_shndx = false;
274 for symbol in &self.symbols {
275 let index = symbol
276 .section
277 .id()
278 .map(|s| section_offsets[s.0].index)
279 .unwrap_or(0);
280 if index >= elf::SHN_LORESERVE as usize {
281 need_symtab_shndx = true;
282 break;
283 }
284 }
285 let symtab_shndx_offset = offset;
286 let mut symtab_shndx_str_id = None;
287 let mut symtab_shndx_len = 0;
288 if need_symtab_shndx {
289 symtab_shndx_str_id = Some(shstrtab.add(&b".symtab_shndx"[..]));
290 symtab_shndx_len = symtab_count * 4;
291 offset += symtab_shndx_len;
292 section_num += 1;
293 }
294
295 // Calculate size of strtab.
296 let strtab_str_id = shstrtab.add(&b".strtab"[..]);
297 let strtab_offset = offset;
298 // Start with null name.
299 let mut strtab_data = vec![0];
300 strtab.write(1, &mut strtab_data);
301 offset += strtab_data.len();
302 let strtab_index = section_num;
303 section_num += 1;
304
305 // Calculate size of relocations.
306 for (index, section) in self.sections.iter().enumerate() {
307 let count = section.relocations.len();
308 if count != 0 {
309 offset = align(offset, pointer_align);
310 section_offsets[index].reloc_offset = offset;
311 let len = count * elf.rel_size(is_rela);
312 section_offsets[index].reloc_len = len;
313 offset += len;
314 }
315 }
316
317 // Calculate size of shstrtab.
318 let shstrtab_str_id = shstrtab.add(&b".shstrtab"[..]);
319 let shstrtab_offset = offset;
320 // Start with null section name.
321 let mut shstrtab_data = vec![0];
322 shstrtab.write(1, &mut shstrtab_data);
323 offset += shstrtab_data.len();
324 let shstrtab_index = section_num;
325 section_num += 1;
326
327 // Calculate size of section headers.
328 offset = align(offset, pointer_align);
329 let e_shoff = offset;
330 let e_shentsize = elf.section_header_size();
331 offset += section_num * e_shentsize;
332
333 // Start writing.
334 buffer
335 .reserve(offset)
336 .map_err(|_| Error(String::from("Cannot allocate buffer")))?;
337
338 // Write file header.
339 let e_ident = elf::Ident {
340 magic: elf::ELFMAG,
341 class: match address_size {
342 AddressSize::U8 | AddressSize::U16 | AddressSize::U32 => elf::ELFCLASS32,
343 AddressSize::U64 => elf::ELFCLASS64,
344 },
345 data: if endian.is_little_endian() {
346 elf::ELFDATA2LSB
347 } else {
348 elf::ELFDATA2MSB
349 },
350 version: elf::EV_CURRENT,
351 os_abi: elf::ELFOSABI_NONE,
352 abi_version: 0,
353 padding: [0; 7],
354 };
355 let e_type = elf::ET_REL;
356 let e_machine = match self.architecture {
357 Architecture::Aarch64 => elf::EM_AARCH64,
358 Architecture::Arm => elf::EM_ARM,
359 Architecture::Avr => elf::EM_AVR,
360 Architecture::Bpf => elf::EM_BPF,
361 Architecture::I386 => elf::EM_386,
362 Architecture::X86_64 => elf::EM_X86_64,
363 Architecture::X86_64_X32 => elf::EM_X86_64,
364 Architecture::Hexagon => elf::EM_HEXAGON,
365 Architecture::Mips => elf::EM_MIPS,
366 Architecture::Mips64 => elf::EM_MIPS,
367 Architecture::Msp430 => elf::EM_MSP430,
368 Architecture::PowerPc => elf::EM_PPC,
369 Architecture::PowerPc64 => elf::EM_PPC64,
370 Architecture::Riscv32 => elf::EM_RISCV,
371 Architecture::Riscv64 => elf::EM_RISCV,
372 Architecture::S390x => elf::EM_S390,
373 Architecture::Sparc64 => elf::EM_SPARCV9,
374 _ => {
375 return Err(Error(format!(
376 "unimplemented architecture {:?}",
377 self.architecture
378 )));
379 }
380 };
381 let e_flags = if let FileFlags::Elf { e_flags } = self.flags {
382 e_flags
383 } else {
384 0
385 };
386 let e_shnum = if section_num >= elf::SHN_LORESERVE as usize {
387 0
388 } else {
389 section_num as u16
390 };
391 let e_shstrndx = if shstrtab_index >= elf::SHN_LORESERVE as usize {
392 elf::SHN_XINDEX
393 } else {
394 shstrtab_index as u16
395 };
396
397 elf.write_file_header(
398 buffer,
399 FileHeader {
400 e_ident,
401 e_type,
402 e_machine,
403 e_version: elf::EV_CURRENT.into(),
404 e_entry: 0,
405 e_phoff: 0,
406 e_shoff: e_shoff as u64,
407 e_flags,
408 e_ehsize: e_ehsize as u16,
409 e_phentsize: 0,
410 e_phnum: 0,
411 e_shentsize: e_shentsize as u16,
412 e_shnum,
413 e_shstrndx,
414 },
415 );
416
417 // Write section data.
418 for (index, comdat) in self.comdats.iter().enumerate() {
419 let mut data = Vec::new();
420 data.write_pod(&U32::new(self.endian, elf::GRP_COMDAT));
421 for section in &comdat.sections {
422 data.write_pod(&U32::new(
423 self.endian,
424 section_offsets[section.0].index as u32,
425 ));
426 }
427
428 write_align(buffer, 4);
429 debug_assert_eq!(comdat_offsets[index].offset, buffer.len());
430 debug_assert_eq!(comdat_offsets[index].len, data.len());
431 buffer.write_bytes(&data);
432 }
433 for (index, section) in self.sections.iter().enumerate() {
434 let len = section.data.len();
435 if len != 0 {
436 write_align(buffer, section.align as usize);
437 debug_assert_eq!(section_offsets[index].offset, buffer.len());
438 buffer.write_bytes(&section.data);
439 }
440 }
441
442 // Write symbols.
443 write_align(buffer, pointer_align);
444 debug_assert_eq!(symtab_offset, buffer.len());
445 elf.write_symbol(
446 buffer,
447 Sym {
448 st_name: 0,
449 st_info: 0,
450 st_other: 0,
451 st_shndx: 0,
452 st_value: 0,
453 st_size: 0,
454 },
455 );
456 let mut symtab_shndx = Vec::new();
457 if need_symtab_shndx {
458 symtab_shndx.write_pod(&U32::new(endian, 0));
459 }
460 let mut write_symbol = |index: usize, symbol: &Symbol| -> Result<()> {
461 let st_info = if let SymbolFlags::Elf { st_info, .. } = symbol.flags {
462 st_info
463 } else {
464 let st_type = match symbol.kind {
465 SymbolKind::Null => elf::STT_NOTYPE,
466 SymbolKind::Text => {
467 if symbol.is_undefined() {
468 elf::STT_NOTYPE
469 } else {
470 elf::STT_FUNC
471 }
472 }
473 SymbolKind::Data => {
474 if symbol.is_undefined() {
475 elf::STT_NOTYPE
476 } else if symbol.is_common() {
477 elf::STT_COMMON
478 } else {
479 elf::STT_OBJECT
480 }
481 }
482 SymbolKind::Section => elf::STT_SECTION,
483 SymbolKind::File => elf::STT_FILE,
484 SymbolKind::Tls => elf::STT_TLS,
485 SymbolKind::Label => elf::STT_NOTYPE,
486 SymbolKind::Unknown => {
487 if symbol.is_undefined() {
488 elf::STT_NOTYPE
489 } else {
490 return Err(Error(format!(
491 "unimplemented symbol `{}` kind {:?}",
492 symbol.name().unwrap_or(""),
493 symbol.kind
494 )));
495 }
496 }
497 };
498 let st_bind = if symbol.weak {
499 elf::STB_WEAK
500 } else if symbol.is_undefined() {
501 elf::STB_GLOBAL
502 } else if symbol.is_local() {
503 elf::STB_LOCAL
504 } else {
505 elf::STB_GLOBAL
506 };
507 (st_bind << 4) + st_type
508 };
509 let st_other = if let SymbolFlags::Elf { st_other, .. } = symbol.flags {
510 st_other
511 } else if symbol.scope == SymbolScope::Linkage {
512 elf::STV_HIDDEN
513 } else {
514 elf::STV_DEFAULT
515 };
516 let (st_shndx, xindex) = match symbol.section {
517 SymbolSection::None => {
518 debug_assert_eq!(symbol.kind, SymbolKind::File);
519 (elf::SHN_ABS, 0)
520 }
521 SymbolSection::Undefined => (elf::SHN_UNDEF, 0),
522 SymbolSection::Absolute => (elf::SHN_ABS, 0),
523 SymbolSection::Common => (elf::SHN_COMMON, 0),
524 SymbolSection::Section(id) => {
525 let index = section_offsets[id.0].index as u32;
526 (
527 if index >= elf::SHN_LORESERVE as u32 {
528 elf::SHN_XINDEX
529 } else {
530 index as u16
531 },
532 index,
533 )
534 }
535 };
536 let st_name = symbol_offsets[index]
537 .str_id
538 .map(|id| strtab.get_offset(id))
539 .unwrap_or(0) as u32;
540 elf.write_symbol(
541 buffer,
542 Sym {
543 st_name,
544 st_info,
545 st_other,
546 st_shndx,
547 st_value: symbol.value,
548 st_size: symbol.size,
549 },
550 );
551 if need_symtab_shndx {
552 symtab_shndx.write_pod(&U32::new(endian, xindex));
553 }
554 Ok(())
555 };
556 for (index, symbol) in self.symbols.iter().enumerate() {
557 if symbol.is_local() {
558 write_symbol(index, symbol)?;
559 }
560 }
561 for (index, symbol) in self.symbols.iter().enumerate() {
562 if !symbol.is_local() {
563 write_symbol(index, symbol)?;
564 }
565 }
566 if need_symtab_shndx {
567 debug_assert_eq!(symtab_shndx_offset, buffer.len());
568 debug_assert_eq!(symtab_shndx_len, symtab_shndx.len());
569 buffer.write_bytes(&symtab_shndx);
570 }
571
572 // Write strtab section.
573 debug_assert_eq!(strtab_offset, buffer.len());
574 buffer.write_bytes(&strtab_data);
575
576 // Write relocations.
577 for (index, section) in self.sections.iter().enumerate() {
578 if !section.relocations.is_empty() {
579 write_align(buffer, pointer_align);
580 debug_assert_eq!(section_offsets[index].reloc_offset, buffer.len());
581 for reloc in &section.relocations {
582 let r_type = match self.architecture {
583 Architecture::Aarch64 => match (reloc.kind, reloc.encoding, reloc.size) {
584 (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => {
585 elf::R_AARCH64_ABS64
586 }
587 (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => {
588 elf::R_AARCH64_ABS32
589 }
590 (RelocationKind::Absolute, RelocationEncoding::Generic, 16) => {
591 elf::R_AARCH64_ABS16
592 }
593 (RelocationKind::Relative, RelocationEncoding::Generic, 64) => {
594 elf::R_AARCH64_PREL64
595 }
596 (RelocationKind::Relative, RelocationEncoding::Generic, 32) => {
597 elf::R_AARCH64_PREL32
598 }
599 (RelocationKind::Relative, RelocationEncoding::Generic, 16) => {
600 elf::R_AARCH64_PREL16
601 }
602 (RelocationKind::Relative, RelocationEncoding::AArch64Call, 26)
603 | (RelocationKind::PltRelative, RelocationEncoding::AArch64Call, 26) => {
604 elf::R_AARCH64_CALL26
605 }
606 (RelocationKind::Elf(x), _, _) => x,
607 _ => {
608 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
609 }
610 },
611 Architecture::Arm => match (reloc.kind, reloc.encoding, reloc.size) {
612 (RelocationKind::Absolute, _, 32) => elf::R_ARM_ABS32,
613 (RelocationKind::Elf(x), _, _) => x,
614 _ => {
615 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
616 }
617 },
618 Architecture::Avr => match (reloc.kind, reloc.encoding, reloc.size) {
619 (RelocationKind::Absolute, _, 32) => elf::R_AVR_32,
620 (RelocationKind::Absolute, _, 16) => elf::R_AVR_16,
621 (RelocationKind::Elf(x), _, _) => x,
622 _ => {
623 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
624 }
625 },
626 Architecture::Bpf => match (reloc.kind, reloc.encoding, reloc.size) {
627 (RelocationKind::Absolute, _, 64) => elf::R_BPF_64_64,
628 (RelocationKind::Absolute, _, 32) => elf::R_BPF_64_32,
629 (RelocationKind::Elf(x), _, _) => x,
630 _ => {
631 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
632 }
633 },
634 Architecture::I386 => match (reloc.kind, reloc.size) {
635 (RelocationKind::Absolute, 32) => elf::R_386_32,
636 (RelocationKind::Relative, 32) => elf::R_386_PC32,
637 (RelocationKind::Got, 32) => elf::R_386_GOT32,
638 (RelocationKind::PltRelative, 32) => elf::R_386_PLT32,
639 (RelocationKind::GotBaseOffset, 32) => elf::R_386_GOTOFF,
640 (RelocationKind::GotBaseRelative, 32) => elf::R_386_GOTPC,
641 (RelocationKind::Absolute, 16) => elf::R_386_16,
642 (RelocationKind::Relative, 16) => elf::R_386_PC16,
643 (RelocationKind::Absolute, 8) => elf::R_386_8,
644 (RelocationKind::Relative, 8) => elf::R_386_PC8,
645 (RelocationKind::Elf(x), _) => x,
646 _ => {
647 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
648 }
649 },
650 Architecture::X86_64 | Architecture::X86_64_X32 => {
651 match (reloc.kind, reloc.encoding, reloc.size) {
652 (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => {
653 elf::R_X86_64_64
654 }
655 (RelocationKind::Relative, _, 32) => elf::R_X86_64_PC32,
656 (RelocationKind::Got, _, 32) => elf::R_X86_64_GOT32,
657 (RelocationKind::PltRelative, _, 32) => elf::R_X86_64_PLT32,
658 (RelocationKind::GotRelative, _, 32) => elf::R_X86_64_GOTPCREL,
659 (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => {
660 elf::R_X86_64_32
661 }
662 (RelocationKind::Absolute, RelocationEncoding::X86Signed, 32) => {
663 elf::R_X86_64_32S
664 }
665 (RelocationKind::Absolute, _, 16) => elf::R_X86_64_16,
666 (RelocationKind::Relative, _, 16) => elf::R_X86_64_PC16,
667 (RelocationKind::Absolute, _, 8) => elf::R_X86_64_8,
668 (RelocationKind::Relative, _, 8) => elf::R_X86_64_PC8,
669 (RelocationKind::Elf(x), _, _) => x,
670 _ => {
671 return Err(Error(format!(
672 "unimplemented relocation {:?}",
673 reloc
674 )));
675 }
676 }
677 }
678 Architecture::Hexagon => match (reloc.kind, reloc.encoding, reloc.size) {
679 (RelocationKind::Absolute, _, 32) => elf::R_HEX_32,
680 (RelocationKind::Elf(x), _, _) => x,
681 _ => {
682 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
683 }
684 },
685 Architecture::Mips | Architecture::Mips64 => {
686 match (reloc.kind, reloc.encoding, reloc.size) {
687 (RelocationKind::Absolute, _, 16) => elf::R_MIPS_16,
688 (RelocationKind::Absolute, _, 32) => elf::R_MIPS_32,
689 (RelocationKind::Absolute, _, 64) => elf::R_MIPS_64,
690 (RelocationKind::Elf(x), _, _) => x,
691 _ => {
692 return Err(Error(format!(
693 "unimplemented relocation {:?}",
694 reloc
695 )));
696 }
697 }
698 }
699 Architecture::Msp430 => match (reloc.kind, reloc.encoding, reloc.size) {
700 (RelocationKind::Absolute, _, 32) => elf::R_MSP430_32,
701 (RelocationKind::Absolute, _, 16) => elf::R_MSP430_16_BYTE,
702 (RelocationKind::Elf(x), _, _) => x,
703 _ => {
704 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
705 }
706 },
707 Architecture::PowerPc => match (reloc.kind, reloc.encoding, reloc.size) {
708 (RelocationKind::Absolute, _, 32) => elf::R_PPC_ADDR32,
709 (RelocationKind::Elf(x), _, _) => x,
710 _ => {
711 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
712 }
713 },
714 Architecture::PowerPc64 => match (reloc.kind, reloc.encoding, reloc.size) {
715 (RelocationKind::Absolute, _, 32) => elf::R_PPC64_ADDR32,
716 (RelocationKind::Absolute, _, 64) => elf::R_PPC64_ADDR64,
717 (RelocationKind::Elf(x), _, _) => x,
718 _ => {
719 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
720 }
721 },
722 Architecture::Riscv32 | Architecture::Riscv64 => {
723 match (reloc.kind, reloc.encoding, reloc.size) {
724 (RelocationKind::Absolute, _, 32) => elf::R_RISCV_32,
725 (RelocationKind::Absolute, _, 64) => elf::R_RISCV_64,
726 (RelocationKind::Elf(x), _, _) => x,
727 _ => {
728 return Err(Error(format!(
729 "unimplemented relocation {:?}",
730 reloc
731 )));
732 }
733 }
734 }
735 Architecture::S390x => match (reloc.kind, reloc.encoding, reloc.size) {
736 (RelocationKind::Absolute, RelocationEncoding::Generic, 8) => {
737 elf::R_390_8
738 }
739 (RelocationKind::Absolute, RelocationEncoding::Generic, 16) => {
740 elf::R_390_16
741 }
742 (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => {
743 elf::R_390_32
744 }
745 (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => {
746 elf::R_390_64
747 }
748 (RelocationKind::Relative, RelocationEncoding::Generic, 16) => {
749 elf::R_390_PC16
750 }
751 (RelocationKind::Relative, RelocationEncoding::Generic, 32) => {
752 elf::R_390_PC32
753 }
754 (RelocationKind::Relative, RelocationEncoding::Generic, 64) => {
755 elf::R_390_PC64
756 }
757 (RelocationKind::Relative, RelocationEncoding::S390xDbl, 16) => {
758 elf::R_390_PC16DBL
759 }
760 (RelocationKind::Relative, RelocationEncoding::S390xDbl, 32) => {
761 elf::R_390_PC32DBL
762 }
763 (RelocationKind::PltRelative, RelocationEncoding::S390xDbl, 16) => {
764 elf::R_390_PLT16DBL
765 }
766 (RelocationKind::PltRelative, RelocationEncoding::S390xDbl, 32) => {
767 elf::R_390_PLT32DBL
768 }
769 (RelocationKind::Got, RelocationEncoding::Generic, 16) => {
770 elf::R_390_GOT16
771 }
772 (RelocationKind::Got, RelocationEncoding::Generic, 32) => {
773 elf::R_390_GOT32
774 }
775 (RelocationKind::Got, RelocationEncoding::Generic, 64) => {
776 elf::R_390_GOT64
777 }
778 (RelocationKind::GotRelative, RelocationEncoding::S390xDbl, 32) => {
779 elf::R_390_GOTENT
780 }
781 (RelocationKind::GotBaseOffset, RelocationEncoding::Generic, 16) => {
782 elf::R_390_GOTOFF16
783 }
784 (RelocationKind::GotBaseOffset, RelocationEncoding::Generic, 32) => {
785 elf::R_390_GOTOFF32
786 }
787 (RelocationKind::GotBaseOffset, RelocationEncoding::Generic, 64) => {
788 elf::R_390_GOTOFF64
789 }
790 (RelocationKind::GotBaseRelative, RelocationEncoding::Generic, 64) => {
791 elf::R_390_GOTPC
792 }
793 (RelocationKind::GotBaseRelative, RelocationEncoding::S390xDbl, 32) => {
794 elf::R_390_GOTPCDBL
795 }
796 (RelocationKind::Elf(x), _, _) => x,
797 _ => {
798 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
799 }
800 },
801 Architecture::Sparc64 => match (reloc.kind, reloc.encoding, reloc.size) {
802 // TODO: use R_SPARC_32/R_SPARC_64 if aligned.
803 (RelocationKind::Absolute, _, 32) => elf::R_SPARC_UA32,
804 (RelocationKind::Absolute, _, 64) => elf::R_SPARC_UA64,
805 (RelocationKind::Elf(x), _, _) => x,
806 _ => {
807 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
808 }
809 },
810 _ => {
811 if let RelocationKind::Elf(x) = reloc.kind {
812 x
813 } else {
814 return Err(Error(format!("unimplemented relocation {:?}", reloc)));
815 }
816 }
817 };
818 let r_sym = symbol_offsets[reloc.symbol.0].index as u32;
819 elf.write_rel(
820 buffer,
821 is_mips64el,
822 is_rela,
823 Rel {
824 r_offset: reloc.offset,
825 r_sym,
826 r_type,
827 r_addend: reloc.addend,
828 },
829 );
830 }
831 }
832 }
833
834 // Write shstrtab section.
835 debug_assert_eq!(shstrtab_offset, buffer.len());
836 buffer.write_bytes(&shstrtab_data);
837
838 // Write section headers.
839 write_align(buffer, pointer_align);
840 debug_assert_eq!(e_shoff, buffer.len());
841 elf.write_section_header(
842 buffer,
843 SectionHeader {
844 sh_name: 0,
845 sh_type: 0,
846 sh_flags: 0,
847 sh_addr: 0,
848 sh_offset: 0,
849 sh_size: if section_num >= elf::SHN_LORESERVE as usize {
850 section_num as u64
851 } else {
852 0
853 },
854 sh_link: if shstrtab_index >= elf::SHN_LORESERVE as usize {
855 shstrtab_index as u32
856 } else {
857 0
858 },
859 // TODO: e_phnum overflow
860 sh_info: 0,
861 sh_addralign: 0,
862 sh_entsize: 0,
863 },
864 );
865 for (index, comdat) in self.comdats.iter().enumerate() {
866 let sh_name = comdat_offsets[index]
867 .str_id
868 .map(|id| shstrtab.get_offset(id))
869 .unwrap_or(0) as u32;
870 elf.write_section_header(
871 buffer,
872 SectionHeader {
873 sh_name,
874 sh_type: elf::SHT_GROUP,
875 sh_flags: 0,
876 sh_addr: 0,
877 sh_offset: comdat_offsets[index].offset as u64,
878 sh_size: comdat_offsets[index].len as u64,
879 sh_link: symtab_index as u32,
880 sh_info: symbol_offsets[comdat.symbol.0].index as u32,
881 sh_addralign: 4,
882 sh_entsize: 4,
883 },
884 );
885 }
886 for (index, section) in self.sections.iter().enumerate() {
887 let sh_type = match section.kind {
888 SectionKind::UninitializedData | SectionKind::UninitializedTls => elf::SHT_NOBITS,
889 SectionKind::Note => elf::SHT_NOTE,
890 SectionKind::Elf(sh_type) => sh_type,
891 _ => elf::SHT_PROGBITS,
892 };
893 let sh_flags = if let SectionFlags::Elf { sh_flags } = section.flags {
894 sh_flags
895 } else {
896 match section.kind {
897 SectionKind::Text => elf::SHF_ALLOC | elf::SHF_EXECINSTR,
898 SectionKind::Data => elf::SHF_ALLOC | elf::SHF_WRITE,
899 SectionKind::Tls => elf::SHF_ALLOC | elf::SHF_WRITE | elf::SHF_TLS,
900 SectionKind::UninitializedData => elf::SHF_ALLOC | elf::SHF_WRITE,
901 SectionKind::UninitializedTls => elf::SHF_ALLOC | elf::SHF_WRITE | elf::SHF_TLS,
902 SectionKind::ReadOnlyData => elf::SHF_ALLOC,
903 SectionKind::ReadOnlyString => {
904 elf::SHF_ALLOC | elf::SHF_STRINGS | elf::SHF_MERGE
905 }
906 SectionKind::OtherString => elf::SHF_STRINGS | elf::SHF_MERGE,
907 SectionKind::Other
908 | SectionKind::Debug
909 | SectionKind::Metadata
910 | SectionKind::Linker
911 | SectionKind::Note
912 | SectionKind::Elf(_) => 0,
913 SectionKind::Unknown | SectionKind::Common | SectionKind::TlsVariables => {
914 return Err(Error(format!(
915 "unimplemented section `{}` kind {:?}",
916 section.name().unwrap_or(""),
917 section.kind
918 )));
919 }
920 }
921 .into()
922 };
923 // TODO: not sure if this is correct, maybe user should determine this
924 let sh_entsize = match section.kind {
925 SectionKind::ReadOnlyString | SectionKind::OtherString => 1,
926 _ => 0,
927 };
928 let sh_name = section_offsets[index]
929 .str_id
930 .map(|id| shstrtab.get_offset(id))
931 .unwrap_or(0) as u32;
932 elf.write_section_header(
933 buffer,
934 SectionHeader {
935 sh_name,
936 sh_type,
937 sh_flags,
938 sh_addr: 0,
939 sh_offset: section_offsets[index].offset as u64,
940 sh_size: section.size,
941 sh_link: 0,
942 sh_info: 0,
943 sh_addralign: section.align,
944 sh_entsize,
945 },
946 );
947
948 if !section.relocations.is_empty() {
949 let sh_name = section_offsets[index]
950 .reloc_str_id
951 .map(|id| shstrtab.get_offset(id))
952 .unwrap_or(0);
953 elf.write_section_header(
954 buffer,
955 SectionHeader {
956 sh_name: sh_name as u32,
957 sh_type: if is_rela { elf::SHT_RELA } else { elf::SHT_REL },
958 sh_flags: elf::SHF_INFO_LINK.into(),
959 sh_addr: 0,
960 sh_offset: section_offsets[index].reloc_offset as u64,
961 sh_size: section_offsets[index].reloc_len as u64,
962 sh_link: symtab_index as u32,
963 sh_info: section_offsets[index].index as u32,
964 sh_addralign: pointer_align as u64,
965 sh_entsize: elf.rel_size(is_rela) as u64,
966 },
967 );
968 }
969 }
970
971 // Write symtab section header.
972 elf.write_section_header(
973 buffer,
974 SectionHeader {
975 sh_name: shstrtab.get_offset(symtab_str_id) as u32,
976 sh_type: elf::SHT_SYMTAB,
977 sh_flags: 0,
978 sh_addr: 0,
979 sh_offset: symtab_offset as u64,
980 sh_size: symtab_len as u64,
981 sh_link: strtab_index as u32,
982 sh_info: symtab_count_local as u32,
983 sh_addralign: pointer_align as u64,
984 sh_entsize: elf.symbol_size() as u64,
985 },
986 );
987
988 // Write symtab_shndx section header.
989 if need_symtab_shndx {
990 elf.write_section_header(
991 buffer,
992 SectionHeader {
993 sh_name: shstrtab.get_offset(symtab_shndx_str_id.unwrap()) as u32,
994 sh_type: elf::SHT_SYMTAB_SHNDX,
995 sh_flags: 0,
996 sh_addr: 0,
997 sh_offset: symtab_shndx_offset as u64,
998 sh_size: symtab_shndx_len as u64,
999 sh_link: symtab_index as u32,
1000 sh_info: symtab_count_local as u32,
1001 sh_addralign: 4,
1002 sh_entsize: 4,
1003 },
1004 );
1005 }
1006
1007 // Write strtab section header.
1008 elf.write_section_header(
1009 buffer,
1010 SectionHeader {
1011 sh_name: shstrtab.get_offset(strtab_str_id) as u32,
1012 sh_type: elf::SHT_STRTAB,
1013 sh_flags: 0,
1014 sh_addr: 0,
1015 sh_offset: strtab_offset as u64,
1016 sh_size: strtab_data.len() as u64,
1017 sh_link: 0,
1018 sh_info: 0,
1019 sh_addralign: 1,
1020 sh_entsize: 0,
1021 },
1022 );
1023
1024 // Write shstrtab section header.
1025 elf.write_section_header(
1026 buffer,
1027 SectionHeader {
1028 sh_name: shstrtab.get_offset(shstrtab_str_id) as u32,
1029 sh_type: elf::SHT_STRTAB,
1030 sh_flags: 0,
1031 sh_addr: 0,
1032 sh_offset: shstrtab_offset as u64,
1033 sh_size: shstrtab_data.len() as u64,
1034 sh_link: 0,
1035 sh_info: 0,
1036 sh_addralign: 1,
1037 sh_entsize: 0,
1038 },
1039 );
1040
1041 debug_assert_eq!(offset, buffer.len());
1042
1043 Ok(())
1044 }
1045 }
1046
1047 /// Native endian version of `FileHeader64`.
1048 struct FileHeader {
1049 e_ident: elf::Ident,
1050 e_type: u16,
1051 e_machine: u16,
1052 e_version: u32,
1053 e_entry: u64,
1054 e_phoff: u64,
1055 e_shoff: u64,
1056 e_flags: u32,
1057 e_ehsize: u16,
1058 e_phentsize: u16,
1059 e_phnum: u16,
1060 e_shentsize: u16,
1061 e_shnum: u16,
1062 e_shstrndx: u16,
1063 }
1064
1065 /// Native endian version of `SectionHeader64`.
1066 struct SectionHeader {
1067 sh_name: u32,
1068 sh_type: u32,
1069 sh_flags: u64,
1070 sh_addr: u64,
1071 sh_offset: u64,
1072 sh_size: u64,
1073 sh_link: u32,
1074 sh_info: u32,
1075 sh_addralign: u64,
1076 sh_entsize: u64,
1077 }
1078
1079 /// Native endian version of `Sym64`.
1080 struct Sym {
1081 st_name: u32,
1082 st_info: u8,
1083 st_other: u8,
1084 st_shndx: u16,
1085 st_value: u64,
1086 st_size: u64,
1087 }
1088
1089 /// Unified native endian version of `Rel*`.
1090 struct Rel {
1091 r_offset: u64,
1092 r_sym: u32,
1093 r_type: u32,
1094 r_addend: i64,
1095 }
1096
1097 trait Elf {
1098 fn file_header_size(&self) -> usize;
1099 fn section_header_size(&self) -> usize;
1100 fn symbol_size(&self) -> usize;
1101 fn rel_size(&self, is_rela: bool) -> usize;
1102 fn write_file_header(&self, buffer: &mut dyn WritableBuffer, section: FileHeader);
1103 fn write_section_header(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader);
1104 fn write_symbol(&self, buffer: &mut dyn WritableBuffer, symbol: Sym);
1105 fn write_rel(
1106 &self,
1107 buffer: &mut dyn WritableBuffer,
1108 is_mips64el: bool,
1109 is_rela: bool,
1110 rel: Rel,
1111 );
1112 }
1113
1114 struct Elf32<E> {
1115 endian: E,
1116 }
1117
1118 impl<E: Endian> Elf for Elf32<E> {
1119 fn file_header_size(&self) -> usize {
1120 mem::size_of::<elf::FileHeader32<E>>()
1121 }
1122
1123 fn section_header_size(&self) -> usize {
1124 mem::size_of::<elf::SectionHeader32<E>>()
1125 }
1126
1127 fn symbol_size(&self) -> usize {
1128 mem::size_of::<elf::Sym32<E>>()
1129 }
1130
1131 fn rel_size(&self, is_rela: bool) -> usize {
1132 if is_rela {
1133 mem::size_of::<elf::Rela32<E>>()
1134 } else {
1135 mem::size_of::<elf::Rel32<E>>()
1136 }
1137 }
1138
1139 fn write_file_header(&self, buffer: &mut dyn WritableBuffer, file: FileHeader) {
1140 let endian = self.endian;
1141 let file = elf::FileHeader32 {
1142 e_ident: file.e_ident,
1143 e_type: U16::new(endian, file.e_type),
1144 e_machine: U16::new(endian, file.e_machine),
1145 e_version: U32::new(endian, file.e_version),
1146 e_entry: U32::new(endian, file.e_entry as u32),
1147 e_phoff: U32::new(endian, file.e_phoff as u32),
1148 e_shoff: U32::new(endian, file.e_shoff as u32),
1149 e_flags: U32::new(endian, file.e_flags),
1150 e_ehsize: U16::new(endian, file.e_ehsize),
1151 e_phentsize: U16::new(endian, file.e_phentsize),
1152 e_phnum: U16::new(endian, file.e_phnum),
1153 e_shentsize: U16::new(endian, file.e_shentsize),
1154 e_shnum: U16::new(endian, file.e_shnum),
1155 e_shstrndx: U16::new(endian, file.e_shstrndx),
1156 };
1157 buffer.write(&file);
1158 }
1159
1160 fn write_section_header(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader) {
1161 let endian = self.endian;
1162 let section = elf::SectionHeader32 {
1163 sh_name: U32::new(endian, section.sh_name),
1164 sh_type: U32::new(endian, section.sh_type),
1165 sh_flags: U32::new(endian, section.sh_flags as u32),
1166 sh_addr: U32::new(endian, section.sh_addr as u32),
1167 sh_offset: U32::new(endian, section.sh_offset as u32),
1168 sh_size: U32::new(endian, section.sh_size as u32),
1169 sh_link: U32::new(endian, section.sh_link),
1170 sh_info: U32::new(endian, section.sh_info),
1171 sh_addralign: U32::new(endian, section.sh_addralign as u32),
1172 sh_entsize: U32::new(endian, section.sh_entsize as u32),
1173 };
1174 buffer.write(&section);
1175 }
1176
1177 fn write_symbol(&self, buffer: &mut dyn WritableBuffer, symbol: Sym) {
1178 let endian = self.endian;
1179 let symbol = elf::Sym32 {
1180 st_name: U32::new(endian, symbol.st_name),
1181 st_info: symbol.st_info,
1182 st_other: symbol.st_other,
1183 st_shndx: U16::new(endian, symbol.st_shndx),
1184 st_value: U32::new(endian, symbol.st_value as u32),
1185 st_size: U32::new(endian, symbol.st_size as u32),
1186 };
1187 buffer.write(&symbol);
1188 }
1189
1190 fn write_rel(
1191 &self,
1192 buffer: &mut dyn WritableBuffer,
1193 _is_mips64el: bool,
1194 is_rela: bool,
1195 rel: Rel,
1196 ) {
1197 let endian = self.endian;
1198 if is_rela {
1199 let rel = elf::Rela32 {
1200 r_offset: U32::new(endian, rel.r_offset as u32),
1201 r_info: elf::Rel32::r_info(endian, rel.r_sym, rel.r_type as u8),
1202 r_addend: I32::new(endian, rel.r_addend as i32),
1203 };
1204 buffer.write(&rel);
1205 } else {
1206 let rel = elf::Rel32 {
1207 r_offset: U32::new(endian, rel.r_offset as u32),
1208 r_info: elf::Rel32::r_info(endian, rel.r_sym, rel.r_type as u8),
1209 };
1210 buffer.write(&rel);
1211 }
1212 }
1213 }
1214
1215 struct Elf64<E> {
1216 endian: E,
1217 }
1218
1219 impl<E: Endian> Elf for Elf64<E> {
1220 fn file_header_size(&self) -> usize {
1221 mem::size_of::<elf::FileHeader64<E>>()
1222 }
1223
1224 fn section_header_size(&self) -> usize {
1225 mem::size_of::<elf::SectionHeader64<E>>()
1226 }
1227
1228 fn symbol_size(&self) -> usize {
1229 mem::size_of::<elf::Sym64<E>>()
1230 }
1231
1232 fn rel_size(&self, is_rela: bool) -> usize {
1233 if is_rela {
1234 mem::size_of::<elf::Rela64<E>>()
1235 } else {
1236 mem::size_of::<elf::Rel64<E>>()
1237 }
1238 }
1239
1240 fn write_file_header(&self, buffer: &mut dyn WritableBuffer, file: FileHeader) {
1241 let endian = self.endian;
1242 let file = elf::FileHeader64 {
1243 e_ident: file.e_ident,
1244 e_type: U16::new(endian, file.e_type),
1245 e_machine: U16::new(endian, file.e_machine),
1246 e_version: U32::new(endian, file.e_version),
1247 e_entry: U64::new(endian, file.e_entry),
1248 e_phoff: U64::new(endian, file.e_phoff),
1249 e_shoff: U64::new(endian, file.e_shoff),
1250 e_flags: U32::new(endian, file.e_flags),
1251 e_ehsize: U16::new(endian, file.e_ehsize),
1252 e_phentsize: U16::new(endian, file.e_phentsize),
1253 e_phnum: U16::new(endian, file.e_phnum),
1254 e_shentsize: U16::new(endian, file.e_shentsize),
1255 e_shnum: U16::new(endian, file.e_shnum),
1256 e_shstrndx: U16::new(endian, file.e_shstrndx),
1257 };
1258 buffer.write(&file)
1259 }
1260
1261 fn write_section_header(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader) {
1262 let endian = self.endian;
1263 let section = elf::SectionHeader64 {
1264 sh_name: U32::new(endian, section.sh_name),
1265 sh_type: U32::new(endian, section.sh_type),
1266 sh_flags: U64::new(endian, section.sh_flags),
1267 sh_addr: U64::new(endian, section.sh_addr),
1268 sh_offset: U64::new(endian, section.sh_offset),
1269 sh_size: U64::new(endian, section.sh_size),
1270 sh_link: U32::new(endian, section.sh_link),
1271 sh_info: U32::new(endian, section.sh_info),
1272 sh_addralign: U64::new(endian, section.sh_addralign),
1273 sh_entsize: U64::new(endian, section.sh_entsize),
1274 };
1275 buffer.write(&section);
1276 }
1277
1278 fn write_symbol(&self, buffer: &mut dyn WritableBuffer, symbol: Sym) {
1279 let endian = self.endian;
1280 let symbol = elf::Sym64 {
1281 st_name: U32::new(endian, symbol.st_name),
1282 st_info: symbol.st_info,
1283 st_other: symbol.st_other,
1284 st_shndx: U16::new(endian, symbol.st_shndx),
1285 st_value: U64::new(endian, symbol.st_value),
1286 st_size: U64::new(endian, symbol.st_size),
1287 };
1288 buffer.write(&symbol);
1289 }
1290
1291 fn write_rel(
1292 &self,
1293 buffer: &mut dyn WritableBuffer,
1294 is_mips64el: bool,
1295 is_rela: bool,
1296 rel: Rel,
1297 ) {
1298 let endian = self.endian;
1299 if is_rela {
1300 let rel = elf::Rela64 {
1301 r_offset: U64::new(endian, rel.r_offset),
1302 r_info: elf::Rela64::r_info(endian, is_mips64el, rel.r_sym, rel.r_type),
1303 r_addend: I64::new(endian, rel.r_addend),
1304 };
1305 buffer.write(&rel);
1306 } else {
1307 let rel = elf::Rel64 {
1308 r_offset: U64::new(endian, rel.r_offset),
1309 r_info: elf::Rel64::r_info(endian, rel.r_sym, rel.r_type),
1310 };
1311 buffer.write(&rel);
1312 }
1313 }
1314 }