mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 22:35:24 +00:00
dwarf: add debug info for unions
This commit is contained in:
parent
0d5d353197
commit
1c33ea2c35
@ -83,8 +83,9 @@ pub const abbrev_struct_type = 6;
|
||||
pub const abbrev_struct_member = 7;
|
||||
pub const abbrev_enum_type = 8;
|
||||
pub const abbrev_enum_variant = 9;
|
||||
pub const abbrev_pad1 = 10;
|
||||
pub const abbrev_parameter = 11;
|
||||
pub const abbrev_union_type = 10;
|
||||
pub const abbrev_pad1 = 11;
|
||||
pub const abbrev_parameter = 12;
|
||||
|
||||
/// The reloc offset for the virtual address of a function in its Line Number Program.
|
||||
/// Size is a virtual address integer.
|
||||
@ -452,6 +453,8 @@ pub fn commitDeclDebugInfo(
|
||||
var dbg_type_arena = std.heap.ArenaAllocator.init(gpa);
|
||||
defer dbg_type_arena.deinit();
|
||||
|
||||
var nested_ref4_relocs = std.ArrayList(u32).init(gpa);
|
||||
defer nested_ref4_relocs.deinit();
|
||||
{
|
||||
// Now we emit the .debug_info types of the Decl. These will count towards the size of
|
||||
// the buffer, so we have to do it before computing the offset, and we can't perform the actual
|
||||
@ -463,7 +466,13 @@ pub fn commitDeclDebugInfo(
|
||||
.target = self.target,
|
||||
}).?;
|
||||
value_ptr.off = @intCast(u32, dbg_info_buffer.items.len);
|
||||
try self.addDbgInfoType(dbg_type_arena.allocator(), ty, dbg_info_buffer, dbg_info_type_relocs);
|
||||
try self.addDbgInfoType(
|
||||
dbg_type_arena.allocator(),
|
||||
ty,
|
||||
dbg_info_buffer,
|
||||
dbg_info_type_relocs,
|
||||
&nested_ref4_relocs,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -478,13 +487,27 @@ pub fn commitDeclDebugInfo(
|
||||
// Now that we have the offset assigned we can finally perform type relocations.
|
||||
for (dbg_info_type_relocs.values()) |value| {
|
||||
for (value.relocs.items) |off| {
|
||||
mem.writeIntLittle(
|
||||
mem.writeInt(
|
||||
u32,
|
||||
dbg_info_buffer.items[off..][0..4],
|
||||
atom.off + value.off,
|
||||
target_endian,
|
||||
);
|
||||
}
|
||||
}
|
||||
// Offsets to positions with known a priori relative displacement values.
|
||||
// Here, we just need to add the offset of the atom to the read value in the
|
||||
// relocated cell.
|
||||
// TODO Should probably generalise this with type relocs.
|
||||
for (nested_ref4_relocs.items) |off| {
|
||||
const addend = mem.readInt(u32, dbg_info_buffer.items[off..][0..4], target_endian);
|
||||
mem.writeInt(
|
||||
u32,
|
||||
dbg_info_buffer.items[off..][0..4],
|
||||
atom.off + addend,
|
||||
target_endian,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
try self.writeDeclDebugInfo(file, atom, dbg_info_buffer.items);
|
||||
@ -751,8 +774,10 @@ fn addDbgInfoType(
|
||||
ty: Type,
|
||||
dbg_info_buffer: *std.ArrayList(u8),
|
||||
dbg_info_type_relocs: *File.DbgInfoTypeRelocsTable,
|
||||
nested_ref4_relocs: *std.ArrayList(u32),
|
||||
) error{OutOfMemory}!void {
|
||||
const target = self.target;
|
||||
const target_endian = self.target.cpu.arch.endian();
|
||||
var relocs = std.ArrayList(struct { ty: Type, reloc: u32 }).init(arena);
|
||||
|
||||
switch (ty.zigTypeTag()) {
|
||||
@ -962,7 +987,6 @@ fn addDbgInfoType(
|
||||
.enum_numbered => ty.castTag(.enum_numbered).?.data.values,
|
||||
else => unreachable,
|
||||
};
|
||||
const target_endian = self.target.cpu.arch.endian();
|
||||
for (fields.keys()) |field_name, field_i| {
|
||||
// DW.AT.enumerator
|
||||
try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2 + @sizeOf(u64));
|
||||
@ -983,6 +1007,94 @@ fn addDbgInfoType(
|
||||
// DW.AT.enumeration_type delimit children
|
||||
try dbg_info_buffer.append(0);
|
||||
},
|
||||
.Union => {
|
||||
const layout = ty.unionGetLayout(target);
|
||||
const union_obj = ty.cast(Type.Payload.Union).?.data;
|
||||
const payload_offset = if (layout.tag_align >= layout.payload_align) layout.tag_size else 0;
|
||||
const tag_offset = if (layout.tag_align >= layout.payload_align) 0 else layout.payload_size;
|
||||
const is_tagged = layout.tag_size > 0;
|
||||
const union_name = try ty.nameAllocArena(arena, target);
|
||||
|
||||
// TODO this is temporary to match current state of unions in Zig - we don't yet have
|
||||
// safety checks implemented meaning the implicit tag is not yet stored and generated
|
||||
// for untagged unions.
|
||||
if (is_tagged) {
|
||||
// DW.AT.structure_type
|
||||
try dbg_info_buffer.append(abbrev_struct_type);
|
||||
// DW.AT.byte_size, DW.FORM.sdata
|
||||
try leb128.writeULEB128(dbg_info_buffer.writer(), layout.abi_size);
|
||||
// DW.AT.name, DW.FORM.string
|
||||
try dbg_info_buffer.ensureUnusedCapacity(union_name.len + 1);
|
||||
dbg_info_buffer.appendSliceAssumeCapacity(union_name);
|
||||
dbg_info_buffer.appendAssumeCapacity(0);
|
||||
|
||||
// DW.AT.member
|
||||
try dbg_info_buffer.ensureUnusedCapacity(9);
|
||||
dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
|
||||
// DW.AT.name, DW.FORM.string
|
||||
dbg_info_buffer.appendSliceAssumeCapacity("payload");
|
||||
dbg_info_buffer.appendAssumeCapacity(0);
|
||||
// DW.AT.type, DW.FORM.ref4
|
||||
const inner_union_index = dbg_info_buffer.items.len;
|
||||
try dbg_info_buffer.ensureUnusedCapacity(4);
|
||||
mem.writeInt(
|
||||
u32,
|
||||
dbg_info_buffer.addManyAsArrayAssumeCapacity(4),
|
||||
@intCast(u32, inner_union_index + 5),
|
||||
target_endian,
|
||||
);
|
||||
try nested_ref4_relocs.append(@intCast(u32, inner_union_index));
|
||||
// DW.AT.data_member_location, DW.FORM.sdata
|
||||
try leb128.writeULEB128(dbg_info_buffer.writer(), payload_offset);
|
||||
}
|
||||
|
||||
// DW.AT.union_type
|
||||
try dbg_info_buffer.append(abbrev_union_type);
|
||||
// DW.AT.byte_size, DW.FORM.sdata,
|
||||
try leb128.writeULEB128(dbg_info_buffer.writer(), layout.payload_size);
|
||||
// DW.AT.name, DW.FORM.string
|
||||
if (is_tagged) {
|
||||
try dbg_info_buffer.writer().print("AnonUnion\x00", .{});
|
||||
} else {
|
||||
try dbg_info_buffer.writer().print("{s}\x00", .{union_name});
|
||||
}
|
||||
|
||||
const fields = ty.unionFields();
|
||||
for (fields.keys()) |field_name| {
|
||||
const field = fields.get(field_name).?;
|
||||
if (!field.ty.hasRuntimeBits()) continue;
|
||||
// DW.AT.member
|
||||
try dbg_info_buffer.append(abbrev_struct_member);
|
||||
// DW.AT.name, DW.FORM.string
|
||||
try dbg_info_buffer.writer().print("{s}\x00", .{field_name});
|
||||
// DW.AT.type, DW.FORM.ref4
|
||||
const index = dbg_info_buffer.items.len;
|
||||
try dbg_info_buffer.resize(index + 4);
|
||||
try relocs.append(.{ .ty = field.ty, .reloc = @intCast(u32, index) });
|
||||
// DW.AT.data_member_location, DW.FORM.sdata
|
||||
try dbg_info_buffer.append(0);
|
||||
}
|
||||
// DW.AT.union_type delimit children
|
||||
try dbg_info_buffer.append(0);
|
||||
|
||||
if (is_tagged) {
|
||||
// DW.AT.member
|
||||
try dbg_info_buffer.ensureUnusedCapacity(5);
|
||||
dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member);
|
||||
// DW.AT.name, DW.FORM.string
|
||||
dbg_info_buffer.appendSliceAssumeCapacity("tag");
|
||||
dbg_info_buffer.appendAssumeCapacity(0);
|
||||
// DW.AT.type, DW.FORM.ref4
|
||||
const index = dbg_info_buffer.items.len;
|
||||
try dbg_info_buffer.resize(index + 4);
|
||||
try relocs.append(.{ .ty = union_obj.tag_ty, .reloc = @intCast(u32, index) });
|
||||
// DW.AT.data_member_location, DW.FORM.sdata
|
||||
try leb128.writeULEB128(dbg_info_buffer.writer(), tag_offset);
|
||||
|
||||
// DW.AT.structure_type delimit children
|
||||
try dbg_info_buffer.append(0);
|
||||
}
|
||||
},
|
||||
else => {
|
||||
log.debug("TODO implement .debug_info for type '{}'", .{ty.fmtDebug()});
|
||||
try dbg_info_buffer.append(abbrev_pad1);
|
||||
@ -1089,6 +1201,15 @@ pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void {
|
||||
DW.FORM.data8,
|
||||
0,
|
||||
0, // table sentinel
|
||||
abbrev_union_type,
|
||||
DW.TAG.union_type,
|
||||
DW.CHILDREN.yes, // header
|
||||
DW.AT.byte_size,
|
||||
DW.FORM.sdata,
|
||||
DW.AT.name,
|
||||
DW.FORM.string,
|
||||
0,
|
||||
0, // table sentinel
|
||||
abbrev_pad1,
|
||||
DW.TAG.unspecified_type,
|
||||
DW.CHILDREN.no, // header
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user