| author | |
| committer | |
| log | d9147b91a601ad2442aaa43f4dba2d01b25d803d |
| tree | 26f06816d827f4fd82772816dd4a33e2f7a465b6 |
| parent | 492cc2ef8d1d21d96e25541c22ab885a31c62770 |
| parent | 1254509d78d8dd3d6eb7922bbb924084eae826fd |
| signature |
elf: cleanups, cleanups, cleanups12 files changed, 738 insertions(+), 854 deletions(-)
src/link/Dwarf.zig+4-4| ... | @@ -317,7 +317,7 @@ pub const Section = struct { | ... | @@ -317,7 +317,7 @@ pub const Section = struct { |
| 317 | fn resize(sec: *Section, dwarf: *Dwarf, len: u64) UpdateError!void { | 317 | fn resize(sec: *Section, dwarf: *Dwarf, len: u64) UpdateError!void { |
| 318 | if (dwarf.bin_file.cast(.elf)) |elf_file| { | 318 | if (dwarf.bin_file.cast(.elf)) |elf_file| { |
| 319 | try elf_file.growNonAllocSection(sec.index, len, @intCast(sec.alignment.toByteUnits().?), true); | 319 | try elf_file.growNonAllocSection(sec.index, len, @intCast(sec.alignment.toByteUnits().?), true); |
| 320 | const shdr = &elf_file.shdrs.items[sec.index]; | 320 | const shdr = &elf_file.sections.items(.shdr)[sec.index]; |
| 321 | sec.off = shdr.sh_offset; | 321 | sec.off = shdr.sh_offset; |
| 322 | sec.len = shdr.sh_size; | 322 | sec.len = shdr.sh_size; |
| 323 | } else if (dwarf.bin_file.cast(.macho)) |macho_file| { | 323 | } else if (dwarf.bin_file.cast(.macho)) |macho_file| { |
| ... | @@ -340,7 +340,7 @@ pub const Section = struct { | ... | @@ -340,7 +340,7 @@ pub const Section = struct { |
| 340 | sec.off += len; | 340 | sec.off += len; |
| 341 | sec.len -= len; | 341 | sec.len -= len; |
| 342 | if (dwarf.bin_file.cast(.elf)) |elf_file| { | 342 | if (dwarf.bin_file.cast(.elf)) |elf_file| { |
| 343 | const shdr = &elf_file.shdrs.items[sec.index]; | 343 | const shdr = &elf_file.sections.items(.shdr)[sec.index]; |
| 344 | shdr.sh_offset = sec.off; | 344 | shdr.sh_offset = sec.off; |
| 345 | shdr.sh_size = sec.len; | 345 | shdr.sh_size = sec.len; |
| 346 | } else if (dwarf.bin_file.cast(.macho)) |macho_file| { | 346 | } else if (dwarf.bin_file.cast(.macho)) |macho_file| { |
| ... | @@ -771,7 +771,7 @@ const Entry = struct { | ... | @@ -771,7 +771,7 @@ const Entry = struct { |
| 771 | log.err("missing {} from {s}", .{ | 771 | log.err("missing {} from {s}", .{ |
| 772 | @as(Entry.Index, @enumFromInt(entry - unit.entries.items.ptr)), | 772 | @as(Entry.Index, @enumFromInt(entry - unit.entries.items.ptr)), |
| 773 | std.mem.sliceTo(if (dwarf.bin_file.cast(.elf)) |elf_file| | 773 | std.mem.sliceTo(if (dwarf.bin_file.cast(.elf)) |elf_file| |
| 774 | elf_file.shstrtab.items[elf_file.shdrs.items[sec.index].sh_name..] | 774 | elf_file.shstrtab.items[elf_file.sections.items(.shdr)[sec.index].sh_name..] |
| 775 | else if (dwarf.bin_file.cast(.macho)) |macho_file| | 775 | else if (dwarf.bin_file.cast(.macho)) |macho_file| |
| 776 | if (macho_file.d_sym) |*d_sym| | 776 | if (macho_file.d_sym) |*d_sym| |
| 777 | &d_sym.sections.items[sec.index].segname | 777 | &d_sym.sections.items[sec.index].segname |
| ... | @@ -1529,7 +1529,7 @@ pub fn reloadSectionMetadata(dwarf: *Dwarf) void { | ... | @@ -1529,7 +1529,7 @@ pub fn reloadSectionMetadata(dwarf: *Dwarf) void { |
| 1529 | elf_file.debug_rnglists_section_index.?, | 1529 | elf_file.debug_rnglists_section_index.?, |
| 1530 | elf_file.debug_str_section_index.?, | 1530 | elf_file.debug_str_section_index.?, |
| 1531 | }) |sec, section_index| { | 1531 | }) |sec, section_index| { |
| 1532 | const shdr = &elf_file.shdrs.items[section_index]; | 1532 | const shdr = &elf_file.sections.items(.shdr)[section_index]; |
| 1533 | sec.index = section_index; | 1533 | sec.index = section_index; |
| 1534 | sec.off = shdr.sh_offset; | 1534 | sec.off = shdr.sh_offset; |
| 1535 | sec.len = shdr.sh_size; | 1535 | sec.len = shdr.sh_size; |
src/link/Elf.zig+213-623| ... | @@ -45,17 +45,10 @@ linker_defined_index: ?File.Index = null, | ... | @@ -45,17 +45,10 @@ linker_defined_index: ?File.Index = null, |
| 45 | objects: std.ArrayListUnmanaged(File.Index) = .{}, | 45 | objects: std.ArrayListUnmanaged(File.Index) = .{}, |
| 46 | shared_objects: std.ArrayListUnmanaged(File.Index) = .{}, | 46 | shared_objects: std.ArrayListUnmanaged(File.Index) = .{}, |
| 47 | 47 | ||
| 48 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. | 48 | /// List of all output sections and their associated metadata. |
| 49 | /// Same order as in the file. | 49 | sections: std.MultiArrayList(Section) = .{}, |
| 50 | shdrs: std.ArrayListUnmanaged(elf.Elf64_Shdr) = .{}, | ||
| 51 | /// Given index to a section, pulls index of containing phdr if any. | ||
| 52 | phdr_to_shdr_table: std.AutoHashMapUnmanaged(u32, u32) = .{}, | ||
| 53 | /// File offset into the shdr table. | 50 | /// File offset into the shdr table. |
| 54 | shdr_table_offset: ?u64 = null, | 51 | shdr_table_offset: ?u64 = null, |
| 55 | /// Table of lists of atoms per output section. | ||
| 56 | /// This table is not used to track incrementally generated atoms. | ||
| 57 | output_sections: std.AutoArrayHashMapUnmanaged(u32, std.ArrayListUnmanaged(Ref)) = .{}, | ||
| 58 | output_rela_sections: std.AutoArrayHashMapUnmanaged(u32, RelaSection) = .{}, | ||
| 59 | 52 | ||
| 60 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. | 53 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. |
| 61 | /// Same order as in the file. | 54 | /// Same order as in the file. |
| ... | @@ -181,9 +174,6 @@ thunks: std.ArrayListUnmanaged(Thunk) = .{}, | ... | @@ -181,9 +174,6 @@ thunks: std.ArrayListUnmanaged(Thunk) = .{}, |
| 181 | /// List of output merge sections with deduped contents. | 174 | /// List of output merge sections with deduped contents. |
| 182 | merge_sections: std.ArrayListUnmanaged(MergeSection) = .{}, | 175 | merge_sections: std.ArrayListUnmanaged(MergeSection) = .{}, |
| 183 | 176 | ||
| 184 | /// Table of last atom index in a section and matching atom free list if any. | ||
| 185 | last_atom_and_free_list_table: LastAtomAndFreeListTable = .{}, | ||
| 186 | |||
| 187 | first_eflags: ?elf.Elf64_Word = null, | 177 | first_eflags: ?elf.Elf64_Word = null, |
| 188 | 178 | ||
| 189 | /// When allocating, the ideal_capacity is calculated by | 179 | /// When allocating, the ideal_capacity is calculated by |
| ... | @@ -387,8 +377,7 @@ pub fn createEmpty( | ... | @@ -387,8 +377,7 @@ pub fn createEmpty( |
| 387 | )}), | 377 | )}), |
| 388 | } }); | 378 | } }); |
| 389 | self.zig_object_index = index; | 379 | self.zig_object_index = index; |
| 390 | try self.zigObjectPtr().?.init(self); | 380 | try self.zigObjectPtr().?.init(self, .{ |
| 391 | try self.initMetadata(.{ | ||
| 392 | .symbol_count_hint = options.symbol_count_hint, | 381 | .symbol_count_hint = options.symbol_count_hint, |
| 393 | .program_code_size_hint = options.program_code_size_hint, | 382 | .program_code_size_hint = options.program_code_size_hint, |
| 394 | }); | 383 | }); |
| ... | @@ -430,17 +419,12 @@ pub fn deinit(self: *Elf) void { | ... | @@ -430,17 +419,12 @@ pub fn deinit(self: *Elf) void { |
| 430 | self.objects.deinit(gpa); | 419 | self.objects.deinit(gpa); |
| 431 | self.shared_objects.deinit(gpa); | 420 | self.shared_objects.deinit(gpa); |
| 432 | 421 | ||
| 433 | self.shdrs.deinit(gpa); | 422 | for (self.sections.items(.atom_list), self.sections.items(.free_list)) |*atoms, *free_list| { |
| 434 | self.phdr_to_shdr_table.deinit(gpa); | 423 | atoms.deinit(gpa); |
| 435 | self.phdrs.deinit(gpa); | 424 | free_list.deinit(gpa); |
| 436 | for (self.output_sections.values()) |*list| { | ||
| 437 | list.deinit(gpa); | ||
| 438 | } | 425 | } |
| 439 | self.output_sections.deinit(gpa); | 426 | self.sections.deinit(gpa); |
| 440 | for (self.output_rela_sections.values()) |*sec| { | 427 | self.phdrs.deinit(gpa); |
| 441 | sec.atom_list.deinit(gpa); | ||
| 442 | } | ||
| 443 | self.output_rela_sections.deinit(gpa); | ||
| 444 | self.shstrtab.deinit(gpa); | 428 | self.shstrtab.deinit(gpa); |
| 445 | self.symtab.deinit(gpa); | 429 | self.symtab.deinit(gpa); |
| 446 | self.strtab.deinit(gpa); | 430 | self.strtab.deinit(gpa); |
| ... | @@ -454,10 +438,6 @@ pub fn deinit(self: *Elf) void { | ... | @@ -454,10 +438,6 @@ pub fn deinit(self: *Elf) void { |
| 454 | sect.deinit(gpa); | 438 | sect.deinit(gpa); |
| 455 | } | 439 | } |
| 456 | self.merge_sections.deinit(gpa); | 440 | self.merge_sections.deinit(gpa); |
| 457 | for (self.last_atom_and_free_list_table.values()) |*value| { | ||
| 458 | value.free_list.deinit(gpa); | ||
| 459 | } | ||
| 460 | self.last_atom_and_free_list_table.deinit(gpa); | ||
| 461 | 441 | ||
| 462 | self.got.deinit(gpa); | 442 | self.got.deinit(gpa); |
| 463 | self.plt.deinit(gpa); | 443 | self.plt.deinit(gpa); |
| ... | @@ -506,7 +486,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 { | ... | @@ -506,7 +486,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 { |
| 506 | 486 | ||
| 507 | if (self.shdr_table_offset) |off| { | 487 | if (self.shdr_table_offset) |off| { |
| 508 | const shdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Shdr) else @sizeOf(elf.Elf64_Shdr); | 488 | const shdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Shdr) else @sizeOf(elf.Elf64_Shdr); |
| 509 | const tight_size = self.shdrs.items.len * shdr_size; | 489 | const tight_size = self.sections.items(.shdr).len * shdr_size; |
| 510 | const increased_size = padToIdeal(tight_size); | 490 | const increased_size = padToIdeal(tight_size); |
| 511 | const test_end = off +| increased_size; | 491 | const test_end = off +| increased_size; |
| 512 | if (start < test_end) { | 492 | if (start < test_end) { |
| ... | @@ -515,7 +495,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 { | ... | @@ -515,7 +495,7 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 { |
| 515 | } | 495 | } |
| 516 | } | 496 | } |
| 517 | 497 | ||
| 518 | for (self.shdrs.items) |shdr| { | 498 | for (self.sections.items(.shdr)) |shdr| { |
| 519 | if (shdr.sh_type == elf.SHT_NOBITS) continue; | 499 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 520 | const increased_size = padToIdeal(shdr.sh_size); | 500 | const increased_size = padToIdeal(shdr.sh_size); |
| 521 | const test_end = shdr.sh_offset +| increased_size; | 501 | const test_end = shdr.sh_offset +| increased_size; |
| ... | @@ -545,7 +525,7 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 { | ... | @@ -545,7 +525,7 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 { |
| 545 | if (self.shdr_table_offset) |off| { | 525 | if (self.shdr_table_offset) |off| { |
| 546 | if (off > start and off < min_pos) min_pos = off; | 526 | if (off > start and off < min_pos) min_pos = off; |
| 547 | } | 527 | } |
| 548 | for (self.shdrs.items) |section| { | 528 | for (self.sections.items(.shdr)) |section| { |
| 549 | if (section.sh_offset <= start) continue; | 529 | if (section.sh_offset <= start) continue; |
| 550 | if (section.sh_offset < min_pos) min_pos = section.sh_offset; | 530 | if (section.sh_offset < min_pos) min_pos = section.sh_offset; |
| 551 | } | 531 | } |
| ... | @@ -574,318 +554,13 @@ pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 { | ... | @@ -574,318 +554,13 @@ pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 { |
| 574 | return start; | 554 | return start; |
| 575 | } | 555 | } |
| 576 | 556 | ||
| 577 | pub const InitMetadataOptions = struct { | ||
| 578 | symbol_count_hint: u64, | ||
| 579 | program_code_size_hint: u64, | ||
| 580 | }; | ||
| 581 | |||
| 582 | /// TODO move to ZigObject | ||
| 583 | pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void { | ||
| 584 | const gpa = self.base.comp.gpa; | ||
| 585 | const ptr_size = self.ptrWidthBytes(); | ||
| 586 | const target = self.base.comp.root_mod.resolved_target.result; | ||
| 587 | const ptr_bit_width = target.ptrBitWidth(); | ||
| 588 | const zo = self.zigObjectPtr().?; | ||
| 589 | |||
| 590 | const fillSection = struct { | ||
| 591 | fn fillSection(elf_file: *Elf, shdr: *elf.Elf64_Shdr, size: u64, phndx: ?u16) !void { | ||
| 592 | if (elf_file.base.isRelocatable()) { | ||
| 593 | const off = try elf_file.findFreeSpace(size, shdr.sh_addralign); | ||
| 594 | shdr.sh_offset = off; | ||
| 595 | shdr.sh_size = size; | ||
| 596 | } else { | ||
| 597 | const phdr = elf_file.phdrs.items[phndx.?]; | ||
| 598 | shdr.sh_addr = phdr.p_vaddr; | ||
| 599 | shdr.sh_offset = phdr.p_offset; | ||
| 600 | shdr.sh_size = phdr.p_memsz; | ||
| 601 | } | ||
| 602 | } | ||
| 603 | }.fillSection; | ||
| 604 | |||
| 605 | comptime assert(number_of_zig_segments == 5); | ||
| 606 | |||
| 607 | if (!self.base.isRelocatable()) { | ||
| 608 | if (self.phdr_zig_load_re_index == null) { | ||
| 609 | const filesz = options.program_code_size_hint; | ||
| 610 | const off = try self.findFreeSpace(filesz, self.page_size); | ||
| 611 | self.phdr_zig_load_re_index = try self.addPhdr(.{ | ||
| 612 | .type = elf.PT_LOAD, | ||
| 613 | .offset = off, | ||
| 614 | .filesz = filesz, | ||
| 615 | .addr = if (ptr_bit_width >= 32) 0x4000000 else 0x4000, | ||
| 616 | .memsz = filesz, | ||
| 617 | .@"align" = self.page_size, | ||
| 618 | .flags = elf.PF_X | elf.PF_R | elf.PF_W, | ||
| 619 | }); | ||
| 620 | } | ||
| 621 | |||
| 622 | if (self.phdr_zig_load_ro_index == null) { | ||
| 623 | const alignment = self.page_size; | ||
| 624 | const filesz: u64 = 1024; | ||
| 625 | const off = try self.findFreeSpace(filesz, alignment); | ||
| 626 | self.phdr_zig_load_ro_index = try self.addPhdr(.{ | ||
| 627 | .type = elf.PT_LOAD, | ||
| 628 | .offset = off, | ||
| 629 | .filesz = filesz, | ||
| 630 | .addr = if (ptr_bit_width >= 32) 0xc000000 else 0xa000, | ||
| 631 | .memsz = filesz, | ||
| 632 | .@"align" = alignment, | ||
| 633 | .flags = elf.PF_R | elf.PF_W, | ||
| 634 | }); | ||
| 635 | } | ||
| 636 | |||
| 637 | if (self.phdr_zig_load_rw_index == null) { | ||
| 638 | const alignment = self.page_size; | ||
| 639 | const filesz: u64 = 1024; | ||
| 640 | const off = try self.findFreeSpace(filesz, alignment); | ||
| 641 | self.phdr_zig_load_rw_index = try self.addPhdr(.{ | ||
| 642 | .type = elf.PT_LOAD, | ||
| 643 | .offset = off, | ||
| 644 | .filesz = filesz, | ||
| 645 | .addr = if (ptr_bit_width >= 32) 0x10000000 else 0xc000, | ||
| 646 | .memsz = filesz, | ||
| 647 | .@"align" = alignment, | ||
| 648 | .flags = elf.PF_R | elf.PF_W, | ||
| 649 | }); | ||
| 650 | } | ||
| 651 | |||
| 652 | if (self.phdr_zig_load_zerofill_index == null) { | ||
| 653 | const alignment = self.page_size; | ||
| 654 | self.phdr_zig_load_zerofill_index = try self.addPhdr(.{ | ||
| 655 | .type = elf.PT_LOAD, | ||
| 656 | .addr = if (ptr_bit_width >= 32) 0x14000000 else 0xf000, | ||
| 657 | .memsz = 1024, | ||
| 658 | .@"align" = alignment, | ||
| 659 | .flags = elf.PF_R | elf.PF_W, | ||
| 660 | }); | ||
| 661 | } | ||
| 662 | } | ||
| 663 | |||
| 664 | if (self.zig_text_section_index == null) { | ||
| 665 | self.zig_text_section_index = try self.addSection(.{ | ||
| 666 | .name = try self.insertShString(".text.zig"), | ||
| 667 | .type = elf.SHT_PROGBITS, | ||
| 668 | .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, | ||
| 669 | .addralign = 1, | ||
| 670 | .offset = std.math.maxInt(u64), | ||
| 671 | }); | ||
| 672 | const shdr = &self.shdrs.items[self.zig_text_section_index.?]; | ||
| 673 | try fillSection(self, shdr, options.program_code_size_hint, self.phdr_zig_load_re_index); | ||
| 674 | if (self.base.isRelocatable()) { | ||
| 675 | const rela_shndx = try self.addRelaShdr(try self.insertShString(".rela.text.zig"), self.zig_text_section_index.?); | ||
| 676 | try self.output_rela_sections.putNoClobber(gpa, self.zig_text_section_index.?, .{ | ||
| 677 | .shndx = rela_shndx, | ||
| 678 | }); | ||
| 679 | } else { | ||
| 680 | try self.phdr_to_shdr_table.putNoClobber( | ||
| 681 | gpa, | ||
| 682 | self.zig_text_section_index.?, | ||
| 683 | self.phdr_zig_load_re_index.?, | ||
| 684 | ); | ||
| 685 | } | ||
| 686 | try self.output_sections.putNoClobber(gpa, self.zig_text_section_index.?, .{}); | ||
| 687 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_text_section_index.?, .{}); | ||
| 688 | } | ||
| 689 | |||
| 690 | if (self.zig_data_rel_ro_section_index == null) { | ||
| 691 | self.zig_data_rel_ro_section_index = try self.addSection(.{ | ||
| 692 | .name = try self.insertShString(".data.rel.ro.zig"), | ||
| 693 | .type = elf.SHT_PROGBITS, | ||
| 694 | .addralign = 1, | ||
| 695 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | ||
| 696 | .offset = std.math.maxInt(u64), | ||
| 697 | }); | ||
| 698 | const shdr = &self.shdrs.items[self.zig_data_rel_ro_section_index.?]; | ||
| 699 | try fillSection(self, shdr, 1024, self.phdr_zig_load_ro_index); | ||
| 700 | if (self.base.isRelocatable()) { | ||
| 701 | const rela_shndx = try self.addRelaShdr( | ||
| 702 | try self.insertShString(".rela.data.rel.ro.zig"), | ||
| 703 | self.zig_data_rel_ro_section_index.?, | ||
| 704 | ); | ||
| 705 | try self.output_rela_sections.putNoClobber(gpa, self.zig_data_rel_ro_section_index.?, .{ | ||
| 706 | .shndx = rela_shndx, | ||
| 707 | }); | ||
| 708 | } else { | ||
| 709 | try self.phdr_to_shdr_table.putNoClobber( | ||
| 710 | gpa, | ||
| 711 | self.zig_data_rel_ro_section_index.?, | ||
| 712 | self.phdr_zig_load_ro_index.?, | ||
| 713 | ); | ||
| 714 | } | ||
| 715 | try self.output_sections.putNoClobber(gpa, self.zig_data_rel_ro_section_index.?, .{}); | ||
| 716 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_data_rel_ro_section_index.?, .{}); | ||
| 717 | } | ||
| 718 | |||
| 719 | if (self.zig_data_section_index == null) { | ||
| 720 | self.zig_data_section_index = try self.addSection(.{ | ||
| 721 | .name = try self.insertShString(".data.zig"), | ||
| 722 | .type = elf.SHT_PROGBITS, | ||
| 723 | .addralign = ptr_size, | ||
| 724 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | ||
| 725 | .offset = std.math.maxInt(u64), | ||
| 726 | }); | ||
| 727 | const shdr = &self.shdrs.items[self.zig_data_section_index.?]; | ||
| 728 | try fillSection(self, shdr, 1024, self.phdr_zig_load_rw_index); | ||
| 729 | if (self.base.isRelocatable()) { | ||
| 730 | const rela_shndx = try self.addRelaShdr( | ||
| 731 | try self.insertShString(".rela.data.zig"), | ||
| 732 | self.zig_data_section_index.?, | ||
| 733 | ); | ||
| 734 | try self.output_rela_sections.putNoClobber(gpa, self.zig_data_section_index.?, .{ | ||
| 735 | .shndx = rela_shndx, | ||
| 736 | }); | ||
| 737 | } else { | ||
| 738 | try self.phdr_to_shdr_table.putNoClobber( | ||
| 739 | gpa, | ||
| 740 | self.zig_data_section_index.?, | ||
| 741 | self.phdr_zig_load_rw_index.?, | ||
| 742 | ); | ||
| 743 | } | ||
| 744 | try self.output_sections.putNoClobber(gpa, self.zig_data_section_index.?, .{}); | ||
| 745 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_data_section_index.?, .{}); | ||
| 746 | } | ||
| 747 | |||
| 748 | if (self.zig_bss_section_index == null) { | ||
| 749 | self.zig_bss_section_index = try self.addSection(.{ | ||
| 750 | .name = try self.insertShString(".bss.zig"), | ||
| 751 | .type = elf.SHT_NOBITS, | ||
| 752 | .addralign = ptr_size, | ||
| 753 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | ||
| 754 | .offset = 0, | ||
| 755 | }); | ||
| 756 | const shdr = &self.shdrs.items[self.zig_bss_section_index.?]; | ||
| 757 | if (self.phdr_zig_load_zerofill_index) |phndx| { | ||
| 758 | const phdr = self.phdrs.items[phndx]; | ||
| 759 | shdr.sh_addr = phdr.p_vaddr; | ||
| 760 | shdr.sh_size = phdr.p_memsz; | ||
| 761 | try self.phdr_to_shdr_table.putNoClobber(gpa, self.zig_bss_section_index.?, phndx); | ||
| 762 | } else { | ||
| 763 | shdr.sh_size = 1024; | ||
| 764 | } | ||
| 765 | try self.output_sections.putNoClobber(gpa, self.zig_bss_section_index.?, .{}); | ||
| 766 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_bss_section_index.?, .{}); | ||
| 767 | } | ||
| 768 | |||
| 769 | if (zo.dwarf) |*dwarf| { | ||
| 770 | const addSectionSymbol = struct { | ||
| 771 | fn addSectionSymbol( | ||
| 772 | zig_object: *ZigObject, | ||
| 773 | alloc: Allocator, | ||
| 774 | name: [:0]const u8, | ||
| 775 | alignment: Atom.Alignment, | ||
| 776 | shndx: u32, | ||
| 777 | ) !Symbol.Index { | ||
| 778 | const name_off = try zig_object.addString(alloc, name); | ||
| 779 | const index = try zig_object.newSymbolWithAtom(alloc, name_off); | ||
| 780 | const sym = zig_object.symbol(index); | ||
| 781 | const esym = &zig_object.symtab.items(.elf_sym)[sym.esym_index]; | ||
| 782 | esym.st_info |= elf.STT_SECTION; | ||
| 783 | const atom_ptr = zig_object.atom(sym.ref.index).?; | ||
| 784 | atom_ptr.alignment = alignment; | ||
| 785 | atom_ptr.output_section_index = shndx; | ||
| 786 | return index; | ||
| 787 | } | ||
| 788 | }.addSectionSymbol; | ||
| 789 | |||
| 790 | if (self.debug_str_section_index == null) { | ||
| 791 | self.debug_str_section_index = try self.addSection(.{ | ||
| 792 | .name = try self.insertShString(".debug_str"), | ||
| 793 | .flags = elf.SHF_MERGE | elf.SHF_STRINGS, | ||
| 794 | .entsize = 1, | ||
| 795 | .type = elf.SHT_PROGBITS, | ||
| 796 | .addralign = 1, | ||
| 797 | }); | ||
| 798 | zo.debug_str_section_dirty = true; | ||
| 799 | zo.debug_str_index = try addSectionSymbol(zo, gpa, ".debug_str", .@"1", self.debug_str_section_index.?); | ||
| 800 | try self.output_sections.putNoClobber(gpa, self.debug_str_section_index.?, .{}); | ||
| 801 | } | ||
| 802 | |||
| 803 | if (self.debug_info_section_index == null) { | ||
| 804 | self.debug_info_section_index = try self.addSection(.{ | ||
| 805 | .name = try self.insertShString(".debug_info"), | ||
| 806 | .type = elf.SHT_PROGBITS, | ||
| 807 | .addralign = 1, | ||
| 808 | }); | ||
| 809 | zo.debug_info_section_dirty = true; | ||
| 810 | zo.debug_info_index = try addSectionSymbol(zo, gpa, ".debug_info", .@"1", self.debug_info_section_index.?); | ||
| 811 | try self.output_sections.putNoClobber(gpa, self.debug_info_section_index.?, .{}); | ||
| 812 | } | ||
| 813 | |||
| 814 | if (self.debug_abbrev_section_index == null) { | ||
| 815 | self.debug_abbrev_section_index = try self.addSection(.{ | ||
| 816 | .name = try self.insertShString(".debug_abbrev"), | ||
| 817 | .type = elf.SHT_PROGBITS, | ||
| 818 | .addralign = 1, | ||
| 819 | }); | ||
| 820 | zo.debug_abbrev_section_dirty = true; | ||
| 821 | zo.debug_abbrev_index = try addSectionSymbol(zo, gpa, ".debug_abbrev", .@"1", self.debug_abbrev_section_index.?); | ||
| 822 | try self.output_sections.putNoClobber(gpa, self.debug_abbrev_section_index.?, .{}); | ||
| 823 | } | ||
| 824 | |||
| 825 | if (self.debug_aranges_section_index == null) { | ||
| 826 | self.debug_aranges_section_index = try self.addSection(.{ | ||
| 827 | .name = try self.insertShString(".debug_aranges"), | ||
| 828 | .type = elf.SHT_PROGBITS, | ||
| 829 | .addralign = 16, | ||
| 830 | }); | ||
| 831 | zo.debug_aranges_section_dirty = true; | ||
| 832 | zo.debug_aranges_index = try addSectionSymbol(zo, gpa, ".debug_aranges", .@"16", self.debug_aranges_section_index.?); | ||
| 833 | try self.output_sections.putNoClobber(gpa, self.debug_aranges_section_index.?, .{}); | ||
| 834 | } | ||
| 835 | |||
| 836 | if (self.debug_line_section_index == null) { | ||
| 837 | self.debug_line_section_index = try self.addSection(.{ | ||
| 838 | .name = try self.insertShString(".debug_line"), | ||
| 839 | .type = elf.SHT_PROGBITS, | ||
| 840 | .addralign = 1, | ||
| 841 | }); | ||
| 842 | zo.debug_line_section_dirty = true; | ||
| 843 | zo.debug_line_index = try addSectionSymbol(zo, gpa, ".debug_line", .@"1", self.debug_line_section_index.?); | ||
| 844 | try self.output_sections.putNoClobber(gpa, self.debug_line_section_index.?, .{}); | ||
| 845 | } | ||
| 846 | |||
| 847 | if (self.debug_line_str_section_index == null) { | ||
| 848 | self.debug_line_str_section_index = try self.addSection(.{ | ||
| 849 | .name = try self.insertShString(".debug_line_str"), | ||
| 850 | .flags = elf.SHF_MERGE | elf.SHF_STRINGS, | ||
| 851 | .entsize = 1, | ||
| 852 | .type = elf.SHT_PROGBITS, | ||
| 853 | .addralign = 1, | ||
| 854 | }); | ||
| 855 | zo.debug_line_str_section_dirty = true; | ||
| 856 | zo.debug_line_str_index = try addSectionSymbol(zo, gpa, ".debug_line_str", .@"1", self.debug_line_str_section_index.?); | ||
| 857 | try self.output_sections.putNoClobber(gpa, self.debug_line_str_section_index.?, .{}); | ||
| 858 | } | ||
| 859 | |||
| 860 | if (self.debug_loclists_section_index == null) { | ||
| 861 | self.debug_loclists_section_index = try self.addSection(.{ | ||
| 862 | .name = try self.insertShString(".debug_loclists"), | ||
| 863 | .type = elf.SHT_PROGBITS, | ||
| 864 | .addralign = 1, | ||
| 865 | }); | ||
| 866 | zo.debug_loclists_section_dirty = true; | ||
| 867 | zo.debug_loclists_index = try addSectionSymbol(zo, gpa, ".debug_loclists", .@"1", self.debug_loclists_section_index.?); | ||
| 868 | try self.output_sections.putNoClobber(gpa, self.debug_loclists_section_index.?, .{}); | ||
| 869 | } | ||
| 870 | |||
| 871 | if (self.debug_rnglists_section_index == null) { | ||
| 872 | self.debug_rnglists_section_index = try self.addSection(.{ | ||
| 873 | .name = try self.insertShString(".debug_rnglists"), | ||
| 874 | .type = elf.SHT_PROGBITS, | ||
| 875 | .addralign = 1, | ||
| 876 | }); | ||
| 877 | zo.debug_rnglists_section_dirty = true; | ||
| 878 | zo.debug_rnglists_index = try addSectionSymbol(zo, gpa, ".debug_rnglists", .@"1", self.debug_rnglists_section_index.?); | ||
| 879 | try self.output_sections.putNoClobber(gpa, self.debug_rnglists_section_index.?, .{}); | ||
| 880 | } | ||
| 881 | |||
| 882 | try dwarf.initMetadata(); | ||
| 883 | } | ||
| 884 | } | ||
| 885 | |||
| 886 | pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void { | 557 | pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void { |
| 887 | const shdr = &self.shdrs.items[shdr_index]; | 558 | const slice = self.sections.slice(); |
| 888 | const maybe_phdr = if (self.phdr_to_shdr_table.get(shdr_index)) |phndx| &self.phdrs.items[phndx] else null; | 559 | const shdr = &slice.items(.shdr)[shdr_index]; |
| 560 | assert(shdr.sh_flags & elf.SHF_ALLOC != 0); | ||
| 561 | const phndx = slice.items(.phndx)[shdr_index]; | ||
| 562 | const maybe_phdr = if (phndx) |ndx| &self.phdrs.items[ndx] else null; | ||
| 563 | |||
| 889 | log.debug("allocated size {x} of {s}, needed size {x}", .{ | 564 | log.debug("allocated size {x} of {s}, needed size {x}", .{ |
| 890 | self.allocatedSize(shdr.sh_offset), | 565 | self.allocatedSize(shdr.sh_offset), |
| 891 | self.getShString(shdr.sh_name), | 566 | self.getShString(shdr.sh_name), |
| ... | @@ -924,9 +599,7 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void { | ... | @@ -924,9 +599,7 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64) !void { |
| 924 | const mem_capacity = self.allocatedVirtualSize(phdr.p_vaddr); | 599 | const mem_capacity = self.allocatedVirtualSize(phdr.p_vaddr); |
| 925 | if (needed_size > mem_capacity) { | 600 | if (needed_size > mem_capacity) { |
| 926 | var err = try self.base.addErrorWithNotes(2); | 601 | var err = try self.base.addErrorWithNotes(2); |
| 927 | try err.addMsg("fatal linker error: cannot expand load segment phdr({d}) in virtual memory", .{ | 602 | try err.addMsg("fatal linker error: cannot expand load segment phdr({d}) in virtual memory", .{phndx.?}); |
| 928 | self.phdr_to_shdr_table.get(shdr_index).?, | ||
| 929 | }); | ||
| 930 | try err.addNote("TODO: emit relocations to memory locations in self-hosted backends", .{}); | 603 | try err.addNote("TODO: emit relocations to memory locations in self-hosted backends", .{}); |
| 931 | try err.addNote("as a workaround, try increasing pre-allocated virtual memory of each segment", .{}); | 604 | try err.addNote("as a workaround, try increasing pre-allocated virtual memory of each segment", .{}); |
| 932 | } | 605 | } |
| ... | @@ -944,7 +617,8 @@ pub fn growNonAllocSection( | ... | @@ -944,7 +617,8 @@ pub fn growNonAllocSection( |
| 944 | min_alignment: u32, | 617 | min_alignment: u32, |
| 945 | requires_file_copy: bool, | 618 | requires_file_copy: bool, |
| 946 | ) !void { | 619 | ) !void { |
| 947 | const shdr = &self.shdrs.items[shdr_index]; | 620 | const shdr = &self.sections.items(.shdr)[shdr_index]; |
| 621 | assert(shdr.sh_flags & elf.SHF_ALLOC == 0); | ||
| 948 | 622 | ||
| 949 | const allocated_size = self.allocatedSize(shdr.sh_offset); | 623 | const allocated_size = self.allocatedSize(shdr.sh_offset); |
| 950 | if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) { | 624 | if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) { |
| ... | @@ -1328,7 +1002,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod | ... | @@ -1328,7 +1002,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 1328 | const atom_ptr = zo.atom(atom_index) orelse continue; | 1002 | const atom_ptr = zo.atom(atom_index) orelse continue; |
| 1329 | if (!atom_ptr.alive) continue; | 1003 | if (!atom_ptr.alive) continue; |
| 1330 | const out_shndx = atom_ptr.output_section_index; | 1004 | const out_shndx = atom_ptr.output_section_index; |
| 1331 | const shdr = &self.shdrs.items[out_shndx]; | 1005 | const shdr = &self.sections.items(.shdr)[out_shndx]; |
| 1332 | if (shdr.sh_type == elf.SHT_NOBITS) continue; | 1006 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 1333 | const code = try zo.codeAlloc(self, atom_index); | 1007 | const code = try zo.codeAlloc(self, atom_index); |
| 1334 | defer gpa.free(code); | 1008 | defer gpa.free(code); |
| ... | @@ -2692,7 +2366,7 @@ pub fn writeShdrTable(self: *Elf) !void { | ... | @@ -2692,7 +2366,7 @@ pub fn writeShdrTable(self: *Elf) !void { |
| 2692 | }; | 2366 | }; |
| 2693 | 2367 | ||
| 2694 | const shoff = self.shdr_table_offset orelse 0; | 2368 | const shoff = self.shdr_table_offset orelse 0; |
| 2695 | const needed_size = self.shdrs.items.len * shsize; | 2369 | const needed_size = self.sections.items(.shdr).len * shsize; |
| 2696 | 2370 | ||
| 2697 | if (needed_size > self.allocatedSize(shoff)) { | 2371 | if (needed_size > self.allocatedSize(shoff)) { |
| 2698 | self.shdr_table_offset = null; | 2372 | self.shdr_table_offset = null; |
| ... | @@ -2706,12 +2380,12 @@ pub fn writeShdrTable(self: *Elf) !void { | ... | @@ -2706,12 +2380,12 @@ pub fn writeShdrTable(self: *Elf) !void { |
| 2706 | 2380 | ||
| 2707 | switch (self.ptr_width) { | 2381 | switch (self.ptr_width) { |
| 2708 | .p32 => { | 2382 | .p32 => { |
| 2709 | const buf = try gpa.alloc(elf.Elf32_Shdr, self.shdrs.items.len); | 2383 | const buf = try gpa.alloc(elf.Elf32_Shdr, self.sections.items(.shdr).len); |
| 2710 | defer gpa.free(buf); | 2384 | defer gpa.free(buf); |
| 2711 | 2385 | ||
| 2712 | for (buf, 0..) |*shdr, i| { | 2386 | for (buf, 0..) |*shdr, i| { |
| 2713 | assert(self.shdrs.items[i].sh_offset != math.maxInt(u64)); | 2387 | assert(self.sections.items(.shdr)[i].sh_offset != math.maxInt(u64)); |
| 2714 | shdr.* = shdrTo32(self.shdrs.items[i]); | 2388 | shdr.* = shdrTo32(self.sections.items(.shdr)[i]); |
| 2715 | if (foreign_endian) { | 2389 | if (foreign_endian) { |
| 2716 | mem.byteSwapAllFields(elf.Elf32_Shdr, shdr); | 2390 | mem.byteSwapAllFields(elf.Elf32_Shdr, shdr); |
| 2717 | } | 2391 | } |
| ... | @@ -2719,12 +2393,12 @@ pub fn writeShdrTable(self: *Elf) !void { | ... | @@ -2719,12 +2393,12 @@ pub fn writeShdrTable(self: *Elf) !void { |
| 2719 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); | 2393 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); |
| 2720 | }, | 2394 | }, |
| 2721 | .p64 => { | 2395 | .p64 => { |
| 2722 | const buf = try gpa.alloc(elf.Elf64_Shdr, self.shdrs.items.len); | 2396 | const buf = try gpa.alloc(elf.Elf64_Shdr, self.sections.items(.shdr).len); |
| 2723 | defer gpa.free(buf); | 2397 | defer gpa.free(buf); |
| 2724 | 2398 | ||
| 2725 | for (buf, 0..) |*shdr, i| { | 2399 | for (buf, 0..) |*shdr, i| { |
| 2726 | assert(self.shdrs.items[i].sh_offset != math.maxInt(u64)); | 2400 | assert(self.sections.items(.shdr)[i].sh_offset != math.maxInt(u64)); |
| 2727 | shdr.* = self.shdrs.items[i]; | 2401 | shdr.* = self.sections.items(.shdr)[i]; |
| 2728 | if (foreign_endian) { | 2402 | if (foreign_endian) { |
| 2729 | mem.byteSwapAllFields(elf.Elf64_Shdr, shdr); | 2403 | mem.byteSwapAllFields(elf.Elf64_Shdr, shdr); |
| 2730 | } | 2404 | } |
| ... | @@ -2892,7 +2566,7 @@ pub fn writeElfHeader(self: *Elf) !void { | ... | @@ -2892,7 +2566,7 @@ pub fn writeElfHeader(self: *Elf) !void { |
| 2892 | mem.writeInt(u16, hdr_buf[index..][0..2], e_shentsize, endian); | 2566 | mem.writeInt(u16, hdr_buf[index..][0..2], e_shentsize, endian); |
| 2893 | index += 2; | 2567 | index += 2; |
| 2894 | 2568 | ||
| 2895 | const e_shnum = @as(u16, @intCast(self.shdrs.items.len)); | 2569 | const e_shnum = @as(u16, @intCast(self.sections.items(.shdr).len)); |
| 2896 | mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian); | 2570 | mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian); |
| 2897 | index += 2; | 2571 | index += 2; |
| 2898 | 2572 | ||
| ... | @@ -3051,7 +2725,7 @@ pub fn updateMergeSectionSizes(self: *Elf) !void { | ... | @@ -3051,7 +2725,7 @@ pub fn updateMergeSectionSizes(self: *Elf) !void { |
| 3051 | msec.updateSize(); | 2725 | msec.updateSize(); |
| 3052 | } | 2726 | } |
| 3053 | for (self.merge_sections.items) |*msec| { | 2727 | for (self.merge_sections.items) |*msec| { |
| 3054 | const shdr = &self.shdrs.items[msec.output_section_index]; | 2728 | const shdr = &self.sections.items(.shdr)[msec.output_section_index]; |
| 3055 | const offset = msec.alignment.forward(shdr.sh_size); | 2729 | const offset = msec.alignment.forward(shdr.sh_size); |
| 3056 | const padding = offset - shdr.sh_size; | 2730 | const padding = offset - shdr.sh_size; |
| 3057 | msec.value = @intCast(offset); | 2731 | msec.value = @intCast(offset); |
| ... | @@ -3067,7 +2741,7 @@ pub fn writeMergeSections(self: *Elf) !void { | ... | @@ -3067,7 +2741,7 @@ pub fn writeMergeSections(self: *Elf) !void { |
| 3067 | defer buffer.deinit(); | 2741 | defer buffer.deinit(); |
| 3068 | 2742 | ||
| 3069 | for (self.merge_sections.items) |*msec| { | 2743 | for (self.merge_sections.items) |*msec| { |
| 3070 | const shdr = self.shdrs.items[msec.output_section_index]; | 2744 | const shdr = self.sections.items(.shdr)[msec.output_section_index]; |
| 3071 | const fileoff = math.cast(usize, msec.value + shdr.sh_offset) orelse return error.Overflow; | 2745 | const fileoff = math.cast(usize, msec.value + shdr.sh_offset) orelse return error.Overflow; |
| 3072 | const size = math.cast(usize, msec.size) orelse return error.Overflow; | 2746 | const size = math.cast(usize, msec.size) orelse return error.Overflow; |
| 3073 | try buffer.ensureTotalCapacity(size); | 2747 | try buffer.ensureTotalCapacity(size); |
| ... | @@ -3355,7 +3029,7 @@ fn initSpecialPhdrs(self: *Elf) !void { | ... | @@ -3355,7 +3029,7 @@ fn initSpecialPhdrs(self: *Elf) !void { |
| 3355 | .@"align" = 1, | 3029 | .@"align" = 1, |
| 3356 | }); | 3030 | }); |
| 3357 | 3031 | ||
| 3358 | const has_tls = for (self.shdrs.items) |shdr| { | 3032 | const has_tls = for (self.sections.items(.shdr)) |shdr| { |
| 3359 | if (shdr.sh_flags & elf.SHF_TLS != 0) break true; | 3033 | if (shdr.sh_flags & elf.SHF_TLS != 0) break true; |
| 3360 | } else false; | 3034 | } else false; |
| 3361 | if (has_tls) { | 3035 | if (has_tls) { |
| ... | @@ -3384,6 +3058,7 @@ fn initSpecialPhdrs(self: *Elf) !void { | ... | @@ -3384,6 +3058,7 @@ fn initSpecialPhdrs(self: *Elf) !void { |
| 3384 | /// we are about to sort. | 3058 | /// we are about to sort. |
| 3385 | fn sortInitFini(self: *Elf) !void { | 3059 | fn sortInitFini(self: *Elf) !void { |
| 3386 | const gpa = self.base.comp.gpa; | 3060 | const gpa = self.base.comp.gpa; |
| 3061 | const slice = self.sections.slice(); | ||
| 3387 | 3062 | ||
| 3388 | const Entry = struct { | 3063 | const Entry = struct { |
| 3389 | priority: i32, | 3064 | priority: i32, |
| ... | @@ -3397,7 +3072,7 @@ fn sortInitFini(self: *Elf) !void { | ... | @@ -3397,7 +3072,7 @@ fn sortInitFini(self: *Elf) !void { |
| 3397 | } | 3072 | } |
| 3398 | }; | 3073 | }; |
| 3399 | 3074 | ||
| 3400 | for (self.shdrs.items, 0..) |shdr, shndx| { | 3075 | for (slice.items(.shdr), slice.items(.atom_list)) |shdr, *atom_list| { |
| 3401 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; | 3076 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; |
| 3402 | 3077 | ||
| 3403 | var is_init_fini = false; | 3078 | var is_init_fini = false; |
| ... | @@ -3414,8 +3089,6 @@ fn sortInitFini(self: *Elf) !void { | ... | @@ -3414,8 +3089,6 @@ fn sortInitFini(self: *Elf) !void { |
| 3414 | } | 3089 | } |
| 3415 | 3090 | ||
| 3416 | if (!is_init_fini and !is_ctor_dtor) continue; | 3091 | if (!is_init_fini and !is_ctor_dtor) continue; |
| 3417 | |||
| 3418 | const atom_list = self.output_sections.getPtr(@intCast(shndx)).?; | ||
| 3419 | if (atom_list.items.len == 0) continue; | 3092 | if (atom_list.items.len == 0) continue; |
| 3420 | 3093 | ||
| 3421 | var entries = std.ArrayList(Entry).init(gpa); | 3094 | var entries = std.ArrayList(Entry).init(gpa); |
| ... | @@ -3483,7 +3156,7 @@ fn setVersionSymtab(self: *Elf) !void { | ... | @@ -3483,7 +3156,7 @@ fn setVersionSymtab(self: *Elf) !void { |
| 3483 | 3156 | ||
| 3484 | if (self.verneed_section_index) |shndx| { | 3157 | if (self.verneed_section_index) |shndx| { |
| 3485 | try self.verneed.generate(self); | 3158 | try self.verneed.generate(self); |
| 3486 | const shdr = &self.shdrs.items[shndx]; | 3159 | const shdr = &self.sections.items(.shdr)[shndx]; |
| 3487 | shdr.sh_info = @as(u32, @intCast(self.verneed.verneed.items.len)); | 3160 | shdr.sh_info = @as(u32, @intCast(self.verneed.verneed.items.len)); |
| 3488 | } | 3161 | } |
| 3489 | } | 3162 | } |
| ... | @@ -3563,16 +3236,15 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void { | ... | @@ -3563,16 +3236,15 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void { |
| 3563 | } | 3236 | } |
| 3564 | } | 3237 | } |
| 3565 | 3238 | ||
| 3566 | { | 3239 | for (self.sections.items(.phndx)) |*maybe_phndx| { |
| 3567 | var it = self.phdr_to_shdr_table.iterator(); | 3240 | if (maybe_phndx.*) |*index| { |
| 3568 | while (it.next()) |entry| { | 3241 | index.* = backlinks[index.*]; |
| 3569 | entry.value_ptr.* = backlinks[entry.value_ptr.*]; | ||
| 3570 | } | 3242 | } |
| 3571 | } | 3243 | } |
| 3572 | } | 3244 | } |
| 3573 | 3245 | ||
| 3574 | fn shdrRank(self: *Elf, shndx: u32) u8 { | 3246 | fn shdrRank(self: *Elf, shndx: u32) u8 { |
| 3575 | const shdr = self.shdrs.items[shndx]; | 3247 | const shdr = self.sections.items(.shdr)[shndx]; |
| 3576 | const name = self.getShString(shdr.sh_name); | 3248 | const name = self.getShString(shdr.sh_name); |
| 3577 | const flags = shdr.sh_flags; | 3249 | const flags = shdr.sh_flags; |
| 3578 | 3250 | ||
| ... | @@ -3629,9 +3301,9 @@ pub fn sortShdrs(self: *Elf) !void { | ... | @@ -3629,9 +3301,9 @@ pub fn sortShdrs(self: *Elf) !void { |
| 3629 | }; | 3301 | }; |
| 3630 | 3302 | ||
| 3631 | const gpa = self.base.comp.gpa; | 3303 | const gpa = self.base.comp.gpa; |
| 3632 | var entries = try std.ArrayList(Entry).initCapacity(gpa, self.shdrs.items.len); | 3304 | var entries = try std.ArrayList(Entry).initCapacity(gpa, self.sections.items(.shdr).len); |
| 3633 | defer entries.deinit(); | 3305 | defer entries.deinit(); |
| 3634 | for (0..self.shdrs.items.len) |shndx| { | 3306 | for (0..self.sections.items(.shdr).len) |shndx| { |
| 3635 | entries.appendAssumeCapacity(.{ .shndx = @intCast(shndx) }); | 3307 | entries.appendAssumeCapacity(.{ .shndx = @intCast(shndx) }); |
| 3636 | } | 3308 | } |
| 3637 | 3309 | ||
| ... | @@ -3643,20 +3315,18 @@ pub fn sortShdrs(self: *Elf) !void { | ... | @@ -3643,20 +3315,18 @@ pub fn sortShdrs(self: *Elf) !void { |
| 3643 | backlinks[entry.shndx] = @intCast(i); | 3315 | backlinks[entry.shndx] = @intCast(i); |
| 3644 | } | 3316 | } |
| 3645 | 3317 | ||
| 3646 | const slice = try self.shdrs.toOwnedSlice(gpa); | 3318 | var slice = self.sections.toOwnedSlice(); |
| 3647 | defer gpa.free(slice); | 3319 | defer slice.deinit(gpa); |
| 3648 | 3320 | ||
| 3649 | try self.shdrs.ensureTotalCapacityPrecise(gpa, slice.len); | 3321 | try self.sections.ensureTotalCapacity(gpa, slice.len); |
| 3650 | for (entries.items) |sorted| { | 3322 | for (entries.items) |sorted| { |
| 3651 | self.shdrs.appendAssumeCapacity(slice[sorted.shndx]); | 3323 | self.sections.appendAssumeCapacity(slice.get(sorted.shndx)); |
| 3652 | } | 3324 | } |
| 3653 | 3325 | ||
| 3654 | try self.resetShdrIndexes(backlinks); | 3326 | self.resetShdrIndexes(backlinks); |
| 3655 | } | 3327 | } |
| 3656 | 3328 | ||
| 3657 | fn resetShdrIndexes(self: *Elf, backlinks: []const u32) !void { | 3329 | fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { |
| 3658 | const gpa = self.base.comp.gpa; | ||
| 3659 | |||
| 3660 | for (&[_]*?u32{ | 3330 | for (&[_]*?u32{ |
| 3661 | &self.eh_frame_section_index, | 3331 | &self.eh_frame_section_index, |
| 3662 | &self.eh_frame_rela_section_index, | 3332 | &self.eh_frame_rela_section_index, |
| ... | @@ -3697,142 +3367,88 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) !void { | ... | @@ -3697,142 +3367,88 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) !void { |
| 3697 | } | 3367 | } |
| 3698 | } | 3368 | } |
| 3699 | 3369 | ||
| 3370 | for (self.merge_sections.items) |*msec| { | ||
| 3371 | msec.output_section_index = backlinks[msec.output_section_index]; | ||
| 3372 | } | ||
| 3373 | |||
| 3374 | for (self.sections.items(.shdr)) |*shdr| { | ||
| 3375 | if (shdr.sh_type != elf.SHT_RELA) continue; | ||
| 3376 | // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections | ||
| 3377 | // to point at symtab | ||
| 3378 | // shdr.sh_link = backlinks[shdr.sh_link]; | ||
| 3379 | shdr.sh_link = self.symtab_section_index.?; | ||
| 3380 | shdr.sh_info = backlinks[shdr.sh_info]; | ||
| 3381 | } | ||
| 3382 | |||
| 3383 | if (self.zigObjectPtr()) |zo| { | ||
| 3384 | for (zo.atoms_indexes.items) |atom_index| { | ||
| 3385 | const atom_ptr = zo.atom(atom_index) orelse continue; | ||
| 3386 | atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index]; | ||
| 3387 | } | ||
| 3388 | if (zo.dwarf) |*dwarf| dwarf.reloadSectionMetadata(); | ||
| 3389 | } | ||
| 3390 | |||
| 3391 | for (self.comdat_group_sections.items) |*cg| { | ||
| 3392 | cg.shndx = backlinks[cg.shndx]; | ||
| 3393 | } | ||
| 3394 | |||
| 3700 | if (self.symtab_section_index) |index| { | 3395 | if (self.symtab_section_index) |index| { |
| 3701 | const shdr = &self.shdrs.items[index]; | 3396 | const shdr = &self.sections.items(.shdr)[index]; |
| 3702 | shdr.sh_link = self.strtab_section_index.?; | 3397 | shdr.sh_link = self.strtab_section_index.?; |
| 3703 | } | 3398 | } |
| 3704 | 3399 | ||
| 3705 | if (self.dynamic_section_index) |index| { | 3400 | if (self.dynamic_section_index) |index| { |
| 3706 | const shdr = &self.shdrs.items[index]; | 3401 | const shdr = &self.sections.items(.shdr)[index]; |
| 3707 | shdr.sh_link = self.dynstrtab_section_index.?; | 3402 | shdr.sh_link = self.dynstrtab_section_index.?; |
| 3708 | } | 3403 | } |
| 3709 | 3404 | ||
| 3710 | if (self.dynsymtab_section_index) |index| { | 3405 | if (self.dynsymtab_section_index) |index| { |
| 3711 | const shdr = &self.shdrs.items[index]; | 3406 | const shdr = &self.sections.items(.shdr)[index]; |
| 3712 | shdr.sh_link = self.dynstrtab_section_index.?; | 3407 | shdr.sh_link = self.dynstrtab_section_index.?; |
| 3713 | } | 3408 | } |
| 3714 | 3409 | ||
| 3715 | if (self.hash_section_index) |index| { | 3410 | if (self.hash_section_index) |index| { |
| 3716 | const shdr = &self.shdrs.items[index]; | 3411 | const shdr = &self.sections.items(.shdr)[index]; |
| 3717 | shdr.sh_link = self.dynsymtab_section_index.?; | 3412 | shdr.sh_link = self.dynsymtab_section_index.?; |
| 3718 | } | 3413 | } |
| 3719 | 3414 | ||
| 3720 | if (self.gnu_hash_section_index) |index| { | 3415 | if (self.gnu_hash_section_index) |index| { |
| 3721 | const shdr = &self.shdrs.items[index]; | 3416 | const shdr = &self.sections.items(.shdr)[index]; |
| 3722 | shdr.sh_link = self.dynsymtab_section_index.?; | 3417 | shdr.sh_link = self.dynsymtab_section_index.?; |
| 3723 | } | 3418 | } |
| 3724 | 3419 | ||
| 3725 | if (self.versym_section_index) |index| { | 3420 | if (self.versym_section_index) |index| { |
| 3726 | const shdr = &self.shdrs.items[index]; | 3421 | const shdr = &self.sections.items(.shdr)[index]; |
| 3727 | shdr.sh_link = self.dynsymtab_section_index.?; | 3422 | shdr.sh_link = self.dynsymtab_section_index.?; |
| 3728 | } | 3423 | } |
| 3729 | 3424 | ||
| 3730 | if (self.verneed_section_index) |index| { | 3425 | if (self.verneed_section_index) |index| { |
| 3731 | const shdr = &self.shdrs.items[index]; | 3426 | const shdr = &self.sections.items(.shdr)[index]; |
| 3732 | shdr.sh_link = self.dynstrtab_section_index.?; | 3427 | shdr.sh_link = self.dynstrtab_section_index.?; |
| 3733 | } | 3428 | } |
| 3734 | 3429 | ||
| 3735 | if (self.rela_dyn_section_index) |index| { | 3430 | if (self.rela_dyn_section_index) |index| { |
| 3736 | const shdr = &self.shdrs.items[index]; | 3431 | const shdr = &self.sections.items(.shdr)[index]; |
| 3737 | shdr.sh_link = self.dynsymtab_section_index orelse 0; | 3432 | shdr.sh_link = self.dynsymtab_section_index orelse 0; |
| 3738 | } | 3433 | } |
| 3739 | 3434 | ||
| 3740 | if (self.rela_plt_section_index) |index| { | 3435 | if (self.rela_plt_section_index) |index| { |
| 3741 | const shdr = &self.shdrs.items[index]; | 3436 | const shdr = &self.sections.items(.shdr)[index]; |
| 3742 | shdr.sh_link = self.dynsymtab_section_index.?; | 3437 | shdr.sh_link = self.dynsymtab_section_index.?; |
| 3743 | shdr.sh_info = self.plt_section_index.?; | 3438 | shdr.sh_info = self.plt_section_index.?; |
| 3744 | } | 3439 | } |
| 3745 | 3440 | ||
| 3746 | if (self.eh_frame_rela_section_index) |index| { | 3441 | if (self.eh_frame_rela_section_index) |index| { |
| 3747 | const shdr = &self.shdrs.items[index]; | 3442 | const shdr = &self.sections.items(.shdr)[index]; |
| 3748 | shdr.sh_link = self.symtab_section_index.?; | 3443 | shdr.sh_link = self.symtab_section_index.?; |
| 3749 | shdr.sh_info = self.eh_frame_section_index.?; | 3444 | shdr.sh_info = self.eh_frame_section_index.?; |
| 3750 | } | 3445 | } |
| 3751 | |||
| 3752 | { | ||
| 3753 | var output_sections = try self.output_sections.clone(gpa); | ||
| 3754 | defer output_sections.deinit(gpa); | ||
| 3755 | |||
| 3756 | self.output_sections.clearRetainingCapacity(); | ||
| 3757 | |||
| 3758 | var it = output_sections.iterator(); | ||
| 3759 | while (it.next()) |entry| { | ||
| 3760 | const shndx = entry.key_ptr.*; | ||
| 3761 | const meta = entry.value_ptr.*; | ||
| 3762 | self.output_sections.putAssumeCapacityNoClobber(backlinks[shndx], meta); | ||
| 3763 | } | ||
| 3764 | } | ||
| 3765 | |||
| 3766 | for (self.merge_sections.items) |*msec| { | ||
| 3767 | msec.output_section_index = backlinks[msec.output_section_index]; | ||
| 3768 | } | ||
| 3769 | |||
| 3770 | { | ||
| 3771 | var output_rela_sections = try self.output_rela_sections.clone(gpa); | ||
| 3772 | defer output_rela_sections.deinit(gpa); | ||
| 3773 | |||
| 3774 | self.output_rela_sections.clearRetainingCapacity(); | ||
| 3775 | |||
| 3776 | var it = output_rela_sections.iterator(); | ||
| 3777 | while (it.next()) |entry| { | ||
| 3778 | const shndx = entry.key_ptr.*; | ||
| 3779 | var meta = entry.value_ptr.*; | ||
| 3780 | meta.shndx = backlinks[meta.shndx]; | ||
| 3781 | self.output_rela_sections.putAssumeCapacityNoClobber(backlinks[shndx], meta); | ||
| 3782 | } | ||
| 3783 | } | ||
| 3784 | |||
| 3785 | { | ||
| 3786 | var last_atom_and_free_list_table = try self.last_atom_and_free_list_table.clone(gpa); | ||
| 3787 | defer last_atom_and_free_list_table.deinit(gpa); | ||
| 3788 | |||
| 3789 | self.last_atom_and_free_list_table.clearRetainingCapacity(); | ||
| 3790 | |||
| 3791 | var it = last_atom_and_free_list_table.iterator(); | ||
| 3792 | while (it.next()) |entry| { | ||
| 3793 | const shndx = entry.key_ptr.*; | ||
| 3794 | const meta = entry.value_ptr.*; | ||
| 3795 | self.last_atom_and_free_list_table.putAssumeCapacityNoClobber(backlinks[shndx], meta); | ||
| 3796 | } | ||
| 3797 | } | ||
| 3798 | |||
| 3799 | { | ||
| 3800 | var phdr_to_shdr_table = try self.phdr_to_shdr_table.clone(gpa); | ||
| 3801 | defer phdr_to_shdr_table.deinit(gpa); | ||
| 3802 | |||
| 3803 | self.phdr_to_shdr_table.clearRetainingCapacity(); | ||
| 3804 | |||
| 3805 | var it = phdr_to_shdr_table.iterator(); | ||
| 3806 | while (it.next()) |entry| { | ||
| 3807 | const shndx = entry.key_ptr.*; | ||
| 3808 | const phndx = entry.value_ptr.*; | ||
| 3809 | self.phdr_to_shdr_table.putAssumeCapacityNoClobber(backlinks[shndx], phndx); | ||
| 3810 | } | ||
| 3811 | } | ||
| 3812 | |||
| 3813 | if (self.zigObjectPtr()) |zo| { | ||
| 3814 | for (zo.atoms_indexes.items) |atom_index| { | ||
| 3815 | const atom_ptr = zo.atom(atom_index) orelse continue; | ||
| 3816 | atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index]; | ||
| 3817 | } | ||
| 3818 | if (zo.dwarf) |*dwarf| dwarf.reloadSectionMetadata(); | ||
| 3819 | } | ||
| 3820 | |||
| 3821 | for (self.output_rela_sections.keys(), self.output_rela_sections.values()) |shndx, sec| { | ||
| 3822 | const shdr = &self.shdrs.items[sec.shndx]; | ||
| 3823 | shdr.sh_link = self.symtab_section_index.?; | ||
| 3824 | shdr.sh_info = shndx; | ||
| 3825 | } | ||
| 3826 | |||
| 3827 | for (self.comdat_group_sections.items) |*cg| { | ||
| 3828 | cg.shndx = backlinks[cg.shndx]; | ||
| 3829 | } | ||
| 3830 | } | 3446 | } |
| 3831 | 3447 | ||
| 3832 | fn updateSectionSizes(self: *Elf) !void { | 3448 | fn updateSectionSizes(self: *Elf) !void { |
| 3833 | const target = self.base.comp.root_mod.resolved_target.result; | 3449 | const target = self.base.comp.root_mod.resolved_target.result; |
| 3834 | for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| { | 3450 | const slice = self.sections.slice(); |
| 3835 | const shdr = &self.shdrs.items[shndx]; | 3451 | for (slice.items(.shdr), slice.items(.atom_list)) |*shdr, atom_list| { |
| 3836 | if (atom_list.items.len == 0) continue; | 3452 | if (atom_list.items.len == 0) continue; |
| 3837 | if (self.requiresThunks() and shdr.sh_flags & elf.SHF_EXECINSTR != 0) continue; | 3453 | if (self.requiresThunks() and shdr.sh_flags & elf.SHF_EXECINSTR != 0) continue; |
| 3838 | for (atom_list.items) |ref| { | 3454 | for (atom_list.items) |ref| { |
| ... | @@ -3847,38 +3463,38 @@ fn updateSectionSizes(self: *Elf) !void { | ... | @@ -3847,38 +3463,38 @@ fn updateSectionSizes(self: *Elf) !void { |
| 3847 | } | 3463 | } |
| 3848 | 3464 | ||
| 3849 | if (self.requiresThunks()) { | 3465 | if (self.requiresThunks()) { |
| 3850 | for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| { | 3466 | for (slice.items(.shdr), slice.items(.atom_list), 0..) |*shdr, atom_list, shndx| { |
| 3851 | const shdr = self.shdrs.items[shndx]; | ||
| 3852 | if (shdr.sh_flags & elf.SHF_EXECINSTR == 0) continue; | 3467 | if (shdr.sh_flags & elf.SHF_EXECINSTR == 0) continue; |
| 3853 | if (atom_list.items.len == 0) continue; | 3468 | if (atom_list.items.len == 0) continue; |
| 3854 | 3469 | ||
| 3855 | // Create jump/branch range extenders if needed. | 3470 | // Create jump/branch range extenders if needed. |
| 3856 | try thunks.createThunks(shndx, self); | 3471 | try thunks.createThunks(shdr, @intCast(shndx), self); |
| 3857 | } | 3472 | } |
| 3858 | } | 3473 | } |
| 3859 | 3474 | ||
| 3475 | const shdrs = slice.items(.shdr); | ||
| 3860 | if (self.eh_frame_section_index) |index| { | 3476 | if (self.eh_frame_section_index) |index| { |
| 3861 | self.shdrs.items[index].sh_size = try eh_frame.calcEhFrameSize(self); | 3477 | shdrs[index].sh_size = try eh_frame.calcEhFrameSize(self); |
| 3862 | } | 3478 | } |
| 3863 | 3479 | ||
| 3864 | if (self.eh_frame_hdr_section_index) |index| { | 3480 | if (self.eh_frame_hdr_section_index) |index| { |
| 3865 | self.shdrs.items[index].sh_size = eh_frame.calcEhFrameHdrSize(self); | 3481 | shdrs[index].sh_size = eh_frame.calcEhFrameHdrSize(self); |
| 3866 | } | 3482 | } |
| 3867 | 3483 | ||
| 3868 | if (self.got_section_index) |index| { | 3484 | if (self.got_section_index) |index| { |
| 3869 | self.shdrs.items[index].sh_size = self.got.size(self); | 3485 | shdrs[index].sh_size = self.got.size(self); |
| 3870 | } | 3486 | } |
| 3871 | 3487 | ||
| 3872 | if (self.plt_section_index) |index| { | 3488 | if (self.plt_section_index) |index| { |
| 3873 | self.shdrs.items[index].sh_size = self.plt.size(self); | 3489 | shdrs[index].sh_size = self.plt.size(self); |
| 3874 | } | 3490 | } |
| 3875 | 3491 | ||
| 3876 | if (self.got_plt_section_index) |index| { | 3492 | if (self.got_plt_section_index) |index| { |
| 3877 | self.shdrs.items[index].sh_size = self.got_plt.size(self); | 3493 | shdrs[index].sh_size = self.got_plt.size(self); |
| 3878 | } | 3494 | } |
| 3879 | 3495 | ||
| 3880 | if (self.plt_got_section_index) |index| { | 3496 | if (self.plt_got_section_index) |index| { |
| 3881 | self.shdrs.items[index].sh_size = self.plt_got.size(self); | 3497 | shdrs[index].sh_size = self.plt_got.size(self); |
| 3882 | } | 3498 | } |
| 3883 | 3499 | ||
| 3884 | if (self.rela_dyn_section_index) |shndx| { | 3500 | if (self.rela_dyn_section_index) |shndx| { |
| ... | @@ -3889,11 +3505,11 @@ fn updateSectionSizes(self: *Elf) !void { | ... | @@ -3889,11 +3505,11 @@ fn updateSectionSizes(self: *Elf) !void { |
| 3889 | for (self.objects.items) |index| { | 3505 | for (self.objects.items) |index| { |
| 3890 | num += self.file(index).?.object.num_dynrelocs; | 3506 | num += self.file(index).?.object.num_dynrelocs; |
| 3891 | } | 3507 | } |
| 3892 | self.shdrs.items[shndx].sh_size = num * @sizeOf(elf.Elf64_Rela); | 3508 | shdrs[shndx].sh_size = num * @sizeOf(elf.Elf64_Rela); |
| 3893 | } | 3509 | } |
| 3894 | 3510 | ||
| 3895 | if (self.rela_plt_section_index) |index| { | 3511 | if (self.rela_plt_section_index) |index| { |
| 3896 | self.shdrs.items[index].sh_size = self.plt.numRela() * @sizeOf(elf.Elf64_Rela); | 3512 | shdrs[index].sh_size = self.plt.numRela() * @sizeOf(elf.Elf64_Rela); |
| 3897 | } | 3513 | } |
| 3898 | 3514 | ||
| 3899 | if (self.copy_rel_section_index) |index| { | 3515 | if (self.copy_rel_section_index) |index| { |
| ... | @@ -3901,44 +3517,45 @@ fn updateSectionSizes(self: *Elf) !void { | ... | @@ -3901,44 +3517,45 @@ fn updateSectionSizes(self: *Elf) !void { |
| 3901 | } | 3517 | } |
| 3902 | 3518 | ||
| 3903 | if (self.interp_section_index) |index| { | 3519 | if (self.interp_section_index) |index| { |
| 3904 | self.shdrs.items[index].sh_size = target.dynamic_linker.get().?.len + 1; | 3520 | shdrs[index].sh_size = target.dynamic_linker.get().?.len + 1; |
| 3905 | } | 3521 | } |
| 3906 | 3522 | ||
| 3907 | if (self.hash_section_index) |index| { | 3523 | if (self.hash_section_index) |index| { |
| 3908 | self.shdrs.items[index].sh_size = self.hash.size(); | 3524 | shdrs[index].sh_size = self.hash.size(); |
| 3909 | } | 3525 | } |
| 3910 | 3526 | ||
| 3911 | if (self.gnu_hash_section_index) |index| { | 3527 | if (self.gnu_hash_section_index) |index| { |
| 3912 | self.shdrs.items[index].sh_size = self.gnu_hash.size(); | 3528 | shdrs[index].sh_size = self.gnu_hash.size(); |
| 3913 | } | 3529 | } |
| 3914 | 3530 | ||
| 3915 | if (self.dynamic_section_index) |index| { | 3531 | if (self.dynamic_section_index) |index| { |
| 3916 | self.shdrs.items[index].sh_size = self.dynamic.size(self); | 3532 | shdrs[index].sh_size = self.dynamic.size(self); |
| 3917 | } | 3533 | } |
| 3918 | 3534 | ||
| 3919 | if (self.dynsymtab_section_index) |index| { | 3535 | if (self.dynsymtab_section_index) |index| { |
| 3920 | self.shdrs.items[index].sh_size = self.dynsym.size(); | 3536 | shdrs[index].sh_size = self.dynsym.size(); |
| 3921 | } | 3537 | } |
| 3922 | 3538 | ||
| 3923 | if (self.dynstrtab_section_index) |index| { | 3539 | if (self.dynstrtab_section_index) |index| { |
| 3924 | self.shdrs.items[index].sh_size = self.dynstrtab.items.len; | 3540 | shdrs[index].sh_size = self.dynstrtab.items.len; |
| 3925 | } | 3541 | } |
| 3926 | 3542 | ||
| 3927 | if (self.versym_section_index) |index| { | 3543 | if (self.versym_section_index) |index| { |
| 3928 | self.shdrs.items[index].sh_size = self.versym.items.len * @sizeOf(elf.Elf64_Versym); | 3544 | shdrs[index].sh_size = self.versym.items.len * @sizeOf(elf.Elf64_Versym); |
| 3929 | } | 3545 | } |
| 3930 | 3546 | ||
| 3931 | if (self.verneed_section_index) |index| { | 3547 | if (self.verneed_section_index) |index| { |
| 3932 | self.shdrs.items[index].sh_size = self.verneed.size(); | 3548 | shdrs[index].sh_size = self.verneed.size(); |
| 3933 | } | 3549 | } |
| 3934 | 3550 | ||
| 3935 | try self.updateSymtabSize(); | 3551 | try self.updateSymtabSize(); |
| 3936 | self.updateShStrtabSize(); | 3552 | self.updateShStrtabSize(); |
| 3937 | } | 3553 | } |
| 3938 | 3554 | ||
| 3555 | // FIXME:JK this is very much obsolete, remove! | ||
| 3939 | pub fn updateShStrtabSize(self: *Elf) void { | 3556 | pub fn updateShStrtabSize(self: *Elf) void { |
| 3940 | if (self.shstrtab_section_index) |index| { | 3557 | if (self.shstrtab_section_index) |index| { |
| 3941 | self.shdrs.items[index].sh_size = self.shstrtab.items.len; | 3558 | self.sections.items(.shdr)[index].sh_size = self.shstrtab.items.len; |
| 3942 | } | 3559 | } |
| 3943 | } | 3560 | } |
| 3944 | 3561 | ||
| ... | @@ -3971,7 +3588,7 @@ fn getMaxNumberOfPhdrs() u64 { | ... | @@ -3971,7 +3588,7 @@ fn getMaxNumberOfPhdrs() u64 { |
| 3971 | /// We permit a maximum of 3**2 number of segments. | 3588 | /// We permit a maximum of 3**2 number of segments. |
| 3972 | fn calcNumberOfSegments(self: *Elf) usize { | 3589 | fn calcNumberOfSegments(self: *Elf) usize { |
| 3973 | var covers: [9]bool = [_]bool{false} ** 9; | 3590 | var covers: [9]bool = [_]bool{false} ** 9; |
| 3974 | for (self.shdrs.items, 0..) |shdr, shndx| { | 3591 | for (self.sections.items(.shdr), 0..) |shdr, shndx| { |
| 3975 | if (shdr.sh_type == elf.SHT_NULL) continue; | 3592 | if (shdr.sh_type == elf.SHT_NULL) continue; |
| 3976 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; | 3593 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; |
| 3977 | if (self.isZigSection(@intCast(shndx))) continue; | 3594 | if (self.isZigSection(@intCast(shndx))) continue; |
| ... | @@ -4042,8 +3659,9 @@ pub fn allocateAllocSections(self: *Elf) !void { | ... | @@ -4042,8 +3659,9 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 4042 | } | 3659 | } |
| 4043 | }; | 3660 | }; |
| 4044 | 3661 | ||
| 3662 | const slice = self.sections.slice(); | ||
| 4045 | var alignment = Align{}; | 3663 | var alignment = Align{}; |
| 4046 | for (self.shdrs.items, 0..) |shdr, i| { | 3664 | for (slice.items(.shdr), 0..) |shdr, i| { |
| 4047 | if (shdr.sh_type == elf.SHT_NULL) continue; | 3665 | if (shdr.sh_type == elf.SHT_NULL) continue; |
| 4048 | if (shdr.sh_flags & elf.SHF_TLS == 0) continue; | 3666 | if (shdr.sh_flags & elf.SHF_TLS == 0) continue; |
| 4049 | if (alignment.first_tls_index == null) alignment.first_tls_index = i; | 3667 | if (alignment.first_tls_index == null) alignment.first_tls_index = i; |
| ... | @@ -4068,7 +3686,7 @@ pub fn allocateAllocSections(self: *Elf) !void { | ... | @@ -4068,7 +3686,7 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 4068 | cover.deinit(); | 3686 | cover.deinit(); |
| 4069 | }; | 3687 | }; |
| 4070 | 3688 | ||
| 4071 | for (self.shdrs.items, 0..) |shdr, shndx| { | 3689 | for (slice.items(.shdr), 0..) |shdr, shndx| { |
| 4072 | if (shdr.sh_type == elf.SHT_NULL) continue; | 3690 | if (shdr.sh_type == elf.SHT_NULL) continue; |
| 4073 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; | 3691 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; |
| 4074 | if (self.isZigSection(@intCast(shndx))) continue; | 3692 | if (self.isZigSection(@intCast(shndx))) continue; |
| ... | @@ -4089,7 +3707,7 @@ pub fn allocateAllocSections(self: *Elf) !void { | ... | @@ -4089,7 +3707,7 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 4089 | 3707 | ||
| 4090 | var @"align": u64 = self.page_size; | 3708 | var @"align": u64 = self.page_size; |
| 4091 | for (cover.items) |shndx| { | 3709 | for (cover.items) |shndx| { |
| 4092 | const shdr = self.shdrs.items[shndx]; | 3710 | const shdr = slice.items(.shdr)[shndx]; |
| 4093 | if (shdr.sh_type == elf.SHT_NOBITS and shdr.sh_flags & elf.SHF_TLS != 0) continue; | 3711 | if (shdr.sh_type == elf.SHT_NOBITS and shdr.sh_flags & elf.SHF_TLS != 0) continue; |
| 4094 | @"align" = @max(@"align", shdr.sh_addralign); | 3712 | @"align" = @max(@"align", shdr.sh_addralign); |
| 4095 | } | 3713 | } |
| ... | @@ -4101,7 +3719,7 @@ pub fn allocateAllocSections(self: *Elf) !void { | ... | @@ -4101,7 +3719,7 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 4101 | var i: usize = 0; | 3719 | var i: usize = 0; |
| 4102 | while (i < cover.items.len) : (i += 1) { | 3720 | while (i < cover.items.len) : (i += 1) { |
| 4103 | const shndx = cover.items[i]; | 3721 | const shndx = cover.items[i]; |
| 4104 | const shdr = &self.shdrs.items[shndx]; | 3722 | const shdr = &slice.items(.shdr)[shndx]; |
| 4105 | if (shdr.sh_type == elf.SHT_NOBITS and shdr.sh_flags & elf.SHF_TLS != 0) { | 3723 | if (shdr.sh_type == elf.SHT_NOBITS and shdr.sh_flags & elf.SHF_TLS != 0) { |
| 4106 | // .tbss is a little special as it's used only by the loader meaning it doesn't | 3724 | // .tbss is a little special as it's used only by the loader meaning it doesn't |
| 4107 | // need to be actually mmap'ed at runtime. We still need to correctly increment | 3725 | // need to be actually mmap'ed at runtime. We still need to correctly increment |
| ... | @@ -4117,11 +3735,11 @@ pub fn allocateAllocSections(self: *Elf) !void { | ... | @@ -4117,11 +3735,11 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 4117 | // ... | 3735 | // ... |
| 4118 | var tbss_addr = addr; | 3736 | var tbss_addr = addr; |
| 4119 | while (i < cover.items.len and | 3737 | while (i < cover.items.len and |
| 4120 | self.shdrs.items[cover.items[i]].sh_type == elf.SHT_NOBITS and | 3738 | slice.items(.shdr)[cover.items[i]].sh_type == elf.SHT_NOBITS and |
| 4121 | self.shdrs.items[cover.items[i]].sh_flags & elf.SHF_TLS != 0) : (i += 1) | 3739 | slice.items(.shdr)[cover.items[i]].sh_flags & elf.SHF_TLS != 0) : (i += 1) |
| 4122 | { | 3740 | { |
| 4123 | const tbss_shndx = cover.items[i]; | 3741 | const tbss_shndx = cover.items[i]; |
| 4124 | const tbss_shdr = &self.shdrs.items[tbss_shndx]; | 3742 | const tbss_shdr = &slice.items(.shdr)[tbss_shndx]; |
| 4125 | tbss_addr = alignment.@"align"(tbss_shndx, tbss_shdr.sh_addralign, tbss_addr); | 3743 | tbss_addr = alignment.@"align"(tbss_shndx, tbss_shdr.sh_addralign, tbss_addr); |
| 4126 | tbss_shdr.sh_addr = tbss_addr; | 3744 | tbss_shdr.sh_addr = tbss_addr; |
| 4127 | tbss_addr += tbss_shdr.sh_size; | 3745 | tbss_addr += tbss_shdr.sh_size; |
| ... | @@ -4140,7 +3758,7 @@ pub fn allocateAllocSections(self: *Elf) !void { | ... | @@ -4140,7 +3758,7 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 4140 | addr += shdr.sh_size; | 3758 | addr += shdr.sh_size; |
| 4141 | } | 3759 | } |
| 4142 | 3760 | ||
| 4143 | const first = self.shdrs.items[cover.items[0]]; | 3761 | const first = slice.items(.shdr)[cover.items[0]]; |
| 4144 | var off = try self.findFreeSpace(filesz, @"align"); | 3762 | var off = try self.findFreeSpace(filesz, @"align"); |
| 4145 | const phndx = try self.addPhdr(.{ | 3763 | const phndx = try self.addPhdr(.{ |
| 4146 | .type = elf.PT_LOAD, | 3764 | .type = elf.PT_LOAD, |
| ... | @@ -4153,7 +3771,8 @@ pub fn allocateAllocSections(self: *Elf) !void { | ... | @@ -4153,7 +3771,8 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 4153 | }); | 3771 | }); |
| 4154 | 3772 | ||
| 4155 | for (cover.items) |shndx| { | 3773 | for (cover.items) |shndx| { |
| 4156 | const shdr = &self.shdrs.items[shndx]; | 3774 | const shdr = &slice.items(.shdr)[shndx]; |
| 3775 | slice.items(.phndx)[shndx] = phndx; | ||
| 4157 | if (shdr.sh_type == elf.SHT_NOBITS) { | 3776 | if (shdr.sh_type == elf.SHT_NOBITS) { |
| 4158 | shdr.sh_offset = 0; | 3777 | shdr.sh_offset = 0; |
| 4159 | continue; | 3778 | continue; |
| ... | @@ -4161,7 +3780,6 @@ pub fn allocateAllocSections(self: *Elf) !void { | ... | @@ -4161,7 +3780,6 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 4161 | off = alignment.@"align"(shndx, shdr.sh_addralign, off); | 3780 | off = alignment.@"align"(shndx, shdr.sh_addralign, off); |
| 4162 | shdr.sh_offset = off; | 3781 | shdr.sh_offset = off; |
| 4163 | off += shdr.sh_size; | 3782 | off += shdr.sh_size; |
| 4164 | try self.phdr_to_shdr_table.putNoClobber(gpa, shndx, phndx); | ||
| 4165 | } | 3783 | } |
| 4166 | 3784 | ||
| 4167 | addr = mem.alignForward(u64, addr, self.page_size); | 3785 | addr = mem.alignForward(u64, addr, self.page_size); |
| ... | @@ -4170,7 +3788,7 @@ pub fn allocateAllocSections(self: *Elf) !void { | ... | @@ -4170,7 +3788,7 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 4170 | 3788 | ||
| 4171 | /// Allocates non-alloc sections (debug info, symtabs, etc.). | 3789 | /// Allocates non-alloc sections (debug info, symtabs, etc.). |
| 4172 | pub fn allocateNonAllocSections(self: *Elf) !void { | 3790 | pub fn allocateNonAllocSections(self: *Elf) !void { |
| 4173 | for (self.shdrs.items, 0..) |*shdr, shndx| { | 3791 | for (self.sections.items(.shdr), 0..) |*shdr, shndx| { |
| 4174 | if (shdr.sh_type == elf.SHT_NULL) continue; | 3792 | if (shdr.sh_type == elf.SHT_NULL) continue; |
| 4175 | if (shdr.sh_flags & elf.SHF_ALLOC != 0) continue; | 3793 | if (shdr.sh_flags & elf.SHF_ALLOC != 0) continue; |
| 4176 | const needed_size = shdr.sh_size; | 3794 | const needed_size = shdr.sh_size; |
| ... | @@ -4215,13 +3833,15 @@ pub fn allocateNonAllocSections(self: *Elf) !void { | ... | @@ -4215,13 +3833,15 @@ pub fn allocateNonAllocSections(self: *Elf) !void { |
| 4215 | } | 3833 | } |
| 4216 | 3834 | ||
| 4217 | fn allocateSpecialPhdrs(self: *Elf) void { | 3835 | fn allocateSpecialPhdrs(self: *Elf) void { |
| 3836 | const slice = self.sections.slice(); | ||
| 3837 | |||
| 4218 | for (&[_]struct { ?u16, ?u32 }{ | 3838 | for (&[_]struct { ?u16, ?u32 }{ |
| 4219 | .{ self.phdr_interp_index, self.interp_section_index }, | 3839 | .{ self.phdr_interp_index, self.interp_section_index }, |
| 4220 | .{ self.phdr_dynamic_index, self.dynamic_section_index }, | 3840 | .{ self.phdr_dynamic_index, self.dynamic_section_index }, |
| 4221 | .{ self.phdr_gnu_eh_frame_index, self.eh_frame_hdr_section_index }, | 3841 | .{ self.phdr_gnu_eh_frame_index, self.eh_frame_hdr_section_index }, |
| 4222 | }) |pair| { | 3842 | }) |pair| { |
| 4223 | if (pair[0]) |index| { | 3843 | if (pair[0]) |index| { |
| 4224 | const shdr = self.shdrs.items[pair[1].?]; | 3844 | const shdr = slice.items(.shdr)[pair[1].?]; |
| 4225 | const phdr = &self.phdrs.items[index]; | 3845 | const phdr = &self.phdrs.items[index]; |
| 4226 | phdr.p_align = shdr.sh_addralign; | 3846 | phdr.p_align = shdr.sh_addralign; |
| 4227 | phdr.p_offset = shdr.sh_offset; | 3847 | phdr.p_offset = shdr.sh_offset; |
| ... | @@ -4236,11 +3856,11 @@ fn allocateSpecialPhdrs(self: *Elf) void { | ... | @@ -4236,11 +3856,11 @@ fn allocateSpecialPhdrs(self: *Elf) void { |
| 4236 | // We assume TLS sections are laid out contiguously and that there is | 3856 | // We assume TLS sections are laid out contiguously and that there is |
| 4237 | // a single TLS segment. | 3857 | // a single TLS segment. |
| 4238 | if (self.phdr_tls_index) |index| { | 3858 | if (self.phdr_tls_index) |index| { |
| 4239 | const slice = self.shdrs.items; | 3859 | const shdrs = slice.items(.shdr); |
| 4240 | const phdr = &self.phdrs.items[index]; | 3860 | const phdr = &self.phdrs.items[index]; |
| 4241 | var shndx: u32 = 0; | 3861 | var shndx: u32 = 0; |
| 4242 | while (shndx < slice.len) { | 3862 | while (shndx < shdrs.len) { |
| 4243 | const shdr = slice[shndx]; | 3863 | const shdr = shdrs[shndx]; |
| 4244 | if (shdr.sh_flags & elf.SHF_TLS == 0) { | 3864 | if (shdr.sh_flags & elf.SHF_TLS == 0) { |
| 4245 | shndx += 1; | 3865 | shndx += 1; |
| 4246 | continue; | 3866 | continue; |
| ... | @@ -4256,8 +3876,8 @@ fn allocateSpecialPhdrs(self: *Elf) void { | ... | @@ -4256,8 +3876,8 @@ fn allocateSpecialPhdrs(self: *Elf) void { |
| 4256 | } | 3876 | } |
| 4257 | phdr.p_memsz = shdr.sh_addr + shdr.sh_size - phdr.p_vaddr; | 3877 | phdr.p_memsz = shdr.sh_addr + shdr.sh_size - phdr.p_vaddr; |
| 4258 | 3878 | ||
| 4259 | while (shndx < slice.len) : (shndx += 1) { | 3879 | while (shndx < shdrs.len) : (shndx += 1) { |
| 4260 | const next = slice[shndx]; | 3880 | const next = shdrs[shndx]; |
| 4261 | if (next.sh_flags & elf.SHF_TLS == 0) break; | 3881 | if (next.sh_flags & elf.SHF_TLS == 0) break; |
| 4262 | phdr.p_align = @max(phdr.p_align, next.sh_addralign); | 3882 | phdr.p_align = @max(phdr.p_align, next.sh_addralign); |
| 4263 | if (next.sh_type != elf.SHT_NOBITS) { | 3883 | if (next.sh_type != elf.SHT_NOBITS) { |
| ... | @@ -4281,13 +3901,10 @@ fn writeAtoms(self: *Elf) !void { | ... | @@ -4281,13 +3901,10 @@ fn writeAtoms(self: *Elf) !void { |
| 4281 | } | 3901 | } |
| 4282 | 3902 | ||
| 4283 | var has_reloc_errors = false; | 3903 | var has_reloc_errors = false; |
| 4284 | 3904 | const slice = self.sections.slice(); | |
| 4285 | // TODO iterate over `output_sections` directly | 3905 | for (slice.items(.shdr), slice.items(.atom_list), 0..) |shdr, atom_list, shndx| { |
| 4286 | for (self.shdrs.items, 0..) |shdr, shndx| { | ||
| 4287 | if (shdr.sh_type == elf.SHT_NULL) continue; | 3906 | if (shdr.sh_type == elf.SHT_NULL) continue; |
| 4288 | if (shdr.sh_type == elf.SHT_NOBITS) continue; | 3907 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 4289 | |||
| 4290 | const atom_list = self.output_sections.get(@intCast(shndx)) orelse continue; | ||
| 4291 | if (atom_list.items.len == 0) continue; | 3908 | if (atom_list.items.len == 0) continue; |
| 4292 | 3909 | ||
| 4293 | log.debug("writing atoms in '{s}' section", .{self.getShString(shdr.sh_name)}); | 3910 | log.debug("writing atoms in '{s}' section", .{self.getShString(shdr.sh_name)}); |
| ... | @@ -4366,7 +3983,7 @@ fn writeAtoms(self: *Elf) !void { | ... | @@ -4366,7 +3983,7 @@ fn writeAtoms(self: *Elf) !void { |
| 4366 | for (self.thunks.items) |th| { | 3983 | for (self.thunks.items) |th| { |
| 4367 | const thunk_size = th.size(self); | 3984 | const thunk_size = th.size(self); |
| 4368 | try buffer.ensureUnusedCapacity(thunk_size); | 3985 | try buffer.ensureUnusedCapacity(thunk_size); |
| 4369 | const shdr = self.shdrs.items[th.output_section_index]; | 3986 | const shdr = slice.items(.shdr)[th.output_section_index]; |
| 4370 | const offset = @as(u64, @intCast(th.value)) + shdr.sh_offset; | 3987 | const offset = @as(u64, @intCast(th.value)) + shdr.sh_offset; |
| 4371 | try th.write(self, buffer.writer()); | 3988 | try th.write(self, buffer.writer()); |
| 4372 | assert(buffer.items.len == thunk_size); | 3989 | assert(buffer.items.len == thunk_size); |
| ... | @@ -4396,15 +4013,10 @@ pub fn updateSymtabSize(self: *Elf) !void { | ... | @@ -4396,15 +4013,10 @@ pub fn updateSymtabSize(self: *Elf) !void { |
| 4396 | if (self.linker_defined_index) |index| files.appendAssumeCapacity(index); | 4013 | if (self.linker_defined_index) |index| files.appendAssumeCapacity(index); |
| 4397 | 4014 | ||
| 4398 | // Section symbols | 4015 | // Section symbols |
| 4399 | for (self.output_sections.keys()) |_| { | 4016 | nlocals += @intCast(self.sections.slice().len); |
| 4400 | nlocals += 1; | ||
| 4401 | } | ||
| 4402 | if (self.eh_frame_section_index) |_| { | ||
| 4403 | nlocals += 1; | ||
| 4404 | } | ||
| 4405 | 4017 | ||
| 4406 | if (self.requiresThunks()) for (self.thunks.items) |*th| { | 4018 | if (self.requiresThunks()) for (self.thunks.items) |*th| { |
| 4407 | th.output_symtab_ctx.ilocal = nlocals + 1; | 4019 | th.output_symtab_ctx.ilocal = nlocals; |
| 4408 | th.calcSymtabSize(self); | 4020 | th.calcSymtabSize(self); |
| 4409 | nlocals += th.output_symtab_ctx.nlocals; | 4021 | nlocals += th.output_symtab_ctx.nlocals; |
| 4410 | strsize += th.output_symtab_ctx.strsize; | 4022 | strsize += th.output_symtab_ctx.strsize; |
| ... | @@ -4415,8 +4027,8 @@ pub fn updateSymtabSize(self: *Elf) !void { | ... | @@ -4415,8 +4027,8 @@ pub fn updateSymtabSize(self: *Elf) !void { |
| 4415 | const ctx = switch (file_ptr) { | 4027 | const ctx = switch (file_ptr) { |
| 4416 | inline else => |x| &x.output_symtab_ctx, | 4028 | inline else => |x| &x.output_symtab_ctx, |
| 4417 | }; | 4029 | }; |
| 4418 | ctx.ilocal = nlocals + 1; | 4030 | ctx.ilocal = nlocals; |
| 4419 | ctx.iglobal = nglobals + 1; | 4031 | ctx.iglobal = nglobals; |
| 4420 | try file_ptr.updateSymtabSize(self); | 4032 | try file_ptr.updateSymtabSize(self); |
| 4421 | nlocals += ctx.nlocals; | 4033 | nlocals += ctx.nlocals; |
| 4422 | nglobals += ctx.nglobals; | 4034 | nglobals += ctx.nglobals; |
| ... | @@ -4424,21 +4036,21 @@ pub fn updateSymtabSize(self: *Elf) !void { | ... | @@ -4424,21 +4036,21 @@ pub fn updateSymtabSize(self: *Elf) !void { |
| 4424 | } | 4036 | } |
| 4425 | 4037 | ||
| 4426 | if (self.got_section_index) |_| { | 4038 | if (self.got_section_index) |_| { |
| 4427 | self.got.output_symtab_ctx.ilocal = nlocals + 1; | 4039 | self.got.output_symtab_ctx.ilocal = nlocals; |
| 4428 | self.got.updateSymtabSize(self); | 4040 | self.got.updateSymtabSize(self); |
| 4429 | nlocals += self.got.output_symtab_ctx.nlocals; | 4041 | nlocals += self.got.output_symtab_ctx.nlocals; |
| 4430 | strsize += self.got.output_symtab_ctx.strsize; | 4042 | strsize += self.got.output_symtab_ctx.strsize; |
| 4431 | } | 4043 | } |
| 4432 | 4044 | ||
| 4433 | if (self.plt_section_index) |_| { | 4045 | if (self.plt_section_index) |_| { |
| 4434 | self.plt.output_symtab_ctx.ilocal = nlocals + 1; | 4046 | self.plt.output_symtab_ctx.ilocal = nlocals; |
| 4435 | self.plt.updateSymtabSize(self); | 4047 | self.plt.updateSymtabSize(self); |
| 4436 | nlocals += self.plt.output_symtab_ctx.nlocals; | 4048 | nlocals += self.plt.output_symtab_ctx.nlocals; |
| 4437 | strsize += self.plt.output_symtab_ctx.strsize; | 4049 | strsize += self.plt.output_symtab_ctx.strsize; |
| 4438 | } | 4050 | } |
| 4439 | 4051 | ||
| 4440 | if (self.plt_got_section_index) |_| { | 4052 | if (self.plt_got_section_index) |_| { |
| 4441 | self.plt_got.output_symtab_ctx.ilocal = nlocals + 1; | 4053 | self.plt_got.output_symtab_ctx.ilocal = nlocals; |
| 4442 | self.plt_got.updateSymtabSize(self); | 4054 | self.plt_got.updateSymtabSize(self); |
| 4443 | nlocals += self.plt_got.output_symtab_ctx.nlocals; | 4055 | nlocals += self.plt_got.output_symtab_ctx.nlocals; |
| 4444 | strsize += self.plt_got.output_symtab_ctx.strsize; | 4056 | strsize += self.plt_got.output_symtab_ctx.strsize; |
| ... | @@ -4452,24 +4064,26 @@ pub fn updateSymtabSize(self: *Elf) !void { | ... | @@ -4452,24 +4064,26 @@ pub fn updateSymtabSize(self: *Elf) !void { |
| 4452 | ctx.iglobal += nlocals; | 4064 | ctx.iglobal += nlocals; |
| 4453 | } | 4065 | } |
| 4454 | 4066 | ||
| 4455 | const symtab_shdr = &self.shdrs.items[self.symtab_section_index.?]; | 4067 | const slice = self.sections.slice(); |
| 4456 | symtab_shdr.sh_info = nlocals + 1; | 4068 | const symtab_shdr = &slice.items(.shdr)[self.symtab_section_index.?]; |
| 4069 | symtab_shdr.sh_info = nlocals; | ||
| 4457 | symtab_shdr.sh_link = self.strtab_section_index.?; | 4070 | symtab_shdr.sh_link = self.strtab_section_index.?; |
| 4458 | 4071 | ||
| 4459 | const sym_size: u64 = switch (self.ptr_width) { | 4072 | const sym_size: u64 = switch (self.ptr_width) { |
| 4460 | .p32 => @sizeOf(elf.Elf32_Sym), | 4073 | .p32 => @sizeOf(elf.Elf32_Sym), |
| 4461 | .p64 => @sizeOf(elf.Elf64_Sym), | 4074 | .p64 => @sizeOf(elf.Elf64_Sym), |
| 4462 | }; | 4075 | }; |
| 4463 | const needed_size = (nlocals + nglobals + 1) * sym_size; | 4076 | const needed_size = (nlocals + nglobals) * sym_size; |
| 4464 | symtab_shdr.sh_size = needed_size; | 4077 | symtab_shdr.sh_size = needed_size; |
| 4465 | 4078 | ||
| 4466 | const strtab = &self.shdrs.items[self.strtab_section_index.?]; | 4079 | const strtab = &slice.items(.shdr)[self.strtab_section_index.?]; |
| 4467 | strtab.sh_size = strsize + 1; | 4080 | strtab.sh_size = strsize + 1; |
| 4468 | } | 4081 | } |
| 4469 | 4082 | ||
| 4470 | fn writeSyntheticSections(self: *Elf) !void { | 4083 | fn writeSyntheticSections(self: *Elf) !void { |
| 4471 | const target = self.base.comp.root_mod.resolved_target.result; | ||
| 4472 | const gpa = self.base.comp.gpa; | 4084 | const gpa = self.base.comp.gpa; |
| 4085 | const target = self.getTarget(); | ||
| 4086 | const slice = self.sections.slice(); | ||
| 4473 | 4087 | ||
| 4474 | if (self.interp_section_index) |shndx| { | 4088 | if (self.interp_section_index) |shndx| { |
| 4475 | var buffer: [256]u8 = undefined; | 4089 | var buffer: [256]u8 = undefined; |
| ... | @@ -4477,18 +4091,18 @@ fn writeSyntheticSections(self: *Elf) !void { | ... | @@ -4477,18 +4091,18 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4477 | @memcpy(buffer[0..interp.len], interp); | 4091 | @memcpy(buffer[0..interp.len], interp); |
| 4478 | buffer[interp.len] = 0; | 4092 | buffer[interp.len] = 0; |
| 4479 | const contents = buffer[0 .. interp.len + 1]; | 4093 | const contents = buffer[0 .. interp.len + 1]; |
| 4480 | const shdr = self.shdrs.items[shndx]; | 4094 | const shdr = slice.items(.shdr)[shndx]; |
| 4481 | assert(shdr.sh_size == contents.len); | 4095 | assert(shdr.sh_size == contents.len); |
| 4482 | try self.base.file.?.pwriteAll(contents, shdr.sh_offset); | 4096 | try self.base.file.?.pwriteAll(contents, shdr.sh_offset); |
| 4483 | } | 4097 | } |
| 4484 | 4098 | ||
| 4485 | if (self.hash_section_index) |shndx| { | 4099 | if (self.hash_section_index) |shndx| { |
| 4486 | const shdr = self.shdrs.items[shndx]; | 4100 | const shdr = slice.items(.shdr)[shndx]; |
| 4487 | try self.base.file.?.pwriteAll(self.hash.buffer.items, shdr.sh_offset); | 4101 | try self.base.file.?.pwriteAll(self.hash.buffer.items, shdr.sh_offset); |
| 4488 | } | 4102 | } |
| 4489 | 4103 | ||
| 4490 | if (self.gnu_hash_section_index) |shndx| { | 4104 | if (self.gnu_hash_section_index) |shndx| { |
| 4491 | const shdr = self.shdrs.items[shndx]; | 4105 | const shdr = slice.items(.shdr)[shndx]; |
| 4492 | var buffer = try std.ArrayList(u8).initCapacity(gpa, self.gnu_hash.size()); | 4106 | var buffer = try std.ArrayList(u8).initCapacity(gpa, self.gnu_hash.size()); |
| 4493 | defer buffer.deinit(); | 4107 | defer buffer.deinit(); |
| 4494 | try self.gnu_hash.write(self, buffer.writer()); | 4108 | try self.gnu_hash.write(self, buffer.writer()); |
| ... | @@ -4496,12 +4110,12 @@ fn writeSyntheticSections(self: *Elf) !void { | ... | @@ -4496,12 +4110,12 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4496 | } | 4110 | } |
| 4497 | 4111 | ||
| 4498 | if (self.versym_section_index) |shndx| { | 4112 | if (self.versym_section_index) |shndx| { |
| 4499 | const shdr = self.shdrs.items[shndx]; | 4113 | const shdr = slice.items(.shdr)[shndx]; |
| 4500 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.versym.items), shdr.sh_offset); | 4114 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.versym.items), shdr.sh_offset); |
| 4501 | } | 4115 | } |
| 4502 | 4116 | ||
| 4503 | if (self.verneed_section_index) |shndx| { | 4117 | if (self.verneed_section_index) |shndx| { |
| 4504 | const shdr = self.shdrs.items[shndx]; | 4118 | const shdr = slice.items(.shdr)[shndx]; |
| 4505 | var buffer = try std.ArrayList(u8).initCapacity(gpa, self.verneed.size()); | 4119 | var buffer = try std.ArrayList(u8).initCapacity(gpa, self.verneed.size()); |
| 4506 | defer buffer.deinit(); | 4120 | defer buffer.deinit(); |
| 4507 | try self.verneed.write(buffer.writer()); | 4121 | try self.verneed.write(buffer.writer()); |
| ... | @@ -4509,7 +4123,7 @@ fn writeSyntheticSections(self: *Elf) !void { | ... | @@ -4509,7 +4123,7 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4509 | } | 4123 | } |
| 4510 | 4124 | ||
| 4511 | if (self.dynamic_section_index) |shndx| { | 4125 | if (self.dynamic_section_index) |shndx| { |
| 4512 | const shdr = self.shdrs.items[shndx]; | 4126 | const shdr = slice.items(.shdr)[shndx]; |
| 4513 | var buffer = try std.ArrayList(u8).initCapacity(gpa, self.dynamic.size(self)); | 4127 | var buffer = try std.ArrayList(u8).initCapacity(gpa, self.dynamic.size(self)); |
| 4514 | defer buffer.deinit(); | 4128 | defer buffer.deinit(); |
| 4515 | try self.dynamic.write(self, buffer.writer()); | 4129 | try self.dynamic.write(self, buffer.writer()); |
| ... | @@ -4517,7 +4131,7 @@ fn writeSyntheticSections(self: *Elf) !void { | ... | @@ -4517,7 +4131,7 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4517 | } | 4131 | } |
| 4518 | 4132 | ||
| 4519 | if (self.dynsymtab_section_index) |shndx| { | 4133 | if (self.dynsymtab_section_index) |shndx| { |
| 4520 | const shdr = self.shdrs.items[shndx]; | 4134 | const shdr = slice.items(.shdr)[shndx]; |
| 4521 | var buffer = try std.ArrayList(u8).initCapacity(gpa, self.dynsym.size()); | 4135 | var buffer = try std.ArrayList(u8).initCapacity(gpa, self.dynsym.size()); |
| 4522 | defer buffer.deinit(); | 4136 | defer buffer.deinit(); |
| 4523 | try self.dynsym.write(self, buffer.writer()); | 4137 | try self.dynsym.write(self, buffer.writer()); |
| ... | @@ -4525,12 +4139,12 @@ fn writeSyntheticSections(self: *Elf) !void { | ... | @@ -4525,12 +4139,12 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4525 | } | 4139 | } |
| 4526 | 4140 | ||
| 4527 | if (self.dynstrtab_section_index) |shndx| { | 4141 | if (self.dynstrtab_section_index) |shndx| { |
| 4528 | const shdr = self.shdrs.items[shndx]; | 4142 | const shdr = slice.items(.shdr)[shndx]; |
| 4529 | try self.base.file.?.pwriteAll(self.dynstrtab.items, shdr.sh_offset); | 4143 | try self.base.file.?.pwriteAll(self.dynstrtab.items, shdr.sh_offset); |
| 4530 | } | 4144 | } |
| 4531 | 4145 | ||
| 4532 | if (self.eh_frame_section_index) |shndx| { | 4146 | if (self.eh_frame_section_index) |shndx| { |
| 4533 | const shdr = self.shdrs.items[shndx]; | 4147 | const shdr = slice.items(.shdr)[shndx]; |
| 4534 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; | 4148 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; |
| 4535 | var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); | 4149 | var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); |
| 4536 | defer buffer.deinit(); | 4150 | defer buffer.deinit(); |
| ... | @@ -4539,7 +4153,7 @@ fn writeSyntheticSections(self: *Elf) !void { | ... | @@ -4539,7 +4153,7 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4539 | } | 4153 | } |
| 4540 | 4154 | ||
| 4541 | if (self.eh_frame_hdr_section_index) |shndx| { | 4155 | if (self.eh_frame_hdr_section_index) |shndx| { |
| 4542 | const shdr = self.shdrs.items[shndx]; | 4156 | const shdr = slice.items(.shdr)[shndx]; |
| 4543 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; | 4157 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; |
| 4544 | var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); | 4158 | var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); |
| 4545 | defer buffer.deinit(); | 4159 | defer buffer.deinit(); |
| ... | @@ -4548,7 +4162,7 @@ fn writeSyntheticSections(self: *Elf) !void { | ... | @@ -4548,7 +4162,7 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4548 | } | 4162 | } |
| 4549 | 4163 | ||
| 4550 | if (self.got_section_index) |index| { | 4164 | if (self.got_section_index) |index| { |
| 4551 | const shdr = self.shdrs.items[index]; | 4165 | const shdr = slice.items(.shdr)[index]; |
| 4552 | var buffer = try std.ArrayList(u8).initCapacity(gpa, self.got.size(self)); | 4166 | var buffer = try std.ArrayList(u8).initCapacity(gpa, self.got.size(self)); |
| 4553 | defer buffer.deinit(); | 4167 | defer buffer.deinit(); |
| 4554 | try self.got.write(self, buffer.writer()); | 4168 | try self.got.write(self, buffer.writer()); |
| ... | @@ -4556,7 +4170,7 @@ fn writeSyntheticSections(self: *Elf) !void { | ... | @@ -4556,7 +4170,7 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4556 | } | 4170 | } |
| 4557 | 4171 | ||
| 4558 | if (self.rela_dyn_section_index) |shndx| { | 4172 | if (self.rela_dyn_section_index) |shndx| { |
| 4559 | const shdr = self.shdrs.items[shndx]; | 4173 | const shdr = slice.items(.shdr)[shndx]; |
| 4560 | try self.got.addRela(self); | 4174 | try self.got.addRela(self); |
| 4561 | try self.copy_rel.addRela(self); | 4175 | try self.copy_rel.addRela(self); |
| 4562 | self.sortRelaDyn(); | 4176 | self.sortRelaDyn(); |
| ... | @@ -4564,7 +4178,7 @@ fn writeSyntheticSections(self: *Elf) !void { | ... | @@ -4564,7 +4178,7 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4564 | } | 4178 | } |
| 4565 | 4179 | ||
| 4566 | if (self.plt_section_index) |shndx| { | 4180 | if (self.plt_section_index) |shndx| { |
| 4567 | const shdr = self.shdrs.items[shndx]; | 4181 | const shdr = slice.items(.shdr)[shndx]; |
| 4568 | var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt.size(self)); | 4182 | var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt.size(self)); |
| 4569 | defer buffer.deinit(); | 4183 | defer buffer.deinit(); |
| 4570 | try self.plt.write(self, buffer.writer()); | 4184 | try self.plt.write(self, buffer.writer()); |
| ... | @@ -4572,7 +4186,7 @@ fn writeSyntheticSections(self: *Elf) !void { | ... | @@ -4572,7 +4186,7 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4572 | } | 4186 | } |
| 4573 | 4187 | ||
| 4574 | if (self.got_plt_section_index) |shndx| { | 4188 | if (self.got_plt_section_index) |shndx| { |
| 4575 | const shdr = self.shdrs.items[shndx]; | 4189 | const shdr = slice.items(.shdr)[shndx]; |
| 4576 | var buffer = try std.ArrayList(u8).initCapacity(gpa, self.got_plt.size(self)); | 4190 | var buffer = try std.ArrayList(u8).initCapacity(gpa, self.got_plt.size(self)); |
| 4577 | defer buffer.deinit(); | 4191 | defer buffer.deinit(); |
| 4578 | try self.got_plt.write(self, buffer.writer()); | 4192 | try self.got_plt.write(self, buffer.writer()); |
| ... | @@ -4580,7 +4194,7 @@ fn writeSyntheticSections(self: *Elf) !void { | ... | @@ -4580,7 +4194,7 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4580 | } | 4194 | } |
| 4581 | 4195 | ||
| 4582 | if (self.plt_got_section_index) |shndx| { | 4196 | if (self.plt_got_section_index) |shndx| { |
| 4583 | const shdr = self.shdrs.items[shndx]; | 4197 | const shdr = slice.items(.shdr)[shndx]; |
| 4584 | var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt_got.size(self)); | 4198 | var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt_got.size(self)); |
| 4585 | defer buffer.deinit(); | 4199 | defer buffer.deinit(); |
| 4586 | try self.plt_got.write(self, buffer.writer()); | 4200 | try self.plt_got.write(self, buffer.writer()); |
| ... | @@ -4588,7 +4202,7 @@ fn writeSyntheticSections(self: *Elf) !void { | ... | @@ -4588,7 +4202,7 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4588 | } | 4202 | } |
| 4589 | 4203 | ||
| 4590 | if (self.rela_plt_section_index) |shndx| { | 4204 | if (self.rela_plt_section_index) |shndx| { |
| 4591 | const shdr = self.shdrs.items[shndx]; | 4205 | const shdr = slice.items(.shdr)[shndx]; |
| 4592 | try self.plt.addRela(self); | 4206 | try self.plt.addRela(self); |
| 4593 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_plt.items), shdr.sh_offset); | 4207 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_plt.items), shdr.sh_offset); |
| 4594 | } | 4208 | } |
| ... | @@ -4597,19 +4211,21 @@ fn writeSyntheticSections(self: *Elf) !void { | ... | @@ -4597,19 +4211,21 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4597 | try self.writeShStrtab(); | 4211 | try self.writeShStrtab(); |
| 4598 | } | 4212 | } |
| 4599 | 4213 | ||
| 4214 | // FIXME:JK again, why is this needed? | ||
| 4600 | pub fn writeShStrtab(self: *Elf) !void { | 4215 | pub fn writeShStrtab(self: *Elf) !void { |
| 4601 | if (self.shstrtab_section_index) |index| { | 4216 | if (self.shstrtab_section_index) |index| { |
| 4602 | const shdr = self.shdrs.items[index]; | 4217 | const shdr = self.sections.items(.shdr)[index]; |
| 4603 | log.debug("writing .shstrtab from 0x{x} to 0x{x}", .{ shdr.sh_offset, shdr.sh_offset + shdr.sh_size }); | 4218 | log.debug("writing .shstrtab from 0x{x} to 0x{x}", .{ shdr.sh_offset, shdr.sh_offset + shdr.sh_size }); |
| 4604 | try self.base.file.?.pwriteAll(self.shstrtab.items, shdr.sh_offset); | 4219 | try self.base.file.?.pwriteAll(self.shstrtab.items, shdr.sh_offset); |
| 4605 | } | 4220 | } |
| 4606 | } | 4221 | } |
| 4607 | 4222 | ||
| 4608 | pub fn writeSymtab(self: *Elf) !void { | 4223 | pub fn writeSymtab(self: *Elf) !void { |
| 4609 | const target = self.base.comp.root_mod.resolved_target.result; | ||
| 4610 | const gpa = self.base.comp.gpa; | 4224 | const gpa = self.base.comp.gpa; |
| 4611 | const symtab_shdr = self.shdrs.items[self.symtab_section_index.?]; | 4225 | const target = self.getTarget(); |
| 4612 | const strtab_shdr = self.shdrs.items[self.strtab_section_index.?]; | 4226 | const slice = self.sections.slice(); |
| 4227 | const symtab_shdr = slice.items(.shdr)[self.symtab_section_index.?]; | ||
| 4228 | const strtab_shdr = slice.items(.shdr)[self.strtab_section_index.?]; | ||
| 4613 | const sym_size: u64 = switch (self.ptr_width) { | 4229 | const sym_size: u64 = switch (self.ptr_width) { |
| 4614 | .p32 => @sizeOf(elf.Elf32_Sym), | 4230 | .p32 => @sizeOf(elf.Elf32_Sym), |
| 4615 | .p64 => @sizeOf(elf.Elf64_Sym), | 4231 | .p64 => @sizeOf(elf.Elf64_Sym), |
| ... | @@ -4630,7 +4246,17 @@ pub fn writeSymtab(self: *Elf) !void { | ... | @@ -4630,7 +4246,17 @@ pub fn writeSymtab(self: *Elf) !void { |
| 4630 | const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow; | 4246 | const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow; |
| 4631 | try self.strtab.ensureUnusedCapacity(gpa, needed_strtab_size); | 4247 | try self.strtab.ensureUnusedCapacity(gpa, needed_strtab_size); |
| 4632 | 4248 | ||
| 4633 | self.writeSectionSymbols(); | 4249 | for (slice.items(.shdr), 0..) |shdr, shndx| { |
| 4250 | const out_sym = &self.symtab.items[shndx]; | ||
| 4251 | out_sym.* = .{ | ||
| 4252 | .st_name = 0, | ||
| 4253 | .st_value = shdr.sh_addr, | ||
| 4254 | .st_info = if (shdr.sh_type == elf.SHT_NULL) elf.STT_NOTYPE else elf.STT_SECTION, | ||
| 4255 | .st_shndx = @intCast(shndx), | ||
| 4256 | .st_size = 0, | ||
| 4257 | .st_other = 0, | ||
| 4258 | }; | ||
| 4259 | } | ||
| 4634 | 4260 | ||
| 4635 | if (self.requiresThunks()) for (self.thunks.items) |th| { | 4261 | if (self.requiresThunks()) for (self.thunks.items) |th| { |
| 4636 | th.writeSymtab(self); | 4262 | th.writeSymtab(self); |
| ... | @@ -4696,44 +4322,6 @@ pub fn writeSymtab(self: *Elf) !void { | ... | @@ -4696,44 +4322,6 @@ pub fn writeSymtab(self: *Elf) !void { |
| 4696 | try self.base.file.?.pwriteAll(self.strtab.items, strtab_shdr.sh_offset); | 4322 | try self.base.file.?.pwriteAll(self.strtab.items, strtab_shdr.sh_offset); |
| 4697 | } | 4323 | } |
| 4698 | 4324 | ||
| 4699 | fn writeSectionSymbols(self: *Elf) void { | ||
| 4700 | var ilocal: u32 = 1; | ||
| 4701 | for (self.output_sections.keys()) |shndx| { | ||
| 4702 | const shdr = self.shdrs.items[shndx]; | ||
| 4703 | const out_sym = &self.symtab.items[ilocal]; | ||
| 4704 | out_sym.* = .{ | ||
| 4705 | .st_name = 0, | ||
| 4706 | .st_value = shdr.sh_addr, | ||
| 4707 | .st_info = elf.STT_SECTION, | ||
| 4708 | .st_shndx = @intCast(shndx), | ||
| 4709 | .st_size = 0, | ||
| 4710 | .st_other = 0, | ||
| 4711 | }; | ||
| 4712 | ilocal += 1; | ||
| 4713 | } | ||
| 4714 | |||
| 4715 | if (self.eh_frame_section_index) |shndx| { | ||
| 4716 | const shdr = self.shdrs.items[shndx]; | ||
| 4717 | const out_sym = &self.symtab.items[ilocal]; | ||
| 4718 | out_sym.* = .{ | ||
| 4719 | .st_name = 0, | ||
| 4720 | .st_value = shdr.sh_addr, | ||
| 4721 | .st_info = elf.STT_SECTION, | ||
| 4722 | .st_shndx = @intCast(shndx), | ||
| 4723 | .st_size = 0, | ||
| 4724 | .st_other = 0, | ||
| 4725 | }; | ||
| 4726 | ilocal += 1; | ||
| 4727 | } | ||
| 4728 | } | ||
| 4729 | |||
| 4730 | pub fn sectionSymbolOutputSymtabIndex(self: Elf, shndx: u32) u32 { | ||
| 4731 | if (self.eh_frame_section_index) |index| { | ||
| 4732 | if (index == shndx) return @intCast(self.output_sections.keys().len + 1); | ||
| 4733 | } | ||
| 4734 | return @intCast(self.output_sections.getIndex(shndx).? + 1); | ||
| 4735 | } | ||
| 4736 | |||
| 4737 | /// Always 4 or 8 depending on whether this is 32-bit ELF or 64-bit ELF. | 4325 | /// Always 4 or 8 depending on whether this is 32-bit ELF or 64-bit ELF. |
| 4738 | pub fn ptrWidthBytes(self: Elf) u8 { | 4326 | pub fn ptrWidthBytes(self: Elf) u8 { |
| 4739 | return switch (self.ptr_width) { | 4327 | return switch (self.ptr_width) { |
| ... | @@ -4745,8 +4333,7 @@ pub fn ptrWidthBytes(self: Elf) u8 { | ... | @@ -4745,8 +4333,7 @@ pub fn ptrWidthBytes(self: Elf) u8 { |
| 4745 | /// Does not necessarily match `ptrWidthBytes` for example can be 2 bytes | 4333 | /// Does not necessarily match `ptrWidthBytes` for example can be 2 bytes |
| 4746 | /// in a 32-bit ELF file. | 4334 | /// in a 32-bit ELF file. |
| 4747 | pub fn archPtrWidthBytes(self: Elf) u8 { | 4335 | pub fn archPtrWidthBytes(self: Elf) u8 { |
| 4748 | const target = self.base.comp.root_mod.resolved_target.result; | 4336 | return @intCast(@divExact(self.getTarget().ptrBitWidth(), 8)); |
| 4749 | return @intCast(@divExact(target.ptrBitWidth(), 8)); | ||
| 4750 | } | 4337 | } |
| 4751 | 4338 | ||
| 4752 | fn phdrTo32(phdr: elf.Elf64_Phdr) elf.Elf32_Phdr { | 4339 | fn phdrTo32(phdr: elf.Elf64_Phdr) elf.Elf32_Phdr { |
| ... | @@ -5069,7 +4656,7 @@ pub fn isDebugSection(self: Elf, shndx: u32) bool { | ... | @@ -5069,7 +4656,7 @@ pub fn isDebugSection(self: Elf, shndx: u32) bool { |
| 5069 | return false; | 4656 | return false; |
| 5070 | } | 4657 | } |
| 5071 | 4658 | ||
| 5072 | fn addPhdr(self: *Elf, opts: struct { | 4659 | pub fn addPhdr(self: *Elf, opts: struct { |
| 5073 | type: u32 = 0, | 4660 | type: u32 = 0, |
| 5074 | flags: u32 = 0, | 4661 | flags: u32 = 0, |
| 5075 | @"align": u64 = 0, | 4662 | @"align": u64 = 0, |
| ... | @@ -5126,25 +4713,26 @@ pub const AddSectionOpts = struct { | ... | @@ -5126,25 +4713,26 @@ pub const AddSectionOpts = struct { |
| 5126 | 4713 | ||
| 5127 | pub fn addSection(self: *Elf, opts: AddSectionOpts) !u32 { | 4714 | pub fn addSection(self: *Elf, opts: AddSectionOpts) !u32 { |
| 5128 | const gpa = self.base.comp.gpa; | 4715 | const gpa = self.base.comp.gpa; |
| 5129 | const index: u32 = @intCast(self.shdrs.items.len); | 4716 | const index: u32 = @intCast(try self.sections.addOne(gpa)); |
| 5130 | const shdr = try self.shdrs.addOne(gpa); | 4717 | self.sections.set(index, .{ |
| 5131 | shdr.* = .{ | 4718 | .shdr = .{ |
| 5132 | .sh_name = opts.name, | 4719 | .sh_name = opts.name, |
| 5133 | .sh_type = opts.type, | 4720 | .sh_type = opts.type, |
| 5134 | .sh_flags = opts.flags, | 4721 | .sh_flags = opts.flags, |
| 5135 | .sh_addr = 0, | 4722 | .sh_addr = 0, |
| 5136 | .sh_offset = opts.offset, | 4723 | .sh_offset = opts.offset, |
| 5137 | .sh_size = 0, | 4724 | .sh_size = 0, |
| 5138 | .sh_link = opts.link, | 4725 | .sh_link = opts.link, |
| 5139 | .sh_info = opts.info, | 4726 | .sh_info = opts.info, |
| 5140 | .sh_addralign = opts.addralign, | 4727 | .sh_addralign = opts.addralign, |
| 5141 | .sh_entsize = opts.entsize, | 4728 | .sh_entsize = opts.entsize, |
| 5142 | }; | 4729 | }, |
| 4730 | }); | ||
| 5143 | return index; | 4731 | return index; |
| 5144 | } | 4732 | } |
| 5145 | 4733 | ||
| 5146 | pub fn sectionByName(self: *Elf, name: [:0]const u8) ?u32 { | 4734 | pub fn sectionByName(self: *Elf, name: [:0]const u8) ?u32 { |
| 5147 | for (self.shdrs.items, 0..) |*shdr, i| { | 4735 | for (self.sections.items(.shdr), 0..) |*shdr, i| { |
| 5148 | const this_name = self.getShString(shdr.sh_name); | 4736 | const this_name = self.getShString(shdr.sh_name); |
| 5149 | if (mem.eql(u8, this_name, name)) return @intCast(i); | 4737 | if (mem.eql(u8, this_name, name)) return @intCast(i); |
| 5150 | } else return null; | 4738 | } else return null; |
| ... | @@ -5322,7 +4910,7 @@ pub fn gotAddress(self: *Elf) i64 { | ... | @@ -5322,7 +4910,7 @@ pub fn gotAddress(self: *Elf) i64 { |
| 5322 | break :blk self.got_plt_section_index.?; | 4910 | break :blk self.got_plt_section_index.?; |
| 5323 | break :blk if (self.got_section_index) |shndx| shndx else null; | 4911 | break :blk if (self.got_section_index) |shndx| shndx else null; |
| 5324 | }; | 4912 | }; |
| 5325 | return if (shndx) |index| @intCast(self.shdrs.items[index].sh_addr) else 0; | 4913 | return if (shndx) |index| @intCast(self.sections.items(.shdr)[index].sh_addr) else 0; |
| 5326 | } | 4914 | } |
| 5327 | 4915 | ||
| 5328 | pub fn tpAddress(self: *Elf) i64 { | 4916 | pub fn tpAddress(self: *Elf) i64 { |
| ... | @@ -5676,16 +5264,16 @@ fn fmtDumpState( | ... | @@ -5676,16 +5264,16 @@ fn fmtDumpState( |
| 5676 | } | 5264 | } |
| 5677 | 5265 | ||
| 5678 | try writer.writeAll("\nOutput shdrs\n"); | 5266 | try writer.writeAll("\nOutput shdrs\n"); |
| 5679 | for (self.shdrs.items, 0..) |shdr, shndx| { | 5267 | for (self.sections.items(.shdr), self.sections.items(.phndx), 0..) |shdr, phndx, shndx| { |
| 5680 | try writer.print(" shdr({d}) : phdr({?d}) : {}\n", .{ | 5268 | try writer.print(" shdr({d}) : phdr({?d}) : {}\n", .{ |
| 5681 | shndx, | 5269 | shndx, |
| 5682 | self.phdr_to_shdr_table.get(@intCast(shndx)), | 5270 | phndx, |
| 5683 | self.fmtShdr(shdr), | 5271 | self.fmtShdr(shdr), |
| 5684 | }); | 5272 | }); |
| 5685 | } | 5273 | } |
| 5686 | try writer.writeAll("\nOutput phdrs\n"); | 5274 | try writer.writeAll("\nOutput phdrs\n"); |
| 5687 | for (self.phdrs.items, 0..) |phdr, phndx| { | 5275 | for (self.phdrs.items, 0..) |phdr, phndx| { |
| 5688 | try writer.print(" phdr{d} : {}\n", .{ phndx, self.fmtPhdr(phdr) }); | 5276 | try writer.print(" phdr({d}) : {}\n", .{ phndx, self.fmtPhdr(phdr) }); |
| 5689 | } | 5277 | } |
| 5690 | } | 5278 | } |
| 5691 | 5279 | ||
| ... | @@ -5746,7 +5334,7 @@ fn requiresThunks(self: Elf) bool { | ... | @@ -5746,7 +5334,7 @@ fn requiresThunks(self: Elf) bool { |
| 5746 | /// so that we reserve enough space for the program header table up-front. | 5334 | /// so that we reserve enough space for the program header table up-front. |
| 5747 | /// Bump these numbers when adding or deleting a Zig specific pre-allocated segment, or adding | 5335 | /// Bump these numbers when adding or deleting a Zig specific pre-allocated segment, or adding |
| 5748 | /// more special-purpose program headers. | 5336 | /// more special-purpose program headers. |
| 5749 | const number_of_zig_segments = 5; | 5337 | pub const number_of_zig_segments = 4; |
| 5750 | const max_number_of_object_segments = 9; | 5338 | const max_number_of_object_segments = 9; |
| 5751 | const max_number_of_special_phdrs = 5; | 5339 | const max_number_of_special_phdrs = 5; |
| 5752 | 5340 | ||
| ... | @@ -5814,8 +5402,8 @@ pub const SystemLib = struct { | ... | @@ -5814,8 +5402,8 @@ pub const SystemLib = struct { |
| 5814 | }; | 5402 | }; |
| 5815 | 5403 | ||
| 5816 | pub const Ref = struct { | 5404 | pub const Ref = struct { |
| 5817 | index: u32, | 5405 | index: u32 = 0, |
| 5818 | file: u32, | 5406 | file: u32 = 0, |
| 5819 | 5407 | ||
| 5820 | pub fn eql(ref: Ref, other: Ref) bool { | 5408 | pub fn eql(ref: Ref, other: Ref) bool { |
| 5821 | return ref.index == other.index and ref.file == other.file; | 5409 | return ref.index == other.index and ref.file == other.file; |
| ... | @@ -5923,9 +5511,18 @@ pub const SymbolResolver = struct { | ... | @@ -5923,9 +5511,18 @@ pub const SymbolResolver = struct { |
| 5923 | pub const Index = u32; | 5511 | pub const Index = u32; |
| 5924 | }; | 5512 | }; |
| 5925 | 5513 | ||
| 5926 | const LastAtomAndFreeList = struct { | 5514 | const Section = struct { |
| 5515 | /// Section header. | ||
| 5516 | shdr: elf.Elf64_Shdr, | ||
| 5517 | |||
| 5518 | /// Assigned program header index if any. | ||
| 5519 | phndx: ?u32 = null, | ||
| 5520 | |||
| 5521 | /// List of atoms contributing to this section. | ||
| 5522 | atom_list: std.ArrayListUnmanaged(Ref) = .{}, | ||
| 5523 | |||
| 5927 | /// Index of the last allocated atom in this section. | 5524 | /// Index of the last allocated atom in this section. |
| 5928 | last_atom_index: Atom.Index = 0, | 5525 | last_atom: Ref = .{ .index = 0, .file = 0 }, |
| 5929 | 5526 | ||
| 5930 | /// A list of atoms that have surplus capacity. This list can have false | 5527 | /// A list of atoms that have surplus capacity. This list can have false |
| 5931 | /// positives, as functions grow and shrink over time, only sometimes being added | 5528 | /// positives, as functions grow and shrink over time, only sometimes being added |
| ... | @@ -5942,15 +5539,8 @@ const LastAtomAndFreeList = struct { | ... | @@ -5942,15 +5539,8 @@ const LastAtomAndFreeList = struct { |
| 5942 | /// overcapacity can be negative. A simple way to have negative overcapacity is to | 5539 | /// overcapacity can be negative. A simple way to have negative overcapacity is to |
| 5943 | /// allocate a fresh text block, which will have ideal capacity, and then grow it | 5540 | /// allocate a fresh text block, which will have ideal capacity, and then grow it |
| 5944 | /// by 1 byte. It will then have -1 overcapacity. | 5541 | /// by 1 byte. It will then have -1 overcapacity. |
| 5945 | free_list: std.ArrayListUnmanaged(Atom.Index) = .{}, | 5542 | free_list: std.ArrayListUnmanaged(Ref) = .{}, |
| 5946 | }; | ||
| 5947 | const LastAtomAndFreeListTable = std.AutoArrayHashMapUnmanaged(u32, LastAtomAndFreeList); | ||
| 5948 | |||
| 5949 | const RelaSection = struct { | ||
| 5950 | shndx: u32, | ||
| 5951 | atom_list: std.ArrayListUnmanaged(Ref) = .{}, | ||
| 5952 | }; | 5543 | }; |
| 5953 | const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection); | ||
| 5954 | 5544 | ||
| 5955 | fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 { | 5545 | fn defaultEntrySymbolName(cpu_arch: std.Target.Cpu.Arch) []const u8 { |
| 5956 | return switch (cpu_arch) { | 5546 | return switch (cpu_arch) { |
src/link/Elf/Atom.zig+94-81| ... | @@ -25,10 +25,9 @@ relocs_section_index: u32 = 0, | ... | @@ -25,10 +25,9 @@ relocs_section_index: u32 = 0, |
| 25 | /// Index of this atom in the linker's atoms table. | 25 | /// Index of this atom in the linker's atoms table. |
| 26 | atom_index: Index = 0, | 26 | atom_index: Index = 0, |
| 27 | 27 | ||
| 28 | /// Points to the previous and next neighbors, based on the `text_offset`. | 28 | /// Points to the previous and next neighbors. |
| 29 | /// This can be used to find, for example, the capacity of this `TextBlock`. | 29 | prev_atom_ref: Elf.Ref = .{}, |
| 30 | prev_index: Index = 0, | 30 | next_atom_ref: Elf.Ref = .{}, |
| 31 | next_index: Index = 0, | ||
| 32 | 31 | ||
| 33 | /// Specifies whether this atom is alive or has been garbage collected. | 32 | /// Specifies whether this atom is alive or has been garbage collected. |
| 34 | alive: bool = true, | 33 | alive: bool = true, |
| ... | @@ -48,10 +47,22 @@ pub fn name(self: Atom, elf_file: *Elf) [:0]const u8 { | ... | @@ -48,10 +47,22 @@ pub fn name(self: Atom, elf_file: *Elf) [:0]const u8 { |
| 48 | } | 47 | } |
| 49 | 48 | ||
| 50 | pub fn address(self: Atom, elf_file: *Elf) i64 { | 49 | pub fn address(self: Atom, elf_file: *Elf) i64 { |
| 51 | const shdr = elf_file.shdrs.items[self.output_section_index]; | 50 | const shdr = elf_file.sections.items(.shdr)[self.output_section_index]; |
| 52 | return @as(i64, @intCast(shdr.sh_addr)) + self.value; | 51 | return @as(i64, @intCast(shdr.sh_addr)) + self.value; |
| 53 | } | 52 | } |
| 54 | 53 | ||
| 54 | pub fn ref(self: Atom) Elf.Ref { | ||
| 55 | return .{ .index = self.atom_index, .file = self.file_index }; | ||
| 56 | } | ||
| 57 | |||
| 58 | pub fn prevAtom(self: Atom, elf_file: *Elf) ?*Atom { | ||
| 59 | return elf_file.atom(self.prev_atom_ref); | ||
| 60 | } | ||
| 61 | |||
| 62 | pub fn nextAtom(self: Atom, elf_file: *Elf) ?*Atom { | ||
| 63 | return elf_file.atom(self.next_atom_ref); | ||
| 64 | } | ||
| 65 | |||
| 55 | pub fn debugTombstoneValue(self: Atom, target: Symbol, elf_file: *Elf) ?u64 { | 66 | pub fn debugTombstoneValue(self: Atom, target: Symbol, elf_file: *Elf) ?u64 { |
| 56 | if (target.mergeSubsection(elf_file)) |msub| { | 67 | if (target.mergeSubsection(elf_file)) |msub| { |
| 57 | if (msub.alive) return null; | 68 | if (msub.alive) return null; |
| ... | @@ -95,18 +106,16 @@ pub fn priority(self: Atom, elf_file: *Elf) u64 { | ... | @@ -95,18 +106,16 @@ pub fn priority(self: Atom, elf_file: *Elf) u64 { |
| 95 | /// File offset relocation happens transparently, so it is not included in | 106 | /// File offset relocation happens transparently, so it is not included in |
| 96 | /// this calculation. | 107 | /// this calculation. |
| 97 | pub fn capacity(self: Atom, elf_file: *Elf) u64 { | 108 | pub fn capacity(self: Atom, elf_file: *Elf) u64 { |
| 98 | const zo = elf_file.zigObjectPtr().?; | 109 | const next_addr = if (self.nextAtom(elf_file)) |next_atom| |
| 99 | const next_addr = if (zo.atom(self.next_index)) |next| | 110 | next_atom.address(elf_file) |
| 100 | next.address(elf_file) | ||
| 101 | else | 111 | else |
| 102 | std.math.maxInt(u32); | 112 | std.math.maxInt(u32); |
| 103 | return @intCast(next_addr - self.address(elf_file)); | 113 | return @intCast(next_addr - self.address(elf_file)); |
| 104 | } | 114 | } |
| 105 | 115 | ||
| 106 | pub fn freeListEligible(self: Atom, elf_file: *Elf) bool { | 116 | pub fn freeListEligible(self: Atom, elf_file: *Elf) bool { |
| 107 | const zo = elf_file.zigObjectPtr().?; | ||
| 108 | // No need to keep a free list node for the last block. | 117 | // No need to keep a free list node for the last block. |
| 109 | const next = zo.atom(self.next_index) orelse return false; | 118 | const next = self.nextAtom(elf_file) orelse return false; |
| 110 | const cap: u64 = @intCast(next.address(elf_file) - self.address(elf_file)); | 119 | const cap: u64 = @intCast(next.address(elf_file) - self.address(elf_file)); |
| 111 | const ideal_cap = Elf.padToIdeal(self.size); | 120 | const ideal_cap = Elf.padToIdeal(self.size); |
| 112 | if (cap <= ideal_cap) return false; | 121 | if (cap <= ideal_cap) return false; |
| ... | @@ -115,11 +124,10 @@ pub fn freeListEligible(self: Atom, elf_file: *Elf) bool { | ... | @@ -115,11 +124,10 @@ pub fn freeListEligible(self: Atom, elf_file: *Elf) bool { |
| 115 | } | 124 | } |
| 116 | 125 | ||
| 117 | pub fn allocate(self: *Atom, elf_file: *Elf) !void { | 126 | pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 118 | const zo = elf_file.zigObjectPtr().?; | 127 | const slice = elf_file.sections.slice(); |
| 119 | const shdr = &elf_file.shdrs.items[self.output_section_index]; | 128 | const shdr = &slice.items(.shdr)[self.output_section_index]; |
| 120 | const meta = elf_file.last_atom_and_free_list_table.getPtr(self.output_section_index).?; | 129 | const free_list = &slice.items(.free_list)[self.output_section_index]; |
| 121 | const free_list = &meta.free_list; | 130 | const last_atom_ref = &slice.items(.last_atom)[self.output_section_index]; |
| 122 | const last_atom_index = &meta.last_atom_index; | ||
| 123 | const new_atom_ideal_capacity = Elf.padToIdeal(self.size); | 131 | const new_atom_ideal_capacity = Elf.padToIdeal(self.size); |
| 124 | 132 | ||
| 125 | // We use these to indicate our intention to update metadata, placing the new atom, | 133 | // We use these to indicate our intention to update metadata, placing the new atom, |
| ... | @@ -127,7 +135,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { | ... | @@ -127,7 +135,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 127 | // It would be simpler to do it inside the for loop below, but that would cause a | 135 | // It would be simpler to do it inside the for loop below, but that would cause a |
| 128 | // problem if an error was returned later in the function. So this action | 136 | // problem if an error was returned later in the function. So this action |
| 129 | // is actually carried out at the end of the function, when errors are no longer possible. | 137 | // is actually carried out at the end of the function, when errors are no longer possible. |
| 130 | var atom_placement: ?Atom.Index = null; | 138 | var atom_placement: ?Elf.Ref = null; |
| 131 | var free_list_removal: ?usize = null; | 139 | var free_list_removal: ?usize = null; |
| 132 | 140 | ||
| 133 | // First we look for an appropriately sized free list node. | 141 | // First we look for an appropriately sized free list node. |
| ... | @@ -135,8 +143,8 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { | ... | @@ -135,8 +143,8 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 135 | self.value = blk: { | 143 | self.value = blk: { |
| 136 | var i: usize = if (elf_file.base.child_pid == null) 0 else free_list.items.len; | 144 | var i: usize = if (elf_file.base.child_pid == null) 0 else free_list.items.len; |
| 137 | while (i < free_list.items.len) { | 145 | while (i < free_list.items.len) { |
| 138 | const big_atom_index = free_list.items[i]; | 146 | const big_atom_ref = free_list.items[i]; |
| 139 | const big_atom = zo.atom(big_atom_index).?; | 147 | const big_atom = elf_file.atom(big_atom_ref).?; |
| 140 | // We now have a pointer to a live atom that has too much capacity. | 148 | // We now have a pointer to a live atom that has too much capacity. |
| 141 | // Is it enough that we could fit this new atom? | 149 | // Is it enough that we could fit this new atom? |
| 142 | const cap = big_atom.capacity(elf_file); | 150 | const cap = big_atom.capacity(elf_file); |
| ... | @@ -163,50 +171,52 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { | ... | @@ -163,50 +171,52 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 163 | const keep_free_list_node = remaining_capacity >= Elf.min_text_capacity; | 171 | const keep_free_list_node = remaining_capacity >= Elf.min_text_capacity; |
| 164 | 172 | ||
| 165 | // Set up the metadata to be updated, after errors are no longer possible. | 173 | // Set up the metadata to be updated, after errors are no longer possible. |
| 166 | atom_placement = big_atom_index; | 174 | atom_placement = big_atom_ref; |
| 167 | if (!keep_free_list_node) { | 175 | if (!keep_free_list_node) { |
| 168 | free_list_removal = i; | 176 | free_list_removal = i; |
| 169 | } | 177 | } |
| 170 | break :blk @intCast(new_start_vaddr); | 178 | break :blk @intCast(new_start_vaddr); |
| 171 | } else if (zo.atom(last_atom_index.*)) |last| { | 179 | } else if (elf_file.atom(last_atom_ref.*)) |last_atom| { |
| 172 | const ideal_capacity = Elf.padToIdeal(last.size); | 180 | const ideal_capacity = Elf.padToIdeal(last_atom.size); |
| 173 | const ideal_capacity_end_vaddr = @as(u64, @intCast(last.value)) + ideal_capacity; | 181 | const ideal_capacity_end_vaddr = @as(u64, @intCast(last_atom.value)) + ideal_capacity; |
| 174 | const new_start_vaddr = self.alignment.forward(ideal_capacity_end_vaddr); | 182 | const new_start_vaddr = self.alignment.forward(ideal_capacity_end_vaddr); |
| 175 | // Set up the metadata to be updated, after errors are no longer possible. | 183 | // Set up the metadata to be updated, after errors are no longer possible. |
| 176 | atom_placement = last.atom_index; | 184 | atom_placement = last_atom.ref(); |
| 177 | break :blk @intCast(new_start_vaddr); | 185 | break :blk @intCast(new_start_vaddr); |
| 178 | } else { | 186 | } else { |
| 179 | break :blk 0; | 187 | break :blk 0; |
| 180 | } | 188 | } |
| 181 | }; | 189 | }; |
| 182 | 190 | ||
| 183 | log.debug("allocated atom({d}) : '{s}' at 0x{x} to 0x{x}", .{ | 191 | log.debug("allocated atom({}) : '{s}' at 0x{x} to 0x{x}", .{ |
| 184 | self.atom_index, | 192 | self.ref(), |
| 185 | self.name(elf_file), | 193 | self.name(elf_file), |
| 186 | self.address(elf_file), | 194 | self.address(elf_file), |
| 187 | self.address(elf_file) + @as(i64, @intCast(self.size)), | 195 | self.address(elf_file) + @as(i64, @intCast(self.size)), |
| 188 | }); | 196 | }); |
| 189 | 197 | ||
| 190 | const expand_section = if (atom_placement) |placement_index| | 198 | const expand_section = if (atom_placement) |placement_ref| |
| 191 | zo.atom(placement_index).?.next_index == 0 | 199 | elf_file.atom(placement_ref).?.nextAtom(elf_file) == null |
| 192 | else | 200 | else |
| 193 | true; | 201 | true; |
| 194 | if (expand_section) { | 202 | if (expand_section) { |
| 195 | const needed_size: u64 = @intCast(self.value + @as(i64, @intCast(self.size))); | 203 | const needed_size: u64 = @intCast(self.value + @as(i64, @intCast(self.size))); |
| 196 | try elf_file.growAllocSection(self.output_section_index, needed_size); | 204 | try elf_file.growAllocSection(self.output_section_index, needed_size); |
| 197 | last_atom_index.* = self.atom_index; | 205 | last_atom_ref.* = self.ref(); |
| 198 | 206 | ||
| 199 | const zig_object = elf_file.zigObjectPtr().?; | 207 | switch (self.file(elf_file).?) { |
| 200 | if (zig_object.dwarf) |_| { | 208 | .zig_object => |zo| if (zo.dwarf) |_| { |
| 201 | // The .debug_info section has `low_pc` and `high_pc` values which is the virtual address | 209 | // The .debug_info section has `low_pc` and `high_pc` values which is the virtual address |
| 202 | // range of the compilation unit. When we expand the text section, this range changes, | 210 | // range of the compilation unit. When we expand the text section, this range changes, |
| 203 | // so the DW_TAG.compile_unit tag of the .debug_info section becomes dirty. | 211 | // so the DW_TAG.compile_unit tag of the .debug_info section becomes dirty. |
| 204 | zig_object.debug_info_section_dirty = true; | 212 | zo.debug_info_section_dirty = true; |
| 205 | // This becomes dirty for the same reason. We could potentially make this more | 213 | // This becomes dirty for the same reason. We could potentially make this more |
| 206 | // fine-grained with the addition of support for more compilation units. It is planned to | 214 | // fine-grained with the addition of support for more compilation units. It is planned to |
| 207 | // model each package as a different compilation unit. | 215 | // model each package as a different compilation unit. |
| 208 | zig_object.debug_aranges_section_dirty = true; | 216 | zo.debug_aranges_section_dirty = true; |
| 209 | zig_object.debug_rnglists_section_dirty = true; | 217 | zo.debug_rnglists_section_dirty = true; |
| 218 | }, | ||
| 219 | else => {}, | ||
| 210 | } | 220 | } |
| 211 | } | 221 | } |
| 212 | shdr.sh_addralign = @max(shdr.sh_addralign, self.alignment.toByteUnits().?); | 222 | shdr.sh_addralign = @max(shdr.sh_addralign, self.alignment.toByteUnits().?); |
| ... | @@ -214,21 +224,21 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { | ... | @@ -214,21 +224,21 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 214 | // This function can also reallocate an atom. | 224 | // This function can also reallocate an atom. |
| 215 | // In this case we need to "unplug" it from its previous location before | 225 | // In this case we need to "unplug" it from its previous location before |
| 216 | // plugging it in to its new location. | 226 | // plugging it in to its new location. |
| 217 | if (zo.atom(self.prev_index)) |prev| { | 227 | if (self.prevAtom(elf_file)) |prev| { |
| 218 | prev.next_index = self.next_index; | 228 | prev.next_atom_ref = self.next_atom_ref; |
| 219 | } | 229 | } |
| 220 | if (zo.atom(self.next_index)) |next| { | 230 | if (self.nextAtom(elf_file)) |next| { |
| 221 | next.prev_index = self.prev_index; | 231 | next.prev_atom_ref = self.prev_atom_ref; |
| 222 | } | 232 | } |
| 223 | 233 | ||
| 224 | if (atom_placement) |big_atom_index| { | 234 | if (atom_placement) |big_atom_ref| { |
| 225 | const big_atom = zo.atom(big_atom_index).?; | 235 | const big_atom = elf_file.atom(big_atom_ref).?; |
| 226 | self.prev_index = big_atom_index; | 236 | self.prev_atom_ref = big_atom_ref; |
| 227 | self.next_index = big_atom.next_index; | 237 | self.next_atom_ref = big_atom.next_atom_ref; |
| 228 | big_atom.next_index = self.atom_index; | 238 | big_atom.next_atom_ref = self.ref(); |
| 229 | } else { | 239 | } else { |
| 230 | self.prev_index = 0; | 240 | self.prev_atom_ref = .{ .index = 0, .file = 0 }; |
| 231 | self.next_index = 0; | 241 | self.next_atom_ref = .{ .index = 0, .file = 0 }; |
| 232 | } | 242 | } |
| 233 | if (free_list_removal) |i| { | 243 | if (free_list_removal) |i| { |
| 234 | _ = free_list.swapRemove(i); | 244 | _ = free_list.swapRemove(i); |
| ... | @@ -248,64 +258,70 @@ pub fn grow(self: *Atom, elf_file: *Elf) !void { | ... | @@ -248,64 +258,70 @@ pub fn grow(self: *Atom, elf_file: *Elf) !void { |
| 248 | } | 258 | } |
| 249 | 259 | ||
| 250 | pub fn free(self: *Atom, elf_file: *Elf) void { | 260 | pub fn free(self: *Atom, elf_file: *Elf) void { |
| 251 | log.debug("freeAtom {d} ({s})", .{ self.atom_index, self.name(elf_file) }); | 261 | log.debug("freeAtom atom({}) ({s})", .{ self.ref(), self.name(elf_file) }); |
| 252 | 262 | ||
| 253 | const zo = elf_file.zigObjectPtr().?; | ||
| 254 | const comp = elf_file.base.comp; | 263 | const comp = elf_file.base.comp; |
| 255 | const gpa = comp.gpa; | 264 | const gpa = comp.gpa; |
| 256 | const shndx = self.output_section_index; | 265 | const shndx = self.output_section_index; |
| 257 | const meta = elf_file.last_atom_and_free_list_table.getPtr(shndx).?; | 266 | const slice = elf_file.sections.slice(); |
| 258 | const free_list = &meta.free_list; | 267 | const free_list = &slice.items(.free_list)[shndx]; |
| 259 | const last_atom_index = &meta.last_atom_index; | 268 | const last_atom_ref = &slice.items(.last_atom)[shndx]; |
| 260 | var already_have_free_list_node = false; | 269 | var already_have_free_list_node = false; |
| 261 | { | 270 | { |
| 262 | var i: usize = 0; | 271 | var i: usize = 0; |
| 263 | // TODO turn free_list into a hash map | 272 | // TODO turn free_list into a hash map |
| 264 | while (i < free_list.items.len) { | 273 | while (i < free_list.items.len) { |
| 265 | if (free_list.items[i] == self.atom_index) { | 274 | if (free_list.items[i].eql(self.ref())) { |
| 266 | _ = free_list.swapRemove(i); | 275 | _ = free_list.swapRemove(i); |
| 267 | continue; | 276 | continue; |
| 268 | } | 277 | } |
| 269 | if (free_list.items[i] == self.prev_index) { | 278 | if (self.prevAtom(elf_file)) |prev_atom| { |
| 270 | already_have_free_list_node = true; | 279 | if (free_list.items[i].eql(prev_atom.ref())) { |
| 280 | already_have_free_list_node = true; | ||
| 281 | } | ||
| 271 | } | 282 | } |
| 272 | i += 1; | 283 | i += 1; |
| 273 | } | 284 | } |
| 274 | } | 285 | } |
| 275 | 286 | ||
| 276 | if (zo.atom(last_atom_index.*)) |last_atom| { | 287 | if (elf_file.atom(last_atom_ref.*)) |last_atom| { |
| 277 | if (last_atom.atom_index == self.atom_index) { | 288 | if (last_atom.ref().eql(self.ref())) { |
| 278 | if (zo.atom(self.prev_index)) |_| { | 289 | if (self.prevAtom(elf_file)) |prev_atom| { |
| 279 | // TODO shrink the section size here | 290 | // TODO shrink the section size here |
| 280 | last_atom_index.* = self.prev_index; | 291 | last_atom_ref.* = prev_atom.ref(); |
| 281 | } else { | 292 | } else { |
| 282 | last_atom_index.* = 0; | 293 | last_atom_ref.* = .{}; |
| 283 | } | 294 | } |
| 284 | } | 295 | } |
| 285 | } | 296 | } |
| 286 | 297 | ||
| 287 | if (zo.atom(self.prev_index)) |prev| { | 298 | if (self.prevAtom(elf_file)) |prev_atom| { |
| 288 | prev.next_index = self.next_index; | 299 | prev_atom.next_atom_ref = self.next_atom_ref; |
| 289 | if (!already_have_free_list_node and prev.*.freeListEligible(elf_file)) { | 300 | if (!already_have_free_list_node and prev_atom.*.freeListEligible(elf_file)) { |
| 290 | // The free list is heuristics, it doesn't have to be perfect, so we can | 301 | // The free list is heuristics, it doesn't have to be perfect, so we can |
| 291 | // ignore the OOM here. | 302 | // ignore the OOM here. |
| 292 | free_list.append(gpa, prev.atom_index) catch {}; | 303 | free_list.append(gpa, prev_atom.ref()) catch {}; |
| 293 | } | 304 | } |
| 294 | } else { | 305 | } else { |
| 295 | self.prev_index = 0; | 306 | self.prev_atom_ref = .{}; |
| 296 | } | 307 | } |
| 297 | 308 | ||
| 298 | if (zo.atom(self.next_index)) |next| { | 309 | if (self.nextAtom(elf_file)) |next_atom| { |
| 299 | next.prev_index = self.prev_index; | 310 | next_atom.prev_atom_ref = self.prev_atom_ref; |
| 300 | } else { | 311 | } else { |
| 301 | self.next_index = 0; | 312 | self.next_atom_ref = .{}; |
| 302 | } | 313 | } |
| 303 | 314 | ||
| 304 | // TODO create relocs free list | 315 | switch (self.file(elf_file).?) { |
| 305 | self.freeRelocs(zo); | 316 | .zig_object => |zo| { |
| 306 | // TODO figure out how to free input section mappind in ZigModule | 317 | // TODO create relocs free list |
| 307 | // const zig_object = elf_file.zigObjectPtr().? | 318 | self.freeRelocs(zo); |
| 308 | // assert(zig_object.atoms.swapRemove(self.atom_index)); | 319 | // TODO figure out how to free input section mappind in ZigModule |
| 320 | // const zig_object = elf_file.zigObjectPtr().? | ||
| 321 | // assert(zig_object.atoms.swapRemove(self.atom_index)); | ||
| 322 | }, | ||
| 323 | else => {}, | ||
| 324 | } | ||
| 309 | self.* = .{}; | 325 | self.* = .{}; |
| 310 | } | 326 | } |
| 311 | 327 | ||
| ... | @@ -336,10 +352,7 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El | ... | @@ -336,10 +352,7 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El |
| 336 | switch (target.type(elf_file)) { | 352 | switch (target.type(elf_file)) { |
| 337 | elf.STT_SECTION => { | 353 | elf.STT_SECTION => { |
| 338 | r_addend += @intCast(target.address(.{}, elf_file)); | 354 | r_addend += @intCast(target.address(.{}, elf_file)); |
| 339 | r_sym = if (target.outputShndx(elf_file)) |osec| | 355 | r_sym = target.outputShndx(elf_file) orelse 0; |
| 340 | elf_file.sectionSymbolOutputSymtabIndex(osec) | ||
| 341 | else | ||
| 342 | 0; | ||
| 343 | }, | 356 | }, |
| 344 | else => { | 357 | else => { |
| 345 | r_sym = target.outputSymtabIndex(elf_file) orelse 0; | 358 | r_sym = target.outputSymtabIndex(elf_file) orelse 0; |
src/link/Elf/LinkerDefined.zig+17-15| ... | @@ -129,9 +129,10 @@ pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void { | ... | @@ -129,9 +129,10 @@ pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void { |
| 129 | 129 | ||
| 130 | pub fn initStartStopSymbols(self: *LinkerDefined, elf_file: *Elf) !void { | 130 | pub fn initStartStopSymbols(self: *LinkerDefined, elf_file: *Elf) !void { |
| 131 | const gpa = elf_file.base.comp.gpa; | 131 | const gpa = elf_file.base.comp.gpa; |
| 132 | const slice = elf_file.sections.slice(); | ||
| 132 | 133 | ||
| 133 | var nsyms: usize = 0; | 134 | var nsyms: usize = 0; |
| 134 | for (elf_file.shdrs.items) |shdr| { | 135 | for (slice.items(.shdr)) |shdr| { |
| 135 | if (elf_file.getStartStopBasename(shdr)) |_| { | 136 | if (elf_file.getStartStopBasename(shdr)) |_| { |
| 136 | nsyms += 2; // __start_, __stop_ | 137 | nsyms += 2; // __start_, __stop_ |
| 137 | } | 138 | } |
| ... | @@ -143,7 +144,7 @@ pub fn initStartStopSymbols(self: *LinkerDefined, elf_file: *Elf) !void { | ... | @@ -143,7 +144,7 @@ pub fn initStartStopSymbols(self: *LinkerDefined, elf_file: *Elf) !void { |
| 143 | try self.symbols_extra.ensureUnusedCapacity(gpa, nsyms * @sizeOf(Symbol.Extra)); | 144 | try self.symbols_extra.ensureUnusedCapacity(gpa, nsyms * @sizeOf(Symbol.Extra)); |
| 144 | try self.symbols_resolver.ensureUnusedCapacity(gpa, nsyms); | 145 | try self.symbols_resolver.ensureUnusedCapacity(gpa, nsyms); |
| 145 | 146 | ||
| 146 | for (elf_file.shdrs.items) |shdr| { | 147 | for (slice.items(.shdr)) |shdr| { |
| 147 | if (elf_file.getStartStopBasename(shdr)) |name| { | 148 | if (elf_file.getStartStopBasename(shdr)) |name| { |
| 148 | const start_name = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name}); | 149 | const start_name = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name}); |
| 149 | defer gpa.free(start_name); | 150 | defer gpa.free(start_name); |
| ... | @@ -193,6 +194,7 @@ pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) !void { | ... | @@ -193,6 +194,7 @@ pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) !void { |
| 193 | pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { | 194 | pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { |
| 194 | const comp = elf_file.base.comp; | 195 | const comp = elf_file.base.comp; |
| 195 | const link_mode = comp.config.link_mode; | 196 | const link_mode = comp.config.link_mode; |
| 197 | const shdrs = elf_file.sections.items(.shdr); | ||
| 196 | 198 | ||
| 197 | const allocSymbol = struct { | 199 | const allocSymbol = struct { |
| 198 | fn allocSymbol(ld: *LinkerDefined, index: Symbol.Index, value: u64, osec: u32, ef: *Elf) void { | 200 | fn allocSymbol(ld: *LinkerDefined, index: Symbol.Index, value: u64, osec: u32, ef: *Elf) void { |
| ... | @@ -204,7 +206,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { | ... | @@ -204,7 +206,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { |
| 204 | 206 | ||
| 205 | // _DYNAMIC | 207 | // _DYNAMIC |
| 206 | if (elf_file.dynamic_section_index) |shndx| { | 208 | if (elf_file.dynamic_section_index) |shndx| { |
| 207 | const shdr = &elf_file.shdrs.items[shndx]; | 209 | const shdr = shdrs[shndx]; |
| 208 | allocSymbol(self, self.dynamic_index.?, shdr.sh_addr, shndx, elf_file); | 210 | allocSymbol(self, self.dynamic_index.?, shdr.sh_addr, shndx, elf_file); |
| 209 | } | 211 | } |
| 210 | 212 | ||
| ... | @@ -213,21 +215,21 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { | ... | @@ -213,21 +215,21 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { |
| 213 | 215 | ||
| 214 | // __init_array_start, __init_array_end | 216 | // __init_array_start, __init_array_end |
| 215 | if (elf_file.sectionByName(".init_array")) |shndx| { | 217 | if (elf_file.sectionByName(".init_array")) |shndx| { |
| 216 | const shdr = &elf_file.shdrs.items[shndx]; | 218 | const shdr = shdrs[shndx]; |
| 217 | allocSymbol(self, self.init_array_start_index.?, shdr.sh_addr, shndx, elf_file); | 219 | allocSymbol(self, self.init_array_start_index.?, shdr.sh_addr, shndx, elf_file); |
| 218 | allocSymbol(self, self.init_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file); | 220 | allocSymbol(self, self.init_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file); |
| 219 | } | 221 | } |
| 220 | 222 | ||
| 221 | // __fini_array_start, __fini_array_end | 223 | // __fini_array_start, __fini_array_end |
| 222 | if (elf_file.sectionByName(".fini_array")) |shndx| { | 224 | if (elf_file.sectionByName(".fini_array")) |shndx| { |
| 223 | const shdr = &elf_file.shdrs.items[shndx]; | 225 | const shdr = shdrs[shndx]; |
| 224 | allocSymbol(self, self.fini_array_start_index.?, shdr.sh_addr, shndx, elf_file); | 226 | allocSymbol(self, self.fini_array_start_index.?, shdr.sh_addr, shndx, elf_file); |
| 225 | allocSymbol(self, self.fini_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file); | 227 | allocSymbol(self, self.fini_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file); |
| 226 | } | 228 | } |
| 227 | 229 | ||
| 228 | // __preinit_array_start, __preinit_array_end | 230 | // __preinit_array_start, __preinit_array_end |
| 229 | if (elf_file.sectionByName(".preinit_array")) |shndx| { | 231 | if (elf_file.sectionByName(".preinit_array")) |shndx| { |
| 230 | const shdr = &elf_file.shdrs.items[shndx]; | 232 | const shdr = shdrs[shndx]; |
| 231 | allocSymbol(self, self.preinit_array_start_index.?, shdr.sh_addr, shndx, elf_file); | 233 | allocSymbol(self, self.preinit_array_start_index.?, shdr.sh_addr, shndx, elf_file); |
| 232 | allocSymbol(self, self.preinit_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file); | 234 | allocSymbol(self, self.preinit_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file); |
| 233 | } | 235 | } |
| ... | @@ -235,38 +237,38 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { | ... | @@ -235,38 +237,38 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { |
| 235 | // _GLOBAL_OFFSET_TABLE_ | 237 | // _GLOBAL_OFFSET_TABLE_ |
| 236 | if (elf_file.getTarget().cpu.arch == .x86_64) { | 238 | if (elf_file.getTarget().cpu.arch == .x86_64) { |
| 237 | if (elf_file.got_plt_section_index) |shndx| { | 239 | if (elf_file.got_plt_section_index) |shndx| { |
| 238 | const shdr = elf_file.shdrs.items[shndx]; | 240 | const shdr = shdrs[shndx]; |
| 239 | allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file); | 241 | allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file); |
| 240 | } | 242 | } |
| 241 | } else { | 243 | } else { |
| 242 | if (elf_file.got_section_index) |shndx| { | 244 | if (elf_file.got_section_index) |shndx| { |
| 243 | const shdr = elf_file.shdrs.items[shndx]; | 245 | const shdr = shdrs[shndx]; |
| 244 | allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file); | 246 | allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file); |
| 245 | } | 247 | } |
| 246 | } | 248 | } |
| 247 | 249 | ||
| 248 | // _PROCEDURE_LINKAGE_TABLE_ | 250 | // _PROCEDURE_LINKAGE_TABLE_ |
| 249 | if (elf_file.plt_section_index) |shndx| { | 251 | if (elf_file.plt_section_index) |shndx| { |
| 250 | const shdr = &elf_file.shdrs.items[shndx]; | 252 | const shdr = shdrs[shndx]; |
| 251 | allocSymbol(self, self.plt_index.?, shdr.sh_addr, shndx, elf_file); | 253 | allocSymbol(self, self.plt_index.?, shdr.sh_addr, shndx, elf_file); |
| 252 | } | 254 | } |
| 253 | 255 | ||
| 254 | // __dso_handle | 256 | // __dso_handle |
| 255 | if (self.dso_handle_index) |index| { | 257 | if (self.dso_handle_index) |index| { |
| 256 | const shdr = &elf_file.shdrs.items[1]; | 258 | const shdr = shdrs[1]; |
| 257 | allocSymbol(self, index, shdr.sh_addr, 0, elf_file); | 259 | allocSymbol(self, index, shdr.sh_addr, 0, elf_file); |
| 258 | } | 260 | } |
| 259 | 261 | ||
| 260 | // __GNU_EH_FRAME_HDR | 262 | // __GNU_EH_FRAME_HDR |
| 261 | if (elf_file.eh_frame_hdr_section_index) |shndx| { | 263 | if (elf_file.eh_frame_hdr_section_index) |shndx| { |
| 262 | const shdr = &elf_file.shdrs.items[shndx]; | 264 | const shdr = shdrs[shndx]; |
| 263 | allocSymbol(self, self.gnu_eh_frame_hdr_index.?, shdr.sh_addr, shndx, elf_file); | 265 | allocSymbol(self, self.gnu_eh_frame_hdr_index.?, shdr.sh_addr, shndx, elf_file); |
| 264 | } | 266 | } |
| 265 | 267 | ||
| 266 | // __rela_iplt_start, __rela_iplt_end | 268 | // __rela_iplt_start, __rela_iplt_end |
| 267 | if (elf_file.rela_dyn_section_index) |shndx| blk: { | 269 | if (elf_file.rela_dyn_section_index) |shndx| blk: { |
| 268 | if (link_mode != .static or comp.config.pie) break :blk; | 270 | if (link_mode != .static or comp.config.pie) break :blk; |
| 269 | const shdr = &elf_file.shdrs.items[shndx]; | 271 | const shdr = shdrs[shndx]; |
| 270 | const end_addr = shdr.sh_addr + shdr.sh_size; | 272 | const end_addr = shdr.sh_addr + shdr.sh_size; |
| 271 | const start_addr = end_addr - elf_file.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela); | 273 | const start_addr = end_addr - elf_file.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela); |
| 272 | allocSymbol(self, self.rela_iplt_start_index.?, start_addr, shndx, elf_file); | 274 | allocSymbol(self, self.rela_iplt_start_index.?, start_addr, shndx, elf_file); |
| ... | @@ -277,7 +279,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { | ... | @@ -277,7 +279,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { |
| 277 | { | 279 | { |
| 278 | var value: u64 = 0; | 280 | var value: u64 = 0; |
| 279 | var osec: u32 = 0; | 281 | var osec: u32 = 0; |
| 280 | for (elf_file.shdrs.items, 0..) |shdr, shndx| { | 282 | for (shdrs, 0..) |shdr, shndx| { |
| 281 | if (shdr.sh_flags & elf.SHF_ALLOC != 0) { | 283 | if (shdr.sh_flags & elf.SHF_ALLOC != 0) { |
| 282 | value = shdr.sh_addr + shdr.sh_size; | 284 | value = shdr.sh_addr + shdr.sh_size; |
| 283 | osec = @intCast(shndx); | 285 | osec = @intCast(shndx); |
| ... | @@ -289,7 +291,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { | ... | @@ -289,7 +291,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { |
| 289 | // __global_pointer$ | 291 | // __global_pointer$ |
| 290 | if (self.global_pointer_index) |index| { | 292 | if (self.global_pointer_index) |index| { |
| 291 | const value, const osec = if (elf_file.sectionByName(".sdata")) |shndx| .{ | 293 | const value, const osec = if (elf_file.sectionByName(".sdata")) |shndx| .{ |
| 292 | elf_file.shdrs.items[shndx].sh_addr + 0x800, | 294 | shdrs[shndx].sh_addr + 0x800, |
| 293 | shndx, | 295 | shndx, |
| 294 | } else .{ 0, 0 }; | 296 | } else .{ 0, 0 }; |
| 295 | allocSymbol(self, index, value, osec, elf_file); | 297 | allocSymbol(self, index, value, osec, elf_file); |
| ... | @@ -305,7 +307,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { | ... | @@ -305,7 +307,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { |
| 305 | const stop_ref = self.resolveSymbol(self.start_stop_indexes.items[index + 1], elf_file); | 307 | const stop_ref = self.resolveSymbol(self.start_stop_indexes.items[index + 1], elf_file); |
| 306 | const stop = elf_file.symbol(stop_ref).?; | 308 | const stop = elf_file.symbol(stop_ref).?; |
| 307 | const shndx = elf_file.sectionByName(name["__start_".len..]).?; | 309 | const shndx = elf_file.sectionByName(name["__start_".len..]).?; |
| 308 | const shdr = &elf_file.shdrs.items[shndx]; | 310 | const shdr = shdrs[shndx]; |
| 309 | start.value = @intCast(shdr.sh_addr); | 311 | start.value = @intCast(shdr.sh_addr); |
| 310 | start.output_section_index = shndx; | 312 | start.output_section_index = shndx; |
| 311 | stop.value = @intCast(shdr.sh_addr + shdr.sh_size); | 313 | stop.value = @intCast(shdr.sh_addr + shdr.sh_size); |
src/link/Elf/Object.zig+9-11| ... | @@ -998,9 +998,8 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void { | ... | @@ -998,9 +998,8 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void { |
| 998 | 998 | ||
| 999 | const comp = elf_file.base.comp; | 999 | const comp = elf_file.base.comp; |
| 1000 | const gpa = comp.gpa; | 1000 | const gpa = comp.gpa; |
| 1001 | const gop = try elf_file.output_sections.getOrPut(gpa, atom_ptr.output_section_index); | 1001 | const atom_list = &elf_file.sections.items(.atom_list)[atom_ptr.output_section_index]; |
| 1002 | if (!gop.found_existing) gop.value_ptr.* = .{}; | 1002 | try atom_list.append(gpa, .{ .index = atom_index, .file = self.index }); |
| 1003 | try gop.value_ptr.append(gpa, .{ .index = atom_index, .file = self.index }); | ||
| 1004 | } | 1003 | } |
| 1005 | } | 1004 | } |
| 1006 | 1005 | ||
| ... | @@ -1011,7 +1010,8 @@ pub fn initRelaSections(self: *Object, elf_file: *Elf) !void { | ... | @@ -1011,7 +1010,8 @@ pub fn initRelaSections(self: *Object, elf_file: *Elf) !void { |
| 1011 | const shndx = atom_ptr.relocsShndx() orelse continue; | 1010 | const shndx = atom_ptr.relocsShndx() orelse continue; |
| 1012 | const shdr = self.shdrs.items[shndx]; | 1011 | const shdr = self.shdrs.items[shndx]; |
| 1013 | const out_shndx = try self.initOutputSection(elf_file, shdr); | 1012 | const out_shndx = try self.initOutputSection(elf_file, shdr); |
| 1014 | const out_shdr = &elf_file.shdrs.items[out_shndx]; | 1013 | const out_shdr = &elf_file.sections.items(.shdr)[out_shndx]; |
| 1014 | out_shdr.sh_type = elf.SHT_RELA; | ||
| 1015 | out_shdr.sh_addralign = @alignOf(elf.Elf64_Rela); | 1015 | out_shdr.sh_addralign = @alignOf(elf.Elf64_Rela); |
| 1016 | out_shdr.sh_entsize = @sizeOf(elf.Elf64_Rela); | 1016 | out_shdr.sh_entsize = @sizeOf(elf.Elf64_Rela); |
| 1017 | out_shdr.sh_flags |= elf.SHF_INFO_LINK; | 1017 | out_shdr.sh_flags |= elf.SHF_INFO_LINK; |
| ... | @@ -1027,15 +1027,13 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void { | ... | @@ -1027,15 +1027,13 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void { |
| 1027 | const shdr = self.shdrs.items[shndx]; | 1027 | const shdr = self.shdrs.items[shndx]; |
| 1028 | break :blk self.initOutputSection(elf_file, shdr) catch unreachable; | 1028 | break :blk self.initOutputSection(elf_file, shdr) catch unreachable; |
| 1029 | }; | 1029 | }; |
| 1030 | const shdr = &elf_file.shdrs.items[shndx]; | 1030 | const slice = elf_file.sections.slice(); |
| 1031 | const shdr = &slice.items(.shdr)[shndx]; | ||
| 1031 | shdr.sh_info = atom_ptr.output_section_index; | 1032 | shdr.sh_info = atom_ptr.output_section_index; |
| 1032 | shdr.sh_link = elf_file.symtab_section_index.?; | 1033 | shdr.sh_link = elf_file.symtab_section_index.?; |
| 1033 | 1034 | const gpa = elf_file.base.comp.gpa; | |
| 1034 | const comp = elf_file.base.comp; | 1035 | const atom_list = &elf_file.sections.items(.atom_list)[shndx]; |
| 1035 | const gpa = comp.gpa; | 1036 | try atom_list.append(gpa, .{ .index = atom_index, .file = self.index }); |
| 1036 | const gop = try elf_file.output_rela_sections.getOrPut(gpa, atom_ptr.output_section_index); | ||
| 1037 | if (!gop.found_existing) gop.value_ptr.* = .{ .shndx = shndx }; | ||
| 1038 | try gop.value_ptr.atom_list.append(gpa, .{ .index = atom_index, .file = self.index }); | ||
| 1039 | } | 1037 | } |
| 1040 | } | 1038 | } |
| 1041 | 1039 |
src/link/Elf/Symbol.zig+7-7| ... | @@ -11,7 +11,7 @@ file_index: File.Index = 0, | ... | @@ -11,7 +11,7 @@ file_index: File.Index = 0, |
| 11 | 11 | ||
| 12 | /// Reference to Atom or merge subsection containing this symbol if any. | 12 | /// Reference to Atom or merge subsection containing this symbol if any. |
| 13 | /// Use `atom` or `mergeSubsection` to get the pointer to the atom. | 13 | /// Use `atom` or `mergeSubsection` to get the pointer to the atom. |
| 14 | ref: Elf.Ref = .{ .index = 0, .file = 0 }, | 14 | ref: Elf.Ref = .{}, |
| 15 | 15 | ||
| 16 | /// Assigned output section index for this symbol. | 16 | /// Assigned output section index for this symbol. |
| 17 | output_section_index: u32 = 0, | 17 | output_section_index: u32 = 0, |
| ... | @@ -126,7 +126,7 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true, trampoline: bool | ... | @@ -126,7 +126,7 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true, trampoline: bool |
| 126 | const sym_name = symbol.name(elf_file); | 126 | const sym_name = symbol.name(elf_file); |
| 127 | const sh_addr, const sh_size = blk: { | 127 | const sh_addr, const sh_size = blk: { |
| 128 | const shndx = elf_file.eh_frame_section_index orelse break :blk .{ 0, 0 }; | 128 | const shndx = elf_file.eh_frame_section_index orelse break :blk .{ 0, 0 }; |
| 129 | const shdr = elf_file.shdrs.items[shndx]; | 129 | const shdr = elf_file.sections.items(.shdr)[shndx]; |
| 130 | break :blk .{ shdr.sh_addr, shdr.sh_size }; | 130 | break :blk .{ shdr.sh_addr, shdr.sh_size }; |
| 131 | }; | 131 | }; |
| 132 | if (mem.startsWith(u8, sym_name, "__EH_FRAME_BEGIN__") or | 132 | if (mem.startsWith(u8, sym_name, "__EH_FRAME_BEGIN__") or |
| ... | @@ -173,7 +173,7 @@ pub fn gotAddress(symbol: Symbol, elf_file: *Elf) i64 { | ... | @@ -173,7 +173,7 @@ pub fn gotAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 173 | pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 { | 173 | pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 174 | if (!(symbol.flags.has_plt and symbol.flags.has_got)) return 0; | 174 | if (!(symbol.flags.has_plt and symbol.flags.has_got)) return 0; |
| 175 | const extras = symbol.extra(elf_file); | 175 | const extras = symbol.extra(elf_file); |
| 176 | const shdr = elf_file.shdrs.items[elf_file.plt_got_section_index.?]; | 176 | const shdr = elf_file.sections.items(.shdr)[elf_file.plt_got_section_index.?]; |
| 177 | const cpu_arch = elf_file.getTarget().cpu.arch; | 177 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 178 | return @intCast(shdr.sh_addr + extras.plt_got * PltGotSection.entrySize(cpu_arch)); | 178 | return @intCast(shdr.sh_addr + extras.plt_got * PltGotSection.entrySize(cpu_arch)); |
| 179 | } | 179 | } |
| ... | @@ -181,7 +181,7 @@ pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 { | ... | @@ -181,7 +181,7 @@ pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 181 | pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 { | 181 | pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 182 | if (!symbol.flags.has_plt) return 0; | 182 | if (!symbol.flags.has_plt) return 0; |
| 183 | const extras = symbol.extra(elf_file); | 183 | const extras = symbol.extra(elf_file); |
| 184 | const shdr = elf_file.shdrs.items[elf_file.plt_section_index.?]; | 184 | const shdr = elf_file.sections.items(.shdr)[elf_file.plt_section_index.?]; |
| 185 | const cpu_arch = elf_file.getTarget().cpu.arch; | 185 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 186 | return @intCast(shdr.sh_addr + extras.plt * PltSection.entrySize(cpu_arch) + PltSection.preambleSize(cpu_arch)); | 186 | return @intCast(shdr.sh_addr + extras.plt * PltSection.entrySize(cpu_arch) + PltSection.preambleSize(cpu_arch)); |
| 187 | } | 187 | } |
| ... | @@ -189,13 +189,13 @@ pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 { | ... | @@ -189,13 +189,13 @@ pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 189 | pub fn gotPltAddress(symbol: Symbol, elf_file: *Elf) i64 { | 189 | pub fn gotPltAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 190 | if (!symbol.flags.has_plt) return 0; | 190 | if (!symbol.flags.has_plt) return 0; |
| 191 | const extras = symbol.extra(elf_file); | 191 | const extras = symbol.extra(elf_file); |
| 192 | const shdr = elf_file.shdrs.items[elf_file.got_plt_section_index.?]; | 192 | const shdr = elf_file.sections.items(.shdr)[elf_file.got_plt_section_index.?]; |
| 193 | return @intCast(shdr.sh_addr + extras.plt * 8 + GotPltSection.preamble_size); | 193 | return @intCast(shdr.sh_addr + extras.plt * 8 + GotPltSection.preamble_size); |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | pub fn copyRelAddress(symbol: Symbol, elf_file: *Elf) i64 { | 196 | pub fn copyRelAddress(symbol: Symbol, elf_file: *Elf) i64 { |
| 197 | if (!symbol.flags.has_copy_rel) return 0; | 197 | if (!symbol.flags.has_copy_rel) return 0; |
| 198 | const shdr = elf_file.shdrs.items[elf_file.copy_rel_section_index.?]; | 198 | const shdr = elf_file.sections.items(.shdr)[elf_file.copy_rel_section_index.?]; |
| 199 | return @as(i64, @intCast(shdr.sh_addr)) + symbol.value; | 199 | return @as(i64, @intCast(shdr.sh_addr)) + symbol.value; |
| 200 | } | 200 | } |
| 201 | 201 | ||
| ... | @@ -300,7 +300,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void { | ... | @@ -300,7 +300,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void { |
| 300 | break :blk 0; | 300 | break :blk 0; |
| 301 | } | 301 | } |
| 302 | if (st_shndx == elf.SHN_ABS or st_shndx == elf.SHN_COMMON) break :blk symbol.address(.{ .plt = false }, elf_file); | 302 | if (st_shndx == elf.SHN_ABS or st_shndx == elf.SHN_COMMON) break :blk symbol.address(.{ .plt = false }, elf_file); |
| 303 | const shdr = elf_file.shdrs.items[st_shndx]; | 303 | const shdr = elf_file.sections.items(.shdr)[st_shndx]; |
| 304 | if (shdr.sh_flags & elf.SHF_TLS != 0 and file_ptr != .linker_defined) | 304 | if (shdr.sh_flags & elf.SHF_TLS != 0 and file_ptr != .linker_defined) |
| 305 | break :blk symbol.address(.{ .plt = false }, elf_file) - elf_file.tlsAddress(); | 305 | break :blk symbol.address(.{ .plt = false }, elf_file) - elf_file.tlsAddress(); |
| 306 | break :blk symbol.address(.{ .plt = false, .trampoline = false }, elf_file); | 306 | break :blk symbol.address(.{ .plt = false, .trampoline = false }, elf_file); |
src/link/Elf/ZigObject.zig+310-38| ... | @@ -63,24 +63,300 @@ pub const global_symbol_bit: u32 = 0x80000000; | ... | @@ -63,24 +63,300 @@ pub const global_symbol_bit: u32 = 0x80000000; |
| 63 | pub const symbol_mask: u32 = 0x7fffffff; | 63 | pub const symbol_mask: u32 = 0x7fffffff; |
| 64 | pub const SHN_ATOM: u16 = 0x100; | 64 | pub const SHN_ATOM: u16 = 0x100; |
| 65 | 65 | ||
| 66 | pub fn init(self: *ZigObject, elf_file: *Elf) !void { | 66 | const InitOptions = struct { |
| 67 | symbol_count_hint: u64, | ||
| 68 | program_code_size_hint: u64, | ||
| 69 | }; | ||
| 70 | |||
| 71 | pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { | ||
| 67 | const comp = elf_file.base.comp; | 72 | const comp = elf_file.base.comp; |
| 68 | const gpa = comp.gpa; | 73 | const gpa = comp.gpa; |
| 74 | const ptr_size = elf_file.ptrWidthBytes(); | ||
| 75 | const target = elf_file.getTarget(); | ||
| 76 | const ptr_bit_width = target.ptrBitWidth(); | ||
| 69 | 77 | ||
| 70 | try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) }); // null input section | 78 | try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) }); // null input section |
| 71 | try self.relocs.append(gpa, .{}); // null relocs section | 79 | try self.relocs.append(gpa, .{}); // null relocs section |
| 72 | try self.strtab.buffer.append(gpa, 0); | 80 | try self.strtab.buffer.append(gpa, 0); |
| 73 | 81 | ||
| 74 | const name_off = try self.strtab.insert(gpa, self.path); | 82 | { |
| 75 | const symbol_index = try self.newLocalSymbol(gpa, name_off); | 83 | const name_off = try self.strtab.insert(gpa, self.path); |
| 76 | const sym = self.symbol(symbol_index); | 84 | const symbol_index = try self.newLocalSymbol(gpa, name_off); |
| 77 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; | 85 | const sym = self.symbol(symbol_index); |
| 78 | esym.st_info = elf.STT_FILE; | 86 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; |
| 79 | esym.st_shndx = elf.SHN_ABS; | 87 | esym.st_info = elf.STT_FILE; |
| 88 | esym.st_shndx = elf.SHN_ABS; | ||
| 89 | } | ||
| 90 | |||
| 91 | const fillSection = struct { | ||
| 92 | fn fillSection(ef: *Elf, shdr: *elf.Elf64_Shdr, size: u64, phndx: ?u16) !void { | ||
| 93 | if (ef.base.isRelocatable()) { | ||
| 94 | const off = try ef.findFreeSpace(size, shdr.sh_addralign); | ||
| 95 | shdr.sh_offset = off; | ||
| 96 | shdr.sh_size = size; | ||
| 97 | } else { | ||
| 98 | const phdr = ef.phdrs.items[phndx.?]; | ||
| 99 | shdr.sh_addr = phdr.p_vaddr; | ||
| 100 | shdr.sh_offset = phdr.p_offset; | ||
| 101 | shdr.sh_size = phdr.p_memsz; | ||
| 102 | } | ||
| 103 | } | ||
| 104 | }.fillSection; | ||
| 105 | |||
| 106 | comptime assert(Elf.number_of_zig_segments == 4); | ||
| 107 | |||
| 108 | if (!elf_file.base.isRelocatable()) { | ||
| 109 | if (elf_file.phdr_zig_load_re_index == null) { | ||
| 110 | const filesz = options.program_code_size_hint; | ||
| 111 | const off = try elf_file.findFreeSpace(filesz, elf_file.page_size); | ||
| 112 | elf_file.phdr_zig_load_re_index = try elf_file.addPhdr(.{ | ||
| 113 | .type = elf.PT_LOAD, | ||
| 114 | .offset = off, | ||
| 115 | .filesz = filesz, | ||
| 116 | .addr = if (ptr_bit_width >= 32) 0x4000000 else 0x4000, | ||
| 117 | .memsz = filesz, | ||
| 118 | .@"align" = elf_file.page_size, | ||
| 119 | .flags = elf.PF_X | elf.PF_R | elf.PF_W, | ||
| 120 | }); | ||
| 121 | } | ||
| 122 | |||
| 123 | if (elf_file.phdr_zig_load_ro_index == null) { | ||
| 124 | const alignment = elf_file.page_size; | ||
| 125 | const filesz: u64 = 1024; | ||
| 126 | const off = try elf_file.findFreeSpace(filesz, alignment); | ||
| 127 | elf_file.phdr_zig_load_ro_index = try elf_file.addPhdr(.{ | ||
| 128 | .type = elf.PT_LOAD, | ||
| 129 | .offset = off, | ||
| 130 | .filesz = filesz, | ||
| 131 | .addr = if (ptr_bit_width >= 32) 0xc000000 else 0xa000, | ||
| 132 | .memsz = filesz, | ||
| 133 | .@"align" = alignment, | ||
| 134 | .flags = elf.PF_R | elf.PF_W, | ||
| 135 | }); | ||
| 136 | } | ||
| 137 | |||
| 138 | if (elf_file.phdr_zig_load_rw_index == null) { | ||
| 139 | const alignment = elf_file.page_size; | ||
| 140 | const filesz: u64 = 1024; | ||
| 141 | const off = try elf_file.findFreeSpace(filesz, alignment); | ||
| 142 | elf_file.phdr_zig_load_rw_index = try elf_file.addPhdr(.{ | ||
| 143 | .type = elf.PT_LOAD, | ||
| 144 | .offset = off, | ||
| 145 | .filesz = filesz, | ||
| 146 | .addr = if (ptr_bit_width >= 32) 0x10000000 else 0xc000, | ||
| 147 | .memsz = filesz, | ||
| 148 | .@"align" = alignment, | ||
| 149 | .flags = elf.PF_R | elf.PF_W, | ||
| 150 | }); | ||
| 151 | } | ||
| 152 | |||
| 153 | if (elf_file.phdr_zig_load_zerofill_index == null) { | ||
| 154 | const alignment = elf_file.page_size; | ||
| 155 | elf_file.phdr_zig_load_zerofill_index = try elf_file.addPhdr(.{ | ||
| 156 | .type = elf.PT_LOAD, | ||
| 157 | .addr = if (ptr_bit_width >= 32) 0x14000000 else 0xf000, | ||
| 158 | .memsz = 1024, | ||
| 159 | .@"align" = alignment, | ||
| 160 | .flags = elf.PF_R | elf.PF_W, | ||
| 161 | }); | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | if (elf_file.zig_text_section_index == null) { | ||
| 166 | elf_file.zig_text_section_index = try elf_file.addSection(.{ | ||
| 167 | .name = try elf_file.insertShString(".text.zig"), | ||
| 168 | .type = elf.SHT_PROGBITS, | ||
| 169 | .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, | ||
| 170 | .addralign = 1, | ||
| 171 | .offset = std.math.maxInt(u64), | ||
| 172 | }); | ||
| 173 | const shdr = &elf_file.sections.items(.shdr)[elf_file.zig_text_section_index.?]; | ||
| 174 | const phndx = &elf_file.sections.items(.phndx)[elf_file.zig_text_section_index.?]; | ||
| 175 | try fillSection(elf_file, shdr, options.program_code_size_hint, elf_file.phdr_zig_load_re_index); | ||
| 176 | if (elf_file.base.isRelocatable()) { | ||
| 177 | _ = try elf_file.addRelaShdr( | ||
| 178 | try elf_file.insertShString(".rela.text.zig"), | ||
| 179 | elf_file.zig_text_section_index.?, | ||
| 180 | ); | ||
| 181 | } else { | ||
| 182 | phndx.* = elf_file.phdr_zig_load_re_index.?; | ||
| 183 | } | ||
| 184 | } | ||
| 185 | |||
| 186 | if (elf_file.zig_data_rel_ro_section_index == null) { | ||
| 187 | elf_file.zig_data_rel_ro_section_index = try elf_file.addSection(.{ | ||
| 188 | .name = try elf_file.insertShString(".data.rel.ro.zig"), | ||
| 189 | .type = elf.SHT_PROGBITS, | ||
| 190 | .addralign = 1, | ||
| 191 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | ||
| 192 | .offset = std.math.maxInt(u64), | ||
| 193 | }); | ||
| 194 | const shdr = &elf_file.sections.items(.shdr)[elf_file.zig_data_rel_ro_section_index.?]; | ||
| 195 | const phndx = &elf_file.sections.items(.phndx)[elf_file.zig_data_rel_ro_section_index.?]; | ||
| 196 | try fillSection(elf_file, shdr, 1024, elf_file.phdr_zig_load_ro_index); | ||
| 197 | if (elf_file.base.isRelocatable()) { | ||
| 198 | _ = try elf_file.addRelaShdr( | ||
| 199 | try elf_file.insertShString(".rela.data.rel.ro.zig"), | ||
| 200 | elf_file.zig_data_rel_ro_section_index.?, | ||
| 201 | ); | ||
| 202 | } else { | ||
| 203 | phndx.* = elf_file.phdr_zig_load_ro_index.?; | ||
| 204 | } | ||
| 205 | } | ||
| 206 | |||
| 207 | if (elf_file.zig_data_section_index == null) { | ||
| 208 | elf_file.zig_data_section_index = try elf_file.addSection(.{ | ||
| 209 | .name = try elf_file.insertShString(".data.zig"), | ||
| 210 | .type = elf.SHT_PROGBITS, | ||
| 211 | .addralign = ptr_size, | ||
| 212 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | ||
| 213 | .offset = std.math.maxInt(u64), | ||
| 214 | }); | ||
| 215 | const shdr = &elf_file.sections.items(.shdr)[elf_file.zig_data_section_index.?]; | ||
| 216 | const phndx = &elf_file.sections.items(.phndx)[elf_file.zig_data_section_index.?]; | ||
| 217 | try fillSection(elf_file, shdr, 1024, elf_file.phdr_zig_load_rw_index); | ||
| 218 | if (elf_file.base.isRelocatable()) { | ||
| 219 | _ = try elf_file.addRelaShdr( | ||
| 220 | try elf_file.insertShString(".rela.data.zig"), | ||
| 221 | elf_file.zig_data_section_index.?, | ||
| 222 | ); | ||
| 223 | } else { | ||
| 224 | phndx.* = elf_file.phdr_zig_load_rw_index.?; | ||
| 225 | } | ||
| 226 | } | ||
| 227 | |||
| 228 | if (elf_file.zig_bss_section_index == null) { | ||
| 229 | elf_file.zig_bss_section_index = try elf_file.addSection(.{ | ||
| 230 | .name = try elf_file.insertShString(".bss.zig"), | ||
| 231 | .type = elf.SHT_NOBITS, | ||
| 232 | .addralign = ptr_size, | ||
| 233 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, | ||
| 234 | .offset = 0, | ||
| 235 | }); | ||
| 236 | const shdr = &elf_file.sections.items(.shdr)[elf_file.zig_bss_section_index.?]; | ||
| 237 | const phndx = &elf_file.sections.items(.phndx)[elf_file.zig_bss_section_index.?]; | ||
| 238 | if (elf_file.base.isRelocatable()) { | ||
| 239 | shdr.sh_size = 1024; | ||
| 240 | } else { | ||
| 241 | phndx.* = elf_file.phdr_zig_load_zerofill_index.?; | ||
| 242 | const phdr = elf_file.phdrs.items[phndx.*.?]; | ||
| 243 | shdr.sh_addr = phdr.p_vaddr; | ||
| 244 | shdr.sh_size = phdr.p_memsz; | ||
| 245 | } | ||
| 246 | } | ||
| 80 | 247 | ||
| 81 | switch (comp.config.debug_format) { | 248 | switch (comp.config.debug_format) { |
| 82 | .strip => {}, | 249 | .strip => {}, |
| 83 | .dwarf => |v| self.dwarf = Dwarf.init(&elf_file.base, v), | 250 | .dwarf => |v| { |
| 251 | var dwarf = Dwarf.init(&elf_file.base, v); | ||
| 252 | |||
| 253 | const addSectionSymbol = struct { | ||
| 254 | fn addSectionSymbol( | ||
| 255 | zig_object: *ZigObject, | ||
| 256 | alloc: Allocator, | ||
| 257 | name: [:0]const u8, | ||
| 258 | alignment: Atom.Alignment, | ||
| 259 | shndx: u32, | ||
| 260 | ) !Symbol.Index { | ||
| 261 | const name_off = try zig_object.addString(alloc, name); | ||
| 262 | const index = try zig_object.newSymbolWithAtom(alloc, name_off); | ||
| 263 | const sym = zig_object.symbol(index); | ||
| 264 | const esym = &zig_object.symtab.items(.elf_sym)[sym.esym_index]; | ||
| 265 | esym.st_info |= elf.STT_SECTION; | ||
| 266 | const atom_ptr = zig_object.atom(sym.ref.index).?; | ||
| 267 | atom_ptr.alignment = alignment; | ||
| 268 | atom_ptr.output_section_index = shndx; | ||
| 269 | return index; | ||
| 270 | } | ||
| 271 | }.addSectionSymbol; | ||
| 272 | |||
| 273 | if (elf_file.debug_str_section_index == null) { | ||
| 274 | elf_file.debug_str_section_index = try elf_file.addSection(.{ | ||
| 275 | .name = try elf_file.insertShString(".debug_str"), | ||
| 276 | .flags = elf.SHF_MERGE | elf.SHF_STRINGS, | ||
| 277 | .entsize = 1, | ||
| 278 | .type = elf.SHT_PROGBITS, | ||
| 279 | .addralign = 1, | ||
| 280 | }); | ||
| 281 | self.debug_str_section_dirty = true; | ||
| 282 | self.debug_str_index = try addSectionSymbol(self, gpa, ".debug_str", .@"1", elf_file.debug_str_section_index.?); | ||
| 283 | } | ||
| 284 | |||
| 285 | if (elf_file.debug_info_section_index == null) { | ||
| 286 | elf_file.debug_info_section_index = try elf_file.addSection(.{ | ||
| 287 | .name = try elf_file.insertShString(".debug_info"), | ||
| 288 | .type = elf.SHT_PROGBITS, | ||
| 289 | .addralign = 1, | ||
| 290 | }); | ||
| 291 | self.debug_info_section_dirty = true; | ||
| 292 | self.debug_info_index = try addSectionSymbol(self, gpa, ".debug_info", .@"1", elf_file.debug_info_section_index.?); | ||
| 293 | } | ||
| 294 | |||
| 295 | if (elf_file.debug_abbrev_section_index == null) { | ||
| 296 | elf_file.debug_abbrev_section_index = try elf_file.addSection(.{ | ||
| 297 | .name = try elf_file.insertShString(".debug_abbrev"), | ||
| 298 | .type = elf.SHT_PROGBITS, | ||
| 299 | .addralign = 1, | ||
| 300 | }); | ||
| 301 | self.debug_abbrev_section_dirty = true; | ||
| 302 | self.debug_abbrev_index = try addSectionSymbol(self, gpa, ".debug_abbrev", .@"1", elf_file.debug_abbrev_section_index.?); | ||
| 303 | } | ||
| 304 | |||
| 305 | if (elf_file.debug_aranges_section_index == null) { | ||
| 306 | elf_file.debug_aranges_section_index = try elf_file.addSection(.{ | ||
| 307 | .name = try elf_file.insertShString(".debug_aranges"), | ||
| 308 | .type = elf.SHT_PROGBITS, | ||
| 309 | .addralign = 16, | ||
| 310 | }); | ||
| 311 | self.debug_aranges_section_dirty = true; | ||
| 312 | self.debug_aranges_index = try addSectionSymbol(self, gpa, ".debug_aranges", .@"16", elf_file.debug_aranges_section_index.?); | ||
| 313 | } | ||
| 314 | |||
| 315 | if (elf_file.debug_line_section_index == null) { | ||
| 316 | elf_file.debug_line_section_index = try elf_file.addSection(.{ | ||
| 317 | .name = try elf_file.insertShString(".debug_line"), | ||
| 318 | .type = elf.SHT_PROGBITS, | ||
| 319 | .addralign = 1, | ||
| 320 | }); | ||
| 321 | self.debug_line_section_dirty = true; | ||
| 322 | self.debug_line_index = try addSectionSymbol(self, gpa, ".debug_line", .@"1", elf_file.debug_line_section_index.?); | ||
| 323 | } | ||
| 324 | |||
| 325 | if (elf_file.debug_line_str_section_index == null) { | ||
| 326 | elf_file.debug_line_str_section_index = try elf_file.addSection(.{ | ||
| 327 | .name = try elf_file.insertShString(".debug_line_str"), | ||
| 328 | .flags = elf.SHF_MERGE | elf.SHF_STRINGS, | ||
| 329 | .entsize = 1, | ||
| 330 | .type = elf.SHT_PROGBITS, | ||
| 331 | .addralign = 1, | ||
| 332 | }); | ||
| 333 | self.debug_line_str_section_dirty = true; | ||
| 334 | self.debug_line_str_index = try addSectionSymbol(self, gpa, ".debug_line_str", .@"1", elf_file.debug_line_str_section_index.?); | ||
| 335 | } | ||
| 336 | |||
| 337 | if (elf_file.debug_loclists_section_index == null) { | ||
| 338 | elf_file.debug_loclists_section_index = try elf_file.addSection(.{ | ||
| 339 | .name = try elf_file.insertShString(".debug_loclists"), | ||
| 340 | .type = elf.SHT_PROGBITS, | ||
| 341 | .addralign = 1, | ||
| 342 | }); | ||
| 343 | self.debug_loclists_section_dirty = true; | ||
| 344 | self.debug_loclists_index = try addSectionSymbol(self, gpa, ".debug_loclists", .@"1", elf_file.debug_loclists_section_index.?); | ||
| 345 | } | ||
| 346 | |||
| 347 | if (elf_file.debug_rnglists_section_index == null) { | ||
| 348 | elf_file.debug_rnglists_section_index = try elf_file.addSection(.{ | ||
| 349 | .name = try elf_file.insertShString(".debug_rnglists"), | ||
| 350 | .type = elf.SHT_PROGBITS, | ||
| 351 | .addralign = 1, | ||
| 352 | }); | ||
| 353 | self.debug_rnglists_section_dirty = true; | ||
| 354 | self.debug_rnglists_index = try addSectionSymbol(self, gpa, ".debug_rnglists", .@"1", elf_file.debug_rnglists_section_index.?); | ||
| 355 | } | ||
| 356 | |||
| 357 | try dwarf.initMetadata(); | ||
| 358 | self.dwarf = dwarf; | ||
| 359 | }, | ||
| 84 | .code_view => unreachable, | 360 | .code_view => unreachable, |
| 85 | } | 361 | } |
| 86 | } | 362 | } |
| ... | @@ -198,7 +474,7 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi | ... | @@ -198,7 +474,7 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi |
| 198 | const atom_ptr = self.atom(sym.ref.index).?; | 474 | const atom_ptr = self.atom(sym.ref.index).?; |
| 199 | if (!atom_ptr.alive) continue; | 475 | if (!atom_ptr.alive) continue; |
| 200 | const shndx = sym.outputShndx(elf_file).?; | 476 | const shndx = sym.outputShndx(elf_file).?; |
| 201 | const shdr = elf_file.shdrs.items[shndx]; | 477 | const shdr = elf_file.sections.items(.shdr)[shndx]; |
| 202 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; | 478 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; |
| 203 | esym.st_size = shdr.sh_size; | 479 | esym.st_size = shdr.sh_size; |
| 204 | atom_ptr.size = shdr.sh_size; | 480 | atom_ptr.size = shdr.sh_size; |
| ... | @@ -358,13 +634,10 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi | ... | @@ -358,13 +634,10 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi |
| 358 | } | 634 | } |
| 359 | 635 | ||
| 360 | if (elf_file.base.isRelocatable() and relocs.items.len > 0) { | 636 | if (elf_file.base.isRelocatable() and relocs.items.len > 0) { |
| 361 | const gop = try elf_file.output_rela_sections.getOrPut(gpa, shndx); | 637 | const rela_sect_name = try std.fmt.allocPrintZ(gpa, ".rela{s}", .{elf_file.getShString(shdr.sh_name)}); |
| 362 | if (!gop.found_existing) { | 638 | defer gpa.free(rela_sect_name); |
| 363 | const rela_sect_name = try std.fmt.allocPrintZ(gpa, ".rela{s}", .{elf_file.getShString(shdr.sh_name)}); | 639 | if (elf_file.sectionByName(rela_sect_name) == null) { |
| 364 | defer gpa.free(rela_sect_name); | 640 | _ = try elf_file.addRelaShdr(try elf_file.insertShString(rela_sect_name), shndx); |
| 365 | const rela_sh_name = try elf_file.insertShString(rela_sect_name); | ||
| 366 | const rela_shndx = try elf_file.addRelaShdr(rela_sh_name, shndx); | ||
| 367 | gop.value_ptr.* = .{ .shndx = rela_shndx }; | ||
| 368 | } | 641 | } |
| 369 | } | 642 | } |
| 370 | } | 643 | } |
| ... | @@ -446,7 +719,7 @@ fn newAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Atom.Index { | ... | @@ -446,7 +719,7 @@ fn newAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Atom.Index { |
| 446 | return index; | 719 | return index; |
| 447 | } | 720 | } |
| 448 | 721 | ||
| 449 | pub fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index { | 722 | fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index { |
| 450 | const atom_index = try self.newAtom(allocator, name_off); | 723 | const atom_index = try self.newAtom(allocator, name_off); |
| 451 | const sym_index = try self.newLocalSymbol(allocator, name_off); | 724 | const sym_index = try self.newLocalSymbol(allocator, name_off); |
| 452 | const sym = self.symbol(sym_index); | 725 | const sym = self.symbol(sym_index); |
| ... | @@ -460,7 +733,7 @@ pub fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name_off: u32) | ... | @@ -460,7 +733,7 @@ pub fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name_off: u32) |
| 460 | pub fn inputShdr(self: *ZigObject, atom_index: Atom.Index, elf_file: *Elf) elf.Elf64_Shdr { | 733 | pub fn inputShdr(self: *ZigObject, atom_index: Atom.Index, elf_file: *Elf) elf.Elf64_Shdr { |
| 461 | const atom_ptr = self.atom(atom_index) orelse return Elf.null_shdr; | 734 | const atom_ptr = self.atom(atom_index) orelse return Elf.null_shdr; |
| 462 | const shndx = atom_ptr.output_section_index; | 735 | const shndx = atom_ptr.output_section_index; |
| 463 | var shdr = elf_file.shdrs.items[shndx]; | 736 | var shdr = elf_file.sections.items(.shdr)[shndx]; |
| 464 | shdr.sh_addr = 0; | 737 | shdr.sh_addr = 0; |
| 465 | shdr.sh_offset = 0; | 738 | shdr.sh_offset = 0; |
| 466 | shdr.sh_size = atom_ptr.size; | 739 | shdr.sh_size = atom_ptr.size; |
| ... | @@ -638,8 +911,8 @@ pub fn readFileContents(self: *ZigObject, elf_file: *Elf) !void { | ... | @@ -638,8 +911,8 @@ pub fn readFileContents(self: *ZigObject, elf_file: *Elf) !void { |
| 638 | .p32 => @sizeOf(elf.Elf32_Shdr), | 911 | .p32 => @sizeOf(elf.Elf32_Shdr), |
| 639 | .p64 => @sizeOf(elf.Elf64_Shdr), | 912 | .p64 => @sizeOf(elf.Elf64_Shdr), |
| 640 | }; | 913 | }; |
| 641 | var end_pos: u64 = elf_file.shdr_table_offset.? + elf_file.shdrs.items.len * shsize; | 914 | var end_pos: u64 = elf_file.shdr_table_offset.? + elf_file.sections.items(.shdr).len * shsize; |
| 642 | for (elf_file.shdrs.items) |shdr| { | 915 | for (elf_file.sections.items(.shdr)) |shdr| { |
| 643 | if (shdr.sh_type == elf.SHT_NOBITS) continue; | 916 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 644 | end_pos = @max(end_pos, shdr.sh_offset + shdr.sh_size); | 917 | end_pos = @max(end_pos, shdr.sh_offset + shdr.sh_size); |
| 645 | } | 918 | } |
| ... | @@ -692,12 +965,14 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void { | ... | @@ -692,12 +965,14 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void { |
| 692 | // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level | 965 | // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level |
| 693 | if (self.relocs.items[rela_shndx].items.len == 0) continue; | 966 | if (self.relocs.items[rela_shndx].items.len == 0) continue; |
| 694 | const out_shndx = atom_ptr.output_section_index; | 967 | const out_shndx = atom_ptr.output_section_index; |
| 695 | const out_shdr = elf_file.shdrs.items[out_shndx]; | 968 | const out_shdr = elf_file.sections.items(.shdr)[out_shndx]; |
| 696 | if (out_shdr.sh_type == elf.SHT_NOBITS) continue; | 969 | if (out_shdr.sh_type == elf.SHT_NOBITS) continue; |
| 697 | 970 | const out_rela_shndx = for (elf_file.sections.items(.shdr), 0..) |out_rela_shdr, out_rela_shndx| { | |
| 971 | if (out_rela_shdr.sh_type == elf.SHT_RELA and out_rela_shdr.sh_info == out_shndx) break out_rela_shndx; | ||
| 972 | } else unreachable; | ||
| 973 | const atom_list = &elf_file.sections.items(.atom_list)[out_rela_shndx]; | ||
| 698 | const gpa = elf_file.base.comp.gpa; | 974 | const gpa = elf_file.base.comp.gpa; |
| 699 | const sec = elf_file.output_rela_sections.getPtr(out_shndx).?; | 975 | try atom_list.append(gpa, .{ .index = atom_index, .file = self.index }); |
| 700 | try sec.atom_list.append(gpa, .{ .index = atom_index, .file = self.index }); | ||
| 701 | } | 976 | } |
| 702 | } | 977 | } |
| 703 | 978 | ||
| ... | @@ -767,7 +1042,7 @@ pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void { | ... | @@ -767,7 +1042,7 @@ pub fn writeSymtab(self: ZigObject, elf_file: *Elf) void { |
| 767 | pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 { | 1042 | pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 { |
| 768 | const gpa = elf_file.base.comp.gpa; | 1043 | const gpa = elf_file.base.comp.gpa; |
| 769 | const atom_ptr = self.atom(atom_index).?; | 1044 | const atom_ptr = self.atom(atom_index).?; |
| 770 | const shdr = &elf_file.shdrs.items[atom_ptr.output_section_index]; | 1045 | const shdr = &elf_file.sections.items(.shdr)[atom_ptr.output_section_index]; |
| 771 | 1046 | ||
| 772 | if (shdr.sh_flags & elf.SHF_TLS != 0) { | 1047 | if (shdr.sh_flags & elf.SHF_TLS != 0) { |
| 773 | const tlv = self.tls_variables.get(atom_index).?; | 1048 | const tlv = self.tls_variables.get(atom_index).?; |
| ... | @@ -1094,7 +1369,7 @@ fn updateNavCode( | ... | @@ -1094,7 +1369,7 @@ fn updateNavCode( |
| 1094 | } | 1369 | } |
| 1095 | } | 1370 | } |
| 1096 | 1371 | ||
| 1097 | const shdr = elf_file.shdrs.items[shdr_index]; | 1372 | const shdr = elf_file.sections.items(.shdr)[shdr_index]; |
| 1098 | if (shdr.sh_type != elf.SHT_NOBITS) { | 1373 | if (shdr.sh_type != elf.SHT_NOBITS) { |
| 1099 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); | 1374 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); |
| 1100 | try elf_file.base.file.?.pwriteAll(code, file_offset); | 1375 | try elf_file.base.file.?.pwriteAll(code, file_offset); |
| ... | @@ -1149,16 +1424,13 @@ fn updateTlv( | ... | @@ -1149,16 +1424,13 @@ fn updateTlv( |
| 1149 | gop.value_ptr.* = .{ .symbol_index = sym_index }; | 1424 | gop.value_ptr.* = .{ .symbol_index = sym_index }; |
| 1150 | 1425 | ||
| 1151 | // We only store the data for the TLV if it's non-zerofill. | 1426 | // We only store the data for the TLV if it's non-zerofill. |
| 1152 | if (elf_file.shdrs.items[shndx].sh_type != elf.SHT_NOBITS) { | 1427 | if (elf_file.sections.items(.shdr)[shndx].sh_type != elf.SHT_NOBITS) { |
| 1153 | gop.value_ptr.code = try gpa.dupe(u8, code); | 1428 | gop.value_ptr.code = try gpa.dupe(u8, code); |
| 1154 | } | 1429 | } |
| 1155 | } | 1430 | } |
| 1156 | 1431 | ||
| 1157 | { | 1432 | const atom_list = &elf_file.sections.items(.atom_list)[atom_ptr.output_section_index]; |
| 1158 | const gop = try elf_file.output_sections.getOrPut(gpa, atom_ptr.output_section_index); | 1433 | try atom_list.append(gpa, .{ .index = atom_ptr.atom_index, .file = self.index }); |
| 1159 | if (!gop.found_existing) gop.value_ptr.* = .{}; | ||
| 1160 | try gop.value_ptr.append(gpa, .{ .index = atom_ptr.atom_index, .file = self.index }); | ||
| 1161 | } | ||
| 1162 | } | 1434 | } |
| 1163 | 1435 | ||
| 1164 | pub fn updateFunc( | 1436 | pub fn updateFunc( |
| ... | @@ -1210,7 +1482,7 @@ pub fn updateFunc( | ... | @@ -1210,7 +1482,7 @@ pub fn updateFunc( |
| 1210 | const shndx = try self.getNavShdrIndex(elf_file, zcu, func.owner_nav, sym_index, code); | 1482 | const shndx = try self.getNavShdrIndex(elf_file, zcu, func.owner_nav, sym_index, code); |
| 1211 | log.debug("setting shdr({x},{s}) for {}", .{ | 1483 | log.debug("setting shdr({x},{s}) for {}", .{ |
| 1212 | shndx, | 1484 | shndx, |
| 1213 | elf_file.getShString(elf_file.shdrs.items[shndx].sh_name), | 1485 | elf_file.getShString(elf_file.sections.items(.shdr)[shndx].sh_name), |
| 1214 | ip.getNav(func.owner_nav).fqn.fmt(ip), | 1486 | ip.getNav(func.owner_nav).fqn.fmt(ip), |
| 1215 | }); | 1487 | }); |
| 1216 | const old_rva, const old_alignment = blk: { | 1488 | const old_rva, const old_alignment = blk: { |
| ... | @@ -1338,10 +1610,10 @@ pub fn updateNav( | ... | @@ -1338,10 +1610,10 @@ pub fn updateNav( |
| 1338 | const shndx = try self.getNavShdrIndex(elf_file, zcu, nav_index, sym_index, code); | 1610 | const shndx = try self.getNavShdrIndex(elf_file, zcu, nav_index, sym_index, code); |
| 1339 | log.debug("setting shdr({x},{s}) for {}", .{ | 1611 | log.debug("setting shdr({x},{s}) for {}", .{ |
| 1340 | shndx, | 1612 | shndx, |
| 1341 | elf_file.getShString(elf_file.shdrs.items[shndx].sh_name), | 1613 | elf_file.getShString(elf_file.sections.items(.shdr)[shndx].sh_name), |
| 1342 | nav.fqn.fmt(ip), | 1614 | nav.fqn.fmt(ip), |
| 1343 | }); | 1615 | }); |
| 1344 | if (elf_file.shdrs.items[shndx].sh_flags & elf.SHF_TLS != 0) | 1616 | if (elf_file.sections.items(.shdr)[shndx].sh_flags & elf.SHF_TLS != 0) |
| 1345 | try self.updateTlv(elf_file, pt, nav_index, sym_index, shndx, code) | 1617 | try self.updateTlv(elf_file, pt, nav_index, sym_index, shndx, code) |
| 1346 | else | 1618 | else |
| 1347 | try self.updateNavCode(elf_file, pt, nav_index, sym_index, shndx, code, elf.STT_OBJECT); | 1619 | try self.updateNavCode(elf_file, pt, nav_index, sym_index, shndx, code, elf.STT_OBJECT); |
| ... | @@ -1440,7 +1712,7 @@ fn updateLazySymbol( | ... | @@ -1440,7 +1712,7 @@ fn updateLazySymbol( |
| 1440 | local_sym.value = 0; | 1712 | local_sym.value = 0; |
| 1441 | local_esym.st_value = 0; | 1713 | local_esym.st_value = 0; |
| 1442 | 1714 | ||
| 1443 | const shdr = elf_file.shdrs.items[output_section_index]; | 1715 | const shdr = elf_file.sections.items(.shdr)[output_section_index]; |
| 1444 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); | 1716 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); |
| 1445 | try elf_file.base.file.?.pwriteAll(code, file_offset); | 1717 | try elf_file.base.file.?.pwriteAll(code, file_offset); |
| 1446 | } | 1718 | } |
| ... | @@ -1496,7 +1768,7 @@ fn lowerConst( | ... | @@ -1496,7 +1768,7 @@ fn lowerConst( |
| 1496 | // TODO rename and re-audit this method | 1768 | // TODO rename and re-audit this method |
| 1497 | errdefer self.freeNavMetadata(elf_file, sym_index); | 1769 | errdefer self.freeNavMetadata(elf_file, sym_index); |
| 1498 | 1770 | ||
| 1499 | const shdr = elf_file.shdrs.items[output_section_index]; | 1771 | const shdr = elf_file.sections.items(.shdr)[output_section_index]; |
| 1500 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); | 1772 | const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); |
| 1501 | try elf_file.base.file.?.pwriteAll(code, file_offset); | 1773 | try elf_file.base.file.?.pwriteAll(code, file_offset); |
| 1502 | 1774 | ||
| ... | @@ -1660,7 +1932,7 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) u64 { | ... | @@ -1660,7 +1932,7 @@ fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) u64 { |
| 1660 | 1932 | ||
| 1661 | fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void { | 1933 | fn writeTrampoline(tr_sym: Symbol, target: Symbol, elf_file: *Elf) !void { |
| 1662 | const atom_ptr = tr_sym.atom(elf_file).?; | 1934 | const atom_ptr = tr_sym.atom(elf_file).?; |
| 1663 | const shdr = elf_file.shdrs.items[atom_ptr.output_section_index]; | 1935 | const shdr = elf_file.sections.items(.shdr)[atom_ptr.output_section_index]; |
| 1664 | const fileoff = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); | 1936 | const fileoff = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)); |
| 1665 | const source_addr = tr_sym.address(.{}, elf_file); | 1937 | const source_addr = tr_sym.address(.{}, elf_file); |
| 1666 | const target_addr = target.address(.{ .trampoline = false }, elf_file); | 1938 | const target_addr = target.address(.{ .trampoline = false }, elf_file); |
src/link/Elf/eh_frame.zig+12-7| ... | @@ -13,7 +13,7 @@ pub const Fde = struct { | ... | @@ -13,7 +13,7 @@ pub const Fde = struct { |
| 13 | 13 | ||
| 14 | pub fn address(fde: Fde, elf_file: *Elf) u64 { | 14 | pub fn address(fde: Fde, elf_file: *Elf) u64 { |
| 15 | const base: u64 = if (elf_file.eh_frame_section_index) |shndx| | 15 | const base: u64 = if (elf_file.eh_frame_section_index) |shndx| |
| 16 | elf_file.shdrs.items[shndx].sh_addr | 16 | elf_file.sections.items(.shdr)[shndx].sh_addr |
| 17 | else | 17 | else |
| 18 | 0; | 18 | 0; |
| 19 | return base + fde.out_offset; | 19 | return base + fde.out_offset; |
| ... | @@ -112,7 +112,7 @@ pub const Cie = struct { | ... | @@ -112,7 +112,7 @@ pub const Cie = struct { |
| 112 | 112 | ||
| 113 | pub fn address(cie: Cie, elf_file: *Elf) u64 { | 113 | pub fn address(cie: Cie, elf_file: *Elf) u64 { |
| 114 | const base: u64 = if (elf_file.eh_frame_section_index) |shndx| | 114 | const base: u64 = if (elf_file.eh_frame_section_index) |shndx| |
| 115 | elf_file.shdrs.items[shndx].sh_addr | 115 | elf_file.sections.items(.shdr)[shndx].sh_addr |
| 116 | else | 116 | else |
| 117 | 0; | 117 | 0; |
| 118 | return base + cie.out_offset; | 118 | return base + cie.out_offset; |
| ... | @@ -326,7 +326,9 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file: | ... | @@ -326,7 +326,9 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file: |
| 326 | } | 326 | } |
| 327 | 327 | ||
| 328 | pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void { | 328 | pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void { |
| 329 | relocs_log.debug("{x}: .eh_frame", .{elf_file.shdrs.items[elf_file.eh_frame_section_index.?].sh_addr}); | 329 | relocs_log.debug("{x}: .eh_frame", .{ |
| 330 | elf_file.sections.items(.shdr)[elf_file.eh_frame_section_index.?].sh_addr, | ||
| 331 | }); | ||
| 330 | 332 | ||
| 331 | var has_reloc_errors = false; | 333 | var has_reloc_errors = false; |
| 332 | 334 | ||
| ... | @@ -423,7 +425,7 @@ fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Re | ... | @@ -423,7 +425,7 @@ fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Re |
| 423 | switch (sym.type(elf_file)) { | 425 | switch (sym.type(elf_file)) { |
| 424 | elf.STT_SECTION => { | 426 | elf.STT_SECTION => { |
| 425 | r_addend += @intCast(sym.address(.{}, elf_file)); | 427 | r_addend += @intCast(sym.address(.{}, elf_file)); |
| 426 | r_sym = elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx(elf_file).?); | 428 | r_sym = sym.outputShndx(elf_file).?; |
| 427 | }, | 429 | }, |
| 428 | else => { | 430 | else => { |
| 429 | r_sym = sym.outputSymtabIndex(elf_file) orelse 0; | 431 | r_sym = sym.outputSymtabIndex(elf_file) orelse 0; |
| ... | @@ -446,7 +448,9 @@ fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Re | ... | @@ -446,7 +448,9 @@ fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Re |
| 446 | } | 448 | } |
| 447 | 449 | ||
| 448 | pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void { | 450 | pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void { |
| 449 | relocs_log.debug("{x}: .eh_frame", .{elf_file.shdrs.items[elf_file.eh_frame_section_index.?].sh_addr}); | 451 | relocs_log.debug("{x}: .eh_frame", .{ |
| 452 | elf_file.sections.items(.shdr)[elf_file.eh_frame_section_index.?].sh_addr, | ||
| 453 | }); | ||
| 450 | 454 | ||
| 451 | for (elf_file.objects.items) |index| { | 455 | for (elf_file.objects.items) |index| { |
| 452 | const object = elf_file.file(index).?.object; | 456 | const object = elf_file.file(index).?.object; |
| ... | @@ -482,8 +486,9 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void { | ... | @@ -482,8 +486,9 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void { |
| 482 | try writer.writeByte(EH_PE.udata4); | 486 | try writer.writeByte(EH_PE.udata4); |
| 483 | try writer.writeByte(EH_PE.datarel | EH_PE.sdata4); | 487 | try writer.writeByte(EH_PE.datarel | EH_PE.sdata4); |
| 484 | 488 | ||
| 485 | const eh_frame_shdr = elf_file.shdrs.items[elf_file.eh_frame_section_index.?]; | 489 | const shdrs = elf_file.sections.items(.shdr); |
| 486 | const eh_frame_hdr_shdr = elf_file.shdrs.items[elf_file.eh_frame_hdr_section_index.?]; | 490 | const eh_frame_shdr = shdrs[elf_file.eh_frame_section_index.?]; |
| 491 | const eh_frame_hdr_shdr = shdrs[elf_file.eh_frame_hdr_section_index.?]; | ||
| 487 | const num_fdes = @as(u32, @intCast(@divExact(eh_frame_hdr_shdr.sh_size - eh_frame_hdr_header_size, 8))); | 492 | const num_fdes = @as(u32, @intCast(@divExact(eh_frame_hdr_shdr.sh_size - eh_frame_hdr_header_size, 8))); |
| 488 | try writer.writeInt( | 493 | try writer.writeInt( |
| 489 | u32, | 494 | u32, |
src/link/Elf/merge_section.zig+2-4| ... | @@ -29,7 +29,7 @@ pub const MergeSection = struct { | ... | @@ -29,7 +29,7 @@ pub const MergeSection = struct { |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | pub fn address(msec: MergeSection, elf_file: *Elf) i64 { | 31 | pub fn address(msec: MergeSection, elf_file: *Elf) i64 { |
| 32 | const shdr = elf_file.shdrs.items[msec.output_section_index]; | 32 | const shdr = elf_file.sections.items(.shdr)[msec.output_section_index]; |
| 33 | return @intCast(shdr.sh_addr + msec.value); | 33 | return @intCast(shdr.sh_addr + msec.value); |
| 34 | } | 34 | } |
| 35 | 35 | ||
| ... | @@ -108,13 +108,11 @@ pub const MergeSection = struct { | ... | @@ -108,13 +108,11 @@ pub const MergeSection = struct { |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | pub fn initOutputSection(msec: *MergeSection, elf_file: *Elf) !void { | 110 | pub fn initOutputSection(msec: *MergeSection, elf_file: *Elf) !void { |
| 111 | const shndx = elf_file.sectionByName(msec.name(elf_file)) orelse try elf_file.addSection(.{ | 111 | msec.output_section_index = elf_file.sectionByName(msec.name(elf_file)) orelse try elf_file.addSection(.{ |
| 112 | .name = msec.name_offset, | 112 | .name = msec.name_offset, |
| 113 | .type = msec.type, | 113 | .type = msec.type, |
| 114 | .flags = msec.flags, | 114 | .flags = msec.flags, |
| 115 | }); | 115 | }); |
| 116 | try elf_file.output_sections.put(elf_file.base.comp.gpa, shndx, .{}); | ||
| 117 | msec.output_section_index = shndx; | ||
| 118 | } | 116 | } |
| 119 | 117 | ||
| 120 | pub fn addMergeSubsection(msec: *MergeSection, allocator: Allocator) !MergeSubsection.Index { | 118 | pub fn addMergeSubsection(msec: *MergeSection, allocator: Allocator) !MergeSubsection.Index { |
src/link/Elf/relocatable.zig+37-38| ... | @@ -347,36 +347,36 @@ fn initComdatGroups(elf_file: *Elf) !void { | ... | @@ -347,36 +347,36 @@ fn initComdatGroups(elf_file: *Elf) !void { |
| 347 | } | 347 | } |
| 348 | 348 | ||
| 349 | fn updateSectionSizes(elf_file: *Elf) !void { | 349 | fn updateSectionSizes(elf_file: *Elf) !void { |
| 350 | for (elf_file.output_sections.keys(), elf_file.output_sections.values()) |shndx, atom_list| { | 350 | const slice = elf_file.sections.slice(); |
| 351 | const shdr = &elf_file.shdrs.items[shndx]; | 351 | for (slice.items(.shdr), 0..) |*shdr, shndx| { |
| 352 | for (atom_list.items) |ref| { | 352 | const atom_list = slice.items(.atom_list)[shndx]; |
| 353 | const atom_ptr = elf_file.atom(ref) orelse continue; | 353 | if (shdr.sh_type != elf.SHT_RELA) { |
| 354 | if (!atom_ptr.alive) continue; | 354 | for (atom_list.items) |ref| { |
| 355 | const offset = atom_ptr.alignment.forward(shdr.sh_size); | 355 | const atom_ptr = elf_file.atom(ref) orelse continue; |
| 356 | const padding = offset - shdr.sh_size; | 356 | if (!atom_ptr.alive) continue; |
| 357 | atom_ptr.value = @intCast(offset); | 357 | const offset = atom_ptr.alignment.forward(shdr.sh_size); |
| 358 | shdr.sh_size += padding + atom_ptr.size; | 358 | const padding = offset - shdr.sh_size; |
| 359 | shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits() orelse 1); | 359 | atom_ptr.value = @intCast(offset); |
| 360 | } | 360 | shdr.sh_size += padding + atom_ptr.size; |
| 361 | } | 361 | shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits() orelse 1); |
| 362 | } | ||
| 363 | } else { | ||
| 364 | for (atom_list.items) |ref| { | ||
| 365 | const atom_ptr = elf_file.atom(ref) orelse continue; | ||
| 366 | if (!atom_ptr.alive) continue; | ||
| 367 | const relocs = atom_ptr.relocs(elf_file); | ||
| 368 | shdr.sh_size += shdr.sh_entsize * relocs.len; | ||
| 369 | } | ||
| 362 | 370 | ||
| 363 | for (elf_file.output_rela_sections.values()) |sec| { | 371 | if (shdr.sh_size == 0) shdr.sh_offset = 0; |
| 364 | const shdr = &elf_file.shdrs.items[sec.shndx]; | ||
| 365 | for (sec.atom_list.items) |ref| { | ||
| 366 | const atom_ptr = elf_file.atom(ref) orelse continue; | ||
| 367 | if (!atom_ptr.alive) continue; | ||
| 368 | const relocs = atom_ptr.relocs(elf_file); | ||
| 369 | shdr.sh_size += shdr.sh_entsize * relocs.len; | ||
| 370 | } | 372 | } |
| 371 | |||
| 372 | if (shdr.sh_size == 0) shdr.sh_offset = 0; | ||
| 373 | } | 373 | } |
| 374 | 374 | ||
| 375 | if (elf_file.eh_frame_section_index) |index| { | 375 | if (elf_file.eh_frame_section_index) |index| { |
| 376 | elf_file.shdrs.items[index].sh_size = try eh_frame.calcEhFrameSize(elf_file); | 376 | slice.items(.shdr)[index].sh_size = try eh_frame.calcEhFrameSize(elf_file); |
| 377 | } | 377 | } |
| 378 | if (elf_file.eh_frame_rela_section_index) |index| { | 378 | if (elf_file.eh_frame_rela_section_index) |index| { |
| 379 | const shdr = &elf_file.shdrs.items[index]; | 379 | const shdr = &slice.items(.shdr)[index]; |
| 380 | shdr.sh_size = eh_frame.calcEhFrameRelocs(elf_file) * shdr.sh_entsize; | 380 | shdr.sh_size = eh_frame.calcEhFrameRelocs(elf_file) * shdr.sh_entsize; |
| 381 | } | 381 | } |
| 382 | 382 | ||
| ... | @@ -387,19 +387,18 @@ fn updateSectionSizes(elf_file: *Elf) !void { | ... | @@ -387,19 +387,18 @@ fn updateSectionSizes(elf_file: *Elf) !void { |
| 387 | 387 | ||
| 388 | fn updateComdatGroupsSizes(elf_file: *Elf) void { | 388 | fn updateComdatGroupsSizes(elf_file: *Elf) void { |
| 389 | for (elf_file.comdat_group_sections.items) |cg| { | 389 | for (elf_file.comdat_group_sections.items) |cg| { |
| 390 | const shdr = &elf_file.shdrs.items[cg.shndx]; | 390 | const shdr = &elf_file.sections.items(.shdr)[cg.shndx]; |
| 391 | shdr.sh_size = cg.size(elf_file); | 391 | shdr.sh_size = cg.size(elf_file); |
| 392 | shdr.sh_link = elf_file.symtab_section_index.?; | 392 | shdr.sh_link = elf_file.symtab_section_index.?; |
| 393 | 393 | ||
| 394 | const sym = cg.symbol(elf_file); | 394 | const sym = cg.symbol(elf_file); |
| 395 | shdr.sh_info = sym.outputSymtabIndex(elf_file) orelse | 395 | shdr.sh_info = sym.outputSymtabIndex(elf_file) orelse sym.outputShndx(elf_file).?; |
| 396 | elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx(elf_file).?); | ||
| 397 | } | 396 | } |
| 398 | } | 397 | } |
| 399 | 398 | ||
| 400 | /// Allocates alloc sections when merging relocatable objects files together. | 399 | /// Allocates alloc sections when merging relocatable objects files together. |
| 401 | fn allocateAllocSections(elf_file: *Elf) !void { | 400 | fn allocateAllocSections(elf_file: *Elf) !void { |
| 402 | for (elf_file.shdrs.items) |*shdr| { | 401 | for (elf_file.sections.items(.shdr)) |*shdr| { |
| 403 | if (shdr.sh_type == elf.SHT_NULL) continue; | 402 | if (shdr.sh_type == elf.SHT_NULL) continue; |
| 404 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; | 403 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; |
| 405 | if (shdr.sh_type == elf.SHT_NOBITS) { | 404 | if (shdr.sh_type == elf.SHT_NOBITS) { |
| ... | @@ -418,13 +417,13 @@ fn allocateAllocSections(elf_file: *Elf) !void { | ... | @@ -418,13 +417,13 @@ fn allocateAllocSections(elf_file: *Elf) !void { |
| 418 | 417 | ||
| 419 | fn writeAtoms(elf_file: *Elf) !void { | 418 | fn writeAtoms(elf_file: *Elf) !void { |
| 420 | const gpa = elf_file.base.comp.gpa; | 419 | const gpa = elf_file.base.comp.gpa; |
| 420 | const slice = elf_file.sections.slice(); | ||
| 421 | 421 | ||
| 422 | // TODO iterate over `output_sections` directly | 422 | // TODO iterate over `output_sections` directly |
| 423 | for (elf_file.shdrs.items, 0..) |shdr, shndx| { | 423 | for (slice.items(.shdr), slice.items(.atom_list), 0..) |shdr, atom_list, shndx| { |
| 424 | if (shdr.sh_type == elf.SHT_NULL) continue; | 424 | if (shdr.sh_type == elf.SHT_NULL) continue; |
| 425 | if (shdr.sh_type == elf.SHT_NOBITS) continue; | 425 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 426 | 426 | if (shdr.sh_type == elf.SHT_RELA) continue; | |
| 427 | const atom_list = elf_file.output_sections.get(@intCast(shndx)) orelse continue; | ||
| 428 | if (atom_list.items.len == 0) continue; | 427 | if (atom_list.items.len == 0) continue; |
| 429 | 428 | ||
| 430 | log.debug("writing atoms in '{s}' section", .{elf_file.getShString(shdr.sh_name)}); | 429 | log.debug("writing atoms in '{s}' section", .{elf_file.getShString(shdr.sh_name)}); |
| ... | @@ -490,18 +489,18 @@ fn writeAtoms(elf_file: *Elf) !void { | ... | @@ -490,18 +489,18 @@ fn writeAtoms(elf_file: *Elf) !void { |
| 490 | 489 | ||
| 491 | fn writeSyntheticSections(elf_file: *Elf) !void { | 490 | fn writeSyntheticSections(elf_file: *Elf) !void { |
| 492 | const gpa = elf_file.base.comp.gpa; | 491 | const gpa = elf_file.base.comp.gpa; |
| 492 | const slice = elf_file.sections.slice(); | ||
| 493 | 493 | ||
| 494 | for (elf_file.output_rela_sections.values()) |sec| { | 494 | for (slice.items(.shdr), slice.items(.atom_list)) |shdr, atom_list| { |
| 495 | if (sec.atom_list.items.len == 0) continue; | 495 | if (shdr.sh_type != elf.SHT_RELA) continue; |
| 496 | 496 | if (atom_list.items.len == 0) continue; | |
| 497 | const shdr = elf_file.shdrs.items[sec.shndx]; | ||
| 498 | 497 | ||
| 499 | const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse | 498 | const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse |
| 500 | return error.Overflow; | 499 | return error.Overflow; |
| 501 | var relocs = try std.ArrayList(elf.Elf64_Rela).initCapacity(gpa, num_relocs); | 500 | var relocs = try std.ArrayList(elf.Elf64_Rela).initCapacity(gpa, num_relocs); |
| 502 | defer relocs.deinit(); | 501 | defer relocs.deinit(); |
| 503 | 502 | ||
| 504 | for (sec.atom_list.items) |ref| { | 503 | for (atom_list.items) |ref| { |
| 505 | const atom_ptr = elf_file.atom(ref) orelse continue; | 504 | const atom_ptr = elf_file.atom(ref) orelse continue; |
| 506 | if (!atom_ptr.alive) continue; | 505 | if (!atom_ptr.alive) continue; |
| 507 | try atom_ptr.writeRelocs(elf_file, &relocs); | 506 | try atom_ptr.writeRelocs(elf_file, &relocs); |
| ... | @@ -527,7 +526,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void { | ... | @@ -527,7 +526,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void { |
| 527 | } | 526 | } |
| 528 | 527 | ||
| 529 | if (elf_file.eh_frame_section_index) |shndx| { | 528 | if (elf_file.eh_frame_section_index) |shndx| { |
| 530 | const shdr = elf_file.shdrs.items[shndx]; | 529 | const shdr = slice.items(.shdr)[shndx]; |
| 531 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; | 530 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; |
| 532 | var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); | 531 | var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); |
| 533 | defer buffer.deinit(); | 532 | defer buffer.deinit(); |
| ... | @@ -540,7 +539,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void { | ... | @@ -540,7 +539,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void { |
| 540 | try elf_file.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); | 539 | try elf_file.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); |
| 541 | } | 540 | } |
| 542 | if (elf_file.eh_frame_rela_section_index) |shndx| { | 541 | if (elf_file.eh_frame_rela_section_index) |shndx| { |
| 543 | const shdr = elf_file.shdrs.items[shndx]; | 542 | const shdr = slice.items(.shdr)[shndx]; |
| 544 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; | 543 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; |
| 545 | var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); | 544 | var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); |
| 546 | defer buffer.deinit(); | 545 | defer buffer.deinit(); |
| ... | @@ -561,7 +560,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void { | ... | @@ -561,7 +560,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void { |
| 561 | fn writeComdatGroups(elf_file: *Elf) !void { | 560 | fn writeComdatGroups(elf_file: *Elf) !void { |
| 562 | const gpa = elf_file.base.comp.gpa; | 561 | const gpa = elf_file.base.comp.gpa; |
| 563 | for (elf_file.comdat_group_sections.items) |cgs| { | 562 | for (elf_file.comdat_group_sections.items) |cgs| { |
| 564 | const shdr = elf_file.shdrs.items[cgs.shndx]; | 563 | const shdr = elf_file.sections.items(.shdr)[cgs.shndx]; |
| 565 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; | 564 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; |
| 566 | var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); | 565 | var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); |
| 567 | defer buffer.deinit(); | 566 | defer buffer.deinit(); |
src/link/Elf/synthetic_sections.zig+30-22| ... | @@ -95,6 +95,8 @@ pub const DynamicSection = struct { | ... | @@ -95,6 +95,8 @@ pub const DynamicSection = struct { |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | pub fn write(dt: DynamicSection, elf_file: *Elf, writer: anytype) !void { | 97 | pub fn write(dt: DynamicSection, elf_file: *Elf, writer: anytype) !void { |
| 98 | const shdrs = elf_file.sections.items(.shdr); | ||
| 99 | |||
| 98 | // NEEDED | 100 | // NEEDED |
| 99 | for (dt.needed.items) |off| { | 101 | for (dt.needed.items) |off| { |
| 100 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NEEDED, .d_val = off }); | 102 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_NEEDED, .d_val = off }); |
| ... | @@ -112,33 +114,33 @@ pub const DynamicSection = struct { | ... | @@ -112,33 +114,33 @@ pub const DynamicSection = struct { |
| 112 | 114 | ||
| 113 | // INIT | 115 | // INIT |
| 114 | if (elf_file.sectionByName(".init")) |shndx| { | 116 | if (elf_file.sectionByName(".init")) |shndx| { |
| 115 | const addr = elf_file.shdrs.items[shndx].sh_addr; | 117 | const addr = shdrs[shndx].sh_addr; |
| 116 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT, .d_val = addr }); | 118 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT, .d_val = addr }); |
| 117 | } | 119 | } |
| 118 | 120 | ||
| 119 | // FINI | 121 | // FINI |
| 120 | if (elf_file.sectionByName(".fini")) |shndx| { | 122 | if (elf_file.sectionByName(".fini")) |shndx| { |
| 121 | const addr = elf_file.shdrs.items[shndx].sh_addr; | 123 | const addr = shdrs[shndx].sh_addr; |
| 122 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI, .d_val = addr }); | 124 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI, .d_val = addr }); |
| 123 | } | 125 | } |
| 124 | 126 | ||
| 125 | // INIT_ARRAY | 127 | // INIT_ARRAY |
| 126 | if (elf_file.sectionByName(".init_array")) |shndx| { | 128 | if (elf_file.sectionByName(".init_array")) |shndx| { |
| 127 | const shdr = elf_file.shdrs.items[shndx]; | 129 | const shdr = shdrs[shndx]; |
| 128 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAY, .d_val = shdr.sh_addr }); | 130 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAY, .d_val = shdr.sh_addr }); |
| 129 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAYSZ, .d_val = shdr.sh_size }); | 131 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_INIT_ARRAYSZ, .d_val = shdr.sh_size }); |
| 130 | } | 132 | } |
| 131 | 133 | ||
| 132 | // FINI_ARRAY | 134 | // FINI_ARRAY |
| 133 | if (elf_file.sectionByName(".fini_array")) |shndx| { | 135 | if (elf_file.sectionByName(".fini_array")) |shndx| { |
| 134 | const shdr = elf_file.shdrs.items[shndx]; | 136 | const shdr = shdrs[shndx]; |
| 135 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAY, .d_val = shdr.sh_addr }); | 137 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAY, .d_val = shdr.sh_addr }); |
| 136 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAYSZ, .d_val = shdr.sh_size }); | 138 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_FINI_ARRAYSZ, .d_val = shdr.sh_size }); |
| 137 | } | 139 | } |
| 138 | 140 | ||
| 139 | // RELA | 141 | // RELA |
| 140 | if (elf_file.rela_dyn_section_index) |shndx| { | 142 | if (elf_file.rela_dyn_section_index) |shndx| { |
| 141 | const shdr = elf_file.shdrs.items[shndx]; | 143 | const shdr = shdrs[shndx]; |
| 142 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr }); | 144 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr }); |
| 143 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size }); | 145 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size }); |
| 144 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELAENT, .d_val = shdr.sh_entsize }); | 146 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELAENT, .d_val = shdr.sh_entsize }); |
| ... | @@ -146,7 +148,7 @@ pub const DynamicSection = struct { | ... | @@ -146,7 +148,7 @@ pub const DynamicSection = struct { |
| 146 | 148 | ||
| 147 | // JMPREL | 149 | // JMPREL |
| 148 | if (elf_file.rela_plt_section_index) |shndx| { | 150 | if (elf_file.rela_plt_section_index) |shndx| { |
| 149 | const shdr = elf_file.shdrs.items[shndx]; | 151 | const shdr = shdrs[shndx]; |
| 150 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr }); | 152 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr }); |
| 151 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size }); | 153 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size }); |
| 152 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTREL, .d_val = elf.DT_RELA }); | 154 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTREL, .d_val = elf.DT_RELA }); |
| ... | @@ -154,18 +156,18 @@ pub const DynamicSection = struct { | ... | @@ -154,18 +156,18 @@ pub const DynamicSection = struct { |
| 154 | 156 | ||
| 155 | // PLTGOT | 157 | // PLTGOT |
| 156 | if (elf_file.got_plt_section_index) |shndx| { | 158 | if (elf_file.got_plt_section_index) |shndx| { |
| 157 | const addr = elf_file.shdrs.items[shndx].sh_addr; | 159 | const addr = shdrs[shndx].sh_addr; |
| 158 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTGOT, .d_val = addr }); | 160 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTGOT, .d_val = addr }); |
| 159 | } | 161 | } |
| 160 | 162 | ||
| 161 | { | 163 | { |
| 162 | assert(elf_file.hash_section_index != null); | 164 | assert(elf_file.hash_section_index != null); |
| 163 | const addr = elf_file.shdrs.items[elf_file.hash_section_index.?].sh_addr; | 165 | const addr = shdrs[elf_file.hash_section_index.?].sh_addr; |
| 164 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_HASH, .d_val = addr }); | 166 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_HASH, .d_val = addr }); |
| 165 | } | 167 | } |
| 166 | 168 | ||
| 167 | if (elf_file.gnu_hash_section_index) |shndx| { | 169 | if (elf_file.gnu_hash_section_index) |shndx| { |
| 168 | const addr = elf_file.shdrs.items[shndx].sh_addr; | 170 | const addr = shdrs[shndx].sh_addr; |
| 169 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_GNU_HASH, .d_val = addr }); | 171 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_GNU_HASH, .d_val = addr }); |
| 170 | } | 172 | } |
| 171 | 173 | ||
| ... | @@ -177,7 +179,7 @@ pub const DynamicSection = struct { | ... | @@ -177,7 +179,7 @@ pub const DynamicSection = struct { |
| 177 | // SYMTAB + SYMENT | 179 | // SYMTAB + SYMENT |
| 178 | { | 180 | { |
| 179 | assert(elf_file.dynsymtab_section_index != null); | 181 | assert(elf_file.dynsymtab_section_index != null); |
| 180 | const shdr = elf_file.shdrs.items[elf_file.dynsymtab_section_index.?]; | 182 | const shdr = shdrs[elf_file.dynsymtab_section_index.?]; |
| 181 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMTAB, .d_val = shdr.sh_addr }); | 183 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMTAB, .d_val = shdr.sh_addr }); |
| 182 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize }); | 184 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize }); |
| 183 | } | 185 | } |
| ... | @@ -185,20 +187,20 @@ pub const DynamicSection = struct { | ... | @@ -185,20 +187,20 @@ pub const DynamicSection = struct { |
| 185 | // STRTAB + STRSZ | 187 | // STRTAB + STRSZ |
| 186 | { | 188 | { |
| 187 | assert(elf_file.dynstrtab_section_index != null); | 189 | assert(elf_file.dynstrtab_section_index != null); |
| 188 | const shdr = elf_file.shdrs.items[elf_file.dynstrtab_section_index.?]; | 190 | const shdr = shdrs[elf_file.dynstrtab_section_index.?]; |
| 189 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRTAB, .d_val = shdr.sh_addr }); | 191 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRTAB, .d_val = shdr.sh_addr }); |
| 190 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size }); | 192 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size }); |
| 191 | } | 193 | } |
| 192 | 194 | ||
| 193 | // VERSYM | 195 | // VERSYM |
| 194 | if (elf_file.versym_section_index) |shndx| { | 196 | if (elf_file.versym_section_index) |shndx| { |
| 195 | const addr = elf_file.shdrs.items[shndx].sh_addr; | 197 | const addr = shdrs[shndx].sh_addr; |
| 196 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERSYM, .d_val = addr }); | 198 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERSYM, .d_val = addr }); |
| 197 | } | 199 | } |
| 198 | 200 | ||
| 199 | // VERNEED + VERNEEDNUM | 201 | // VERNEED + VERNEEDNUM |
| 200 | if (elf_file.verneed_section_index) |shndx| { | 202 | if (elf_file.verneed_section_index) |shndx| { |
| 201 | const addr = elf_file.shdrs.items[shndx].sh_addr; | 203 | const addr = shdrs[shndx].sh_addr; |
| 202 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERNEED, .d_val = addr }); | 204 | try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERNEED, .d_val = addr }); |
| 203 | try writer.writeStruct(elf.Elf64_Dyn{ | 205 | try writer.writeStruct(elf.Elf64_Dyn{ |
| 204 | .d_tag = elf.DT_VERNEEDNUM, | 206 | .d_tag = elf.DT_VERNEEDNUM, |
| ... | @@ -259,7 +261,7 @@ pub const GotSection = struct { | ... | @@ -259,7 +261,7 @@ pub const GotSection = struct { |
| 259 | 261 | ||
| 260 | pub fn address(entry: Entry, elf_file: *Elf) i64 { | 262 | pub fn address(entry: Entry, elf_file: *Elf) i64 { |
| 261 | const ptr_bytes = elf_file.archPtrWidthBytes(); | 263 | const ptr_bytes = elf_file.archPtrWidthBytes(); |
| 262 | const shdr = &elf_file.shdrs.items[elf_file.got_section_index.?]; | 264 | const shdr = &elf_file.sections.items(.shdr)[elf_file.got_section_index.?]; |
| 263 | return @as(i64, @intCast(shdr.sh_addr)) + entry.cell_index * ptr_bytes; | 265 | return @as(i64, @intCast(shdr.sh_addr)) + entry.cell_index * ptr_bytes; |
| 264 | } | 266 | } |
| 265 | }; | 267 | }; |
| ... | @@ -759,8 +761,9 @@ pub const PltSection = struct { | ... | @@ -759,8 +761,9 @@ pub const PltSection = struct { |
| 759 | 761 | ||
| 760 | const x86_64 = struct { | 762 | const x86_64 = struct { |
| 761 | fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void { | 763 | fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void { |
| 762 | const plt_addr = elf_file.shdrs.items[elf_file.plt_section_index.?].sh_addr; | 764 | const shdrs = elf_file.sections.items(.shdr); |
| 763 | const got_plt_addr = elf_file.shdrs.items[elf_file.got_plt_section_index.?].sh_addr; | 765 | const plt_addr = shdrs[elf_file.plt_section_index.?].sh_addr; |
| 766 | const got_plt_addr = shdrs[elf_file.got_plt_section_index.?].sh_addr; | ||
| 764 | var preamble = [_]u8{ | 767 | var preamble = [_]u8{ |
| 765 | 0xf3, 0x0f, 0x1e, 0xfa, // endbr64 | 768 | 0xf3, 0x0f, 0x1e, 0xfa, // endbr64 |
| 766 | 0x41, 0x53, // push r11 | 769 | 0x41, 0x53, // push r11 |
| ... | @@ -794,8 +797,9 @@ pub const PltSection = struct { | ... | @@ -794,8 +797,9 @@ pub const PltSection = struct { |
| 794 | const aarch64 = struct { | 797 | const aarch64 = struct { |
| 795 | fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void { | 798 | fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void { |
| 796 | { | 799 | { |
| 797 | const plt_addr: i64 = @intCast(elf_file.shdrs.items[elf_file.plt_section_index.?].sh_addr); | 800 | const shdrs = elf_file.sections.items(.shdr); |
| 798 | const got_plt_addr: i64 = @intCast(elf_file.shdrs.items[elf_file.got_plt_section_index.?].sh_addr); | 801 | const plt_addr: i64 = @intCast(shdrs[elf_file.plt_section_index.?].sh_addr); |
| 802 | const got_plt_addr: i64 = @intCast(shdrs[elf_file.got_plt_section_index.?].sh_addr); | ||
| 799 | // TODO: relax if possible | 803 | // TODO: relax if possible |
| 800 | // .got.plt[2] | 804 | // .got.plt[2] |
| 801 | const pages = try aarch64_util.calcNumberOfPages(plt_addr + 4, got_plt_addr + 16); | 805 | const pages = try aarch64_util.calcNumberOfPages(plt_addr + 4, got_plt_addr + 16); |
| ... | @@ -869,7 +873,7 @@ pub const GotPltSection = struct { | ... | @@ -869,7 +873,7 @@ pub const GotPltSection = struct { |
| 869 | try writer.writeInt(u64, 0x0, .little); | 873 | try writer.writeInt(u64, 0x0, .little); |
| 870 | try writer.writeInt(u64, 0x0, .little); | 874 | try writer.writeInt(u64, 0x0, .little); |
| 871 | if (elf_file.plt_section_index) |shndx| { | 875 | if (elf_file.plt_section_index) |shndx| { |
| 872 | const plt_addr = elf_file.shdrs.items[shndx].sh_addr; | 876 | const plt_addr = elf_file.sections.items(.shdr)[shndx].sh_addr; |
| 873 | for (0..elf_file.plt.symbols.items.len) |_| { | 877 | for (0..elf_file.plt.symbols.items.len) |_| { |
| 874 | // [N]: .plt | 878 | // [N]: .plt |
| 875 | try writer.writeInt(u64, plt_addr, .little); | 879 | try writer.writeInt(u64, plt_addr, .little); |
| ... | @@ -1027,7 +1031,7 @@ pub const CopyRelSection = struct { | ... | @@ -1027,7 +1031,7 @@ pub const CopyRelSection = struct { |
| 1027 | } | 1031 | } |
| 1028 | 1032 | ||
| 1029 | pub fn updateSectionSize(copy_rel: CopyRelSection, shndx: u32, elf_file: *Elf) !void { | 1033 | pub fn updateSectionSize(copy_rel: CopyRelSection, shndx: u32, elf_file: *Elf) !void { |
| 1030 | const shdr = &elf_file.shdrs.items[shndx]; | 1034 | const shdr = &elf_file.sections.items(.shdr)[shndx]; |
| 1031 | for (copy_rel.symbols.items) |ref| { | 1035 | for (copy_rel.symbols.items) |ref| { |
| 1032 | const symbol = elf_file.symbol(ref).?; | 1036 | const symbol = elf_file.symbol(ref).?; |
| 1033 | const shared_object = symbol.file(elf_file).?.shared_object; | 1037 | const shared_object = symbol.file(elf_file).?.shared_object; |
| ... | @@ -1487,8 +1491,12 @@ pub const ComdatGroupSection = struct { | ... | @@ -1487,8 +1491,12 @@ pub const ComdatGroupSection = struct { |
| 1487 | elf.SHT_RELA => { | 1491 | elf.SHT_RELA => { |
| 1488 | const atom_index = object.atoms_indexes.items[shdr.sh_info]; | 1492 | const atom_index = object.atoms_indexes.items[shdr.sh_info]; |
| 1489 | const atom = object.atom(atom_index).?; | 1493 | const atom = object.atom(atom_index).?; |
| 1490 | const rela = elf_file.output_rela_sections.get(atom.output_section_index).?; | 1494 | const rela_shndx = for (elf_file.sections.items(.shdr), 0..) |rela_shdr, rela_shndx| { |
| 1491 | try writer.writeInt(u32, rela.shndx, .little); | 1495 | if (rela_shdr.sh_type == elf.SHT_RELA and |
| 1496 | atom.output_section_index == rela_shdr.sh_info) | ||
| 1497 | break rela_shndx; | ||
| 1498 | } else unreachable; | ||
| 1499 | try writer.writeInt(u32, @intCast(rela_shndx), .little); | ||
| 1492 | }, | 1500 | }, |
| 1493 | else => { | 1501 | else => { |
| 1494 | const atom_index = object.atoms_indexes.items[shndx]; | 1502 | const atom_index = object.atoms_indexes.items[shndx]; |
src/link/Elf/thunks.zig+3-4| ... | @@ -1,9 +1,8 @@ | ... | @@ -1,9 +1,8 @@ |
| 1 | pub fn createThunks(shndx: u32, elf_file: *Elf) !void { | 1 | pub fn createThunks(shdr: *elf.Elf64_Shdr, shndx: u32, elf_file: *Elf) !void { |
| 2 | const gpa = elf_file.base.comp.gpa; | 2 | const gpa = elf_file.base.comp.gpa; |
| 3 | const cpu_arch = elf_file.getTarget().cpu.arch; | 3 | const cpu_arch = elf_file.getTarget().cpu.arch; |
| 4 | const max_distance = maxAllowedDistance(cpu_arch); | 4 | const max_distance = maxAllowedDistance(cpu_arch); |
| 5 | const shdr = &elf_file.shdrs.items[shndx]; | 5 | const atoms = elf_file.sections.items(.atom_list)[shndx].items; |
| 6 | const atoms = elf_file.output_sections.get(shndx).?.items; | ||
| 7 | assert(atoms.len > 0); | 6 | assert(atoms.len > 0); |
| 8 | 7 | ||
| 9 | for (atoms) |ref| { | 8 | for (atoms) |ref| { |
| ... | @@ -89,7 +88,7 @@ pub const Thunk = struct { | ... | @@ -89,7 +88,7 @@ pub const Thunk = struct { |
| 89 | } | 88 | } |
| 90 | 89 | ||
| 91 | pub fn address(thunk: Thunk, elf_file: *Elf) i64 { | 90 | pub fn address(thunk: Thunk, elf_file: *Elf) i64 { |
| 92 | const shdr = elf_file.shdrs.items[thunk.output_section_index]; | 91 | const shdr = elf_file.sections.items(.shdr)[thunk.output_section_index]; |
| 93 | return @as(i64, @intCast(shdr.sh_addr)) + thunk.value; | 92 | return @as(i64, @intCast(shdr.sh_addr)) + thunk.value; |
| 94 | } | 93 | } |
| 95 | 94 |