authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-19 08:40:22+02:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-08-21 01:43:21-04:00
logd388d555d5abc06962e4e8a409a5fa28f8c4f84c
tree8a3e9dd7421bbb4e5ae7deabed64548ea46e7d70
parentd3d5ed992c339ef114115fb621e0659ce121e027

elf: parse and emit Elf relocs for cross section refs for .debug* sections


2 files changed, 57 insertions(+), 16 deletions(-)

src/link/Dwarf.zig+4-4
......@@ -287,7 +287,7 @@ pub 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 };
......@@ -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}", .{
src/link/Elf/ZigObject.zig+53-12
......@@ -195,15 +195,15 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi
195195 self.debug_line_str_index.?,
196196 self.debug_loclists_index.?,
197197 self.debug_rnglists_index.?,
198 }, [_]Dwarf.Section{
199 dwarf.debug_info.section,
200 dwarf.debug_abbrev.section,
201 dwarf.debug_str.section,
202 dwarf.debug_aranges.section,
203 dwarf.debug_line.section,
204 dwarf.debug_line_str.section,
205 dwarf.debug_loclists.section,
206 dwarf.debug_rnglists.section,
198 }, [_]*Dwarf.Section{
199 &dwarf.debug_info.section,
200 &dwarf.debug_abbrev.section,
201 &dwarf.debug_str.section,
202 &dwarf.debug_aranges.section,
203 &dwarf.debug_line.section,
204 &dwarf.debug_line_str.section,
205 &dwarf.debug_loclists.section,
206 &dwarf.debug_rnglists.section,
207207 }) |sym_index, sect| {
208208 const sym = self.symbol(sym_index);
209209 const atom_ptr = self.atom(sym.ref.index).?;
......@@ -215,11 +215,52 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi
215215 atom_ptr.size = shdr.sh_size;
216216 atom_ptr.alignment = Atom.Alignment.fromNonzeroByteUnits(shdr.sh_addralign);
217217
218 log.debug("parsing relocs in {s}", .{sym.name(elf_file)});
219
218220 const relocs = &self.relocs.items[atom_ptr.relocsShndx().?];
219221 for (sect.units.items) |*unit| {
222 try relocs.ensureUnusedCapacity(gpa, unit.cross_section_relocs.items.len);
223 for (unit.cross_section_relocs.items) |reloc| {
224 const target_sym_index = switch (reloc.target_sec) {
225 .debug_abbrev => self.debug_abbrev_index.?,
226 .debug_info => self.debug_info_index.?,
227 .debug_line => self.debug_line_index.?,
228 .debug_line_str => self.debug_line_str_index.?,
229 .debug_loclists => self.debug_loclists_index.?,
230 .debug_rnglists => self.debug_rnglists_index.?,
231 .debug_str => self.debug_str_index.?,
232 };
233 const target_sec = switch (reloc.target_sec) {
234 inline else => |target_sec| &@field(dwarf, @tagName(target_sec)).section,
235 };
236 const target_unit = target_sec.getUnit(reloc.target_unit);
237 const r_offset = unit.off + reloc.source_off + (if (reloc.source_entry.unwrap()) |source_entry|
238 unit.header_len + unit.getEntry(source_entry).off
239 else
240 0);
241 const r_addend: i64 = @intCast(reloc.target_off + (if (reloc.target_entry.unwrap()) |target_entry|
242 target_unit.header_len + target_unit.getEntry(target_entry).assertNonEmpty(unit, sect, dwarf).off
243 else
244 0));
245 const r_type: elf.R_X86_64 = switch (dwarf.format) {
246 .@"32" => .@"32",
247 .@"64" => .@"64",
248 };
249 log.debug(" {s} <- r_off={x}, r_add={x}, r_type={s}", .{
250 self.symbol(target_sym_index).name(elf_file),
251 r_offset,
252 r_addend,
253 @tagName(r_type),
254 });
255 atom_ptr.addRelocAssumeCapacity(.{
256 .r_offset = r_offset,
257 .r_addend = r_addend,
258 .r_info = (@as(u64, @intCast(target_sym_index)) << 32) | @intFromEnum(r_type),
259 }, self);
260 }
261
220262 try relocs.ensureUnusedCapacity(gpa, unit.external_relocs.items.len);
221263 for (unit.external_relocs.items) |reloc| {
222 const tsym = self.symbol(reloc.target_sym);
223264 const r_offset = unit.off + unit.header_len + unit.getEntry(reloc.source_entry).off + reloc.source_off;
224265 const r_addend: i64 = @intCast(reloc.target_off);
225266 const r_type: elf.R_X86_64 = switch (dwarf.address_size) {
......@@ -227,8 +268,8 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi
227268 .@"64" => .@"64",
228269 else => unreachable,
229270 };
230 log.debug("{s} <- r_off={x}, r_add={x}, r_type={s}\n", .{
231 tsym.name(elf_file),
271 log.debug(" {s} <- r_off={x}, r_add={x}, r_type={s}", .{
272 self.symbol(reloc.target_sym).name(elf_file),
232273 r_offset,
233274 r_addend,
234275 @tagName(r_type),