authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-21 14:51:10+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-08-21 14:51:10+02:00
log8fc15f188c0deb1b0e2847297e535823eca1d2e8
tree1dcda4337dc446f1d1c5e3bb478ea4b9678c383c
parent61919fe63d1eb7134a3c85fe0a4cf279744de3e9
parente79ac14ef34d8ceea945de972b7f395b8f53621f
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #21145 from ziglang/elf-dwarf-relocs

elf+zigobject: emit relocs for debug sections

10 files changed, 470 insertions(+), 238 deletions(-)

src/arch/riscv64/Emit.zig+12-12
......@@ -56,17 +56,17 @@ pub fn emitMir(emit: *Emit) Error!void {
5656 const hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20);
5757 const lo_r_type: u32 = @intFromEnum(std.elf.R_RISCV.LO12_I);
5858
59 try atom_ptr.addReloc(elf_file, .{
59 try atom_ptr.addReloc(elf_file.base.comp.gpa, .{
6060 .r_offset = start_offset,
6161 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | hi_r_type,
6262 .r_addend = 0,
63 });
63 }, zo);
6464
65 try atom_ptr.addReloc(elf_file, .{
65 try atom_ptr.addReloc(elf_file.base.comp.gpa, .{
6666 .r_offset = start_offset + 4,
6767 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | lo_r_type,
6868 .r_addend = 0,
69 });
69 }, zo);
7070 },
7171 .load_tlv_reloc => |symbol| {
7272 const elf_file = emit.bin_file.cast(.elf).?;
......@@ -76,23 +76,23 @@ pub fn emitMir(emit: *Emit) Error!void {
7676
7777 const R_RISCV = std.elf.R_RISCV;
7878
79 try atom_ptr.addReloc(elf_file, .{
79 try atom_ptr.addReloc(elf_file.base.comp.gpa, .{
8080 .r_offset = start_offset,
8181 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | @intFromEnum(R_RISCV.TPREL_HI20),
8282 .r_addend = 0,
83 });
83 }, zo);
8484
85 try atom_ptr.addReloc(elf_file, .{
85 try atom_ptr.addReloc(elf_file.base.comp.gpa, .{
8686 .r_offset = start_offset + 4,
8787 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | @intFromEnum(R_RISCV.TPREL_ADD),
8888 .r_addend = 0,
89 });
89 }, zo);
9090
91 try atom_ptr.addReloc(elf_file, .{
91 try atom_ptr.addReloc(elf_file.base.comp.gpa, .{
9292 .r_offset = start_offset + 8,
9393 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | @intFromEnum(R_RISCV.TPREL_LO12_I),
9494 .r_addend = 0,
95 });
95 }, zo);
9696 },
9797 .call_extern_fn_reloc => |symbol| {
9898 const elf_file = emit.bin_file.cast(.elf).?;
......@@ -101,11 +101,11 @@ pub fn emitMir(emit: *Emit) Error!void {
101101
102102 const r_type: u32 = @intFromEnum(std.elf.R_RISCV.CALL_PLT);
103103
104 try atom_ptr.addReloc(elf_file, .{
104 try atom_ptr.addReloc(elf_file.base.comp.gpa, .{
105105 .r_offset = start_offset,
106106 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type,
107107 .r_addend = 0,
108 });
108 }, zo);
109109 },
110110 };
111111 }
src/arch/x86_64/Emit.zig+10-10
......@@ -48,11 +48,11 @@ pub fn emitMir(emit: *Emit) Error!void {
4848 const zo = elf_file.zigObjectPtr().?;
4949 const atom_ptr = zo.symbol(emit.atom_index).atom(elf_file).?;
5050 const r_type = @intFromEnum(std.elf.R_X86_64.PLT32);
51 try atom_ptr.addReloc(elf_file, .{
51 try atom_ptr.addReloc(elf_file.base.comp.gpa, .{
5252 .r_offset = end_offset - 4,
5353 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
5454 .r_addend = lowered_relocs[0].off - 4,
55 });
55 }, zo);
5656 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
5757 // Add relocation to the decl.
5858 const zo = macho_file.getZigObject().?;
......@@ -95,22 +95,22 @@ pub fn emitMir(emit: *Emit) Error!void {
9595 const zo = elf_file.zigObjectPtr().?;
9696 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
9797 const r_type = @intFromEnum(std.elf.R_X86_64.TLSLD);
98 try atom.addReloc(elf_file, .{
98 try atom.addReloc(elf_file.base.comp.gpa, .{
9999 .r_offset = end_offset - 4,
100100 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
101101 .r_addend = lowered_relocs[0].off - 4,
102 });
102 }, zo);
103103 },
104104 .linker_dtpoff => |sym_index| {
105105 const elf_file = emit.lower.bin_file.cast(.elf).?;
106106 const zo = elf_file.zigObjectPtr().?;
107107 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
108108 const r_type = @intFromEnum(std.elf.R_X86_64.DTPOFF32);
109 try atom.addReloc(elf_file, .{
109 try atom.addReloc(elf_file.base.comp.gpa, .{
110110 .r_offset = end_offset - 4,
111111 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
112112 .r_addend = lowered_relocs[0].off,
113 });
113 }, zo);
114114 },
115115 .linker_reloc => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
116116 const zo = elf_file.zigObjectPtr().?;
......@@ -121,21 +121,21 @@ pub fn emitMir(emit: *Emit) Error!void {
121121 @intFromEnum(std.elf.R_X86_64.GOTPCREL)
122122 else
123123 @intFromEnum(std.elf.R_X86_64.PC32);
124 try atom.addReloc(elf_file, .{
124 try atom.addReloc(elf_file.base.comp.gpa, .{
125125 .r_offset = end_offset - 4,
126126 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
127127 .r_addend = lowered_relocs[0].off - 4,
128 });
128 }, zo);
129129 } else {
130130 const r_type: u32 = if (sym.flags.is_tls)
131131 @intFromEnum(std.elf.R_X86_64.TPOFF32)
132132 else
133133 @intFromEnum(std.elf.R_X86_64.@"32");
134 try atom.addReloc(elf_file, .{
134 try atom.addReloc(elf_file.base.comp.gpa, .{
135135 .r_offset = end_offset - 4,
136136 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
137137 .r_addend = lowered_relocs[0].off,
138 });
138 }, zo);
139139 }
140140 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
141141 const zo = macho_file.getZigObject().?;
src/link/Dwarf.zig+57-23
......@@ -201,7 +201,7 @@ const StringSection = struct {
201201};
202202
203203/// A linker section containing a sequence of `Unit`s.
204const Section = struct {
204pub const Section = struct {
205205 dirty: bool,
206206 pad_to_ideal: bool,
207207 alignment: InternPool.Alignment,
......@@ -287,7 +287,7 @@ const Section = struct {
287287 return sec.getUnit(unit).addEntry(sec, dwarf);
288288 }
289289
290 fn getUnit(sec: *Section, unit: Unit.Index) *Unit {
290 pub fn getUnit(sec: *Section, unit: Unit.Index) *Unit {
291291 return &sec.units.items[@intFromEnum(unit)];
292292 }
293293
......@@ -368,7 +368,7 @@ const Unit = struct {
368368 none = std.math.maxInt(u32),
369369 _,
370370
371 fn unwrap(uio: Optional) ?Index {
371 pub fn unwrap(uio: Optional) ?Index {
372372 return if (uio != .none) @enumFromInt(@intFromEnum(uio)) else null;
373373 }
374374 };
......@@ -415,7 +415,7 @@ const Unit = struct {
415415 return entry;
416416 }
417417
418 fn getEntry(unit: *Unit, entry: Entry.Index) *Entry {
418 pub fn getEntry(unit: *Unit, entry: Entry.Index) *Entry {
419419 return &unit.entries.items[@intFromEnum(entry)];
420420 }
421421
......@@ -614,7 +614,7 @@ const Entry = struct {
614614 none = std.math.maxInt(u32),
615615 _,
616616
617 fn unwrap(eio: Optional) ?Index {
617 pub fn unwrap(eio: Optional) ?Index {
618618 return if (eio != .none) @enumFromInt(@intFromEnum(eio)) else null;
619619 }
620620 };
......@@ -736,7 +736,7 @@ const Entry = struct {
736736 }
737737 }
738738
739 fn assertNonEmpty(entry: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf) *Entry {
739 pub fn assertNonEmpty(entry: *Entry, unit: *Unit, sec: *Section, dwarf: *Dwarf) *Entry {
740740 if (entry.len > 0) return entry;
741741 if (std.debug.runtime_safety) {
742742 log.err("missing {} from {s}", .{
......@@ -1958,11 +1958,10 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
19581958 const loc = tree.tokenLocation(0, tree.nodes.items(.main_token)[decl_inst.data.declaration.src_node]);
19591959 assert(loc.line == zcu.navSrcLine(nav_index));
19601960
1961 const unit = try dwarf.getUnit(file.mod);
19621961 var wip_nav: WipNav = .{
19631962 .dwarf = dwarf,
19641963 .pt = pt,
1965 .unit = unit,
1964 .unit = try dwarf.getUnit(file.mod),
19661965 .entry = undefined,
19671966 .any_children = false,
19681967 .func = .none,
......@@ -1981,7 +1980,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
19811980 switch (ip.indexToKey(nav_val.toIntern())) {
19821981 .func => |func| {
19831982 if (nav_gop.found_existing) {
1984 const unit_ptr = dwarf.debug_info.section.getUnit(unit);
1983 const unit_ptr = dwarf.debug_info.section.getUnit(wip_nav.unit);
19851984 const entry_ptr = unit_ptr.getEntry(nav_gop.value_ptr.*);
19861985 if (entry_ptr.len >= AbbrevCode.decl_bytes) {
19871986 var abbrev_code_buf: [AbbrevCode.decl_bytes]u8 = undefined;
......@@ -2000,7 +1999,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
20001999 }
20012000 }
20022001 entry_ptr.clear();
2003 } else nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);
2002 } else nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
20042003 wip_nav.entry = nav_gop.value_ptr.*;
20052004
20062005 const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: {
......@@ -2074,8 +2073,14 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
20742073 if (type_inst_info.inst != value_inst) break :decl_struct;
20752074
20762075 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());
2077 if (type_gop.found_existing) nav_gop.value_ptr.* = type_gop.value_ptr.* else {
2078 if (!nav_gop.found_existing) nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);
2076 if (type_gop.found_existing) {
2077 dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).clear();
2078 nav_gop.value_ptr.* = type_gop.value_ptr.*;
2079 } else {
2080 if (nav_gop.found_existing)
2081 dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear()
2082 else
2083 nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
20792084 type_gop.value_ptr.* = nav_gop.value_ptr.*;
20802085 }
20812086 wip_nav.entry = nav_gop.value_ptr.*;
......@@ -2139,7 +2144,10 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
21392144 break :done;
21402145 }
21412146
2142 if (!nav_gop.found_existing) nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);
2147 if (nav_gop.found_existing)
2148 dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear()
2149 else
2150 nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
21432151 wip_nav.entry = nav_gop.value_ptr.*;
21442152 const diw = wip_nav.debug_info.writer(dwarf.gpa);
21452153 try uleb128(diw, @intFromEnum(AbbrevCode.decl_alias));
......@@ -2190,8 +2198,14 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
21902198 if (type_inst_info.inst != value_inst) break :decl_enum;
21912199
21922200 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());
2193 if (type_gop.found_existing) nav_gop.value_ptr.* = type_gop.value_ptr.* else {
2194 if (!nav_gop.found_existing) nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);
2201 if (type_gop.found_existing) {
2202 dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).clear();
2203 nav_gop.value_ptr.* = type_gop.value_ptr.*;
2204 } else {
2205 if (nav_gop.found_existing)
2206 dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear()
2207 else
2208 nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
21952209 type_gop.value_ptr.* = nav_gop.value_ptr.*;
21962210 }
21972211 wip_nav.entry = nav_gop.value_ptr.*;
......@@ -2215,7 +2229,10 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
22152229 break :done;
22162230 }
22172231
2218 if (!nav_gop.found_existing) nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);
2232 if (nav_gop.found_existing)
2233 dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear()
2234 else
2235 nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
22192236 wip_nav.entry = nav_gop.value_ptr.*;
22202237 const diw = wip_nav.debug_info.writer(dwarf.gpa);
22212238 try uleb128(diw, @intFromEnum(AbbrevCode.decl_alias));
......@@ -2264,8 +2281,14 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
22642281 if (type_inst_info.inst != value_inst) break :decl_union;
22652282
22662283 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());
2267 if (type_gop.found_existing) nav_gop.value_ptr.* = type_gop.value_ptr.* else {
2268 if (!nav_gop.found_existing) nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);
2284 if (type_gop.found_existing) {
2285 dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).clear();
2286 nav_gop.value_ptr.* = type_gop.value_ptr.*;
2287 } else {
2288 if (nav_gop.found_existing)
2289 dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear()
2290 else
2291 nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
22692292 type_gop.value_ptr.* = nav_gop.value_ptr.*;
22702293 }
22712294 wip_nav.entry = nav_gop.value_ptr.*;
......@@ -2328,7 +2351,10 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
23282351 break :done;
23292352 }
23302353
2331 if (!nav_gop.found_existing) nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);
2354 if (nav_gop.found_existing)
2355 dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear()
2356 else
2357 nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
23322358 wip_nav.entry = nav_gop.value_ptr.*;
23332359 const diw = wip_nav.debug_info.writer(dwarf.gpa);
23342360 try uleb128(diw, @intFromEnum(AbbrevCode.decl_alias));
......@@ -2377,8 +2403,14 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
23772403 if (type_inst_info.inst != value_inst) break :decl_opaque;
23782404
23792405 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());
2380 if (type_gop.found_existing) nav_gop.value_ptr.* = type_gop.value_ptr.* else {
2381 if (!nav_gop.found_existing) nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);
2406 if (type_gop.found_existing) {
2407 dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(type_gop.value_ptr.*).clear();
2408 nav_gop.value_ptr.* = type_gop.value_ptr.*;
2409 } else {
2410 if (nav_gop.found_existing)
2411 dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear()
2412 else
2413 nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
23822414 type_gop.value_ptr.* = nav_gop.value_ptr.*;
23832415 }
23842416 wip_nav.entry = nav_gop.value_ptr.*;
......@@ -2394,7 +2426,10 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
23942426 break :done;
23952427 }
23962428
2397 if (!nav_gop.found_existing) nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);
2429 if (nav_gop.found_existing)
2430 dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear()
2431 else
2432 nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
23982433 wip_nav.entry = nav_gop.value_ptr.*;
23992434 const diw = wip_nav.debug_info.writer(dwarf.gpa);
24002435 try uleb128(diw, @intFromEnum(AbbrevCode.decl_alias));
......@@ -2412,7 +2447,6 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
24122447 },
24132448 }
24142449 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items);
2415 try dwarf.debug_loclists.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_loclists.items);
24162450 try wip_nav.flush();
24172451}
24182452
src/link/Elf.zig+84-110
......@@ -585,7 +585,7 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
585585 const ptr_size = self.ptrWidthBytes();
586586 const target = self.base.comp.root_mod.resolved_target.result;
587587 const ptr_bit_width = target.ptrBitWidth();
588 const zig_object = self.zigObjectPtr().?;
588 const zo = self.zigObjectPtr().?;
589589
590590 const fillSection = struct {
591591 fn fillSection(elf_file: *Elf, shdr: *elf.Elf64_Shdr, size: u64, phndx: ?u16) !void {
......@@ -766,7 +766,27 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
766766 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_bss_section_index.?, .{});
767767 }
768768
769 if (zig_object.dwarf) |*dwarf| {
769 if (zo.dwarf) |*dwarf| {
770 const addSectionSymbol = struct {
771 fn addSectionSymbol(
772 zig_object: *ZigObject,
773 alloc: Allocator,
774 name: [:0]const u8,
775 alignment: Atom.Alignment,
776 shndx: u32,
777 ) !Symbol.Index {
778 const name_off = try zig_object.addString(alloc, name);
779 const index = try zig_object.newSymbolWithAtom(alloc, name_off);
780 const sym = zig_object.symbol(index);
781 const esym = &zig_object.symtab.items(.elf_sym)[sym.esym_index];
782 esym.st_info |= elf.STT_SECTION;
783 const atom_ptr = zig_object.atom(sym.ref.index).?;
784 atom_ptr.alignment = alignment;
785 atom_ptr.output_section_index = shndx;
786 return index;
787 }
788 }.addSectionSymbol;
789
770790 if (self.debug_str_section_index == null) {
771791 self.debug_str_section_index = try self.addSection(.{
772792 .name = try self.insertShString(".debug_str"),
......@@ -775,7 +795,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
775795 .type = elf.SHT_PROGBITS,
776796 .addralign = 1,
777797 });
778 zig_object.debug_str_section_dirty = true;
798 zo.debug_str_section_dirty = true;
799 zo.debug_str_index = try addSectionSymbol(zo, gpa, ".debug_str", .@"1", self.debug_str_section_index.?);
779800 try self.output_sections.putNoClobber(gpa, self.debug_str_section_index.?, .{});
780801 }
781802
......@@ -785,7 +806,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
785806 .type = elf.SHT_PROGBITS,
786807 .addralign = 1,
787808 });
788 zig_object.debug_info_section_dirty = true;
809 zo.debug_info_section_dirty = true;
810 zo.debug_info_index = try addSectionSymbol(zo, gpa, ".debug_info", .@"1", self.debug_info_section_index.?);
789811 try self.output_sections.putNoClobber(gpa, self.debug_info_section_index.?, .{});
790812 }
791813
......@@ -795,7 +817,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
795817 .type = elf.SHT_PROGBITS,
796818 .addralign = 1,
797819 });
798 zig_object.debug_abbrev_section_dirty = true;
820 zo.debug_abbrev_section_dirty = true;
821 zo.debug_abbrev_index = try addSectionSymbol(zo, gpa, ".debug_abbrev", .@"1", self.debug_abbrev_section_index.?);
799822 try self.output_sections.putNoClobber(gpa, self.debug_abbrev_section_index.?, .{});
800823 }
801824
......@@ -805,7 +828,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
805828 .type = elf.SHT_PROGBITS,
806829 .addralign = 16,
807830 });
808 zig_object.debug_aranges_section_dirty = true;
831 zo.debug_aranges_section_dirty = true;
832 zo.debug_aranges_index = try addSectionSymbol(zo, gpa, ".debug_aranges", .@"16", self.debug_aranges_section_index.?);
809833 try self.output_sections.putNoClobber(gpa, self.debug_aranges_section_index.?, .{});
810834 }
811835
......@@ -815,7 +839,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
815839 .type = elf.SHT_PROGBITS,
816840 .addralign = 1,
817841 });
818 zig_object.debug_line_section_dirty = true;
842 zo.debug_line_section_dirty = true;
843 zo.debug_line_index = try addSectionSymbol(zo, gpa, ".debug_line", .@"1", self.debug_line_section_index.?);
819844 try self.output_sections.putNoClobber(gpa, self.debug_line_section_index.?, .{});
820845 }
821846
......@@ -827,7 +852,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
827852 .type = elf.SHT_PROGBITS,
828853 .addralign = 1,
829854 });
830 zig_object.debug_line_str_section_dirty = true;
855 zo.debug_line_str_section_dirty = true;
856 zo.debug_line_str_index = try addSectionSymbol(zo, gpa, ".debug_line_str", .@"1", self.debug_line_str_section_index.?);
831857 try self.output_sections.putNoClobber(gpa, self.debug_line_str_section_index.?, .{});
832858 }
833859
......@@ -837,7 +863,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
837863 .type = elf.SHT_PROGBITS,
838864 .addralign = 1,
839865 });
840 zig_object.debug_loclists_section_dirty = true;
866 zo.debug_loclists_section_dirty = true;
867 zo.debug_loclists_index = try addSectionSymbol(zo, gpa, ".debug_loclists", .@"1", self.debug_loclists_section_index.?);
841868 try self.output_sections.putNoClobber(gpa, self.debug_loclists_section_index.?, .{});
842869 }
843870
......@@ -847,7 +874,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
847874 .type = elf.SHT_PROGBITS,
848875 .addralign = 1,
849876 });
850 zig_object.debug_rnglists_section_dirty = true;
877 zo.debug_rnglists_section_dirty = true;
878 zo.debug_rnglists_index = try addSectionSymbol(zo, gpa, ".debug_rnglists", .@"1", self.debug_rnglists_section_index.?);
851879 try self.output_sections.putNoClobber(gpa, self.debug_rnglists_section_index.?, .{});
852880 }
853881
......@@ -1254,7 +1282,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
12541282 try self.addCommentString();
12551283 try self.finalizeMergeSections();
12561284 try self.initOutputSections();
1257 try self.initMergeSections();
12581285 if (self.linkerDefinedPtr()) |obj| {
12591286 try obj.initStartStopSymbols(self);
12601287 }
......@@ -1317,8 +1344,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
13171344 try self.base.file.?.pwriteAll(code, file_offset);
13181345 }
13191346
1320 if (zo.dwarf) |*dwarf| try dwarf.resolveRelocs();
1321
13221347 if (has_reloc_errors) return error.FlushFailure;
13231348 }
13241349
......@@ -2652,15 +2677,6 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
26522677 }
26532678}
26542679
2655fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64) void {
2656 const target = self.base.comp.root_mod.resolved_target.result;
2657 const target_endian = target.cpu.arch.endian();
2658 switch (self.ptr_width) {
2659 .p32 => mem.writeInt(u32, buf.addManyAsArrayAssumeCapacity(4), @as(u32, @intCast(addr)), target_endian),
2660 .p64 => mem.writeInt(u64, buf.addManyAsArrayAssumeCapacity(8), addr, target_endian),
2661 }
2662}
2663
26642680pub fn writeShdrTable(self: *Elf) !void {
26652681 const gpa = self.base.comp.gpa;
26662682 const target = self.base.comp.root_mod.resolved_target.result;
......@@ -3031,17 +3047,17 @@ pub fn finalizeMergeSections(self: *Elf) !void {
30313047}
30323048
30333049pub fn updateMergeSectionSizes(self: *Elf) !void {
3050 for (self.merge_sections.items) |*msec| {
3051 msec.updateSize();
3052 }
30343053 for (self.merge_sections.items) |*msec| {
30353054 const shdr = &self.shdrs.items[msec.output_section_index];
3036 for (msec.finalized_subsections.items) |msub_index| {
3037 const msub = msec.mergeSubsection(msub_index);
3038 assert(msub.alive);
3039 const offset = msub.alignment.forward(shdr.sh_size);
3040 const padding = offset - shdr.sh_size;
3041 msub.value = @intCast(offset);
3042 shdr.sh_size += padding + msub.size;
3043 shdr.sh_addralign = @max(shdr.sh_addralign, msub.alignment.toByteUnits() orelse 1);
3044 }
3055 const offset = msec.alignment.forward(shdr.sh_size);
3056 const padding = offset - shdr.sh_size;
3057 msec.value = @intCast(offset);
3058 shdr.sh_size += padding + msec.size;
3059 shdr.sh_addralign = @max(shdr.sh_addralign, msec.alignment.toByteUnits() orelse 1);
3060 shdr.sh_entsize = if (shdr.sh_entsize == 0) msec.entsize else @min(shdr.sh_entsize, msec.entsize);
30453061 }
30463062}
30473063
......@@ -3052,7 +3068,8 @@ pub fn writeMergeSections(self: *Elf) !void {
30523068
30533069 for (self.merge_sections.items) |*msec| {
30543070 const shdr = self.shdrs.items[msec.output_section_index];
3055 const size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
3071 const fileoff = math.cast(usize, msec.value + shdr.sh_offset) orelse return error.Overflow;
3072 const size = math.cast(usize, msec.size) orelse return error.Overflow;
30563073 try buffer.ensureTotalCapacity(size);
30573074 buffer.appendNTimesAssumeCapacity(0, size);
30583075
......@@ -3064,7 +3081,7 @@ pub fn writeMergeSections(self: *Elf) !void {
30643081 @memcpy(buffer.items[off..][0..string.len], string);
30653082 }
30663083
3067 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
3084 try self.base.file.?.pwriteAll(buffer.items, fileoff);
30683085 buffer.clearRetainingCapacity();
30693086 }
30703087}
......@@ -3073,26 +3090,9 @@ fn initOutputSections(self: *Elf) !void {
30733090 for (self.objects.items) |index| {
30743091 try self.file(index).?.object.initOutputSections(self);
30753092 }
3076}
3077
3078pub fn initMergeSections(self: *Elf) !void {
30793093 for (self.merge_sections.items) |*msec| {
30803094 if (msec.finalized_subsections.items.len == 0) continue;
3081 const name = msec.name(self);
3082 const shndx = self.sectionByName(name) orelse try self.addSection(.{
3083 .name = msec.name_offset,
3084 .type = msec.type,
3085 .flags = msec.flags,
3086 });
3087 msec.output_section_index = shndx;
3088
3089 var entsize = msec.mergeSubsection(msec.finalized_subsections.items[0]).entsize;
3090 for (msec.finalized_subsections.items) |msub_index| {
3091 const msub = msec.mergeSubsection(msub_index);
3092 entsize = @min(entsize, msub.entsize);
3093 }
3094 const shdr = &self.shdrs.items[shndx];
3095 shdr.sh_entsize = entsize;
3095 try msec.initOutputSection(self);
30963096 }
30973097}
30983098
......@@ -4184,26 +4184,21 @@ pub fn allocateNonAllocSections(self: *Elf) !void {
41844184 shdr.sh_offset,
41854185 new_offset,
41864186 });
4187 const zig_object = self.zigObjectPtr().?;
4188 const existing_size = blk: {
4189 if (shndx == self.debug_info_section_index.?)
4190 break :blk zig_object.debug_info_section_zig_size;
4191 if (shndx == self.debug_abbrev_section_index.?)
4192 break :blk zig_object.debug_abbrev_section_zig_size;
4193 if (shndx == self.debug_str_section_index.?)
4194 break :blk zig_object.debug_str_section_zig_size;
4195 if (shndx == self.debug_aranges_section_index.?)
4196 break :blk zig_object.debug_aranges_section_zig_size;
4197 if (shndx == self.debug_line_section_index.?)
4198 break :blk zig_object.debug_line_section_zig_size;
4199 if (shndx == self.debug_line_str_section_index.?)
4200 break :blk zig_object.debug_line_str_section_zig_size;
4201 if (shndx == self.debug_loclists_section_index.?)
4202 break :blk zig_object.debug_loclists_section_zig_size;
4203 if (shndx == self.debug_rnglists_section_index.?)
4204 break :blk zig_object.debug_rnglists_section_zig_size;
4205 unreachable;
4206 };
4187 const zo = self.zigObjectPtr().?;
4188 const existing_size = for ([_]Symbol.Index{
4189 zo.debug_info_index.?,
4190 zo.debug_abbrev_index.?,
4191 zo.debug_aranges_index.?,
4192 zo.debug_str_index.?,
4193 zo.debug_line_index.?,
4194 zo.debug_line_str_index.?,
4195 zo.debug_loclists_index.?,
4196 zo.debug_rnglists_index.?,
4197 }) |sym_index| {
4198 const sym = zo.symbol(sym_index);
4199 const atom_ptr = sym.atom(self).?;
4200 if (atom_ptr.output_section_index == shndx) break atom_ptr.size;
4201 } else 0;
42074202 const amt = try self.base.file.?.copyRangeAll(
42084203 shdr.sh_offset,
42094204 self.base.file.?,
......@@ -4299,24 +4294,21 @@ fn writeAtoms(self: *Elf) !void {
42994294
43004295 // TODO really, really handle debug section separately
43014296 const base_offset = if (self.isDebugSection(@intCast(shndx))) blk: {
4302 const zig_object = self.zigObjectPtr().?;
4303 if (shndx == self.debug_info_section_index.?)
4304 break :blk zig_object.debug_info_section_zig_size;
4305 if (shndx == self.debug_abbrev_section_index.?)
4306 break :blk zig_object.debug_abbrev_section_zig_size;
4307 if (shndx == self.debug_str_section_index.?)
4308 break :blk zig_object.debug_str_section_zig_size;
4309 if (shndx == self.debug_aranges_section_index.?)
4310 break :blk zig_object.debug_aranges_section_zig_size;
4311 if (shndx == self.debug_line_section_index.?)
4312 break :blk zig_object.debug_line_section_zig_size;
4313 if (shndx == self.debug_line_str_section_index.?)
4314 break :blk zig_object.debug_line_str_section_zig_size;
4315 if (shndx == self.debug_loclists_section_index.?)
4316 break :blk zig_object.debug_loclists_section_zig_size;
4317 if (shndx == self.debug_rnglists_section_index.?)
4318 break :blk zig_object.debug_rnglists_section_zig_size;
4319 unreachable;
4297 const zo = self.zigObjectPtr().?;
4298 break :blk for ([_]Symbol.Index{
4299 zo.debug_info_index.?,
4300 zo.debug_abbrev_index.?,
4301 zo.debug_aranges_index.?,
4302 zo.debug_str_index.?,
4303 zo.debug_line_index.?,
4304 zo.debug_line_str_index.?,
4305 zo.debug_loclists_index.?,
4306 zo.debug_rnglists_index.?,
4307 }) |sym_index| {
4308 const sym = zo.symbol(sym_index);
4309 const atom_ptr = sym.atom(self).?;
4310 if (atom_ptr.output_section_index == shndx) break atom_ptr.size;
4311 } else 0;
43204312 } else 0;
43214313 const sh_offset = shdr.sh_offset + base_offset;
43224314 const sh_size = math.cast(usize, shdr.sh_size - base_offset) orelse return error.Overflow;
......@@ -4410,7 +4402,6 @@ pub fn updateSymtabSize(self: *Elf) !void {
44104402 if (self.eh_frame_section_index) |_| {
44114403 nlocals += 1;
44124404 }
4413 nlocals += @intCast(self.merge_sections.items.len);
44144405
44154406 if (self.requiresThunks()) for (self.thunks.items) |*th| {
44164407 th.output_symtab_ctx.ilocal = nlocals + 1;
......@@ -4734,30 +4725,12 @@ fn writeSectionSymbols(self: *Elf) void {
47344725 };
47354726 ilocal += 1;
47364727 }
4737
4738 for (self.merge_sections.items) |msec| {
4739 const shdr = self.shdrs.items[msec.output_section_index];
4740 const out_sym = &self.symtab.items[ilocal];
4741 out_sym.* = .{
4742 .st_name = 0,
4743 .st_value = shdr.sh_addr,
4744 .st_info = elf.STT_SECTION,
4745 .st_shndx = @intCast(msec.output_section_index),
4746 .st_size = 0,
4747 .st_other = 0,
4748 };
4749 ilocal += 1;
4750 }
47514728}
47524729
47534730pub fn sectionSymbolOutputSymtabIndex(self: Elf, shndx: u32) u32 {
47544731 if (self.eh_frame_section_index) |index| {
47554732 if (index == shndx) return @intCast(self.output_sections.keys().len + 1);
47564733 }
4757 const base: usize = if (self.eh_frame_section_index == null) 0 else 1;
4758 for (self.merge_sections.items, 0..) |msec, index| {
4759 if (msec.output_section_index == shndx) return @intCast(self.output_sections.keys().len + 1 + index + base);
4760 }
47614734 return @intCast(self.output_sections.getIndex(shndx).? + 1);
47624735}
47634736
......@@ -5520,10 +5493,11 @@ fn formatShdr(
55205493 _ = options;
55215494 _ = unused_fmt_string;
55225495 const shdr = ctx.shdr;
5523 try writer.print("{s} : @{x} ({x}) : align({x}) : size({x}) : flags({})", .{
5496 try writer.print("{s} : @{x} ({x}) : align({x}) : size({x}) : entsize({x}) : flags({})", .{
55245497 ctx.elf_file.getShString(shdr.sh_name), shdr.sh_offset,
55255498 shdr.sh_addr, shdr.sh_addralign,
5526 shdr.sh_size, fmtShdrFlags(shdr.sh_flags),
5499 shdr.sh_size, shdr.sh_entsize,
5500 fmtShdrFlags(shdr.sh_flags),
55275501 });
55285502}
55295503
src/link/Elf/Atom.zig+12-14
......@@ -302,7 +302,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
302302 }
303303
304304 // TODO create relocs free list
305 self.freeRelocs(elf_file);
305 self.freeRelocs(zo);
306306 // TODO figure out how to free input section mappind in ZigModule
307307 // const zig_object = elf_file.zigObjectPtr().?
308308 // assert(zig_object.atoms.swapRemove(self.atom_index));
......@@ -377,21 +377,19 @@ pub fn markFdesDead(self: Atom, elf_file: *Elf) void {
377377 }
378378}
379379
380pub fn addReloc(self: Atom, elf_file: *Elf, reloc: elf.Elf64_Rela) !void {
381 const comp = elf_file.base.comp;
382 const gpa = comp.gpa;
383 const file_ptr = self.file(elf_file).?;
384 assert(file_ptr == .zig_object);
385 const zig_object = file_ptr.zig_object;
386 const rels = &zig_object.relocs.items[self.relocs_section_index];
387 try rels.append(gpa, reloc);
380pub fn addReloc(self: Atom, alloc: Allocator, reloc: elf.Elf64_Rela, zo: *ZigObject) !void {
381 const rels = &zo.relocs.items[self.relocs_section_index];
382 try rels.ensureUnusedCapacity(alloc, 1);
383 self.addRelocAssumeCapacity(reloc, zo);
388384}
389385
390pub fn freeRelocs(self: Atom, elf_file: *Elf) void {
391 const file_ptr = self.file(elf_file).?;
392 assert(file_ptr == .zig_object);
393 const zig_object = file_ptr.zig_object;
394 zig_object.relocs.items[self.relocs_section_index].clearRetainingCapacity();
386pub fn addRelocAssumeCapacity(self: Atom, reloc: elf.Elf64_Rela, zo: *ZigObject) void {
387 const rels = &zo.relocs.items[self.relocs_section_index];
388 rels.appendAssumeCapacity(reloc);
389}
390
391pub fn freeRelocs(self: Atom, zo: *ZigObject) void {
392 zo.relocs.items[self.relocs_section_index].clearRetainingCapacity();
395393}
396394
397395pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) bool {
src/link/Elf/ZigObject.zig+159-47
......@@ -50,16 +50,14 @@ debug_line_str_section_dirty: bool = false,
5050debug_loclists_section_dirty: bool = false,
5151debug_rnglists_section_dirty: bool = false,
5252
53/// Size contribution of Zig's metadata to each debug section.
54/// Used to track start of metadata from input object files.
55debug_info_section_zig_size: u64 = 0,
56debug_abbrev_section_zig_size: u64 = 0,
57debug_str_section_zig_size: u64 = 0,
58debug_aranges_section_zig_size: u64 = 0,
59debug_line_section_zig_size: u64 = 0,
60debug_line_str_section_zig_size: u64 = 0,
61debug_loclists_section_zig_size: u64 = 0,
62debug_rnglists_section_zig_size: u64 = 0,
53debug_info_index: ?Symbol.Index = null,
54debug_abbrev_index: ?Symbol.Index = null,
55debug_aranges_index: ?Symbol.Index = null,
56debug_str_index: ?Symbol.Index = null,
57debug_line_index: ?Symbol.Index = null,
58debug_line_str_index: ?Symbol.Index = null,
59debug_loclists_index: ?Symbol.Index = null,
60debug_rnglists_index: ?Symbol.Index = null,
6361
6462pub const global_symbol_bit: u32 = 0x80000000;
6563pub const symbol_mask: u32 = 0x7fffffff;
......@@ -171,13 +169,154 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi
171169 if (self.dwarf) |*dwarf| {
172170 const pt: Zcu.PerThread = .{ .zcu = elf_file.base.comp.module.?, .tid = tid };
173171 try dwarf.flushModule(pt);
172 try dwarf.resolveRelocs();
173
174 const gpa = elf_file.base.comp.gpa;
175 const cpu_arch = elf_file.getTarget().cpu.arch;
176
177 // TODO invert this logic so that we manage the output section with the atom, not the
178 // other way around
179 for ([_]u32{
180 self.debug_info_index.?,
181 self.debug_abbrev_index.?,
182 self.debug_str_index.?,
183 self.debug_aranges_index.?,
184 self.debug_line_index.?,
185 self.debug_line_str_index.?,
186 self.debug_loclists_index.?,
187 self.debug_rnglists_index.?,
188 }, [_]*Dwarf.Section{
189 &dwarf.debug_info.section,
190 &dwarf.debug_abbrev.section,
191 &dwarf.debug_str.section,
192 &dwarf.debug_aranges.section,
193 &dwarf.debug_line.section,
194 &dwarf.debug_line_str.section,
195 &dwarf.debug_loclists.section,
196 &dwarf.debug_rnglists.section,
197 }) |sym_index, sect| {
198 const sym = self.symbol(sym_index);
199 const atom_ptr = self.atom(sym.ref.index).?;
200 if (!atom_ptr.alive) continue;
201 const shndx = sym.outputShndx(elf_file).?;
202 const shdr = elf_file.shdrs.items[shndx];
203 const esym = &self.symtab.items(.elf_sym)[sym.esym_index];
204 esym.st_size = shdr.sh_size;
205 atom_ptr.size = shdr.sh_size;
206 atom_ptr.alignment = Atom.Alignment.fromNonzeroByteUnits(shdr.sh_addralign);
207
208 log.debug("parsing relocs in {s}", .{sym.name(elf_file)});
209
210 const relocs = &self.relocs.items[atom_ptr.relocsShndx().?];
211 for (sect.units.items) |*unit| {
212 try relocs.ensureUnusedCapacity(gpa, unit.cross_section_relocs.items.len);
213 for (unit.cross_section_relocs.items) |reloc| {
214 const target_sym_index = switch (reloc.target_sec) {
215 .debug_abbrev => self.debug_abbrev_index.?,
216 .debug_info => self.debug_info_index.?,
217 .debug_line => self.debug_line_index.?,
218 .debug_line_str => self.debug_line_str_index.?,
219 .debug_loclists => self.debug_loclists_index.?,
220 .debug_rnglists => self.debug_rnglists_index.?,
221 .debug_str => self.debug_str_index.?,
222 };
223 const target_sec = switch (reloc.target_sec) {
224 inline else => |target_sec| &@field(dwarf, @tagName(target_sec)).section,
225 };
226 const target_unit = target_sec.getUnit(reloc.target_unit);
227 const r_offset = unit.off + reloc.source_off;
228 const r_addend: i64 = @intCast(target_unit.off + reloc.target_off + (if (reloc.target_entry.unwrap()) |target_entry|
229 target_unit.header_len + target_unit.getEntry(target_entry).assertNonEmpty(unit, sect, dwarf).off
230 else
231 0));
232 const r_type = relocation.dwarf.crossSectionRelocType(dwarf.format, cpu_arch);
233 log.debug(" {s} <- r_off={x}, r_add={x}, r_type={}", .{
234 self.symbol(target_sym_index).name(elf_file),
235 r_offset,
236 r_addend,
237 relocation.fmtRelocType(r_type, cpu_arch),
238 });
239 atom_ptr.addRelocAssumeCapacity(.{
240 .r_offset = r_offset,
241 .r_addend = r_addend,
242 .r_info = (@as(u64, @intCast(target_sym_index)) << 32) | r_type,
243 }, self);
244 }
245
246 for (unit.entries.items) |*entry| {
247 const entry_off = unit.off + unit.header_len + entry.off;
248
249 try relocs.ensureUnusedCapacity(gpa, entry.cross_section_relocs.items.len);
250 for (entry.cross_section_relocs.items) |reloc| {
251 const target_sym_index = switch (reloc.target_sec) {
252 .debug_abbrev => self.debug_abbrev_index.?,
253 .debug_info => self.debug_info_index.?,
254 .debug_line => self.debug_line_index.?,
255 .debug_line_str => self.debug_line_str_index.?,
256 .debug_loclists => self.debug_loclists_index.?,
257 .debug_rnglists => self.debug_rnglists_index.?,
258 .debug_str => self.debug_str_index.?,
259 };
260 const target_sec = switch (reloc.target_sec) {
261 inline else => |target_sec| &@field(dwarf, @tagName(target_sec)).section,
262 };
263 const target_unit = target_sec.getUnit(reloc.target_unit);
264 const r_offset = entry_off + reloc.source_off;
265 const r_addend: i64 = @intCast(target_unit.off + reloc.target_off + (if (reloc.target_entry.unwrap()) |target_entry|
266 target_unit.header_len + target_unit.getEntry(target_entry).assertNonEmpty(unit, sect, dwarf).off
267 else
268 0));
269 const r_type = relocation.dwarf.crossSectionRelocType(dwarf.format, cpu_arch);
270 log.debug(" {s} <- r_off={x}, r_add={x}, r_type={}", .{
271 self.symbol(target_sym_index).name(elf_file),
272 r_offset,
273 r_addend,
274 relocation.fmtRelocType(r_type, cpu_arch),
275 });
276 atom_ptr.addRelocAssumeCapacity(.{
277 .r_offset = r_offset,
278 .r_addend = r_addend,
279 .r_info = (@as(u64, @intCast(target_sym_index)) << 32) | r_type,
280 }, self);
281 }
282
283 try relocs.ensureUnusedCapacity(gpa, entry.external_relocs.items.len);
284 for (entry.external_relocs.items) |reloc| {
285 const target_sym = self.symbol(reloc.target_sym);
286 const r_offset = entry_off + reloc.source_off;
287 const r_addend: i64 = @intCast(reloc.target_off);
288 const r_type = relocation.dwarf.externalRelocType(target_sym.*, dwarf.address_size, cpu_arch);
289 log.debug(" {s} <- r_off={x}, r_add={x}, r_type={}", .{
290 target_sym.name(elf_file),
291 r_offset,
292 r_addend,
293 relocation.fmtRelocType(r_type, cpu_arch),
294 });
295 atom_ptr.addRelocAssumeCapacity(.{
296 .r_offset = r_offset,
297 .r_addend = r_addend,
298 .r_info = (@as(u64, @intCast(reloc.target_sym)) << 32) | r_type,
299 }, self);
300 }
301 }
302 }
303
304 if (elf_file.base.isRelocatable() and relocs.items.len > 0) {
305 const gop = try elf_file.output_rela_sections.getOrPut(gpa, shndx);
306 if (!gop.found_existing) {
307 const rela_sect_name = try std.fmt.allocPrintZ(gpa, ".rela{s}", .{elf_file.getShString(shdr.sh_name)});
308 defer gpa.free(rela_sect_name);
309 const rela_sh_name = try elf_file.insertShString(rela_sect_name);
310 const rela_shndx = try elf_file.addRelaShdr(rela_sh_name, shndx);
311 gop.value_ptr.* = .{ .shndx = rela_shndx };
312 }
313 }
314 }
174315
175316 self.debug_abbrev_section_dirty = false;
176317 self.debug_aranges_section_dirty = false;
177318 self.debug_rnglists_section_dirty = false;
178319 self.debug_str_section_dirty = false;
179
180 self.saveDebugSectionsSizes(elf_file);
181320 }
182321
183322 // The point of flushModule() is to commit changes, so in theory, nothing should
......@@ -190,33 +329,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi
190329 assert(!self.debug_str_section_dirty);
191330}
192331
193fn saveDebugSectionsSizes(self: *ZigObject, elf_file: *Elf) void {
194 if (elf_file.debug_info_section_index) |shndx| {
195 self.debug_info_section_zig_size = elf_file.shdrs.items[shndx].sh_size;
196 }
197 if (elf_file.debug_abbrev_section_index) |shndx| {
198 self.debug_abbrev_section_zig_size = elf_file.shdrs.items[shndx].sh_size;
199 }
200 if (elf_file.debug_str_section_index) |shndx| {
201 self.debug_str_section_zig_size = elf_file.shdrs.items[shndx].sh_size;
202 }
203 if (elf_file.debug_aranges_section_index) |shndx| {
204 self.debug_aranges_section_zig_size = elf_file.shdrs.items[shndx].sh_size;
205 }
206 if (elf_file.debug_line_section_index) |shndx| {
207 self.debug_line_section_zig_size = elf_file.shdrs.items[shndx].sh_size;
208 }
209 if (elf_file.debug_line_str_section_index) |shndx| {
210 self.debug_line_str_section_zig_size = elf_file.shdrs.items[shndx].sh_size;
211 }
212 if (elf_file.debug_loclists_section_index) |shndx| {
213 self.debug_loclists_section_zig_size = elf_file.shdrs.items[shndx].sh_size;
214 }
215 if (elf_file.debug_rnglists_section_index) |shndx| {
216 self.debug_rnglists_section_zig_size = elf_file.shdrs.items[shndx].sh_size;
217 }
218}
219
220332fn newSymbol(self: *ZigObject, allocator: Allocator, name_off: u32, st_bind: u4) !Symbol.Index {
221333 try self.symtab.ensureUnusedCapacity(allocator, 1);
222334 try self.symbols.ensureUnusedCapacity(allocator, 1);
......@@ -278,7 +390,7 @@ fn newAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Atom.Index {
278390 return index;
279391}
280392
281fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index {
393pub fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index {
282394 const atom_index = try self.newAtom(allocator, name_off);
283395 const sym_index = try self.newLocalSymbol(allocator, name_off);
284396 const sym = self.symbol(sym_index);
......@@ -642,11 +754,11 @@ pub fn getNavVAddr(
642754 const vaddr = this_sym.address(.{}, elf_file);
643755 const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(elf_file).?;
644756 const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch);
645 try parent_atom.addReloc(elf_file, .{
757 try parent_atom.addReloc(elf_file.base.comp.gpa, .{
646758 .r_offset = reloc_info.offset,
647759 .r_info = (@as(u64, @intCast(this_sym_index)) << 32) | r_type,
648760 .r_addend = reloc_info.addend,
649 });
761 }, self);
650762 return @intCast(vaddr);
651763}
652764
......@@ -661,11 +773,11 @@ pub fn getUavVAddr(
661773 const vaddr = sym.address(.{}, elf_file);
662774 const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(elf_file).?;
663775 const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch);
664 try parent_atom.addReloc(elf_file, .{
776 try parent_atom.addReloc(elf_file.base.comp.gpa, .{
665777 .r_offset = reloc_info.offset,
666778 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
667779 .r_addend = reloc_info.addend,
668 });
780 }, self);
669781 return @intCast(vaddr);
670782}
671783
......@@ -1012,7 +1124,7 @@ pub fn updateFunc(
10121124 log.debug("updateFunc {}({d})", .{ ip.getNav(func.owner_nav).fqn.fmt(ip), func.owner_nav });
10131125
10141126 const sym_index = try self.getOrCreateMetadataForNav(elf_file, func.owner_nav);
1015 self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file);
1127 self.symbol(sym_index).atom(elf_file).?.freeRelocs(self);
10161128
10171129 var code_buffer = std.ArrayList(u8).init(gpa);
10181130 defer code_buffer.deinit();
......@@ -1140,7 +1252,7 @@ pub fn updateNav(
11401252
11411253 if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(pt)) {
11421254 const sym_index = try self.getOrCreateMetadataForNav(elf_file, nav_index);
1143 self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file);
1255 self.symbol(sym_index).atom(elf_file).?.freeRelocs(self);
11441256
11451257 var code_buffer = std.ArrayList(u8).init(zcu.gpa);
11461258 defer code_buffer.deinit();
......@@ -1529,7 +1641,7 @@ pub fn asFile(self: *ZigObject) File {
15291641 return .{ .zig_object = self };
15301642}
15311643
1532fn addString(self: *ZigObject, allocator: Allocator, string: []const u8) !u32 {
1644pub fn addString(self: *ZigObject, allocator: Allocator, string: []const u8) !u32 {
15331645 return self.strtab.insert(allocator, string);
15341646}
15351647
src/link/Elf/merge_section.zig+32-2
......@@ -1,4 +1,8 @@
11pub const MergeSection = struct {
2 value: u64 = 0,
3 size: u64 = 0,
4 alignment: Atom.Alignment = .@"1",
5 entsize: u32 = 0,
26 name_offset: u32 = 0,
37 type: u32 = 0,
48 flags: u64 = 0,
......@@ -26,7 +30,7 @@ pub const MergeSection = struct {
2630
2731 pub fn address(msec: MergeSection, elf_file: *Elf) i64 {
2832 const shdr = elf_file.shdrs.items[msec.output_section_index];
29 return @intCast(shdr.sh_addr);
33 return @intCast(shdr.sh_addr + msec.value);
3034 }
3135
3236 const InsertResult = struct {
......@@ -90,6 +94,29 @@ pub const MergeSection = struct {
9094 std.mem.sort(MergeSubsection.Index, msec.finalized_subsections.items, msec, sortFn);
9195 }
9296
97 pub fn updateSize(msec: *MergeSection) void {
98 for (msec.finalized_subsections.items) |msub_index| {
99 const msub = msec.mergeSubsection(msub_index);
100 assert(msub.alive);
101 const offset = msub.alignment.forward(msec.size);
102 const padding = offset - msec.size;
103 msub.value = @intCast(offset);
104 msec.size += padding + msub.size;
105 msec.alignment = msec.alignment.max(msub.alignment);
106 msec.entsize = if (msec.entsize == 0) msub.entsize else @min(msec.entsize, msub.entsize);
107 }
108 }
109
110 pub fn initOutputSection(msec: *MergeSection, elf_file: *Elf) !void {
111 const shndx = elf_file.sectionByName(msec.name(elf_file)) orelse try elf_file.addSection(.{
112 .name = msec.name_offset,
113 .type = msec.type,
114 .flags = msec.flags,
115 });
116 try elf_file.output_sections.put(elf_file.base.comp.gpa, shndx, .{});
117 msec.output_section_index = shndx;
118 }
119
93120 pub fn addMergeSubsection(msec: *MergeSection, allocator: Allocator) !MergeSubsection.Index {
94121 const index: MergeSubsection.Index = @intCast(msec.subsections.items.len);
95122 const msub = try msec.subsections.addOne(allocator);
......@@ -163,9 +190,12 @@ pub const MergeSection = struct {
163190 _ = unused_fmt_string;
164191 const msec = ctx.msec;
165192 const elf_file = ctx.elf_file;
166 try writer.print("{s} : @{x} : type({x}) : flags({x})\n", .{
193 try writer.print("{s} : @{x} : size({x}) : align({x}) : entsize({x}) : type({x}) : flags({x})\n", .{
167194 msec.name(elf_file),
168195 msec.address(elf_file),
196 msec.size,
197 msec.alignment.toByteUnits() orelse 0,
198 msec.entsize,
169199 msec.type,
170200 msec.flags,
171201 });
src/link/Elf/relocatable.zig+26-20
......@@ -42,7 +42,11 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co
4242 try elf_file.finalizeMergeSections();
4343 zig_object.claimUnresolvedObject(elf_file);
4444
45 try elf_file.initMergeSections();
45 for (elf_file.merge_sections.items) |*msec| {
46 if (msec.finalized_subsections.items.len == 0) continue;
47 try msec.initOutputSection(elf_file);
48 }
49
4650 try elf_file.initSymtab();
4751 try elf_file.initShStrtab();
4852 try elf_file.sortShdrs();
......@@ -198,7 +202,6 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const
198202 claimUnresolved(elf_file);
199203
200204 try initSections(elf_file);
201 try elf_file.initMergeSections();
202205 try elf_file.sortShdrs();
203206 if (elf_file.zigObjectPtr()) |zig_object| {
204207 try zig_object.addAtomsToRelaSections(elf_file);
......@@ -294,6 +297,11 @@ fn initSections(elf_file: *Elf) !void {
294297 try object.initRelaSections(elf_file);
295298 }
296299
300 for (elf_file.merge_sections.items) |*msec| {
301 if (msec.finalized_subsections.items.len == 0) continue;
302 try msec.initOutputSection(elf_file);
303 }
304
297305 const needs_eh_frame = for (elf_file.objects.items) |index| {
298306 if (elf_file.file(index).?.object.cies.items.len > 0) break true;
299307 } else false;
......@@ -423,24 +431,21 @@ fn writeAtoms(elf_file: *Elf) !void {
423431
424432 // TODO really, really handle debug section separately
425433 const base_offset = if (elf_file.isDebugSection(@intCast(shndx))) blk: {
426 const zig_object = elf_file.zigObjectPtr().?;
427 if (shndx == elf_file.debug_info_section_index.?)
428 break :blk zig_object.debug_info_section_zig_size;
429 if (shndx == elf_file.debug_abbrev_section_index.?)
430 break :blk zig_object.debug_abbrev_section_zig_size;
431 if (shndx == elf_file.debug_str_section_index.?)
432 break :blk zig_object.debug_str_section_zig_size;
433 if (shndx == elf_file.debug_aranges_section_index.?)
434 break :blk zig_object.debug_aranges_section_zig_size;
435 if (shndx == elf_file.debug_line_section_index.?)
436 break :blk zig_object.debug_line_section_zig_size;
437 if (shndx == elf_file.debug_line_str_section_index.?)
438 break :blk zig_object.debug_line_str_section_zig_size;
439 if (shndx == elf_file.debug_loclists_section_index.?)
440 break :blk zig_object.debug_loclists_section_zig_size;
441 if (shndx == elf_file.debug_rnglists_section_index.?)
442 break :blk zig_object.debug_rnglists_section_zig_size;
443 unreachable;
434 const zo = elf_file.zigObjectPtr().?;
435 break :blk for ([_]Symbol.Index{
436 zo.debug_info_index.?,
437 zo.debug_abbrev_index.?,
438 zo.debug_aranges_index.?,
439 zo.debug_str_index.?,
440 zo.debug_line_index.?,
441 zo.debug_line_str_index.?,
442 zo.debug_loclists_index.?,
443 zo.debug_rnglists_index.?,
444 }) |sym_index| {
445 const sym = zo.symbol(sym_index);
446 const atom_ptr = sym.atom(elf_file).?;
447 if (atom_ptr.output_section_index == shndx) break atom_ptr.size;
448 } else 0;
444449 } else 0;
445450 const sh_offset = shdr.sh_offset + base_offset;
446451 const sh_size = math.cast(usize, shdr.sh_size - base_offset) orelse return error.Overflow;
......@@ -586,3 +591,4 @@ const Compilation = @import("../../Compilation.zig");
586591const Elf = @import("../Elf.zig");
587592const File = @import("file.zig").File;
588593const Object = @import("Object.zig");
594const Symbol = @import("Symbol.zig");
src/link/Elf/relocation.zig+40
......@@ -91,6 +91,44 @@ pub fn encode(comptime kind: Kind, cpu_arch: std.Target.Cpu.Arch) u32 {
9191 };
9292}
9393
94pub const dwarf = struct {
95 pub fn crossSectionRelocType(format: DW.Format, cpu_arch: std.Target.Cpu.Arch) u32 {
96 return switch (cpu_arch) {
97 .x86_64 => @intFromEnum(switch (format) {
98 .@"32" => elf.R_X86_64.@"32",
99 .@"64" => .@"64",
100 }),
101 .riscv64 => @intFromEnum(switch (format) {
102 .@"32" => elf.R_RISCV.@"32",
103 .@"64" => .@"64",
104 }),
105 else => @panic("TODO unhandled cpu arch"),
106 };
107 }
108
109 pub fn externalRelocType(
110 target: Symbol,
111 address_size: Dwarf.AddressSize,
112 cpu_arch: std.Target.Cpu.Arch,
113 ) u32 {
114 return switch (cpu_arch) {
115 .x86_64 => @intFromEnum(switch (address_size) {
116 .@"32" => if (target.flags.is_tls) elf.R_X86_64.DTPOFF32 else .@"32",
117 .@"64" => if (target.flags.is_tls) elf.R_X86_64.DTPOFF64 else .@"64",
118 else => unreachable,
119 }),
120 .riscv64 => @intFromEnum(switch (address_size) {
121 .@"32" => elf.R_RISCV.@"32",
122 .@"64" => elf.R_RISCV.@"64",
123 else => unreachable,
124 }),
125 else => @panic("TODO unhandled cpu arch"),
126 };
127 }
128
129 const DW = std.dwarf;
130};
131
94132const FormatRelocTypeCtx = struct {
95133 r_type: u32,
96134 cpu_arch: std.Target.Cpu.Arch,
......@@ -124,4 +162,6 @@ const assert = std.debug.assert;
124162const elf = std.elf;
125163const std = @import("std");
126164
165const Dwarf = @import("../Dwarf.zig");
127166const Elf = @import("../Elf.zig");
167const Symbol = @import("Symbol.zig");
test/src/Debugger.zig+38
......@@ -695,6 +695,44 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
695695 \\1 breakpoints deleted; 0 breakpoint locations disabled.
696696 },
697697 );
698 db.addLldbTest(
699 "link_object",
700 target,
701 &.{
702 .{
703 .path = "main.zig",
704 .source =
705 \\extern fn fabsf(f32) f32;
706 \\pub fn main() void {
707 \\ var x: f32 = -1234.5;
708 \\ x = fabsf(x);
709 \\ _ = &x;
710 \\}
711 ,
712 },
713 },
714 \\breakpoint set --file main.zig --source-pattern-regexp 'x = fabsf\(x\);'
715 \\process launch
716 \\frame variable x
717 \\breakpoint delete --force 1
718 \\
719 \\breakpoint set --file main.zig --source-pattern-regexp '_ = &x;'
720 \\process continue
721 \\frame variable x
722 \\breakpoint delete --force 2
723 ,
724 &.{
725 \\(lldb) frame variable x
726 \\(f32) x = -1234.5
727 \\(lldb) breakpoint delete --force 1
728 \\1 breakpoints deleted; 0 breakpoint locations disabled.
729 ,
730 \\(lldb) frame variable x
731 \\(f32) x = 1234.5
732 \\(lldb) breakpoint delete --force 2
733 \\1 breakpoints deleted; 0 breakpoint locations disabled.
734 },
735 );
698736}
699737
700738const File = struct { import: ?[]const u8 = null, path: []const u8, source: []const u8 };