From 60e2a04322cb3cb49fdc2c1b28060bc261754302 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 10 Apr 2019 23:30:41 +0200 Subject: Correct parsing of DWARF line_info section --- std/debug.zig | 290 ++++++++++++++++++++++++++++------------------------------ 1 file changed, 139 insertions(+), 151 deletions(-) (limited to 'std/debug.zig') diff --git a/std/debug.zig b/std/debug.zig index c85a982059..2bef2e69cc 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -1213,7 +1213,6 @@ const CompileUnit = struct { version: u16, is_64: bool, die: *Die, - index: usize, pc_range: ?PcRange, }; @@ -1787,173 +1786,165 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo { const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir); + const line_info_offset = try compile_unit.die.getAttrSecOffset(DW.AT_stmt_list); - const debug_line_end = di.debug_line.offset + di.debug_line.size; - var this_offset = di.debug_line.offset; - var this_index: usize = 0; + assert(line_info_offset < di.debug_line.size); - while (this_offset < debug_line_end) : (this_index += 1) { - try di.dwarf_seekable_stream.seekTo(this_offset); + try di.dwarf_seekable_stream.seekTo(di.debug_line.offset + line_info_offset); - var is_64: bool = undefined; - const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64); - if (unit_length == 0) return error.MissingDebugInfo; - const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); - - if (compile_unit.index != this_index) { - this_offset += next_offset; - continue; - } + var is_64: bool = undefined; + const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64); + if (unit_length == 0) { + return error.MissingDebugInfo; + } + const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); - const version = try di.dwarf_in_stream.readInt(u16, di.endian); - // TODO support 3 and 5 - if (version != 2 and version != 4) return error.InvalidDebugInfo; + const version = try di.dwarf_in_stream.readInt(u16, di.endian); + // TODO support 3 and 5 + if (version != 2 and version != 4) return error.InvalidDebugInfo; - const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian); - const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length; + const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian); + const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length; - const minimum_instruction_length = try di.dwarf_in_stream.readByte(); - if (minimum_instruction_length == 0) return error.InvalidDebugInfo; + const minimum_instruction_length = try di.dwarf_in_stream.readByte(); + if (minimum_instruction_length == 0) return error.InvalidDebugInfo; - if (version >= 4) { - // maximum_operations_per_instruction - _ = try di.dwarf_in_stream.readByte(); - } + if (version >= 4) { + // maximum_operations_per_instruction + _ = try di.dwarf_in_stream.readByte(); + } - const default_is_stmt = (try di.dwarf_in_stream.readByte()) != 0; - const line_base = try di.dwarf_in_stream.readByteSigned(); + const default_is_stmt = (try di.dwarf_in_stream.readByte()) != 0; + const line_base = try di.dwarf_in_stream.readByteSigned(); - const line_range = try di.dwarf_in_stream.readByte(); - if (line_range == 0) return error.InvalidDebugInfo; + const line_range = try di.dwarf_in_stream.readByte(); + if (line_range == 0) return error.InvalidDebugInfo; - const opcode_base = try di.dwarf_in_stream.readByte(); + const opcode_base = try di.dwarf_in_stream.readByte(); - const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1); + const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1); - { - var i: usize = 0; - while (i < opcode_base - 1) : (i += 1) { - standard_opcode_lengths[i] = try di.dwarf_in_stream.readByte(); - } + { + var i: usize = 0; + while (i < opcode_base - 1) : (i += 1) { + standard_opcode_lengths[i] = try di.dwarf_in_stream.readByte(); } + } - var include_directories = ArrayList([]u8).init(di.allocator()); - try include_directories.append(compile_unit_cwd); - while (true) { - const dir = try di.readString(); - if (dir.len == 0) break; - try include_directories.append(dir); - } + var include_directories = ArrayList([]u8).init(di.allocator()); + try include_directories.append(compile_unit_cwd); + while (true) { + const dir = try di.readString(); + if (dir.len == 0) break; + try include_directories.append(dir); + } - var file_entries = ArrayList(FileEntry).init(di.allocator()); - var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), &file_entries, target_address); + var file_entries = ArrayList(FileEntry).init(di.allocator()); + var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), &file_entries, target_address); - 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); - try file_entries.append(FileEntry{ - .file_name = file_name, - .dir_index = dir_index, - .mtime = mtime, - .len_bytes = len_bytes, - }); - } + 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); + try file_entries.append(FileEntry{ + .file_name = file_name, + .dir_index = dir_index, + .mtime = mtime, + .len_bytes = len_bytes, + }); + } - try di.dwarf_seekable_stream.seekTo(prog_start_offset); + try di.dwarf_seekable_stream.seekTo(prog_start_offset); - while (true) { - const opcode = try di.dwarf_in_stream.readByte(); - - if (opcode == DW.LNS_extended_op) { - const op_size = try readULeb128(di.dwarf_in_stream); - if (op_size < 1) return error.InvalidDebugInfo; - var sub_op = try di.dwarf_in_stream.readByte(); - switch (sub_op) { - DW.LNE_end_sequence => { - prog.end_sequence = true; - if (try prog.checkLineMatch()) |info| return info; - return error.MissingDebugInfo; - }, - DW.LNE_set_address => { - const addr = try di.dwarf_in_stream.readInt(usize, di.endian); - prog.address = 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); - try file_entries.append(FileEntry{ - .file_name = file_name, - .dir_index = dir_index, - .mtime = mtime, - .len_bytes = len_bytes, - }); - }, - else => { - const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo; - try di.dwarf_seekable_stream.seekForward(fwd_amt); - }, - } - } else if (opcode >= opcode_base) { - // special opcodes - const adjusted_opcode = opcode - opcode_base; - const inc_addr = minimum_instruction_length * (adjusted_opcode / line_range); - const inc_line = i32(line_base) + i32(adjusted_opcode % line_range); - prog.line += inc_line; - prog.address += inc_addr; - if (try prog.checkLineMatch()) |info| return info; - prog.basic_block = false; - } else { - switch (opcode) { - DW.LNS_copy => { - if (try prog.checkLineMatch()) |info| return info; - prog.basic_block = false; - }, - DW.LNS_advance_pc => { - const arg = try readULeb128(di.dwarf_in_stream); - prog.address += arg * minimum_instruction_length; - }, - DW.LNS_advance_line => { - const arg = try readILeb128(di.dwarf_in_stream); - prog.line += arg; - }, - DW.LNS_set_file => { - const arg = try readULeb128(di.dwarf_in_stream); - prog.file = arg; - }, - DW.LNS_set_column => { - const arg = try readULeb128(di.dwarf_in_stream); - prog.column = arg; - }, - DW.LNS_negate_stmt => { - prog.is_stmt = !prog.is_stmt; - }, - DW.LNS_set_basic_block => { - prog.basic_block = true; - }, - DW.LNS_const_add_pc => { - const inc_addr = minimum_instruction_length * ((255 - opcode_base) / line_range); - prog.address += inc_addr; - }, - DW.LNS_fixed_advance_pc => { - const arg = try di.dwarf_in_stream.readInt(u16, di.endian); - prog.address += arg; - }, - DW.LNS_set_prologue_end => {}, - else => { - if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo; - const len_bytes = standard_opcode_lengths[opcode - 1]; - try di.dwarf_seekable_stream.seekForward(len_bytes); - }, - } + while (true) { + const opcode = try di.dwarf_in_stream.readByte(); + + if (opcode == DW.LNS_extended_op) { + const op_size = try readULeb128(di.dwarf_in_stream); + if (op_size < 1) return error.InvalidDebugInfo; + var sub_op = try di.dwarf_in_stream.readByte(); + switch (sub_op) { + DW.LNE_end_sequence => { + prog.end_sequence = true; + if (try prog.checkLineMatch()) |info| return info; + return error.MissingDebugInfo; + }, + DW.LNE_set_address => { + const addr = try di.dwarf_in_stream.readInt(usize, di.endian); + prog.address = 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); + try file_entries.append(FileEntry{ + .file_name = file_name, + .dir_index = dir_index, + .mtime = mtime, + .len_bytes = len_bytes, + }); + }, + else => { + const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo; + try di.dwarf_seekable_stream.seekForward(fwd_amt); + }, + } + } else if (opcode >= opcode_base) { + // special opcodes + const adjusted_opcode = opcode - opcode_base; + const inc_addr = minimum_instruction_length * (adjusted_opcode / line_range); + const inc_line = i32(line_base) + i32(adjusted_opcode % line_range); + prog.line += inc_line; + prog.address += inc_addr; + if (try prog.checkLineMatch()) |info| return info; + prog.basic_block = false; + } else { + switch (opcode) { + DW.LNS_copy => { + if (try prog.checkLineMatch()) |info| return info; + prog.basic_block = false; + }, + DW.LNS_advance_pc => { + const arg = try readULeb128(di.dwarf_in_stream); + prog.address += arg * minimum_instruction_length; + }, + DW.LNS_advance_line => { + const arg = try readILeb128(di.dwarf_in_stream); + prog.line += arg; + }, + DW.LNS_set_file => { + const arg = try readULeb128(di.dwarf_in_stream); + prog.file = arg; + }, + DW.LNS_set_column => { + const arg = try readULeb128(di.dwarf_in_stream); + prog.column = arg; + }, + DW.LNS_negate_stmt => { + prog.is_stmt = !prog.is_stmt; + }, + DW.LNS_set_basic_block => { + prog.basic_block = true; + }, + DW.LNS_const_add_pc => { + const inc_addr = minimum_instruction_length * ((255 - opcode_base) / line_range); + prog.address += inc_addr; + }, + DW.LNS_fixed_advance_pc => { + const arg = try di.dwarf_in_stream.readInt(u16, di.endian); + prog.address += arg; + }, + DW.LNS_set_prologue_end => {}, + else => { + if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo; + const len_bytes = standard_opcode_lengths[opcode - 1]; + try di.dwarf_seekable_stream.seekForward(len_bytes); + }, } } - - this_offset += next_offset; } return error.MissingDebugInfo; @@ -1962,7 +1953,6 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr fn scanAllCompileUnits(di: *DwarfInfo) !void { const debug_info_end = di.debug_info.offset + di.debug_info.size; var this_unit_offset = di.debug_info.offset; - var cu_index: usize = 0; while (this_unit_offset < debug_info_end) { try di.dwarf_seekable_stream.seekTo(this_unit_offset); @@ -2019,11 +2009,9 @@ fn scanAllCompileUnits(di: *DwarfInfo) !void { .is_64 = is_64, .pc_range = pc_range, .die = compile_unit_die, - .index = cu_index, }); this_unit_offset += next_offset; - cu_index += 1; } } -- cgit v1.2.3 From 795b3e9b68986a587ac1fc9a2df6d87067d6f955 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 11 Apr 2019 09:53:47 +0200 Subject: Fix reading of udata/sdata encoded attributes --- std/debug.zig | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'std/debug.zig') diff --git a/std/debug.zig b/std/debug.zig index 2bef2e69cc..5fae39d513 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -1251,13 +1251,12 @@ const FormValue = union(enum) { }; const Constant = struct { - payload: []u8, + payload: u64, signed: bool, fn asUnsignedLe(self: *const Constant) !u64 { - if (self.payload.len > @sizeOf(u64)) return error.InvalidDebugInfo; if (self.signed) return error.InvalidDebugInfo; - return mem.readVarInt(u64, self.payload, builtin.Endian.Little); + return self.payload; } }; @@ -1442,11 +1441,18 @@ fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) ! return parseFormValueBlockLen(allocator, in_stream, block_len); } -fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, size: usize) !FormValue { +fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, size: i32) !FormValue { return FormValue{ .Const = Constant{ .signed = signed, - .payload = try readAllocBytes(allocator, in_stream, size), + .payload = switch (size) { + 1 => try in_stream.readIntLittle(u8), + 2 => try in_stream.readIntLittle(u16), + 4 => try in_stream.readIntLittle(u32), + 8 => try in_stream.readIntLittle(u64), + -1 => if (signed) try readULeb128(in_stream) else @intCast(u64, try readILeb128(in_stream)), + else => unreachable, + }, }, }; } @@ -1484,9 +1490,8 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 DW.FORM_data4 => parseFormValueConstant(allocator, in_stream, false, 4), DW.FORM_data8 => parseFormValueConstant(allocator, in_stream, false, 8), DW.FORM_udata, DW.FORM_sdata => { - const block_len = try readULeb128(in_stream); const signed = form_id == DW.FORM_sdata; - return parseFormValueConstant(allocator, in_stream, signed, block_len); + return parseFormValueConstant(allocator, in_stream, signed, -1); }, DW.FORM_exprloc => { const size = try readULeb128(in_stream); -- cgit v1.2.3 From 38492b2ea4b7aac9685ede264701ac0b7bb291c0 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 11 Apr 2019 10:35:35 +0200 Subject: Fix reading of reference attributes --- std/debug.zig | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) (limited to 'std/debug.zig') diff --git a/std/debug.zig b/std/debug.zig index 5fae39d513..f29c2869af 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -1243,9 +1243,7 @@ const FormValue = union(enum) { ExprLoc: []u8, Flag: bool, SecOffset: u64, - Ref: []u8, RefAddr: u64, - RefSig8: u64, String: []u8, StrPtr: u64, }; @@ -1465,14 +1463,17 @@ fn parseFormValueTargetAddrSize(in_stream: var) !u64 { return if (@sizeOf(usize) == 4) u64(try in_stream.readIntLittle(u32)) else if (@sizeOf(usize) == 8) try in_stream.readIntLittle(u64) else unreachable; } -fn parseFormValueRefLen(allocator: *mem.Allocator, in_stream: var, size: usize) !FormValue { - const buf = try readAllocBytes(allocator, in_stream, size); - return FormValue{ .Ref = buf }; -} - -fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type) !FormValue { - const block_len = try in_stream.readIntLittle(T); - return parseFormValueRefLen(allocator, in_stream, block_len); +fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, size: i32) !FormValue { + return FormValue{ + .RefAddr = switch (size) { + 1 => try in_stream.readIntLittle(u8), + 2 => try in_stream.readIntLittle(u16), + 4 => try in_stream.readIntLittle(u32), + 8 => try in_stream.readIntLittle(u64), + -1 => try readULeb128(in_stream), + else => unreachable, + }, + }; } fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) anyerror!FormValue { @@ -1502,17 +1503,14 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 DW.FORM_flag_present => FormValue{ .Flag = true }, DW.FORM_sec_offset => FormValue{ .SecOffset = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, - DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, u8), - DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, u16), - DW.FORM_ref4 => parseFormValueRef(allocator, in_stream, u32), - DW.FORM_ref8 => parseFormValueRef(allocator, in_stream, u64), - DW.FORM_ref_udata => { - const ref_len = try readULeb128(in_stream); - return parseFormValueRefLen(allocator, in_stream, ref_len); - }, + DW.FORM_ref1 => parseFormValueRef(allocator, in_stream, 1), + DW.FORM_ref2 => parseFormValueRef(allocator, in_stream, 2), + DW.FORM_ref4 => parseFormValueRef(allocator, in_stream, 4), + DW.FORM_ref8 => parseFormValueRef(allocator, in_stream, 8), + DW.FORM_ref_udata => parseFormValueRef(allocator, in_stream, -1), DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, - DW.FORM_ref_sig8 => FormValue{ .RefSig8 = try in_stream.readIntLittle(u64) }, + DW.FORM_ref_sig8 => FormValue{ .RefAddr = try in_stream.readIntLittle(u64) }, DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) }, DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, -- cgit v1.2.3 From 51eb4ebec1435dc0050bd1d40c48416019972e65 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 11 Apr 2019 15:41:42 +0200 Subject: Distinguish between absolute/relative addresses --- std/debug.zig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'std/debug.zig') diff --git a/std/debug.zig b/std/debug.zig index f29c2869af..ec3f609022 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -1243,6 +1243,7 @@ const FormValue = union(enum) { ExprLoc: []u8, Flag: bool, SecOffset: u64, + Ref: u64, RefAddr: u64, String: []u8, StrPtr: u64, @@ -1465,7 +1466,7 @@ fn parseFormValueTargetAddrSize(in_stream: var) !u64 { fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, size: i32) !FormValue { return FormValue{ - .RefAddr = switch (size) { + .Ref = switch (size) { 1 => try in_stream.readIntLittle(u8), 2 => try in_stream.readIntLittle(u16), 4 => try in_stream.readIntLittle(u32), @@ -1510,7 +1511,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 DW.FORM_ref_udata => parseFormValueRef(allocator, in_stream, -1), DW.FORM_ref_addr => FormValue{ .RefAddr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, - DW.FORM_ref_sig8 => FormValue{ .RefAddr = try in_stream.readIntLittle(u64) }, + DW.FORM_ref_sig8 => FormValue{ .Ref = try in_stream.readIntLittle(u64) }, DW.FORM_string => FormValue{ .String = try readStringRaw(allocator, in_stream) }, DW.FORM_strp => FormValue{ .StrPtr = try parseFormValueDwarfOffsetSize(in_stream, is_64) }, -- cgit v1.2.3 From 27cd830ec8ca1ddba692c65e8a129a2b5c9a1673 Mon Sep 17 00:00:00 2001 From: Matthew Iannucci Date: Thu, 11 Apr 2019 13:15:17 -0400 Subject: Add initial support for iOS targets (#2237) * Add iOS C int sizes... try to hack in iOS DebugInfo * Get rid of ios link check for now * Remove macos linkversion check --- src/link.cpp | 10 ---------- src/target.cpp | 17 ++++++++++++++++- std/debug.zig | 2 +- 3 files changed, 17 insertions(+), 12 deletions(-) (limited to 'std/debug.zig') diff --git a/src/link.cpp b/src/link.cpp index 70f91f2b8e..2a152e1d1e 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -1562,16 +1562,6 @@ static void construct_linker_job_macho(LinkJob *lj) { lj->args.append("dynamic_lookup"); } - if (platform.kind == MacOS) { - if (darwin_version_lt(&platform, 10, 5)) { - lj->args.append("-lgcc_s.10.4"); - } else if (darwin_version_lt(&platform, 10, 6)) { - lj->args.append("-lgcc_s.10.5"); - } - } else { - zig_panic("TODO"); - } - for (size_t i = 0; i < g->darwin_frameworks.length; i += 1) { lj->args.append("-framework"); lj->args.append(buf_ptr(g->darwin_frameworks.at(i))); diff --git a/src/target.cpp b/src/target.cpp index dda8188765..3b4265359c 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -894,10 +894,25 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { case CIntTypeCount: zig_unreachable(); } + case OsIOS: + switch (id) { + case CIntTypeShort: + case CIntTypeUShort: + return 16; + case CIntTypeInt: + case CIntTypeUInt: + return 32; + case CIntTypeLong: + case CIntTypeULong: + case CIntTypeLongLong: + case CIntTypeULongLong: + return 64; + case CIntTypeCount: + zig_unreachable(); + } case OsAnanas: case OsCloudABI: case OsDragonFly: - case OsIOS: case OsKFreeBSD: case OsLv2: case OsSolaris: diff --git a/std/debug.zig b/std/debug.zig index c85a982059..bfcfbc6e77 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -1178,7 +1178,7 @@ pub const DwarfInfo = struct { }; pub const DebugInfo = switch (builtin.os) { - builtin.Os.macosx => struct { + builtin.Os.macosx, builtin.Os.ios => struct { symbols: []const MachoSymbol, strings: []const u8, ofiles: OFileTable, -- cgit v1.2.3 From 0286be127e4b9f74ddffcc241b947c7c5bb3dfce Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 19 Apr 2019 19:59:14 +0200 Subject: Fix parseFormValueConstant Signed/unsigned confusion made the code fail an assertion sometimes. --- std/debug.zig | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'std/debug.zig') diff --git a/std/debug.zig b/std/debug.zig index 90b4ff31d5..b360601e92 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -1440,7 +1440,7 @@ fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, size: usize) ! return parseFormValueBlockLen(allocator, in_stream, block_len); } -fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, size: i32) !FormValue { +fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, comptime size: i32) !FormValue { return FormValue{ .Const = Constant{ .signed = signed, @@ -1449,8 +1449,9 @@ 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) try readULeb128(in_stream) else @intCast(u64, try readILeb128(in_stream)), - else => unreachable, + -1 => if (signed) @intCast(u64, try readILeb128(in_stream)) + else try readULeb128(in_stream), + else => @compileError("Invalid size"), }, }, }; -- cgit v1.2.3 From c2542bb7b775118f69366849b18e139e120ddb16 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 20 Apr 2019 10:35:39 +0200 Subject: Recover symbol infos from DWARF sections --- std/debug.zig | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- std/dwarf.zig | 1 + 2 files changed, 159 insertions(+), 1 deletion(-) (limited to 'std/debug.zig') diff --git a/std/debug.zig b/std/debug.zig index b360601e92..f3d549f3d2 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -692,7 +692,7 @@ pub fn printSourceAtAddressDwarf( const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name); if (getLineNumberInfoDwarf(debug_info, compile_unit.*, address - 1)) |line_info| { defer line_info.deinit(); - const symbol_name = "???"; + const symbol_name = getSymbolNameDwarf(debug_info, address - 1) orelse "???"[0..2]; try printLineInfo( out_stream, line_info, @@ -969,6 +969,8 @@ fn findDwarfSectionFromElf(elf_file: *elf.Elf, name: []const u8) !?DwarfInfo.Sec pub fn openDwarfDebugInfo(di: *DwarfInfo, allocator: *mem.Allocator) !void { di.abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator); di.compile_unit_list = ArrayList(CompileUnit).init(allocator); + di.func_list = ArrayList(Func).init(allocator); + try scanAllFunctions(di); try scanAllCompileUnits(di); } @@ -992,6 +994,7 @@ pub fn openElfDebugInfo( .debug_ranges = (try findDwarfSectionFromElf(&efile, ".debug_ranges")), .abbrev_table_list = undefined, .compile_unit_list = undefined, + .func_list = undefined, }; try openDwarfDebugInfo(&di, allocator); return di; @@ -1162,6 +1165,7 @@ pub const DwarfInfo = struct { debug_ranges: ?Section, abbrev_table_list: ArrayList(AbbrevTableHeader), compile_unit_list: ArrayList(CompileUnit), + func_list: ArrayList(Func), pub const Section = struct { offset: usize, @@ -1301,6 +1305,14 @@ const Die = struct { }; } + fn getAttrRef(self: *const Die, id: u64) !u64 { + const form_value = self.getAttr(id) orelse return error.MissingDebugInfo; + return switch (form_value.*) { + FormValue.Ref => |value| value, + else => error.InvalidDebugInfo, + }; + } + fn getAttrString(self: *const Die, di: *DwarfInfo, id: u64) ![]u8 { const form_value = self.getAttr(id) orelse return error.MissingDebugInfo; return switch (form_value.*) { @@ -1572,6 +1584,26 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con return null; } +fn parseDie1(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !?Die { + const abbrev_code = try readULeb128(di.dwarf_in_stream); + if (abbrev_code == 0) return null; + const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo; + + var result = Die{ + .tag_id = table_entry.tag_id, + .has_children = table_entry.has_children, + .attrs = ArrayList(Die.Attr).init(di.allocator()), + }; + try result.attrs.resize(table_entry.attrs.len); + for (table_entry.attrs.toSliceConst()) |attr, i| { + result.attrs.items[i] = Die.Attr{ + .id = attr.attr_id, + .value = try parseFormValue(di.allocator(), di.dwarf_in_stream, attr.form_id, is_64), + }; + } + return result; +} + fn parseDie(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die { const abbrev_code = try readULeb128(di.dwarf_in_stream); const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo; @@ -1955,6 +1987,131 @@ fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_addr return error.MissingDebugInfo; } +const Func = struct { + pc_range: ?PcRange, + name: ?[]u8, +}; + +fn getSymbolNameDwarf(di: *DwarfInfo, address: u64) ?[]u8 { + for (di.func_list.toSliceConst()) |*func| { + if (func.pc_range) |range| { + if (address >= range.start and address < range.end) { + return func.name; + } + } + } + + return null; +} + +fn scanAllFunctions(di: *DwarfInfo) !void { + const debug_info_end = di.debug_info.offset + di.debug_info.size; + var this_unit_offset = di.debug_info.offset; + + while (this_unit_offset < debug_info_end) { + try di.dwarf_seekable_stream.seekTo(this_unit_offset); + + var is_64: bool = undefined; + const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64); + if (unit_length == 0) return; + const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); + + const version = try di.dwarf_in_stream.readInt(u16, di.endian); + if (version < 2 or version > 5) return error.InvalidDebugInfo; + + const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian); + + const address_size = try di.dwarf_in_stream.readByte(); + if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; + + const compile_unit_pos = try di.dwarf_seekable_stream.getPos(); + const abbrev_table = try getAbbrevTable(di, debug_abbrev_offset); + + try di.dwarf_seekable_stream.seekTo(compile_unit_pos); + + const next_unit_pos = this_unit_offset + next_offset; + + while ((try di.dwarf_seekable_stream.getPos()) < next_unit_pos) { + const die_obj = (try parseDie1(di, abbrev_table, is_64)) orelse continue; + const after_die_offset = try di.dwarf_seekable_stream.getPos(); + + switch (die_obj.tag_id) { + DW.TAG_subprogram, + DW.TAG_inlined_subroutine, + DW.TAG_subroutine, + DW.TAG_entry_point => { + const fn_name = x: { + var depth: i32 = 3; + var this_die_obj = die_obj; + // Prenvent endless loops + while (depth > 0) : (depth -= 1) { + if (this_die_obj.getAttr(DW.AT_name)) |_| { + const name = try this_die_obj.getAttrString(di, DW.AT_name); + break :x name; + } + else if (this_die_obj.getAttr(DW.AT_abstract_origin)) |ref| { + // Follow the DIE it points to and repeat + const ref_offset = try this_die_obj.getAttrRef(DW.AT_abstract_origin); + if (ref_offset > next_offset) return error.InvalidDebugInfo; + try di.dwarf_seekable_stream.seekTo(this_unit_offset + ref_offset); + this_die_obj = (try parseDie1(di, abbrev_table, is_64)) orelse return error.InvalidDebugInfo; + } + else if (this_die_obj.getAttr(DW.AT_specification)) |ref| { + // Follow the DIE it points to and repeat + const ref_offset = try this_die_obj.getAttrRef(DW.AT_abstract_origin); + if (ref_offset > next_offset) return error.InvalidDebugInfo; + try di.dwarf_seekable_stream.seekTo(this_unit_offset + ref_offset); + this_die_obj = (try parseDie1(di, abbrev_table, is_64)) orelse return error.InvalidDebugInfo; + } + else { + break :x null; + } + } + + break :x null; + }; + + const pc_range = x: { + if (die_obj.getAttrAddr(DW.AT_low_pc)) |low_pc| { + if (die_obj.getAttr(DW.AT_high_pc)) |high_pc_value| { + const pc_end = switch (high_pc_value.*) { + FormValue.Address => |value| value, + FormValue.Const => |value| b: { + const offset = try value.asUnsignedLe(); + break :b (low_pc + offset); + }, + else => return error.InvalidDebugInfo, + }; + break :x PcRange{ + .start = low_pc, + .end = pc_end, + }; + } else { + break :x null; + } + } else |err| { + if (err != error.MissingDebugInfo) return err; + break :x null; + } + }; + + try di.func_list.append(Func{ + .name = fn_name, + .pc_range = pc_range, + }); + }, + else => { + continue; + } + } + + try di.dwarf_seekable_stream.seekTo(after_die_offset); + } + + this_unit_offset += next_offset; + } +} + fn scanAllCompileUnits(di: *DwarfInfo) !void { const debug_info_end = di.debug_info.offset + di.debug_info.size; var this_unit_offset = di.debug_info.offset; diff --git a/std/dwarf.zig b/std/dwarf.zig index af73ada9e5..2f3b29302d 100644 --- a/std/dwarf.zig +++ b/std/dwarf.zig @@ -13,6 +13,7 @@ pub const TAG_reference_type = 0x10; pub const TAG_compile_unit = 0x11; pub const TAG_string_type = 0x12; pub const TAG_structure_type = 0x13; +pub const TAG_subroutine = 0x14; pub const TAG_subroutine_type = 0x15; pub const TAG_typedef = 0x16; pub const TAG_union_type = 0x17; -- cgit v1.2.3 From 9b83fe6b4c289ac7168bb052c3538ccd188ae83c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 20 Apr 2019 13:48:38 -0400 Subject: fixup and zig fmt --- std/debug.zig | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) (limited to 'std/debug.zig') diff --git a/std/debug.zig b/std/debug.zig index f3d549f3d2..acb1494a90 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -376,7 +376,6 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres // There is an unknown number of LineBlockFragmentHeaders (and their accompanying line and column records) // from now on. We will iterate through them, and eventually find a LineInfo that we're interested in, // breaking out to :subsections. If not, we will make sure to not read anything outside of this subsection. - const subsection_end_index = sect_offset + subsect_hdr.Length; while (line_index < subsection_end_index) { @@ -692,7 +691,7 @@ pub fn printSourceAtAddressDwarf( const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name); if (getLineNumberInfoDwarf(debug_info, compile_unit.*, address - 1)) |line_info| { defer line_info.deinit(); - const symbol_name = getSymbolNameDwarf(debug_info, address - 1) orelse "???"[0..2]; + const symbol_name = getSymbolNameDwarf(debug_info, address - 1) orelse "???"; try printLineInfo( out_stream, line_info, @@ -1457,12 +1456,11 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo .Const = Constant{ .signed = signed, .payload = switch (size) { - 1 => try in_stream.readIntLittle(u8), - 2 => try in_stream.readIntLittle(u16), - 4 => try in_stream.readIntLittle(u32), - 8 => try in_stream.readIntLittle(u64), - -1 => if (signed) @intCast(u64, try readILeb128(in_stream)) - else try readULeb128(in_stream), + 1 => try in_stream.readIntLittle(u8), + 2 => try in_stream.readIntLittle(u16), + 4 => try in_stream.readIntLittle(u32), + 8 => try in_stream.readIntLittle(u64), + -1 => if (signed) @intCast(u64, try readILeb128(in_stream)) else try readULeb128(in_stream), else => @compileError("Invalid size"), }, }, @@ -1480,10 +1478,10 @@ fn parseFormValueTargetAddrSize(in_stream: var) !u64 { fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, size: i32) !FormValue { return FormValue{ .Ref = switch (size) { - 1 => try in_stream.readIntLittle(u8), - 2 => try in_stream.readIntLittle(u16), - 4 => try in_stream.readIntLittle(u32), - 8 => try in_stream.readIntLittle(u64), + 1 => try in_stream.readIntLittle(u8), + 2 => try in_stream.readIntLittle(u16), + 4 => try in_stream.readIntLittle(u32), + 8 => try in_stream.readIntLittle(u64), -1 => try readULeb128(in_stream), else => unreachable, }, @@ -1992,7 +1990,7 @@ const Func = struct { name: ?[]u8, }; -fn getSymbolNameDwarf(di: *DwarfInfo, address: u64) ?[]u8 { +fn getSymbolNameDwarf(di: *DwarfInfo, address: u64) ?[]const u8 { for (di.func_list.toSliceConst()) |*func| { if (func.pc_range) |range| { if (address >= range.start and address < range.end) { @@ -2036,10 +2034,7 @@ fn scanAllFunctions(di: *DwarfInfo) !void { const after_die_offset = try di.dwarf_seekable_stream.getPos(); switch (die_obj.tag_id) { - DW.TAG_subprogram, - DW.TAG_inlined_subroutine, - DW.TAG_subroutine, - DW.TAG_entry_point => { + DW.TAG_subprogram, DW.TAG_inlined_subroutine, DW.TAG_subroutine, DW.TAG_entry_point => { const fn_name = x: { var depth: i32 = 3; var this_die_obj = die_obj; @@ -2048,22 +2043,19 @@ fn scanAllFunctions(di: *DwarfInfo) !void { if (this_die_obj.getAttr(DW.AT_name)) |_| { const name = try this_die_obj.getAttrString(di, DW.AT_name); break :x name; - } - else if (this_die_obj.getAttr(DW.AT_abstract_origin)) |ref| { + } else if (this_die_obj.getAttr(DW.AT_abstract_origin)) |ref| { // Follow the DIE it points to and repeat const ref_offset = try this_die_obj.getAttrRef(DW.AT_abstract_origin); if (ref_offset > next_offset) return error.InvalidDebugInfo; try di.dwarf_seekable_stream.seekTo(this_unit_offset + ref_offset); this_die_obj = (try parseDie1(di, abbrev_table, is_64)) orelse return error.InvalidDebugInfo; - } - else if (this_die_obj.getAttr(DW.AT_specification)) |ref| { + } else if (this_die_obj.getAttr(DW.AT_specification)) |ref| { // Follow the DIE it points to and repeat const ref_offset = try this_die_obj.getAttrRef(DW.AT_abstract_origin); if (ref_offset > next_offset) return error.InvalidDebugInfo; try di.dwarf_seekable_stream.seekTo(this_unit_offset + ref_offset); this_die_obj = (try parseDie1(di, abbrev_table, is_64)) orelse return error.InvalidDebugInfo; - } - else { + } else { break :x null; } } @@ -2102,7 +2094,7 @@ fn scanAllFunctions(di: *DwarfInfo) !void { }, else => { continue; - } + }, } try di.dwarf_seekable_stream.seekTo(after_die_offset); -- cgit v1.2.3 From 57ec183c09e1c9d313fc6ce35cdbfb4b3aa08016 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 23 Apr 2019 09:57:22 +0200 Subject: Fix reading of signed leb128 values --- std/debug.zig | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'std/debug.zig') diff --git a/std/debug.zig b/std/debug.zig index acb1494a90..dd34e4e205 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -1460,7 +1460,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) @intCast(u64, try readILeb128(in_stream)) else try readULeb128(in_stream), + -1 => if (signed) @bitCast(u64, try readILeb128(in_stream)) else try readULeb128(in_stream), else => @compileError("Invalid size"), }, }, @@ -2272,14 +2272,15 @@ fn readILeb128Mem(ptr: *[*]const u8) !i64 { const byte = ptr.*[i]; i += 1; - var operand: i64 = undefined; - if (@shlWithOverflow(i64, byte & 0b01111111, @intCast(u6, shift), &operand)) return error.InvalidDebugInfo; + if (shift > @sizeOf(i64) * 8) return error.InvalidDebugInfo; - result |= operand; + 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)); + if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0) { + result |= -(i64(1) << @intCast(u6, shift)); + } ptr.* += i; return result; } @@ -2323,15 +2324,15 @@ fn readILeb128(in_stream: var) !i64 { while (true) { const byte = try in_stream.readByte(); - var operand: i64 = undefined; - - if (@shlWithOverflow(i64, byte & 0b01111111, @intCast(u6, shift), &operand)) return error.InvalidDebugInfo; + if (shift > @sizeOf(i64) * 8) return error.InvalidDebugInfo; - result |= operand; + 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)); + if (shift < @sizeOf(i64) * 8 and (byte & 0b01000000) != 0) { + result |= -(i64(1) << @intCast(u6, shift)); + } return result; } } -- cgit v1.2.3 From b095e33667972cb650341e8cfbae7ae41ca9580d Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 23 Apr 2019 09:57:57 +0200 Subject: Fix silly typo --- std/debug.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'std/debug.zig') diff --git a/std/debug.zig b/std/debug.zig index dd34e4e205..7c4343b221 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -2051,7 +2051,7 @@ fn scanAllFunctions(di: *DwarfInfo) !void { this_die_obj = (try parseDie1(di, abbrev_table, is_64)) orelse return error.InvalidDebugInfo; } else if (this_die_obj.getAttr(DW.AT_specification)) |ref| { // Follow the DIE it points to and repeat - const ref_offset = try this_die_obj.getAttrRef(DW.AT_abstract_origin); + const ref_offset = try this_die_obj.getAttrRef(DW.AT_specification); if (ref_offset > next_offset) return error.InvalidDebugInfo; try di.dwarf_seekable_stream.seekTo(this_unit_offset + ref_offset); this_die_obj = (try parseDie1(di, abbrev_table, is_64)) orelse return error.InvalidDebugInfo; -- cgit v1.2.3 From 374d16793f115a5f35060a972fc5d3b43dac958a Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Tue, 23 Apr 2019 10:05:46 +0200 Subject: Go one instruction before the return address The return address may not point to an area covered by the debug infos so we hope for the best and decrement the address so that it points to the caller instruction. --- std/debug.zig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'std/debug.zig') diff --git a/std/debug.zig b/std/debug.zig index 7c4343b221..c5741f3909 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -221,7 +221,7 @@ pub fn writeStackTrace( frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len; }) { const return_address = stack_trace.instruction_addresses[frame_index]; - try printSourceAtAddress(debug_info, out_stream, return_address, tty_color); + try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_color); } } @@ -263,7 +263,7 @@ pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color } var it = StackIterator.init(start_addr); while (it.next()) |return_address| { - try printSourceAtAddress(debug_info, out_stream, return_address, tty_color); + try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_color); } } @@ -689,9 +689,9 @@ pub fn printSourceAtAddressDwarf( return; }; const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name); - if (getLineNumberInfoDwarf(debug_info, compile_unit.*, address - 1)) |line_info| { + if (getLineNumberInfoDwarf(debug_info, compile_unit.*, address)) |line_info| { defer line_info.deinit(); - const symbol_name = getSymbolNameDwarf(debug_info, address - 1) orelse "???"; + const symbol_name = getSymbolNameDwarf(debug_info, address) orelse "???"; try printLineInfo( out_stream, line_info, -- cgit v1.2.3 From 9c12237d2d0643fcf34ad6d027ce78d285e40271 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 8 May 2019 19:11:01 -0400 Subject: std.debug: fix stack trace iteration code Previously, the stack trace iteration code was using the number of frames collected as the number of frames to print, not recognizing the fixed size of the buffer. So it would redundantly print items, matching the total number of frames ever collected. Now the iteration code is limited to the actual stack trace frame count, and will not print duplicate frames. Closes #2447 Closes #2151 --- std/debug.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'std/debug.zig') diff --git a/std/debug.zig b/std/debug.zig index c5741f3909..7f1a249f7a 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -214,7 +214,7 @@ pub fn writeStackTrace( tty_color: bool, ) !void { var frame_index: usize = 0; - var frames_left: usize = stack_trace.index; + var frames_left: usize = std.math.min(stack_trace.index, stack_trace.instruction_addresses.len); while (frames_left != 0) : ({ frames_left -= 1; -- cgit v1.2.3 From 4d8f96dd88c97fa175952f8dd7ab548409c78b0e Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Thu, 9 May 2019 23:46:12 +0200 Subject: Fix minor bug in LEB128 parsing --- CMakeLists.txt | 1 + std/debug.zig | 155 ++++++++---------------------------- std/debug/leb128.zig | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 256 insertions(+), 120 deletions(-) create mode 100644 std/debug/leb128.zig (limited to 'std/debug.zig') diff --git a/CMakeLists.txt b/CMakeLists.txt index 991dc8519c..456945a6c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -487,6 +487,7 @@ set(ZIG_STD_FILES "crypto/x25519.zig" "cstr.zig" "debug.zig" + "debug/leb128.zig" "debug/failing_allocator.zig" "dwarf.zig" "dynamic_library.zig" diff --git a/std/debug.zig b/std/debug.zig index 7f1a249f7a..61d6e648dd 100644 --- a/std/debug.zig +++ b/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..]); diff --git a/std/debug/leb128.zig b/std/debug/leb128.zig new file mode 100644 index 0000000000..7bdb30a267 --- /dev/null +++ b/std/debug/leb128.zig @@ -0,0 +1,220 @@ +const std = @import("std"); +const testing = std.testing; + +pub fn readULEB128(comptime T: type, in_stream: var) !T { + const ShiftT = @IntType(false, std.math.log2(T.bit_count)); + + var result: T = 0; + var shift: ShiftT = 0; + + while (true) { + const byte = try in_stream.readByte(); + + var operand: T = undefined; + if (@shlWithOverflow(T, byte & 0x7f, shift, &operand)) + return error.Overflow; + + result |= operand; + + if (@addWithOverflow(ShiftT, shift, 7, &shift)) + return error.Overflow; + + if ((byte & 0x80) == 0) + return result; + } +} + +pub fn readULEB128Mem(comptime T: type, ptr: *[*]const u8) !T { + const ShiftT = @IntType(false, std.math.log2(T.bit_count)); + + var result: T = 0; + var shift: ShiftT = 0; + var i: usize = 0; + + while (true) { + const byte = ptr.*[i]; + i += 1; + + var operand: T = undefined; + if (@shlWithOverflow(T, byte & 0x7f, shift, &operand)) + return error.Overflow; + + result |= operand; + + if (@addWithOverflow(ShiftT, shift, 7, &shift)) + return error.Overflow; + + if ((byte & 0x80) == 0) { + ptr.* += i; + return result; + } + } +} + +pub fn readILEB128(comptime T: type, in_stream: var) !T { + const ShiftT = @IntType(false, std.math.log2(T.bit_count)); + + var result: T = 0; + var shift: ShiftT = 0; + + while (true) { + const byte = u8(try in_stream.readByte()); + + var operand: T = undefined; + if (@shlWithOverflow(T, @intCast(T, byte & 0x7f), shift, &operand)) + return error.Overflow; + + result |= operand; + + if (@addWithOverflow(ShiftT, shift, 7, &shift)) + return error.Overflow; + + if ((byte & 0x80) == 0) { + if (shift <= ShiftT(T.bit_count - 1) and (byte & 0x40) != 0) { + result |= T(-1) << shift; + } + return result; + } + } +} + +pub fn readILEB128Mem(comptime T: type, ptr: *[*]const u8) !T { + const ShiftT = @IntType(false, std.math.log2(T.bit_count)); + + var result: T = 0; + var shift: ShiftT = 0; + var i: usize = 0; + + while (true) { + const byte = ptr.*[i]; + i += 1; + + var operand: T = undefined; + if (@shlWithOverflow(T, @intCast(T, byte & 0x7f), shift, &operand)) + return error.Overflow; + + result |= operand; + + if (@addWithOverflow(ShiftT, shift, 7, &shift)) + return error.Overflow; + + if ((byte & 0x80) == 0) { + if (shift <= ShiftT(T.bit_count - 1) and (byte & 0x40) != 0) { + result |= T(-1) << shift; + } + ptr.* += i; + return result; + } + } +} + +const OneByteReadInStream = struct { + const Error = error{NoError}; + const Stream = std.io.InStream(Error); + + stream: Stream, + str: []const u8, + curr: usize, + + fn init(str: []const u8) @This() { + return @This(){ + .stream = Stream{ .readFn = readFn }, + .str = str, + .curr = 0, + }; + } + + fn readFn(in_stream: *Stream, dest: []u8) Error!usize { + const self = @fieldParentPtr(@This(), "stream", in_stream); + if (self.str.len <= self.curr or dest.len == 0) + return 0; + + dest[0] = self.str[self.curr]; + self.curr += 1; + return 1; + } +}; + +fn test_read_ileb128(comptime T: type, encoded: []const u8) !T { + var in_stream = OneByteReadInStream.init(encoded); + const v1 = try readILEB128(T, &in_stream.stream); + var in_ptr = encoded.ptr; + const v2 = try readILEB128Mem(T, &in_ptr); + testing.expectEqual(v1, v2); + return v2; +} + +fn test_read_uleb128(comptime T: type, encoded: []const u8) !T { + var in_stream = OneByteReadInStream.init(encoded); + const v1 = try readULEB128(T, &in_stream.stream); + var in_ptr = encoded.ptr; + const v2 = try readULEB128Mem(T, &in_ptr); + return v2; +} + +test "deserialize signed LEB128" { + // Truncated + testing.expectError(error.EndOfStream, test_read_ileb128(i64, "\x80")); + + // Overflow + testing.expectError(error.Overflow, test_read_ileb128(i8, "\x80\x80\x40")); + testing.expectError(error.Overflow, test_read_ileb128(i16, "\x80\x80\x80\x40")); + testing.expectError(error.Overflow, test_read_ileb128(i32, "\x80\x80\x80\x80\x40")); + testing.expectError(error.Overflow, test_read_ileb128(i64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x40")); + + // Decode SLEB128 + testing.expect((try test_read_ileb128(i64, "\x00")) == 0); + testing.expect((try test_read_ileb128(i64, "\x01")) == 1); + testing.expect((try test_read_ileb128(i64, "\x3f")) == 63); + testing.expect((try test_read_ileb128(i64, "\x40")) == -64); + testing.expect((try test_read_ileb128(i64, "\x41")) == -63); + testing.expect((try test_read_ileb128(i64, "\x7f")) == -1); + testing.expect((try test_read_ileb128(i64, "\x80\x01")) == 128); + testing.expect((try test_read_ileb128(i64, "\x81\x01")) == 129); + testing.expect((try test_read_ileb128(i64, "\xff\x7e")) == -129); + testing.expect((try test_read_ileb128(i64, "\x80\x7f")) == -128); + testing.expect((try test_read_ileb128(i64, "\x81\x7f")) == -127); + testing.expect((try test_read_ileb128(i64, "\xc0\x00")) == 64); + testing.expect((try test_read_ileb128(i64, "\xc7\x9f\x7f")) == -12345); + + // Decode unnormalized SLEB128 with extra padding bytes. + testing.expect((try test_read_ileb128(i64, "\x80\x00")) == 0); + testing.expect((try test_read_ileb128(i64, "\x80\x80\x00")) == 0); + testing.expect((try test_read_ileb128(i64, "\xff\x00")) == 0x7f); + testing.expect((try test_read_ileb128(i64, "\xff\x80\x00")) == 0x7f); + testing.expect((try test_read_ileb128(i64, "\x80\x81\x00")) == 0x80); + testing.expect((try test_read_ileb128(i64, "\x80\x81\x80\x00")) == 0x80); +} + +test "deserialize unsigned LEB128" { + // Truncated + testing.expectError(error.EndOfStream, test_read_uleb128(u64, "\x80")); + + // Overflow + testing.expectError(error.Overflow, test_read_uleb128(u8, "\x80\x80\x40")); + testing.expectError(error.Overflow, test_read_uleb128(u16, "\x80\x80\x80\x40")); + testing.expectError(error.Overflow, test_read_uleb128(u32, "\x80\x80\x80\x80\x40")); + testing.expectError(error.Overflow, test_read_uleb128(u64, "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x40")); + + // Decode ULEB128 + testing.expect((try test_read_uleb128(u64, "\x00")) == 0); + testing.expect((try test_read_uleb128(u64, "\x01")) == 1); + testing.expect((try test_read_uleb128(u64, "\x3f")) == 63); + testing.expect((try test_read_uleb128(u64, "\x40")) == 64); + testing.expect((try test_read_uleb128(u64, "\x7f")) == 0x7f); + testing.expect((try test_read_uleb128(u64, "\x80\x01")) == 0x80); + testing.expect((try test_read_uleb128(u64, "\x81\x01")) == 0x81); + testing.expect((try test_read_uleb128(u64, "\x90\x01")) == 0x90); + testing.expect((try test_read_uleb128(u64, "\xff\x01")) == 0xff); + testing.expect((try test_read_uleb128(u64, "\x80\x02")) == 0x100); + testing.expect((try test_read_uleb128(u64, "\x81\x02")) == 0x101); + testing.expect((try test_read_uleb128(u64, "\x80\xc1\x80\x80\x10")) == 4294975616); + + // Decode ULEB128 with extra padding bytes + testing.expect((try test_read_uleb128(u64, "\x80\x00")) == 0); + testing.expect((try test_read_uleb128(u64, "\x80\x80\x00")) == 0); + testing.expect((try test_read_uleb128(u64, "\xff\x00")) == 0x7f); + testing.expect((try test_read_uleb128(u64, "\xff\x80\x00")) == 0x7f); + testing.expect((try test_read_uleb128(u64, "\x80\x81\x00")) == 0x80); + testing.expect((try test_read_uleb128(u64, "\x80\x81\x80\x00")) == 0x80); +} -- cgit v1.2.3 From 8cc4eaea9f5bbf2f77af4903f32d21ec7911f759 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Fri, 10 May 2019 00:44:24 +0200 Subject: Use matching types when parsing fields --- std/debug.zig | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'std/debug.zig') diff --git a/std/debug.zig b/std/debug.zig index 61d6e648dd..d017f96144 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -1718,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 leb.readULEB128Mem(u64, &ptr); - const mtime = try leb.readULEB128Mem(u64, &ptr); - const len_bytes = try leb.readULEB128Mem(u64, &ptr); + const dir_index = try leb.readULEB128Mem(usize, &ptr); + const mtime = try leb.readULEB128Mem(usize, &ptr); + const len_bytes = try leb.readULEB128Mem(usize, &ptr); try file_entries.append(FileEntry{ .file_name = file_name, .dir_index = dir_index, @@ -1749,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 leb.readULEB128Mem(u64, &ptr); - const mtime = try leb.readULEB128Mem(u64, &ptr); - const len_bytes = try leb.readULEB128Mem(u64, &ptr); + const dir_index = try leb.readULEB128Mem(usize, &ptr); + const mtime = try leb.readULEB128Mem(usize, &ptr); + const len_bytes = try leb.readULEB128Mem(usize, &ptr); try file_entries.append(FileEntry{ .file_name = file_name, .dir_index = dir_index, @@ -1882,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 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); + const dir_index = try leb.readULEB128(usize, di.dwarf_in_stream); + const mtime = try leb.readULEB128(usize, di.dwarf_in_stream); + const len_bytes = try leb.readULEB128(usize, di.dwarf_in_stream); try file_entries.append(FileEntry{ .file_name = file_name, .dir_index = dir_index, @@ -1914,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 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); + const dir_index = try leb.readULEB128(usize, di.dwarf_in_stream); + const mtime = try leb.readULEB128(usize, di.dwarf_in_stream); + const len_bytes = try leb.readULEB128(usize, di.dwarf_in_stream); try file_entries.append(FileEntry{ .file_name = file_name, .dir_index = dir_index, -- cgit v1.2.3