Fix minor bug in LEB128 parsing
This commit is contained in:
155
std/debug.zig
155
std/debug.zig
@@ -13,6 +13,8 @@ const ArrayList = std.ArrayList;
|
||||
const builtin = @import("builtin");
|
||||
const maxInt = std.math.maxInt;
|
||||
|
||||
const leb = @import("debug/leb128.zig");
|
||||
|
||||
pub const FailingAllocator = @import("debug/failing_allocator.zig").FailingAllocator;
|
||||
pub const failing_allocator = &FailingAllocator.init(global_allocator, 0).allocator;
|
||||
|
||||
@@ -1460,7 +1462,7 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo
|
||||
2 => try in_stream.readIntLittle(u16),
|
||||
4 => try in_stream.readIntLittle(u32),
|
||||
8 => try in_stream.readIntLittle(u64),
|
||||
-1 => if (signed) @bitCast(u64, try readILeb128(in_stream)) else try readULeb128(in_stream),
|
||||
-1 => if (signed) @bitCast(u64, try leb.readILEB128(i64, in_stream)) else try leb.readULEB128(u64, in_stream),
|
||||
else => @compileError("Invalid size"),
|
||||
},
|
||||
},
|
||||
@@ -1482,7 +1484,7 @@ fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, size: i32) !Form
|
||||
2 => try in_stream.readIntLittle(u16),
|
||||
4 => try in_stream.readIntLittle(u32),
|
||||
8 => try in_stream.readIntLittle(u64),
|
||||
-1 => try readULeb128(in_stream),
|
||||
-1 => try leb.readULEB128(u64, in_stream),
|
||||
else => unreachable,
|
||||
},
|
||||
};
|
||||
@@ -1495,7 +1497,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
|
||||
DW.FORM_block2 => parseFormValueBlock(allocator, in_stream, 2),
|
||||
DW.FORM_block4 => parseFormValueBlock(allocator, in_stream, 4),
|
||||
DW.FORM_block => x: {
|
||||
const block_len = try readULeb128(in_stream);
|
||||
const block_len = try leb.readULEB128(usize, in_stream);
|
||||
return parseFormValueBlockLen(allocator, in_stream, block_len);
|
||||
},
|
||||
DW.FORM_data1 => parseFormValueConstant(allocator, in_stream, false, 1),
|
||||
@@ -1507,7 +1509,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
|
||||
return parseFormValueConstant(allocator, in_stream, signed, -1);
|
||||
},
|
||||
DW.FORM_exprloc => {
|
||||
const size = try readULeb128(in_stream);
|
||||
const size = try leb.readULEB128(usize, in_stream);
|
||||
const buf = try readAllocBytes(allocator, in_stream, size);
|
||||
return FormValue{ .ExprLoc = buf };
|
||||
},
|
||||
@@ -1527,7 +1529,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
|
||||
DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) },
|
||||
DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) },
|
||||
DW.FORM_indirect => {
|
||||
const child_form_id = try readULeb128(in_stream);
|
||||
const child_form_id = try leb.readULEB128(u64, in_stream);
|
||||
return parseFormValue(allocator, in_stream, child_form_id, is_64);
|
||||
},
|
||||
else => error.InvalidDebugInfo,
|
||||
@@ -1537,19 +1539,19 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
|
||||
fn parseAbbrevTable(di: *DwarfInfo) !AbbrevTable {
|
||||
var result = AbbrevTable.init(di.allocator());
|
||||
while (true) {
|
||||
const abbrev_code = try readULeb128(di.dwarf_in_stream);
|
||||
const abbrev_code = try leb.readULEB128(u64, di.dwarf_in_stream);
|
||||
if (abbrev_code == 0) return result;
|
||||
try result.append(AbbrevTableEntry{
|
||||
.abbrev_code = abbrev_code,
|
||||
.tag_id = try readULeb128(di.dwarf_in_stream),
|
||||
.tag_id = try leb.readULEB128(u64, di.dwarf_in_stream),
|
||||
.has_children = (try di.dwarf_in_stream.readByte()) == DW.CHILDREN_yes,
|
||||
.attrs = ArrayList(AbbrevAttr).init(di.allocator()),
|
||||
});
|
||||
const attrs = &result.items[result.len - 1].attrs;
|
||||
|
||||
while (true) {
|
||||
const attr_id = try readULeb128(di.dwarf_in_stream);
|
||||
const form_id = try readULeb128(di.dwarf_in_stream);
|
||||
const attr_id = try leb.readULEB128(u64, di.dwarf_in_stream);
|
||||
const form_id = try leb.readULEB128(u64, di.dwarf_in_stream);
|
||||
if (attr_id == 0 and form_id == 0) break;
|
||||
try attrs.append(AbbrevAttr{
|
||||
.attr_id = attr_id,
|
||||
@@ -1583,7 +1585,7 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con
|
||||
}
|
||||
|
||||
fn parseDie1(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !?Die {
|
||||
const abbrev_code = try readULeb128(di.dwarf_in_stream);
|
||||
const abbrev_code = try leb.readULEB128(u64, di.dwarf_in_stream);
|
||||
if (abbrev_code == 0) return null;
|
||||
const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo;
|
||||
|
||||
@@ -1603,7 +1605,7 @@ fn parseDie1(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !?Di
|
||||
}
|
||||
|
||||
fn parseDie(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die {
|
||||
const abbrev_code = try readULeb128(di.dwarf_in_stream);
|
||||
const abbrev_code = try leb.readULEB128(u64, di.dwarf_in_stream);
|
||||
const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo;
|
||||
|
||||
var result = Die{
|
||||
@@ -1716,9 +1718,9 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
|
||||
while (true) {
|
||||
const file_name = readStringMem(&ptr);
|
||||
if (file_name.len == 0) break;
|
||||
const dir_index = try readULeb128Mem(&ptr);
|
||||
const mtime = try readULeb128Mem(&ptr);
|
||||
const len_bytes = try readULeb128Mem(&ptr);
|
||||
const dir_index = try leb.readULEB128Mem(u64, &ptr);
|
||||
const mtime = try leb.readULEB128Mem(u64, &ptr);
|
||||
const len_bytes = try leb.readULEB128Mem(u64, &ptr);
|
||||
try file_entries.append(FileEntry{
|
||||
.file_name = file_name,
|
||||
.dir_index = dir_index,
|
||||
@@ -1732,7 +1734,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
|
||||
const opcode = readByteMem(&ptr);
|
||||
|
||||
if (opcode == DW.LNS_extended_op) {
|
||||
const op_size = try readULeb128Mem(&ptr);
|
||||
const op_size = try leb.readULEB128Mem(u64, &ptr);
|
||||
if (op_size < 1) return error.InvalidDebugInfo;
|
||||
var sub_op = readByteMem(&ptr);
|
||||
switch (sub_op) {
|
||||
@@ -1747,9 +1749,9 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
|
||||
},
|
||||
DW.LNE_define_file => {
|
||||
const file_name = readStringMem(&ptr);
|
||||
const dir_index = try readULeb128Mem(&ptr);
|
||||
const mtime = try readULeb128Mem(&ptr);
|
||||
const len_bytes = try readULeb128Mem(&ptr);
|
||||
const dir_index = try leb.readULEB128Mem(u64, &ptr);
|
||||
const mtime = try leb.readULEB128Mem(u64, &ptr);
|
||||
const len_bytes = try leb.readULEB128Mem(u64, &ptr);
|
||||
try file_entries.append(FileEntry{
|
||||
.file_name = file_name,
|
||||
.dir_index = dir_index,
|
||||
@@ -1777,19 +1779,19 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
|
||||
prog.basic_block = false;
|
||||
},
|
||||
DW.LNS_advance_pc => {
|
||||
const arg = try readULeb128Mem(&ptr);
|
||||
const arg = try leb.readULEB128Mem(u64, &ptr);
|
||||
prog.address += arg * minimum_instruction_length;
|
||||
},
|
||||
DW.LNS_advance_line => {
|
||||
const arg = try readILeb128Mem(&ptr);
|
||||
const arg = try leb.readILEB128Mem(i64, &ptr);
|
||||
prog.line += arg;
|
||||
},
|
||||
DW.LNS_set_file => {
|
||||
const arg = try readULeb128Mem(&ptr);
|
||||
const arg = try leb.readULEB128Mem(u64, &ptr);
|
||||
prog.file = arg;
|
||||
},
|
||||
DW.LNS_set_column => {
|
||||
const arg = try readULeb128Mem(&ptr);
|
||||
const arg = try leb.readULEB128Mem(u64, &ptr);
|
||||
prog.column = arg;
|
||||
},
|
||||
DW.LNS_negate_stmt => {
|
||||
@@ -1880,9 +1882,9 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr
|
||||
while (true) {
|
||||
const file_name = try di.readString();
|
||||
if (file_name.len == 0) break;
|
||||
const dir_index = try readULeb128(di.dwarf_in_stream);
|
||||
const mtime = try readULeb128(di.dwarf_in_stream);
|
||||
const len_bytes = try readULeb128(di.dwarf_in_stream);
|
||||
const dir_index = try leb.readULEB128(u64, di.dwarf_in_stream);
|
||||
const mtime = try leb.readULEB128(u64, di.dwarf_in_stream);
|
||||
const len_bytes = try leb.readULEB128(u64, di.dwarf_in_stream);
|
||||
try file_entries.append(FileEntry{
|
||||
.file_name = file_name,
|
||||
.dir_index = dir_index,
|
||||
@@ -1897,7 +1899,7 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr
|
||||
const opcode = try di.dwarf_in_stream.readByte();
|
||||
|
||||
if (opcode == DW.LNS_extended_op) {
|
||||
const op_size = try readULeb128(di.dwarf_in_stream);
|
||||
const op_size = try leb.readULEB128(u64, di.dwarf_in_stream);
|
||||
if (op_size < 1) return error.InvalidDebugInfo;
|
||||
var sub_op = try di.dwarf_in_stream.readByte();
|
||||
switch (sub_op) {
|
||||
@@ -1912,9 +1914,9 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr
|
||||
},
|
||||
DW.LNE_define_file => {
|
||||
const file_name = try di.readString();
|
||||
const dir_index = try readULeb128(di.dwarf_in_stream);
|
||||
const mtime = try readULeb128(di.dwarf_in_stream);
|
||||
const len_bytes = try readULeb128(di.dwarf_in_stream);
|
||||
const dir_index = try leb.readULEB128(u64, di.dwarf_in_stream);
|
||||
const mtime = try leb.readULEB128(u64, di.dwarf_in_stream);
|
||||
const len_bytes = try leb.readULEB128(u64, di.dwarf_in_stream);
|
||||
try file_entries.append(FileEntry{
|
||||
.file_name = file_name,
|
||||
.dir_index = dir_index,
|
||||
@@ -1943,19 +1945,19 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr
|
||||
prog.basic_block = false;
|
||||
},
|
||||
DW.LNS_advance_pc => {
|
||||
const arg = try readULeb128(di.dwarf_in_stream);
|
||||
const arg = try leb.readULEB128(u64, di.dwarf_in_stream);
|
||||
prog.address += arg * minimum_instruction_length;
|
||||
},
|
||||
DW.LNS_advance_line => {
|
||||
const arg = try readILeb128(di.dwarf_in_stream);
|
||||
const arg = try leb.readILEB128(i64, di.dwarf_in_stream);
|
||||
prog.line += arg;
|
||||
},
|
||||
DW.LNS_set_file => {
|
||||
const arg = try readULeb128(di.dwarf_in_stream);
|
||||
const arg = try leb.readULEB128(u64, di.dwarf_in_stream);
|
||||
prog.file = arg;
|
||||
},
|
||||
DW.LNS_set_column => {
|
||||
const arg = try readULeb128(di.dwarf_in_stream);
|
||||
const arg = try leb.readULEB128(u64, di.dwarf_in_stream);
|
||||
prog.column = arg;
|
||||
},
|
||||
DW.LNS_negate_stmt => {
|
||||
@@ -2240,53 +2242,6 @@ fn readStringMem(ptr: *[*]const u8) []const u8 {
|
||||
return result;
|
||||
}
|
||||
|
||||
fn readULeb128Mem(ptr: *[*]const u8) !u64 {
|
||||
var result: u64 = 0;
|
||||
var shift: usize = 0;
|
||||
var i: usize = 0;
|
||||
|
||||
while (true) {
|
||||
const byte = ptr.*[i];
|
||||
i += 1;
|
||||
|
||||
var operand: u64 = undefined;
|
||||
|
||||
if (@shlWithOverflow(u64, byte & 0b01111111, @intCast(u6, shift), &operand)) return error.InvalidDebugInfo;
|
||||
|
||||
result |= operand;
|
||||
|
||||
if ((byte & 0b10000000) == 0) {
|
||||
ptr.* += i;
|
||||
return result;
|
||||
}
|
||||
|
||||
shift += 7;
|
||||
}
|
||||
}
|
||||
fn readILeb128Mem(ptr: *[*]const u8) !i64 {
|
||||
var result: i64 = 0;
|
||||
var shift: usize = 0;
|
||||
var i: usize = 0;
|
||||
|
||||
while (true) {
|
||||
const byte = ptr.*[i];
|
||||
i += 1;
|
||||
|
||||
if (shift > @sizeOf(i64) * 8) return error.InvalidDebugInfo;
|
||||
|
||||
result |= i64(byte & 0b01111111) << @intCast(u6, shift);
|
||||
shift += 7;
|
||||
|
||||
if ((byte & 0b10000000) == 0) {
|
||||
if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0) {
|
||||
result |= -(i64(1) << @intCast(u6, shift));
|
||||
}
|
||||
ptr.* += i;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 {
|
||||
const first_32_bits = try in_stream.readIntLittle(u32);
|
||||
is_64.* = (first_32_bits == 0xffffffff);
|
||||
@@ -2298,46 +2253,6 @@ fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool)
|
||||
}
|
||||
}
|
||||
|
||||
fn readULeb128(in_stream: var) !u64 {
|
||||
var result: u64 = 0;
|
||||
var shift: usize = 0;
|
||||
|
||||
while (true) {
|
||||
const byte = try in_stream.readByte();
|
||||
|
||||
var operand: u64 = undefined;
|
||||
|
||||
if (@shlWithOverflow(u64, byte & 0b01111111, @intCast(u6, shift), &operand)) return error.InvalidDebugInfo;
|
||||
|
||||
result |= operand;
|
||||
|
||||
if ((byte & 0b10000000) == 0) return result;
|
||||
|
||||
shift += 7;
|
||||
}
|
||||
}
|
||||
|
||||
fn readILeb128(in_stream: var) !i64 {
|
||||
var result: i64 = 0;
|
||||
var shift: usize = 0;
|
||||
|
||||
while (true) {
|
||||
const byte = try in_stream.readByte();
|
||||
|
||||
if (shift > @sizeOf(i64) * 8) return error.InvalidDebugInfo;
|
||||
|
||||
result |= i64(byte & 0b01111111) << @intCast(u6, shift);
|
||||
shift += 7;
|
||||
|
||||
if ((byte & 0b10000000) == 0) {
|
||||
if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0) {
|
||||
result |= -(i64(1) << @intCast(u6, shift));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This should only be used in temporary test programs.
|
||||
pub const global_allocator = &global_fixed_allocator.allocator;
|
||||
var global_fixed_allocator = std.heap.ThreadSafeFixedBufferAllocator.init(global_allocator_mem[0..]);
|
||||
|
||||
Reference in New Issue
Block a user