mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 14:25:16 +00:00
- rework CFI instruction parsing to not use std.meta
- move register formatting code to zig-dwardump
This commit is contained in:
parent
e72e762d1e
commit
c98e03fc7e
@ -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 } };
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user