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