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