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 { elf_section_info( &self, section: StandardSection, ) -> (&'static [u8], &'static [u8], SectionKind)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 elf_subsection_name(&self, section: &[u8], value: &[u8]) -> Vec<u8>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 elf_has_relocation_addend(&self) -> Result<bool>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 elf_fixup_relocation(&mut self, mut relocation: &mut Relocation) -> Result<i64>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 elf_write(&self, buffer: &mut dyn WritableBuffer) -> Result<()>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(§ion.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(§ion.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(§ion.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 §ion.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 { file_header_size(&self) -> usize1098 fn file_header_size(&self) -> usize; section_header_size(&self) -> usize1099 fn section_header_size(&self) -> usize; symbol_size(&self) -> usize1100 fn symbol_size(&self) -> usize; rel_size(&self, is_rela: bool) -> usize1101 fn rel_size(&self, is_rela: bool) -> usize; write_file_header(&self, buffer: &mut dyn WritableBuffer, section: FileHeader)1102 fn write_file_header(&self, buffer: &mut dyn WritableBuffer, section: FileHeader); write_section_header(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader)1103 fn write_section_header(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader); write_symbol(&self, buffer: &mut dyn WritableBuffer, symbol: Sym)1104 fn write_symbol(&self, buffer: &mut dyn WritableBuffer, symbol: Sym); write_rel( &self, buffer: &mut dyn WritableBuffer, is_mips64el: bool, is_rela: bool, rel: Rel, )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> { file_header_size(&self) -> usize1119 fn file_header_size(&self) -> usize { 1120 mem::size_of::<elf::FileHeader32<E>>() 1121 } 1122 section_header_size(&self) -> usize1123 fn section_header_size(&self) -> usize { 1124 mem::size_of::<elf::SectionHeader32<E>>() 1125 } 1126 symbol_size(&self) -> usize1127 fn symbol_size(&self) -> usize { 1128 mem::size_of::<elf::Sym32<E>>() 1129 } 1130 rel_size(&self, is_rela: bool) -> usize1131 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 write_file_header(&self, buffer: &mut dyn WritableBuffer, file: FileHeader)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 write_section_header(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader)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(§ion); 1175 } 1176 write_symbol(&self, buffer: &mut dyn WritableBuffer, symbol: Sym)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 write_rel( &self, buffer: &mut dyn WritableBuffer, _is_mips64el: bool, is_rela: bool, rel: Rel, )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> { file_header_size(&self) -> usize1220 fn file_header_size(&self) -> usize { 1221 mem::size_of::<elf::FileHeader64<E>>() 1222 } 1223 section_header_size(&self) -> usize1224 fn section_header_size(&self) -> usize { 1225 mem::size_of::<elf::SectionHeader64<E>>() 1226 } 1227 symbol_size(&self) -> usize1228 fn symbol_size(&self) -> usize { 1229 mem::size_of::<elf::Sym64<E>>() 1230 } 1231 rel_size(&self, is_rela: bool) -> usize1232 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 write_file_header(&self, buffer: &mut dyn WritableBuffer, file: FileHeader)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 write_section_header(&self, buffer: &mut dyn WritableBuffer, section: SectionHeader)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(§ion); 1276 } 1277 write_symbol(&self, buffer: &mut dyn WritableBuffer, symbol: Sym)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 write_rel( &self, buffer: &mut dyn WritableBuffer, is_mips64el: bool, is_rela: bool, rel: Rel, )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 } 1315