authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-03 21:01:06-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-03 21:01:06-07:00
logd624bf8059fa3a86a740f40a1ef763756edd91ce
treef9bd61eb3c321c269d60169abcd1f063df4d3979
parentac10841fa9321c71fa0e682521dd39872d43c132

stage2 .debug_line stepping with gdb is working


4 files changed, 100 insertions(+), 44 deletions(-)

lib/std/zig.zig+13-6
......@@ -43,12 +43,19 @@ pub fn findLineColumn(source: []const u8, byte_offset: usize) struct { line: usi
4343 return .{ .line = line, .column = column };
4444}
4545
46pub fn lineDelta(source: []const u8, start: usize, end: usize) usize {
47 var line: usize = 0;
48 for (source[start..end]) |byte| switch (byte) {
49 '\n' => line += 1,
50 else => continue,
51 };
46pub fn lineDelta(source: []const u8, start: usize, end: usize) isize {
47 var line: isize = 0;
48 if (end >= start) {
49 for (source[start..end]) |byte| switch (byte) {
50 '\n' => line += 1,
51 else => continue,
52 };
53 } else {
54 for (source[end..start]) |byte| switch (byte) {
55 '\n' => line -= 1,
56 else => continue,
57 };
58 }
5259 return line;
5360}
5461
src-self-hosted/Module.zig+3
......@@ -1484,6 +1484,9 @@ fn getAstTree(self: *Module, root_scope: *Scope.File) !*ast.Tree {
14841484}
14851485
14861486fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {
1487 const tracy = trace(@src());
1488 defer tracy.end();
1489
14871490 // We may be analyzing it for the first time, or this may be
14881491 // an incremental update. This code handles both cases.
14891492 const tree = try self.getAstTree(root_scope);
src-self-hosted/codegen.zig+14-7
......@@ -225,6 +225,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
225225 prev_di_src: usize,
226226 /// Relative to the beginning of `code`.
227227 prev_di_pc: usize,
228 /// The is_stmt register value, used to avoid redundant LNS_negate_stmt ops.
229 prev_di_is_stmt: bool,
228230 /// Used to find newlines and count line deltas.
229231 source: []const u8,
230232 /// Byte offset within the source file of the ending curly.
......@@ -420,6 +422,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
420422 .stack_align = undefined,
421423 .prev_di_pc = 0,
422424 .prev_di_src = lbrace_src,
425 .prev_di_is_stmt = true,
423426 .rbrace_src = rbrace_src,
424427 .source = tree.source,
425428 };
......@@ -523,7 +526,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
523526 },
524527 }
525528 // Drop them off at the rbrace.
526 try self.dbgAdvancePCAndLine(self.rbrace_src);
529 try self.dbgAdvancePCAndLine(self.rbrace_src, true);
527530 }
528531
529532 fn genBody(self: *Self, body: ir.Body) InnerError!void {
......@@ -542,15 +545,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
542545
543546 fn dbgSetPrologueEnd(self: *Self) InnerError!void {
544547 try self.dbg_line.append(DW.LNS_set_prologue_end);
545 try self.dbgAdvancePCAndLine(self.prev_di_src);
548 try self.dbgAdvancePCAndLine(self.prev_di_src, true);
546549 }
547550
548551 fn dbgSetEpilogueBegin(self: *Self) InnerError!void {
549552 try self.dbg_line.append(DW.LNS_set_epilogue_begin);
550 try self.dbgAdvancePCAndLine(self.prev_di_src);
553 try self.dbgAdvancePCAndLine(self.prev_di_src, true);
551554 }
552555
553 fn dbgAdvancePCAndLine(self: *Self, src: usize) InnerError!void {
556 fn dbgAdvancePCAndLine(self: *Self, src: usize, is_stmt: bool) InnerError!void {
554557 // TODO Look into improving the performance here by adding a token-index-to-line
555558 // lookup table, and changing ir.Inst from storing byte offset to token. Currently
556559 // this involves scanning over the source code for newlines
......@@ -562,12 +565,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
562565 // TODO Look into using the DWARF special opcodes to compress this data. It lets you emit
563566 // single-byte opcodes that add different numbers to both the PC and the line number
564567 // at the same time.
565 try self.dbg_line.ensureCapacity(self.dbg_line.items.len + 11);
568 try self.dbg_line.ensureCapacity(self.dbg_line.items.len + 12);
569 if (self.prev_di_is_stmt != is_stmt) {
570 self.dbg_line.appendAssumeCapacity(DW.LNS_negate_stmt);
571 self.prev_di_is_stmt = is_stmt;
572 }
566573 self.dbg_line.appendAssumeCapacity(DW.LNS_advance_pc);
567574 leb128.writeULEB128(self.dbg_line.writer(), delta_pc) catch unreachable;
568575 if (delta_line != 0) {
569576 self.dbg_line.appendAssumeCapacity(DW.LNS_advance_line);
570 leb128.writeULEB128(self.dbg_line.writer(), delta_line) catch unreachable;
577 leb128.writeILEB128(self.dbg_line.writer(), delta_line) catch unreachable;
571578 }
572579 self.dbg_line.appendAssumeCapacity(DW.LNS_copy);
573580 }
......@@ -1172,7 +1179,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
11721179 }
11731180
11741181 fn genDbgStmt(self: *Self, inst: *ir.Inst.NoOp) !MCValue {
1175 try self.dbgAdvancePCAndLine(inst.base.src);
1182 try self.dbgAdvancePCAndLine(inst.base.src, true);
11761183 return MCValue.none;
11771184 }
11781185
src-self-hosted/link.zig+70-31
......@@ -1263,7 +1263,7 @@ pub const File = struct {
12631263 @panic("TODO: handle .debug_line header exceeding its padding");
12641264 }
12651265 const jmp_amt = dbg_line_prg_off - di_buf.items.len;
1266 try self.pwriteWithNops(di_buf.items, jmp_amt, debug_line_sect.sh_offset);
1266 try self.pwriteWithNops(0, di_buf.items, jmp_amt, debug_line_sect.sh_offset);
12671267 self.debug_line_header_dirty = false;
12681268 }
12691269
......@@ -1958,12 +1958,13 @@ pub const File = struct {
19581958 self.shdr_table_dirty = true; // TODO look into making only the one section dirty
19591959 self.debug_line_header_dirty = true;
19601960 }
1961 const padding_size: u32 = if (src_fn.next) |next| next.off - (src_fn.off + src_fn.len) else 0;
1961 const prev_padding_size: u32 = if (src_fn.prev) |prev| src_fn.off - (prev.off + prev.len) else 0;
1962 const next_padding_size: u32 = if (src_fn.next) |next| next.off - (src_fn.off + src_fn.len) else 0;
19621963
19631964 // We only have support for one compilation unit so far, so the offsets are directly
19641965 // from the .debug_line section.
19651966 const file_pos = debug_line_sect.sh_offset + src_fn.off;
1966 try self.pwriteWithNops(dbg_line_buffer.items, padding_size, file_pos);
1967 try self.pwriteWithNops(prev_padding_size, dbg_line_buffer.items, next_padding_size, file_pos);
19671968 }
19681969
19691970 // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated.
......@@ -2282,44 +2283,82 @@ pub const File = struct {
22822283
22832284 }
22842285
2285 /// Writes to the file a buffer, followed by the specified number of bytes of NOPs.
2286 /// Asserts `padding_size >= 2` and less than 126,976 bytes (if this limit is ever
2287 /// reached, this function can be improved to make more than one pwritev call).
2288 fn pwriteWithNops(self: *Elf, buf: []const u8, padding_size: usize, offset: usize) !void {
2286 /// Writes to the file a buffer, prefixed and suffixed by the specified number of
2287 /// bytes of NOPs. Asserts each padding size is at least two bytes and total padding bytes
2288 /// are less than 126,976 bytes (if this limit is ever reached, this function can be
2289 /// improved to make more than one pwritev call, or the limit can be raised by a fixed
2290 /// amount by increasing the length of `vecs`).
2291 fn pwriteWithNops(
2292 self: *Elf,
2293 prev_padding_size: usize,
2294 buf: []const u8,
2295 next_padding_size: usize,
2296 offset: usize,
2297 ) !void {
22892298 const page_of_nops = [1]u8{DW.LNS_negate_stmt} ** 4096;
22902299 const three_byte_nop = [3]u8{DW.LNS_advance_pc, 0b1000_0000, 0};
22912300 var vecs: [32]std.os.iovec_const = undefined;
22922301 var vec_index: usize = 0;
2302 {
2303 var padding_left = prev_padding_size;
2304 if (padding_left % 2 != 0) {
2305 vecs[vec_index] = .{
2306 .iov_base = &three_byte_nop,
2307 .iov_len = three_byte_nop.len,
2308 };
2309 vec_index += 1;
2310 padding_left -= three_byte_nop.len;
2311 }
2312 while (padding_left > page_of_nops.len) {
2313 vecs[vec_index] = .{
2314 .iov_base = &page_of_nops,
2315 .iov_len = page_of_nops.len,
2316 };
2317 vec_index += 1;
2318 padding_left -= page_of_nops.len;
2319 }
2320 if (padding_left > 0) {
2321 vecs[vec_index] = .{
2322 .iov_base = &page_of_nops,
2323 .iov_len = padding_left,
2324 };
2325 vec_index += 1;
2326 }
2327 }
2328
22932329 vecs[vec_index] = .{
22942330 .iov_base = buf.ptr,
22952331 .iov_len = buf.len,
22962332 };
22972333 vec_index += 1;
2298 var padding_left = padding_size;
2299 if (padding_left % 2 != 0) {
2300 vecs[vec_index] = .{
2301 .iov_base = &three_byte_nop,
2302 .iov_len = three_byte_nop.len,
2303 };
2304 vec_index += 1;
2305 padding_left -= three_byte_nop.len;
2306 }
2307 while (padding_left > page_of_nops.len) {
2308 vecs[vec_index] = .{
2309 .iov_base = &page_of_nops,
2310 .iov_len = page_of_nops.len,
2311 };
2312 vec_index += 1;
2313 padding_left -= page_of_nops.len;
2314 }
2315 if (padding_left > 0) {
2316 vecs[vec_index] = .{
2317 .iov_base = &page_of_nops,
2318 .iov_len = padding_left,
2319 };
2320 vec_index += 1;
2334
2335 {
2336 var padding_left = next_padding_size;
2337 if (padding_left % 2 != 0) {
2338 vecs[vec_index] = .{
2339 .iov_base = &three_byte_nop,
2340 .iov_len = three_byte_nop.len,
2341 };
2342 vec_index += 1;
2343 padding_left -= three_byte_nop.len;
2344 }
2345 while (padding_left > page_of_nops.len) {
2346 vecs[vec_index] = .{
2347 .iov_base = &page_of_nops,
2348 .iov_len = page_of_nops.len,
2349 };
2350 vec_index += 1;
2351 padding_left -= page_of_nops.len;
2352 }
2353 if (padding_left > 0) {
2354 vecs[vec_index] = .{
2355 .iov_base = &page_of_nops,
2356 .iov_len = padding_left,
2357 };
2358 vec_index += 1;
2359 }
23212360 }
2322 try self.file.?.pwritevAll(vecs[0..vec_index], offset);
2361 try self.file.?.pwritevAll(vecs[0..vec_index], offset - prev_padding_size);
23232362 }
23242363
23252364 };