1 use std::mem; 2 use std::vec::Vec; 3 4 use crate::elf; 5 use crate::endian::*; 6 use crate::pod::BytesMut; 7 use crate::write::string::*; 8 use crate::write::util::*; 9 use crate::write::*; 10 11 #[derive(Default, Clone, Copy)] 12 struct SectionOffsets { 13 index: usize, 14 offset: usize, 15 str_id: Option<StringId>, 16 reloc_index: usize, 17 reloc_offset: usize, 18 reloc_len: usize, 19 reloc_str_id: Option<StringId>, 20 } 21 22 #[derive(Default, Clone, Copy)] 23 struct SymbolOffsets { 24 index: usize, 25 str_id: Option<StringId>, 26 } 27 28 impl Object { elf_section_info( &self, section: StandardSection, ) -> (&'static [u8], &'static [u8], SectionKind)29 pub(crate) fn elf_section_info( 30 &self, 31 section: StandardSection, 32 ) -> (&'static [u8], &'static [u8], SectionKind) { 33 match section { 34 StandardSection::Text => (&[], &b".text"[..], SectionKind::Text), 35 StandardSection::Data => (&[], &b".data"[..], SectionKind::Data), 36 StandardSection::ReadOnlyData | StandardSection::ReadOnlyString => { 37 (&[], &b".rodata"[..], SectionKind::ReadOnlyData) 38 } 39 StandardSection::ReadOnlyDataWithRel => (&[], b".data.rel.ro", SectionKind::Data), 40 StandardSection::UninitializedData => { 41 (&[], &b".bss"[..], SectionKind::UninitializedData) 42 } 43 StandardSection::Tls => (&[], &b".tdata"[..], SectionKind::Tls), 44 StandardSection::UninitializedTls => { 45 (&[], &b".tbss"[..], SectionKind::UninitializedTls) 46 } 47 StandardSection::TlsVariables => { 48 // Unsupported section. 49 (&[], &[], SectionKind::TlsVariables) 50 } 51 StandardSection::Common => { 52 // Unsupported section. 53 (&[], &[], SectionKind::Common) 54 } 55 } 56 } 57 elf_subsection_name(&self, section: &[u8], value: &[u8]) -> Vec<u8>58 pub(crate) fn elf_subsection_name(&self, section: &[u8], value: &[u8]) -> Vec<u8> { 59 let mut name = section.to_vec(); 60 name.push(b'.'); 61 name.extend(value); 62 name 63 } 64 elf_has_relocation_addend(&self) -> Result<bool>65 fn elf_has_relocation_addend(&self) -> Result<bool> { 66 Ok(match self.architecture { 67 Architecture::Arm(_) => false, 68 Architecture::Aarch64(_) => false, 69 Architecture::I386 => false, 70 Architecture::X86_64 => true, 71 _ => { 72 return Err(Error(format!( 73 "unimplemented architecture {:?}", 74 self.architecture 75 ))); 76 } 77 }) 78 } 79 elf_fixup_relocation(&mut self, mut relocation: &mut Relocation) -> Result<i64>80 pub(crate) fn elf_fixup_relocation(&mut self, mut relocation: &mut Relocation) -> Result<i64> { 81 // Return true if we should use a section symbol to avoid preemption. 82 fn want_section_symbol(relocation: &Relocation, symbol: &Symbol) -> bool { 83 if symbol.scope != SymbolScope::Dynamic { 84 // Only dynamic symbols can be preemptible. 85 return false; 86 } 87 match symbol.kind { 88 SymbolKind::Text | SymbolKind::Data => {} 89 _ => return false, 90 } 91 match relocation.kind { 92 // Anything using GOT or PLT is preemptible. 93 // We also require that `Other` relocations must already be correct. 94 RelocationKind::Got 95 | RelocationKind::GotRelative 96 | RelocationKind::GotBaseRelative 97 | RelocationKind::PltRelative 98 | RelocationKind::Elf(_) => return false, 99 // Absolute relocations are preemptible for non-local data. 100 // TODO: not sure if this rule is exactly correct 101 // This rule was added to handle global data references in debuginfo. 102 // Maybe this should be a new relocation kind so that the caller can decide. 103 RelocationKind::Absolute => { 104 if symbol.kind == SymbolKind::Data { 105 return false; 106 } 107 } 108 _ => {} 109 } 110 true 111 } 112 113 // Use section symbols for relocations where required to avoid preemption. 114 // Otherwise, the linker will fail with: 115 // relocation R_X86_64_PC32 against symbol `SomeSymbolName' can not be used when 116 // making a shared object; recompile with -fPIC 117 let symbol = &self.symbols[relocation.symbol.0]; 118 if want_section_symbol(relocation, symbol) { 119 if let Some(section) = symbol.section.id() { 120 relocation.addend += symbol.value as i64; 121 relocation.symbol = self.section_symbol(section); 122 } 123 } 124 125 // Determine whether the addend is stored in the relocation or the data. 126 if self.elf_has_relocation_addend()? { 127 Ok(0) 128 } else { 129 let constant = relocation.addend; 130 relocation.addend = 0; 131 Ok(constant) 132 } 133 } 134 elf_write(&self) -> Result<Vec<u8>>135 pub(crate) fn elf_write(&self) -> Result<Vec<u8>> { 136 let (is_32, pointer_align) = match self.architecture.pointer_width().unwrap() { 137 PointerWidth::U16 | PointerWidth::U32 => (true, 4), 138 PointerWidth::U64 => (false, 8), 139 }; 140 let endian = match self.architecture.endianness().unwrap() { 141 Endianness::Little => RunTimeEndian::Little, 142 Endianness::Big => RunTimeEndian::Big, 143 }; 144 let elf32 = Elf32 { endian }; 145 let elf64 = Elf64 { endian }; 146 let elf: &dyn Elf = if is_32 { &elf32 } else { &elf64 }; 147 148 // Calculate offsets of everything. 149 let mut offset = 0; 150 151 // ELF header. 152 let e_ehsize = elf.file_header_size(); 153 offset += e_ehsize; 154 155 // Create reloc section header names. 156 let is_rela = self.elf_has_relocation_addend()?; 157 let reloc_names: Vec<_> = self 158 .sections 159 .iter() 160 .map(|section| { 161 let mut reloc_name = Vec::new(); 162 if !section.relocations.is_empty() { 163 reloc_name.extend_from_slice(if is_rela { 164 &b".rela"[..] 165 } else { 166 &b".rel"[..] 167 }); 168 reloc_name.extend_from_slice(§ion.name); 169 } 170 reloc_name 171 }) 172 .collect(); 173 174 // Calculate size of section data. 175 let mut shstrtab = StringTable::default(); 176 let mut section_offsets = vec![SectionOffsets::default(); self.sections.len()]; 177 // Null section. 178 let mut section_num = 1; 179 for (index, section) in self.sections.iter().enumerate() { 180 section_offsets[index].str_id = Some(shstrtab.add(§ion.name)); 181 section_offsets[index].index = section_num; 182 section_num += 1; 183 184 let len = section.data.len(); 185 if len != 0 { 186 offset = align(offset, section.align as usize); 187 section_offsets[index].offset = offset; 188 offset += len; 189 } else { 190 section_offsets[index].offset = offset; 191 } 192 193 if !section.relocations.is_empty() { 194 section_offsets[index].reloc_str_id = Some(shstrtab.add(&reloc_names[index])); 195 section_offsets[index].reloc_index = section_num; 196 section_num += 1; 197 } 198 } 199 200 // Calculate index of symbols and add symbol strings to strtab. 201 let mut strtab = StringTable::default(); 202 let mut symbol_offsets = vec![SymbolOffsets::default(); self.symbols.len()]; 203 // Null symbol. 204 let mut symtab_count = 1; 205 // Local symbols must come before global. 206 for (index, symbol) in self.symbols.iter().enumerate() { 207 if symbol.is_local() { 208 symbol_offsets[index].index = symtab_count; 209 symtab_count += 1; 210 } 211 } 212 let symtab_count_local = symtab_count; 213 for (index, symbol) in self.symbols.iter().enumerate() { 214 if !symbol.is_local() { 215 symbol_offsets[index].index = symtab_count; 216 symtab_count += 1; 217 } 218 } 219 for (index, symbol) in self.symbols.iter().enumerate() { 220 if symbol.kind != SymbolKind::Section { 221 symbol_offsets[index].str_id = Some(strtab.add(&symbol.name)); 222 } 223 } 224 225 // Calculate size of symtab. 226 let symtab_str_id = shstrtab.add(&b".symtab"[..]); 227 offset = align(offset, pointer_align); 228 let symtab_offset = offset; 229 let symtab_len = symtab_count * elf.symbol_size(); 230 offset += symtab_len; 231 let symtab_index = section_num; 232 section_num += 1; 233 234 // Calculate size of symtab_shndx. 235 let mut need_symtab_shndx = false; 236 for symbol in &self.symbols { 237 let index = symbol 238 .section 239 .id() 240 .map(|s| section_offsets[s.0].index) 241 .unwrap_or(0); 242 if index >= elf::SHN_LORESERVE as usize { 243 need_symtab_shndx = true; 244 break; 245 } 246 } 247 let symtab_shndx_offset = offset; 248 let mut symtab_shndx_str_id = None; 249 let mut symtab_shndx_len = 0; 250 if need_symtab_shndx { 251 symtab_shndx_str_id = Some(shstrtab.add(&b".symtab_shndx"[..])); 252 symtab_shndx_len = symtab_count * 4; 253 offset += symtab_shndx_len; 254 section_num += 1; 255 } 256 257 // Calculate size of strtab. 258 let strtab_str_id = shstrtab.add(&b".strtab"[..]); 259 let strtab_offset = offset; 260 let mut strtab_data = Vec::new(); 261 // Null name. 262 strtab_data.push(0); 263 strtab.write(1, &mut strtab_data); 264 offset += strtab_data.len(); 265 let strtab_index = section_num; 266 section_num += 1; 267 268 // Calculate size of relocations. 269 for (index, section) in self.sections.iter().enumerate() { 270 let count = section.relocations.len(); 271 if count != 0 { 272 offset = align(offset, pointer_align); 273 section_offsets[index].reloc_offset = offset; 274 let len = count * elf.rel_size(is_rela); 275 section_offsets[index].reloc_len = len; 276 offset += len; 277 } 278 } 279 280 // Calculate size of shstrtab. 281 let shstrtab_str_id = shstrtab.add(&b".shstrtab"[..]); 282 let shstrtab_offset = offset; 283 let mut shstrtab_data = Vec::new(); 284 // Null section name. 285 shstrtab_data.push(0); 286 shstrtab.write(1, &mut shstrtab_data); 287 offset += shstrtab_data.len(); 288 let shstrtab_index = section_num; 289 section_num += 1; 290 291 // Calculate size of section headers. 292 offset = align(offset, pointer_align); 293 let e_shoff = offset; 294 let e_shentsize = elf.section_header_size(); 295 offset += section_num * e_shentsize; 296 297 // Start writing. 298 let mut buffer = BytesMut(Vec::with_capacity(offset)); 299 300 // Write file header. 301 let e_ident = elf::Ident { 302 magic: elf::ELFMAG, 303 class: if is_32 { 304 elf::ELFCLASS32 305 } else { 306 elf::ELFCLASS64 307 }, 308 data: if endian.is_little_endian() { 309 elf::ELFDATA2LSB 310 } else { 311 elf::ELFDATA2MSB 312 }, 313 version: elf::EV_CURRENT, 314 os_abi: elf::ELFOSABI_NONE, 315 abi_version: 0, 316 padding: [0; 7], 317 }; 318 let e_type = elf::ET_REL; 319 let e_machine = match self.architecture { 320 Architecture::Arm(_) => elf::EM_ARM, 321 Architecture::Aarch64(_) => elf::EM_AARCH64, 322 Architecture::I386 => elf::EM_386, 323 Architecture::X86_64 => elf::EM_X86_64, 324 _ => { 325 return Err(Error(format!( 326 "unimplemented architecture {:?}", 327 self.architecture 328 ))); 329 } 330 }; 331 let e_flags = if let FileFlags::Elf { e_flags } = self.flags { 332 e_flags 333 } else { 334 0 335 }; 336 let e_shnum = if section_num >= elf::SHN_LORESERVE as usize { 337 0 338 } else { 339 section_num as u16 340 }; 341 let e_shstrndx = if shstrtab_index >= elf::SHN_LORESERVE as usize { 342 elf::SHN_XINDEX 343 } else { 344 shstrtab_index as u16 345 }; 346 347 elf.write_file_header( 348 &mut buffer, 349 FileHeader { 350 e_ident, 351 e_type, 352 e_machine, 353 e_version: elf::EV_CURRENT.into(), 354 e_entry: 0, 355 e_phoff: 0, 356 e_shoff: e_shoff as u64, 357 e_flags, 358 e_ehsize: e_ehsize as u16, 359 e_phentsize: 0, 360 e_phnum: 0, 361 e_shentsize: e_shentsize as u16, 362 e_shnum, 363 e_shstrndx, 364 }, 365 ); 366 367 // Write section data. 368 for (index, section) in self.sections.iter().enumerate() { 369 let len = section.data.len(); 370 if len != 0 { 371 write_align(&mut buffer, section.align as usize); 372 debug_assert_eq!(section_offsets[index].offset, buffer.len()); 373 buffer.write_bytes(§ion.data); 374 } 375 } 376 377 // Write symbols. 378 write_align(&mut buffer, pointer_align); 379 debug_assert_eq!(symtab_offset, buffer.len()); 380 elf.write_symbol( 381 &mut buffer, 382 Sym { 383 st_name: 0, 384 st_info: 0, 385 st_other: 0, 386 st_shndx: 0, 387 st_value: 0, 388 st_size: 0, 389 }, 390 ); 391 let mut symtab_shndx = BytesMut::new(); 392 if need_symtab_shndx { 393 symtab_shndx.write(&U32::new(endian, 0)); 394 } 395 let mut write_symbol = |index: usize, symbol: &Symbol| -> Result<()> { 396 let st_info = if let SymbolFlags::Elf { st_info, .. } = symbol.flags { 397 st_info 398 } else { 399 let st_type = match symbol.kind { 400 SymbolKind::Null => elf::STT_NOTYPE, 401 SymbolKind::Text => { 402 if symbol.is_undefined() { 403 elf::STT_NOTYPE 404 } else { 405 elf::STT_FUNC 406 } 407 } 408 SymbolKind::Data => { 409 if symbol.is_undefined() { 410 elf::STT_NOTYPE 411 } else if symbol.is_common() { 412 elf::STT_COMMON 413 } else { 414 elf::STT_OBJECT 415 } 416 } 417 SymbolKind::Section => elf::STT_SECTION, 418 SymbolKind::File => elf::STT_FILE, 419 SymbolKind::Tls => elf::STT_TLS, 420 SymbolKind::Label => elf::STT_NOTYPE, 421 SymbolKind::Unknown => { 422 if symbol.is_undefined() { 423 elf::STT_NOTYPE 424 } else { 425 return Err(Error(format!( 426 "unimplemented symbol `{}` kind {:?}", 427 symbol.name().unwrap_or(""), 428 symbol.kind 429 ))); 430 } 431 } 432 }; 433 let st_bind = if symbol.is_undefined() { 434 elf::STB_GLOBAL 435 } else if symbol.is_local() { 436 elf::STB_LOCAL 437 } else if symbol.weak { 438 elf::STB_WEAK 439 } else { 440 elf::STB_GLOBAL 441 }; 442 (st_bind << 4) + st_type 443 }; 444 let st_other = if let SymbolFlags::Elf { st_other, .. } = symbol.flags { 445 st_other 446 } else if symbol.scope == SymbolScope::Linkage { 447 elf::STV_HIDDEN 448 } else { 449 elf::STV_DEFAULT 450 }; 451 let (st_shndx, xindex) = match symbol.section { 452 SymbolSection::None => { 453 debug_assert_eq!(symbol.kind, SymbolKind::File); 454 (elf::SHN_ABS, 0) 455 } 456 SymbolSection::Undefined => (elf::SHN_UNDEF, 0), 457 SymbolSection::Absolute => (elf::SHN_ABS, 0), 458 SymbolSection::Common => (elf::SHN_COMMON, 0), 459 SymbolSection::Section(id) => { 460 let index = section_offsets[id.0].index as u32; 461 ( 462 if index >= elf::SHN_LORESERVE as u32 { 463 elf::SHN_XINDEX 464 } else { 465 index as u16 466 }, 467 index, 468 ) 469 } 470 }; 471 let st_name = symbol_offsets[index] 472 .str_id 473 .map(|id| strtab.get_offset(id)) 474 .unwrap_or(0) as u32; 475 elf.write_symbol( 476 &mut buffer, 477 Sym { 478 st_name, 479 st_info, 480 st_other, 481 st_shndx, 482 st_value: symbol.value, 483 st_size: symbol.size, 484 }, 485 ); 486 if need_symtab_shndx { 487 symtab_shndx.write(&U32::new(endian, xindex)); 488 } 489 Ok(()) 490 }; 491 for (index, symbol) in self.symbols.iter().enumerate() { 492 if symbol.is_local() { 493 write_symbol(index, symbol)?; 494 } 495 } 496 for (index, symbol) in self.symbols.iter().enumerate() { 497 if !symbol.is_local() { 498 write_symbol(index, symbol)?; 499 } 500 } 501 if need_symtab_shndx { 502 debug_assert_eq!(symtab_shndx_offset, buffer.len()); 503 debug_assert_eq!(symtab_shndx_len, symtab_shndx.len()); 504 buffer.write_bytes(&symtab_shndx); 505 } 506 507 // Write strtab section. 508 debug_assert_eq!(strtab_offset, buffer.len()); 509 buffer.extend(&strtab_data); 510 511 // Write relocations. 512 for (index, section) in self.sections.iter().enumerate() { 513 if !section.relocations.is_empty() { 514 write_align(&mut buffer, pointer_align); 515 debug_assert_eq!(section_offsets[index].reloc_offset, buffer.len()); 516 for reloc in §ion.relocations { 517 let r_type = match self.architecture { 518 Architecture::I386 => match (reloc.kind, reloc.size) { 519 (RelocationKind::Absolute, 32) => elf::R_386_32, 520 (RelocationKind::Relative, 32) => elf::R_386_PC32, 521 (RelocationKind::Got, 32) => elf::R_386_GOT32, 522 (RelocationKind::PltRelative, 32) => elf::R_386_PLT32, 523 (RelocationKind::GotBaseOffset, 32) => elf::R_386_GOTOFF, 524 (RelocationKind::GotBaseRelative, 32) => elf::R_386_GOTPC, 525 (RelocationKind::Absolute, 16) => elf::R_386_16, 526 (RelocationKind::Relative, 16) => elf::R_386_PC16, 527 (RelocationKind::Absolute, 8) => elf::R_386_8, 528 (RelocationKind::Relative, 8) => elf::R_386_PC8, 529 (RelocationKind::Elf(x), _) => x, 530 _ => { 531 return Err(Error(format!("unimplemented relocation {:?}", reloc))); 532 } 533 }, 534 Architecture::X86_64 => match (reloc.kind, reloc.encoding, reloc.size) { 535 (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => { 536 elf::R_X86_64_64 537 } 538 (RelocationKind::Relative, _, 32) => elf::R_X86_64_PC32, 539 (RelocationKind::Got, _, 32) => elf::R_X86_64_GOT32, 540 (RelocationKind::PltRelative, _, 32) => elf::R_X86_64_PLT32, 541 (RelocationKind::GotRelative, _, 32) => elf::R_X86_64_GOTPCREL, 542 (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => { 543 elf::R_X86_64_32 544 } 545 (RelocationKind::Absolute, RelocationEncoding::X86Signed, 32) => { 546 elf::R_X86_64_32S 547 } 548 (RelocationKind::Absolute, _, 16) => elf::R_X86_64_16, 549 (RelocationKind::Relative, _, 16) => elf::R_X86_64_PC16, 550 (RelocationKind::Absolute, _, 8) => elf::R_X86_64_8, 551 (RelocationKind::Relative, _, 8) => elf::R_X86_64_PC8, 552 (RelocationKind::Elf(x), _, _) => x, 553 _ => { 554 return Err(Error(format!("unimplemented relocation {:?}", reloc))); 555 } 556 }, 557 _ => { 558 return Err(Error(format!( 559 "unimplemented architecture {:?}", 560 self.architecture 561 ))); 562 } 563 }; 564 let r_sym = symbol_offsets[reloc.symbol.0].index as u32; 565 elf.write_rel( 566 &mut buffer, 567 is_rela, 568 Rel { 569 r_offset: reloc.offset, 570 r_sym, 571 r_type, 572 r_addend: reloc.addend, 573 }, 574 ); 575 } 576 } 577 } 578 579 // Write shstrtab section. 580 debug_assert_eq!(shstrtab_offset, buffer.len()); 581 buffer.extend(&shstrtab_data); 582 583 // Write section headers. 584 write_align(&mut buffer, pointer_align); 585 debug_assert_eq!(e_shoff, buffer.len()); 586 elf.write_section_header( 587 &mut buffer, 588 SectionHeader { 589 sh_name: 0, 590 sh_type: 0, 591 sh_flags: 0, 592 sh_addr: 0, 593 sh_offset: 0, 594 sh_size: if section_num >= elf::SHN_LORESERVE as usize { 595 section_num as u64 596 } else { 597 0 598 }, 599 sh_link: if shstrtab_index >= elf::SHN_LORESERVE as usize { 600 shstrtab_index as u32 601 } else { 602 0 603 }, 604 // TODO: e_phnum overflow 605 sh_info: 0, 606 sh_addralign: 0, 607 sh_entsize: 0, 608 }, 609 ); 610 for (index, section) in self.sections.iter().enumerate() { 611 let sh_type = match section.kind { 612 SectionKind::UninitializedData | SectionKind::UninitializedTls => elf::SHT_NOBITS, 613 _ => elf::SHT_PROGBITS, 614 }; 615 let sh_flags = if let SectionFlags::Elf { sh_flags } = section.flags { 616 sh_flags 617 } else { 618 match section.kind { 619 SectionKind::Text => elf::SHF_ALLOC | elf::SHF_EXECINSTR, 620 SectionKind::Data => elf::SHF_ALLOC | elf::SHF_WRITE, 621 SectionKind::Tls => elf::SHF_ALLOC | elf::SHF_WRITE | elf::SHF_TLS, 622 SectionKind::UninitializedData => elf::SHF_ALLOC | elf::SHF_WRITE, 623 SectionKind::UninitializedTls => elf::SHF_ALLOC | elf::SHF_WRITE | elf::SHF_TLS, 624 SectionKind::ReadOnlyData => elf::SHF_ALLOC, 625 SectionKind::ReadOnlyString => { 626 elf::SHF_ALLOC | elf::SHF_STRINGS | elf::SHF_MERGE 627 } 628 SectionKind::OtherString => elf::SHF_STRINGS | elf::SHF_MERGE, 629 SectionKind::Other 630 | SectionKind::Debug 631 | SectionKind::Metadata 632 | SectionKind::Linker => 0, 633 SectionKind::Unknown | SectionKind::Common | SectionKind::TlsVariables => { 634 return Err(Error(format!( 635 "unimplemented section `{}` kind {:?}", 636 section.name().unwrap_or(""), 637 section.kind 638 ))); 639 } 640 } 641 .into() 642 }; 643 // TODO: not sure if this is correct, maybe user should determine this 644 let sh_entsize = match section.kind { 645 SectionKind::ReadOnlyString | SectionKind::OtherString => 1, 646 _ => 0, 647 }; 648 let sh_name = section_offsets[index] 649 .str_id 650 .map(|id| shstrtab.get_offset(id)) 651 .unwrap_or(0) as u32; 652 elf.write_section_header( 653 &mut buffer, 654 SectionHeader { 655 sh_name, 656 sh_type, 657 sh_flags, 658 sh_addr: 0, 659 sh_offset: section_offsets[index].offset as u64, 660 sh_size: section.size, 661 sh_link: 0, 662 sh_info: 0, 663 sh_addralign: section.align, 664 sh_entsize, 665 }, 666 ); 667 668 if !section.relocations.is_empty() { 669 let sh_name = section_offsets[index] 670 .reloc_str_id 671 .map(|id| shstrtab.get_offset(id)) 672 .unwrap_or(0); 673 elf.write_section_header( 674 &mut buffer, 675 SectionHeader { 676 sh_name: sh_name as u32, 677 sh_type: if is_rela { elf::SHT_RELA } else { elf::SHT_REL }, 678 sh_flags: elf::SHF_INFO_LINK.into(), 679 sh_addr: 0, 680 sh_offset: section_offsets[index].reloc_offset as u64, 681 sh_size: section_offsets[index].reloc_len as u64, 682 sh_link: symtab_index as u32, 683 sh_info: section_offsets[index].index as u32, 684 sh_addralign: pointer_align as u64, 685 sh_entsize: elf.rel_size(is_rela) as u64, 686 }, 687 ); 688 } 689 } 690 691 // Write symtab section header. 692 elf.write_section_header( 693 &mut buffer, 694 SectionHeader { 695 sh_name: shstrtab.get_offset(symtab_str_id) as u32, 696 sh_type: elf::SHT_SYMTAB, 697 sh_flags: 0, 698 sh_addr: 0, 699 sh_offset: symtab_offset as u64, 700 sh_size: symtab_len as u64, 701 sh_link: strtab_index as u32, 702 sh_info: symtab_count_local as u32, 703 sh_addralign: pointer_align as u64, 704 sh_entsize: elf.symbol_size() as u64, 705 }, 706 ); 707 708 // Write symtab_shndx section header. 709 if need_symtab_shndx { 710 elf.write_section_header( 711 &mut buffer, 712 SectionHeader { 713 sh_name: shstrtab.get_offset(symtab_shndx_str_id.unwrap()) as u32, 714 sh_type: elf::SHT_SYMTAB_SHNDX, 715 sh_flags: 0, 716 sh_addr: 0, 717 sh_offset: symtab_shndx_offset as u64, 718 sh_size: symtab_shndx_len as u64, 719 sh_link: symtab_index as u32, 720 sh_info: symtab_count_local as u32, 721 sh_addralign: 4, 722 sh_entsize: 4, 723 }, 724 ); 725 } 726 727 // Write strtab section header. 728 elf.write_section_header( 729 &mut buffer, 730 SectionHeader { 731 sh_name: shstrtab.get_offset(strtab_str_id) as u32, 732 sh_type: elf::SHT_STRTAB, 733 sh_flags: 0, 734 sh_addr: 0, 735 sh_offset: strtab_offset as u64, 736 sh_size: strtab_data.len() as u64, 737 sh_link: 0, 738 sh_info: 0, 739 sh_addralign: 1, 740 sh_entsize: 0, 741 }, 742 ); 743 744 // Write shstrtab section header. 745 elf.write_section_header( 746 &mut buffer, 747 SectionHeader { 748 sh_name: shstrtab.get_offset(shstrtab_str_id) as u32, 749 sh_type: elf::SHT_STRTAB, 750 sh_flags: 0, 751 sh_addr: 0, 752 sh_offset: shstrtab_offset as u64, 753 sh_size: shstrtab_data.len() as u64, 754 sh_link: 0, 755 sh_info: 0, 756 sh_addralign: 1, 757 sh_entsize: 0, 758 }, 759 ); 760 761 Ok(buffer.0) 762 } 763 } 764 765 /// Native endian version of `FileHeader64`. 766 struct FileHeader { 767 e_ident: elf::Ident, 768 e_type: u16, 769 e_machine: u16, 770 e_version: u32, 771 e_entry: u64, 772 e_phoff: u64, 773 e_shoff: u64, 774 e_flags: u32, 775 e_ehsize: u16, 776 e_phentsize: u16, 777 e_phnum: u16, 778 e_shentsize: u16, 779 e_shnum: u16, 780 e_shstrndx: u16, 781 } 782 783 /// Native endian version of `SectionHeader64`. 784 struct SectionHeader { 785 sh_name: u32, 786 sh_type: u32, 787 sh_flags: u64, 788 sh_addr: u64, 789 sh_offset: u64, 790 sh_size: u64, 791 sh_link: u32, 792 sh_info: u32, 793 sh_addralign: u64, 794 sh_entsize: u64, 795 } 796 797 /// Native endian version of `Sym64`. 798 struct Sym { 799 st_name: u32, 800 st_info: u8, 801 st_other: u8, 802 st_shndx: u16, 803 st_value: u64, 804 st_size: u64, 805 } 806 807 /// Unified native endian version of `Rel*`. 808 struct Rel { 809 r_offset: u64, 810 r_sym: u32, 811 r_type: u32, 812 r_addend: i64, 813 } 814 815 trait Elf { file_header_size(&self) -> usize816 fn file_header_size(&self) -> usize; section_header_size(&self) -> usize817 fn section_header_size(&self) -> usize; symbol_size(&self) -> usize818 fn symbol_size(&self) -> usize; rel_size(&self, is_rela: bool) -> usize819 fn rel_size(&self, is_rela: bool) -> usize; write_file_header(&self, buffer: &mut BytesMut, section: FileHeader)820 fn write_file_header(&self, buffer: &mut BytesMut, section: FileHeader); write_section_header(&self, buffer: &mut BytesMut, section: SectionHeader)821 fn write_section_header(&self, buffer: &mut BytesMut, section: SectionHeader); write_symbol(&self, buffer: &mut BytesMut, symbol: Sym)822 fn write_symbol(&self, buffer: &mut BytesMut, symbol: Sym); write_rel(&self, buffer: &mut BytesMut, is_rela: bool, rel: Rel)823 fn write_rel(&self, buffer: &mut BytesMut, is_rela: bool, rel: Rel); 824 } 825 826 struct Elf32<E> { 827 endian: E, 828 } 829 830 impl<E: Endian> Elf for Elf32<E> { file_header_size(&self) -> usize831 fn file_header_size(&self) -> usize { 832 mem::size_of::<elf::FileHeader32<E>>() 833 } 834 section_header_size(&self) -> usize835 fn section_header_size(&self) -> usize { 836 mem::size_of::<elf::SectionHeader32<E>>() 837 } 838 symbol_size(&self) -> usize839 fn symbol_size(&self) -> usize { 840 mem::size_of::<elf::Sym32<E>>() 841 } 842 rel_size(&self, is_rela: bool) -> usize843 fn rel_size(&self, is_rela: bool) -> usize { 844 if is_rela { 845 mem::size_of::<elf::Rela32<E>>() 846 } else { 847 mem::size_of::<elf::Rel32<E>>() 848 } 849 } 850 write_file_header(&self, buffer: &mut BytesMut, file: FileHeader)851 fn write_file_header(&self, buffer: &mut BytesMut, file: FileHeader) { 852 let endian = self.endian; 853 let file = elf::FileHeader32 { 854 e_ident: file.e_ident, 855 e_type: U16::new(endian, file.e_type), 856 e_machine: U16::new(endian, file.e_machine), 857 e_version: U32::new(endian, file.e_version), 858 e_entry: U32::new(endian, file.e_entry as u32), 859 e_phoff: U32::new(endian, file.e_phoff as u32), 860 e_shoff: U32::new(endian, file.e_shoff as u32), 861 e_flags: U32::new(endian, file.e_flags), 862 e_ehsize: U16::new(endian, file.e_ehsize), 863 e_phentsize: U16::new(endian, file.e_phentsize), 864 e_phnum: U16::new(endian, file.e_phnum), 865 e_shentsize: U16::new(endian, file.e_shentsize), 866 e_shnum: U16::new(endian, file.e_shnum), 867 e_shstrndx: U16::new(endian, file.e_shstrndx), 868 }; 869 buffer.write(&file); 870 } 871 write_section_header(&self, buffer: &mut BytesMut, section: SectionHeader)872 fn write_section_header(&self, buffer: &mut BytesMut, section: SectionHeader) { 873 let endian = self.endian; 874 let section = elf::SectionHeader32 { 875 sh_name: U32::new(endian, section.sh_name), 876 sh_type: U32::new(endian, section.sh_type), 877 sh_flags: U32::new(endian, section.sh_flags as u32), 878 sh_addr: U32::new(endian, section.sh_addr as u32), 879 sh_offset: U32::new(endian, section.sh_offset as u32), 880 sh_size: U32::new(endian, section.sh_size as u32), 881 sh_link: U32::new(endian, section.sh_link), 882 sh_info: U32::new(endian, section.sh_info), 883 sh_addralign: U32::new(endian, section.sh_addralign as u32), 884 sh_entsize: U32::new(endian, section.sh_entsize as u32), 885 }; 886 buffer.write(§ion); 887 } 888 write_symbol(&self, buffer: &mut BytesMut, symbol: Sym)889 fn write_symbol(&self, buffer: &mut BytesMut, symbol: Sym) { 890 let endian = self.endian; 891 let symbol = elf::Sym32 { 892 st_name: U32::new(endian, symbol.st_name), 893 st_info: symbol.st_info, 894 st_other: symbol.st_other, 895 st_shndx: U16::new(endian, symbol.st_shndx), 896 st_value: U32::new(endian, symbol.st_value as u32), 897 st_size: U32::new(endian, symbol.st_size as u32), 898 }; 899 buffer.write(&symbol); 900 } 901 write_rel(&self, buffer: &mut BytesMut, is_rela: bool, rel: Rel)902 fn write_rel(&self, buffer: &mut BytesMut, is_rela: bool, rel: Rel) { 903 let endian = self.endian; 904 if is_rela { 905 let rel = elf::Rela32 { 906 r_offset: U32::new(endian, rel.r_offset as u32), 907 r_info: elf::Rel32::r_info(endian, rel.r_sym, rel.r_type as u8), 908 r_addend: I32::new(endian, rel.r_addend as i32), 909 }; 910 buffer.write(&rel); 911 } else { 912 let rel = elf::Rel32 { 913 r_offset: U32::new(endian, rel.r_offset as u32), 914 r_info: elf::Rel32::r_info(endian, rel.r_sym, rel.r_type as u8), 915 }; 916 buffer.write(&rel); 917 } 918 } 919 } 920 921 struct Elf64<E> { 922 endian: E, 923 } 924 925 impl<E: Endian> Elf for Elf64<E> { file_header_size(&self) -> usize926 fn file_header_size(&self) -> usize { 927 mem::size_of::<elf::FileHeader64<E>>() 928 } 929 section_header_size(&self) -> usize930 fn section_header_size(&self) -> usize { 931 mem::size_of::<elf::SectionHeader64<E>>() 932 } 933 symbol_size(&self) -> usize934 fn symbol_size(&self) -> usize { 935 mem::size_of::<elf::Sym64<E>>() 936 } 937 rel_size(&self, is_rela: bool) -> usize938 fn rel_size(&self, is_rela: bool) -> usize { 939 if is_rela { 940 mem::size_of::<elf::Rela64<E>>() 941 } else { 942 mem::size_of::<elf::Rel64<E>>() 943 } 944 } 945 write_file_header(&self, buffer: &mut BytesMut, file: FileHeader)946 fn write_file_header(&self, buffer: &mut BytesMut, file: FileHeader) { 947 let endian = self.endian; 948 let file = elf::FileHeader64 { 949 e_ident: file.e_ident, 950 e_type: U16::new(endian, file.e_type), 951 e_machine: U16::new(endian, file.e_machine), 952 e_version: U32::new(endian, file.e_version), 953 e_entry: U64::new(endian, file.e_entry), 954 e_phoff: U64::new(endian, file.e_phoff), 955 e_shoff: U64::new(endian, file.e_shoff), 956 e_flags: U32::new(endian, file.e_flags), 957 e_ehsize: U16::new(endian, file.e_ehsize), 958 e_phentsize: U16::new(endian, file.e_phentsize), 959 e_phnum: U16::new(endian, file.e_phnum), 960 e_shentsize: U16::new(endian, file.e_shentsize), 961 e_shnum: U16::new(endian, file.e_shnum), 962 e_shstrndx: U16::new(endian, file.e_shstrndx), 963 }; 964 buffer.write(&file) 965 } 966 write_section_header(&self, buffer: &mut BytesMut, section: SectionHeader)967 fn write_section_header(&self, buffer: &mut BytesMut, section: SectionHeader) { 968 let endian = self.endian; 969 let section = elf::SectionHeader64 { 970 sh_name: U32::new(endian, section.sh_name), 971 sh_type: U32::new(endian, section.sh_type), 972 sh_flags: U64::new(endian, section.sh_flags), 973 sh_addr: U64::new(endian, section.sh_addr), 974 sh_offset: U64::new(endian, section.sh_offset), 975 sh_size: U64::new(endian, section.sh_size), 976 sh_link: U32::new(endian, section.sh_link), 977 sh_info: U32::new(endian, section.sh_info), 978 sh_addralign: U64::new(endian, section.sh_addralign), 979 sh_entsize: U64::new(endian, section.sh_entsize), 980 }; 981 buffer.write(§ion); 982 } 983 write_symbol(&self, buffer: &mut BytesMut, symbol: Sym)984 fn write_symbol(&self, buffer: &mut BytesMut, symbol: Sym) { 985 let endian = self.endian; 986 let symbol = elf::Sym64 { 987 st_name: U32::new(endian, symbol.st_name), 988 st_info: symbol.st_info, 989 st_other: symbol.st_other, 990 st_shndx: U16::new(endian, symbol.st_shndx), 991 st_value: U64::new(endian, symbol.st_value), 992 st_size: U64::new(endian, symbol.st_size), 993 }; 994 buffer.write(&symbol); 995 } 996 write_rel(&self, buffer: &mut BytesMut, is_rela: bool, rel: Rel)997 fn write_rel(&self, buffer: &mut BytesMut, is_rela: bool, rel: Rel) { 998 let endian = self.endian; 999 if is_rela { 1000 let rel = elf::Rela64 { 1001 r_offset: U64::new(endian, rel.r_offset), 1002 r_info: elf::Rela64::r_info(endian, rel.r_sym, rel.r_type), 1003 r_addend: I64::new(endian, rel.r_addend), 1004 }; 1005 buffer.write(&rel); 1006 } else { 1007 let rel = elf::Rel64 { 1008 r_offset: U64::new(endian, rel.r_offset), 1009 r_info: elf::Rel64::r_info(endian, rel.r_sym, rel.r_type), 1010 }; 1011 buffer.write(&rel); 1012 } 1013 } 1014 } 1015