1 //! Helper for writing ELF files. 2 use std::mem; 3 use std::string::String; 4 use std::vec::Vec; 5 6 use crate::elf; 7 use crate::endian::*; 8 use crate::write::string::{StringId, StringTable}; 9 use crate::write::util; 10 use crate::write::{Error, Result, WritableBuffer}; 11 12 /// The index of an ELF section. 13 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 14 pub struct SectionIndex(pub u32); 15 16 /// The index of an ELF symbol. 17 #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 18 pub struct SymbolIndex(pub u32); 19 20 /// A helper for writing ELF files. 21 /// 22 /// Writing uses a two phase approach. The first phase builds up all of the information 23 /// that may need to be known ahead of time: 24 /// - build string tables 25 /// - reserve section indices 26 /// - reserve symbol indices 27 /// - reserve file ranges for headers and sections 28 /// 29 /// Some of the information has ordering requirements. For example, strings must be added 30 /// to string tables before reserving the file range for the string table. Symbol indices 31 /// must be reserved after reserving the section indices they reference. There are debug 32 /// asserts to check some of these requirements. 33 /// 34 /// The second phase writes everything out in order. Thus the caller must ensure writing 35 /// is in the same order that file ranges were reserved. There are debug asserts to assist 36 /// with checking this. 37 #[allow(missing_debug_implementations)] 38 pub struct Writer<'a> { 39 endian: Endianness, 40 is_64: bool, 41 is_mips64el: bool, 42 elf_align: usize, 43 44 buffer: &'a mut dyn WritableBuffer, 45 len: usize, 46 47 segment_offset: usize, 48 segment_num: u32, 49 50 section_offset: usize, 51 section_num: u32, 52 53 shstrtab: StringTable<'a>, 54 shstrtab_str_id: Option<StringId>, 55 shstrtab_index: SectionIndex, 56 shstrtab_offset: usize, 57 shstrtab_data: Vec<u8>, 58 59 need_strtab: bool, 60 strtab: StringTable<'a>, 61 strtab_str_id: Option<StringId>, 62 strtab_index: SectionIndex, 63 strtab_offset: usize, 64 strtab_data: Vec<u8>, 65 66 symtab_str_id: Option<StringId>, 67 symtab_index: SectionIndex, 68 symtab_offset: usize, 69 symtab_num: u32, 70 71 need_symtab_shndx: bool, 72 symtab_shndx_str_id: Option<StringId>, 73 symtab_shndx_offset: usize, 74 symtab_shndx_data: Vec<u8>, 75 76 need_dynstr: bool, 77 dynstr: StringTable<'a>, 78 dynstr_str_id: Option<StringId>, 79 dynstr_index: SectionIndex, 80 dynstr_offset: usize, 81 dynstr_data: Vec<u8>, 82 83 dynsym_str_id: Option<StringId>, 84 dynsym_index: SectionIndex, 85 dynsym_offset: usize, 86 dynsym_num: u32, 87 88 dynamic_str_id: Option<StringId>, 89 dynamic_offset: usize, 90 dynamic_num: usize, 91 92 hash_str_id: Option<StringId>, 93 hash_offset: usize, 94 hash_size: usize, 95 96 gnu_hash_str_id: Option<StringId>, 97 gnu_hash_offset: usize, 98 gnu_hash_size: usize, 99 100 gnu_versym_str_id: Option<StringId>, 101 gnu_versym_offset: usize, 102 103 gnu_verdef_str_id: Option<StringId>, 104 gnu_verdef_offset: usize, 105 gnu_verdef_size: usize, 106 gnu_verdef_count: u16, 107 gnu_verdef_remaining: u16, 108 gnu_verdaux_remaining: u16, 109 110 gnu_verneed_str_id: Option<StringId>, 111 gnu_verneed_offset: usize, 112 gnu_verneed_size: usize, 113 gnu_verneed_count: u16, 114 gnu_verneed_remaining: u16, 115 gnu_vernaux_remaining: u16, 116 } 117 118 impl<'a> Writer<'a> { 119 /// Create a new `Writer` for the given endianness and ELF class. new(endian: Endianness, is_64: bool, buffer: &'a mut dyn WritableBuffer) -> Self120 pub fn new(endian: Endianness, is_64: bool, buffer: &'a mut dyn WritableBuffer) -> Self { 121 let elf_align = if is_64 { 8 } else { 4 }; 122 Writer { 123 endian, 124 is_64, 125 // Determined later. 126 is_mips64el: false, 127 elf_align, 128 129 buffer, 130 len: 0, 131 132 segment_offset: 0, 133 segment_num: 0, 134 135 section_offset: 0, 136 section_num: 0, 137 138 shstrtab: StringTable::default(), 139 shstrtab_str_id: None, 140 shstrtab_index: SectionIndex(0), 141 shstrtab_offset: 0, 142 shstrtab_data: Vec::new(), 143 144 need_strtab: false, 145 strtab: StringTable::default(), 146 strtab_str_id: None, 147 strtab_index: SectionIndex(0), 148 strtab_offset: 0, 149 strtab_data: Vec::new(), 150 151 symtab_str_id: None, 152 symtab_index: SectionIndex(0), 153 symtab_offset: 0, 154 symtab_num: 0, 155 156 need_symtab_shndx: false, 157 symtab_shndx_str_id: None, 158 symtab_shndx_offset: 0, 159 symtab_shndx_data: Vec::new(), 160 161 need_dynstr: false, 162 dynstr: StringTable::default(), 163 dynstr_str_id: None, 164 dynstr_index: SectionIndex(0), 165 dynstr_offset: 0, 166 dynstr_data: Vec::new(), 167 168 dynsym_str_id: None, 169 dynsym_index: SectionIndex(0), 170 dynsym_offset: 0, 171 dynsym_num: 0, 172 173 dynamic_str_id: None, 174 dynamic_offset: 0, 175 dynamic_num: 0, 176 177 hash_str_id: None, 178 hash_offset: 0, 179 hash_size: 0, 180 181 gnu_hash_str_id: None, 182 gnu_hash_offset: 0, 183 gnu_hash_size: 0, 184 185 gnu_versym_str_id: None, 186 gnu_versym_offset: 0, 187 188 gnu_verdef_str_id: None, 189 gnu_verdef_offset: 0, 190 gnu_verdef_size: 0, 191 gnu_verdef_count: 0, 192 gnu_verdef_remaining: 0, 193 gnu_verdaux_remaining: 0, 194 195 gnu_verneed_str_id: None, 196 gnu_verneed_offset: 0, 197 gnu_verneed_size: 0, 198 gnu_verneed_count: 0, 199 gnu_verneed_remaining: 0, 200 gnu_vernaux_remaining: 0, 201 } 202 } 203 204 /// Return the current file length that has been reserved. reserved_len(&self) -> usize205 pub fn reserved_len(&self) -> usize { 206 self.len 207 } 208 209 /// Return the current file length that has been written. 210 #[allow(clippy::len_without_is_empty)] len(&self) -> usize211 pub fn len(&self) -> usize { 212 self.buffer.len() 213 } 214 215 /// Reserve a file range with the given size and starting alignment. 216 /// 217 /// Returns the aligned offset of the start of the range. reserve(&mut self, len: usize, align_start: usize) -> usize218 pub fn reserve(&mut self, len: usize, align_start: usize) -> usize { 219 if len == 0 { 220 return self.len; 221 } 222 self.len = util::align(self.len, align_start); 223 let offset = self.len; 224 self.len += len; 225 offset 226 } 227 228 /// Write alignment padding bytes. write_align(&mut self, align_start: usize)229 pub fn write_align(&mut self, align_start: usize) { 230 util::write_align(self.buffer, align_start); 231 } 232 233 /// Write data. 234 /// 235 /// This is typically used to write section data. write(&mut self, data: &[u8])236 pub fn write(&mut self, data: &[u8]) { 237 self.buffer.write_bytes(data); 238 } 239 240 /// Reserve the file range up to the given file offset. reserve_until(&mut self, offset: usize)241 pub fn reserve_until(&mut self, offset: usize) { 242 debug_assert!(self.len <= offset); 243 self.len = offset; 244 } 245 246 /// Write padding up to the given file offset. pad_until(&mut self, offset: usize)247 pub fn pad_until(&mut self, offset: usize) { 248 debug_assert!(self.buffer.len() <= offset); 249 self.buffer.resize(offset); 250 } 251 file_header_size(&self) -> usize252 fn file_header_size(&self) -> usize { 253 if self.is_64 { 254 mem::size_of::<elf::FileHeader64<Endianness>>() 255 } else { 256 mem::size_of::<elf::FileHeader32<Endianness>>() 257 } 258 } 259 260 /// Reserve the range for the file header. 261 /// 262 /// This must be at the start of the file. reserve_file_header(&mut self)263 pub fn reserve_file_header(&mut self) { 264 debug_assert_eq!(self.len, 0); 265 self.reserve(self.file_header_size(), 1); 266 } 267 268 /// Write the file header. 269 /// 270 /// This must be at the start of the file. 271 /// 272 /// Fields that can be derived from known information are automatically set by this function. write_file_header(&mut self, header: &FileHeader) -> Result<()>273 pub fn write_file_header(&mut self, header: &FileHeader) -> Result<()> { 274 debug_assert_eq!(self.buffer.len(), 0); 275 276 self.is_mips64el = 277 self.is_64 && self.endian.is_little_endian() && header.e_machine == elf::EM_MIPS; 278 279 // Start writing. 280 self.buffer 281 .reserve(self.len) 282 .map_err(|_| Error(String::from("Cannot allocate buffer")))?; 283 284 // Write file header. 285 let e_ident = elf::Ident { 286 magic: elf::ELFMAG, 287 class: if self.is_64 { 288 elf::ELFCLASS64 289 } else { 290 elf::ELFCLASS32 291 }, 292 data: if self.endian.is_little_endian() { 293 elf::ELFDATA2LSB 294 } else { 295 elf::ELFDATA2MSB 296 }, 297 version: elf::EV_CURRENT, 298 os_abi: header.os_abi, 299 abi_version: header.abi_version, 300 padding: [0; 7], 301 }; 302 303 let e_ehsize = self.file_header_size() as u16; 304 305 let e_phoff = self.segment_offset as u64; 306 let e_phentsize = if self.segment_num == 0 { 307 0 308 } else { 309 self.program_header_size() as u16 310 }; 311 // TODO: overflow 312 let e_phnum = self.segment_num as u16; 313 314 let e_shoff = self.section_offset as u64; 315 let e_shentsize = if self.section_num == 0 { 316 0 317 } else { 318 self.section_header_size() as u16 319 }; 320 let e_shnum = if self.section_num >= elf::SHN_LORESERVE.into() { 321 0 322 } else { 323 self.section_num as u16 324 }; 325 let e_shstrndx = if self.shstrtab_index.0 >= elf::SHN_LORESERVE.into() { 326 elf::SHN_XINDEX 327 } else { 328 self.shstrtab_index.0 as u16 329 }; 330 331 let endian = self.endian; 332 if self.is_64 { 333 let file = elf::FileHeader64 { 334 e_ident, 335 e_type: U16::new(endian, header.e_type), 336 e_machine: U16::new(endian, header.e_machine), 337 e_version: U32::new(endian, elf::EV_CURRENT.into()), 338 e_entry: U64::new(endian, header.e_entry), 339 e_phoff: U64::new(endian, e_phoff), 340 e_shoff: U64::new(endian, e_shoff), 341 e_flags: U32::new(endian, header.e_flags), 342 e_ehsize: U16::new(endian, e_ehsize), 343 e_phentsize: U16::new(endian, e_phentsize), 344 e_phnum: U16::new(endian, e_phnum), 345 e_shentsize: U16::new(endian, e_shentsize), 346 e_shnum: U16::new(endian, e_shnum), 347 e_shstrndx: U16::new(endian, e_shstrndx), 348 }; 349 self.buffer.write(&file) 350 } else { 351 let file = elf::FileHeader32 { 352 e_ident, 353 e_type: U16::new(endian, header.e_type), 354 e_machine: U16::new(endian, header.e_machine), 355 e_version: U32::new(endian, elf::EV_CURRENT.into()), 356 e_entry: U32::new(endian, header.e_entry as u32), 357 e_phoff: U32::new(endian, e_phoff as u32), 358 e_shoff: U32::new(endian, e_shoff as u32), 359 e_flags: U32::new(endian, header.e_flags), 360 e_ehsize: U16::new(endian, e_ehsize), 361 e_phentsize: U16::new(endian, e_phentsize), 362 e_phnum: U16::new(endian, e_phnum), 363 e_shentsize: U16::new(endian, e_shentsize), 364 e_shnum: U16::new(endian, e_shnum), 365 e_shstrndx: U16::new(endian, e_shstrndx), 366 }; 367 self.buffer.write(&file); 368 } 369 370 Ok(()) 371 } 372 program_header_size(&self) -> usize373 fn program_header_size(&self) -> usize { 374 if self.is_64 { 375 mem::size_of::<elf::ProgramHeader64<Endianness>>() 376 } else { 377 mem::size_of::<elf::ProgramHeader32<Endianness>>() 378 } 379 } 380 381 /// Reserve the range for the program headers. reserve_program_headers(&mut self, num: u32)382 pub fn reserve_program_headers(&mut self, num: u32) { 383 debug_assert_eq!(self.segment_offset, 0); 384 if num == 0 { 385 return; 386 } 387 self.segment_num = num; 388 self.segment_offset = 389 self.reserve(num as usize * self.program_header_size(), self.elf_align); 390 } 391 392 /// Write alignment padding bytes prior to the program headers. write_align_program_headers(&mut self)393 pub fn write_align_program_headers(&mut self) { 394 if self.segment_offset == 0 { 395 return; 396 } 397 util::write_align(self.buffer, self.elf_align); 398 debug_assert_eq!(self.segment_offset, self.buffer.len()); 399 } 400 401 /// Write a program header. write_program_header(&mut self, header: &ProgramHeader)402 pub fn write_program_header(&mut self, header: &ProgramHeader) { 403 let endian = self.endian; 404 if self.is_64 { 405 let header = elf::ProgramHeader64 { 406 p_type: U32::new(endian, header.p_type), 407 p_flags: U32::new(endian, header.p_flags), 408 p_offset: U64::new(endian, header.p_offset), 409 p_vaddr: U64::new(endian, header.p_vaddr), 410 p_paddr: U64::new(endian, header.p_paddr), 411 p_filesz: U64::new(endian, header.p_filesz), 412 p_memsz: U64::new(endian, header.p_memsz), 413 p_align: U64::new(endian, header.p_align), 414 }; 415 self.buffer.write(&header); 416 } else { 417 let header = elf::ProgramHeader32 { 418 p_type: U32::new(endian, header.p_type), 419 p_offset: U32::new(endian, header.p_offset as u32), 420 p_vaddr: U32::new(endian, header.p_vaddr as u32), 421 p_paddr: U32::new(endian, header.p_paddr as u32), 422 p_filesz: U32::new(endian, header.p_filesz as u32), 423 p_memsz: U32::new(endian, header.p_memsz as u32), 424 p_flags: U32::new(endian, header.p_flags), 425 p_align: U32::new(endian, header.p_align as u32), 426 }; 427 self.buffer.write(&header); 428 } 429 } 430 431 /// Reserve the section index for the null section header. 432 /// 433 /// The null section header is usually automatically reserved, 434 /// but this can be used to force an empty section table. 435 /// 436 /// This must be called before [`Self::reserve_section_headers`]. reserve_null_section_index(&mut self) -> SectionIndex437 pub fn reserve_null_section_index(&mut self) -> SectionIndex { 438 debug_assert_eq!(self.section_num, 0); 439 if self.section_num == 0 { 440 self.section_num = 1; 441 } 442 SectionIndex(0) 443 } 444 445 /// Reserve a section table index. 446 /// 447 /// Automatically also reserves the null section header if required. 448 /// 449 /// This must be called before [`Self::reserve_section_headers`]. reserve_section_index(&mut self) -> SectionIndex450 pub fn reserve_section_index(&mut self) -> SectionIndex { 451 debug_assert_eq!(self.section_offset, 0); 452 if self.section_num == 0 { 453 self.section_num = 1; 454 } 455 let index = self.section_num; 456 self.section_num += 1; 457 SectionIndex(index) 458 } 459 section_header_size(&self) -> usize460 fn section_header_size(&self) -> usize { 461 if self.is_64 { 462 mem::size_of::<elf::SectionHeader64<Endianness>>() 463 } else { 464 mem::size_of::<elf::SectionHeader32<Endianness>>() 465 } 466 } 467 468 /// Reserve the range for the section headers. 469 /// 470 /// This function does nothing if no sections were reserved. 471 /// This must be called after [`Self::reserve_section_index`] 472 /// and other functions that reserve section indices. reserve_section_headers(&mut self)473 pub fn reserve_section_headers(&mut self) { 474 debug_assert_eq!(self.section_offset, 0); 475 if self.section_num == 0 { 476 return; 477 } 478 self.section_offset = self.reserve( 479 self.section_num as usize * self.section_header_size(), 480 self.elf_align, 481 ); 482 } 483 484 /// Write the null section header. 485 /// 486 /// This must be the first section header that is written. 487 /// This function does nothing if no sections were reserved. write_null_section_header(&mut self)488 pub fn write_null_section_header(&mut self) { 489 if self.section_num == 0 { 490 return; 491 } 492 util::write_align(self.buffer, self.elf_align); 493 debug_assert_eq!(self.section_offset, self.buffer.len()); 494 self.write_section_header(&SectionHeader { 495 name: None, 496 sh_type: 0, 497 sh_flags: 0, 498 sh_addr: 0, 499 sh_offset: 0, 500 sh_size: if self.section_num >= elf::SHN_LORESERVE.into() { 501 self.section_num.into() 502 } else { 503 0 504 }, 505 sh_link: if self.shstrtab_index.0 >= elf::SHN_LORESERVE.into() { 506 self.shstrtab_index.0 507 } else { 508 0 509 }, 510 // TODO: e_phnum overflow 511 sh_info: 0, 512 sh_addralign: 0, 513 sh_entsize: 0, 514 }); 515 } 516 517 /// Write a section header. write_section_header(&mut self, section: &SectionHeader)518 pub fn write_section_header(&mut self, section: &SectionHeader) { 519 let sh_name = if let Some(name) = section.name { 520 self.shstrtab.get_offset(name) as u32 521 } else { 522 0 523 }; 524 let endian = self.endian; 525 if self.is_64 { 526 let section = elf::SectionHeader64 { 527 sh_name: U32::new(endian, sh_name), 528 sh_type: U32::new(endian, section.sh_type), 529 sh_flags: U64::new(endian, section.sh_flags), 530 sh_addr: U64::new(endian, section.sh_addr), 531 sh_offset: U64::new(endian, section.sh_offset), 532 sh_size: U64::new(endian, section.sh_size), 533 sh_link: U32::new(endian, section.sh_link), 534 sh_info: U32::new(endian, section.sh_info), 535 sh_addralign: U64::new(endian, section.sh_addralign), 536 sh_entsize: U64::new(endian, section.sh_entsize), 537 }; 538 self.buffer.write(§ion); 539 } else { 540 let section = elf::SectionHeader32 { 541 sh_name: U32::new(endian, sh_name), 542 sh_type: U32::new(endian, section.sh_type), 543 sh_flags: U32::new(endian, section.sh_flags as u32), 544 sh_addr: U32::new(endian, section.sh_addr as u32), 545 sh_offset: U32::new(endian, section.sh_offset as u32), 546 sh_size: U32::new(endian, section.sh_size as u32), 547 sh_link: U32::new(endian, section.sh_link), 548 sh_info: U32::new(endian, section.sh_info), 549 sh_addralign: U32::new(endian, section.sh_addralign as u32), 550 sh_entsize: U32::new(endian, section.sh_entsize as u32), 551 }; 552 self.buffer.write(§ion); 553 } 554 } 555 556 /// Add a section name to the section header string table. 557 /// 558 /// This will be stored in the `.shstrtab` section. 559 /// 560 /// This must be called before [`Self::reserve_shstrtab`]. add_section_name(&mut self, name: &'a [u8]) -> StringId561 pub fn add_section_name(&mut self, name: &'a [u8]) -> StringId { 562 debug_assert_eq!(self.shstrtab_offset, 0); 563 self.shstrtab.add(name) 564 } 565 566 /// Reserve the range for the section header string table. 567 /// 568 /// This range is used for a section named `.shstrtab`. 569 /// 570 /// This function does nothing if no sections were reserved. 571 /// This must be called after [`Self::add_section_name`]. 572 /// and other functions that reserve section names and indices. reserve_shstrtab(&mut self)573 pub fn reserve_shstrtab(&mut self) { 574 debug_assert_eq!(self.shstrtab_offset, 0); 575 if self.section_num == 0 { 576 return; 577 } 578 // Start with null section name. 579 self.shstrtab_data = vec![0]; 580 self.shstrtab.write(1, &mut self.shstrtab_data); 581 self.shstrtab_offset = self.reserve(self.shstrtab_data.len(), 1); 582 } 583 584 /// Write the section header string table. 585 /// 586 /// This function does nothing if the section was not reserved. write_shstrtab(&mut self)587 pub fn write_shstrtab(&mut self) { 588 if self.shstrtab_offset == 0 { 589 return; 590 } 591 debug_assert_eq!(self.shstrtab_offset, self.buffer.len()); 592 self.buffer.write_bytes(&self.shstrtab_data); 593 } 594 595 /// Reserve the section index for the section header string table. 596 /// 597 /// This must be called before [`Self::reserve_shstrtab`] 598 /// and [`Self::reserve_section_headers`]. reserve_shstrtab_section_index(&mut self) -> SectionIndex599 pub fn reserve_shstrtab_section_index(&mut self) -> SectionIndex { 600 debug_assert_eq!(self.shstrtab_index, SectionIndex(0)); 601 self.shstrtab_str_id = Some(self.add_section_name(&b".shstrtab"[..])); 602 self.shstrtab_index = self.reserve_section_index(); 603 self.shstrtab_index 604 } 605 606 /// Write the section header for the section header string table. 607 /// 608 /// This function does nothing if the section index was not reserved. write_shstrtab_section_header(&mut self)609 pub fn write_shstrtab_section_header(&mut self) { 610 if self.shstrtab_index == SectionIndex(0) { 611 return; 612 } 613 self.write_section_header(&SectionHeader { 614 name: self.shstrtab_str_id, 615 sh_type: elf::SHT_STRTAB, 616 sh_flags: 0, 617 sh_addr: 0, 618 sh_offset: self.shstrtab_offset as u64, 619 sh_size: self.shstrtab_data.len() as u64, 620 sh_link: 0, 621 sh_info: 0, 622 sh_addralign: 1, 623 sh_entsize: 0, 624 }); 625 } 626 627 /// Add a string to the string table. 628 /// 629 /// This will be stored in the `.strtab` section. 630 /// 631 /// This must be called before [`Self::reserve_strtab`]. add_string(&mut self, name: &'a [u8]) -> StringId632 pub fn add_string(&mut self, name: &'a [u8]) -> StringId { 633 debug_assert_eq!(self.strtab_offset, 0); 634 self.need_strtab = true; 635 self.strtab.add(name) 636 } 637 638 /// Return true if `.strtab` is needed. strtab_needed(&self) -> bool639 pub fn strtab_needed(&self) -> bool { 640 self.need_strtab 641 } 642 643 /// Reserve the range for the string table. 644 /// 645 /// This range is used for a section named `.strtab`. 646 /// 647 /// This function does nothing if no strings or symbols were defined. 648 /// This must be called after [`Self::add_string`]. reserve_strtab(&mut self)649 pub fn reserve_strtab(&mut self) { 650 debug_assert_eq!(self.strtab_offset, 0); 651 if !self.need_strtab { 652 return; 653 } 654 // Start with null string. 655 self.strtab_data = vec![0]; 656 self.strtab.write(1, &mut self.strtab_data); 657 self.strtab_offset = self.reserve(self.strtab_data.len(), 1); 658 } 659 660 /// Write the string table. 661 /// 662 /// This function does nothing if the section was not reserved. write_strtab(&mut self)663 pub fn write_strtab(&mut self) { 664 if self.strtab_offset == 0 { 665 return; 666 } 667 debug_assert_eq!(self.strtab_offset, self.buffer.len()); 668 self.buffer.write_bytes(&self.strtab_data); 669 } 670 671 /// Reserve the section index for the string table. 672 /// 673 /// This must be called before [`Self::reserve_section_headers`]. reserve_strtab_section_index(&mut self) -> SectionIndex674 pub fn reserve_strtab_section_index(&mut self) -> SectionIndex { 675 debug_assert_eq!(self.strtab_index, SectionIndex(0)); 676 self.strtab_str_id = Some(self.add_section_name(&b".strtab"[..])); 677 self.strtab_index = self.reserve_section_index(); 678 self.strtab_index 679 } 680 681 /// Write the section header for the string table. 682 /// 683 /// This function does nothing if the section index was not reserved. write_strtab_section_header(&mut self)684 pub fn write_strtab_section_header(&mut self) { 685 if self.strtab_index == SectionIndex(0) { 686 return; 687 } 688 self.write_section_header(&SectionHeader { 689 name: self.strtab_str_id, 690 sh_type: elf::SHT_STRTAB, 691 sh_flags: 0, 692 sh_addr: 0, 693 sh_offset: self.strtab_offset as u64, 694 sh_size: self.strtab_data.len() as u64, 695 sh_link: 0, 696 sh_info: 0, 697 sh_addralign: 1, 698 sh_entsize: 0, 699 }); 700 } 701 702 /// Reserve a symbol table entry. 703 /// 704 /// This will be stored in the `.symtab` section. 705 /// 706 /// `section_index` is used to determine whether `.symtab_shndx` is required. 707 /// 708 /// Automatically also reserves the null symbol if required. 709 /// Callers may assume that the returned indices will be sequential 710 /// starting at 1. 711 /// 712 /// This must be called before [`Self::reserve_symtab`] and 713 /// [`Self::reserve_symtab_shndx`]. reserve_symbol_index(&mut self, section_index: Option<SectionIndex>) -> SymbolIndex714 pub fn reserve_symbol_index(&mut self, section_index: Option<SectionIndex>) -> SymbolIndex { 715 debug_assert_eq!(self.symtab_offset, 0); 716 debug_assert_eq!(self.symtab_shndx_offset, 0); 717 if self.symtab_num == 0 { 718 self.symtab_num = 1; 719 // The symtab must link to a strtab. 720 self.need_strtab = true; 721 } 722 let index = self.symtab_num; 723 self.symtab_num += 1; 724 if let Some(section_index) = section_index { 725 if section_index.0 >= elf::SHN_LORESERVE.into() { 726 self.need_symtab_shndx = true; 727 } 728 } 729 SymbolIndex(index) 730 } 731 732 /// Return the number of reserved symbol table entries. 733 /// 734 /// Includes the null symbol. symbol_count(&self) -> u32735 pub fn symbol_count(&self) -> u32 { 736 self.symtab_num 737 } 738 symbol_size(&self) -> usize739 fn symbol_size(&self) -> usize { 740 if self.is_64 { 741 mem::size_of::<elf::Sym64<Endianness>>() 742 } else { 743 mem::size_of::<elf::Sym32<Endianness>>() 744 } 745 } 746 747 /// Reserve the range for the symbol table. 748 /// 749 /// This range is used for a section named `.symtab`. 750 /// This function does nothing if no symbols were reserved. 751 /// This must be called after [`Self::reserve_symbol_index`]. reserve_symtab(&mut self)752 pub fn reserve_symtab(&mut self) { 753 debug_assert_eq!(self.symtab_offset, 0); 754 if self.symtab_num == 0 { 755 return; 756 } 757 self.symtab_offset = self.reserve( 758 self.symtab_num as usize * self.symbol_size(), 759 self.elf_align, 760 ); 761 } 762 763 /// Write the null symbol. 764 /// 765 /// This must be the first symbol that is written. 766 /// This function does nothing if no symbols were reserved. write_null_symbol(&mut self)767 pub fn write_null_symbol(&mut self) { 768 if self.symtab_num == 0 { 769 return; 770 } 771 util::write_align(self.buffer, self.elf_align); 772 debug_assert_eq!(self.symtab_offset, self.buffer.len()); 773 if self.is_64 { 774 self.buffer.write(&elf::Sym64::<Endianness>::default()); 775 } else { 776 self.buffer.write(&elf::Sym32::<Endianness>::default()); 777 } 778 779 if self.need_symtab_shndx { 780 self.symtab_shndx_data.write_pod(&U32::new(self.endian, 0)); 781 } 782 } 783 784 /// Write a symbol. write_symbol(&mut self, sym: &Sym)785 pub fn write_symbol(&mut self, sym: &Sym) { 786 let st_name = if let Some(name) = sym.name { 787 self.strtab.get_offset(name) as u32 788 } else { 789 0 790 }; 791 let st_shndx = if let Some(section) = sym.section { 792 if section.0 >= elf::SHN_LORESERVE as u32 { 793 elf::SHN_XINDEX 794 } else { 795 section.0 as u16 796 } 797 } else { 798 sym.st_shndx 799 }; 800 801 let endian = self.endian; 802 if self.is_64 { 803 let sym = elf::Sym64 { 804 st_name: U32::new(endian, st_name), 805 st_info: sym.st_info, 806 st_other: sym.st_other, 807 st_shndx: U16::new(endian, st_shndx), 808 st_value: U64::new(endian, sym.st_value), 809 st_size: U64::new(endian, sym.st_size), 810 }; 811 self.buffer.write(&sym); 812 } else { 813 let sym = elf::Sym32 { 814 st_name: U32::new(endian, st_name), 815 st_info: sym.st_info, 816 st_other: sym.st_other, 817 st_shndx: U16::new(endian, st_shndx), 818 st_value: U32::new(endian, sym.st_value as u32), 819 st_size: U32::new(endian, sym.st_size as u32), 820 }; 821 self.buffer.write(&sym); 822 } 823 824 if self.need_symtab_shndx { 825 let section_index = sym.section.unwrap_or(SectionIndex(0)); 826 self.symtab_shndx_data 827 .write_pod(&U32::new(self.endian, section_index.0)); 828 } 829 } 830 831 /// Reserve the section index for the symbol table. 832 /// 833 /// This must be called before [`Self::reserve_section_headers`]. reserve_symtab_section_index(&mut self) -> SectionIndex834 pub fn reserve_symtab_section_index(&mut self) -> SectionIndex { 835 debug_assert_eq!(self.symtab_index, SectionIndex(0)); 836 self.symtab_str_id = Some(self.add_section_name(&b".symtab"[..])); 837 self.symtab_index = self.reserve_section_index(); 838 self.symtab_index 839 } 840 841 /// Return the section index of the symbol table. symtab_index(&mut self) -> SectionIndex842 pub fn symtab_index(&mut self) -> SectionIndex { 843 self.symtab_index 844 } 845 846 /// Write the section header for the symbol table. 847 /// 848 /// This function does nothing if the section index was not reserved. write_symtab_section_header(&mut self, num_local: u32)849 pub fn write_symtab_section_header(&mut self, num_local: u32) { 850 if self.symtab_index == SectionIndex(0) { 851 return; 852 } 853 self.write_section_header(&SectionHeader { 854 name: self.symtab_str_id, 855 sh_type: elf::SHT_SYMTAB, 856 sh_flags: 0, 857 sh_addr: 0, 858 sh_offset: self.symtab_offset as u64, 859 sh_size: self.symtab_num as u64 * self.symbol_size() as u64, 860 sh_link: self.strtab_index.0, 861 sh_info: num_local, 862 sh_addralign: self.elf_align as u64, 863 sh_entsize: self.symbol_size() as u64, 864 }); 865 } 866 867 /// Return true if `.symtab_shndx` is needed. symtab_shndx_needed(&self) -> bool868 pub fn symtab_shndx_needed(&self) -> bool { 869 self.need_symtab_shndx 870 } 871 872 /// Reserve the range for the extended section indices for the symbol table. 873 /// 874 /// This range is used for a section named `.symtab_shndx`. 875 /// This also reserves a section index. 876 /// 877 /// This function does nothing if extended section indices are not needed. 878 /// This must be called after [`Self::reserve_symbol_index`]. reserve_symtab_shndx(&mut self)879 pub fn reserve_symtab_shndx(&mut self) { 880 debug_assert_eq!(self.symtab_shndx_offset, 0); 881 if !self.need_symtab_shndx { 882 return; 883 } 884 self.symtab_shndx_offset = self.reserve(self.symtab_num as usize * 4, 4); 885 self.symtab_shndx_data.reserve(self.symtab_num as usize * 4); 886 } 887 888 /// Write the extended section indices for the symbol table. 889 /// 890 /// This function does nothing if the section was not reserved. write_symtab_shndx(&mut self)891 pub fn write_symtab_shndx(&mut self) { 892 if self.symtab_shndx_offset == 0 { 893 return; 894 } 895 debug_assert_eq!(self.symtab_shndx_offset, self.buffer.len()); 896 debug_assert_eq!(self.symtab_num as usize * 4, self.symtab_shndx_data.len()); 897 self.buffer.write_bytes(&self.symtab_shndx_data); 898 } 899 900 /// Reserve the section index for the extended section indices symbol table. 901 /// 902 /// You should check [`Self::symtab_shndx_needed`] before calling this 903 /// unless you have other means of knowing if this section is needed. 904 /// 905 /// This must be called before [`Self::reserve_section_headers`]. reserve_symtab_shndx_section_index(&mut self) -> SectionIndex906 pub fn reserve_symtab_shndx_section_index(&mut self) -> SectionIndex { 907 debug_assert!(self.symtab_shndx_str_id.is_none()); 908 self.symtab_shndx_str_id = Some(self.add_section_name(&b".symtab_shndx"[..])); 909 self.reserve_section_index() 910 } 911 912 /// Write the section header for the extended section indices for the symbol table. 913 /// 914 /// This function does nothing if the section index was not reserved. write_symtab_shndx_section_header(&mut self)915 pub fn write_symtab_shndx_section_header(&mut self) { 916 if self.symtab_shndx_str_id.is_none() { 917 return; 918 } 919 let sh_size = if self.symtab_shndx_offset == 0 { 920 0 921 } else { 922 (self.symtab_num * 4) as u64 923 }; 924 self.write_section_header(&SectionHeader { 925 name: self.symtab_shndx_str_id, 926 sh_type: elf::SHT_SYMTAB_SHNDX, 927 sh_flags: 0, 928 sh_addr: 0, 929 sh_offset: self.symtab_shndx_offset as u64, 930 sh_size, 931 sh_link: self.symtab_index.0, 932 sh_info: 0, 933 sh_addralign: 4, 934 sh_entsize: 4, 935 }); 936 } 937 938 /// Add a string to the dynamic string table. 939 /// 940 /// This will be stored in the `.dynstr` section. 941 /// 942 /// This must be called before [`Self::reserve_dynstr`]. add_dynamic_string(&mut self, name: &'a [u8]) -> StringId943 pub fn add_dynamic_string(&mut self, name: &'a [u8]) -> StringId { 944 debug_assert_eq!(self.dynstr_offset, 0); 945 self.need_dynstr = true; 946 self.dynstr.add(name) 947 } 948 949 /// Get a string that was previously added to the dynamic string table. 950 /// 951 /// Panics if the string was not added. get_dynamic_string(&self, name: &'a [u8]) -> StringId952 pub fn get_dynamic_string(&self, name: &'a [u8]) -> StringId { 953 self.dynstr.get_id(name) 954 } 955 956 /// Return true if `.dynstr` is needed. dynstr_needed(&self) -> bool957 pub fn dynstr_needed(&self) -> bool { 958 self.need_dynstr 959 } 960 961 /// Reserve the range for the dynamic string table. 962 /// 963 /// This range is used for a section named `.dynstr`. 964 /// 965 /// This function does nothing if no dynamic strings or symbols were defined. 966 /// This must be called after [`Self::add_dynamic_string`]. reserve_dynstr(&mut self)967 pub fn reserve_dynstr(&mut self) { 968 debug_assert_eq!(self.dynstr_offset, 0); 969 if !self.need_dynstr { 970 return; 971 } 972 // Start with null string. 973 self.dynstr_data = vec![0]; 974 self.dynstr.write(1, &mut self.dynstr_data); 975 self.dynstr_offset = self.reserve(self.dynstr_data.len(), 1); 976 } 977 978 /// Write the dynamic string table. 979 /// 980 /// This function does nothing if the section was not reserved. write_dynstr(&mut self)981 pub fn write_dynstr(&mut self) { 982 if self.dynstr_offset == 0 { 983 return; 984 } 985 debug_assert_eq!(self.dynstr_offset, self.buffer.len()); 986 self.buffer.write_bytes(&self.dynstr_data); 987 } 988 989 /// Reserve the section index for the dynamic string table. 990 /// 991 /// This must be called before [`Self::reserve_section_headers`]. reserve_dynstr_section_index(&mut self) -> SectionIndex992 pub fn reserve_dynstr_section_index(&mut self) -> SectionIndex { 993 debug_assert_eq!(self.dynstr_index, SectionIndex(0)); 994 self.dynstr_str_id = Some(self.add_section_name(&b".dynstr"[..])); 995 self.dynstr_index = self.reserve_section_index(); 996 self.dynstr_index 997 } 998 999 /// Return the section index of the dynamic string table. dynstr_index(&mut self) -> SectionIndex1000 pub fn dynstr_index(&mut self) -> SectionIndex { 1001 self.dynstr_index 1002 } 1003 1004 /// Write the section header for the dynamic string table. 1005 /// 1006 /// This function does nothing if the section index was not reserved. write_dynstr_section_header(&mut self, sh_addr: u64)1007 pub fn write_dynstr_section_header(&mut self, sh_addr: u64) { 1008 if self.dynstr_index == SectionIndex(0) { 1009 return; 1010 } 1011 self.write_section_header(&SectionHeader { 1012 name: self.dynstr_str_id, 1013 sh_type: elf::SHT_STRTAB, 1014 sh_flags: elf::SHF_ALLOC.into(), 1015 sh_addr, 1016 sh_offset: self.dynstr_offset as u64, 1017 sh_size: self.dynstr_data.len() as u64, 1018 sh_link: 0, 1019 sh_info: 0, 1020 sh_addralign: 1, 1021 sh_entsize: 0, 1022 }); 1023 } 1024 1025 /// Reserve the null dynamic symbol table entry. 1026 /// 1027 /// This will be stored in the `.dynsym` section. 1028 /// 1029 /// The null dynamic symbol table entry is usually automatically reserved, 1030 /// but this can be used to force an empty dynamic symbol table. 1031 /// 1032 /// This must be called before [`Self::reserve_dynsym`]. reserve_null_dynamic_symbol_index(&mut self) -> SymbolIndex1033 pub fn reserve_null_dynamic_symbol_index(&mut self) -> SymbolIndex { 1034 debug_assert_eq!(self.dynsym_offset, 0); 1035 debug_assert_eq!(self.dynsym_num, 0); 1036 self.dynsym_num = 1; 1037 // The symtab must link to a strtab. 1038 self.need_dynstr = true; 1039 SymbolIndex(0) 1040 } 1041 1042 /// Reserve a dynamic symbol table entry. 1043 /// 1044 /// This will be stored in the `.dynsym` section. 1045 /// 1046 /// Automatically also reserves the null symbol if required. 1047 /// Callers may assume that the returned indices will be sequential 1048 /// starting at 1. 1049 /// 1050 /// This must be called before [`Self::reserve_dynsym`]. reserve_dynamic_symbol_index(&mut self) -> SymbolIndex1051 pub fn reserve_dynamic_symbol_index(&mut self) -> SymbolIndex { 1052 debug_assert_eq!(self.dynsym_offset, 0); 1053 if self.dynsym_num == 0 { 1054 self.dynsym_num = 1; 1055 // The symtab must link to a strtab. 1056 self.need_dynstr = true; 1057 } 1058 let index = self.dynsym_num; 1059 self.dynsym_num += 1; 1060 SymbolIndex(index) 1061 } 1062 1063 /// Return the number of reserved dynamic symbols. 1064 /// 1065 /// Includes the null symbol. dynamic_symbol_count(&mut self) -> u321066 pub fn dynamic_symbol_count(&mut self) -> u32 { 1067 self.dynsym_num 1068 } 1069 1070 /// Reserve the range for the dynamic symbol table. 1071 /// 1072 /// This range is used for a section named `.dynsym`. 1073 /// 1074 /// This function does nothing if no dynamic symbols were reserved. 1075 /// This must be called after [`Self::reserve_dynamic_symbol_index`]. reserve_dynsym(&mut self)1076 pub fn reserve_dynsym(&mut self) { 1077 debug_assert_eq!(self.dynsym_offset, 0); 1078 if self.dynsym_num == 0 { 1079 return; 1080 } 1081 self.dynsym_offset = self.reserve( 1082 self.dynsym_num as usize * self.symbol_size(), 1083 self.elf_align, 1084 ); 1085 } 1086 1087 /// Write the null dynamic symbol. 1088 /// 1089 /// This must be the first dynamic symbol that is written. 1090 /// This function does nothing if no dynamic symbols were reserved. write_null_dynamic_symbol(&mut self)1091 pub fn write_null_dynamic_symbol(&mut self) { 1092 if self.dynsym_num == 0 { 1093 return; 1094 } 1095 util::write_align(self.buffer, self.elf_align); 1096 debug_assert_eq!(self.dynsym_offset, self.buffer.len()); 1097 if self.is_64 { 1098 self.buffer.write(&elf::Sym64::<Endianness>::default()); 1099 } else { 1100 self.buffer.write(&elf::Sym32::<Endianness>::default()); 1101 } 1102 } 1103 1104 /// Write a dynamic symbol. write_dynamic_symbol(&mut self, sym: &Sym)1105 pub fn write_dynamic_symbol(&mut self, sym: &Sym) { 1106 let st_name = if let Some(name) = sym.name { 1107 self.dynstr.get_offset(name) as u32 1108 } else { 1109 0 1110 }; 1111 1112 let st_shndx = if let Some(section) = sym.section { 1113 if section.0 >= elf::SHN_LORESERVE as u32 { 1114 // TODO: we don't actually write out .dynsym_shndx yet. 1115 // This is unlikely to be needed though. 1116 elf::SHN_XINDEX 1117 } else { 1118 section.0 as u16 1119 } 1120 } else { 1121 sym.st_shndx 1122 }; 1123 1124 let endian = self.endian; 1125 if self.is_64 { 1126 let sym = elf::Sym64 { 1127 st_name: U32::new(endian, st_name), 1128 st_info: sym.st_info, 1129 st_other: sym.st_other, 1130 st_shndx: U16::new(endian, st_shndx), 1131 st_value: U64::new(endian, sym.st_value), 1132 st_size: U64::new(endian, sym.st_size), 1133 }; 1134 self.buffer.write(&sym); 1135 } else { 1136 let sym = elf::Sym32 { 1137 st_name: U32::new(endian, st_name), 1138 st_info: sym.st_info, 1139 st_other: sym.st_other, 1140 st_shndx: U16::new(endian, st_shndx), 1141 st_value: U32::new(endian, sym.st_value as u32), 1142 st_size: U32::new(endian, sym.st_size as u32), 1143 }; 1144 self.buffer.write(&sym); 1145 } 1146 } 1147 1148 /// Reserve the section index for the dynamic symbol table. 1149 /// 1150 /// This must be called before [`Self::reserve_section_headers`]. reserve_dynsym_section_index(&mut self) -> SectionIndex1151 pub fn reserve_dynsym_section_index(&mut self) -> SectionIndex { 1152 debug_assert_eq!(self.dynsym_index, SectionIndex(0)); 1153 self.dynsym_str_id = Some(self.add_section_name(&b".dynsym"[..])); 1154 self.dynsym_index = self.reserve_section_index(); 1155 self.dynsym_index 1156 } 1157 1158 /// Return the section index of the dynamic symbol table. dynsym_index(&mut self) -> SectionIndex1159 pub fn dynsym_index(&mut self) -> SectionIndex { 1160 self.dynsym_index 1161 } 1162 1163 /// Write the section header for the dynamic symbol table. 1164 /// 1165 /// This function does nothing if the section index was not reserved. write_dynsym_section_header(&mut self, sh_addr: u64, num_local: u32)1166 pub fn write_dynsym_section_header(&mut self, sh_addr: u64, num_local: u32) { 1167 if self.dynsym_index == SectionIndex(0) { 1168 return; 1169 } 1170 self.write_section_header(&SectionHeader { 1171 name: self.dynsym_str_id, 1172 sh_type: elf::SHT_DYNSYM, 1173 sh_flags: elf::SHF_ALLOC.into(), 1174 sh_addr, 1175 sh_offset: self.dynsym_offset as u64, 1176 sh_size: self.dynsym_num as u64 * self.symbol_size() as u64, 1177 sh_link: self.dynstr_index.0, 1178 sh_info: num_local, 1179 sh_addralign: self.elf_align as u64, 1180 sh_entsize: self.symbol_size() as u64, 1181 }); 1182 } 1183 dyn_size(&self) -> usize1184 fn dyn_size(&self) -> usize { 1185 if self.is_64 { 1186 mem::size_of::<elf::Dyn64<Endianness>>() 1187 } else { 1188 mem::size_of::<elf::Dyn32<Endianness>>() 1189 } 1190 } 1191 1192 /// Reserve the range for the `.dynamic` section. 1193 /// 1194 /// This function does nothing if `dynamic_num` is zero. reserve_dynamic(&mut self, dynamic_num: usize)1195 pub fn reserve_dynamic(&mut self, dynamic_num: usize) { 1196 debug_assert_eq!(self.dynamic_offset, 0); 1197 if dynamic_num == 0 { 1198 return; 1199 } 1200 self.dynamic_num = dynamic_num; 1201 self.dynamic_offset = self.reserve(dynamic_num * self.dyn_size(), self.elf_align); 1202 } 1203 1204 /// Write alignment padding bytes prior to the `.dynamic` section. 1205 /// 1206 /// This function does nothing if the section was not reserved. write_align_dynamic(&mut self)1207 pub fn write_align_dynamic(&mut self) { 1208 if self.dynamic_offset == 0 { 1209 return; 1210 } 1211 util::write_align(self.buffer, self.elf_align); 1212 debug_assert_eq!(self.dynamic_offset, self.buffer.len()); 1213 } 1214 1215 /// Write a dynamic string entry. write_dynamic_string(&mut self, tag: u32, id: StringId)1216 pub fn write_dynamic_string(&mut self, tag: u32, id: StringId) { 1217 self.write_dynamic(tag, self.dynstr.get_offset(id) as u64); 1218 } 1219 1220 /// Write a dynamic value entry. write_dynamic(&mut self, d_tag: u32, d_val: u64)1221 pub fn write_dynamic(&mut self, d_tag: u32, d_val: u64) { 1222 debug_assert!(self.dynamic_offset <= self.buffer.len()); 1223 let endian = self.endian; 1224 if self.is_64 { 1225 let d = elf::Dyn64 { 1226 d_tag: U64::new(endian, d_tag.into()), 1227 d_val: U64::new(endian, d_val), 1228 }; 1229 self.buffer.write(&d); 1230 } else { 1231 let d = elf::Dyn32 { 1232 d_tag: U32::new(endian, d_tag), 1233 d_val: U32::new(endian, d_val as u32), 1234 }; 1235 self.buffer.write(&d); 1236 } 1237 debug_assert!( 1238 self.dynamic_offset + self.dynamic_num * self.dyn_size() >= self.buffer.len() 1239 ); 1240 } 1241 1242 /// Reserve the section index for the dynamic table. reserve_dynamic_section_index(&mut self) -> SectionIndex1243 pub fn reserve_dynamic_section_index(&mut self) -> SectionIndex { 1244 debug_assert!(self.dynamic_str_id.is_none()); 1245 self.dynamic_str_id = Some(self.add_section_name(&b".dynamic"[..])); 1246 self.reserve_section_index() 1247 } 1248 1249 /// Write the section header for the dynamic table. 1250 /// 1251 /// This function does nothing if the section index was not reserved. write_dynamic_section_header(&mut self, sh_addr: u64)1252 pub fn write_dynamic_section_header(&mut self, sh_addr: u64) { 1253 if self.dynamic_str_id.is_none() { 1254 return; 1255 } 1256 self.write_section_header(&SectionHeader { 1257 name: self.dynamic_str_id, 1258 sh_type: elf::SHT_DYNAMIC, 1259 sh_flags: (elf::SHF_WRITE | elf::SHF_ALLOC).into(), 1260 sh_addr, 1261 sh_offset: self.dynamic_offset as u64, 1262 sh_size: (self.dynamic_num * self.dyn_size()) as u64, 1263 sh_link: self.dynstr_index.0, 1264 sh_info: 0, 1265 sh_addralign: self.elf_align as u64, 1266 sh_entsize: self.dyn_size() as u64, 1267 }); 1268 } 1269 rel_size(&self, is_rela: bool) -> usize1270 fn rel_size(&self, is_rela: bool) -> usize { 1271 if self.is_64 { 1272 if is_rela { 1273 mem::size_of::<elf::Rela64<Endianness>>() 1274 } else { 1275 mem::size_of::<elf::Rel64<Endianness>>() 1276 } 1277 } else { 1278 if is_rela { 1279 mem::size_of::<elf::Rela32<Endianness>>() 1280 } else { 1281 mem::size_of::<elf::Rel32<Endianness>>() 1282 } 1283 } 1284 } 1285 1286 /// Reserve a file range for a SysV hash section. 1287 /// 1288 /// `symbol_count` is the number of symbols in the hash, 1289 /// not the total number of symbols. reserve_hash(&mut self, bucket_count: u32, chain_count: u32)1290 pub fn reserve_hash(&mut self, bucket_count: u32, chain_count: u32) { 1291 self.hash_size = mem::size_of::<elf::HashHeader<Endianness>>() 1292 + bucket_count as usize * 4 1293 + chain_count as usize * 4; 1294 self.hash_offset = self.reserve(self.hash_size, self.elf_align); 1295 } 1296 1297 /// Write a SysV hash section. 1298 /// 1299 /// `chain_count` is the number of symbols in the hash. 1300 /// The argument to `hash` will be in the range `0..chain_count`. write_hash<F>(&mut self, bucket_count: u32, chain_count: u32, hash: F) where F: Fn(u32) -> Option<u32>,1301 pub fn write_hash<F>(&mut self, bucket_count: u32, chain_count: u32, hash: F) 1302 where 1303 F: Fn(u32) -> Option<u32>, 1304 { 1305 let mut buckets = vec![U32::new(self.endian, 0); bucket_count as usize]; 1306 let mut chains = vec![U32::new(self.endian, 0); chain_count as usize]; 1307 for i in 0..chain_count { 1308 if let Some(hash) = hash(i) { 1309 let bucket = hash % bucket_count; 1310 chains[i as usize] = buckets[bucket as usize]; 1311 buckets[bucket as usize] = U32::new(self.endian, i); 1312 } 1313 } 1314 1315 util::write_align(self.buffer, self.elf_align); 1316 debug_assert_eq!(self.hash_offset, self.buffer.len()); 1317 self.buffer.write(&elf::HashHeader { 1318 bucket_count: U32::new(self.endian, bucket_count), 1319 chain_count: U32::new(self.endian, chain_count), 1320 }); 1321 self.buffer.write_slice(&buckets); 1322 self.buffer.write_slice(&chains); 1323 } 1324 1325 /// Reserve the section index for the SysV hash table. reserve_hash_section_index(&mut self) -> SectionIndex1326 pub fn reserve_hash_section_index(&mut self) -> SectionIndex { 1327 debug_assert!(self.hash_str_id.is_none()); 1328 self.hash_str_id = Some(self.add_section_name(&b".hash"[..])); 1329 self.reserve_section_index() 1330 } 1331 1332 /// Write the section header for the SysV hash table. 1333 /// 1334 /// This function does nothing if the section index was not reserved. write_hash_section_header(&mut self, sh_addr: u64)1335 pub fn write_hash_section_header(&mut self, sh_addr: u64) { 1336 if self.hash_str_id.is_none() { 1337 return; 1338 } 1339 self.write_section_header(&SectionHeader { 1340 name: self.hash_str_id, 1341 sh_type: elf::SHT_HASH, 1342 sh_flags: elf::SHF_ALLOC.into(), 1343 sh_addr, 1344 sh_offset: self.hash_offset as u64, 1345 sh_size: self.hash_size as u64, 1346 sh_link: self.dynsym_index.0, 1347 sh_info: 0, 1348 sh_addralign: self.elf_align as u64, 1349 sh_entsize: 4, 1350 }); 1351 } 1352 1353 /// Reserve a file range for a GNU hash section. 1354 /// 1355 /// `symbol_count` is the number of symbols in the hash, 1356 /// not the total number of symbols. reserve_gnu_hash(&mut self, bloom_count: u32, bucket_count: u32, symbol_count: u32)1357 pub fn reserve_gnu_hash(&mut self, bloom_count: u32, bucket_count: u32, symbol_count: u32) { 1358 self.gnu_hash_size = mem::size_of::<elf::GnuHashHeader<Endianness>>() 1359 + bloom_count as usize * self.elf_align 1360 + bucket_count as usize * 4 1361 + symbol_count as usize * 4; 1362 self.gnu_hash_offset = self.reserve(self.gnu_hash_size, self.elf_align); 1363 } 1364 1365 /// Write a GNU hash section. 1366 /// 1367 /// `symbol_count` is the number of symbols in the hash. 1368 /// The argument to `hash` will be in the range `0..symbol_count`. 1369 /// 1370 /// This requires that symbols are already sorted by bucket. write_gnu_hash<F>( &mut self, symbol_base: u32, bloom_shift: u32, bloom_count: u32, bucket_count: u32, symbol_count: u32, hash: F, ) where F: Fn(u32) -> u32,1371 pub fn write_gnu_hash<F>( 1372 &mut self, 1373 symbol_base: u32, 1374 bloom_shift: u32, 1375 bloom_count: u32, 1376 bucket_count: u32, 1377 symbol_count: u32, 1378 hash: F, 1379 ) where 1380 F: Fn(u32) -> u32, 1381 { 1382 util::write_align(self.buffer, self.elf_align); 1383 debug_assert_eq!(self.gnu_hash_offset, self.buffer.len()); 1384 self.buffer.write(&elf::GnuHashHeader { 1385 bucket_count: U32::new(self.endian, bucket_count), 1386 symbol_base: U32::new(self.endian, symbol_base), 1387 bloom_count: U32::new(self.endian, bloom_count), 1388 bloom_shift: U32::new(self.endian, bloom_shift), 1389 }); 1390 1391 // Calculate and write bloom filter. 1392 if self.is_64 { 1393 let mut bloom_filters = vec![0; bloom_count as usize]; 1394 for i in 0..symbol_count { 1395 let h = hash(i); 1396 bloom_filters[((h / 64) & (bloom_count - 1)) as usize] |= 1397 1 << (h % 64) | 1 << ((h >> bloom_shift) % 64); 1398 } 1399 for bloom_filter in bloom_filters { 1400 self.buffer.write(&U64::new(self.endian, bloom_filter)); 1401 } 1402 } else { 1403 let mut bloom_filters = vec![0; bloom_count as usize]; 1404 for i in 0..symbol_count { 1405 let h = hash(i); 1406 bloom_filters[((h / 32) & (bloom_count - 1)) as usize] |= 1407 1 << (h % 32) | 1 << ((h >> bloom_shift) % 32); 1408 } 1409 for bloom_filter in bloom_filters { 1410 self.buffer.write(&U32::new(self.endian, bloom_filter)); 1411 } 1412 } 1413 1414 // Write buckets. 1415 // 1416 // This requires that symbols are already sorted by bucket. 1417 let mut bucket = 0; 1418 for i in 0..symbol_count { 1419 let symbol_bucket = hash(i) % bucket_count; 1420 while bucket < symbol_bucket { 1421 self.buffer.write(&U32::new(self.endian, 0)); 1422 bucket += 1; 1423 } 1424 if bucket == symbol_bucket { 1425 self.buffer.write(&U32::new(self.endian, symbol_base + i)); 1426 bucket += 1; 1427 } 1428 } 1429 while bucket < bucket_count { 1430 self.buffer.write(&U32::new(self.endian, 0)); 1431 bucket += 1; 1432 } 1433 1434 // Write hash values. 1435 for i in 0..symbol_count { 1436 let mut h = hash(i); 1437 if i == symbol_count - 1 || h % bucket_count != hash(i + 1) % bucket_count { 1438 h |= 1; 1439 } else { 1440 h &= !1; 1441 } 1442 self.buffer.write(&U32::new(self.endian, h)); 1443 } 1444 } 1445 1446 /// Reserve the section index for the GNU hash table. reserve_gnu_hash_section_index(&mut self) -> SectionIndex1447 pub fn reserve_gnu_hash_section_index(&mut self) -> SectionIndex { 1448 debug_assert!(self.gnu_hash_str_id.is_none()); 1449 self.gnu_hash_str_id = Some(self.add_section_name(&b".gnu.hash"[..])); 1450 self.reserve_section_index() 1451 } 1452 1453 /// Write the section header for the GNU hash table. 1454 /// 1455 /// This function does nothing if the section index was not reserved. write_gnu_hash_section_header(&mut self, sh_addr: u64)1456 pub fn write_gnu_hash_section_header(&mut self, sh_addr: u64) { 1457 if self.gnu_hash_str_id.is_none() { 1458 return; 1459 } 1460 self.write_section_header(&SectionHeader { 1461 name: self.gnu_hash_str_id, 1462 sh_type: elf::SHT_GNU_HASH, 1463 sh_flags: elf::SHF_ALLOC.into(), 1464 sh_addr, 1465 sh_offset: self.gnu_hash_offset as u64, 1466 sh_size: self.gnu_hash_size as u64, 1467 sh_link: self.dynsym_index.0, 1468 sh_info: 0, 1469 sh_addralign: self.elf_align as u64, 1470 sh_entsize: 0, 1471 }); 1472 } 1473 1474 /// Reserve the range for the `.gnu.version` section. 1475 /// 1476 /// This function does nothing if no dynamic symbols were reserved. reserve_gnu_versym(&mut self)1477 pub fn reserve_gnu_versym(&mut self) { 1478 debug_assert_eq!(self.gnu_versym_offset, 0); 1479 if self.dynsym_num == 0 { 1480 return; 1481 } 1482 self.gnu_versym_offset = self.reserve(self.dynsym_num as usize * 2, 2); 1483 } 1484 1485 /// Write the null symbol version entry. 1486 /// 1487 /// This must be the first symbol version that is written. 1488 /// This function does nothing if no dynamic symbols were reserved. write_null_gnu_versym(&mut self)1489 pub fn write_null_gnu_versym(&mut self) { 1490 if self.dynsym_num == 0 { 1491 return; 1492 } 1493 util::write_align(self.buffer, 2); 1494 debug_assert_eq!(self.gnu_versym_offset, self.buffer.len()); 1495 self.write_gnu_versym(0); 1496 } 1497 1498 /// Write a symbol version entry. write_gnu_versym(&mut self, versym: u16)1499 pub fn write_gnu_versym(&mut self, versym: u16) { 1500 self.buffer.write(&U16::new(self.endian, versym)); 1501 } 1502 1503 /// Reserve the section index for the `.gnu.version` section. reserve_gnu_versym_section_index(&mut self) -> SectionIndex1504 pub fn reserve_gnu_versym_section_index(&mut self) -> SectionIndex { 1505 debug_assert!(self.gnu_versym_str_id.is_none()); 1506 self.gnu_versym_str_id = Some(self.add_section_name(&b".gnu.version"[..])); 1507 self.reserve_section_index() 1508 } 1509 1510 /// Write the section header for the `.gnu.version` section. 1511 /// 1512 /// This function does nothing if the section index was not reserved. write_gnu_versym_section_header(&mut self, sh_addr: u64)1513 pub fn write_gnu_versym_section_header(&mut self, sh_addr: u64) { 1514 if self.gnu_versym_str_id.is_none() { 1515 return; 1516 } 1517 self.write_section_header(&SectionHeader { 1518 name: self.gnu_versym_str_id, 1519 sh_type: elf::SHT_GNU_VERSYM, 1520 sh_flags: elf::SHF_ALLOC.into(), 1521 sh_addr, 1522 sh_offset: self.gnu_versym_offset as u64, 1523 sh_size: self.dynsym_num as u64 * 2, 1524 sh_link: self.dynsym_index.0, 1525 sh_info: 0, 1526 sh_addralign: 2, 1527 sh_entsize: 2, 1528 }); 1529 } 1530 1531 /// Reserve the range for the `.gnu.version_d` section. reserve_gnu_verdef(&mut self, verdef_count: usize, verdaux_count: usize)1532 pub fn reserve_gnu_verdef(&mut self, verdef_count: usize, verdaux_count: usize) { 1533 debug_assert_eq!(self.gnu_verdef_offset, 0); 1534 if verdef_count == 0 { 1535 return; 1536 } 1537 self.gnu_verdef_size = verdef_count * mem::size_of::<elf::Verdef<Endianness>>() 1538 + verdaux_count * mem::size_of::<elf::Verdaux<Endianness>>(); 1539 self.gnu_verdef_offset = self.reserve(self.gnu_verdef_size, self.elf_align); 1540 self.gnu_verdef_count = verdef_count as u16; 1541 self.gnu_verdef_remaining = self.gnu_verdef_count; 1542 } 1543 1544 /// Write alignment padding bytes prior to a `.gnu.version_d` section. write_align_gnu_verdef(&mut self)1545 pub fn write_align_gnu_verdef(&mut self) { 1546 if self.gnu_verdef_offset == 0 { 1547 return; 1548 } 1549 util::write_align(self.buffer, self.elf_align); 1550 debug_assert_eq!(self.gnu_verdef_offset, self.buffer.len()); 1551 } 1552 1553 /// Write a version definition entry. write_gnu_verdef(&mut self, verdef: &Verdef)1554 pub fn write_gnu_verdef(&mut self, verdef: &Verdef) { 1555 debug_assert_ne!(self.gnu_verdef_remaining, 0); 1556 self.gnu_verdef_remaining -= 1; 1557 let vd_next = if self.gnu_verdef_remaining == 0 { 1558 0 1559 } else { 1560 mem::size_of::<elf::Verdef<Endianness>>() as u32 1561 + verdef.aux_count as u32 * mem::size_of::<elf::Verdaux<Endianness>>() as u32 1562 }; 1563 1564 self.gnu_verdaux_remaining = verdef.aux_count; 1565 let vd_aux = if verdef.aux_count == 0 { 1566 0 1567 } else { 1568 mem::size_of::<elf::Verdef<Endianness>>() as u32 1569 }; 1570 1571 self.buffer.write(&elf::Verdef { 1572 vd_version: U16::new(self.endian, verdef.version), 1573 vd_flags: U16::new(self.endian, verdef.flags), 1574 vd_ndx: U16::new(self.endian, verdef.index), 1575 vd_cnt: U16::new(self.endian, verdef.aux_count), 1576 vd_hash: U32::new(self.endian, elf::hash(self.dynstr.get_string(verdef.name))), 1577 vd_aux: U32::new(self.endian, vd_aux), 1578 vd_next: U32::new(self.endian, vd_next), 1579 }); 1580 self.write_gnu_verdaux(verdef.name); 1581 } 1582 1583 /// Write a version definition auxiliary entry. write_gnu_verdaux(&mut self, name: StringId)1584 pub fn write_gnu_verdaux(&mut self, name: StringId) { 1585 debug_assert_ne!(self.gnu_verdaux_remaining, 0); 1586 self.gnu_verdaux_remaining -= 1; 1587 let vda_next = if self.gnu_verdaux_remaining == 0 { 1588 0 1589 } else { 1590 mem::size_of::<elf::Verdaux<Endianness>>() as u32 1591 }; 1592 self.buffer.write(&elf::Verdaux { 1593 vda_name: U32::new(self.endian, self.dynstr.get_offset(name) as u32), 1594 vda_next: U32::new(self.endian, vda_next), 1595 }); 1596 } 1597 1598 /// Reserve the section index for the `.gnu.version_d` section. reserve_gnu_verdef_section_index(&mut self) -> SectionIndex1599 pub fn reserve_gnu_verdef_section_index(&mut self) -> SectionIndex { 1600 debug_assert!(self.gnu_verdef_str_id.is_none()); 1601 self.gnu_verdef_str_id = Some(self.add_section_name(&b".gnu.version_d"[..])); 1602 self.reserve_section_index() 1603 } 1604 1605 /// Write the section header for the `.gnu.version_d` section. 1606 /// 1607 /// This function does nothing if the section index was not reserved. write_gnu_verdef_section_header(&mut self, sh_addr: u64)1608 pub fn write_gnu_verdef_section_header(&mut self, sh_addr: u64) { 1609 if self.gnu_verdef_str_id.is_none() { 1610 return; 1611 } 1612 self.write_section_header(&SectionHeader { 1613 name: self.gnu_verdef_str_id, 1614 sh_type: elf::SHT_GNU_VERDEF, 1615 sh_flags: elf::SHF_ALLOC.into(), 1616 sh_addr, 1617 sh_offset: self.gnu_verdef_offset as u64, 1618 sh_size: self.gnu_verdef_size as u64, 1619 sh_link: self.dynstr_index.0, 1620 sh_info: self.gnu_verdef_count.into(), 1621 sh_addralign: self.elf_align as u64, 1622 sh_entsize: 0, 1623 }); 1624 } 1625 1626 /// Reserve the range for the `.gnu.version_r` section. reserve_gnu_verneed(&mut self, verneed_count: usize, vernaux_count: usize)1627 pub fn reserve_gnu_verneed(&mut self, verneed_count: usize, vernaux_count: usize) { 1628 debug_assert_eq!(self.gnu_verneed_offset, 0); 1629 if verneed_count == 0 { 1630 return; 1631 } 1632 self.gnu_verneed_size = verneed_count * mem::size_of::<elf::Verneed<Endianness>>() 1633 + vernaux_count * mem::size_of::<elf::Vernaux<Endianness>>(); 1634 self.gnu_verneed_offset = self.reserve(self.gnu_verneed_size, self.elf_align); 1635 self.gnu_verneed_count = verneed_count as u16; 1636 self.gnu_verneed_remaining = self.gnu_verneed_count; 1637 } 1638 1639 /// Write alignment padding bytes prior to a `.gnu.version_r` section. write_align_gnu_verneed(&mut self)1640 pub fn write_align_gnu_verneed(&mut self) { 1641 if self.gnu_verneed_offset == 0 { 1642 return; 1643 } 1644 util::write_align(self.buffer, self.elf_align); 1645 debug_assert_eq!(self.gnu_verneed_offset, self.buffer.len()); 1646 } 1647 1648 /// Write a version need entry. write_gnu_verneed(&mut self, verneed: &Verneed)1649 pub fn write_gnu_verneed(&mut self, verneed: &Verneed) { 1650 debug_assert_ne!(self.gnu_verneed_remaining, 0); 1651 self.gnu_verneed_remaining -= 1; 1652 let vn_next = if self.gnu_verneed_remaining == 0 { 1653 0 1654 } else { 1655 mem::size_of::<elf::Verneed<Endianness>>() as u32 1656 + verneed.aux_count as u32 * mem::size_of::<elf::Vernaux<Endianness>>() as u32 1657 }; 1658 1659 self.gnu_vernaux_remaining = verneed.aux_count; 1660 let vn_aux = if verneed.aux_count == 0 { 1661 0 1662 } else { 1663 mem::size_of::<elf::Verneed<Endianness>>() as u32 1664 }; 1665 1666 self.buffer.write(&elf::Verneed { 1667 vn_version: U16::new(self.endian, verneed.version), 1668 vn_cnt: U16::new(self.endian, verneed.aux_count), 1669 vn_file: U32::new(self.endian, self.dynstr.get_offset(verneed.file) as u32), 1670 vn_aux: U32::new(self.endian, vn_aux), 1671 vn_next: U32::new(self.endian, vn_next), 1672 }); 1673 } 1674 1675 /// Write a version need auxiliary entry. write_gnu_vernaux(&mut self, vernaux: &Vernaux)1676 pub fn write_gnu_vernaux(&mut self, vernaux: &Vernaux) { 1677 debug_assert_ne!(self.gnu_vernaux_remaining, 0); 1678 self.gnu_vernaux_remaining -= 1; 1679 let vna_next = if self.gnu_vernaux_remaining == 0 { 1680 0 1681 } else { 1682 mem::size_of::<elf::Vernaux<Endianness>>() as u32 1683 }; 1684 self.buffer.write(&elf::Vernaux { 1685 vna_hash: U32::new(self.endian, elf::hash(self.dynstr.get_string(vernaux.name))), 1686 vna_flags: U16::new(self.endian, vernaux.flags), 1687 vna_other: U16::new(self.endian, vernaux.index), 1688 vna_name: U32::new(self.endian, self.dynstr.get_offset(vernaux.name) as u32), 1689 vna_next: U32::new(self.endian, vna_next), 1690 }); 1691 } 1692 1693 /// Reserve the section index for the `.gnu.version_r` section. reserve_gnu_verneed_section_index(&mut self) -> SectionIndex1694 pub fn reserve_gnu_verneed_section_index(&mut self) -> SectionIndex { 1695 debug_assert!(self.gnu_verneed_str_id.is_none()); 1696 self.gnu_verneed_str_id = Some(self.add_section_name(&b".gnu.version_r"[..])); 1697 self.reserve_section_index() 1698 } 1699 1700 /// Write the section header for the `.gnu.version_r` section. 1701 /// 1702 /// This function does nothing if the section index was not reserved. write_gnu_verneed_section_header(&mut self, sh_addr: u64)1703 pub fn write_gnu_verneed_section_header(&mut self, sh_addr: u64) { 1704 if self.gnu_verneed_str_id.is_none() { 1705 return; 1706 } 1707 self.write_section_header(&SectionHeader { 1708 name: self.gnu_verneed_str_id, 1709 sh_type: elf::SHT_GNU_VERNEED, 1710 sh_flags: elf::SHF_ALLOC.into(), 1711 sh_addr, 1712 sh_offset: self.gnu_verneed_offset as u64, 1713 sh_size: self.gnu_verneed_size as u64, 1714 sh_link: self.dynstr_index.0, 1715 sh_info: self.gnu_verneed_count.into(), 1716 sh_addralign: self.elf_align as u64, 1717 sh_entsize: 0, 1718 }); 1719 } 1720 1721 /// Reserve a file range for the given number of relocations. 1722 /// 1723 /// Returns the offset of the range. reserve_relocations(&mut self, count: usize, is_rela: bool) -> usize1724 pub fn reserve_relocations(&mut self, count: usize, is_rela: bool) -> usize { 1725 self.reserve(count * self.rel_size(is_rela), self.elf_align) 1726 } 1727 1728 /// Write alignment padding bytes prior to a relocation section. write_align_relocation(&mut self)1729 pub fn write_align_relocation(&mut self) { 1730 util::write_align(self.buffer, self.elf_align); 1731 } 1732 1733 /// Write a relocation. write_relocation(&mut self, is_rela: bool, rel: &Rel)1734 pub fn write_relocation(&mut self, is_rela: bool, rel: &Rel) { 1735 let endian = self.endian; 1736 if self.is_64 { 1737 if is_rela { 1738 let rel = elf::Rela64 { 1739 r_offset: U64::new(endian, rel.r_offset), 1740 r_info: elf::Rela64::r_info(endian, self.is_mips64el, rel.r_sym, rel.r_type), 1741 r_addend: I64::new(endian, rel.r_addend), 1742 }; 1743 self.buffer.write(&rel); 1744 } else { 1745 let rel = elf::Rel64 { 1746 r_offset: U64::new(endian, rel.r_offset), 1747 r_info: elf::Rel64::r_info(endian, rel.r_sym, rel.r_type), 1748 }; 1749 self.buffer.write(&rel); 1750 } 1751 } else { 1752 if is_rela { 1753 let rel = elf::Rela32 { 1754 r_offset: U32::new(endian, rel.r_offset as u32), 1755 r_info: elf::Rel32::r_info(endian, rel.r_sym, rel.r_type as u8), 1756 r_addend: I32::new(endian, rel.r_addend as i32), 1757 }; 1758 self.buffer.write(&rel); 1759 } else { 1760 let rel = elf::Rel32 { 1761 r_offset: U32::new(endian, rel.r_offset as u32), 1762 r_info: elf::Rel32::r_info(endian, rel.r_sym, rel.r_type as u8), 1763 }; 1764 self.buffer.write(&rel); 1765 } 1766 } 1767 } 1768 1769 /// Write the section header for a relocation section. 1770 /// 1771 /// `section` is the index of the section the relocations apply to, 1772 /// or 0 if none. 1773 /// 1774 /// `symtab` is the index of the symbol table the relocations refer to, 1775 /// or 0 if none. 1776 /// 1777 /// `offset` is the file offset of the relocations. write_relocation_section_header( &mut self, name: StringId, section: SectionIndex, symtab: SectionIndex, offset: usize, count: usize, is_rela: bool, )1778 pub fn write_relocation_section_header( 1779 &mut self, 1780 name: StringId, 1781 section: SectionIndex, 1782 symtab: SectionIndex, 1783 offset: usize, 1784 count: usize, 1785 is_rela: bool, 1786 ) { 1787 self.write_section_header(&SectionHeader { 1788 name: Some(name), 1789 sh_type: if is_rela { elf::SHT_RELA } else { elf::SHT_REL }, 1790 sh_flags: elf::SHF_INFO_LINK.into(), 1791 sh_addr: 0, 1792 sh_offset: offset as u64, 1793 sh_size: (count * self.rel_size(is_rela)) as u64, 1794 sh_link: symtab.0, 1795 sh_info: section.0, 1796 sh_addralign: self.elf_align as u64, 1797 sh_entsize: self.rel_size(is_rela) as u64, 1798 }); 1799 } 1800 1801 /// Reserve a file range for a COMDAT section. 1802 /// 1803 /// `count` is the number of sections in the COMDAT group. 1804 /// 1805 /// Returns the offset of the range. reserve_comdat(&mut self, count: usize) -> usize1806 pub fn reserve_comdat(&mut self, count: usize) -> usize { 1807 self.reserve((count + 1) * 4, 4) 1808 } 1809 1810 /// Write `GRP_COMDAT` at the start of the COMDAT section. write_comdat_header(&mut self)1811 pub fn write_comdat_header(&mut self) { 1812 util::write_align(self.buffer, 4); 1813 self.buffer.write(&U32::new(self.endian, elf::GRP_COMDAT)); 1814 } 1815 1816 /// Write an entry in a COMDAT section. write_comdat_entry(&mut self, entry: SectionIndex)1817 pub fn write_comdat_entry(&mut self, entry: SectionIndex) { 1818 self.buffer.write(&U32::new(self.endian, entry.0)); 1819 } 1820 1821 /// Write the section header for a COMDAT section. write_comdat_section_header( &mut self, name: StringId, symtab: SectionIndex, symbol: SymbolIndex, offset: usize, count: usize, )1822 pub fn write_comdat_section_header( 1823 &mut self, 1824 name: StringId, 1825 symtab: SectionIndex, 1826 symbol: SymbolIndex, 1827 offset: usize, 1828 count: usize, 1829 ) { 1830 self.write_section_header(&SectionHeader { 1831 name: Some(name), 1832 sh_type: elf::SHT_GROUP, 1833 sh_flags: 0, 1834 sh_addr: 0, 1835 sh_offset: offset as u64, 1836 sh_size: ((count + 1) * 4) as u64, 1837 sh_link: symtab.0, 1838 sh_info: symbol.0, 1839 sh_addralign: 4, 1840 sh_entsize: 4, 1841 }); 1842 } 1843 } 1844 1845 /// Native endian version of [`elf::FileHeader64`]. 1846 #[allow(missing_docs)] 1847 #[derive(Debug, Clone)] 1848 pub struct FileHeader { 1849 pub os_abi: u8, 1850 pub abi_version: u8, 1851 pub e_type: u16, 1852 pub e_machine: u16, 1853 pub e_entry: u64, 1854 pub e_flags: u32, 1855 } 1856 1857 /// Native endian version of [`elf::ProgramHeader64`]. 1858 #[allow(missing_docs)] 1859 #[derive(Debug, Clone)] 1860 pub struct ProgramHeader { 1861 pub p_type: u32, 1862 pub p_flags: u32, 1863 pub p_offset: u64, 1864 pub p_vaddr: u64, 1865 pub p_paddr: u64, 1866 pub p_filesz: u64, 1867 pub p_memsz: u64, 1868 pub p_align: u64, 1869 } 1870 1871 /// Native endian version of [`elf::SectionHeader64`]. 1872 #[allow(missing_docs)] 1873 #[derive(Debug, Clone)] 1874 pub struct SectionHeader { 1875 pub name: Option<StringId>, 1876 pub sh_type: u32, 1877 pub sh_flags: u64, 1878 pub sh_addr: u64, 1879 pub sh_offset: u64, 1880 pub sh_size: u64, 1881 pub sh_link: u32, 1882 pub sh_info: u32, 1883 pub sh_addralign: u64, 1884 pub sh_entsize: u64, 1885 } 1886 1887 /// Native endian version of [`elf::Sym64`]. 1888 #[allow(missing_docs)] 1889 #[derive(Debug, Clone)] 1890 pub struct Sym { 1891 pub name: Option<StringId>, 1892 pub section: Option<SectionIndex>, 1893 pub st_info: u8, 1894 pub st_other: u8, 1895 pub st_shndx: u16, 1896 pub st_value: u64, 1897 pub st_size: u64, 1898 } 1899 1900 /// Unified native endian version of [`elf::Rel64`] and [`elf::Rela64`]. 1901 #[allow(missing_docs)] 1902 #[derive(Debug, Clone)] 1903 pub struct Rel { 1904 pub r_offset: u64, 1905 pub r_sym: u32, 1906 pub r_type: u32, 1907 pub r_addend: i64, 1908 } 1909 1910 /// Information required for writing [`elf::Verdef`]. 1911 #[allow(missing_docs)] 1912 #[derive(Debug, Clone)] 1913 pub struct Verdef { 1914 pub version: u16, 1915 pub flags: u16, 1916 pub index: u16, 1917 pub aux_count: u16, 1918 /// The name for the first [`elf::Verdaux`] entry. 1919 pub name: StringId, 1920 } 1921 1922 /// Information required for writing [`elf::Verneed`]. 1923 #[allow(missing_docs)] 1924 #[derive(Debug, Clone)] 1925 pub struct Verneed { 1926 pub version: u16, 1927 pub aux_count: u16, 1928 pub file: StringId, 1929 } 1930 1931 /// Information required for writing [`elf::Vernaux`]. 1932 #[allow(missing_docs)] 1933 #[derive(Debug, Clone)] 1934 pub struct Vernaux { 1935 pub flags: u16, 1936 pub index: u16, 1937 pub name: StringId, 1938 } 1939