diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-01-24 10:33:42 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2022-01-25 23:51:19 +0100 |
| commit | 53c668d3a9dad430749cbc642d7bf8cf45eefba1 (patch) | |
| tree | 38b4ab6279aa9cd396b2a6622451c78116f35dea /src/link | |
| parent | 05c5bb9edd51e73c0d4a2619817fbff73b82f230 (diff) | |
| download | zig-53c668d3a9dad430749cbc642d7bf8cf45eefba1.tar.gz zig-53c668d3a9dad430749cbc642d7bf8cf45eefba1.zip | |
stage2: add naive impl of pointer type in ELF
Augment relocation tracking mechanism to de-duplicate potential
creation of base as well as composite types while unrolling
composite types in the linker - there is still potential for
further space optimisation by moving all type information into
a separate section `.debug_types` and providing references to
entries within that section whenever required (e.g., `ref4` form).
Currently, we duplicate type definitions on a per-decl basis.
Anyhow, with this patch, an example function signature of the following
type:
```zig
fn byPtrPtr(ptr_ptr_x: **u32, ptr_x: *u32) void {
ptr_ptr_x.* = ptr_x;
}
```
will generate the following `.debug_info` for formal parameters:
```
<1><1aa>: Abbrev Number: 3 (DW_TAG_subprogram)
<1ab> DW_AT_low_pc : 0x8000197
<1b3> DW_AT_high_pc : 0x2c
<1b7> DW_AT_name : byPtrPtr
<2><1c0>: Abbrev Number: 7 (DW_TAG_formal_parameter)
<1c1> DW_AT_location : 1 byte block: 55 (DW_OP_reg5 (rdi))
<1c3> DW_AT_type : <0x1df>
<1c7> DW_AT_name : ptr_ptr_x
<2><1d1>: Abbrev Number: 7 (DW_TAG_formal_parameter)
<1d2> DW_AT_location : 1 byte block: 54 (DW_OP_reg4 (rsi))
<1d4> DW_AT_type : <0x1e4>
<1d8> DW_AT_name : ptr_x
<2><1de>: Abbrev Number: 0
<1><1df>: Abbrev Number: 5 (DW_TAG_pointer_type)
<1e0> DW_AT_type : <0x1e4>
<1><1e4>: Abbrev Number: 5 (DW_TAG_pointer_type)
<1e5> DW_AT_type : <0x1e9>
<1><1e9>: Abbrev Number: 4 (DW_TAG_base_type)
<1ea> DW_AT_encoding : 7 (unsigned)
<1eb> DW_AT_byte_size : 4
<1ec> DW_AT_name : u32
```
Diffstat (limited to 'src/link')
| -rw-r--r-- | src/link/Elf.zig | 71 | ||||
| -rw-r--r-- | src/link/MachO.zig | 6 | ||||
| -rw-r--r-- | src/link/MachO/DebugSymbols.zig | 3 |
3 files changed, 60 insertions, 20 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index a7ce8d0783..2b88458bc9 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -783,8 +783,9 @@ pub const abbrev_compile_unit = 1; pub const abbrev_subprogram = 2; pub const abbrev_subprogram_retvoid = 3; pub const abbrev_base_type = 4; -pub const abbrev_pad1 = 5; -pub const abbrev_parameter = 6; +pub const abbrev_ptr_type = 5; +pub const abbrev_pad1 = 6; +pub const abbrev_parameter = 7; pub fn flush(self: *Elf, comp: *Compilation) !void { if (self.base.options.emit == null) { @@ -871,9 +872,21 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { DW.AT.byte_size, DW.FORM.data1, DW.AT.name, - DW.FORM.string, 0, 0, // table sentinel - abbrev_pad1, DW.TAG.unspecified_type, DW.CHILDREN.no, // header - 0, 0, // table sentinel + DW.FORM.string, + 0, + 0, // table sentinel + abbrev_ptr_type, + DW.TAG.pointer_type, + DW.CHILDREN.no, // header + DW.AT.type, + DW.FORM.ref4, + 0, + 0, // table sentinel + abbrev_pad1, + DW.TAG.unspecified_type, + DW.CHILDREN.no, // header + 0, + 0, // table sentinel abbrev_parameter, DW.TAG.formal_parameter, DW.CHILDREN.no, // header DW.AT.location, DW.FORM.exprloc, @@ -2309,8 +2322,7 @@ pub fn freeDecl(self: *Elf, decl: *Module.Decl) void { } fn deinitRelocs(gpa: Allocator, table: *File.DbgInfoTypeRelocsTable) void { - var it = table.valueIterator(); - while (it.next()) |value| { + for (table.values()) |*value| { value.relocs.deinit(gpa); } table.deinit(gpa); @@ -2387,10 +2399,12 @@ fn finishUpdateDecl( // the buffer, so we have to do it before computing the offset, and we can't perform the actual // relocations yet. { - var it = dbg_info_type_relocs.iterator(); - while (it.next()) |entry| { - entry.value_ptr.off = @intCast(u32, dbg_info_buffer.items.len); - try self.addDbgInfoType(entry.key_ptr.*, dbg_info_buffer); + var it: usize = 0; + while (it < dbg_info_type_relocs.count()) : (it += 1) { + const ty = dbg_info_type_relocs.keys()[it]; + const value_ptr = dbg_info_type_relocs.getPtr(ty).?; + value_ptr.off = @intCast(u32, dbg_info_buffer.items.len); + try self.addDbgInfoType(ty, dbg_info_buffer, dbg_info_type_relocs); } } @@ -2401,8 +2415,7 @@ fn finishUpdateDecl( { // Now that we have the offset assigned we can finally perform type relocations. - var it = dbg_info_type_relocs.valueIterator(); - while (it.next()) |value| { + for (dbg_info_type_relocs.values()) |value| { for (value.relocs.items) |off| { mem.writeInt( u32, @@ -2706,7 +2719,14 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { } /// Asserts the type has codegen bits. -fn addDbgInfoType(self: *Elf, ty: Type, dbg_info_buffer: *std.ArrayList(u8)) !void { +fn addDbgInfoType( + self: *Elf, + ty: Type, + dbg_info_buffer: *std.ArrayList(u8), + dbg_info_type_relocs: *File.DbgInfoTypeRelocsTable, +) error{OutOfMemory}!void { + var reloc: ?struct { ty: Type, reloc: u32 } = null; + switch (ty.zigTypeTag()) { .Void => unreachable, .NoReturn => unreachable, @@ -2747,11 +2767,34 @@ fn addDbgInfoType(self: *Elf, ty: Type, dbg_info_buffer: *std.ArrayList(u8)) !vo try dbg_info_buffer.append(abbrev_pad1); } }, + .Pointer => blk: { + if (ty.isSlice()) { + log.debug("TODO implement .debug_info for type '{}'", .{ty}); + try dbg_info_buffer.append(abbrev_pad1); + break :blk; + } + try dbg_info_buffer.ensureUnusedCapacity(5); + dbg_info_buffer.appendAssumeCapacity(abbrev_ptr_type); + const index = dbg_info_buffer.items.len; + try dbg_info_buffer.resize(index + 4); // DW.AT.type, DW.FORM.ref4 + reloc = .{ .ty = ty.childType(), .reloc = @intCast(u32, index) }; + }, else => { log.debug("TODO implement .debug_info for type '{}'", .{ty}); try dbg_info_buffer.append(abbrev_pad1); }, } + + if (reloc) |rel| { + const gop = try dbg_info_type_relocs.getOrPut(self.base.allocator, rel.ty); + if (!gop.found_existing) { + gop.value_ptr.* = .{ + .off = undefined, + .relocs = .{}, + }; + } + try gop.value_ptr.relocs.append(self.base.allocator, rel.reloc); + } } fn updateDeclDebugInfoAllocation(self: *Elf, text_block: *TextBlock, len: u32) !void { diff --git a/src/link/MachO.zig b/src/link/MachO.zig index d7385f1f33..cd1d197010 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -3578,8 +3578,7 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv if (debug_buffers) |dbg| { dbg.dbg_line_buffer.deinit(); dbg.dbg_info_buffer.deinit(); - var it = dbg.dbg_info_type_relocs.valueIterator(); - while (it.next()) |value| { + for (dbg.dbg_info_type_relocs.values()) |*value| { value.relocs.deinit(self.base.allocator); } dbg.dbg_info_type_relocs.deinit(self.base.allocator); @@ -3659,8 +3658,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { if (debug_buffers) |dbg| { dbg.dbg_line_buffer.deinit(); dbg.dbg_info_buffer.deinit(); - var it = dbg.dbg_info_type_relocs.valueIterator(); - while (it.next()) |value| { + for (dbg.dbg_info_type_relocs.values()) |*value| { value.relocs.deinit(self.base.allocator); } dbg.dbg_info_type_relocs.deinit(self.base.allocator); diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig index 88a27ea48f..beef0b6b2c 100644 --- a/src/link/MachO/DebugSymbols.zig +++ b/src/link/MachO/DebugSymbols.zig @@ -1112,8 +1112,7 @@ pub fn commitDeclDebugInfo( { // Now that we have the offset assigned we can finally perform type relocations. - var it = dbg_info_type_relocs.valueIterator(); - while (it.next()) |value| { + for (dbg_info_type_relocs.values()) |value| { for (value.relocs.items) |off| { mem.writeIntLittle( u32, |
