1 use std::vec::Vec; 2 3 use crate::elf; 4 use crate::write::elf::writer::*; 5 use crate::write::string::StringId; 6 use crate::write::*; 7 use crate::AddressSize; 8 9 #[derive(Clone, Copy)] 10 struct ComdatOffsets { 11 offset: usize, 12 str_id: StringId, 13 } 14 15 #[derive(Clone, Copy)] 16 struct SectionOffsets { 17 index: SectionIndex, 18 offset: usize, 19 str_id: StringId, 20 reloc_offset: usize, 21 reloc_str_id: Option<StringId>, 22 } 23 24 #[derive(Default, Clone, Copy)] 25 struct SymbolOffsets { 26 index: SymbolIndex, 27 str_id: Option<StringId>, 28 } 29 30 impl<'a> Object<'a> { elf_section_info( &self, section: StandardSection, ) -> (&'static [u8], &'static [u8], SectionKind)31 pub(crate) fn elf_section_info( 32 &self, 33 section: StandardSection, 34 ) -> (&'static [u8], &'static [u8], SectionKind) { 35 match section { 36 StandardSection::Text => (&[], &b".text"[..], SectionKind::Text), 37 StandardSection::Data => (&[], &b".data"[..], SectionKind::Data), 38 StandardSection::ReadOnlyData | StandardSection::ReadOnlyString => { 39 (&[], &b".rodata"[..], SectionKind::ReadOnlyData) 40 } 41 StandardSection::ReadOnlyDataWithRel => (&[], b".data.rel.ro", SectionKind::Data), 42 StandardSection::UninitializedData => { 43 (&[], &b".bss"[..], SectionKind::UninitializedData) 44 } 45 StandardSection::Tls => (&[], &b".tdata"[..], SectionKind::Tls), 46 StandardSection::UninitializedTls => { 47 (&[], &b".tbss"[..], SectionKind::UninitializedTls) 48 } 49 StandardSection::TlsVariables => { 50 // Unsupported section. 51 (&[], &[], SectionKind::TlsVariables) 52 } 53 StandardSection::Common => { 54 // Unsupported section. 55 (&[], &[], SectionKind::Common) 56 } 57 } 58 } 59 elf_subsection_name(&self, section: &[u8], value: &[u8]) -> Vec<u8>60 pub(crate) fn elf_subsection_name(&self, section: &[u8], value: &[u8]) -> Vec<u8> { 61 let mut name = section.to_vec(); 62 name.push(b'.'); 63 name.extend_from_slice(value); 64 name 65 } 66 elf_has_relocation_addend(&self) -> Result<bool>67 fn elf_has_relocation_addend(&self) -> Result<bool> { 68 Ok(match self.architecture { 69 Architecture::Aarch64 => true, 70 Architecture::Arm => false, 71 Architecture::Avr => true, 72 Architecture::Bpf => false, 73 Architecture::I386 => false, 74 Architecture::X86_64 => true, 75 Architecture::X86_64_X32 => true, 76 Architecture::Hexagon => true, 77 Architecture::Mips => false, 78 Architecture::Mips64 => true, 79 Architecture::Msp430 => true, 80 Architecture::PowerPc => true, 81 Architecture::PowerPc64 => true, 82 Architecture::Riscv64 => true, 83 Architecture::Riscv32 => true, 84 Architecture::S390x => true, 85 Architecture::Sparc64 => true, 86 _ => { 87 return Err(Error(format!( 88 "unimplemented architecture {:?}", 89 self.architecture 90 ))); 91 } 92 }) 93 } 94 elf_fixup_relocation(&mut self, mut relocation: &mut Relocation) -> Result<i64>95 pub(crate) fn elf_fixup_relocation(&mut self, mut relocation: &mut Relocation) -> Result<i64> { 96 // Return true if we should use a section symbol to avoid preemption. 97 fn want_section_symbol(relocation: &Relocation, symbol: &Symbol) -> bool { 98 if symbol.scope != SymbolScope::Dynamic { 99 // Only dynamic symbols can be preemptible. 100 return false; 101 } 102 match symbol.kind { 103 SymbolKind::Text | SymbolKind::Data => {} 104 _ => return false, 105 } 106 match relocation.kind { 107 // Anything using GOT or PLT is preemptible. 108 // We also require that `Other` relocations must already be correct. 109 RelocationKind::Got 110 | RelocationKind::GotRelative 111 | RelocationKind::GotBaseRelative 112 | RelocationKind::PltRelative 113 | RelocationKind::Elf(_) => return false, 114 // Absolute relocations are preemptible for non-local data. 115 // TODO: not sure if this rule is exactly correct 116 // This rule was added to handle global data references in debuginfo. 117 // Maybe this should be a new relocation kind so that the caller can decide. 118 RelocationKind::Absolute => { 119 if symbol.kind == SymbolKind::Data { 120 return false; 121 } 122 } 123 _ => {} 124 } 125 true 126 } 127 128 // Use section symbols for relocations where required to avoid preemption. 129 // Otherwise, the linker will fail with: 130 // relocation R_X86_64_PC32 against symbol `SomeSymbolName' can not be used when 131 // making a shared object; recompile with -fPIC 132 let symbol = &self.symbols[relocation.symbol.0]; 133 if want_section_symbol(relocation, symbol) { 134 if let Some(section) = symbol.section.id() { 135 relocation.addend += symbol.value as i64; 136 relocation.symbol = self.section_symbol(section); 137 } 138 } 139 140 // Determine whether the addend is stored in the relocation or the data. 141 if self.elf_has_relocation_addend()? { 142 Ok(0) 143 } else { 144 let constant = relocation.addend; 145 relocation.addend = 0; 146 Ok(constant) 147 } 148 } 149 elf_write(&self, buffer: &mut dyn WritableBuffer) -> Result<()>150 pub(crate) fn elf_write(&self, buffer: &mut dyn WritableBuffer) -> Result<()> { 151 // Create reloc section header names so we can reference them. 152 let is_rela = self.elf_has_relocation_addend()?; 153 let reloc_names: Vec<_> = self 154 .sections 155 .iter() 156 .map(|section| { 157 let mut reloc_name = Vec::with_capacity( 158 if is_rela { ".rela".len() } else { ".rel".len() } + section.name.len(), 159 ); 160 if !section.relocations.is_empty() { 161 reloc_name.extend_from_slice(if is_rela { 162 &b".rela"[..] 163 } else { 164 &b".rel"[..] 165 }); 166 reloc_name.extend_from_slice(§ion.name); 167 } 168 reloc_name 169 }) 170 .collect(); 171 172 // Start calculating offsets of everything. 173 let is_64 = match self.architecture.address_size().unwrap() { 174 AddressSize::U8 | AddressSize::U16 | AddressSize::U32 => false, 175 AddressSize::U64 => true, 176 }; 177 let mut writer = Writer::new(self.endian, is_64, buffer); 178 writer.reserve_file_header(); 179 180 // Calculate size of section data. 181 let mut comdat_offsets = Vec::with_capacity(self.comdats.len()); 182 for comdat in &self.comdats { 183 if comdat.kind != ComdatKind::Any { 184 return Err(Error(format!( 185 "unsupported COMDAT symbol `{}` kind {:?}", 186 self.symbols[comdat.symbol.0].name().unwrap_or(""), 187 comdat.kind 188 ))); 189 } 190 191 writer.reserve_section_index(); 192 let offset = writer.reserve_comdat(comdat.sections.len()); 193 let str_id = writer.add_section_name(b".group"); 194 comdat_offsets.push(ComdatOffsets { offset, str_id }); 195 } 196 let mut section_offsets = Vec::with_capacity(self.sections.len()); 197 for (section, reloc_name) in self.sections.iter().zip(reloc_names.iter()) { 198 let index = writer.reserve_section_index(); 199 let offset = writer.reserve(section.data.len(), section.align as usize); 200 let str_id = writer.add_section_name(§ion.name); 201 let mut reloc_str_id = None; 202 if !section.relocations.is_empty() { 203 writer.reserve_section_index(); 204 reloc_str_id = Some(writer.add_section_name(reloc_name)); 205 } 206 section_offsets.push(SectionOffsets { 207 index, 208 offset, 209 str_id, 210 // Relocation data is reserved later. 211 reloc_offset: 0, 212 reloc_str_id, 213 }); 214 } 215 216 // Calculate index of symbols and add symbol strings to strtab. 217 let mut symbol_offsets = vec![SymbolOffsets::default(); self.symbols.len()]; 218 // Local symbols must come before global. 219 for (index, symbol) in self.symbols.iter().enumerate() { 220 if symbol.is_local() { 221 let section_index = symbol.section.id().map(|s| section_offsets[s.0].index); 222 symbol_offsets[index].index = writer.reserve_symbol_index(section_index); 223 } 224 } 225 let symtab_num_local = writer.symbol_count(); 226 for (index, symbol) in self.symbols.iter().enumerate() { 227 if !symbol.is_local() { 228 let section_index = symbol.section.id().map(|s| section_offsets[s.0].index); 229 symbol_offsets[index].index = writer.reserve_symbol_index(section_index); 230 } 231 } 232 for (index, symbol) in self.symbols.iter().enumerate() { 233 if symbol.kind != SymbolKind::Section && !symbol.name.is_empty() { 234 symbol_offsets[index].str_id = Some(writer.add_string(&symbol.name)); 235 } 236 } 237 238 // Calculate size of symbols. 239 writer.reserve_symtab_section_index(); 240 writer.reserve_symtab(); 241 if writer.symtab_shndx_needed() { 242 writer.reserve_symtab_shndx_section_index(); 243 } 244 writer.reserve_symtab_shndx(); 245 writer.reserve_strtab_section_index(); 246 writer.reserve_strtab(); 247 248 // Calculate size of relocations. 249 for (index, section) in self.sections.iter().enumerate() { 250 let count = section.relocations.len(); 251 if count != 0 { 252 section_offsets[index].reloc_offset = writer.reserve_relocations(count, is_rela); 253 } 254 } 255 256 // Calculate size of section headers. 257 writer.reserve_shstrtab_section_index(); 258 writer.reserve_shstrtab(); 259 writer.reserve_section_headers(); 260 261 // Start writing. 262 let e_type = elf::ET_REL; 263 let e_machine = match self.architecture { 264 Architecture::Aarch64 => elf::EM_AARCH64, 265 Architecture::Arm => elf::EM_ARM, 266 Architecture::Avr => elf::EM_AVR, 267 Architecture::Bpf => elf::EM_BPF, 268 Architecture::I386 => elf::EM_386, 269 Architecture::X86_64 => elf::EM_X86_64, 270 Architecture::X86_64_X32 => elf::EM_X86_64, 271 Architecture::Hexagon => elf::EM_HEXAGON, 272 Architecture::Mips => elf::EM_MIPS, 273 Architecture::Mips64 => elf::EM_MIPS, 274 Architecture::Msp430 => elf::EM_MSP430, 275 Architecture::PowerPc => elf::EM_PPC, 276 Architecture::PowerPc64 => elf::EM_PPC64, 277 Architecture::Riscv32 => elf::EM_RISCV, 278 Architecture::Riscv64 => elf::EM_RISCV, 279 Architecture::S390x => elf::EM_S390, 280 Architecture::Sparc64 => elf::EM_SPARCV9, 281 _ => { 282 return Err(Error(format!( 283 "unimplemented architecture {:?}", 284 self.architecture 285 ))); 286 } 287 }; 288 let e_flags = if let FileFlags::Elf { e_flags } = self.flags { 289 e_flags 290 } else { 291 0 292 }; 293 writer.write_file_header(&FileHeader { 294 os_abi: elf::ELFOSABI_NONE, 295 abi_version: 0, 296 e_type, 297 e_machine, 298 e_entry: 0, 299 e_flags, 300 })?; 301 302 // Write section data. 303 for comdat in &self.comdats { 304 writer.write_comdat_header(); 305 for section in &comdat.sections { 306 writer.write_comdat_entry(section_offsets[section.0].index); 307 } 308 } 309 for (index, section) in self.sections.iter().enumerate() { 310 let len = section.data.len(); 311 if len != 0 { 312 writer.write_align(section.align as usize); 313 debug_assert_eq!(section_offsets[index].offset, writer.len()); 314 writer.write(§ion.data); 315 } 316 } 317 318 // Write symbols. 319 writer.write_null_symbol(); 320 let mut write_symbol = |index: usize, symbol: &Symbol| -> Result<()> { 321 let st_info = if let SymbolFlags::Elf { st_info, .. } = symbol.flags { 322 st_info 323 } else { 324 let st_type = match symbol.kind { 325 SymbolKind::Null => elf::STT_NOTYPE, 326 SymbolKind::Text => { 327 if symbol.is_undefined() { 328 elf::STT_NOTYPE 329 } else { 330 elf::STT_FUNC 331 } 332 } 333 SymbolKind::Data => { 334 if symbol.is_undefined() { 335 elf::STT_NOTYPE 336 } else if symbol.is_common() { 337 elf::STT_COMMON 338 } else { 339 elf::STT_OBJECT 340 } 341 } 342 SymbolKind::Section => elf::STT_SECTION, 343 SymbolKind::File => elf::STT_FILE, 344 SymbolKind::Tls => elf::STT_TLS, 345 SymbolKind::Label => elf::STT_NOTYPE, 346 SymbolKind::Unknown => { 347 if symbol.is_undefined() { 348 elf::STT_NOTYPE 349 } else { 350 return Err(Error(format!( 351 "unimplemented symbol `{}` kind {:?}", 352 symbol.name().unwrap_or(""), 353 symbol.kind 354 ))); 355 } 356 } 357 }; 358 let st_bind = if symbol.weak { 359 elf::STB_WEAK 360 } else if symbol.is_undefined() { 361 elf::STB_GLOBAL 362 } else if symbol.is_local() { 363 elf::STB_LOCAL 364 } else { 365 elf::STB_GLOBAL 366 }; 367 (st_bind << 4) + st_type 368 }; 369 let st_other = if let SymbolFlags::Elf { st_other, .. } = symbol.flags { 370 st_other 371 } else if symbol.scope == SymbolScope::Linkage { 372 elf::STV_HIDDEN 373 } else { 374 elf::STV_DEFAULT 375 }; 376 let (st_shndx, section) = match symbol.section { 377 SymbolSection::None => { 378 debug_assert_eq!(symbol.kind, SymbolKind::File); 379 (elf::SHN_ABS, None) 380 } 381 SymbolSection::Undefined => (elf::SHN_UNDEF, None), 382 SymbolSection::Absolute => (elf::SHN_ABS, None), 383 SymbolSection::Common => (elf::SHN_COMMON, None), 384 SymbolSection::Section(id) => (0, Some(section_offsets[id.0].index)), 385 }; 386 writer.write_symbol(&Sym { 387 name: symbol_offsets[index].str_id, 388 section, 389 st_info, 390 st_other, 391 st_shndx, 392 st_value: symbol.value, 393 st_size: symbol.size, 394 }); 395 Ok(()) 396 }; 397 for (index, symbol) in self.symbols.iter().enumerate() { 398 if symbol.is_local() { 399 write_symbol(index, symbol)?; 400 } 401 } 402 for (index, symbol) in self.symbols.iter().enumerate() { 403 if !symbol.is_local() { 404 write_symbol(index, symbol)?; 405 } 406 } 407 writer.write_symtab_shndx(); 408 writer.write_strtab(); 409 410 // Write relocations. 411 for (index, section) in self.sections.iter().enumerate() { 412 if !section.relocations.is_empty() { 413 writer.write_align_relocation(); 414 debug_assert_eq!(section_offsets[index].reloc_offset, writer.len()); 415 for reloc in §ion.relocations { 416 let r_type = match self.architecture { 417 Architecture::Aarch64 => match (reloc.kind, reloc.encoding, reloc.size) { 418 (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => { 419 elf::R_AARCH64_ABS64 420 } 421 (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => { 422 elf::R_AARCH64_ABS32 423 } 424 (RelocationKind::Absolute, RelocationEncoding::Generic, 16) => { 425 elf::R_AARCH64_ABS16 426 } 427 (RelocationKind::Relative, RelocationEncoding::Generic, 64) => { 428 elf::R_AARCH64_PREL64 429 } 430 (RelocationKind::Relative, RelocationEncoding::Generic, 32) => { 431 elf::R_AARCH64_PREL32 432 } 433 (RelocationKind::Relative, RelocationEncoding::Generic, 16) => { 434 elf::R_AARCH64_PREL16 435 } 436 (RelocationKind::Relative, RelocationEncoding::AArch64Call, 26) 437 | (RelocationKind::PltRelative, RelocationEncoding::AArch64Call, 26) => { 438 elf::R_AARCH64_CALL26 439 } 440 (RelocationKind::Elf(x), _, _) => x, 441 _ => { 442 return Err(Error(format!("unimplemented relocation {:?}", reloc))); 443 } 444 }, 445 Architecture::Arm => match (reloc.kind, reloc.encoding, reloc.size) { 446 (RelocationKind::Absolute, _, 32) => elf::R_ARM_ABS32, 447 (RelocationKind::Elf(x), _, _) => x, 448 _ => { 449 return Err(Error(format!("unimplemented relocation {:?}", reloc))); 450 } 451 }, 452 Architecture::Avr => match (reloc.kind, reloc.encoding, reloc.size) { 453 (RelocationKind::Absolute, _, 32) => elf::R_AVR_32, 454 (RelocationKind::Absolute, _, 16) => elf::R_AVR_16, 455 (RelocationKind::Elf(x), _, _) => x, 456 _ => { 457 return Err(Error(format!("unimplemented relocation {:?}", reloc))); 458 } 459 }, 460 Architecture::Bpf => match (reloc.kind, reloc.encoding, reloc.size) { 461 (RelocationKind::Absolute, _, 64) => elf::R_BPF_64_64, 462 (RelocationKind::Absolute, _, 32) => elf::R_BPF_64_32, 463 (RelocationKind::Elf(x), _, _) => x, 464 _ => { 465 return Err(Error(format!("unimplemented relocation {:?}", reloc))); 466 } 467 }, 468 Architecture::I386 => match (reloc.kind, reloc.size) { 469 (RelocationKind::Absolute, 32) => elf::R_386_32, 470 (RelocationKind::Relative, 32) => elf::R_386_PC32, 471 (RelocationKind::Got, 32) => elf::R_386_GOT32, 472 (RelocationKind::PltRelative, 32) => elf::R_386_PLT32, 473 (RelocationKind::GotBaseOffset, 32) => elf::R_386_GOTOFF, 474 (RelocationKind::GotBaseRelative, 32) => elf::R_386_GOTPC, 475 (RelocationKind::Absolute, 16) => elf::R_386_16, 476 (RelocationKind::Relative, 16) => elf::R_386_PC16, 477 (RelocationKind::Absolute, 8) => elf::R_386_8, 478 (RelocationKind::Relative, 8) => elf::R_386_PC8, 479 (RelocationKind::Elf(x), _) => x, 480 _ => { 481 return Err(Error(format!("unimplemented relocation {:?}", reloc))); 482 } 483 }, 484 Architecture::X86_64 | Architecture::X86_64_X32 => { 485 match (reloc.kind, reloc.encoding, reloc.size) { 486 (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => { 487 elf::R_X86_64_64 488 } 489 (RelocationKind::Relative, _, 32) => elf::R_X86_64_PC32, 490 (RelocationKind::Got, _, 32) => elf::R_X86_64_GOT32, 491 (RelocationKind::PltRelative, _, 32) => elf::R_X86_64_PLT32, 492 (RelocationKind::GotRelative, _, 32) => elf::R_X86_64_GOTPCREL, 493 (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => { 494 elf::R_X86_64_32 495 } 496 (RelocationKind::Absolute, RelocationEncoding::X86Signed, 32) => { 497 elf::R_X86_64_32S 498 } 499 (RelocationKind::Absolute, _, 16) => elf::R_X86_64_16, 500 (RelocationKind::Relative, _, 16) => elf::R_X86_64_PC16, 501 (RelocationKind::Absolute, _, 8) => elf::R_X86_64_8, 502 (RelocationKind::Relative, _, 8) => elf::R_X86_64_PC8, 503 (RelocationKind::Elf(x), _, _) => x, 504 _ => { 505 return Err(Error(format!( 506 "unimplemented relocation {:?}", 507 reloc 508 ))); 509 } 510 } 511 } 512 Architecture::Hexagon => match (reloc.kind, reloc.encoding, reloc.size) { 513 (RelocationKind::Absolute, _, 32) => elf::R_HEX_32, 514 (RelocationKind::Elf(x), _, _) => x, 515 _ => { 516 return Err(Error(format!("unimplemented relocation {:?}", reloc))); 517 } 518 }, 519 Architecture::Mips | Architecture::Mips64 => { 520 match (reloc.kind, reloc.encoding, reloc.size) { 521 (RelocationKind::Absolute, _, 16) => elf::R_MIPS_16, 522 (RelocationKind::Absolute, _, 32) => elf::R_MIPS_32, 523 (RelocationKind::Absolute, _, 64) => elf::R_MIPS_64, 524 (RelocationKind::Elf(x), _, _) => x, 525 _ => { 526 return Err(Error(format!( 527 "unimplemented relocation {:?}", 528 reloc 529 ))); 530 } 531 } 532 } 533 Architecture::Msp430 => match (reloc.kind, reloc.encoding, reloc.size) { 534 (RelocationKind::Absolute, _, 32) => elf::R_MSP430_32, 535 (RelocationKind::Absolute, _, 16) => elf::R_MSP430_16_BYTE, 536 (RelocationKind::Elf(x), _, _) => x, 537 _ => { 538 return Err(Error(format!("unimplemented relocation {:?}", reloc))); 539 } 540 }, 541 Architecture::PowerPc => match (reloc.kind, reloc.encoding, reloc.size) { 542 (RelocationKind::Absolute, _, 32) => elf::R_PPC_ADDR32, 543 (RelocationKind::Elf(x), _, _) => x, 544 _ => { 545 return Err(Error(format!("unimplemented relocation {:?}", reloc))); 546 } 547 }, 548 Architecture::PowerPc64 => match (reloc.kind, reloc.encoding, reloc.size) { 549 (RelocationKind::Absolute, _, 32) => elf::R_PPC64_ADDR32, 550 (RelocationKind::Absolute, _, 64) => elf::R_PPC64_ADDR64, 551 (RelocationKind::Elf(x), _, _) => x, 552 _ => { 553 return Err(Error(format!("unimplemented relocation {:?}", reloc))); 554 } 555 }, 556 Architecture::Riscv32 | Architecture::Riscv64 => { 557 match (reloc.kind, reloc.encoding, reloc.size) { 558 (RelocationKind::Absolute, _, 32) => elf::R_RISCV_32, 559 (RelocationKind::Absolute, _, 64) => elf::R_RISCV_64, 560 (RelocationKind::Elf(x), _, _) => x, 561 _ => { 562 return Err(Error(format!( 563 "unimplemented relocation {:?}", 564 reloc 565 ))); 566 } 567 } 568 } 569 Architecture::S390x => match (reloc.kind, reloc.encoding, reloc.size) { 570 (RelocationKind::Absolute, RelocationEncoding::Generic, 8) => { 571 elf::R_390_8 572 } 573 (RelocationKind::Absolute, RelocationEncoding::Generic, 16) => { 574 elf::R_390_16 575 } 576 (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => { 577 elf::R_390_32 578 } 579 (RelocationKind::Absolute, RelocationEncoding::Generic, 64) => { 580 elf::R_390_64 581 } 582 (RelocationKind::Relative, RelocationEncoding::Generic, 16) => { 583 elf::R_390_PC16 584 } 585 (RelocationKind::Relative, RelocationEncoding::Generic, 32) => { 586 elf::R_390_PC32 587 } 588 (RelocationKind::Relative, RelocationEncoding::Generic, 64) => { 589 elf::R_390_PC64 590 } 591 (RelocationKind::Relative, RelocationEncoding::S390xDbl, 16) => { 592 elf::R_390_PC16DBL 593 } 594 (RelocationKind::Relative, RelocationEncoding::S390xDbl, 32) => { 595 elf::R_390_PC32DBL 596 } 597 (RelocationKind::PltRelative, RelocationEncoding::S390xDbl, 16) => { 598 elf::R_390_PLT16DBL 599 } 600 (RelocationKind::PltRelative, RelocationEncoding::S390xDbl, 32) => { 601 elf::R_390_PLT32DBL 602 } 603 (RelocationKind::Got, RelocationEncoding::Generic, 16) => { 604 elf::R_390_GOT16 605 } 606 (RelocationKind::Got, RelocationEncoding::Generic, 32) => { 607 elf::R_390_GOT32 608 } 609 (RelocationKind::Got, RelocationEncoding::Generic, 64) => { 610 elf::R_390_GOT64 611 } 612 (RelocationKind::GotRelative, RelocationEncoding::S390xDbl, 32) => { 613 elf::R_390_GOTENT 614 } 615 (RelocationKind::GotBaseOffset, RelocationEncoding::Generic, 16) => { 616 elf::R_390_GOTOFF16 617 } 618 (RelocationKind::GotBaseOffset, RelocationEncoding::Generic, 32) => { 619 elf::R_390_GOTOFF32 620 } 621 (RelocationKind::GotBaseOffset, RelocationEncoding::Generic, 64) => { 622 elf::R_390_GOTOFF64 623 } 624 (RelocationKind::GotBaseRelative, RelocationEncoding::Generic, 64) => { 625 elf::R_390_GOTPC 626 } 627 (RelocationKind::GotBaseRelative, RelocationEncoding::S390xDbl, 32) => { 628 elf::R_390_GOTPCDBL 629 } 630 (RelocationKind::Elf(x), _, _) => x, 631 _ => { 632 return Err(Error(format!("unimplemented relocation {:?}", reloc))); 633 } 634 }, 635 Architecture::Sparc64 => match (reloc.kind, reloc.encoding, reloc.size) { 636 // TODO: use R_SPARC_32/R_SPARC_64 if aligned. 637 (RelocationKind::Absolute, _, 32) => elf::R_SPARC_UA32, 638 (RelocationKind::Absolute, _, 64) => elf::R_SPARC_UA64, 639 (RelocationKind::Elf(x), _, _) => x, 640 _ => { 641 return Err(Error(format!("unimplemented relocation {:?}", reloc))); 642 } 643 }, 644 _ => { 645 if let RelocationKind::Elf(x) = reloc.kind { 646 x 647 } else { 648 return Err(Error(format!("unimplemented relocation {:?}", reloc))); 649 } 650 } 651 }; 652 let r_sym = symbol_offsets[reloc.symbol.0].index.0; 653 writer.write_relocation( 654 is_rela, 655 &Rel { 656 r_offset: reloc.offset, 657 r_sym, 658 r_type, 659 r_addend: reloc.addend, 660 }, 661 ); 662 } 663 } 664 } 665 666 writer.write_shstrtab(); 667 668 // Write section headers. 669 writer.write_null_section_header(); 670 671 let symtab_index = writer.symtab_index(); 672 for (comdat, comdat_offset) in self.comdats.iter().zip(comdat_offsets.iter()) { 673 writer.write_comdat_section_header( 674 comdat_offset.str_id, 675 symtab_index, 676 symbol_offsets[comdat.symbol.0].index, 677 comdat_offset.offset, 678 comdat.sections.len(), 679 ); 680 } 681 for (index, section) in self.sections.iter().enumerate() { 682 let sh_type = match section.kind { 683 SectionKind::UninitializedData | SectionKind::UninitializedTls => elf::SHT_NOBITS, 684 SectionKind::Note => elf::SHT_NOTE, 685 SectionKind::Elf(sh_type) => sh_type, 686 _ => elf::SHT_PROGBITS, 687 }; 688 let sh_flags = if let SectionFlags::Elf { sh_flags } = section.flags { 689 sh_flags 690 } else { 691 match section.kind { 692 SectionKind::Text => elf::SHF_ALLOC | elf::SHF_EXECINSTR, 693 SectionKind::Data => elf::SHF_ALLOC | elf::SHF_WRITE, 694 SectionKind::Tls => elf::SHF_ALLOC | elf::SHF_WRITE | elf::SHF_TLS, 695 SectionKind::UninitializedData => elf::SHF_ALLOC | elf::SHF_WRITE, 696 SectionKind::UninitializedTls => elf::SHF_ALLOC | elf::SHF_WRITE | elf::SHF_TLS, 697 SectionKind::ReadOnlyData => elf::SHF_ALLOC, 698 SectionKind::ReadOnlyString => { 699 elf::SHF_ALLOC | elf::SHF_STRINGS | elf::SHF_MERGE 700 } 701 SectionKind::OtherString => elf::SHF_STRINGS | elf::SHF_MERGE, 702 SectionKind::Other 703 | SectionKind::Debug 704 | SectionKind::Metadata 705 | SectionKind::Linker 706 | SectionKind::Note 707 | SectionKind::Elf(_) => 0, 708 SectionKind::Unknown | SectionKind::Common | SectionKind::TlsVariables => { 709 return Err(Error(format!( 710 "unimplemented section `{}` kind {:?}", 711 section.name().unwrap_or(""), 712 section.kind 713 ))); 714 } 715 } 716 .into() 717 }; 718 // TODO: not sure if this is correct, maybe user should determine this 719 let sh_entsize = match section.kind { 720 SectionKind::ReadOnlyString | SectionKind::OtherString => 1, 721 _ => 0, 722 }; 723 writer.write_section_header(&SectionHeader { 724 name: Some(section_offsets[index].str_id), 725 sh_type, 726 sh_flags, 727 sh_addr: 0, 728 sh_offset: section_offsets[index].offset as u64, 729 sh_size: section.size, 730 sh_link: 0, 731 sh_info: 0, 732 sh_addralign: section.align, 733 sh_entsize, 734 }); 735 736 if !section.relocations.is_empty() { 737 writer.write_relocation_section_header( 738 section_offsets[index].reloc_str_id.unwrap(), 739 section_offsets[index].index, 740 symtab_index, 741 section_offsets[index].reloc_offset, 742 section.relocations.len(), 743 is_rela, 744 ); 745 } 746 } 747 748 writer.write_symtab_section_header(symtab_num_local); 749 writer.write_symtab_shndx_section_header(); 750 writer.write_strtab_section_header(); 751 writer.write_shstrtab_section_header(); 752 753 debug_assert_eq!(writer.reserved_len(), writer.len()); 754 755 Ok(()) 756 } 757 } 758