authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-05-22 17:59:20-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-07-20 22:58:13-04:00
logc98e03fc7ed509536076132fe9ea5d9d00038c23
tree7c96643cc53c6176722584d4d0d723cf20d849dc
parente72e762d1e81b06c38902348a3f6625a85e1dce0

- rework CFI instruction parsing to not use std.meta

- move register formatting code to zig-dwardump

2 files changed, 29 insertions(+), 102 deletions(-)

lib/std/dwarf/abi.zig+4-89
......@@ -25,21 +25,6 @@ pub fn fpRegNum(reg_ctx: RegisterContext) u8 {
2525 .x86_64 => 6,
2626 .arm => 11,
2727 .aarch64 => 29,
28
29 // const ctx = @ptrCast(*const os.ucontext_t, @alignCast(@alignOf(os.ucontext_t), ctx_ptr));
30 // const ip = switch (native_os) {
31 // .macos => @intCast(usize, ctx.mcontext.ss.pc),
32 // .netbsd => @intCast(usize, ctx.mcontext.gregs[os.REG.PC]),
33 // .freebsd => @intCast(usize, ctx.mcontext.gpregs.elr),
34 // else => @intCast(usize, ctx.mcontext.pc),
35 // };
36 // // x29 is the ABI-designated frame pointer
37 // const bp = switch (native_os) {
38 // .macos => @intCast(usize, ctx.mcontext.ss.fp),
39 // .netbsd => @intCast(usize, ctx.mcontext.gregs[os.REG.FP]),
40 // .freebsd => @intCast(usize, ctx.mcontext.gpregs.x[os.REG.FP]),
41 // else => @intCast(usize, ctx.mcontext.regs[29]),
42 // };
4328 else => unreachable,
4429 };
4530}
......@@ -231,7 +216,10 @@ pub fn regBytes(ucontext_ptr: anytype, reg_number: u8, reg_ctx: ?RegisterContext
231216 0...29 => mem.asBytes(&ucontext_ptr.mcontext.gpregs.x[reg_number]),
232217 30 => mem.asBytes(&ucontext_ptr.mcontext.gpregs.lr),
233218 31 => mem.asBytes(&ucontext_ptr.mcontext.gpregs.sp),
234 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
219
220 // TODO: This seems wrong, but it was in the previous debug.zig code for mapping PC, check this
221 32 => mem.asBytes(&ucontext_ptr.mcontext.gpregs.elr),
222
235223 else => error.InvalidRegister,
236224 },
237225 else => switch (reg_number) {
......@@ -252,76 +240,3 @@ pub fn getRegDefaultValue(reg_number: u8, out: []u8) void {
252240 _ = reg_number;
253241 @memset(out, undefined);
254242}
255
256fn writeUnknownReg(writer: anytype, reg_number: u8) !void {
257 try writer.print("reg{}", .{reg_number});
258}
259
260pub fn writeRegisterName(writer: anytype, arch: ?std.Target.Cpu.Arch, reg_number: u8) !void {
261 if (arch) |a| {
262 switch (a) {
263 .x86_64 => {
264 switch (reg_number) {
265 0 => try writer.writeAll("RAX"),
266 1 => try writer.writeAll("RDX"),
267 2 => try writer.writeAll("RCX"),
268 3 => try writer.writeAll("RBX"),
269 4 => try writer.writeAll("RSI"),
270 5 => try writer.writeAll("RDI"),
271 6 => try writer.writeAll("RBP"),
272 7 => try writer.writeAll("RSP"),
273 8...15 => try writer.print("R{}", .{reg_number}),
274 16 => try writer.writeAll("RIP"),
275 17...32 => try writer.print("XMM{}", .{reg_number - 17}),
276 33...40 => try writer.print("ST{}", .{reg_number - 33}),
277 41...48 => try writer.print("MM{}", .{reg_number - 41}),
278 49 => try writer.writeAll("RFLAGS"),
279 50 => try writer.writeAll("ES"),
280 51 => try writer.writeAll("CS"),
281 52 => try writer.writeAll("SS"),
282 53 => try writer.writeAll("DS"),
283 54 => try writer.writeAll("FS"),
284 55 => try writer.writeAll("GS"),
285 // 56-57 Reserved
286 58 => try writer.writeAll("FS.BASE"),
287 59 => try writer.writeAll("GS.BASE"),
288 // 60-61 Reserved
289 62 => try writer.writeAll("TR"),
290 63 => try writer.writeAll("LDTR"),
291 64 => try writer.writeAll("MXCSR"),
292 65 => try writer.writeAll("FCW"),
293 66 => try writer.writeAll("FSW"),
294 67...82 => try writer.print("XMM{}", .{reg_number - 51}),
295 // 83-117 Reserved
296 118...125 => try writer.print("K{}", .{reg_number - 118}),
297 // 126-129 Reserved
298 else => try writeUnknownReg(writer, reg_number),
299 }
300 },
301
302 // TODO: Add x86, aarch64
303
304 else => try writeUnknownReg(writer, reg_number),
305 }
306 } else try writeUnknownReg(writer, reg_number);
307}
308
309const FormatRegisterData = struct {
310 reg_number: u8,
311 arch: ?std.Target.Cpu.Arch,
312};
313
314pub fn formatRegister(
315 data: FormatRegisterData,
316 comptime fmt: []const u8,
317 options: std.fmt.FormatOptions,
318 writer: anytype,
319) !void {
320 _ = fmt;
321 _ = options;
322 try writeRegisterName(writer, data.arch, data.reg_number);
323}
324
325pub fn fmtRegister(reg_number: u8, arch: ?std.Target.Cpu.Arch) std.fmt.Formatter(formatRegister) {
326 return .{ .data = .{ .reg_number = reg_number, .arch = arch } };
327}
lib/std/dwarf/call_frame.zig+25-13
......@@ -38,12 +38,12 @@ const Opcode = enum(u8) {
3838 val_expression = 0x16,
3939
4040 // These opcodes encode an operand in the lower 6 bits of the opcode itself
41 pub const lo_inline = Opcode.advance_loc;
41 pub const lo_inline = @enumToInt(Opcode.advance_loc);
4242 pub const hi_inline = @enumToInt(Opcode.restore) | 0b111111;
4343
4444 // These opcodes are trailed by zero or more operands
45 pub const lo_reserved = Opcode.nop;
46 pub const hi_reserved = Opcode.val_expression;
45 pub const lo_reserved = @enumToInt(Opcode.nop);
46 pub const hi_reserved = @enumToInt(Opcode.val_expression);
4747
4848 // Vendor-specific opcodes
4949 pub const lo_user = 0x1c;
......@@ -187,28 +187,40 @@ pub const Instruction = union(Opcode) {
187187 val_offset_sf: InstructionType(.{ .a = .uleb128_offset, .b = .sleb128_offset }),
188188 val_expression: InstructionType(.{ .a = .uleb128_offset, .block = .block }),
189189
190 fn readOperands(
191 self: *Instruction,
192 stream: *std.io.FixedBufferStream([]const u8),
193 opcode_value: ?u6,
194 addr_size_bytes: u8,
195 endian: std.builtin.Endian,
196 ) !void {
197 switch (self.*) {
198 inline else => |*inst| inst.* = try @TypeOf(inst.*).read(stream, opcode_value, addr_size_bytes, endian),
199 }
200 }
201
190202 pub fn read(
191203 stream: *std.io.FixedBufferStream([]const u8),
192204 addr_size_bytes: u8,
193205 endian: std.builtin.Endian,
194206 ) !Instruction {
195 @setEvalBranchQuota(1800);
196
197207 return switch (try stream.reader().readByte()) {
198 inline @enumToInt(Opcode.lo_inline)...Opcode.hi_inline => |opcode| blk: {
208 inline Opcode.lo_inline...Opcode.hi_inline => |opcode| blk: {
199209 const e = @intToEnum(Opcode, opcode & 0b11000000);
200 const payload_type = std.meta.TagPayload(Instruction, e);
201 const value = try payload_type.read(stream, @intCast(u6, opcode & 0b111111), addr_size_bytes, endian);
202 break :blk @unionInit(Instruction, @tagName(e), value);
210 var result = @unionInit(Instruction, @tagName(e), undefined);
211 try result.readOperands(stream, @intCast(u6, opcode & 0b111111), addr_size_bytes, endian);
212 break :blk result;
203213 },
204 inline @enumToInt(Opcode.lo_reserved)...@enumToInt(Opcode.hi_reserved) => |opcode| blk: {
214 inline Opcode.lo_reserved...Opcode.hi_reserved => |opcode| blk: {
205215 const e = @intToEnum(Opcode, opcode);
206 const payload_type = std.meta.TagPayload(Instruction, e);
207 const value = try payload_type.read(stream, null, addr_size_bytes, endian);
208 break :blk @unionInit(Instruction, @tagName(e), value);
216 var result = @unionInit(Instruction, @tagName(e), undefined);
217 try result.readOperands(stream, null, addr_size_bytes, endian);
218 break :blk result;
209219 },
210220 Opcode.lo_user...Opcode.hi_user => error.UnimplementedUserOpcode,
211221 else => |opcode| blk: {
222
223 // TODO: Remove this
212224 std.debug.print("Opcode {x}\n", .{opcode});
213225
214226 break :blk error.InvalidOpcode;