x86: fix generating debug info for variables

Add handling for these additional `MCValue`s:
* `.immediate` - lower to `DW.OP.consts` or `DW.OP.constu` depending
  on signedness followed by popping off the DWARF stack with
  `DW.OP.stack_value`
* `.undef` - lower to `DW.OP.implicit_value`
* `.none` - lower to `DW.OP.lit0` followed by popping off the DWARF
  stack with `DW.OP.stack_value`

For any remaining unhandled case, we generate `DW.OP.nop` in order
not to mess up remaining DWARF info.
This commit is contained in:
Jakub Konka 2022-08-12 11:55:38 +02:00
parent f2f1bb7cb6
commit aeaffd42f6
2 changed files with 54 additions and 5 deletions

View File

@ -4370,6 +4370,7 @@ fn genVarDbgInfo(
.dwarf => |dw| {
const dbg_info = &dw.dbg_info;
try dbg_info.append(@enumToInt(link.File.Dwarf.AbbrevKind.variable));
const endian = self.target.cpu.arch.endian();
switch (mcv) {
.register => |reg| {
@ -4390,7 +4391,6 @@ fn genVarDbgInfo(
dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
},
.memory, .got_load, .direct_load => {
const endian = self.target.cpu.arch.endian();
const ptr_width = @intCast(u8, @divExact(self.target.cpu.arch.ptrBitWidth(), 8));
const is_ptr = switch (tag) {
.dbg_var_ptr => true,
@ -4425,7 +4425,53 @@ fn genVarDbgInfo(
else => {},
}
},
.immediate => |x| {
const signedness: std.builtin.Signedness = blk: {
if (ty.zigTypeTag() != .Int) break :blk .unsigned;
break :blk ty.intInfo(self.target.*).signedness;
};
try dbg_info.ensureUnusedCapacity(2);
const fixup = dbg_info.items.len;
dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
1,
switch (signedness) {
.signed => DW.OP.consts,
.unsigned => DW.OP.constu,
},
});
switch (signedness) {
.signed => try leb128.writeILEB128(dbg_info.writer(), @bitCast(i64, x)),
.unsigned => try leb128.writeULEB128(dbg_info.writer(), x),
}
try dbg_info.append(DW.OP.stack_value);
dbg_info.items[fixup] += @intCast(u8, dbg_info.items.len - fixup - 2);
},
.undef => {
// DW.AT.location, DW.FORM.exprloc
// uleb128(exprloc_len)
// DW.OP.implicit_value uleb128(len_of_bytes) bytes
const abi_size = @intCast(u32, ty.abiSize(self.target.*));
var implicit_value_len = std.ArrayList(u8).init(self.gpa);
defer implicit_value_len.deinit();
try leb128.writeULEB128(implicit_value_len.writer(), abi_size);
const total_exprloc_len = 1 + implicit_value_len.items.len + abi_size;
try leb128.writeULEB128(dbg_info.writer(), total_exprloc_len);
try dbg_info.ensureUnusedCapacity(total_exprloc_len);
dbg_info.appendAssumeCapacity(DW.OP.implicit_value);
dbg_info.appendSliceAssumeCapacity(implicit_value_len.items);
dbg_info.appendNTimesAssumeCapacity(0xaa, abi_size);
},
.none => {
try dbg_info.ensureUnusedCapacity(3);
dbg_info.appendSliceAssumeCapacity(&[3]u8{ // DW.AT.location, DW.FORM.exprloc
2, DW.OP.lit0, DW.OP.stack_value,
});
},
else => {
try dbg_info.ensureUnusedCapacity(2);
dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
1, DW.OP.nop,
});
log.debug("TODO generate debug info for {}", .{mcv});
},
}

View File

@ -102,7 +102,7 @@ pub const DeclState = struct {
}
pub fn addExprlocReloc(self: *DeclState, target: u32, offset: u32, is_ptr: bool) !void {
log.debug("{x}: target sym @{d}, via GOT {}", .{ offset, target, is_ptr });
log.debug("{x}: target sym %{d}, via GOT {}", .{ offset, target, is_ptr });
try self.exprloc_relocs.append(self.gpa, .{
.@"type" = if (is_ptr) .got_load else .direct_load,
.target = target,
@ -135,7 +135,7 @@ pub const DeclState = struct {
.@"type" = ty,
.offset = undefined,
});
log.debug("@{d}: {}", .{ sym_index, ty.fmtDebug() });
log.debug("%{d}: {}", .{ sym_index, ty.fmtDebug() });
try self.abbrev_resolver.putNoClobberContext(self.gpa, ty, sym_index, .{
.mod = self.mod,
});
@ -143,7 +143,7 @@ pub const DeclState = struct {
.mod = self.mod,
}).?;
};
log.debug("{x}: @{d} + 0", .{ offset, resolv });
log.debug("{x}: %{d} + 0", .{ offset, resolv });
try self.abbrev_relocs.append(self.gpa, .{
.target = resolv,
.atom = atom,
@ -1056,6 +1056,7 @@ pub fn commitDeclState(
break :blk false;
};
if (deferred) {
log.debug("resolving %{d} deferred until flush", .{target});
try self.global_abbrev_relocs.append(gpa, .{
.target = null,
.offset = reloc.offset,
@ -1063,10 +1064,12 @@ pub fn commitDeclState(
.addend = reloc.addend,
});
} else {
const value = symbol.atom.off + symbol.offset + reloc.addend;
log.debug("{x}: [() => {x}] (%{d}, '{}')", .{ reloc.offset, value, target, ty.fmtDebug() });
mem.writeInt(
u32,
dbg_info_buffer.items[reloc.offset..][0..@sizeOf(u32)],
symbol.atom.off + symbol.offset + reloc.addend,
value,
target_endian,
);
}