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 {...@@ -56,17 +56,17 @@ pub fn emitMir(emit: *Emit) Error!void {
56 const hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20);56 const hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20);
57 const lo_r_type: u32 = @intFromEnum(std.elf.R_RISCV.LO12_I);57 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, .{
60 .r_offset = start_offset,60 .r_offset = start_offset,
61 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | hi_r_type,61 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | hi_r_type,
62 .r_addend = 0,62 .r_addend = 0,
63 });63 }, zo);
6464
65 try atom_ptr.addReloc(elf_file, .{65 try atom_ptr.addReloc(elf_file.base.comp.gpa, .{
66 .r_offset = start_offset + 4,66 .r_offset = start_offset + 4,
67 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | lo_r_type,67 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | lo_r_type,
68 .r_addend = 0,68 .r_addend = 0,
69 });69 }, zo);
70 },70 },
71 .load_tlv_reloc => |symbol| {71 .load_tlv_reloc => |symbol| {
72 const elf_file = emit.bin_file.cast(.elf).?;72 const elf_file = emit.bin_file.cast(.elf).?;
...@@ -76,23 +76,23 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -76,23 +76,23 @@ pub fn emitMir(emit: *Emit) Error!void {
7676
77 const R_RISCV = std.elf.R_RISCV;77 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, .{
80 .r_offset = start_offset,80 .r_offset = start_offset,
81 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | @intFromEnum(R_RISCV.TPREL_HI20),81 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | @intFromEnum(R_RISCV.TPREL_HI20),
82 .r_addend = 0,82 .r_addend = 0,
83 });83 }, zo);
8484
85 try atom_ptr.addReloc(elf_file, .{85 try atom_ptr.addReloc(elf_file.base.comp.gpa, .{
86 .r_offset = start_offset + 4,86 .r_offset = start_offset + 4,
87 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | @intFromEnum(R_RISCV.TPREL_ADD),87 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | @intFromEnum(R_RISCV.TPREL_ADD),
88 .r_addend = 0,88 .r_addend = 0,
89 });89 }, zo);
9090
91 try atom_ptr.addReloc(elf_file, .{91 try atom_ptr.addReloc(elf_file.base.comp.gpa, .{
92 .r_offset = start_offset + 8,92 .r_offset = start_offset + 8,
93 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | @intFromEnum(R_RISCV.TPREL_LO12_I),93 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | @intFromEnum(R_RISCV.TPREL_LO12_I),
94 .r_addend = 0,94 .r_addend = 0,
95 });95 }, zo);
96 },96 },
97 .call_extern_fn_reloc => |symbol| {97 .call_extern_fn_reloc => |symbol| {
98 const elf_file = emit.bin_file.cast(.elf).?;98 const elf_file = emit.bin_file.cast(.elf).?;
...@@ -101,11 +101,11 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -101,11 +101,11 @@ pub fn emitMir(emit: *Emit) Error!void {
101101
102 const r_type: u32 = @intFromEnum(std.elf.R_RISCV.CALL_PLT);102 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, .{
105 .r_offset = start_offset,105 .r_offset = start_offset,
106 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type,106 .r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | r_type,
107 .r_addend = 0,107 .r_addend = 0,
108 });108 }, zo);
109 },109 },
110 };110 };
111 }111 }
src/arch/x86_64/Emit.zig+10-10
...@@ -48,11 +48,11 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -48,11 +48,11 @@ pub fn emitMir(emit: *Emit) Error!void {
48 const zo = elf_file.zigObjectPtr().?;48 const zo = elf_file.zigObjectPtr().?;
49 const atom_ptr = zo.symbol(emit.atom_index).atom(elf_file).?;49 const atom_ptr = zo.symbol(emit.atom_index).atom(elf_file).?;
50 const r_type = @intFromEnum(std.elf.R_X86_64.PLT32);50 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, .{
52 .r_offset = end_offset - 4,52 .r_offset = end_offset - 4,
53 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,53 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
54 .r_addend = lowered_relocs[0].off - 4,54 .r_addend = lowered_relocs[0].off - 4,
55 });55 }, zo);
56 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {56 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
57 // Add relocation to the decl.57 // Add relocation to the decl.
58 const zo = macho_file.getZigObject().?;58 const zo = macho_file.getZigObject().?;
...@@ -95,22 +95,22 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -95,22 +95,22 @@ pub fn emitMir(emit: *Emit) Error!void {
95 const zo = elf_file.zigObjectPtr().?;95 const zo = elf_file.zigObjectPtr().?;
96 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;96 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
97 const r_type = @intFromEnum(std.elf.R_X86_64.TLSLD);97 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, .{
99 .r_offset = end_offset - 4,99 .r_offset = end_offset - 4,
100 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,100 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
101 .r_addend = lowered_relocs[0].off - 4,101 .r_addend = lowered_relocs[0].off - 4,
102 });102 }, zo);
103 },103 },
104 .linker_dtpoff => |sym_index| {104 .linker_dtpoff => |sym_index| {
105 const elf_file = emit.lower.bin_file.cast(.elf).?;105 const elf_file = emit.lower.bin_file.cast(.elf).?;
106 const zo = elf_file.zigObjectPtr().?;106 const zo = elf_file.zigObjectPtr().?;
107 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;107 const atom = zo.symbol(emit.atom_index).atom(elf_file).?;
108 const r_type = @intFromEnum(std.elf.R_X86_64.DTPOFF32);108 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, .{
110 .r_offset = end_offset - 4,110 .r_offset = end_offset - 4,
111 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,111 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
112 .r_addend = lowered_relocs[0].off,112 .r_addend = lowered_relocs[0].off,
113 });113 }, zo);
114 },114 },
115 .linker_reloc => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| {115 .linker_reloc => |sym_index| if (emit.lower.bin_file.cast(.elf)) |elf_file| {
116 const zo = elf_file.zigObjectPtr().?;116 const zo = elf_file.zigObjectPtr().?;
...@@ -121,21 +121,21 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -121,21 +121,21 @@ pub fn emitMir(emit: *Emit) Error!void {
121 @intFromEnum(std.elf.R_X86_64.GOTPCREL)121 @intFromEnum(std.elf.R_X86_64.GOTPCREL)
122 else122 else
123 @intFromEnum(std.elf.R_X86_64.PC32);123 @intFromEnum(std.elf.R_X86_64.PC32);
124 try atom.addReloc(elf_file, .{124 try atom.addReloc(elf_file.base.comp.gpa, .{
125 .r_offset = end_offset - 4,125 .r_offset = end_offset - 4,
126 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,126 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
127 .r_addend = lowered_relocs[0].off - 4,127 .r_addend = lowered_relocs[0].off - 4,
128 });128 }, zo);
129 } else {129 } else {
130 const r_type: u32 = if (sym.flags.is_tls)130 const r_type: u32 = if (sym.flags.is_tls)
131 @intFromEnum(std.elf.R_X86_64.TPOFF32)131 @intFromEnum(std.elf.R_X86_64.TPOFF32)
132 else132 else
133 @intFromEnum(std.elf.R_X86_64.@"32");133 @intFromEnum(std.elf.R_X86_64.@"32");
134 try atom.addReloc(elf_file, .{134 try atom.addReloc(elf_file.base.comp.gpa, .{
135 .r_offset = end_offset - 4,135 .r_offset = end_offset - 4,
136 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,136 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
137 .r_addend = lowered_relocs[0].off,137 .r_addend = lowered_relocs[0].off,
138 });138 }, zo);
139 }139 }
140 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {140 } else if (emit.lower.bin_file.cast(.macho)) |macho_file| {
141 const zo = macho_file.getZigObject().?;141 const zo = macho_file.getZigObject().?;
src/link/Dwarf.zig+57-23
...@@ -201,7 +201,7 @@ const StringSection = struct {...@@ -201,7 +201,7 @@ const StringSection = struct {
201};201};
202202
203/// A linker section containing a sequence of `Unit`s.203/// A linker section containing a sequence of `Unit`s.
204const Section = struct {204pub const Section = struct {
205 dirty: bool,205 dirty: bool,
206 pad_to_ideal: bool,206 pad_to_ideal: bool,
207 alignment: InternPool.Alignment,207 alignment: InternPool.Alignment,
...@@ -287,7 +287,7 @@ const Section = struct {...@@ -287,7 +287,7 @@ const Section = struct {
287 return sec.getUnit(unit).addEntry(sec, dwarf);287 return sec.getUnit(unit).addEntry(sec, dwarf);
288 }288 }
289289
290 fn getUnit(sec: *Section, unit: Unit.Index) *Unit {290 pub fn getUnit(sec: *Section, unit: Unit.Index) *Unit {
291 return &sec.units.items[@intFromEnum(unit)];291 return &sec.units.items[@intFromEnum(unit)];
292 }292 }
293293
...@@ -368,7 +368,7 @@ const Unit = struct {...@@ -368,7 +368,7 @@ const Unit = struct {
368 none = std.math.maxInt(u32),368 none = std.math.maxInt(u32),
369 _,369 _,
370370
371 fn unwrap(uio: Optional) ?Index {371 pub fn unwrap(uio: Optional) ?Index {
372 return if (uio != .none) @enumFromInt(@intFromEnum(uio)) else null;372 return if (uio != .none) @enumFromInt(@intFromEnum(uio)) else null;
373 }373 }
374 };374 };
...@@ -415,7 +415,7 @@ const Unit = struct {...@@ -415,7 +415,7 @@ const Unit = struct {
415 return entry;415 return entry;
416 }416 }
417417
418 fn getEntry(unit: *Unit, entry: Entry.Index) *Entry {418 pub fn getEntry(unit: *Unit, entry: Entry.Index) *Entry {
419 return &unit.entries.items[@intFromEnum(entry)];419 return &unit.entries.items[@intFromEnum(entry)];
420 }420 }
421421
...@@ -614,7 +614,7 @@ const Entry = struct {...@@ -614,7 +614,7 @@ const Entry = struct {
614 none = std.math.maxInt(u32),614 none = std.math.maxInt(u32),
615 _,615 _,
616616
617 fn unwrap(eio: Optional) ?Index {617 pub fn unwrap(eio: Optional) ?Index {
618 return if (eio != .none) @enumFromInt(@intFromEnum(eio)) else null;618 return if (eio != .none) @enumFromInt(@intFromEnum(eio)) else null;
619 }619 }
620 };620 };
...@@ -736,7 +736,7 @@ const Entry = struct {...@@ -736,7 +736,7 @@ const Entry = struct {
736 }736 }
737 }737 }
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 {
740 if (entry.len > 0) return entry;740 if (entry.len > 0) return entry;
741 if (std.debug.runtime_safety) {741 if (std.debug.runtime_safety) {
742 log.err("missing {} from {s}", .{742 log.err("missing {} from {s}", .{
...@@ -1958,11 +1958,10 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -1958,11 +1958,10 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
1958 const loc = tree.tokenLocation(0, tree.nodes.items(.main_token)[decl_inst.data.declaration.src_node]);1958 const loc = tree.tokenLocation(0, tree.nodes.items(.main_token)[decl_inst.data.declaration.src_node]);
1959 assert(loc.line == zcu.navSrcLine(nav_index));1959 assert(loc.line == zcu.navSrcLine(nav_index));
19601960
1961 const unit = try dwarf.getUnit(file.mod);
1962 var wip_nav: WipNav = .{1961 var wip_nav: WipNav = .{
1963 .dwarf = dwarf,1962 .dwarf = dwarf,
1964 .pt = pt,1963 .pt = pt,
1965 .unit = unit,1964 .unit = try dwarf.getUnit(file.mod),
1966 .entry = undefined,1965 .entry = undefined,
1967 .any_children = false,1966 .any_children = false,
1968 .func = .none,1967 .func = .none,
...@@ -1981,7 +1980,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -1981,7 +1980,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
1981 switch (ip.indexToKey(nav_val.toIntern())) {1980 switch (ip.indexToKey(nav_val.toIntern())) {
1982 .func => |func| {1981 .func => |func| {
1983 if (nav_gop.found_existing) {1982 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);
1985 const entry_ptr = unit_ptr.getEntry(nav_gop.value_ptr.*);1984 const entry_ptr = unit_ptr.getEntry(nav_gop.value_ptr.*);
1986 if (entry_ptr.len >= AbbrevCode.decl_bytes) {1985 if (entry_ptr.len >= AbbrevCode.decl_bytes) {
1987 var abbrev_code_buf: [AbbrevCode.decl_bytes]u8 = undefined;1986 var abbrev_code_buf: [AbbrevCode.decl_bytes]u8 = undefined;
...@@ -2000,7 +1999,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -2000,7 +1999,7 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
2000 }1999 }
2001 }2000 }
2002 entry_ptr.clear();2001 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);
2004 wip_nav.entry = nav_gop.value_ptr.*;2003 wip_nav.entry = nav_gop.value_ptr.*;
20052004
2006 const parent_type, const accessibility: u8 = if (nav.analysis_owner.unwrap()) |cau| parent: {2005 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...@@ -2074,8 +2073,14 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
2074 if (type_inst_info.inst != value_inst) break :decl_struct;2073 if (type_inst_info.inst != value_inst) break :decl_struct;
20752074
2076 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());2075 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 {2076 if (type_gop.found_existing) {
2078 if (!nav_gop.found_existing) nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);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);
2079 type_gop.value_ptr.* = nav_gop.value_ptr.*;2084 type_gop.value_ptr.* = nav_gop.value_ptr.*;
2080 }2085 }
2081 wip_nav.entry = nav_gop.value_ptr.*;2086 wip_nav.entry = nav_gop.value_ptr.*;
...@@ -2139,7 +2144,10 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -2139,7 +2144,10 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
2139 break :done;2144 break :done;
2140 }2145 }
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);
2143 wip_nav.entry = nav_gop.value_ptr.*;2151 wip_nav.entry = nav_gop.value_ptr.*;
2144 const diw = wip_nav.debug_info.writer(dwarf.gpa);2152 const diw = wip_nav.debug_info.writer(dwarf.gpa);
2145 try uleb128(diw, @intFromEnum(AbbrevCode.decl_alias));2153 try uleb128(diw, @intFromEnum(AbbrevCode.decl_alias));
...@@ -2190,8 +2198,14 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -2190,8 +2198,14 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
2190 if (type_inst_info.inst != value_inst) break :decl_enum;2198 if (type_inst_info.inst != value_inst) break :decl_enum;
21912199
2192 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());2200 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 {2201 if (type_gop.found_existing) {
2194 if (!nav_gop.found_existing) nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);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);
2195 type_gop.value_ptr.* = nav_gop.value_ptr.*;2209 type_gop.value_ptr.* = nav_gop.value_ptr.*;
2196 }2210 }
2197 wip_nav.entry = nav_gop.value_ptr.*;2211 wip_nav.entry = nav_gop.value_ptr.*;
...@@ -2215,7 +2229,10 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -2215,7 +2229,10 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
2215 break :done;2229 break :done;
2216 }2230 }
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);
2219 wip_nav.entry = nav_gop.value_ptr.*;2236 wip_nav.entry = nav_gop.value_ptr.*;
2220 const diw = wip_nav.debug_info.writer(dwarf.gpa);2237 const diw = wip_nav.debug_info.writer(dwarf.gpa);
2221 try uleb128(diw, @intFromEnum(AbbrevCode.decl_alias));2238 try uleb128(diw, @intFromEnum(AbbrevCode.decl_alias));
...@@ -2264,8 +2281,14 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -2264,8 +2281,14 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
2264 if (type_inst_info.inst != value_inst) break :decl_union;2281 if (type_inst_info.inst != value_inst) break :decl_union;
22652282
2266 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());2283 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 {2284 if (type_gop.found_existing) {
2268 if (!nav_gop.found_existing) nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);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);
2269 type_gop.value_ptr.* = nav_gop.value_ptr.*;2292 type_gop.value_ptr.* = nav_gop.value_ptr.*;
2270 }2293 }
2271 wip_nav.entry = nav_gop.value_ptr.*;2294 wip_nav.entry = nav_gop.value_ptr.*;
...@@ -2328,7 +2351,10 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -2328,7 +2351,10 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
2328 break :done;2351 break :done;
2329 }2352 }
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);
2332 wip_nav.entry = nav_gop.value_ptr.*;2358 wip_nav.entry = nav_gop.value_ptr.*;
2333 const diw = wip_nav.debug_info.writer(dwarf.gpa);2359 const diw = wip_nav.debug_info.writer(dwarf.gpa);
2334 try uleb128(diw, @intFromEnum(AbbrevCode.decl_alias));2360 try uleb128(diw, @intFromEnum(AbbrevCode.decl_alias));
...@@ -2377,8 +2403,14 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -2377,8 +2403,14 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
2377 if (type_inst_info.inst != value_inst) break :decl_opaque;2403 if (type_inst_info.inst != value_inst) break :decl_opaque;
23782404
2379 const type_gop = try dwarf.types.getOrPut(dwarf.gpa, nav_val.toIntern());2405 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 {2406 if (type_gop.found_existing) {
2381 if (!nav_gop.found_existing) nav_gop.value_ptr.* = try dwarf.addCommonEntry(unit);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);
2382 type_gop.value_ptr.* = nav_gop.value_ptr.*;2414 type_gop.value_ptr.* = nav_gop.value_ptr.*;
2383 }2415 }
2384 wip_nav.entry = nav_gop.value_ptr.*;2416 wip_nav.entry = nav_gop.value_ptr.*;
...@@ -2394,7 +2426,10 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -2394,7 +2426,10 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
2394 break :done;2426 break :done;
2395 }2427 }
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);
2398 wip_nav.entry = nav_gop.value_ptr.*;2433 wip_nav.entry = nav_gop.value_ptr.*;
2399 const diw = wip_nav.debug_info.writer(dwarf.gpa);2434 const diw = wip_nav.debug_info.writer(dwarf.gpa);
2400 try uleb128(diw, @intFromEnum(AbbrevCode.decl_alias));2435 try uleb128(diw, @intFromEnum(AbbrevCode.decl_alias));
...@@ -2412,7 +2447,6 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool...@@ -2412,7 +2447,6 @@ pub fn updateComptimeNav(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPool
2412 },2447 },
2413 }2448 }
2414 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items);2449 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);
2416 try wip_nav.flush();2450 try wip_nav.flush();
2417}2451}
24182452
src/link/Elf.zig+84-110
...@@ -585,7 +585,7 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {...@@ -585,7 +585,7 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
585 const ptr_size = self.ptrWidthBytes();585 const ptr_size = self.ptrWidthBytes();
586 const target = self.base.comp.root_mod.resolved_target.result;586 const target = self.base.comp.root_mod.resolved_target.result;
587 const ptr_bit_width = target.ptrBitWidth();587 const ptr_bit_width = target.ptrBitWidth();
588 const zig_object = self.zigObjectPtr().?;588 const zo = self.zigObjectPtr().?;
589589
590 const fillSection = struct {590 const fillSection = struct {
591 fn fillSection(elf_file: *Elf, shdr: *elf.Elf64_Shdr, size: u64, phndx: ?u16) !void {591 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 {...@@ -766,7 +766,27 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
766 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_bss_section_index.?, .{});766 try self.last_atom_and_free_list_table.putNoClobber(gpa, self.zig_bss_section_index.?, .{});
767 }767 }
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
770 if (self.debug_str_section_index == null) {790 if (self.debug_str_section_index == null) {
771 self.debug_str_section_index = try self.addSection(.{791 self.debug_str_section_index = try self.addSection(.{
772 .name = try self.insertShString(".debug_str"),792 .name = try self.insertShString(".debug_str"),
...@@ -775,7 +795,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {...@@ -775,7 +795,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
775 .type = elf.SHT_PROGBITS,795 .type = elf.SHT_PROGBITS,
776 .addralign = 1,796 .addralign = 1,
777 });797 });
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.?);
779 try self.output_sections.putNoClobber(gpa, self.debug_str_section_index.?, .{});800 try self.output_sections.putNoClobber(gpa, self.debug_str_section_index.?, .{});
780 }801 }
781802
...@@ -785,7 +806,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {...@@ -785,7 +806,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
785 .type = elf.SHT_PROGBITS,806 .type = elf.SHT_PROGBITS,
786 .addralign = 1,807 .addralign = 1,
787 });808 });
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.?);
789 try self.output_sections.putNoClobber(gpa, self.debug_info_section_index.?, .{});811 try self.output_sections.putNoClobber(gpa, self.debug_info_section_index.?, .{});
790 }812 }
791813
...@@ -795,7 +817,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {...@@ -795,7 +817,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
795 .type = elf.SHT_PROGBITS,817 .type = elf.SHT_PROGBITS,
796 .addralign = 1,818 .addralign = 1,
797 });819 });
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.?);
799 try self.output_sections.putNoClobber(gpa, self.debug_abbrev_section_index.?, .{});822 try self.output_sections.putNoClobber(gpa, self.debug_abbrev_section_index.?, .{});
800 }823 }
801824
...@@ -805,7 +828,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {...@@ -805,7 +828,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
805 .type = elf.SHT_PROGBITS,828 .type = elf.SHT_PROGBITS,
806 .addralign = 16,829 .addralign = 16,
807 });830 });
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.?);
809 try self.output_sections.putNoClobber(gpa, self.debug_aranges_section_index.?, .{});833 try self.output_sections.putNoClobber(gpa, self.debug_aranges_section_index.?, .{});
810 }834 }
811835
...@@ -815,7 +839,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {...@@ -815,7 +839,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
815 .type = elf.SHT_PROGBITS,839 .type = elf.SHT_PROGBITS,
816 .addralign = 1,840 .addralign = 1,
817 });841 });
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.?);
819 try self.output_sections.putNoClobber(gpa, self.debug_line_section_index.?, .{});844 try self.output_sections.putNoClobber(gpa, self.debug_line_section_index.?, .{});
820 }845 }
821846
...@@ -827,7 +852,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {...@@ -827,7 +852,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
827 .type = elf.SHT_PROGBITS,852 .type = elf.SHT_PROGBITS,
828 .addralign = 1,853 .addralign = 1,
829 });854 });
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.?);
831 try self.output_sections.putNoClobber(gpa, self.debug_line_str_section_index.?, .{});857 try self.output_sections.putNoClobber(gpa, self.debug_line_str_section_index.?, .{});
832 }858 }
833859
...@@ -837,7 +863,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {...@@ -837,7 +863,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
837 .type = elf.SHT_PROGBITS,863 .type = elf.SHT_PROGBITS,
838 .addralign = 1,864 .addralign = 1,
839 });865 });
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.?);
841 try self.output_sections.putNoClobber(gpa, self.debug_loclists_section_index.?, .{});868 try self.output_sections.putNoClobber(gpa, self.debug_loclists_section_index.?, .{});
842 }869 }
843870
...@@ -847,7 +874,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {...@@ -847,7 +874,8 @@ pub fn initMetadata(self: *Elf, options: InitMetadataOptions) !void {
847 .type = elf.SHT_PROGBITS,874 .type = elf.SHT_PROGBITS,
848 .addralign = 1,875 .addralign = 1,
849 });876 });
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.?);
851 try self.output_sections.putNoClobber(gpa, self.debug_rnglists_section_index.?, .{});879 try self.output_sections.putNoClobber(gpa, self.debug_rnglists_section_index.?, .{});
852 }880 }
853881
...@@ -1254,7 +1282,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod...@@ -1254,7 +1282,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
1254 try self.addCommentString();1282 try self.addCommentString();
1255 try self.finalizeMergeSections();1283 try self.finalizeMergeSections();
1256 try self.initOutputSections();1284 try self.initOutputSections();
1257 try self.initMergeSections();
1258 if (self.linkerDefinedPtr()) |obj| {1285 if (self.linkerDefinedPtr()) |obj| {
1259 try obj.initStartStopSymbols(self);1286 try obj.initStartStopSymbols(self);
1260 }1287 }
...@@ -1317,8 +1344,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod...@@ -1317,8 +1344,6 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
1317 try self.base.file.?.pwriteAll(code, file_offset);1344 try self.base.file.?.pwriteAll(code, file_offset);
1318 }1345 }
13191346
1320 if (zo.dwarf) |*dwarf| try dwarf.resolveRelocs();
1321
1322 if (has_reloc_errors) return error.FlushFailure;1347 if (has_reloc_errors) return error.FlushFailure;
1323 }1348 }
13241349
...@@ -2652,15 +2677,6 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s...@@ -2652,15 +2677,6 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
2652 }2677 }
2653}2678}
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
2664pub fn writeShdrTable(self: *Elf) !void {2680pub fn writeShdrTable(self: *Elf) !void {
2665 const gpa = self.base.comp.gpa;2681 const gpa = self.base.comp.gpa;
2666 const target = self.base.comp.root_mod.resolved_target.result;2682 const target = self.base.comp.root_mod.resolved_target.result;
...@@ -3031,17 +3047,17 @@ pub fn finalizeMergeSections(self: *Elf) !void {...@@ -3031,17 +3047,17 @@ pub fn finalizeMergeSections(self: *Elf) !void {
3031}3047}
30323048
3033pub fn updateMergeSectionSizes(self: *Elf) !void {3049pub fn updateMergeSectionSizes(self: *Elf) !void {
3050 for (self.merge_sections.items) |*msec| {
3051 msec.updateSize();
3052 }
3034 for (self.merge_sections.items) |*msec| {3053 for (self.merge_sections.items) |*msec| {
3035 const shdr = &self.shdrs.items[msec.output_section_index];3054 const shdr = &self.shdrs.items[msec.output_section_index];
3036 for (msec.finalized_subsections.items) |msub_index| {3055 const offset = msec.alignment.forward(shdr.sh_size);
3037 const msub = msec.mergeSubsection(msub_index);3056 const padding = offset - shdr.sh_size;
3038 assert(msub.alive);3057 msec.value = @intCast(offset);
3039 const offset = msub.alignment.forward(shdr.sh_size);3058 shdr.sh_size += padding + msec.size;
3040 const padding = offset - shdr.sh_size;3059 shdr.sh_addralign = @max(shdr.sh_addralign, msec.alignment.toByteUnits() orelse 1);
3041 msub.value = @intCast(offset);3060 shdr.sh_entsize = if (shdr.sh_entsize == 0) msec.entsize else @min(shdr.sh_entsize, msec.entsize);
3042 shdr.sh_size += padding + msub.size;
3043 shdr.sh_addralign = @max(shdr.sh_addralign, msub.alignment.toByteUnits() orelse 1);
3044 }
3045 }3061 }
3046}3062}
30473063
...@@ -3052,7 +3068,8 @@ pub fn writeMergeSections(self: *Elf) !void {...@@ -3052,7 +3068,8 @@ pub fn writeMergeSections(self: *Elf) !void {
30523068
3053 for (self.merge_sections.items) |*msec| {3069 for (self.merge_sections.items) |*msec| {
3054 const shdr = self.shdrs.items[msec.output_section_index];3070 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;
3056 try buffer.ensureTotalCapacity(size);3073 try buffer.ensureTotalCapacity(size);
3057 buffer.appendNTimesAssumeCapacity(0, size);3074 buffer.appendNTimesAssumeCapacity(0, size);
30583075
...@@ -3064,7 +3081,7 @@ pub fn writeMergeSections(self: *Elf) !void {...@@ -3064,7 +3081,7 @@ pub fn writeMergeSections(self: *Elf) !void {
3064 @memcpy(buffer.items[off..][0..string.len], string);3081 @memcpy(buffer.items[off..][0..string.len], string);
3065 }3082 }
30663083
3067 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);3084 try self.base.file.?.pwriteAll(buffer.items, fileoff);
3068 buffer.clearRetainingCapacity();3085 buffer.clearRetainingCapacity();
3069 }3086 }
3070}3087}
...@@ -3073,26 +3090,9 @@ fn initOutputSections(self: *Elf) !void {...@@ -3073,26 +3090,9 @@ fn initOutputSections(self: *Elf) !void {
3073 for (self.objects.items) |index| {3090 for (self.objects.items) |index| {
3074 try self.file(index).?.object.initOutputSections(self);3091 try self.file(index).?.object.initOutputSections(self);
3075 }3092 }
3076}
3077
3078pub fn initMergeSections(self: *Elf) !void {
3079 for (self.merge_sections.items) |*msec| {3093 for (self.merge_sections.items) |*msec| {
3080 if (msec.finalized_subsections.items.len == 0) continue;3094 if (msec.finalized_subsections.items.len == 0) continue;
3081 const name = msec.name(self);3095 try msec.initOutputSection(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;
3096 }3096 }
3097}3097}
30983098
...@@ -4184,26 +4184,21 @@ pub fn allocateNonAllocSections(self: *Elf) !void {...@@ -4184,26 +4184,21 @@ pub fn allocateNonAllocSections(self: *Elf) !void {
4184 shdr.sh_offset,4184 shdr.sh_offset,
4185 new_offset,4185 new_offset,
4186 });4186 });
4187 const zig_object = self.zigObjectPtr().?;4187 const zo = self.zigObjectPtr().?;
4188 const existing_size = blk: {4188 const existing_size = for ([_]Symbol.Index{
4189 if (shndx == self.debug_info_section_index.?)4189 zo.debug_info_index.?,
4190 break :blk zig_object.debug_info_section_zig_size;4190 zo.debug_abbrev_index.?,
4191 if (shndx == self.debug_abbrev_section_index.?)4191 zo.debug_aranges_index.?,
4192 break :blk zig_object.debug_abbrev_section_zig_size;4192 zo.debug_str_index.?,
4193 if (shndx == self.debug_str_section_index.?)4193 zo.debug_line_index.?,
4194 break :blk zig_object.debug_str_section_zig_size;4194 zo.debug_line_str_index.?,
4195 if (shndx == self.debug_aranges_section_index.?)4195 zo.debug_loclists_index.?,
4196 break :blk zig_object.debug_aranges_section_zig_size;4196 zo.debug_rnglists_index.?,
4197 if (shndx == self.debug_line_section_index.?)4197 }) |sym_index| {
4198 break :blk zig_object.debug_line_section_zig_size;4198 const sym = zo.symbol(sym_index);
4199 if (shndx == self.debug_line_str_section_index.?)4199 const atom_ptr = sym.atom(self).?;
4200 break :blk zig_object.debug_line_str_section_zig_size;4200 if (atom_ptr.output_section_index == shndx) break atom_ptr.size;
4201 if (shndx == self.debug_loclists_section_index.?)4201 } else 0;
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 };
4207 const amt = try self.base.file.?.copyRangeAll(4202 const amt = try self.base.file.?.copyRangeAll(
4208 shdr.sh_offset,4203 shdr.sh_offset,
4209 self.base.file.?,4204 self.base.file.?,
...@@ -4299,24 +4294,21 @@ fn writeAtoms(self: *Elf) !void {...@@ -4299,24 +4294,21 @@ fn writeAtoms(self: *Elf) !void {
42994294
4300 // TODO really, really handle debug section separately4295 // TODO really, really handle debug section separately
4301 const base_offset = if (self.isDebugSection(@intCast(shndx))) blk: {4296 const base_offset = if (self.isDebugSection(@intCast(shndx))) blk: {
4302 const zig_object = self.zigObjectPtr().?;4297 const zo = self.zigObjectPtr().?;
4303 if (shndx == self.debug_info_section_index.?)4298 break :blk for ([_]Symbol.Index{
4304 break :blk zig_object.debug_info_section_zig_size;4299 zo.debug_info_index.?,
4305 if (shndx == self.debug_abbrev_section_index.?)4300 zo.debug_abbrev_index.?,
4306 break :blk zig_object.debug_abbrev_section_zig_size;4301 zo.debug_aranges_index.?,
4307 if (shndx == self.debug_str_section_index.?)4302 zo.debug_str_index.?,
4308 break :blk zig_object.debug_str_section_zig_size;4303 zo.debug_line_index.?,
4309 if (shndx == self.debug_aranges_section_index.?)4304 zo.debug_line_str_index.?,
4310 break :blk zig_object.debug_aranges_section_zig_size;4305 zo.debug_loclists_index.?,
4311 if (shndx == self.debug_line_section_index.?)4306 zo.debug_rnglists_index.?,
4312 break :blk zig_object.debug_line_section_zig_size;4307 }) |sym_index| {
4313 if (shndx == self.debug_line_str_section_index.?)4308 const sym = zo.symbol(sym_index);
4314 break :blk zig_object.debug_line_str_section_zig_size;4309 const atom_ptr = sym.atom(self).?;
4315 if (shndx == self.debug_loclists_section_index.?)4310 if (atom_ptr.output_section_index == shndx) break atom_ptr.size;
4316 break :blk zig_object.debug_loclists_section_zig_size;4311 } else 0;
4317 if (shndx == self.debug_rnglists_section_index.?)
4318 break :blk zig_object.debug_rnglists_section_zig_size;
4319 unreachable;
4320 } else 0;4312 } else 0;
4321 const sh_offset = shdr.sh_offset + base_offset;4313 const sh_offset = shdr.sh_offset + base_offset;
4322 const sh_size = math.cast(usize, shdr.sh_size - base_offset) orelse return error.Overflow;4314 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 {...@@ -4410,7 +4402,6 @@ pub fn updateSymtabSize(self: *Elf) !void {
4410 if (self.eh_frame_section_index) |_| {4402 if (self.eh_frame_section_index) |_| {
4411 nlocals += 1;4403 nlocals += 1;
4412 }4404 }
4413 nlocals += @intCast(self.merge_sections.items.len);
44144405
4415 if (self.requiresThunks()) for (self.thunks.items) |*th| {4406 if (self.requiresThunks()) for (self.thunks.items) |*th| {
4416 th.output_symtab_ctx.ilocal = nlocals + 1;4407 th.output_symtab_ctx.ilocal = nlocals + 1;
...@@ -4734,30 +4725,12 @@ fn writeSectionSymbols(self: *Elf) void {...@@ -4734,30 +4725,12 @@ fn writeSectionSymbols(self: *Elf) void {
4734 };4725 };
4735 ilocal += 1;4726 ilocal += 1;
4736 }4727 }
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 }
4751}4728}
47524729
4753pub fn sectionSymbolOutputSymtabIndex(self: Elf, shndx: u32) u32 {4730pub fn sectionSymbolOutputSymtabIndex(self: Elf, shndx: u32) u32 {
4754 if (self.eh_frame_section_index) |index| {4731 if (self.eh_frame_section_index) |index| {
4755 if (index == shndx) return @intCast(self.output_sections.keys().len + 1);4732 if (index == shndx) return @intCast(self.output_sections.keys().len + 1);
4756 }4733 }
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 }
4761 return @intCast(self.output_sections.getIndex(shndx).? + 1);4734 return @intCast(self.output_sections.getIndex(shndx).? + 1);
4762}4735}
47634736
...@@ -5520,10 +5493,11 @@ fn formatShdr(...@@ -5520,10 +5493,11 @@ fn formatShdr(
5520 _ = options;5493 _ = options;
5521 _ = unused_fmt_string;5494 _ = unused_fmt_string;
5522 const shdr = ctx.shdr;5495 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({})", .{
5524 ctx.elf_file.getShString(shdr.sh_name), shdr.sh_offset,5497 ctx.elf_file.getShString(shdr.sh_name), shdr.sh_offset,
5525 shdr.sh_addr, shdr.sh_addralign,5498 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),
5527 });5501 });
5528}5502}
55295503
src/link/Elf/Atom.zig+12-14
...@@ -302,7 +302,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void {...@@ -302,7 +302,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
302 }302 }
303303
304 // TODO create relocs free list304 // TODO create relocs free list
305 self.freeRelocs(elf_file);305 self.freeRelocs(zo);
306 // TODO figure out how to free input section mappind in ZigModule306 // TODO figure out how to free input section mappind in ZigModule
307 // const zig_object = elf_file.zigObjectPtr().?307 // const zig_object = elf_file.zigObjectPtr().?
308 // assert(zig_object.atoms.swapRemove(self.atom_index));308 // assert(zig_object.atoms.swapRemove(self.atom_index));
...@@ -377,21 +377,19 @@ pub fn markFdesDead(self: Atom, elf_file: *Elf) void {...@@ -377,21 +377,19 @@ pub fn markFdesDead(self: Atom, elf_file: *Elf) void {
377 }377 }
378}378}
379379
380pub fn addReloc(self: Atom, elf_file: *Elf, reloc: elf.Elf64_Rela) !void {380pub fn addReloc(self: Atom, alloc: Allocator, reloc: elf.Elf64_Rela, zo: *ZigObject) !void {
381 const comp = elf_file.base.comp;381 const rels = &zo.relocs.items[self.relocs_section_index];
382 const gpa = comp.gpa;382 try rels.ensureUnusedCapacity(alloc, 1);
383 const file_ptr = self.file(elf_file).?;383 self.addRelocAssumeCapacity(reloc, zo);
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);
388}384}
389385
390pub fn freeRelocs(self: Atom, elf_file: *Elf) void {386pub fn addRelocAssumeCapacity(self: Atom, reloc: elf.Elf64_Rela, zo: *ZigObject) void {
391 const file_ptr = self.file(elf_file).?;387 const rels = &zo.relocs.items[self.relocs_section_index];
392 assert(file_ptr == .zig_object);388 rels.appendAssumeCapacity(reloc);
393 const zig_object = file_ptr.zig_object;389}
394 zig_object.relocs.items[self.relocs_section_index].clearRetainingCapacity();390
391pub fn freeRelocs(self: Atom, zo: *ZigObject) void {
392 zo.relocs.items[self.relocs_section_index].clearRetainingCapacity();
395}393}
396394
397pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) bool {395pub 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,...@@ -50,16 +50,14 @@ debug_line_str_section_dirty: bool = false,
50debug_loclists_section_dirty: bool = false,50debug_loclists_section_dirty: bool = false,
51debug_rnglists_section_dirty: bool = false,51debug_rnglists_section_dirty: bool = false,
5252
53/// Size contribution of Zig's metadata to each debug section.53debug_info_index: ?Symbol.Index = null,
54/// Used to track start of metadata from input object files.54debug_abbrev_index: ?Symbol.Index = null,
55debug_info_section_zig_size: u64 = 0,55debug_aranges_index: ?Symbol.Index = null,
56debug_abbrev_section_zig_size: u64 = 0,56debug_str_index: ?Symbol.Index = null,
57debug_str_section_zig_size: u64 = 0,57debug_line_index: ?Symbol.Index = null,
58debug_aranges_section_zig_size: u64 = 0,58debug_line_str_index: ?Symbol.Index = null,
59debug_line_section_zig_size: u64 = 0,59debug_loclists_index: ?Symbol.Index = null,
60debug_line_str_section_zig_size: u64 = 0,60debug_rnglists_index: ?Symbol.Index = null,
61debug_loclists_section_zig_size: u64 = 0,
62debug_rnglists_section_zig_size: u64 = 0,
6361
64pub const global_symbol_bit: u32 = 0x80000000;62pub const global_symbol_bit: u32 = 0x80000000;
65pub const symbol_mask: u32 = 0x7fffffff;63pub const symbol_mask: u32 = 0x7fffffff;
...@@ -171,13 +169,154 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi...@@ -171,13 +169,154 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi
171 if (self.dwarf) |*dwarf| {169 if (self.dwarf) |*dwarf| {
172 const pt: Zcu.PerThread = .{ .zcu = elf_file.base.comp.module.?, .tid = tid };170 const pt: Zcu.PerThread = .{ .zcu = elf_file.base.comp.module.?, .tid = tid };
173 try dwarf.flushModule(pt);171 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
175 self.debug_abbrev_section_dirty = false;316 self.debug_abbrev_section_dirty = false;
176 self.debug_aranges_section_dirty = false;317 self.debug_aranges_section_dirty = false;
177 self.debug_rnglists_section_dirty = false;318 self.debug_rnglists_section_dirty = false;
178 self.debug_str_section_dirty = false;319 self.debug_str_section_dirty = false;
179
180 self.saveDebugSectionsSizes(elf_file);
181 }320 }
182321
183 // The point of flushModule() is to commit changes, so in theory, nothing should322 // 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...@@ -190,33 +329,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi
190 assert(!self.debug_str_section_dirty);329 assert(!self.debug_str_section_dirty);
191}330}
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
220fn newSymbol(self: *ZigObject, allocator: Allocator, name_off: u32, st_bind: u4) !Symbol.Index {332fn newSymbol(self: *ZigObject, allocator: Allocator, name_off: u32, st_bind: u4) !Symbol.Index {
221 try self.symtab.ensureUnusedCapacity(allocator, 1);333 try self.symtab.ensureUnusedCapacity(allocator, 1);
222 try self.symbols.ensureUnusedCapacity(allocator, 1);334 try self.symbols.ensureUnusedCapacity(allocator, 1);
...@@ -278,7 +390,7 @@ fn newAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Atom.Index {...@@ -278,7 +390,7 @@ fn newAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Atom.Index {
278 return index;390 return index;
279}391}
280392
281fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index {393pub fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name_off: u32) !Symbol.Index {
282 const atom_index = try self.newAtom(allocator, name_off);394 const atom_index = try self.newAtom(allocator, name_off);
283 const sym_index = try self.newLocalSymbol(allocator, name_off);395 const sym_index = try self.newLocalSymbol(allocator, name_off);
284 const sym = self.symbol(sym_index);396 const sym = self.symbol(sym_index);
...@@ -642,11 +754,11 @@ pub fn getNavVAddr(...@@ -642,11 +754,11 @@ pub fn getNavVAddr(
642 const vaddr = this_sym.address(.{}, elf_file);754 const vaddr = this_sym.address(.{}, elf_file);
643 const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(elf_file).?;755 const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(elf_file).?;
644 const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch);756 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, .{
646 .r_offset = reloc_info.offset,758 .r_offset = reloc_info.offset,
647 .r_info = (@as(u64, @intCast(this_sym_index)) << 32) | r_type,759 .r_info = (@as(u64, @intCast(this_sym_index)) << 32) | r_type,
648 .r_addend = reloc_info.addend,760 .r_addend = reloc_info.addend,
649 });761 }, self);
650 return @intCast(vaddr);762 return @intCast(vaddr);
651}763}
652764
...@@ -661,11 +773,11 @@ pub fn getUavVAddr(...@@ -661,11 +773,11 @@ pub fn getUavVAddr(
661 const vaddr = sym.address(.{}, elf_file);773 const vaddr = sym.address(.{}, elf_file);
662 const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(elf_file).?;774 const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(elf_file).?;
663 const r_type = relocation.encode(.abs, elf_file.getTarget().cpu.arch);775 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, .{
665 .r_offset = reloc_info.offset,777 .r_offset = reloc_info.offset,
666 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,778 .r_info = (@as(u64, @intCast(sym_index)) << 32) | r_type,
667 .r_addend = reloc_info.addend,779 .r_addend = reloc_info.addend,
668 });780 }, self);
669 return @intCast(vaddr);781 return @intCast(vaddr);
670}782}
671783
...@@ -1012,7 +1124,7 @@ pub fn updateFunc(...@@ -1012,7 +1124,7 @@ pub fn updateFunc(
1012 log.debug("updateFunc {}({d})", .{ ip.getNav(func.owner_nav).fqn.fmt(ip), func.owner_nav });1124 log.debug("updateFunc {}({d})", .{ ip.getNav(func.owner_nav).fqn.fmt(ip), func.owner_nav });
10131125
1014 const sym_index = try self.getOrCreateMetadataForNav(elf_file, func.owner_nav);1126 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
1017 var code_buffer = std.ArrayList(u8).init(gpa);1129 var code_buffer = std.ArrayList(u8).init(gpa);
1018 defer code_buffer.deinit();1130 defer code_buffer.deinit();
...@@ -1140,7 +1252,7 @@ pub fn updateNav(...@@ -1140,7 +1252,7 @@ pub fn updateNav(
11401252
1141 if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(pt)) {1253 if (nav_init != .none and Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(pt)) {
1142 const sym_index = try self.getOrCreateMetadataForNav(elf_file, nav_index);1254 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
1145 var code_buffer = std.ArrayList(u8).init(zcu.gpa);1257 var code_buffer = std.ArrayList(u8).init(zcu.gpa);
1146 defer code_buffer.deinit();1258 defer code_buffer.deinit();
...@@ -1529,7 +1641,7 @@ pub fn asFile(self: *ZigObject) File {...@@ -1529,7 +1641,7 @@ pub fn asFile(self: *ZigObject) File {
1529 return .{ .zig_object = self };1641 return .{ .zig_object = self };
1530}1642}
15311643
1532fn addString(self: *ZigObject, allocator: Allocator, string: []const u8) !u32 {1644pub fn addString(self: *ZigObject, allocator: Allocator, string: []const u8) !u32 {
1533 return self.strtab.insert(allocator, string);1645 return self.strtab.insert(allocator, string);
1534}1646}
15351647
src/link/Elf/merge_section.zig+32-2
...@@ -1,4 +1,8 @@...@@ -1,4 +1,8 @@
1pub const MergeSection = struct {1pub const MergeSection = struct {
2 value: u64 = 0,
3 size: u64 = 0,
4 alignment: Atom.Alignment = .@"1",
5 entsize: u32 = 0,
2 name_offset: u32 = 0,6 name_offset: u32 = 0,
3 type: u32 = 0,7 type: u32 = 0,
4 flags: u64 = 0,8 flags: u64 = 0,
...@@ -26,7 +30,7 @@ pub const MergeSection = struct {...@@ -26,7 +30,7 @@ pub const MergeSection = struct {
2630
27 pub fn address(msec: MergeSection, elf_file: *Elf) i64 {31 pub fn address(msec: MergeSection, elf_file: *Elf) i64 {
28 const shdr = elf_file.shdrs.items[msec.output_section_index];32 const shdr = elf_file.shdrs.items[msec.output_section_index];
29 return @intCast(shdr.sh_addr);33 return @intCast(shdr.sh_addr + msec.value);
30 }34 }
3135
32 const InsertResult = struct {36 const InsertResult = struct {
...@@ -90,6 +94,29 @@ pub const MergeSection = struct {...@@ -90,6 +94,29 @@ pub const MergeSection = struct {
90 std.mem.sort(MergeSubsection.Index, msec.finalized_subsections.items, msec, sortFn);94 std.mem.sort(MergeSubsection.Index, msec.finalized_subsections.items, msec, sortFn);
91 }95 }
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
93 pub fn addMergeSubsection(msec: *MergeSection, allocator: Allocator) !MergeSubsection.Index {120 pub fn addMergeSubsection(msec: *MergeSection, allocator: Allocator) !MergeSubsection.Index {
94 const index: MergeSubsection.Index = @intCast(msec.subsections.items.len);121 const index: MergeSubsection.Index = @intCast(msec.subsections.items.len);
95 const msub = try msec.subsections.addOne(allocator);122 const msub = try msec.subsections.addOne(allocator);
...@@ -163,9 +190,12 @@ pub const MergeSection = struct {...@@ -163,9 +190,12 @@ pub const MergeSection = struct {
163 _ = unused_fmt_string;190 _ = unused_fmt_string;
164 const msec = ctx.msec;191 const msec = ctx.msec;
165 const elf_file = ctx.elf_file;192 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", .{
167 msec.name(elf_file),194 msec.name(elf_file),
168 msec.address(elf_file),195 msec.address(elf_file),
196 msec.size,
197 msec.alignment.toByteUnits() orelse 0,
198 msec.entsize,
169 msec.type,199 msec.type,
170 msec.flags,200 msec.flags,
171 });201 });
src/link/Elf/relocatable.zig+26-20
...@@ -42,7 +42,11 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co...@@ -42,7 +42,11 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]co
42 try elf_file.finalizeMergeSections();42 try elf_file.finalizeMergeSections();
43 zig_object.claimUnresolvedObject(elf_file);43 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
46 try elf_file.initSymtab();50 try elf_file.initSymtab();
47 try elf_file.initShStrtab();51 try elf_file.initShStrtab();
48 try elf_file.sortShdrs();52 try elf_file.sortShdrs();
...@@ -198,7 +202,6 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const...@@ -198,7 +202,6 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const
198 claimUnresolved(elf_file);202 claimUnresolved(elf_file);
199203
200 try initSections(elf_file);204 try initSections(elf_file);
201 try elf_file.initMergeSections();
202 try elf_file.sortShdrs();205 try elf_file.sortShdrs();
203 if (elf_file.zigObjectPtr()) |zig_object| {206 if (elf_file.zigObjectPtr()) |zig_object| {
204 try zig_object.addAtomsToRelaSections(elf_file);207 try zig_object.addAtomsToRelaSections(elf_file);
...@@ -294,6 +297,11 @@ fn initSections(elf_file: *Elf) !void {...@@ -294,6 +297,11 @@ fn initSections(elf_file: *Elf) !void {
294 try object.initRelaSections(elf_file);297 try object.initRelaSections(elf_file);
295 }298 }
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
297 const needs_eh_frame = for (elf_file.objects.items) |index| {305 const needs_eh_frame = for (elf_file.objects.items) |index| {
298 if (elf_file.file(index).?.object.cies.items.len > 0) break true;306 if (elf_file.file(index).?.object.cies.items.len > 0) break true;
299 } else false;307 } else false;
...@@ -423,24 +431,21 @@ fn writeAtoms(elf_file: *Elf) !void {...@@ -423,24 +431,21 @@ fn writeAtoms(elf_file: *Elf) !void {
423431
424 // TODO really, really handle debug section separately432 // TODO really, really handle debug section separately
425 const base_offset = if (elf_file.isDebugSection(@intCast(shndx))) blk: {433 const base_offset = if (elf_file.isDebugSection(@intCast(shndx))) blk: {
426 const zig_object = elf_file.zigObjectPtr().?;434 const zo = elf_file.zigObjectPtr().?;
427 if (shndx == elf_file.debug_info_section_index.?)435 break :blk for ([_]Symbol.Index{
428 break :blk zig_object.debug_info_section_zig_size;436 zo.debug_info_index.?,
429 if (shndx == elf_file.debug_abbrev_section_index.?)437 zo.debug_abbrev_index.?,
430 break :blk zig_object.debug_abbrev_section_zig_size;438 zo.debug_aranges_index.?,
431 if (shndx == elf_file.debug_str_section_index.?)439 zo.debug_str_index.?,
432 break :blk zig_object.debug_str_section_zig_size;440 zo.debug_line_index.?,
433 if (shndx == elf_file.debug_aranges_section_index.?)441 zo.debug_line_str_index.?,
434 break :blk zig_object.debug_aranges_section_zig_size;442 zo.debug_loclists_index.?,
435 if (shndx == elf_file.debug_line_section_index.?)443 zo.debug_rnglists_index.?,
436 break :blk zig_object.debug_line_section_zig_size;444 }) |sym_index| {
437 if (shndx == elf_file.debug_line_str_section_index.?)445 const sym = zo.symbol(sym_index);
438 break :blk zig_object.debug_line_str_section_zig_size;446 const atom_ptr = sym.atom(elf_file).?;
439 if (shndx == elf_file.debug_loclists_section_index.?)447 if (atom_ptr.output_section_index == shndx) break atom_ptr.size;
440 break :blk zig_object.debug_loclists_section_zig_size;448 } else 0;
441 if (shndx == elf_file.debug_rnglists_section_index.?)
442 break :blk zig_object.debug_rnglists_section_zig_size;
443 unreachable;
444 } else 0;449 } else 0;
445 const sh_offset = shdr.sh_offset + base_offset;450 const sh_offset = shdr.sh_offset + base_offset;
446 const sh_size = math.cast(usize, shdr.sh_size - base_offset) orelse return error.Overflow;451 const sh_size = math.cast(usize, shdr.sh_size - base_offset) orelse return error.Overflow;
...@@ -586,3 +591,4 @@ const Compilation = @import("../../Compilation.zig");...@@ -586,3 +591,4 @@ const Compilation = @import("../../Compilation.zig");
586const Elf = @import("../Elf.zig");591const Elf = @import("../Elf.zig");
587const File = @import("file.zig").File;592const File = @import("file.zig").File;
588const Object = @import("Object.zig");593const 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 {...@@ -91,6 +91,44 @@ pub fn encode(comptime kind: Kind, cpu_arch: std.Target.Cpu.Arch) u32 {
91 };91 };
92}92}
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
94const FormatRelocTypeCtx = struct {132const FormatRelocTypeCtx = struct {
95 r_type: u32,133 r_type: u32,
96 cpu_arch: std.Target.Cpu.Arch,134 cpu_arch: std.Target.Cpu.Arch,
...@@ -124,4 +162,6 @@ const assert = std.debug.assert;...@@ -124,4 +162,6 @@ const assert = std.debug.assert;
124const elf = std.elf;162const elf = std.elf;
125const std = @import("std");163const std = @import("std");
126164
165const Dwarf = @import("../Dwarf.zig");
127const Elf = @import("../Elf.zig");166const 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 {...@@ -695,6 +695,44 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
695 \\1 breakpoints deleted; 0 breakpoint locations disabled.695 \\1 breakpoints deleted; 0 breakpoint locations disabled.
696 },696 },
697 );697 );
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 );
698}736}
699737
700const File = struct { import: ?[]const u8 = null, path: []const u8, source: []const u8 };738const File = struct { import: ?[]const u8 = null, path: []const u8, source: []const u8 };