authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-05-09 02:24:57-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-07-20 22:58:13-04:00
log338df862d147986c797902706967b3dae7c95cd6
tree74395d320108f6444f95a1c77d85256dd64a7675
parentf3f3c877e0da444e6e5208d7c7179776ddb8ecd8

- fix remember_state

- implement def_cfa_register

1 files changed, 38 insertions(+), 45 deletions(-)

lib/std/dwarf/call_frame.zig+38-45
......@@ -233,17 +233,10 @@ pub const Instruction = union(Opcode) {
233233 .register => {},
234234 .remember_state => {},
235235 .restore_state => {},
236 .def_cfa => |i| {
237 try abi.writeRegisterName(writer, arch, i.operands.register);
238 try writer.print(" {d:<1}", .{@intCast(i64, i.operands.offset)});
239 },
240 .def_cfa_register => {},
241 .def_cfa_offset => |i| {
242 try writer.print("{d:<1}", .{@intCast(i64, i.operands.offset)});
243 },
244 .def_cfa_expression => |i| {
245 try writeExpression(writer, i.operands.block, arch, addr_size_bytes, endian);
246 },
236 .def_cfa => |i| try writer.print("{} {d:<1}", .{ abi.fmtRegister(i.operands.register, arch), @intCast(i64, i.operands.offset)}),
237 .def_cfa_register => |i| try abi.writeRegisterName(writer, arch, i.operands.register),
238 .def_cfa_offset => |i| try writer.print("{d:<1}", .{@intCast(i64, i.operands.offset)}),
239 .def_cfa_expression => |i| try writeExpression(writer, i.operands.block, arch, addr_size_bytes, endian),
247240 .expression => {},
248241 .offset_extended_sf => {},
249242 .def_cfa_sf => {},
......@@ -318,16 +311,6 @@ fn writeExpression(
318311 }
319312}
320313
321// fn formatOffset(data: i64, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
322// _ = fmt;
323// if (data >= 0) try writer.writeByte('+');
324// return std.fmt.formatInt(data, 10, .lower, options, writer);
325// }
326
327// fn fmtOffset(offset: i64) std.fmt.Formatter(formatOffset) {
328// return .{ .data = offset };
329// }
330
331314/// See section 6.4.1 of the DWARF5 specification
332315pub const VirtualMachine = struct {
333316 const RegisterRule = union(enum) {
......@@ -387,7 +370,7 @@ pub const VirtualMachine = struct {
387370 }
388371 };
389372
390 /// Each row contains unwinding rules for a set of registers at a specific location in the program.
373 /// Each row contains unwinding rules for a set of registers at a specific location in the
391374 pub const Row = struct {
392375 /// Offset from pc_begin
393376 offset: u64 = 0,
......@@ -395,31 +378,33 @@ pub const VirtualMachine = struct {
395378 /// The register field of this column defines the register that CFA is derived
396379 /// from, while other columns define registers in terms of the CFA.
397380 cfa: Column = .{},
381 columns: ColumnRange = .{},
382 };
383
384 const ColumnRange = struct {
398385 /// Index into `columns` of the first column in this row.
399 columns_start: usize = undefined,
400 columns_len: u8 = 0,
386 start: usize = undefined,
387 len: u8 = 0,
401388 };
402389
403390 columns: std.ArrayListUnmanaged(Column) = .{},
404 row_stack: std.ArrayListUnmanaged(Row) = .{},
391 stack: std.ArrayListUnmanaged(ColumnRange) = .{},
405392 current_row: Row = .{},
406393
407 // TODO: Add stack machine stack
408
409394 pub fn reset(self: *VirtualMachine) void {
410 self.row_stack.clearRetainingCapacity();
395 self.stack.clearRetainingCapacity();
411396 self.columns.clearRetainingCapacity();
412397 self.current_row = .{};
413398 }
414399
415400 pub fn deinit(self: *VirtualMachine, allocator: std.mem.Allocator) void {
416 self.row_stack.deinit(allocator);
401 self.stack.deinit(allocator);
417402 self.columns.deinit(allocator);
418403 self.* = undefined;
419404 }
420405
421406 pub fn getColumns(self: VirtualMachine, row: Row) []Column {
422 return self.columns.items[row.columns_start..][0..row.columns_len];
407 return self.columns.items[row.columns.start..][0..row.columns.len];
423408 }
424409
425410 fn getOrAddColumn(self: *VirtualMachine, allocator: std.mem.Allocator, register: u8) !*Column {
......@@ -427,10 +412,10 @@ pub const VirtualMachine = struct {
427412 if (c.register == register) return c;
428413 }
429414
430 if (self.current_row.columns_len == 0) {
431 self.current_row.columns_start = self.columns.items.len;
415 if (self.current_row.columns.len == 0) {
416 self.current_row.columns.start = self.columns.items.len;
432417 }
433 self.current_row.columns_len += 1;
418 self.current_row.columns.len += 1;
434419
435420 const column = try self.columns.addOne(allocator);
436421 column.* = .{
......@@ -443,7 +428,7 @@ pub const VirtualMachine = struct {
443428 pub fn step(self: *VirtualMachine, allocator: std.mem.Allocator, cie: dwarf.CommonInformationEntry, instruction: Instruction) !void {
444429 switch (instruction) {
445430 inline .advance_loc, .advance_loc1, .advance_loc2, .advance_loc4 => |i| {
446 self.current_row.offset += i.operands.delta;
431 self.current_row.offset += i.operands.delta * cie.code_alignment_factor;
447432 },
448433 .offset => |i| {
449434 const column = try self.getOrAddColumn(allocator, i.operands.register);
......@@ -458,18 +443,22 @@ pub const VirtualMachine = struct {
458443 .same_value => {},
459444 .register => {},
460445 .remember_state => {
461
462 // TODO: The row stack only actually needs the column information
463 // TODO: Also it needs to copy the columns because changes can edit the referenced columns
464 // TODO: This function could push the column range onto the stack, the copy the columns and update current row
465
466 try self.row_stack.append(allocator, self.current_row);
446 try self.stack.append(allocator, self.current_row.columns);
447 errdefer _ = self.stack.pop();
448
449 const new_start = self.columns.items.len;
450 if (self.current_row.columns.len > 0) {
451 // Since we're copying from the same backing array, ensure it won't be reallocated
452 try self.columns.ensureUnusedCapacity(allocator, self.current_row.columns.len);
453 self.columns.appendSliceAssumeCapacity(self.getColumns(self.current_row));
454 self.current_row.columns.start = new_start;
455 }
467456 },
468457 .restore_state => {
469 if (self.row_stack.items.len == 0) return error.InvalidOperation;
470 const row = self.row_stack.pop();
471 self.current_row.columns_len = row.columns_len;
472 self.current_row.columns_start = row.columns_start;
458 // TODO: Is it possible to remove the duplicate from above? Other instructions may have added columns since then though
459 const columns = self.stack.popOrNull() orelse return error.InvalidOperation;
460 self.current_row.columns.len = columns.len;
461 self.current_row.columns.start = columns.start;
473462 },
474463 .def_cfa => |i| {
475464 self.current_row.cfa = .{
......@@ -477,8 +466,12 @@ pub const VirtualMachine = struct {
477466 .rule = .{ .offset = @intCast(i64, i.operands.offset) },
478467 };
479468 },
480 .def_cfa_register => {},
469 .def_cfa_register => |i| {
470 // TODO: Verify the the current row is using a register and offset (validation)
471 self.current_row.cfa.register = i.operands.register;
472 },
481473 .def_cfa_offset => |i| {
474 // TODO: Verify the the current row is using a register and offset (validation)
482475 self.current_row.cfa.rule = .{ .offset = @intCast(i64, i.operands.offset) };
483476 },
484477 .def_cfa_expression => |i| {