Commit c98e03fc7e

kcbanner <kcbanner@gmail.com>
2023-05-22 23:59:20
- rework CFI instruction parsing to not use std.meta - move register formatting code to zig-dwardump
1 parent e72e762
Changed files (2)
lib
lib/std/dwarf/abi.zig
@@ -25,21 +25,6 @@ pub fn fpRegNum(reg_ctx: RegisterContext) u8 {
         .x86_64 => 6,
         .arm => 11,
         .aarch64 => 29,
-
-        // const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr));
-        // const ip = switch (native_os) {
-        //     .macos => @intCast(usize, ctx.mcontext.ss.pc),
-        //     .netbsd => @intCast(usize, ctx.mcontext.gregs[os.REG.PC]),
-        //     .freebsd => @intCast(usize, ctx.mcontext.gpregs.elr),
-        //     else => @intCast(usize, ctx.mcontext.pc),
-        // };
-        // // x29 is the ABI-designated frame pointer
-        // const bp = switch (native_os) {
-        //     .macos => @intCast(usize, ctx.mcontext.ss.fp),
-        //     .netbsd => @intCast(usize, ctx.mcontext.gregs[os.REG.FP]),
-        //     .freebsd => @intCast(usize, ctx.mcontext.gpregs.x[os.REG.FP]),
-        //     else => @intCast(usize, ctx.mcontext.regs[29]),
-        // };
         else => unreachable,
     };
 }
@@ -231,7 +216,10 @@ pub fn regBytes(ucontext_ptr: anytype, reg_number: u8, reg_ctx: ?RegisterContext
                 0...29 => mem.asBytes(&ucontext_ptr.mcontext.gpregs.x[reg_number]),
                 30 => mem.asBytes(&ucontext_ptr.mcontext.gpregs.lr),
                 31 => mem.asBytes(&ucontext_ptr.mcontext.gpregs.sp),
-                32 => mem.asBytes(&ucontext_ptr.mcontext.gpregs.elr), // TODO: This seems wrong, but it was in the old debug.zig code for PC, check this
+
+                // TODO: This seems wrong, but it was in the previous debug.zig code for mapping PC, check this
+                32 => mem.asBytes(&ucontext_ptr.mcontext.gpregs.elr),
+
                 else => error.InvalidRegister,
             },
             else => switch (reg_number) {
@@ -252,76 +240,3 @@ pub fn getRegDefaultValue(reg_number: u8, out: []u8) void {
     _ = reg_number;
     @memset(out, undefined);
 }
-
-fn writeUnknownReg(writer: anytype, reg_number: u8) !void {
-    try writer.print("reg{}", .{reg_number});
-}
-
-pub fn writeRegisterName(writer: anytype, arch: ?std.Target.Cpu.Arch, reg_number: u8) !void {
-    if (arch) |a| {
-        switch (a) {
-            .x86_64 => {
-                switch (reg_number) {
-                    0 => try writer.writeAll("RAX"),
-                    1 => try writer.writeAll("RDX"),
-                    2 => try writer.writeAll("RCX"),
-                    3 => try writer.writeAll("RBX"),
-                    4 => try writer.writeAll("RSI"),
-                    5 => try writer.writeAll("RDI"),
-                    6 => try writer.writeAll("RBP"),
-                    7 => try writer.writeAll("RSP"),
-                    8...15 => try writer.print("R{}", .{reg_number}),
-                    16 => try writer.writeAll("RIP"),
-                    17...32 => try writer.print("XMM{}", .{reg_number - 17}),
-                    33...40 => try writer.print("ST{}", .{reg_number - 33}),
-                    41...48 => try writer.print("MM{}", .{reg_number - 41}),
-                    49 => try writer.writeAll("RFLAGS"),
-                    50 => try writer.writeAll("ES"),
-                    51 => try writer.writeAll("CS"),
-                    52 => try writer.writeAll("SS"),
-                    53 => try writer.writeAll("DS"),
-                    54 => try writer.writeAll("FS"),
-                    55 => try writer.writeAll("GS"),
-                    // 56-57 Reserved
-                    58 => try writer.writeAll("FS.BASE"),
-                    59 => try writer.writeAll("GS.BASE"),
-                    // 60-61 Reserved
-                    62 => try writer.writeAll("TR"),
-                    63 => try writer.writeAll("LDTR"),
-                    64 => try writer.writeAll("MXCSR"),
-                    65 => try writer.writeAll("FCW"),
-                    66 => try writer.writeAll("FSW"),
-                    67...82 => try writer.print("XMM{}", .{reg_number - 51}),
-                    // 83-117 Reserved
-                    118...125 => try writer.print("K{}", .{reg_number - 118}),
-                    // 126-129 Reserved
-                    else => try writeUnknownReg(writer, reg_number),
-                }
-            },
-
-            // TODO: Add x86, aarch64
-
-            else => try writeUnknownReg(writer, reg_number),
-        }
-    } else try writeUnknownReg(writer, reg_number);
-}
-
-const FormatRegisterData = struct {
-    reg_number: u8,
-    arch: ?std.Target.Cpu.Arch,
-};
-
-pub fn formatRegister(
-    data: FormatRegisterData,
-    comptime fmt: []const u8,
-    options: std.fmt.FormatOptions,
-    writer: anytype,
-) !void {
-    _ = fmt;
-    _ = options;
-    try writeRegisterName(writer, data.arch, data.reg_number);
-}
-
-pub fn fmtRegister(reg_number: u8, arch: ?std.Target.Cpu.Arch) std.fmt.Formatter(formatRegister) {
-    return .{ .data = .{ .reg_number = reg_number, .arch = arch } };
-}
lib/std/dwarf/call_frame.zig
@@ -38,12 +38,12 @@ const Opcode = enum(u8) {
     val_expression = 0x16,
 
     // These opcodes encode an operand in the lower 6 bits of the opcode itself
-    pub const lo_inline = Opcode.advance_loc;
+    pub const lo_inline = @enumToInt(Opcode.advance_loc);
     pub const hi_inline = @enumToInt(Opcode.restore) | 0b111111;
 
     // These opcodes are trailed by zero or more operands
-    pub const lo_reserved = Opcode.nop;
-    pub const hi_reserved = Opcode.val_expression;
+    pub const lo_reserved = @enumToInt(Opcode.nop);
+    pub const hi_reserved = @enumToInt(Opcode.val_expression);
 
     // Vendor-specific opcodes
     pub const lo_user = 0x1c;
@@ -187,28 +187,40 @@ pub const Instruction = union(Opcode) {
     val_offset_sf: InstructionType(.{ .a = .uleb128_offset, .b = .sleb128_offset }),
     val_expression: InstructionType(.{ .a = .uleb128_offset, .block = .block }),
 
+    fn readOperands(
+        self: *Instruction,
+        stream: *std.io.FixedBufferStream([]const u8),
+        opcode_value: ?u6,
+        addr_size_bytes: u8,
+        endian: std.builtin.Endian,
+    ) !void {
+        switch (self.*) {
+            inline else => |*inst| inst.* = try @TypeOf(inst.*).read(stream, opcode_value, addr_size_bytes, endian),
+        }
+    }
+
     pub fn read(
         stream: *std.io.FixedBufferStream([]const u8),
         addr_size_bytes: u8,
         endian: std.builtin.Endian,
     ) !Instruction {
-        @setEvalBranchQuota(1800);
-
         return switch (try stream.reader().readByte()) {
-            inline @enumToInt(Opcode.lo_inline)...Opcode.hi_inline => |opcode| blk: {
+            inline Opcode.lo_inline...Opcode.hi_inline => |opcode| blk: {
                 const e = @intToEnum(Opcode, opcode & 0b11000000);
-                const payload_type = std.meta.TagPayload(Instruction, e);
-                const value = try payload_type.read(stream, @intCast(u6, opcode & 0b111111), addr_size_bytes, endian);
-                break :blk @unionInit(Instruction, @tagName(e), value);
+                var result = @unionInit(Instruction, @tagName(e), undefined);
+                try result.readOperands(stream, @intCast(u6, opcode & 0b111111), addr_size_bytes, endian);
+                break :blk result;
             },
-            inline @enumToInt(Opcode.lo_reserved)...@enumToInt(Opcode.hi_reserved) => |opcode| blk: {
+            inline Opcode.lo_reserved...Opcode.hi_reserved => |opcode| blk: {
                 const e = @intToEnum(Opcode, opcode);
-                const payload_type = std.meta.TagPayload(Instruction, e);
-                const value = try payload_type.read(stream, null, addr_size_bytes, endian);
-                break :blk @unionInit(Instruction, @tagName(e), value);
+                var result = @unionInit(Instruction, @tagName(e), undefined);
+                try result.readOperands(stream, null, addr_size_bytes, endian);
+                break :blk result;
             },
             Opcode.lo_user...Opcode.hi_user => error.UnimplementedUserOpcode,
             else => |opcode| blk: {
+
+                // TODO: Remove this
                 std.debug.print("Opcode {x}\n", .{opcode});
 
                 break :blk error.InvalidOpcode;