aboutsummaryrefslogtreecommitdiff
path: root/src/link/Dwarf.zig
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-12-07 22:29:07 +0100
committerJakub Konka <kubkon@jakubkonka.com>2022-12-09 09:24:25 +0100
commit62145a1b0850f4def3f2ab401da7bed47045044d (patch)
treee2f50f7f324f8b5499313f0ecd3d138dcdd0cbb4 /src/link/Dwarf.zig
parent6817219e275a739794006d242bfa13840757b768 (diff)
downloadzig-62145a1b0850f4def3f2ab401da7bed47045044d.tar.gz
zig-62145a1b0850f4def3f2ab401da7bed47045044d.zip
dwarf: refactor routine for precalculating size of dbg line header
Diffstat (limited to 'src/link/Dwarf.zig')
-rw-r--r--src/link/Dwarf.zig41
1 files changed, 23 insertions, 18 deletions
diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig
index b47091dc0a..87f254683a 100644
--- a/src/link/Dwarf.zig
+++ b/src/link/Dwarf.zig
@@ -2303,7 +2303,6 @@ pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void {
// files, and padding. We have a function to compute the upper bound size, however,
// because it's needed for determining where to put the offset of the first `SrcFn`.
const needed_bytes = self.dbgLineNeededHeaderBytes(paths.dirs, paths.files);
- log.debug("dbg_line_prg_off = {x}, needed_bytes = {x}", .{ dbg_line_prg_off, needed_bytes });
var di_buf = try std.ArrayList(u8).initCapacity(self.allocator, needed_bytes);
defer di_buf.deinit();
@@ -2390,6 +2389,8 @@ pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void {
},
}
+ assert(needed_bytes == di_buf.items.len);
+
// We use NOPs because consumers empirically do not respect the header length field.
if (di_buf.items.len > dbg_line_prg_off) {
// Move the first N files to the end to make more padding for the header.
@@ -2448,27 +2449,31 @@ fn ptrWidthBytes(self: Dwarf) u8 {
}
fn dbgLineNeededHeaderBytes(self: Dwarf, dirs: []const []const u8, files: []const []const u8) u32 {
- _ = self;
- const directory_entry_format_count = 1;
- const file_name_entry_format_count = 1;
- const directory_count = dirs.len + 1;
- const file_name_count = files.len;
-
- var dir_names_len: usize = 0;
- for (dirs) |dir| {
- dir_names_len += dir.len + 1;
+ var size = switch (self.bin_file.tag) { // length field
+ .macho => @sizeOf(u32),
+ else => switch (self.ptr_width) {
+ .p32 => @as(usize, @sizeOf(u32)),
+ .p64 => @sizeOf(u32) + @sizeOf(u64),
+ },
+ };
+ size += @sizeOf(u16); // version field
+ size += switch (self.bin_file.tag) { // offset to end-of-header
+ .macho => @sizeOf(u32),
+ else => self.ptrWidthBytes(),
+ };
+ size += 18; // opcodes
+
+ for (dirs) |dir| { // include dirs
+ size += dir.len + 1;
}
+ size += 1; // include dirs sentinel
- var file_names_len: usize = 0;
- for (files) |file| {
- file_names_len += file.len + 1;
+ for (files) |file| { // file names
+ size += file.len + 1 + 1 + 1 + 1;
}
+ size += 1; // file names sentinel
- return @intCast(u32, 53 + directory_entry_format_count * 2 + file_name_entry_format_count * 2 +
- directory_count * 8 + file_name_count * 8 +
- // These are encoded as DW.FORM.string rather than DW.FORM.strp as we would like
- // because of a workaround for readelf and gdb failing to understand DWARFv5 correctly.
- dir_names_len + file_names_len);
+ return @intCast(u32, size);
}
/// The reloc offset for the line offset of a function from the previous function's line.