mirror of
https://github.com/ziglang/zig.git
synced 2025-02-14 08:30:21 +00:00
debug: Fix parsing of DWARF info for BE machines
Tested with ppc32
This commit is contained in:
parent
1b1cbd9358
commit
72dca05f5c
@ -236,11 +236,11 @@ const LineNumberProgram = struct {
|
||||
}
|
||||
};
|
||||
|
||||
fn readInitialLength(in_stream: var, is_64: *bool) !u64 {
|
||||
const first_32_bits = try in_stream.readIntLittle(u32);
|
||||
fn readUnitLength(in_stream: var, endian: builtin.Endian, is_64: *bool) !u64 {
|
||||
const first_32_bits = try in_stream.readInt(u32, endian);
|
||||
is_64.* = (first_32_bits == 0xffffffff);
|
||||
if (is_64.*) {
|
||||
return in_stream.readIntLittle(u64);
|
||||
return in_stream.readInt(u64, endian);
|
||||
} else {
|
||||
if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo;
|
||||
// TODO this cast should not be needed
|
||||
@ -256,28 +256,36 @@ fn readAllocBytes(allocator: *mem.Allocator, in_stream: var, size: usize) ![]u8
|
||||
return buf;
|
||||
}
|
||||
|
||||
// TODO the noasyncs here are workarounds
|
||||
fn readAddress(in_stream: var, endian: builtin.Endian, is_64: bool) !u64 {
|
||||
return noasync if (is_64)
|
||||
try in_stream.readInt(u64, endian)
|
||||
else
|
||||
@as(u64, try in_stream.readInt(u32, endian));
|
||||
}
|
||||
|
||||
fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
|
||||
const buf = try readAllocBytes(allocator, in_stream, size);
|
||||
return FormValue{ .Block = buf };
|
||||
}
|
||||
|
||||
// TODO the noasyncs here are workarounds
|
||||
fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue {
|
||||
const block_len = try noasync in_stream.readVarInt(usize, builtin.Endian.Little, size);
|
||||
fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, endian: builtin.Endian, size: usize) !FormValue {
|
||||
const block_len = try noasync in_stream.readVarInt(usize, endian, size);
|
||||
return parseFormValueBlockLen(allocator, in_stream, block_len);
|
||||
}
|
||||
|
||||
fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, comptime size: i32) !FormValue {
|
||||
fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, endian: builtin.Endian, comptime size: i32) !FormValue {
|
||||
// TODO: Please forgive me, I've worked around zig not properly spilling some intermediate values here.
|
||||
// `noasync` should be removed from all the function calls once it is fixed.
|
||||
return FormValue{
|
||||
.Const = Constant{
|
||||
.signed = signed,
|
||||
.payload = switch (size) {
|
||||
1 => try noasync in_stream.readIntLittle(u8),
|
||||
2 => try noasync in_stream.readIntLittle(u16),
|
||||
4 => try noasync in_stream.readIntLittle(u32),
|
||||
8 => try noasync in_stream.readIntLittle(u64),
|
||||
1 => try noasync in_stream.readInt(u8, endian),
|
||||
2 => try noasync in_stream.readInt(u16, endian),
|
||||
4 => try noasync in_stream.readInt(u32, endian),
|
||||
8 => try noasync in_stream.readInt(u64, endian),
|
||||
-1 => blk: {
|
||||
if (signed) {
|
||||
const x = try noasync leb.readILEB128(i64, in_stream);
|
||||
@ -294,30 +302,13 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo
|
||||
}
|
||||
|
||||
// TODO the noasyncs here are workarounds
|
||||
fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 {
|
||||
return if (is_64) try noasync in_stream.readIntLittle(u64) else @as(u64, try noasync in_stream.readIntLittle(u32));
|
||||
}
|
||||
|
||||
// TODO the noasyncs here are workarounds
|
||||
fn parseFormValueTargetAddrSize(in_stream: var) !u64 {
|
||||
if (@sizeOf(usize) == 4) {
|
||||
// TODO this cast should not be needed
|
||||
return @as(u64, try noasync in_stream.readIntLittle(u32));
|
||||
} else if (@sizeOf(usize) == 8) {
|
||||
return noasync in_stream.readIntLittle(u64);
|
||||
} else {
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO the noasyncs here are workarounds
|
||||
fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, size: i32) !FormValue {
|
||||
fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, endian: builtin.Endian, size: i32) !FormValue {
|
||||
return FormValue{
|
||||
.Ref = switch (size) {
|
||||
1 => try noasync in_stream.readIntLittle(u8),
|
||||
2 => try noasync in_stream.readIntLittle(u16),
|
||||
4 => try noasync in_stream.readIntLittle(u32),
|
||||
8 => try noasync in_stream.readIntLittle(u64),
|
||||
1 => try noasync in_stream.readInt(u8, endian),
|
||||
2 => try noasync in_stream.readInt(u16, endian),
|
||||
4 => try noasync in_stream.readInt(u32, endian),
|
||||
8 => try noasync in_stream.readInt(u64, endian),
|
||||
-1 => try noasync leb.readULEB128(u64, in_stream),
|
||||
else => unreachable,
|
||||
},
|
||||
@ -325,23 +316,23 @@ fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, size: i32) !Form
|
||||
}
|
||||
|
||||
// TODO the noasyncs here are workarounds
|
||||
fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) anyerror!FormValue {
|
||||
fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, endian: builtin.Endian, is_64: bool) anyerror!FormValue {
|
||||
return switch (form_id) {
|
||||
FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) },
|
||||
FORM_block1 => parseFormValueBlock(allocator, in_stream, 1),
|
||||
FORM_block2 => parseFormValueBlock(allocator, in_stream, 2),
|
||||
FORM_block4 => parseFormValueBlock(allocator, in_stream, 4),
|
||||
FORM_addr => FormValue{ .Address = try readAddress(in_stream, endian, @sizeOf(usize) == 8) },
|
||||
FORM_block1 => parseFormValueBlock(allocator, in_stream, endian, 1),
|
||||
FORM_block2 => parseFormValueBlock(allocator, in_stream, endian, 2),
|
||||
FORM_block4 => parseFormValueBlock(allocator, in_stream, endian, 4),
|
||||
FORM_block => x: {
|
||||
const block_len = try noasync leb.readULEB128(usize, in_stream);
|
||||
return parseFormValueBlockLen(allocator, in_stream, block_len);
|
||||
},
|
||||
FORM_data1 => parseFormValueConstant(allocator, in_stream, false, 1),
|
||||
FORM_data2 => parseFormValueConstant(allocator, in_stream, false, 2),
|
||||
FORM_data4 => parseFormValueConstant(allocator, in_stream, false, 4),
|
||||
FORM_data8 => parseFormValueConstant(allocator, in_stream, false, 8),
|
||||
FORM_data1 => parseFormValueConstant(allocator, in_stream, false, endian, 1),
|
||||
FORM_data2 => parseFormValueConstant(allocator, in_stream, false, endian, 2),
|
||||
FORM_data4 => parseFormValueConstant(allocator, in_stream, false, endian, 4),
|
||||
FORM_data8 => parseFormValueConstant(allocator, in_stream, false, endian, 8),
|
||||
FORM_udata, FORM_sdata => {
|
||||
const signed = form_id == FORM_sdata;
|
||||
return parseFormValueConstant(allocator, in_stream, signed, -1);
|
||||
return parseFormValueConstant(allocator, in_stream, signed, endian, -1);
|
||||
},
|
||||
FORM_exprloc => {
|
||||
const size = try noasync leb.readULEB128(usize, in_stream);
|
||||
@ -350,25 +341,25 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
|
||||
},
|
||||
FORM_flag => FormValue{ .Flag = (try noasync in_stream.readByte()) != 0 },
|
||||
FORM_flag_present => FormValue{ .Flag = true },
|
||||
FORM_sec_offset => FormValue{ .SecOffset = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
|
||||
FORM_sec_offset => FormValue{ .SecOffset = try readAddress(in_stream, endian, is_64) },
|
||||
|
||||
FORM_ref1 => parseFormValueRef(allocator, in_stream, 1),
|
||||
FORM_ref2 => parseFormValueRef(allocator, in_stream, 2),
|
||||
FORM_ref4 => parseFormValueRef(allocator, in_stream, 4),
|
||||
FORM_ref8 => parseFormValueRef(allocator, in_stream, 8),
|
||||
FORM_ref_udata => parseFormValueRef(allocator, in_stream, -1),
|
||||
FORM_ref1 => parseFormValueRef(allocator, in_stream, endian, 1),
|
||||
FORM_ref2 => parseFormValueRef(allocator, in_stream, endian, 2),
|
||||
FORM_ref4 => parseFormValueRef(allocator, in_stream, endian, 4),
|
||||
FORM_ref8 => parseFormValueRef(allocator, in_stream, endian, 8),
|
||||
FORM_ref_udata => parseFormValueRef(allocator, in_stream, endian, -1),
|
||||
|
||||
FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
|
||||
FORM_ref_sig8 => FormValue{ .Ref = try noasync in_stream.readIntLittle(u64) },
|
||||
FORM_ref_addr => FormValue{ .RefAddr = try readAddress(in_stream, endian, is_64) },
|
||||
FORM_ref_sig8 => FormValue{ .Ref = try noasync in_stream.readInt(u64, endian) },
|
||||
|
||||
FORM_string => FormValue{ .String = try in_stream.readUntilDelimiterAlloc(allocator, 0, math.maxInt(usize)) },
|
||||
FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
|
||||
FORM_strp => FormValue{ .StrPtr = try readAddress(in_stream, endian, is_64) },
|
||||
FORM_indirect => {
|
||||
const child_form_id = try noasync leb.readULEB128(u64, in_stream);
|
||||
const F = @TypeOf(async parseFormValue(allocator, in_stream, child_form_id, is_64));
|
||||
const F = @TypeOf(async parseFormValue(allocator, in_stream, child_form_id, endian, is_64));
|
||||
var frame = try allocator.create(F);
|
||||
defer allocator.destroy(frame);
|
||||
return await @asyncCall(frame, {}, parseFormValue, allocator, in_stream, child_form_id, is_64);
|
||||
return await @asyncCall(frame, {}, parseFormValue, allocator, in_stream, child_form_id, endian, is_64);
|
||||
},
|
||||
else => error.InvalidDebugInfo,
|
||||
};
|
||||
@ -423,7 +414,7 @@ pub const DwarfInfo = struct {
|
||||
};
|
||||
|
||||
var is_64: bool = undefined;
|
||||
const unit_length = try readInitialLength(in, &is_64);
|
||||
const unit_length = try readUnitLength(in, di.endian, &is_64);
|
||||
if (unit_length == 0) return;
|
||||
const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4));
|
||||
|
||||
@ -530,7 +521,7 @@ pub const DwarfInfo = struct {
|
||||
};
|
||||
|
||||
var is_64: bool = undefined;
|
||||
const unit_length = try readInitialLength(in, &is_64);
|
||||
const unit_length = try readUnitLength(in, di.endian, &is_64);
|
||||
if (unit_length == 0) return;
|
||||
const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4));
|
||||
|
||||
@ -610,8 +601,8 @@ pub const DwarfInfo = struct {
|
||||
try seekable.seekTo(ranges_offset);
|
||||
|
||||
while (true) {
|
||||
const begin_addr = try in.readIntLittle(usize);
|
||||
const end_addr = try in.readIntLittle(usize);
|
||||
const begin_addr = try in.readInt(usize, di.endian);
|
||||
const end_addr = try in.readInt(usize, di.endian);
|
||||
if (begin_addr == 0 and end_addr == 0) {
|
||||
break;
|
||||
}
|
||||
@ -693,7 +684,7 @@ pub const DwarfInfo = struct {
|
||||
for (table_entry.attrs.span()) |attr, i| {
|
||||
result.attrs.items[i] = Die.Attr{
|
||||
.id = attr.attr_id,
|
||||
.value = try parseFormValue(di.allocator(), in_stream, attr.form_id, is_64),
|
||||
.value = try parseFormValue(di.allocator(), in_stream, attr.form_id, di.endian, is_64),
|
||||
};
|
||||
}
|
||||
return result;
|
||||
@ -710,7 +701,7 @@ pub const DwarfInfo = struct {
|
||||
try seekable.seekTo(line_info_offset);
|
||||
|
||||
var is_64: bool = undefined;
|
||||
const unit_length = try readInitialLength(in, &is_64);
|
||||
const unit_length = try readUnitLength(in, di.endian, &is_64);
|
||||
if (unit_length == 0) {
|
||||
return error.MissingDebugInfo;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user