| ... | @@ -18,12 +18,13 @@ shared_objects: std.ArrayListUnmanaged(File.Index) = .{}, | ... | @@ -18,12 +18,13 @@ shared_objects: std.ArrayListUnmanaged(File.Index) = .{}, |
| 18 | /// Same order as in the file. | 18 | /// Same order as in the file. |
| 19 | shdrs: std.ArrayListUnmanaged(elf.Elf64_Shdr) = .{}, | 19 | shdrs: std.ArrayListUnmanaged(elf.Elf64_Shdr) = .{}, |
| 20 | /// Given index to a section, pulls index of containing phdr if any. | 20 | /// Given index to a section, pulls index of containing phdr if any. |
| 21 | phdr_to_shdr_table: std.AutoHashMapUnmanaged(u16, u16) = .{}, | 21 | phdr_to_shdr_table: std.AutoHashMapUnmanaged(u32, u32) = .{}, |
| 22 | /// File offset into the shdr table. | 22 | /// File offset into the shdr table. |
| 23 | shdr_table_offset: ?u64 = null, | 23 | shdr_table_offset: ?u64 = null, |
| 24 | /// Table of lists of atoms per output section. | 24 | /// Table of lists of atoms per output section. |
| 25 | /// This table is not used to track incrementally generated atoms. | 25 | /// This table is not used to track incrementally generated atoms. |
| 26 | output_sections: std.AutoArrayHashMapUnmanaged(u16, std.ArrayListUnmanaged(Atom.Index)) = .{}, | 26 | output_sections: std.AutoArrayHashMapUnmanaged(u32, std.ArrayListUnmanaged(Atom.Index)) = .{}, |
| | 27 | output_rela_sections: std.AutoArrayHashMapUnmanaged(u32, RelaSection) = .{}, |
| 27 | | 28 | |
| 28 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. | 29 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. |
| 29 | /// Same order as in the file. | 30 | /// Same order as in the file. |
| ... | @@ -101,15 +102,15 @@ copy_rel: CopyRelSection = .{}, | ... | @@ -101,15 +102,15 @@ copy_rel: CopyRelSection = .{}, |
| 101 | rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{}, | 102 | rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{}, |
| 102 | /// .got.zig section | 103 | /// .got.zig section |
| 103 | zig_got: ZigGotSection = .{}, | 104 | zig_got: ZigGotSection = .{}, |
| | 105 | /// SHT_GROUP sections |
| | 106 | /// Applies only to a relocatable. |
| | 107 | comdat_group_sections: std.ArrayListUnmanaged(ComdatGroupSection) = .{}, |
| 104 | | 108 | |
| 105 | /// Tracked section headers with incremental updates to Zig object. | 109 | /// Tracked section headers with incremental updates to Zig object. |
| 106 | /// .rela.* sections are only used when emitting a relocatable object file. | 110 | /// .rela.* sections are only used when emitting a relocatable object file. |
| 107 | zig_text_section_index: ?u16 = null, | 111 | zig_text_section_index: ?u16 = null, |
| 108 | zig_text_rela_section_index: ?u16 = null, | | |
| 109 | zig_data_rel_ro_section_index: ?u16 = null, | 112 | zig_data_rel_ro_section_index: ?u16 = null, |
| 110 | zig_data_rel_ro_rela_section_index: ?u16 = null, | | |
| 111 | zig_data_section_index: ?u16 = null, | 113 | zig_data_section_index: ?u16 = null, |
| 112 | zig_data_rela_section_index: ?u16 = null, | | |
| 113 | zig_bss_section_index: ?u16 = null, | 114 | zig_bss_section_index: ?u16 = null, |
| 114 | zig_got_section_index: ?u16 = null, | 115 | zig_got_section_index: ?u16 = null, |
| 115 | | 116 | |
| ... | @@ -124,6 +125,7 @@ dynamic_section_index: ?u16 = null, | ... | @@ -124,6 +125,7 @@ dynamic_section_index: ?u16 = null, |
| 124 | dynstrtab_section_index: ?u16 = null, | 125 | dynstrtab_section_index: ?u16 = null, |
| 125 | dynsymtab_section_index: ?u16 = null, | 126 | dynsymtab_section_index: ?u16 = null, |
| 126 | eh_frame_section_index: ?u16 = null, | 127 | eh_frame_section_index: ?u16 = null, |
| | 128 | eh_frame_rela_section_index: ?u16 = null, |
| 127 | eh_frame_hdr_section_index: ?u16 = null, | 129 | eh_frame_hdr_section_index: ?u16 = null, |
| 128 | hash_section_index: ?u16 = null, | 130 | hash_section_index: ?u16 = null, |
| 129 | gnu_hash_section_index: ?u16 = null, | 131 | gnu_hash_section_index: ?u16 = null, |
| ... | @@ -216,10 +218,6 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option | ... | @@ -216,10 +218,6 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option |
| 216 | sub_path, options.target.ofmt.fileExt(options.target.cpu.arch), | 218 | sub_path, options.target.ofmt.fileExt(options.target.cpu.arch), |
| 217 | }); | 219 | }); |
| 218 | } | 220 | } |
| 219 | if (is_obj) { | | |
| 220 | // TODO until we implement -r option, we don't want to open a file at this stage. | | |
| 221 | return self; | | |
| 222 | } | | |
| 223 | } | 221 | } |
| 224 | errdefer if (self.base.intermediary_basename) |path| allocator.free(path); | 222 | errdefer if (self.base.intermediary_basename) |path| allocator.free(path); |
| 225 | | 223 | |
| ... | @@ -361,6 +359,10 @@ pub fn deinit(self: *Elf) void { | ... | @@ -361,6 +359,10 @@ pub fn deinit(self: *Elf) void { |
| 361 | list.deinit(gpa); | 359 | list.deinit(gpa); |
| 362 | } | 360 | } |
| 363 | self.output_sections.deinit(gpa); | 361 | self.output_sections.deinit(gpa); |
| | 362 | for (self.output_rela_sections.values()) |*sec| { |
| | 363 | sec.atom_list.deinit(gpa); |
| | 364 | } |
| | 365 | self.output_rela_sections.deinit(gpa); |
| 364 | self.shstrtab.deinit(gpa); | 366 | self.shstrtab.deinit(gpa); |
| 365 | self.symtab.deinit(gpa); | 367 | self.symtab.deinit(gpa); |
| 366 | self.strtab.deinit(gpa); | 368 | self.strtab.deinit(gpa); |
| ... | @@ -395,6 +397,7 @@ pub fn deinit(self: *Elf) void { | ... | @@ -395,6 +397,7 @@ pub fn deinit(self: *Elf) void { |
| 395 | self.rela_dyn.deinit(gpa); | 397 | self.rela_dyn.deinit(gpa); |
| 396 | self.rela_plt.deinit(gpa); | 398 | self.rela_plt.deinit(gpa); |
| 397 | self.zig_got.deinit(gpa); | 399 | self.zig_got.deinit(gpa); |
| | 400 | self.comdat_group_sections.deinit(gpa); |
| 398 | } | 401 | } |
| 399 | | 402 | |
| 400 | pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link.File.RelocInfo) !u64 { | 403 | pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link.File.RelocInfo) !u64 { |
| ... | @@ -601,11 +604,10 @@ pub fn initMetadata(self: *Elf) !void { | ... | @@ -601,11 +604,10 @@ pub fn initMetadata(self: *Elf) !void { |
| 601 | const shdr = &self.shdrs.items[self.zig_text_section_index.?]; | 604 | const shdr = &self.shdrs.items[self.zig_text_section_index.?]; |
| 602 | fillSection(self, shdr, self.base.options.program_code_size_hint, self.phdr_zig_load_re_index); | 605 | fillSection(self, shdr, self.base.options.program_code_size_hint, self.phdr_zig_load_re_index); |
| 603 | if (self.isRelocatable()) { | 606 | if (self.isRelocatable()) { |
| 604 | try zig_object.addSectionSymbol(self.zig_text_section_index.?, self); | 607 | const rela_shndx = try self.addRelaShdr(".rela.text.zig", self.zig_text_section_index.?); |
| 605 | self.zig_text_rela_section_index = try self.addRelaShdr( | 608 | try self.output_rela_sections.putNoClobber(gpa, self.zig_text_section_index.?, .{ |
| 606 | ".rela.text.zig", | 609 | .shndx = rela_shndx, |
| 607 | self.zig_text_section_index.?, | 610 | }); |
| 608 | ); | | |
| 609 | } else { | 611 | } else { |
| 610 | try self.phdr_to_shdr_table.putNoClobber( | 612 | try self.phdr_to_shdr_table.putNoClobber( |
| 611 | gpa, | 613 | gpa, |
| ... | @@ -613,6 +615,7 @@ pub fn initMetadata(self: *Elf) !void { | ... | @@ -613,6 +615,7 @@ pub fn initMetadata(self: *Elf) !void { |
| 613 | self.phdr_zig_load_re_index.?, | 615 | self.phdr_zig_load_re_index.?, |
| 614 | ); | 616 | ); |
| 615 | } | 617 | } |
| | 618 | try self.output_sections.putNoClobber(gpa, self.zig_text_section_index.?, .{}); |
| 616 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_text_section_index.?, .{}); | 619 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_text_section_index.?, .{}); |
| 617 | } | 620 | } |
| 618 | | 621 | |
| ... | @@ -642,17 +645,19 @@ pub fn initMetadata(self: *Elf) !void { | ... | @@ -642,17 +645,19 @@ pub fn initMetadata(self: *Elf) !void { |
| 642 | .name = ".data.rel.ro.zig", | 645 | .name = ".data.rel.ro.zig", |
| 643 | .type = elf.SHT_PROGBITS, | 646 | .type = elf.SHT_PROGBITS, |
| 644 | .addralign = 1, | 647 | .addralign = 1, |
| 645 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, // TODO rename this section to .data.rel.ro | 648 | .flags = elf.SHF_ALLOC | elf.SHF_WRITE, |
| 646 | .offset = std.math.maxInt(u64), | 649 | .offset = std.math.maxInt(u64), |
| 647 | }); | 650 | }); |
| 648 | const shdr = &self.shdrs.items[self.zig_data_rel_ro_section_index.?]; | 651 | const shdr = &self.shdrs.items[self.zig_data_rel_ro_section_index.?]; |
| 649 | fillSection(self, shdr, 1024, self.phdr_zig_load_ro_index); | 652 | fillSection(self, shdr, 1024, self.phdr_zig_load_ro_index); |
| 650 | if (self.isRelocatable()) { | 653 | if (self.isRelocatable()) { |
| 651 | try zig_object.addSectionSymbol(self.zig_data_rel_ro_section_index.?, self); | 654 | const rela_shndx = try self.addRelaShdr( |
| 652 | self.zig_data_rel_ro_rela_section_index = try self.addRelaShdr( | | |
| 653 | ".rela.data.rel.ro.zig", | 655 | ".rela.data.rel.ro.zig", |
| 654 | self.zig_data_rel_ro_section_index.?, | 656 | self.zig_data_rel_ro_section_index.?, |
| 655 | ); | 657 | ); |
| | 658 | try self.output_rela_sections.putNoClobber(gpa, self.zig_data_rel_ro_section_index.?, .{ |
| | 659 | .shndx = rela_shndx, |
| | 660 | }); |
| 656 | } else { | 661 | } else { |
| 657 | try self.phdr_to_shdr_table.putNoClobber( | 662 | try self.phdr_to_shdr_table.putNoClobber( |
| 658 | gpa, | 663 | gpa, |
| ... | @@ -660,6 +665,7 @@ pub fn initMetadata(self: *Elf) !void { | ... | @@ -660,6 +665,7 @@ pub fn initMetadata(self: *Elf) !void { |
| 660 | self.phdr_zig_load_ro_index.?, | 665 | self.phdr_zig_load_ro_index.?, |
| 661 | ); | 666 | ); |
| 662 | } | 667 | } |
| | 668 | try self.output_sections.putNoClobber(gpa, self.zig_data_rel_ro_section_index.?, .{}); |
| 663 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_data_rel_ro_section_index.?, .{}); | 669 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_data_rel_ro_section_index.?, .{}); |
| 664 | } | 670 | } |
| 665 | | 671 | |
| ... | @@ -674,11 +680,13 @@ pub fn initMetadata(self: *Elf) !void { | ... | @@ -674,11 +680,13 @@ pub fn initMetadata(self: *Elf) !void { |
| 674 | const shdr = &self.shdrs.items[self.zig_data_section_index.?]; | 680 | const shdr = &self.shdrs.items[self.zig_data_section_index.?]; |
| 675 | fillSection(self, shdr, 1024, self.phdr_zig_load_rw_index); | 681 | fillSection(self, shdr, 1024, self.phdr_zig_load_rw_index); |
| 676 | if (self.isRelocatable()) { | 682 | if (self.isRelocatable()) { |
| 677 | try zig_object.addSectionSymbol(self.zig_data_section_index.?, self); | 683 | const rela_shndx = try self.addRelaShdr( |
| 678 | self.zig_data_rela_section_index = try self.addRelaShdr( | | |
| 679 | ".rela.data.zig", | 684 | ".rela.data.zig", |
| 680 | self.zig_data_section_index.?, | 685 | self.zig_data_section_index.?, |
| 681 | ); | 686 | ); |
| | 687 | try self.output_rela_sections.putNoClobber(gpa, self.zig_data_section_index.?, .{ |
| | 688 | .shndx = rela_shndx, |
| | 689 | }); |
| 682 | } else { | 690 | } else { |
| 683 | try self.phdr_to_shdr_table.putNoClobber( | 691 | try self.phdr_to_shdr_table.putNoClobber( |
| 684 | gpa, | 692 | gpa, |
| ... | @@ -686,6 +694,7 @@ pub fn initMetadata(self: *Elf) !void { | ... | @@ -686,6 +694,7 @@ pub fn initMetadata(self: *Elf) !void { |
| 686 | self.phdr_zig_load_rw_index.?, | 694 | self.phdr_zig_load_rw_index.?, |
| 687 | ); | 695 | ); |
| 688 | } | 696 | } |
| | 697 | try self.output_sections.putNoClobber(gpa, self.zig_data_section_index.?, .{}); |
| 689 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_data_section_index.?, .{}); | 698 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_data_section_index.?, .{}); |
| 690 | } | 699 | } |
| 691 | | 700 | |
| ... | @@ -704,9 +713,9 @@ pub fn initMetadata(self: *Elf) !void { | ... | @@ -704,9 +713,9 @@ pub fn initMetadata(self: *Elf) !void { |
| 704 | shdr.sh_size = phdr.p_memsz; | 713 | shdr.sh_size = phdr.p_memsz; |
| 705 | try self.phdr_to_shdr_table.putNoClobber(gpa, self.zig_bss_section_index.?, phndx); | 714 | try self.phdr_to_shdr_table.putNoClobber(gpa, self.zig_bss_section_index.?, phndx); |
| 706 | } else { | 715 | } else { |
| 707 | try zig_object.addSectionSymbol(self.zig_bss_section_index.?, self); | | |
| 708 | shdr.sh_size = 1024; | 716 | shdr.sh_size = 1024; |
| 709 | } | 717 | } |
| | 718 | try self.output_sections.putNoClobber(gpa, self.zig_bss_section_index.?, .{}); |
| 710 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_bss_section_index.?, .{}); | 719 | try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_bss_section_index.?, .{}); |
| 711 | } | 720 | } |
| 712 | | 721 | |
| ... | @@ -728,6 +737,7 @@ pub fn initMetadata(self: *Elf) !void { | ... | @@ -728,6 +737,7 @@ pub fn initMetadata(self: *Elf) !void { |
| 728 | shdr.sh_offset = off; | 737 | shdr.sh_offset = off; |
| 729 | shdr.sh_size = size; | 738 | shdr.sh_size = size; |
| 730 | zig_object.debug_strtab_dirty = true; | 739 | zig_object.debug_strtab_dirty = true; |
| | 740 | try self.output_sections.putNoClobber(gpa, self.debug_str_section_index.?, .{}); |
| 731 | } | 741 | } |
| 732 | | 742 | |
| 733 | if (self.debug_info_section_index == null) { | 743 | if (self.debug_info_section_index == null) { |
| ... | @@ -743,6 +753,7 @@ pub fn initMetadata(self: *Elf) !void { | ... | @@ -743,6 +753,7 @@ pub fn initMetadata(self: *Elf) !void { |
| 743 | shdr.sh_offset = off; | 753 | shdr.sh_offset = off; |
| 744 | shdr.sh_size = size; | 754 | shdr.sh_size = size; |
| 745 | zig_object.debug_info_header_dirty = true; | 755 | zig_object.debug_info_header_dirty = true; |
| | 756 | try self.output_sections.putNoClobber(gpa, self.debug_info_section_index.?, .{}); |
| 746 | } | 757 | } |
| 747 | | 758 | |
| 748 | if (self.debug_abbrev_section_index == null) { | 759 | if (self.debug_abbrev_section_index == null) { |
| ... | @@ -758,6 +769,7 @@ pub fn initMetadata(self: *Elf) !void { | ... | @@ -758,6 +769,7 @@ pub fn initMetadata(self: *Elf) !void { |
| 758 | shdr.sh_offset = off; | 769 | shdr.sh_offset = off; |
| 759 | shdr.sh_size = size; | 770 | shdr.sh_size = size; |
| 760 | zig_object.debug_abbrev_section_dirty = true; | 771 | zig_object.debug_abbrev_section_dirty = true; |
| | 772 | try self.output_sections.putNoClobber(gpa, self.debug_abbrev_section_index.?, .{}); |
| 761 | } | 773 | } |
| 762 | | 774 | |
| 763 | if (self.debug_aranges_section_index == null) { | 775 | if (self.debug_aranges_section_index == null) { |
| ... | @@ -773,6 +785,7 @@ pub fn initMetadata(self: *Elf) !void { | ... | @@ -773,6 +785,7 @@ pub fn initMetadata(self: *Elf) !void { |
| 773 | shdr.sh_offset = off; | 785 | shdr.sh_offset = off; |
| 774 | shdr.sh_size = size; | 786 | shdr.sh_size = size; |
| 775 | zig_object.debug_aranges_section_dirty = true; | 787 | zig_object.debug_aranges_section_dirty = true; |
| | 788 | try self.output_sections.putNoClobber(gpa, self.debug_aranges_section_index.?, .{}); |
| 776 | } | 789 | } |
| 777 | | 790 | |
| 778 | if (self.debug_line_section_index == null) { | 791 | if (self.debug_line_section_index == null) { |
| ... | @@ -788,8 +801,17 @@ pub fn initMetadata(self: *Elf) !void { | ... | @@ -788,8 +801,17 @@ pub fn initMetadata(self: *Elf) !void { |
| 788 | shdr.sh_offset = off; | 801 | shdr.sh_offset = off; |
| 789 | shdr.sh_size = size; | 802 | shdr.sh_size = size; |
| 790 | zig_object.debug_line_header_dirty = true; | 803 | zig_object.debug_line_header_dirty = true; |
| | 804 | try self.output_sections.putNoClobber(gpa, self.debug_line_section_index.?, .{}); |
| 791 | } | 805 | } |
| 792 | } | 806 | } |
| | 807 | |
| | 808 | // We need to find current max assumed file offset, and actually write to file to make it a reality. |
| | 809 | var end_pos: u64 = 0; |
| | 810 | for (self.shdrs.items) |shdr| { |
| | 811 | if (shdr.sh_offset == std.math.maxInt(u64)) continue; |
| | 812 | end_pos = @max(end_pos, shdr.sh_offset + shdr.sh_size); |
| | 813 | } |
| | 814 | try self.base.file.?.pwriteAll(&[1]u8{0}, end_pos); |
| 793 | } | 815 | } |
| 794 | | 816 | |
| 795 | pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void { | 817 | pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void { |
| ... | @@ -942,30 +964,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -942,30 +964,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 942 | } else null; | 964 | } else null; |
| 943 | const gc_sections = self.base.options.gc_sections orelse false; | 965 | const gc_sections = self.base.options.gc_sections orelse false; |
| 944 | | 966 | |
| 945 | if (self.isObject() and self.zig_object_index == null) { | 967 | // --verbose-link |
| 946 | // TODO this will become -r route I guess. For now, just copy the object file. | 968 | if (self.base.options.verbose_link) try self.dumpArgv(comp); |
| 947 | const the_object_path = blk: { | | |
| 948 | if (self.base.options.objects.len != 0) { | | |
| 949 | break :blk self.base.options.objects[0].path; | | |
| 950 | } | | |
| 951 | | | |
| 952 | if (comp.c_object_table.count() != 0) | | |
| 953 | break :blk comp.c_object_table.keys()[0].status.success.object_path; | | |
| 954 | | | |
| 955 | if (module_obj_path) |p| | | |
| 956 | break :blk p; | | |
| 957 | | | |
| 958 | // TODO I think this is unreachable. Audit this situation when solving the above TODO | | |
| 959 | // regarding eliding redundant object -> object transformations. | | |
| 960 | return error.NoObjectsToLink; | | |
| 961 | }; | | |
| 962 | // This can happen when using --enable-cache and using the stage1 backend. In this case | | |
| 963 | // we can skip the file copy. | | |
| 964 | if (!mem.eql(u8, the_object_path, full_out_path)) { | | |
| 965 | try fs.cwd().copyFile(the_object_path, fs.cwd(), full_out_path, .{}); | | |
| 966 | } | | |
| 967 | return; | | |
| 968 | } | | |
| 969 | | 969 | |
| 970 | var csu = try CsuObjects.init(arena, self.base.options, comp); | 970 | var csu = try CsuObjects.init(arena, self.base.options, comp); |
| 971 | const compiler_rt_path: ?[]const u8 = blk: { | 971 | const compiler_rt_path: ?[]const u8 = blk: { |
| ... | @@ -974,247 +974,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -974,247 +974,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 974 | break :blk null; | 974 | break :blk null; |
| 975 | }; | 975 | }; |
| 976 | | 976 | |
| 977 | // --verbose-link | | |
| 978 | if (self.base.options.verbose_link) { | | |
| 979 | var argv = std.ArrayList([]const u8).init(arena); | | |
| 980 | | | |
| 981 | try argv.append("zig"); | | |
| 982 | try argv.append("ld"); | | |
| 983 | | | |
| 984 | try argv.append("-o"); | | |
| 985 | try argv.append(full_out_path); | | |
| 986 | | | |
| 987 | if (self.base.options.entry) |entry| { | | |
| 988 | try argv.append("--entry"); | | |
| 989 | try argv.append(entry); | | |
| 990 | } | | |
| 991 | | | |
| 992 | if (self.base.options.dynamic_linker) |path| { | | |
| 993 | try argv.append("-dynamic-linker"); | | |
| 994 | try argv.append(path); | | |
| 995 | } | | |
| 996 | | | |
| 997 | if (self.base.options.soname) |name| { | | |
| 998 | try argv.append("-soname"); | | |
| 999 | try argv.append(name); | | |
| 1000 | } | | |
| 1001 | | | |
| 1002 | for (self.base.options.rpath_list) |rpath| { | | |
| 1003 | try argv.append("-rpath"); | | |
| 1004 | try argv.append(rpath); | | |
| 1005 | } | | |
| 1006 | | | |
| 1007 | if (self.base.options.each_lib_rpath) { | | |
| 1008 | for (self.base.options.lib_dirs) |lib_dir_path| { | | |
| 1009 | try argv.append("-rpath"); | | |
| 1010 | try argv.append(lib_dir_path); | | |
| 1011 | } | | |
| 1012 | for (self.base.options.objects) |obj| { | | |
| 1013 | if (Compilation.classifyFileExt(obj.path) == .shared_library) { | | |
| 1014 | const lib_dir_path = std.fs.path.dirname(obj.path) orelse continue; | | |
| 1015 | if (obj.loption) continue; | | |
| 1016 | | | |
| 1017 | try argv.append("-rpath"); | | |
| 1018 | try argv.append(lib_dir_path); | | |
| 1019 | } | | |
| 1020 | } | | |
| 1021 | } | | |
| 1022 | | | |
| 1023 | if (self.base.options.stack_size_override) |ss| { | | |
| 1024 | try argv.append("-z"); | | |
| 1025 | try argv.append(try std.fmt.allocPrint(arena, "stack-size={d}", .{ss})); | | |
| 1026 | } | | |
| 1027 | | | |
| 1028 | if (self.base.options.image_base_override) |image_base| { | | |
| 1029 | try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{image_base})); | | |
| 1030 | } | | |
| 1031 | | | |
| 1032 | if (gc_sections) { | | |
| 1033 | try argv.append("--gc-sections"); | | |
| 1034 | } | | |
| 1035 | | | |
| 1036 | if (self.base.options.print_gc_sections) { | | |
| 1037 | try argv.append("--print-gc-sections"); | | |
| 1038 | } | | |
| 1039 | | | |
| 1040 | if (self.base.options.eh_frame_hdr) { | | |
| 1041 | try argv.append("--eh-frame-hdr"); | | |
| 1042 | } | | |
| 1043 | | | |
| 1044 | if (self.base.options.rdynamic) { | | |
| 1045 | try argv.append("--export-dynamic"); | | |
| 1046 | } | | |
| 1047 | | | |
| 1048 | if (self.base.options.strip) { | | |
| 1049 | try argv.append("-s"); | | |
| 1050 | } | | |
| 1051 | | | |
| 1052 | if (self.base.options.z_notext) { | | |
| 1053 | try argv.append("-z"); | | |
| 1054 | try argv.append("notext"); | | |
| 1055 | } | | |
| 1056 | | | |
| 1057 | if (self.base.options.z_nocopyreloc) { | | |
| 1058 | try argv.append("-z"); | | |
| 1059 | try argv.append("nocopyreloc"); | | |
| 1060 | } | | |
| 1061 | | | |
| 1062 | if (self.base.options.z_now) { | | |
| 1063 | try argv.append("-z"); | | |
| 1064 | try argv.append("now"); | | |
| 1065 | } | | |
| 1066 | | | |
| 1067 | if (self.isStatic()) { | | |
| 1068 | try argv.append("-static"); | | |
| 1069 | } else if (self.isDynLib()) { | | |
| 1070 | try argv.append("-shared"); | | |
| 1071 | } | | |
| 1072 | | | |
| 1073 | if (self.base.options.pie and self.isExe()) { | | |
| 1074 | try argv.append("-pie"); | | |
| 1075 | } | | |
| 1076 | | | |
| 1077 | // csu prelude | | |
| 1078 | if (csu.crt0) |v| try argv.append(v); | | |
| 1079 | if (csu.crti) |v| try argv.append(v); | | |
| 1080 | if (csu.crtbegin) |v| try argv.append(v); | | |
| 1081 | | | |
| 1082 | for (self.base.options.lib_dirs) |lib_dir| { | | |
| 1083 | try argv.append("-L"); | | |
| 1084 | try argv.append(lib_dir); | | |
| 1085 | } | | |
| 1086 | | | |
| 1087 | if (self.base.options.link_libc) { | | |
| 1088 | if (self.base.options.libc_installation) |libc_installation| { | | |
| 1089 | try argv.append("-L"); | | |
| 1090 | try argv.append(libc_installation.crt_dir.?); | | |
| 1091 | } | | |
| 1092 | } | | |
| 1093 | | | |
| 1094 | var whole_archive = false; | | |
| 1095 | for (self.base.options.objects) |obj| { | | |
| 1096 | if (obj.must_link and !whole_archive) { | | |
| 1097 | try argv.append("-whole-archive"); | | |
| 1098 | whole_archive = true; | | |
| 1099 | } else if (!obj.must_link and whole_archive) { | | |
| 1100 | try argv.append("-no-whole-archive"); | | |
| 1101 | whole_archive = false; | | |
| 1102 | } | | |
| 1103 | | | |
| 1104 | if (obj.loption) { | | |
| 1105 | assert(obj.path[0] == ':'); | | |
| 1106 | try argv.append("-l"); | | |
| 1107 | } | | |
| 1108 | try argv.append(obj.path); | | |
| 1109 | } | | |
| 1110 | if (whole_archive) { | | |
| 1111 | try argv.append("-no-whole-archive"); | | |
| 1112 | whole_archive = false; | | |
| 1113 | } | | |
| 1114 | | | |
| 1115 | for (comp.c_object_table.keys()) |key| { | | |
| 1116 | try argv.append(key.status.success.object_path); | | |
| 1117 | } | | |
| 1118 | | | |
| 1119 | if (module_obj_path) |p| { | | |
| 1120 | try argv.append(p); | | |
| 1121 | } | | |
| 1122 | | | |
| 1123 | // TSAN | | |
| 1124 | if (self.base.options.tsan) { | | |
| 1125 | try argv.append(comp.tsan_static_lib.?.full_object_path); | | |
| 1126 | } | | |
| 1127 | | | |
| 1128 | // libc | | |
| 1129 | if (!self.base.options.skip_linker_dependencies and | | |
| 1130 | !self.base.options.link_libc) | | |
| 1131 | { | | |
| 1132 | if (comp.libc_static_lib) |lib| { | | |
| 1133 | try argv.append(lib.full_object_path); | | |
| 1134 | } | | |
| 1135 | } | | |
| 1136 | | | |
| 1137 | // stack-protector. | | |
| 1138 | // Related: https://github.com/ziglang/zig/issues/7265 | | |
| 1139 | if (comp.libssp_static_lib) |ssp| { | | |
| 1140 | try argv.append(ssp.full_object_path); | | |
| 1141 | } | | |
| 1142 | | | |
| 1143 | // Shared libraries. | | |
| 1144 | // Worst-case, we need an --as-needed argument for every lib, as well | | |
| 1145 | // as one before and one after. | | |
| 1146 | try argv.ensureUnusedCapacity(self.base.options.system_libs.keys().len * 2 + 2); | | |
| 1147 | argv.appendAssumeCapacity("--as-needed"); | | |
| 1148 | var as_needed = true; | | |
| 1149 | | | |
| 1150 | for (self.base.options.system_libs.values()) |lib_info| { | | |
| 1151 | const lib_as_needed = !lib_info.needed; | | |
| 1152 | switch ((@as(u2, @intFromBool(lib_as_needed)) << 1) | @intFromBool(as_needed)) { | | |
| 1153 | 0b00, 0b11 => {}, | | |
| 1154 | 0b01 => { | | |
| 1155 | argv.appendAssumeCapacity("--no-as-needed"); | | |
| 1156 | as_needed = false; | | |
| 1157 | }, | | |
| 1158 | 0b10 => { | | |
| 1159 | argv.appendAssumeCapacity("--as-needed"); | | |
| 1160 | as_needed = true; | | |
| 1161 | }, | | |
| 1162 | } | | |
| 1163 | argv.appendAssumeCapacity(lib_info.path.?); | | |
| 1164 | } | | |
| 1165 | | | |
| 1166 | if (!as_needed) { | | |
| 1167 | argv.appendAssumeCapacity("--as-needed"); | | |
| 1168 | as_needed = true; | | |
| 1169 | } | | |
| 1170 | | | |
| 1171 | // libc++ dep | | |
| 1172 | if (self.base.options.link_libcpp) { | | |
| 1173 | try argv.append(comp.libcxxabi_static_lib.?.full_object_path); | | |
| 1174 | try argv.append(comp.libcxx_static_lib.?.full_object_path); | | |
| 1175 | } | | |
| 1176 | | | |
| 1177 | // libunwind dep | | |
| 1178 | if (self.base.options.link_libunwind) { | | |
| 1179 | try argv.append(comp.libunwind_static_lib.?.full_object_path); | | |
| 1180 | } | | |
| 1181 | | | |
| 1182 | // libc dep | | |
| 1183 | if (self.base.options.link_libc) { | | |
| 1184 | if (self.base.options.libc_installation != null) { | | |
| 1185 | const needs_grouping = self.base.options.link_mode == .Static; | | |
| 1186 | if (needs_grouping) try argv.append("--start-group"); | | |
| 1187 | try argv.appendSlice(target_util.libcFullLinkFlags(target)); | | |
| 1188 | if (needs_grouping) try argv.append("--end-group"); | | |
| 1189 | } else if (target.isGnuLibC()) { | | |
| 1190 | for (glibc.libs) |lib| { | | |
| 1191 | const lib_path = try std.fmt.allocPrint(arena, "{s}{c}lib{s}.so.{d}", .{ | | |
| 1192 | comp.glibc_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover, | | |
| 1193 | }); | | |
| 1194 | try argv.append(lib_path); | | |
| 1195 | } | | |
| 1196 | try argv.append(try comp.get_libc_crt_file(arena, "libc_nonshared.a")); | | |
| 1197 | } else if (target.isMusl()) { | | |
| 1198 | try argv.append(try comp.get_libc_crt_file(arena, switch (self.base.options.link_mode) { | | |
| 1199 | .Static => "libc.a", | | |
| 1200 | .Dynamic => "libc.so", | | |
| 1201 | })); | | |
| 1202 | } | | |
| 1203 | } | | |
| 1204 | | | |
| 1205 | // compiler-rt | | |
| 1206 | if (compiler_rt_path) |p| { | | |
| 1207 | try argv.append(p); | | |
| 1208 | } | | |
| 1209 | | | |
| 1210 | // crt postlude | | |
| 1211 | if (csu.crtend) |v| try argv.append(v); | | |
| 1212 | if (csu.crtn) |v| try argv.append(v); | | |
| 1213 | | | |
| 1214 | Compilation.dump_argv(argv.items); | | |
| 1215 | } | | |
| 1216 | | | |
| 1217 | if (self.zigObjectPtr()) |zig_object| try zig_object.flushModule(self); | 977 | if (self.zigObjectPtr()) |zig_object| try zig_object.flushModule(self); |
| | 978 | if (self.isStaticLib()) return self.flushStaticLib(comp, module_obj_path); |
| | 979 | if (self.isObject()) return self.flushObject(comp, module_obj_path); |
| 1218 | | 980 | |
| 1219 | // Here we will parse input positional and library files (if referenced). | 981 | // Here we will parse input positional and library files (if referenced). |
| 1220 | // This will roughly match in any linker backend we support. | 982 | // This will roughly match in any linker backend we support. |
| ... | @@ -1240,6 +1002,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1240,6 +1002,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1240 | // rpaths | 1002 | // rpaths |
| 1241 | var rpath_table = std.StringArrayHashMap(void).init(self.base.allocator); | 1003 | var rpath_table = std.StringArrayHashMap(void).init(self.base.allocator); |
| 1242 | defer rpath_table.deinit(); | 1004 | defer rpath_table.deinit(); |
| | 1005 | |
| 1243 | for (self.base.options.rpath_list) |rpath| { | 1006 | for (self.base.options.rpath_list) |rpath| { |
| 1244 | _ = try rpath_table.put(rpath, {}); | 1007 | _ = try rpath_table.put(rpath, {}); |
| 1245 | } | 1008 | } |
| ... | @@ -1388,8 +1151,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1388,8 +1151,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1388 | try self.handleAndReportParseError(obj.path, err, &parse_ctx); | 1151 | try self.handleAndReportParseError(obj.path, err, &parse_ctx); |
| 1389 | } | 1152 | } |
| 1390 | | 1153 | |
| 1391 | if (self.isStaticLib()) return self.flushStaticLib(comp); | | |
| 1392 | | | |
| 1393 | // Init all objects | 1154 | // Init all objects |
| 1394 | for (self.objects.items) |index| { | 1155 | for (self.objects.items) |index| { |
| 1395 | try self.file(index).?.object.init(self); | 1156 | try self.file(index).?.object.init(self); |
| ... | @@ -1418,7 +1179,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1418,7 +1179,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1418 | | 1179 | |
| 1419 | // If we haven't already, create a linker-generated input file comprising of | 1180 | // If we haven't already, create a linker-generated input file comprising of |
| 1420 | // linker-defined synthetic symbols only such as `_DYNAMIC`, etc. | 1181 | // linker-defined synthetic symbols only such as `_DYNAMIC`, etc. |
| 1421 | if (self.linker_defined_index == null and !self.isRelocatable()) { | 1182 | if (self.linker_defined_index == null) { |
| 1422 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); | 1183 | const index = @as(File.Index, @intCast(try self.files.addOne(gpa))); |
| 1423 | self.files.set(index, .{ .linker_defined = .{ .index = index } }); | 1184 | self.files.set(index, .{ .linker_defined = .{ .index = index } }); |
| 1424 | self.linker_defined_index = index; | 1185 | self.linker_defined_index = index; |
| ... | @@ -1432,8 +1193,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1432,8 +1193,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1432 | self.resolveSymbols(); | 1193 | self.resolveSymbols(); |
| 1433 | self.markEhFrameAtomsDead(); | 1194 | self.markEhFrameAtomsDead(); |
| 1434 | | 1195 | |
| 1435 | if (self.isObject()) return self.flushObject(comp); | | |
| 1436 | | | |
| 1437 | try self.convertCommonSymbols(); | 1196 | try self.convertCommonSymbols(); |
| 1438 | self.markImportsExports(); | 1197 | self.markImportsExports(); |
| 1439 | | 1198 | |
| ... | @@ -1527,10 +1286,30 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1527,10 +1286,30 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1527 | } | 1286 | } |
| 1528 | } | 1287 | } |
| 1529 | | 1288 | |
| 1530 | pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void { | 1289 | pub fn flushStaticLib(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { |
| 1531 | _ = comp; | | |
| 1532 | const gpa = self.base.allocator; | 1290 | const gpa = self.base.allocator; |
| 1533 | | 1291 | |
| | 1292 | var positionals = std.ArrayList(Compilation.LinkObject).init(gpa); |
| | 1293 | defer positionals.deinit(); |
| | 1294 | |
| | 1295 | try positionals.ensureUnusedCapacity(self.base.options.objects.len); |
| | 1296 | positionals.appendSliceAssumeCapacity(self.base.options.objects); |
| | 1297 | |
| | 1298 | // This is a set of object files emitted by clang in a single `build-exe` invocation. |
| | 1299 | // For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up |
| | 1300 | // in this set. |
| | 1301 | for (comp.c_object_table.keys()) |key| { |
| | 1302 | try positionals.append(.{ .path = key.status.success.object_path }); |
| | 1303 | } |
| | 1304 | |
| | 1305 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); |
| | 1306 | |
| | 1307 | for (positionals.items) |obj| { |
| | 1308 | var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; |
| | 1309 | self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err| |
| | 1310 | try self.handleAndReportParseError(obj.path, err, &parse_ctx); |
| | 1311 | } |
| | 1312 | |
| 1534 | // First, we flush relocatable object file generated with our backends. | 1313 | // First, we flush relocatable object file generated with our backends. |
| 1535 | if (self.zigObjectPtr()) |zig_object| { | 1314 | if (self.zigObjectPtr()) |zig_object| { |
| 1536 | zig_object.resolveSymbols(self); | 1315 | zig_object.resolveSymbols(self); |
| ... | @@ -1539,16 +1318,17 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void | ... | @@ -1539,16 +1318,17 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void |
| 1539 | try self.initSymtab(); | 1318 | try self.initSymtab(); |
| 1540 | try self.initShStrtab(); | 1319 | try self.initShStrtab(); |
| 1541 | try self.sortShdrs(); | 1320 | try self.sortShdrs(); |
| 1542 | zig_object.updateRelaSectionSizes(self); | 1321 | try zig_object.addAtomsToRelaSections(self); |
| 1543 | self.updateSymtabSizeObject(zig_object); | 1322 | try self.updateSectionSizesObject(); |
| 1544 | self.updateShStrtabSize(); | | |
| 1545 | | 1323 | |
| 1546 | try self.allocateNonAllocSections(); | 1324 | try self.allocateNonAllocSections(); |
| 1547 | | 1325 | |
| | 1326 | if (build_options.enable_logging) { |
| | 1327 | state_log.debug("{}", .{self.dumpState()}); |
| | 1328 | } |
| | 1329 | |
| | 1330 | try self.writeSyntheticSectionsObject(); |
| 1548 | try self.writeShdrTable(); | 1331 | try self.writeShdrTable(); |
| 1549 | try zig_object.writeRelaSections(self); | | |
| 1550 | try self.writeSymtabObject(zig_object); | | |
| 1551 | try self.writeShStrtab(); | | |
| 1552 | try self.writeElfHeader(); | 1332 | try self.writeElfHeader(); |
| 1553 | } | 1333 | } |
| 1554 | | 1334 | |
| ... | @@ -1603,67 +1383,391 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void | ... | @@ -1603,67 +1383,391 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void |
| 1603 | pos += @sizeOf(elf.ar_hdr) + (math.cast(usize, state.size) orelse return error.Overflow); | 1383 | pos += @sizeOf(elf.ar_hdr) + (math.cast(usize, state.size) orelse return error.Overflow); |
| 1604 | } | 1384 | } |
| 1605 | | 1385 | |
| 1606 | break :blk pos; | 1386 | break :blk pos; |
| 1607 | }; | 1387 | }; |
| | 1388 | |
| | 1389 | if (build_options.enable_logging) { |
| | 1390 | state_log.debug("ar_symtab\n{}\n", .{ar_symtab.fmt(self)}); |
| | 1391 | state_log.debug("ar_strtab\n{}\n", .{ar_strtab}); |
| | 1392 | } |
| | 1393 | |
| | 1394 | var buffer = std.ArrayList(u8).init(gpa); |
| | 1395 | defer buffer.deinit(); |
| | 1396 | try buffer.ensureTotalCapacityPrecise(total_size); |
| | 1397 | |
| | 1398 | // Write magic |
| | 1399 | try buffer.writer().writeAll(elf.ARMAG); |
| | 1400 | |
| | 1401 | // Write symtab |
| | 1402 | try ar_symtab.write(.p64, self, buffer.writer()); |
| | 1403 | |
| | 1404 | // Write strtab |
| | 1405 | if (ar_strtab.size() > 0) { |
| | 1406 | if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0); |
| | 1407 | try ar_strtab.write(buffer.writer()); |
| | 1408 | } |
| | 1409 | |
| | 1410 | // Write object files |
| | 1411 | for (files.items) |index| { |
| | 1412 | if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0); |
| | 1413 | try self.file(index).?.writeAr(self, buffer.writer()); |
| | 1414 | } |
| | 1415 | |
| | 1416 | assert(buffer.items.len == total_size); |
| | 1417 | |
| | 1418 | try self.base.file.?.setEndPos(total_size); |
| | 1419 | try self.base.file.?.pwriteAll(buffer.items, 0); |
| | 1420 | } |
| | 1421 | |
| | 1422 | pub fn flushObject(self: *Elf, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { |
| | 1423 | const gpa = self.base.allocator; |
| | 1424 | |
| | 1425 | var positionals = std.ArrayList(Compilation.LinkObject).init(gpa); |
| | 1426 | defer positionals.deinit(); |
| | 1427 | try positionals.ensureUnusedCapacity(self.base.options.objects.len); |
| | 1428 | positionals.appendSliceAssumeCapacity(self.base.options.objects); |
| | 1429 | |
| | 1430 | // This is a set of object files emitted by clang in a single `build-exe` invocation. |
| | 1431 | // For instance, the implicit `a.o` as compiled by `zig build-exe a.c` will end up |
| | 1432 | // in this set. |
| | 1433 | for (comp.c_object_table.keys()) |key| { |
| | 1434 | try positionals.append(.{ .path = key.status.success.object_path }); |
| | 1435 | } |
| | 1436 | |
| | 1437 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); |
| | 1438 | |
| | 1439 | for (positionals.items) |obj| { |
| | 1440 | var parse_ctx: ParseErrorCtx = .{ .detected_cpu_arch = undefined }; |
| | 1441 | self.parsePositional(obj.path, obj.must_link, &parse_ctx) catch |err| |
| | 1442 | try self.handleAndReportParseError(obj.path, err, &parse_ctx); |
| | 1443 | } |
| | 1444 | |
| | 1445 | // Init all objects |
| | 1446 | for (self.objects.items) |index| { |
| | 1447 | try self.file(index).?.object.init(self); |
| | 1448 | } |
| | 1449 | |
| | 1450 | // Now, we are ready to resolve the symbols across all input files. |
| | 1451 | // We will first resolve the files in the ZigObject, next in the parsed |
| | 1452 | // input Object files. |
| | 1453 | self.resolveSymbols(); |
| | 1454 | self.markEhFrameAtomsDead(); |
| | 1455 | self.claimUnresolvedObject(); |
| | 1456 | |
| | 1457 | try self.initSectionsObject(); |
| | 1458 | try self.sortShdrs(); |
| | 1459 | if (self.zigObjectPtr()) |zig_object| { |
| | 1460 | try zig_object.addAtomsToRelaSections(self); |
| | 1461 | } |
| | 1462 | for (self.objects.items) |index| { |
| | 1463 | const object = self.file(index).?.object; |
| | 1464 | try object.addAtomsToOutputSections(self); |
| | 1465 | try object.addAtomsToRelaSections(self); |
| | 1466 | } |
| | 1467 | try self.updateSectionSizesObject(); |
| | 1468 | |
| | 1469 | try self.allocateAllocSectionsObject(); |
| | 1470 | try self.allocateNonAllocSections(); |
| | 1471 | self.allocateAtoms(); |
| | 1472 | |
| | 1473 | if (build_options.enable_logging) { |
| | 1474 | state_log.debug("{}", .{self.dumpState()}); |
| | 1475 | } |
| | 1476 | |
| | 1477 | try self.writeAtomsObject(); |
| | 1478 | try self.writeSyntheticSectionsObject(); |
| | 1479 | try self.writeShdrTable(); |
| | 1480 | try self.writeElfHeader(); |
| | 1481 | } |
| | 1482 | |
| | 1483 | /// --verbose-link output |
| | 1484 | fn dumpArgv(self: *Elf, comp: *Compilation) !void { |
| | 1485 | var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator); |
| | 1486 | defer arena_allocator.deinit(); |
| | 1487 | const arena = arena_allocator.allocator(); |
| | 1488 | |
| | 1489 | const target = self.base.options.target; |
| | 1490 | const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type. |
| | 1491 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); |
| | 1492 | const module_obj_path: ?[]const u8 = if (self.base.intermediary_basename) |path| blk: { |
| | 1493 | if (fs.path.dirname(full_out_path)) |dirname| { |
| | 1494 | break :blk try fs.path.join(arena, &.{ dirname, path }); |
| | 1495 | } else { |
| | 1496 | break :blk path; |
| | 1497 | } |
| | 1498 | } else null; |
| | 1499 | const gc_sections = self.base.options.gc_sections orelse false; |
| | 1500 | |
| | 1501 | var csu = try CsuObjects.init(arena, self.base.options, comp); |
| | 1502 | const compiler_rt_path: ?[]const u8 = blk: { |
| | 1503 | if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; |
| | 1504 | if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; |
| | 1505 | break :blk null; |
| | 1506 | }; |
| | 1507 | |
| | 1508 | var argv = std.ArrayList([]const u8).init(arena); |
| | 1509 | |
| | 1510 | try argv.append("zig"); |
| | 1511 | |
| | 1512 | if (self.isStaticLib()) { |
| | 1513 | try argv.append("ar"); |
| | 1514 | } else { |
| | 1515 | try argv.append("ld"); |
| | 1516 | } |
| | 1517 | |
| | 1518 | if (self.isObject()) { |
| | 1519 | try argv.append("-r"); |
| | 1520 | } |
| | 1521 | |
| | 1522 | try argv.append("-o"); |
| | 1523 | try argv.append(full_out_path); |
| | 1524 | |
| | 1525 | if (self.isRelocatable()) { |
| | 1526 | for (self.base.options.objects) |obj| { |
| | 1527 | try argv.append(obj.path); |
| | 1528 | } |
| | 1529 | |
| | 1530 | for (comp.c_object_table.keys()) |key| { |
| | 1531 | try argv.append(key.status.success.object_path); |
| | 1532 | } |
| | 1533 | |
| | 1534 | if (module_obj_path) |p| { |
| | 1535 | try argv.append(p); |
| | 1536 | } |
| | 1537 | } else { |
| | 1538 | if (!self.isStatic()) { |
| | 1539 | if (self.base.options.dynamic_linker) |path| { |
| | 1540 | try argv.append("-dynamic-linker"); |
| | 1541 | try argv.append(path); |
| | 1542 | } |
| | 1543 | } |
| | 1544 | |
| | 1545 | if (self.isDynLib()) { |
| | 1546 | if (self.base.options.soname) |name| { |
| | 1547 | try argv.append("-soname"); |
| | 1548 | try argv.append(name); |
| | 1549 | } |
| | 1550 | } |
| | 1551 | |
| | 1552 | if (self.base.options.entry) |entry| { |
| | 1553 | try argv.append("--entry"); |
| | 1554 | try argv.append(entry); |
| | 1555 | } |
| | 1556 | |
| | 1557 | for (self.base.options.rpath_list) |rpath| { |
| | 1558 | try argv.append("-rpath"); |
| | 1559 | try argv.append(rpath); |
| | 1560 | } |
| | 1561 | |
| | 1562 | if (self.base.options.each_lib_rpath) { |
| | 1563 | for (self.base.options.lib_dirs) |lib_dir_path| { |
| | 1564 | try argv.append("-rpath"); |
| | 1565 | try argv.append(lib_dir_path); |
| | 1566 | } |
| | 1567 | for (self.base.options.objects) |obj| { |
| | 1568 | if (Compilation.classifyFileExt(obj.path) == .shared_library) { |
| | 1569 | const lib_dir_path = std.fs.path.dirname(obj.path) orelse continue; |
| | 1570 | if (obj.loption) continue; |
| | 1571 | |
| | 1572 | try argv.append("-rpath"); |
| | 1573 | try argv.append(lib_dir_path); |
| | 1574 | } |
| | 1575 | } |
| | 1576 | } |
| | 1577 | |
| | 1578 | if (self.base.options.stack_size_override) |ss| { |
| | 1579 | try argv.append("-z"); |
| | 1580 | try argv.append(try std.fmt.allocPrint(arena, "stack-size={d}", .{ss})); |
| | 1581 | } |
| | 1582 | |
| | 1583 | if (self.base.options.image_base_override) |image_base| { |
| | 1584 | try argv.append(try std.fmt.allocPrint(arena, "--image-base={d}", .{image_base})); |
| | 1585 | } |
| | 1586 | |
| | 1587 | if (gc_sections) { |
| | 1588 | try argv.append("--gc-sections"); |
| | 1589 | } |
| | 1590 | |
| | 1591 | if (self.base.options.print_gc_sections) { |
| | 1592 | try argv.append("--print-gc-sections"); |
| | 1593 | } |
| | 1594 | |
| | 1595 | if (self.base.options.eh_frame_hdr) { |
| | 1596 | try argv.append("--eh-frame-hdr"); |
| | 1597 | } |
| | 1598 | |
| | 1599 | if (self.base.options.rdynamic) { |
| | 1600 | try argv.append("--export-dynamic"); |
| | 1601 | } |
| | 1602 | |
| | 1603 | if (self.base.options.z_notext) { |
| | 1604 | try argv.append("-z"); |
| | 1605 | try argv.append("notext"); |
| | 1606 | } |
| | 1607 | |
| | 1608 | if (self.base.options.z_nocopyreloc) { |
| | 1609 | try argv.append("-z"); |
| | 1610 | try argv.append("nocopyreloc"); |
| | 1611 | } |
| | 1612 | |
| | 1613 | if (self.base.options.z_now) { |
| | 1614 | try argv.append("-z"); |
| | 1615 | try argv.append("now"); |
| | 1616 | } |
| | 1617 | |
| | 1618 | if (self.isStatic()) { |
| | 1619 | try argv.append("-static"); |
| | 1620 | } else if (self.isDynLib()) { |
| | 1621 | try argv.append("-shared"); |
| | 1622 | } |
| | 1623 | |
| | 1624 | if (self.base.options.pie and self.isExe()) { |
| | 1625 | try argv.append("-pie"); |
| | 1626 | } |
| | 1627 | |
| | 1628 | if (self.base.options.strip) { |
| | 1629 | try argv.append("-s"); |
| | 1630 | } |
| | 1631 | |
| | 1632 | // csu prelude |
| | 1633 | if (csu.crt0) |v| try argv.append(v); |
| | 1634 | if (csu.crti) |v| try argv.append(v); |
| | 1635 | if (csu.crtbegin) |v| try argv.append(v); |
| | 1636 | |
| | 1637 | for (self.base.options.lib_dirs) |lib_dir| { |
| | 1638 | try argv.append("-L"); |
| | 1639 | try argv.append(lib_dir); |
| | 1640 | } |
| | 1641 | |
| | 1642 | if (self.base.options.link_libc) { |
| | 1643 | if (self.base.options.libc_installation) |libc_installation| { |
| | 1644 | try argv.append("-L"); |
| | 1645 | try argv.append(libc_installation.crt_dir.?); |
| | 1646 | } |
| | 1647 | } |
| 1608 | | 1648 | |
| 1609 | if (build_options.enable_logging) { | 1649 | var whole_archive = false; |
| 1610 | state_log.debug("ar_symtab\n{}\n", .{ar_symtab.fmt(self)}); | 1650 | for (self.base.options.objects) |obj| { |
| 1611 | state_log.debug("ar_strtab\n{}\n", .{ar_strtab}); | 1651 | if (obj.must_link and !whole_archive) { |
| 1612 | } | 1652 | try argv.append("-whole-archive"); |
| | 1653 | whole_archive = true; |
| | 1654 | } else if (!obj.must_link and whole_archive) { |
| | 1655 | try argv.append("-no-whole-archive"); |
| | 1656 | whole_archive = false; |
| | 1657 | } |
| 1613 | | 1658 | |
| 1614 | var buffer = std.ArrayList(u8).init(gpa); | 1659 | if (obj.loption) { |
| 1615 | defer buffer.deinit(); | 1660 | assert(obj.path[0] == ':'); |
| 1616 | try buffer.ensureTotalCapacityPrecise(total_size); | 1661 | try argv.append("-l"); |
| | 1662 | } |
| | 1663 | try argv.append(obj.path); |
| | 1664 | } |
| | 1665 | if (whole_archive) { |
| | 1666 | try argv.append("-no-whole-archive"); |
| | 1667 | whole_archive = false; |
| | 1668 | } |
| 1617 | | 1669 | |
| 1618 | // Write magic | 1670 | for (comp.c_object_table.keys()) |key| { |
| 1619 | try buffer.writer().writeAll(elf.ARMAG); | 1671 | try argv.append(key.status.success.object_path); |
| | 1672 | } |
| 1620 | | 1673 | |
| 1621 | // Write symtab | 1674 | if (module_obj_path) |p| { |
| 1622 | try ar_symtab.write(.p64, self, buffer.writer()); | 1675 | try argv.append(p); |
| | 1676 | } |
| 1623 | | 1677 | |
| 1624 | // Write strtab | 1678 | // TSAN |
| 1625 | if (ar_strtab.size() > 0) { | 1679 | if (self.base.options.tsan) { |
| 1626 | if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0); | 1680 | try argv.append(comp.tsan_static_lib.?.full_object_path); |
| 1627 | try ar_strtab.write(buffer.writer()); | 1681 | } |
| 1628 | } | | |
| 1629 | | 1682 | |
| 1630 | // Write object files | 1683 | // libc |
| 1631 | for (files.items) |index| { | 1684 | if (!self.base.options.skip_linker_dependencies and |
| 1632 | if (!mem.isAligned(buffer.items.len, 2)) try buffer.writer().writeByte(0); | 1685 | !self.base.options.link_libc) |
| 1633 | try self.file(index).?.writeAr(self, buffer.writer()); | 1686 | { |
| 1634 | } | 1687 | if (comp.libc_static_lib) |lib| { |
| | 1688 | try argv.append(lib.full_object_path); |
| | 1689 | } |
| | 1690 | } |
| 1635 | | 1691 | |
| 1636 | assert(buffer.items.len == total_size); | 1692 | // stack-protector. |
| | 1693 | // Related: https://github.com/ziglang/zig/issues/7265 |
| | 1694 | if (comp.libssp_static_lib) |ssp| { |
| | 1695 | try argv.append(ssp.full_object_path); |
| | 1696 | } |
| 1637 | | 1697 | |
| 1638 | try self.base.file.?.setEndPos(total_size); | 1698 | // Shared libraries. |
| 1639 | try self.base.file.?.pwriteAll(buffer.items, 0); | 1699 | // Worst-case, we need an --as-needed argument for every lib, as well |
| 1640 | } | 1700 | // as one before and one after. |
| | 1701 | try argv.ensureUnusedCapacity(self.base.options.system_libs.keys().len * 2 + 2); |
| | 1702 | argv.appendAssumeCapacity("--as-needed"); |
| | 1703 | var as_needed = true; |
| 1641 | | 1704 | |
| 1642 | pub fn flushObject(self: *Elf, comp: *Compilation) link.File.FlushError!void { | 1705 | for (self.base.options.system_libs.values()) |lib_info| { |
| 1643 | _ = comp; | 1706 | const lib_as_needed = !lib_info.needed; |
| | 1707 | switch ((@as(u2, @intFromBool(lib_as_needed)) << 1) | @intFromBool(as_needed)) { |
| | 1708 | 0b00, 0b11 => {}, |
| | 1709 | 0b01 => { |
| | 1710 | argv.appendAssumeCapacity("--no-as-needed"); |
| | 1711 | as_needed = false; |
| | 1712 | }, |
| | 1713 | 0b10 => { |
| | 1714 | argv.appendAssumeCapacity("--as-needed"); |
| | 1715 | as_needed = true; |
| | 1716 | }, |
| | 1717 | } |
| | 1718 | argv.appendAssumeCapacity(lib_info.path.?); |
| | 1719 | } |
| 1644 | | 1720 | |
| 1645 | if (self.objects.items.len > 0) { | 1721 | if (!as_needed) { |
| 1646 | var err = try self.addErrorWithNotes(1); | 1722 | argv.appendAssumeCapacity("--as-needed"); |
| 1647 | try err.addMsg(self, "fatal linker error: too many input positionals", .{}); | 1723 | as_needed = true; |
| 1648 | try err.addNote(self, "TODO implement '-r' option", .{}); | 1724 | } |
| 1649 | return; | | |
| 1650 | } | | |
| 1651 | | 1725 | |
| 1652 | self.claimUnresolvedObject(); | 1726 | // libc++ dep |
| | 1727 | if (self.base.options.link_libcpp) { |
| | 1728 | try argv.append(comp.libcxxabi_static_lib.?.full_object_path); |
| | 1729 | try argv.append(comp.libcxx_static_lib.?.full_object_path); |
| | 1730 | } |
| 1653 | | 1731 | |
| 1654 | try self.initSections(); | 1732 | // libunwind dep |
| 1655 | try self.sortShdrs(); | 1733 | if (self.base.options.link_libunwind) { |
| 1656 | try self.updateSectionSizes(); | 1734 | try argv.append(comp.libunwind_static_lib.?.full_object_path); |
| | 1735 | } |
| 1657 | | 1736 | |
| 1658 | try self.allocateNonAllocSections(); | 1737 | // libc dep |
| | 1738 | if (self.base.options.link_libc) { |
| | 1739 | if (self.base.options.libc_installation != null) { |
| | 1740 | const needs_grouping = self.base.options.link_mode == .Static; |
| | 1741 | if (needs_grouping) try argv.append("--start-group"); |
| | 1742 | try argv.appendSlice(target_util.libcFullLinkFlags(target)); |
| | 1743 | if (needs_grouping) try argv.append("--end-group"); |
| | 1744 | } else if (target.isGnuLibC()) { |
| | 1745 | for (glibc.libs) |lib| { |
| | 1746 | const lib_path = try std.fmt.allocPrint(arena, "{s}{c}lib{s}.so.{d}", .{ |
| | 1747 | comp.glibc_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover, |
| | 1748 | }); |
| | 1749 | try argv.append(lib_path); |
| | 1750 | } |
| | 1751 | try argv.append(try comp.get_libc_crt_file(arena, "libc_nonshared.a")); |
| | 1752 | } else if (target.isMusl()) { |
| | 1753 | try argv.append(try comp.get_libc_crt_file(arena, switch (self.base.options.link_mode) { |
| | 1754 | .Static => "libc.a", |
| | 1755 | .Dynamic => "libc.so", |
| | 1756 | })); |
| | 1757 | } |
| | 1758 | } |
| 1659 | | 1759 | |
| 1660 | if (build_options.enable_logging) { | 1760 | // compiler-rt |
| 1661 | state_log.debug("{}", .{self.dumpState()}); | 1761 | if (compiler_rt_path) |p| { |
| | 1762 | try argv.append(p); |
| | 1763 | } |
| | 1764 | |
| | 1765 | // crt postlude |
| | 1766 | if (csu.crtend) |v| try argv.append(v); |
| | 1767 | if (csu.crtn) |v| try argv.append(v); |
| 1662 | } | 1768 | } |
| 1663 | | 1769 | |
| 1664 | try self.writeShdrTable(); | 1770 | Compilation.dump_argv(argv.items); |
| 1665 | try self.writeSyntheticSections(); | | |
| 1666 | try self.writeElfHeader(); | | |
| 1667 | } | 1771 | } |
| 1668 | | 1772 | |
| 1669 | const ParseError = error{ | 1773 | const ParseError = error{ |
| ... | @@ -2047,8 +2151,7 @@ fn claimUnresolved(self: *Elf) void { | ... | @@ -2047,8 +2151,7 @@ fn claimUnresolved(self: *Elf) void { |
| 2047 | zig_object.claimUnresolved(self); | 2151 | zig_object.claimUnresolved(self); |
| 2048 | } | 2152 | } |
| 2049 | for (self.objects.items) |index| { | 2153 | for (self.objects.items) |index| { |
| 2050 | const object = self.file(index).?.object; | 2154 | self.file(index).?.object.claimUnresolved(self); |
| 2051 | object.claimUnresolved(self); | | |
| 2052 | } | 2155 | } |
| 2053 | } | 2156 | } |
| 2054 | | 2157 | |
| ... | @@ -2056,6 +2159,9 @@ fn claimUnresolvedObject(self: *Elf) void { | ... | @@ -2056,6 +2159,9 @@ fn claimUnresolvedObject(self: *Elf) void { |
| 2056 | if (self.zigObjectPtr()) |zig_object| { | 2159 | if (self.zigObjectPtr()) |zig_object| { |
| 2057 | zig_object.claimUnresolvedObject(self); | 2160 | zig_object.claimUnresolvedObject(self); |
| 2058 | } | 2161 | } |
| | 2162 | for (self.objects.items) |index| { |
| | 2163 | self.file(index).?.object.claimUnresolvedObject(self); |
| | 2164 | } |
| 2059 | } | 2165 | } |
| 2060 | | 2166 | |
| 2061 | /// In scanRelocs we will go over all live atoms and scan their relocs. | 2167 | /// In scanRelocs we will go over all live atoms and scan their relocs. |
| ... | @@ -3460,6 +3566,60 @@ fn initSections(self: *Elf) !void { | ... | @@ -3460,6 +3566,60 @@ fn initSections(self: *Elf) !void { |
| 3460 | try self.initShStrtab(); | 3566 | try self.initShStrtab(); |
| 3461 | } | 3567 | } |
| 3462 | | 3568 | |
| | 3569 | fn initSectionsObject(self: *Elf) !void { |
| | 3570 | const ptr_size = self.ptrWidthBytes(); |
| | 3571 | |
| | 3572 | for (self.objects.items) |index| { |
| | 3573 | const object = self.file(index).?.object; |
| | 3574 | try object.initOutputSections(self); |
| | 3575 | try object.initRelaSections(self); |
| | 3576 | } |
| | 3577 | |
| | 3578 | const needs_eh_frame = for (self.objects.items) |index| { |
| | 3579 | if (self.file(index).?.object.cies.items.len > 0) break true; |
| | 3580 | } else false; |
| | 3581 | if (needs_eh_frame) { |
| | 3582 | self.eh_frame_section_index = try self.addSection(.{ |
| | 3583 | .name = ".eh_frame", |
| | 3584 | .type = elf.SHT_PROGBITS, |
| | 3585 | .flags = elf.SHF_ALLOC, |
| | 3586 | .addralign = ptr_size, |
| | 3587 | .offset = std.math.maxInt(u64), |
| | 3588 | }); |
| | 3589 | self.eh_frame_rela_section_index = try self.addRelaShdr(".rela.eh_frame", self.eh_frame_section_index.?); |
| | 3590 | } |
| | 3591 | |
| | 3592 | try self.initComdatGroups(); |
| | 3593 | try self.initSymtab(); |
| | 3594 | try self.initShStrtab(); |
| | 3595 | } |
| | 3596 | |
| | 3597 | fn initComdatGroups(self: *Elf) !void { |
| | 3598 | const gpa = self.base.allocator; |
| | 3599 | |
| | 3600 | for (self.objects.items) |index| { |
| | 3601 | const object = self.file(index).?.object; |
| | 3602 | |
| | 3603 | for (object.comdat_groups.items) |cg_index| { |
| | 3604 | const cg = self.comdatGroup(cg_index); |
| | 3605 | const cg_owner = self.comdatGroupOwner(cg.owner); |
| | 3606 | if (cg_owner.file != index) continue; |
| | 3607 | |
| | 3608 | const cg_sec = try self.comdat_group_sections.addOne(gpa); |
| | 3609 | cg_sec.* = .{ |
| | 3610 | .shndx = try self.addSection(.{ |
| | 3611 | .name = ".group", |
| | 3612 | .type = elf.SHT_GROUP, |
| | 3613 | .entsize = @sizeOf(u32), |
| | 3614 | .addralign = @alignOf(u32), |
| | 3615 | .offset = std.math.maxInt(u64), |
| | 3616 | }), |
| | 3617 | .cg_index = cg_index, |
| | 3618 | }; |
| | 3619 | } |
| | 3620 | } |
| | 3621 | } |
| | 3622 | |
| 3463 | fn initSymtab(self: *Elf) !void { | 3623 | fn initSymtab(self: *Elf) !void { |
| 3464 | const small_ptr = switch (self.ptr_width) { | 3624 | const small_ptr = switch (self.ptr_width) { |
| 3465 | .p32 => true, | 3625 | .p32 => true, |
| ... | @@ -3586,7 +3746,8 @@ fn sortInitFini(self: *Elf) !void { | ... | @@ -3586,7 +3746,8 @@ fn sortInitFini(self: *Elf) !void { |
| 3586 | | 3746 | |
| 3587 | if (!is_init_fini and !is_ctor_dtor) continue; | 3747 | if (!is_init_fini and !is_ctor_dtor) continue; |
| 3588 | | 3748 | |
| 3589 | const atom_list = self.output_sections.getPtr(@intCast(shndx)) orelse continue; | 3749 | const atom_list = self.output_sections.getPtr(@intCast(shndx)).?; |
| | 3750 | if (atom_list.items.len == 0) continue; |
| 3590 | | 3751 | |
| 3591 | var entries = std.ArrayList(Entry).init(gpa); | 3752 | var entries = std.ArrayList(Entry).init(gpa); |
| 3592 | try entries.ensureTotalCapacityPrecise(atom_list.items.len); | 3753 | try entries.ensureTotalCapacityPrecise(atom_list.items.len); |
| ... | @@ -3627,8 +3788,10 @@ fn setDynamicSection(self: *Elf, rpaths: []const []const u8) !void { | ... | @@ -3627,8 +3788,10 @@ fn setDynamicSection(self: *Elf, rpaths: []const []const u8) !void { |
| 3627 | try self.dynamic.addNeeded(shared_object, self); | 3788 | try self.dynamic.addNeeded(shared_object, self); |
| 3628 | } | 3789 | } |
| 3629 | | 3790 | |
| 3630 | if (self.base.options.soname) |soname| { | 3791 | if (self.isDynLib()) { |
| 3631 | try self.dynamic.setSoname(soname, self); | 3792 | if (self.base.options.soname) |soname| { |
| | 3793 | try self.dynamic.setSoname(soname, self); |
| | 3794 | } |
| 3632 | } | 3795 | } |
| 3633 | | 3796 | |
| 3634 | try self.dynamic.setRpath(rpaths, self); | 3797 | try self.dynamic.setRpath(rpaths, self); |
| ... | @@ -3760,7 +3923,7 @@ fn shdrRank(self: *Elf, shndx: u16) u8 { | ... | @@ -3760,7 +3923,7 @@ fn shdrRank(self: *Elf, shndx: u16) u8 { |
| 3760 | | 3923 | |
| 3761 | elf.SHT_DYNAMIC => return 0xf3, | 3924 | elf.SHT_DYNAMIC => return 0xf3, |
| 3762 | | 3925 | |
| 3763 | elf.SHT_RELA => return 0xf, | 3926 | elf.SHT_RELA, elf.SHT_GROUP => return 0xf, |
| 3764 | | 3927 | |
| 3765 | elf.SHT_PROGBITS => if (flags & elf.SHF_ALLOC != 0) { | 3928 | elf.SHT_PROGBITS => if (flags & elf.SHF_ALLOC != 0) { |
| 3766 | if (flags & elf.SHF_EXECINSTR != 0) { | 3929 | if (flags & elf.SHF_EXECINSTR != 0) { |
| ... | @@ -3819,8 +3982,15 @@ fn sortShdrs(self: *Elf) !void { | ... | @@ -3819,8 +3982,15 @@ fn sortShdrs(self: *Elf) !void { |
| 3819 | self.shdrs.appendAssumeCapacity(slice[sorted.shndx]); | 3982 | self.shdrs.appendAssumeCapacity(slice[sorted.shndx]); |
| 3820 | } | 3983 | } |
| 3821 | | 3984 | |
| | 3985 | try self.resetShdrIndexes(backlinks); |
| | 3986 | } |
| | 3987 | |
| | 3988 | fn resetShdrIndexes(self: *Elf, backlinks: []const u16) !void { |
| | 3989 | const gpa = self.base.allocator; |
| | 3990 | |
| 3822 | for (&[_]*?u16{ | 3991 | for (&[_]*?u16{ |
| 3823 | &self.eh_frame_section_index, | 3992 | &self.eh_frame_section_index, |
| | 3993 | &self.eh_frame_rela_section_index, |
| 3824 | &self.eh_frame_hdr_section_index, | 3994 | &self.eh_frame_hdr_section_index, |
| 3825 | &self.got_section_index, | 3995 | &self.got_section_index, |
| 3826 | &self.symtab_section_index, | 3996 | &self.symtab_section_index, |
| ... | @@ -3841,12 +4011,9 @@ fn sortShdrs(self: *Elf) !void { | ... | @@ -3841,12 +4011,9 @@ fn sortShdrs(self: *Elf) !void { |
| 3841 | &self.versym_section_index, | 4011 | &self.versym_section_index, |
| 3842 | &self.verneed_section_index, | 4012 | &self.verneed_section_index, |
| 3843 | &self.zig_text_section_index, | 4013 | &self.zig_text_section_index, |
| 3844 | &self.zig_text_rela_section_index, | | |
| 3845 | &self.zig_got_section_index, | 4014 | &self.zig_got_section_index, |
| 3846 | &self.zig_data_rel_ro_section_index, | 4015 | &self.zig_data_rel_ro_section_index, |
| 3847 | &self.zig_data_rel_ro_rela_section_index, | | |
| 3848 | &self.zig_data_section_index, | 4016 | &self.zig_data_section_index, |
| 3849 | &self.zig_data_rela_section_index, | | |
| 3850 | &self.zig_bss_section_index, | 4017 | &self.zig_bss_section_index, |
| 3851 | &self.debug_str_section_index, | 4018 | &self.debug_str_section_index, |
| 3852 | &self.debug_info_section_index, | 4019 | &self.debug_info_section_index, |
| ... | @@ -3905,15 +4072,39 @@ fn sortShdrs(self: *Elf) !void { | ... | @@ -3905,15 +4072,39 @@ fn sortShdrs(self: *Elf) !void { |
| 3905 | shdr.sh_info = self.plt_section_index.?; | 4072 | shdr.sh_info = self.plt_section_index.?; |
| 3906 | } | 4073 | } |
| 3907 | | 4074 | |
| 3908 | for (&[_]?u16{ | 4075 | if (self.eh_frame_rela_section_index) |index| { |
| 3909 | self.zig_text_rela_section_index, | | |
| 3910 | self.zig_data_rel_ro_rela_section_index, | | |
| 3911 | self.zig_data_rela_section_index, | | |
| 3912 | }) |maybe_index| { | | |
| 3913 | const index = maybe_index orelse continue; | | |
| 3914 | const shdr = &self.shdrs.items[index]; | 4076 | const shdr = &self.shdrs.items[index]; |
| 3915 | shdr.sh_link = self.symtab_section_index.?; | 4077 | shdr.sh_link = self.symtab_section_index.?; |
| 3916 | shdr.sh_info = backlinks[shdr.sh_info]; | 4078 | shdr.sh_info = self.eh_frame_section_index.?; |
| | 4079 | } |
| | 4080 | |
| | 4081 | { |
| | 4082 | var output_sections = try self.output_sections.clone(gpa); |
| | 4083 | defer output_sections.deinit(gpa); |
| | 4084 | |
| | 4085 | self.output_sections.clearRetainingCapacity(); |
| | 4086 | |
| | 4087 | var it = output_sections.iterator(); |
| | 4088 | while (it.next()) |entry| { |
| | 4089 | const shndx = entry.key_ptr.*; |
| | 4090 | const meta = entry.value_ptr.*; |
| | 4091 | self.output_sections.putAssumeCapacityNoClobber(backlinks[shndx], meta); |
| | 4092 | } |
| | 4093 | } |
| | 4094 | |
| | 4095 | { |
| | 4096 | var output_rela_sections = try self.output_rela_sections.clone(gpa); |
| | 4097 | defer output_rela_sections.deinit(gpa); |
| | 4098 | |
| | 4099 | self.output_rela_sections.clearRetainingCapacity(); |
| | 4100 | |
| | 4101 | var it = output_rela_sections.iterator(); |
| | 4102 | while (it.next()) |entry| { |
| | 4103 | const shndx = entry.key_ptr.*; |
| | 4104 | var meta = entry.value_ptr.*; |
| | 4105 | meta.shndx = backlinks[meta.shndx]; |
| | 4106 | self.output_rela_sections.putAssumeCapacityNoClobber(backlinks[shndx], meta); |
| | 4107 | } |
| 3917 | } | 4108 | } |
| 3918 | | 4109 | |
| 3919 | { | 4110 | { |
| ... | @@ -3965,11 +4156,20 @@ fn sortShdrs(self: *Elf) !void { | ... | @@ -3965,11 +4156,20 @@ fn sortShdrs(self: *Elf) !void { |
| 3965 | global.output_section_index = backlinks[out_shndx]; | 4156 | global.output_section_index = backlinks[out_shndx]; |
| 3966 | } | 4157 | } |
| 3967 | } | 4158 | } |
| | 4159 | |
| | 4160 | for (self.output_rela_sections.keys(), self.output_rela_sections.values()) |shndx, sec| { |
| | 4161 | const shdr = &self.shdrs.items[sec.shndx]; |
| | 4162 | shdr.sh_link = self.symtab_section_index.?; |
| | 4163 | shdr.sh_info = shndx; |
| | 4164 | } |
| | 4165 | |
| | 4166 | for (self.comdat_group_sections.items) |*cg| { |
| | 4167 | cg.shndx = backlinks[cg.shndx]; |
| | 4168 | } |
| 3968 | } | 4169 | } |
| 3969 | | 4170 | |
| 3970 | fn updateSectionSizes(self: *Elf) !void { | 4171 | fn updateSectionSizes(self: *Elf) !void { |
| 3971 | for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| { | 4172 | for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| { |
| 3972 | if (atom_list.items.len == 0) continue; | | |
| 3973 | const shdr = &self.shdrs.items[shndx]; | 4173 | const shdr = &self.shdrs.items[shndx]; |
| 3974 | for (atom_list.items) |atom_index| { | 4174 | for (atom_list.items) |atom_index| { |
| 3975 | const atom_ptr = self.atom(atom_index) orelse continue; | 4175 | const atom_ptr = self.atom(atom_index) orelse continue; |
| ... | @@ -3982,10 +4182,6 @@ fn updateSectionSizes(self: *Elf) !void { | ... | @@ -3982,10 +4182,6 @@ fn updateSectionSizes(self: *Elf) !void { |
| 3982 | } | 4182 | } |
| 3983 | } | 4183 | } |
| 3984 | | 4184 | |
| 3985 | if (self.zigObjectPtr()) |zig_object| { | | |
| 3986 | zig_object.updateRelaSectionSizes(self); | | |
| 3987 | } | | |
| 3988 | | | |
| 3989 | if (self.eh_frame_section_index) |index| { | 4185 | if (self.eh_frame_section_index) |index| { |
| 3990 | self.shdrs.items[index].sh_size = try eh_frame.calcEhFrameSize(self); | 4186 | self.shdrs.items[index].sh_size = try eh_frame.calcEhFrameSize(self); |
| 3991 | } | 4187 | } |
| ... | @@ -4049,22 +4245,73 @@ fn updateSectionSizes(self: *Elf) !void { | ... | @@ -4049,22 +4245,73 @@ fn updateSectionSizes(self: *Elf) !void { |
| 4049 | self.shdrs.items[index].sh_size = self.dynsym.size(); | 4245 | self.shdrs.items[index].sh_size = self.dynsym.size(); |
| 4050 | } | 4246 | } |
| 4051 | | 4247 | |
| 4052 | if (self.dynstrtab_section_index) |index| { | 4248 | if (self.dynstrtab_section_index) |index| { |
| 4053 | self.shdrs.items[index].sh_size = self.dynstrtab.items.len; | 4249 | self.shdrs.items[index].sh_size = self.dynstrtab.items.len; |
| 4054 | } | 4250 | } |
| | 4251 | |
| | 4252 | if (self.versym_section_index) |index| { |
| | 4253 | self.shdrs.items[index].sh_size = self.versym.items.len * @sizeOf(elf.Elf64_Versym); |
| | 4254 | } |
| | 4255 | |
| | 4256 | if (self.verneed_section_index) |index| { |
| | 4257 | self.shdrs.items[index].sh_size = self.verneed.size(); |
| | 4258 | } |
| | 4259 | |
| | 4260 | try self.updateSymtabSize(); |
| | 4261 | self.updateShStrtabSize(); |
| | 4262 | } |
| | 4263 | |
| | 4264 | fn updateSectionSizesObject(self: *Elf) !void { |
| | 4265 | for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| { |
| | 4266 | const shdr = &self.shdrs.items[shndx]; |
| | 4267 | for (atom_list.items) |atom_index| { |
| | 4268 | const atom_ptr = self.atom(atom_index) orelse continue; |
| | 4269 | if (!atom_ptr.flags.alive) continue; |
| | 4270 | const offset = atom_ptr.alignment.forward(shdr.sh_size); |
| | 4271 | const padding = offset - shdr.sh_size; |
| | 4272 | atom_ptr.value = offset; |
| | 4273 | shdr.sh_size += padding + atom_ptr.size; |
| | 4274 | shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits(1)); |
| | 4275 | } |
| | 4276 | } |
| | 4277 | |
| | 4278 | for (self.output_rela_sections.values()) |sec| { |
| | 4279 | const shdr = &self.shdrs.items[sec.shndx]; |
| | 4280 | for (sec.atom_list.items) |atom_index| { |
| | 4281 | const atom_ptr = self.atom(atom_index) orelse continue; |
| | 4282 | if (!atom_ptr.flags.alive) continue; |
| | 4283 | const relocs = atom_ptr.relocs(self); |
| | 4284 | shdr.sh_size += shdr.sh_entsize * relocs.len; |
| | 4285 | } |
| 4055 | | 4286 | |
| 4056 | if (self.versym_section_index) |index| { | 4287 | if (shdr.sh_size == 0) shdr.sh_offset = 0; |
| 4057 | self.shdrs.items[index].sh_size = self.versym.items.len * @sizeOf(elf.Elf64_Versym); | | |
| 4058 | } | 4288 | } |
| 4059 | | 4289 | |
| 4060 | if (self.verneed_section_index) |index| { | 4290 | if (self.eh_frame_section_index) |index| { |
| 4061 | self.shdrs.items[index].sh_size = self.verneed.size(); | 4291 | self.shdrs.items[index].sh_size = try eh_frame.calcEhFrameSize(self); |
| | 4292 | } |
| | 4293 | if (self.eh_frame_rela_section_index) |index| { |
| | 4294 | const shdr = &self.shdrs.items[index]; |
| | 4295 | shdr.sh_size = eh_frame.calcEhFrameRelocs(self) * shdr.sh_entsize; |
| 4062 | } | 4296 | } |
| 4063 | | 4297 | |
| 4064 | self.updateSymtabSize(); | 4298 | try self.updateSymtabSize(); |
| | 4299 | self.updateComdatGroupsSizes(); |
| 4065 | self.updateShStrtabSize(); | 4300 | self.updateShStrtabSize(); |
| 4066 | } | 4301 | } |
| 4067 | | 4302 | |
| | 4303 | fn updateComdatGroupsSizes(self: *Elf) void { |
| | 4304 | for (self.comdat_group_sections.items) |cg| { |
| | 4305 | const shdr = &self.shdrs.items[cg.shndx]; |
| | 4306 | shdr.sh_size = cg.size(self); |
| | 4307 | shdr.sh_link = self.symtab_section_index.?; |
| | 4308 | |
| | 4309 | const sym = self.symbol(cg.symbol(self)); |
| | 4310 | shdr.sh_info = sym.outputSymtabIndex(self) orelse |
| | 4311 | self.sectionSymbolOutputSymtabIndex(sym.outputShndx().?); |
| | 4312 | } |
| | 4313 | } |
| | 4314 | |
| 4068 | fn updateShStrtabSize(self: *Elf) void { | 4315 | fn updateShStrtabSize(self: *Elf) void { |
| 4069 | if (self.shstrtab_section_index) |index| { | 4316 | if (self.shstrtab_section_index) |index| { |
| 4070 | self.shdrs.items[index].sh_size = self.shstrtab.items.len; | 4317 | self.shdrs.items[index].sh_size = self.shstrtab.items.len; |
| ... | @@ -4294,6 +4541,22 @@ fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void { | ... | @@ -4294,6 +4541,22 @@ fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void { |
| 4294 | } | 4541 | } |
| 4295 | } | 4542 | } |
| 4296 | | 4543 | |
| | 4544 | /// Allocates alloc sections when merging relocatable objects files together. |
| | 4545 | fn allocateAllocSectionsObject(self: *Elf) !void { |
| | 4546 | for (self.shdrs.items) |*shdr| { |
| | 4547 | if (shdr.sh_type == elf.SHT_NULL) continue; |
| | 4548 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; |
| | 4549 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| | 4550 | const needed_size = shdr.sh_size; |
| | 4551 | if (needed_size > self.allocatedSize(shdr.sh_offset)) { |
| | 4552 | shdr.sh_size = 0; |
| | 4553 | const new_offset = self.findFreeSpace(needed_size, shdr.sh_addralign); |
| | 4554 | shdr.sh_offset = new_offset; |
| | 4555 | shdr.sh_size = needed_size; |
| | 4556 | } |
| | 4557 | } |
| | 4558 | } |
| | 4559 | |
| 4297 | /// Allocates non-alloc sections (debug info, symtabs, etc.). | 4560 | /// Allocates non-alloc sections (debug info, symtabs, etc.). |
| 4298 | fn allocateNonAllocSections(self: *Elf) !void { | 4561 | fn allocateNonAllocSections(self: *Elf) !void { |
| 4299 | for (self.shdrs.items, 0..) |*shdr, shndx| { | 4562 | for (self.shdrs.items, 0..) |*shdr, shndx| { |
| ... | @@ -4418,6 +4681,7 @@ fn writeAtoms(self: *Elf) !void { | ... | @@ -4418,6 +4681,7 @@ fn writeAtoms(self: *Elf) !void { |
| 4418 | if (shdr.sh_type == elf.SHT_NOBITS) continue; | 4681 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| 4419 | | 4682 | |
| 4420 | const atom_list = self.output_sections.get(@intCast(shndx)) orelse continue; | 4683 | const atom_list = self.output_sections.get(@intCast(shndx)) orelse continue; |
| | 4684 | if (atom_list.items.len == 0) continue; |
| 4421 | | 4685 | |
| 4422 | log.debug("writing atoms in '{s}' section", .{self.getShString(shdr.sh_name)}); | 4686 | log.debug("writing atoms in '{s}' section", .{self.getShString(shdr.sh_name)}); |
| 4423 | | 4687 | |
| ... | @@ -4484,93 +4748,165 @@ fn writeAtoms(self: *Elf) !void { | ... | @@ -4484,93 +4748,165 @@ fn writeAtoms(self: *Elf) !void { |
| 4484 | try self.reportUndefined(&undefs); | 4748 | try self.reportUndefined(&undefs); |
| 4485 | } | 4749 | } |
| 4486 | | 4750 | |
| 4487 | fn updateSymtabSize(self: *Elf) void { | 4751 | fn writeAtomsObject(self: *Elf) !void { |
| 4488 | var sizes = SymtabSize{}; | 4752 | const gpa = self.base.allocator; |
| 4489 | | 4753 | |
| 4490 | if (self.zigObjectPtr()) |zig_object| { | 4754 | // TODO iterate over `output_sections` directly |
| 4491 | zig_object.asFile().updateSymtabSize(self); | 4755 | for (self.shdrs.items, 0..) |shdr, shndx| { |
| 4492 | sizes.add(zig_object.output_symtab_size); | 4756 | if (shdr.sh_type == elf.SHT_NULL) continue; |
| | 4757 | if (shdr.sh_type == elf.SHT_NOBITS) continue; |
| | 4758 | |
| | 4759 | const atom_list = self.output_sections.get(@intCast(shndx)) orelse continue; |
| | 4760 | if (atom_list.items.len == 0) continue; |
| | 4761 | |
| | 4762 | log.debug("writing atoms in '{s}' section", .{self.getShString(shdr.sh_name)}); |
| | 4763 | |
| | 4764 | // TODO really, really handle debug section separately |
| | 4765 | const base_offset = if (self.isDebugSection(@intCast(shndx))) blk: { |
| | 4766 | const zig_object = self.zigObjectPtr().?; |
| | 4767 | if (shndx == self.debug_info_section_index.?) |
| | 4768 | break :blk zig_object.debug_info_section_zig_size; |
| | 4769 | if (shndx == self.debug_abbrev_section_index.?) |
| | 4770 | break :blk zig_object.debug_abbrev_section_zig_size; |
| | 4771 | if (shndx == self.debug_str_section_index.?) |
| | 4772 | break :blk zig_object.debug_str_section_zig_size; |
| | 4773 | if (shndx == self.debug_aranges_section_index.?) |
| | 4774 | break :blk zig_object.debug_aranges_section_zig_size; |
| | 4775 | if (shndx == self.debug_line_section_index.?) |
| | 4776 | break :blk zig_object.debug_line_section_zig_size; |
| | 4777 | unreachable; |
| | 4778 | } else 0; |
| | 4779 | const sh_offset = shdr.sh_offset + base_offset; |
| | 4780 | const sh_size = math.cast(usize, shdr.sh_size - base_offset) orelse return error.Overflow; |
| | 4781 | |
| | 4782 | const buffer = try gpa.alloc(u8, sh_size); |
| | 4783 | defer gpa.free(buffer); |
| | 4784 | const padding_byte: u8 = if (shdr.sh_type == elf.SHT_PROGBITS and |
| | 4785 | shdr.sh_flags & elf.SHF_EXECINSTR != 0) |
| | 4786 | 0xcc // int3 |
| | 4787 | else |
| | 4788 | 0; |
| | 4789 | @memset(buffer, padding_byte); |
| | 4790 | |
| | 4791 | for (atom_list.items) |atom_index| { |
| | 4792 | const atom_ptr = self.atom(atom_index).?; |
| | 4793 | assert(atom_ptr.flags.alive); |
| | 4794 | |
| | 4795 | const object = atom_ptr.file(self).?.object; |
| | 4796 | const offset = math.cast(usize, atom_ptr.value - shdr.sh_addr - base_offset) orelse |
| | 4797 | return error.Overflow; |
| | 4798 | const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow; |
| | 4799 | |
| | 4800 | log.debug("writing atom({d}) from 0x{x} to 0x{x}", .{ |
| | 4801 | atom_index, |
| | 4802 | sh_offset + offset, |
| | 4803 | sh_offset + offset + size, |
| | 4804 | }); |
| | 4805 | |
| | 4806 | // TODO decompress directly into provided buffer |
| | 4807 | const out_code = buffer[offset..][0..size]; |
| | 4808 | const in_code = try object.codeDecompressAlloc(self, atom_index); |
| | 4809 | defer gpa.free(in_code); |
| | 4810 | @memcpy(out_code, in_code); |
| | 4811 | } |
| | 4812 | |
| | 4813 | try self.base.file.?.pwriteAll(buffer, sh_offset); |
| 4493 | } | 4814 | } |
| | 4815 | } |
| | 4816 | |
| | 4817 | fn updateSymtabSize(self: *Elf) !void { |
| | 4818 | var nlocals: u32 = 0; |
| | 4819 | var nglobals: u32 = 0; |
| | 4820 | var strsize: u32 = 0; |
| | 4821 | |
| | 4822 | const gpa = self.base.allocator; |
| | 4823 | var files = std.ArrayList(File.Index).init(gpa); |
| | 4824 | defer files.deinit(); |
| | 4825 | try files.ensureTotalCapacityPrecise(self.objects.items.len + self.shared_objects.items.len + 1); |
| 4494 | | 4826 | |
| | 4827 | if (self.zig_object_index) |index| files.appendAssumeCapacity(index); |
| 4495 | for (self.objects.items) |index| { | 4828 | for (self.objects.items) |index| { |
| 4496 | const file_ptr = self.file(index).?; | 4829 | files.appendAssumeCapacity(index); |
| 4497 | file_ptr.updateSymtabSize(self); | | |
| 4498 | sizes.add(file_ptr.object.output_symtab_size); | | |
| 4499 | } | 4830 | } |
| 4500 | | | |
| 4501 | for (self.shared_objects.items) |index| { | 4831 | for (self.shared_objects.items) |index| { |
| | 4832 | files.appendAssumeCapacity(index); |
| | 4833 | } |
| | 4834 | |
| | 4835 | // Section symbols |
| | 4836 | for (self.output_sections.keys()) |_| { |
| | 4837 | nlocals += 1; |
| | 4838 | } |
| | 4839 | if (self.eh_frame_section_index) |_| { |
| | 4840 | nlocals += 1; |
| | 4841 | } |
| | 4842 | |
| | 4843 | for (files.items) |index| { |
| 4502 | const file_ptr = self.file(index).?; | 4844 | const file_ptr = self.file(index).?; |
| 4503 | file_ptr.updateSymtabSize(self); | 4845 | const ctx = switch (file_ptr) { |
| 4504 | sizes.add(file_ptr.shared_object.output_symtab_size); | 4846 | inline else => |x| &x.output_symtab_ctx, |
| | 4847 | }; |
| | 4848 | ctx.ilocal = nlocals + 1; |
| | 4849 | ctx.iglobal = nglobals + 1; |
| | 4850 | try file_ptr.updateSymtabSize(self); |
| | 4851 | nlocals += ctx.nlocals; |
| | 4852 | nglobals += ctx.nglobals; |
| | 4853 | strsize += ctx.strsize; |
| 4505 | } | 4854 | } |
| 4506 | | 4855 | |
| 4507 | if (self.zig_got_section_index) |_| { | 4856 | if (self.zig_got_section_index) |_| { |
| | 4857 | self.zig_got.output_symtab_ctx.ilocal = nlocals + 1; |
| 4508 | self.zig_got.updateSymtabSize(self); | 4858 | self.zig_got.updateSymtabSize(self); |
| 4509 | sizes.add(self.zig_got.output_symtab_size); | 4859 | nlocals += self.zig_got.output_symtab_ctx.nlocals; |
| | 4860 | strsize += self.zig_got.output_symtab_ctx.strsize; |
| 4510 | } | 4861 | } |
| 4511 | | 4862 | |
| 4512 | if (self.got_section_index) |_| { | 4863 | if (self.got_section_index) |_| { |
| | 4864 | self.got.output_symtab_ctx.ilocal = nlocals + 1; |
| 4513 | self.got.updateSymtabSize(self); | 4865 | self.got.updateSymtabSize(self); |
| 4514 | sizes.add(self.got.output_symtab_size); | 4866 | nlocals += self.got.output_symtab_ctx.nlocals; |
| | 4867 | strsize += self.got.output_symtab_ctx.strsize; |
| 4515 | } | 4868 | } |
| 4516 | | 4869 | |
| 4517 | if (self.plt_section_index) |_| { | 4870 | if (self.plt_section_index) |_| { |
| | 4871 | self.plt.output_symtab_ctx.ilocal = nlocals + 1; |
| 4518 | self.plt.updateSymtabSize(self); | 4872 | self.plt.updateSymtabSize(self); |
| 4519 | sizes.add(self.plt.output_symtab_size); | 4873 | nlocals += self.plt.output_symtab_ctx.nlocals; |
| | 4874 | strsize += self.plt.output_symtab_ctx.strsize; |
| 4520 | } | 4875 | } |
| 4521 | | 4876 | |
| 4522 | if (self.plt_got_section_index) |_| { | 4877 | if (self.plt_got_section_index) |_| { |
| | 4878 | self.plt_got.output_symtab_ctx.ilocal = nlocals + 1; |
| 4523 | self.plt_got.updateSymtabSize(self); | 4879 | self.plt_got.updateSymtabSize(self); |
| 4524 | sizes.add(self.plt_got.output_symtab_size); | 4880 | nlocals += self.plt_got.output_symtab_ctx.nlocals; |
| | 4881 | strsize += self.plt_got.output_symtab_ctx.strsize; |
| 4525 | } | 4882 | } |
| 4526 | | 4883 | |
| 4527 | if (self.linker_defined_index) |index| { | 4884 | for (files.items) |index| { |
| 4528 | const file_ptr = self.file(index).?; | 4885 | const file_ptr = self.file(index).?; |
| 4529 | file_ptr.updateSymtabSize(self); | 4886 | const ctx = switch (file_ptr) { |
| 4530 | sizes.add(file_ptr.linker_defined.output_symtab_size); | 4887 | inline else => |x| &x.output_symtab_ctx, |
| | 4888 | }; |
| | 4889 | ctx.iglobal += nlocals; |
| 4531 | } | 4890 | } |
| 4532 | | 4891 | |
| 4533 | const symtab_shdr = &self.shdrs.items[self.symtab_section_index.?]; | 4892 | const symtab_shdr = &self.shdrs.items[self.symtab_section_index.?]; |
| 4534 | symtab_shdr.sh_info = sizes.nlocals + 1; | 4893 | symtab_shdr.sh_info = nlocals + 1; |
| 4535 | symtab_shdr.sh_link = self.strtab_section_index.?; | | |
| 4536 | | | |
| 4537 | const sym_size: u64 = switch (self.ptr_width) { | | |
| 4538 | .p32 => @sizeOf(elf.Elf32_Sym), | | |
| 4539 | .p64 => @sizeOf(elf.Elf64_Sym), | | |
| 4540 | }; | | |
| 4541 | const needed_size = (sizes.nlocals + sizes.nglobals + 1) * sym_size; | | |
| 4542 | symtab_shdr.sh_size = needed_size; | | |
| 4543 | | | |
| 4544 | const strtab = &self.shdrs.items[self.strtab_section_index.?]; | | |
| 4545 | strtab.sh_size = sizes.strsize + 1; | | |
| 4546 | } | | |
| 4547 | | | |
| 4548 | fn updateSymtabSizeObject(self: *Elf, zig_object: *ZigObject) void { | | |
| 4549 | zig_object.asFile().updateSymtabSize(self); | | |
| 4550 | const sizes = zig_object.output_symtab_size; | | |
| 4551 | | | |
| 4552 | const symtab_shdr = &self.shdrs.items[self.symtab_section_index.?]; | | |
| 4553 | symtab_shdr.sh_info = sizes.nlocals + 1; | | |
| 4554 | symtab_shdr.sh_link = self.strtab_section_index.?; | 4894 | symtab_shdr.sh_link = self.strtab_section_index.?; |
| 4555 | | 4895 | |
| 4556 | const sym_size: u64 = switch (self.ptr_width) { | 4896 | const sym_size: u64 = switch (self.ptr_width) { |
| 4557 | .p32 => @sizeOf(elf.Elf32_Sym), | 4897 | .p32 => @sizeOf(elf.Elf32_Sym), |
| 4558 | .p64 => @sizeOf(elf.Elf64_Sym), | 4898 | .p64 => @sizeOf(elf.Elf64_Sym), |
| 4559 | }; | 4899 | }; |
| 4560 | const needed_size = (sizes.nlocals + sizes.nglobals + 1) * sym_size; | 4900 | const needed_size = (nlocals + nglobals + 1) * sym_size; |
| 4561 | symtab_shdr.sh_size = needed_size; | 4901 | symtab_shdr.sh_size = needed_size; |
| 4562 | | 4902 | |
| 4563 | const strtab = &self.shdrs.items[self.strtab_section_index.?]; | 4903 | const strtab = &self.shdrs.items[self.strtab_section_index.?]; |
| 4564 | strtab.sh_size = sizes.strsize + 1; | 4904 | strtab.sh_size = strsize + 1; |
| 4565 | } | 4905 | } |
| 4566 | | 4906 | |
| 4567 | fn writeSyntheticSections(self: *Elf) !void { | 4907 | fn writeSyntheticSections(self: *Elf) !void { |
| 4568 | const gpa = self.base.allocator; | 4908 | const gpa = self.base.allocator; |
| 4569 | | 4909 | |
| 4570 | if (self.zigObjectPtr()) |zig_object| { | | |
| 4571 | try zig_object.writeRelaSections(self); | | |
| 4572 | } | | |
| 4573 | | | |
| 4574 | if (self.interp_section_index) |shndx| { | 4910 | if (self.interp_section_index) |shndx| { |
| 4575 | const shdr = self.shdrs.items[shndx]; | 4911 | const shdr = self.shdrs.items[shndx]; |
| 4576 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; | 4912 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; |
| ... | @@ -4698,9 +5034,97 @@ fn writeSyntheticSections(self: *Elf) !void { | ... | @@ -4698,9 +5034,97 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4698 | try self.writeShStrtab(); | 5034 | try self.writeShStrtab(); |
| 4699 | } | 5035 | } |
| 4700 | | 5036 | |
| | 5037 | fn writeSyntheticSectionsObject(self: *Elf) !void { |
| | 5038 | const gpa = self.base.allocator; |
| | 5039 | |
| | 5040 | for (self.output_rela_sections.values()) |sec| { |
| | 5041 | if (sec.atom_list.items.len == 0) continue; |
| | 5042 | |
| | 5043 | const shdr = self.shdrs.items[sec.shndx]; |
| | 5044 | |
| | 5045 | const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse |
| | 5046 | return error.Overflow; |
| | 5047 | var relocs = try std.ArrayList(elf.Elf64_Rela).initCapacity(gpa, num_relocs); |
| | 5048 | defer relocs.deinit(); |
| | 5049 | |
| | 5050 | for (sec.atom_list.items) |atom_index| { |
| | 5051 | const atom_ptr = self.atom(atom_index) orelse continue; |
| | 5052 | if (!atom_ptr.flags.alive) continue; |
| | 5053 | try atom_ptr.writeRelocs(self, &relocs); |
| | 5054 | } |
| | 5055 | assert(relocs.items.len == num_relocs); |
| | 5056 | |
| | 5057 | const SortRelocs = struct { |
| | 5058 | pub fn lessThan(ctx: void, lhs: elf.Elf64_Rela, rhs: elf.Elf64_Rela) bool { |
| | 5059 | _ = ctx; |
| | 5060 | return lhs.r_offset < rhs.r_offset; |
| | 5061 | } |
| | 5062 | }; |
| | 5063 | |
| | 5064 | mem.sort(elf.Elf64_Rela, relocs.items, {}, SortRelocs.lessThan); |
| | 5065 | |
| | 5066 | log.debug("writing {s} from 0x{x} to 0x{x}", .{ |
| | 5067 | self.getShString(shdr.sh_name), |
| | 5068 | shdr.sh_offset, |
| | 5069 | shdr.sh_offset + shdr.sh_size, |
| | 5070 | }); |
| | 5071 | |
| | 5072 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), shdr.sh_offset); |
| | 5073 | } |
| | 5074 | |
| | 5075 | if (self.eh_frame_section_index) |shndx| { |
| | 5076 | const shdr = self.shdrs.items[shndx]; |
| | 5077 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; |
| | 5078 | var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); |
| | 5079 | defer buffer.deinit(); |
| | 5080 | try eh_frame.writeEhFrameObject(self, buffer.writer()); |
| | 5081 | log.debug("writing .eh_frame from 0x{x} to 0x{x}", .{ |
| | 5082 | shdr.sh_offset, |
| | 5083 | shdr.sh_offset + shdr.sh_size, |
| | 5084 | }); |
| | 5085 | assert(buffer.items.len == sh_size); |
| | 5086 | try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); |
| | 5087 | } |
| | 5088 | if (self.eh_frame_rela_section_index) |shndx| { |
| | 5089 | const shdr = self.shdrs.items[shndx]; |
| | 5090 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; |
| | 5091 | var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); |
| | 5092 | defer buffer.deinit(); |
| | 5093 | try eh_frame.writeEhFrameRelocs(self, buffer.writer()); |
| | 5094 | assert(buffer.items.len == sh_size); |
| | 5095 | log.debug("writing .rela.eh_frame from 0x{x} to 0x{x}", .{ |
| | 5096 | shdr.sh_offset, |
| | 5097 | shdr.sh_offset + shdr.sh_size, |
| | 5098 | }); |
| | 5099 | try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); |
| | 5100 | } |
| | 5101 | |
| | 5102 | try self.writeComdatGroups(); |
| | 5103 | try self.writeSymtab(); |
| | 5104 | try self.writeShStrtab(); |
| | 5105 | } |
| | 5106 | |
| | 5107 | fn writeComdatGroups(self: *Elf) !void { |
| | 5108 | const gpa = self.base.allocator; |
| | 5109 | for (self.comdat_group_sections.items) |cgs| { |
| | 5110 | const shdr = self.shdrs.items[cgs.shndx]; |
| | 5111 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; |
| | 5112 | var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); |
| | 5113 | defer buffer.deinit(); |
| | 5114 | try cgs.write(self, buffer.writer()); |
| | 5115 | assert(buffer.items.len == sh_size); |
| | 5116 | log.debug("writing COMDAT group from 0x{x} to 0x{x}", .{ |
| | 5117 | shdr.sh_offset, |
| | 5118 | shdr.sh_offset + shdr.sh_size, |
| | 5119 | }); |
| | 5120 | try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); |
| | 5121 | } |
| | 5122 | } |
| | 5123 | |
| 4701 | fn writeShStrtab(self: *Elf) !void { | 5124 | fn writeShStrtab(self: *Elf) !void { |
| 4702 | if (self.shstrtab_section_index) |index| { | 5125 | if (self.shstrtab_section_index) |index| { |
| 4703 | const shdr = self.shdrs.items[index]; | 5126 | const shdr = self.shdrs.items[index]; |
| | 5127 | log.debug("writing .shstrtab from 0x{x} to 0x{x}", .{ shdr.sh_offset, shdr.sh_offset + shdr.sh_size }); |
| 4704 | try self.base.file.?.pwriteAll(self.shstrtab.items, shdr.sh_offset); | 5128 | try self.base.file.?.pwriteAll(self.shstrtab.items, shdr.sh_offset); |
| 4705 | } | 5129 | } |
| 4706 | } | 5130 | } |
| ... | @@ -4715,67 +5139,55 @@ fn writeSymtab(self: *Elf) !void { | ... | @@ -4715,67 +5139,55 @@ fn writeSymtab(self: *Elf) !void { |
| 4715 | }; | 5139 | }; |
| 4716 | const nsyms = math.cast(usize, @divExact(symtab_shdr.sh_size, sym_size)) orelse return error.Overflow; | 5140 | const nsyms = math.cast(usize, @divExact(symtab_shdr.sh_size, sym_size)) orelse return error.Overflow; |
| 4717 | | 5141 | |
| 4718 | log.debug("writing {d} symbols at 0x{x}", .{ nsyms, symtab_shdr.sh_offset }); | 5142 | log.debug("writing {d} symbols in .symtab from 0x{x} to 0x{x}", .{ |
| | 5143 | nsyms, |
| | 5144 | symtab_shdr.sh_offset, |
| | 5145 | symtab_shdr.sh_offset + symtab_shdr.sh_size, |
| | 5146 | }); |
| | 5147 | log.debug("writing .strtab from 0x{x} to 0x{x}", .{ |
| | 5148 | strtab_shdr.sh_offset, |
| | 5149 | strtab_shdr.sh_offset + strtab_shdr.sh_size, |
| | 5150 | }); |
| 4719 | | 5151 | |
| 4720 | try self.symtab.resize(gpa, nsyms); | 5152 | try self.symtab.resize(gpa, nsyms); |
| 4721 | const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow; | 5153 | const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow; |
| 4722 | try self.strtab.ensureUnusedCapacity(gpa, needed_strtab_size); | 5154 | try self.strtab.ensureUnusedCapacity(gpa, needed_strtab_size); |
| 4723 | | 5155 | |
| 4724 | const Ctx = struct { | 5156 | self.writeSectionSymbols(); |
| 4725 | ilocal: usize, | | |
| 4726 | iglobal: usize, | | |
| 4727 | | | |
| 4728 | fn incr(this: *@This(), ss: SymtabSize) void { | | |
| 4729 | this.ilocal += ss.nlocals; | | |
| 4730 | this.iglobal += ss.nglobals; | | |
| 4731 | } | | |
| 4732 | }; | | |
| 4733 | var ctx: Ctx = .{ | | |
| 4734 | .ilocal = 1, | | |
| 4735 | .iglobal = symtab_shdr.sh_info, | | |
| 4736 | }; | | |
| 4737 | | 5157 | |
| 4738 | if (self.zigObjectPtr()) |zig_object| { | 5158 | if (self.zigObjectPtr()) |zig_object| { |
| 4739 | zig_object.asFile().writeSymtab(self, ctx); | 5159 | zig_object.asFile().writeSymtab(self); |
| 4740 | ctx.incr(zig_object.output_symtab_size); | | |
| 4741 | } | 5160 | } |
| 4742 | | 5161 | |
| 4743 | for (self.objects.items) |index| { | 5162 | for (self.objects.items) |index| { |
| 4744 | const file_ptr = self.file(index).?; | 5163 | const file_ptr = self.file(index).?; |
| 4745 | file_ptr.writeSymtab(self, ctx); | 5164 | file_ptr.writeSymtab(self); |
| 4746 | ctx.incr(file_ptr.object.output_symtab_size); | | |
| 4747 | } | 5165 | } |
| 4748 | | 5166 | |
| 4749 | for (self.shared_objects.items) |index| { | 5167 | for (self.shared_objects.items) |index| { |
| 4750 | const file_ptr = self.file(index).?; | 5168 | const file_ptr = self.file(index).?; |
| 4751 | file_ptr.writeSymtab(self, ctx); | 5169 | file_ptr.writeSymtab(self); |
| 4752 | ctx.incr(file_ptr.shared_object.output_symtab_size); | | |
| 4753 | } | 5170 | } |
| 4754 | | 5171 | |
| 4755 | if (self.zig_got_section_index) |_| { | 5172 | if (self.zig_got_section_index) |_| { |
| 4756 | self.zig_got.writeSymtab(self, ctx); | 5173 | self.zig_got.writeSymtab(self); |
| 4757 | ctx.incr(self.zig_got.output_symtab_size); | | |
| 4758 | } | 5174 | } |
| 4759 | | 5175 | |
| 4760 | if (self.got_section_index) |_| { | 5176 | if (self.got_section_index) |_| { |
| 4761 | self.got.writeSymtab(self, ctx); | 5177 | self.got.writeSymtab(self); |
| 4762 | ctx.incr(self.got.output_symtab_size); | | |
| 4763 | } | 5178 | } |
| 4764 | | 5179 | |
| 4765 | if (self.plt_section_index) |_| { | 5180 | if (self.plt_section_index) |_| { |
| 4766 | self.plt.writeSymtab(self, ctx); | 5181 | self.plt.writeSymtab(self); |
| 4767 | ctx.incr(self.plt.output_symtab_size); | | |
| 4768 | } | 5182 | } |
| 4769 | | 5183 | |
| 4770 | if (self.plt_got_section_index) |_| { | 5184 | if (self.plt_got_section_index) |_| { |
| 4771 | self.plt_got.writeSymtab(self, ctx); | 5185 | self.plt_got.writeSymtab(self); |
| 4772 | ctx.incr(self.plt_got.output_symtab_size); | | |
| 4773 | } | 5186 | } |
| 4774 | | 5187 | |
| 4775 | if (self.linker_defined_index) |index| { | 5188 | if (self.linker_defined_index) |index| { |
| 4776 | const file_ptr = self.file(index).?; | 5189 | const file_ptr = self.file(index).?; |
| 4777 | file_ptr.writeSymtab(self, ctx); | 5190 | file_ptr.writeSymtab(self); |
| 4778 | ctx.incr(file_ptr.linker_defined.output_symtab_size); | | |
| 4779 | } | 5191 | } |
| 4780 | | 5192 | |
| 4781 | const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian(); | 5193 | const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian(); |
| ... | @@ -4808,52 +5220,42 @@ fn writeSymtab(self: *Elf) !void { | ... | @@ -4808,52 +5220,42 @@ fn writeSymtab(self: *Elf) !void { |
| 4808 | try self.base.file.?.pwriteAll(self.strtab.items, strtab_shdr.sh_offset); | 5220 | try self.base.file.?.pwriteAll(self.strtab.items, strtab_shdr.sh_offset); |
| 4809 | } | 5221 | } |
| 4810 | | 5222 | |
| 4811 | fn writeSymtabObject(self: *Elf, zig_object: *ZigObject) !void { | 5223 | fn writeSectionSymbols(self: *Elf) void { |
| 4812 | const gpa = self.base.allocator; | 5224 | var ilocal: u32 = 1; |
| 4813 | const symtab_shdr = self.shdrs.items[self.symtab_section_index.?]; | 5225 | for (self.output_sections.keys()) |shndx| { |
| 4814 | const strtab_shdr = self.shdrs.items[self.strtab_section_index.?]; | 5226 | const shdr = self.shdrs.items[shndx]; |
| 4815 | const sym_size: u64 = switch (self.ptr_width) { | 5227 | const out_sym = &self.symtab.items[ilocal]; |
| 4816 | .p32 => @sizeOf(elf.Elf32_Sym), | 5228 | out_sym.* = .{ |
| 4817 | .p64 => @sizeOf(elf.Elf64_Sym), | 5229 | .st_name = 0, |
| 4818 | }; | 5230 | .st_value = shdr.sh_addr, |
| 4819 | const nsyms = math.cast(usize, @divExact(symtab_shdr.sh_size, sym_size)) orelse return error.Overflow; | 5231 | .st_info = elf.STT_SECTION, |
| 4820 | | 5232 | .st_shndx = @intCast(shndx), |
| 4821 | log.debug("writing {d} symbols at 0x{x}", .{ nsyms, symtab_shdr.sh_offset }); | 5233 | .st_size = 0, |
| 4822 | | 5234 | .st_other = 0, |
| 4823 | try self.symtab.resize(gpa, nsyms); | 5235 | }; |
| 4824 | const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow; | 5236 | ilocal += 1; |
| 4825 | try self.strtab.ensureUnusedCapacity(gpa, needed_strtab_size); | 5237 | } |
| 4826 | | | |
| 4827 | zig_object.asFile().writeSymtab(self, .{ .ilocal = 1, .iglobal = symtab_shdr.sh_info }); | | |
| 4828 | | | |
| 4829 | const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian(); | | |
| 4830 | switch (self.ptr_width) { | | |
| 4831 | .p32 => { | | |
| 4832 | const buf = try gpa.alloc(elf.Elf32_Sym, self.symtab.items.len); | | |
| 4833 | defer gpa.free(buf); | | |
| 4834 | | 5238 | |
| 4835 | for (buf, self.symtab.items) |*out, sym| { | 5239 | if (self.eh_frame_section_index) |shndx| { |
| 4836 | out.* = .{ | 5240 | const shdr = self.shdrs.items[shndx]; |
| 4837 | .st_name = sym.st_name, | 5241 | const out_sym = &self.symtab.items[ilocal]; |
| 4838 | .st_info = sym.st_info, | 5242 | out_sym.* = .{ |
| 4839 | .st_other = sym.st_other, | 5243 | .st_name = 0, |
| 4840 | .st_shndx = sym.st_shndx, | 5244 | .st_value = shdr.sh_addr, |
| 4841 | .st_value = @as(u32, @intCast(sym.st_value)), | 5245 | .st_info = elf.STT_SECTION, |
| 4842 | .st_size = @as(u32, @intCast(sym.st_size)), | 5246 | .st_shndx = @intCast(shndx), |
| 4843 | }; | 5247 | .st_size = 0, |
| 4844 | if (foreign_endian) mem.byteSwapAllFields(elf.Elf32_Sym, out); | 5248 | .st_other = 0, |
| 4845 | } | 5249 | }; |
| 4846 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), symtab_shdr.sh_offset); | 5250 | ilocal += 1; |
| 4847 | }, | | |
| 4848 | .p64 => { | | |
| 4849 | if (foreign_endian) { | | |
| 4850 | for (self.symtab.items) |*sym| mem.byteSwapAllFields(elf.Elf64_Sym, sym); | | |
| 4851 | } | | |
| 4852 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.symtab.items), symtab_shdr.sh_offset); | | |
| 4853 | }, | | |
| 4854 | } | 5251 | } |
| | 5252 | } |
| 4855 | | 5253 | |
| 4856 | try self.base.file.?.pwriteAll(self.strtab.items, strtab_shdr.sh_offset); | 5254 | pub fn sectionSymbolOutputSymtabIndex(self: Elf, shndx: u32) u32 { |
| | 5255 | if (self.eh_frame_section_index) |index| { |
| | 5256 | if (index == shndx) return @intCast(self.output_sections.keys().len + 1); |
| | 5257 | } |
| | 5258 | return @intCast(self.output_sections.getIndex(shndx).? + 1); |
| 4857 | } | 5259 | } |
| 4858 | | 5260 | |
| 4859 | /// Always 4 or 8 depending on whether this is 32-bit ELF or 64-bit ELF. | 5261 | /// Always 4 or 8 depending on whether this is 32-bit ELF or 64-bit ELF. |
| ... | @@ -5707,13 +6109,69 @@ fn formatShdr( | ... | @@ -5707,13 +6109,69 @@ fn formatShdr( |
| 5707 | _ = options; | 6109 | _ = options; |
| 5708 | _ = unused_fmt_string; | 6110 | _ = unused_fmt_string; |
| 5709 | const shdr = ctx.shdr; | 6111 | const shdr = ctx.shdr; |
| 5710 | try writer.print("{s} : @{x} ({x}) : align({x}) : size({x})", .{ | 6112 | try writer.print("{s} : @{x} ({x}) : align({x}) : size({x}) : flags({})", .{ |
| 5711 | ctx.elf_file.getShString(shdr.sh_name), shdr.sh_offset, | 6113 | ctx.elf_file.getShString(shdr.sh_name), shdr.sh_offset, |
| 5712 | shdr.sh_addr, shdr.sh_addralign, | 6114 | shdr.sh_addr, shdr.sh_addralign, |
| 5713 | shdr.sh_size, | 6115 | shdr.sh_size, fmtShdrFlags(shdr.sh_flags), |
| 5714 | }); | 6116 | }); |
| 5715 | } | 6117 | } |
| 5716 | | 6118 | |
| | 6119 | pub fn fmtShdrFlags(sh_flags: u64) std.fmt.Formatter(formatShdrFlags) { |
| | 6120 | return .{ .data = sh_flags }; |
| | 6121 | } |
| | 6122 | |
| | 6123 | fn formatShdrFlags( |
| | 6124 | sh_flags: u64, |
| | 6125 | comptime unused_fmt_string: []const u8, |
| | 6126 | options: std.fmt.FormatOptions, |
| | 6127 | writer: anytype, |
| | 6128 | ) !void { |
| | 6129 | _ = unused_fmt_string; |
| | 6130 | _ = options; |
| | 6131 | if (elf.SHF_WRITE & sh_flags != 0) { |
| | 6132 | try writer.writeAll("W"); |
| | 6133 | } |
| | 6134 | if (elf.SHF_ALLOC & sh_flags != 0) { |
| | 6135 | try writer.writeAll("A"); |
| | 6136 | } |
| | 6137 | if (elf.SHF_EXECINSTR & sh_flags != 0) { |
| | 6138 | try writer.writeAll("X"); |
| | 6139 | } |
| | 6140 | if (elf.SHF_MERGE & sh_flags != 0) { |
| | 6141 | try writer.writeAll("M"); |
| | 6142 | } |
| | 6143 | if (elf.SHF_STRINGS & sh_flags != 0) { |
| | 6144 | try writer.writeAll("S"); |
| | 6145 | } |
| | 6146 | if (elf.SHF_INFO_LINK & sh_flags != 0) { |
| | 6147 | try writer.writeAll("I"); |
| | 6148 | } |
| | 6149 | if (elf.SHF_LINK_ORDER & sh_flags != 0) { |
| | 6150 | try writer.writeAll("L"); |
| | 6151 | } |
| | 6152 | if (elf.SHF_EXCLUDE & sh_flags != 0) { |
| | 6153 | try writer.writeAll("E"); |
| | 6154 | } |
| | 6155 | if (elf.SHF_COMPRESSED & sh_flags != 0) { |
| | 6156 | try writer.writeAll("C"); |
| | 6157 | } |
| | 6158 | if (elf.SHF_GROUP & sh_flags != 0) { |
| | 6159 | try writer.writeAll("G"); |
| | 6160 | } |
| | 6161 | if (elf.SHF_OS_NONCONFORMING & sh_flags != 0) { |
| | 6162 | try writer.writeAll("O"); |
| | 6163 | } |
| | 6164 | if (elf.SHF_TLS & sh_flags != 0) { |
| | 6165 | try writer.writeAll("T"); |
| | 6166 | } |
| | 6167 | if (elf.SHF_X86_64_LARGE & sh_flags != 0) { |
| | 6168 | try writer.writeAll("l"); |
| | 6169 | } |
| | 6170 | if (elf.SHF_MIPS_ADDR & sh_flags != 0 or elf.SHF_ARM_PURECODE & sh_flags != 0) { |
| | 6171 | try writer.writeAll("p"); |
| | 6172 | } |
| | 6173 | } |
| | 6174 | |
| 5717 | const FormatPhdrCtx = struct { | 6175 | const FormatPhdrCtx = struct { |
| 5718 | elf_file: *Elf, | 6176 | elf_file: *Elf, |
| 5719 | phdr: elf.Elf64_Phdr, | 6177 | phdr: elf.Elf64_Phdr, |
| ... | @@ -5813,9 +6271,14 @@ fn fmtDumpState( | ... | @@ -5813,9 +6271,14 @@ fn fmtDumpState( |
| 5813 | try writer.print("{}\n", .{self.got.fmt(self)}); | 6271 | try writer.print("{}\n", .{self.got.fmt(self)}); |
| 5814 | try writer.print("{}\n", .{self.zig_got.fmt(self)}); | 6272 | try writer.print("{}\n", .{self.zig_got.fmt(self)}); |
| 5815 | | 6273 | |
| 5816 | try writer.writeAll("Output shdrs\n"); | 6274 | try writer.writeAll("Output COMDAT groups\n"); |
| | 6275 | for (self.comdat_group_sections.items) |cg| { |
| | 6276 | try writer.print(" shdr({d}) : COMDAT({d})\n", .{ cg.shndx, cg.cg_index }); |
| | 6277 | } |
| | 6278 | |
| | 6279 | try writer.writeAll("\nOutput shdrs\n"); |
| 5817 | for (self.shdrs.items, 0..) |shdr, shndx| { | 6280 | for (self.shdrs.items, 0..) |shdr, shndx| { |
| 5818 | try writer.print("shdr({d}) : phdr({?d}) : {}\n", .{ | 6281 | try writer.print(" shdr({d}) : phdr({?d}) : {}\n", .{ |
| 5819 | shndx, | 6282 | shndx, |
| 5820 | self.phdr_to_shdr_table.get(@intCast(shndx)), | 6283 | self.phdr_to_shdr_table.get(@intCast(shndx)), |
| 5821 | self.fmtShdr(shdr), | 6284 | self.fmtShdr(shdr), |
| ... | @@ -5823,7 +6286,7 @@ fn fmtDumpState( | ... | @@ -5823,7 +6286,7 @@ fn fmtDumpState( |
| 5823 | } | 6286 | } |
| 5824 | try writer.writeAll("\nOutput phdrs\n"); | 6287 | try writer.writeAll("\nOutput phdrs\n"); |
| 5825 | for (self.phdrs.items, 0..) |phdr, phndx| { | 6288 | for (self.phdrs.items, 0..) |phdr, phndx| { |
| 5826 | try writer.print("phdr{d} : {}\n", .{ phndx, self.fmtPhdr(phdr) }); | 6289 | try writer.print(" phdr{d} : {}\n", .{ phndx, self.fmtPhdr(phdr) }); |
| 5827 | } | 6290 | } |
| 5828 | } | 6291 | } |
| 5829 | | 6292 | |
| ... | @@ -5882,16 +6345,12 @@ pub const ComdatGroup = struct { | ... | @@ -5882,16 +6345,12 @@ pub const ComdatGroup = struct { |
| 5882 | pub const Index = u32; | 6345 | pub const Index = u32; |
| 5883 | }; | 6346 | }; |
| 5884 | | 6347 | |
| 5885 | pub const SymtabSize = struct { | 6348 | pub const SymtabCtx = struct { |
| | 6349 | ilocal: u32 = 0, |
| | 6350 | iglobal: u32 = 0, |
| 5886 | nlocals: u32 = 0, | 6351 | nlocals: u32 = 0, |
| 5887 | nglobals: u32 = 0, | 6352 | nglobals: u32 = 0, |
| 5888 | strsize: u32 = 0, | 6353 | strsize: u32 = 0, |
| 5889 | | | |
| 5890 | fn add(ss: *SymtabSize, other: SymtabSize) void { | | |
| 5891 | ss.nlocals += other.nlocals; | | |
| 5892 | ss.nglobals += other.nglobals; | | |
| 5893 | ss.strsize += other.strsize; | | |
| 5894 | } | | |
| 5895 | }; | 6354 | }; |
| 5896 | | 6355 | |
| 5897 | pub const null_sym = elf.Elf64_Sym{ | 6356 | pub const null_sym = elf.Elf64_Sym{ |
| ... | @@ -5942,8 +6401,13 @@ const LastAtomAndFreeList = struct { | ... | @@ -5942,8 +6401,13 @@ const LastAtomAndFreeList = struct { |
| 5942 | /// by 1 byte. It will then have -1 overcapacity. | 6401 | /// by 1 byte. It will then have -1 overcapacity. |
| 5943 | free_list: std.ArrayListUnmanaged(Atom.Index) = .{}, | 6402 | free_list: std.ArrayListUnmanaged(Atom.Index) = .{}, |
| 5944 | }; | 6403 | }; |
| | 6404 | const LastAtomAndFreeListTable = std.AutoArrayHashMapUnmanaged(u32, LastAtomAndFreeList); |
| 5945 | | 6405 | |
| 5946 | const LastAtomAndFreeListTable = std.AutoArrayHashMapUnmanaged(u16, LastAtomAndFreeList); | 6406 | const RelaSection = struct { |
| | 6407 | shndx: u32, |
| | 6408 | atom_list: std.ArrayListUnmanaged(Atom.Index) = .{}, |
| | 6409 | }; |
| | 6410 | const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection); |
| 5947 | | 6411 | |
| 5948 | pub const R_X86_64_ZIG_GOT32 = elf.R_X86_64_NUM + 1; | 6412 | pub const R_X86_64_ZIG_GOT32 = elf.R_X86_64_NUM + 1; |
| 5949 | pub const R_X86_64_ZIG_GOTPCREL = elf.R_X86_64_NUM + 2; | 6413 | pub const R_X86_64_ZIG_GOTPCREL = elf.R_X86_64_NUM + 2; |
| ... | @@ -5976,6 +6440,7 @@ const Archive = @import("Elf/Archive.zig"); | ... | @@ -5976,6 +6440,7 @@ const Archive = @import("Elf/Archive.zig"); |
| 5976 | pub const Atom = @import("Elf/Atom.zig"); | 6440 | pub const Atom = @import("Elf/Atom.zig"); |
| 5977 | const Cache = std.Build.Cache; | 6441 | const Cache = std.Build.Cache; |
| 5978 | const Compilation = @import("../Compilation.zig"); | 6442 | const Compilation = @import("../Compilation.zig"); |
| | 6443 | const ComdatGroupSection = synthetic_sections.ComdatGroupSection; |
| 5979 | const CopyRelSection = synthetic_sections.CopyRelSection; | 6444 | const CopyRelSection = synthetic_sections.CopyRelSection; |
| 5980 | const DynamicSection = synthetic_sections.DynamicSection; | 6445 | const DynamicSection = synthetic_sections.DynamicSection; |
| 5981 | const DynsymSection = synthetic_sections.DynsymSection; | 6446 | const DynsymSection = synthetic_sections.DynsymSection; |