| author | |
| committer | |
| log | 9901b9389ed963ff262d1ce4973029a570035f19 |
| tree | c640810510f6c8fcbb2885cd273d86b70ae8ad07 |
| parent | 7601b397ef95b57c05e9a4ed3670782d2dddf84c |
| signature |
4 files changed, 40 insertions(+), 33 deletions(-)
lib/std/debug/Dwarf/Unwind.zig+20-13| ... | ... | @@ -433,7 +433,7 @@ pub const FrameDescriptionEntry = struct { |
| 433 | 433 | .lsb_z => { |
| 434 | 434 | // There is augmentation data, but it's irrelevant to us -- it |
| 435 | 435 | // only contains the LSDA pointer, which we don't care about. |
| 436 | const aug_data_len = try r.takeLeb128(u64); | |
| 436 | const aug_data_len = try r.takeLeb128(usize); | |
| 437 | 437 | _ = try r.discardAll(aug_data_len); |
| 438 | 438 | }, |
| 439 | 439 | } |
| ... | ... | @@ -463,17 +463,20 @@ pub fn prepareLookup(unwind: *Unwind, gpa: Allocator, addr_size_bytes: u8, endia |
| 463 | 463 | switch (try EntryHeader.read(&r, entry_offset, section.id, endian)) { |
| 464 | 464 | .cie => |cie_info| { |
| 465 | 465 | // Ignore CIEs for now; we'll parse them when we read a corresponding FDE |
| 466 | try r.discardAll(cie_info.bytes_len); | |
| 466 | try r.discardAll(cast(usize, cie_info.bytes_len) orelse return error.EndOfStream); | |
| 467 | 467 | continue; |
| 468 | 468 | }, |
| 469 | 469 | .fde => |fde_info| { |
| 470 | var cie_r: Reader = .fixed(section.bytes[fde_info.cie_offset..]); | |
| 470 | if (fde_info.cie_offset > section.bytes.len) return error.EndOfStream; | |
| 471 | var cie_r: Reader = .fixed(section.bytes[@intCast(fde_info.cie_offset)..]); | |
| 471 | 472 | const cie_info = switch (try EntryHeader.read(&cie_r, fde_info.cie_offset, section.id, endian)) { |
| 472 | 473 | .cie => |cie_info| cie_info, |
| 473 | 474 | .fde, .terminator => return bad(), // this is meant to be a CIE |
| 474 | 475 | }; |
| 475 | const cie: CommonInformationEntry = try .parse(try cie_r.take(cie_info.bytes_len), section.id, addr_size_bytes); | |
| 476 | const fde: FrameDescriptionEntry = try .parse(section.vaddr + r.seek, try r.take(fde_info.bytes_len), cie, endian); | |
| 476 | const cie_bytes_len = cast(usize, cie_info.bytes_len) orelse return error.EndOfStream; | |
| 477 | const fde_bytes_len = cast(usize, fde_info.bytes_len) orelse return error.EndOfStream; | |
| 478 | const cie: CommonInformationEntry = try .parse(try cie_r.take(cie_bytes_len), section.id, addr_size_bytes); | |
| 479 | const fde: FrameDescriptionEntry = try .parse(section.vaddr + r.seek, try r.take(fde_bytes_len), cie, endian); | |
| 477 | 480 | try fde_list.append(gpa, .{ |
| 478 | 481 | .pc_begin = fde.pc_begin, |
| 479 | 482 | .fde_offset = entry_offset, |
| ... | ... | @@ -537,27 +540,29 @@ pub fn lookupPc(unwind: *const Unwind, pc: u64, addr_size_bytes: u8, endian: End |
| 537 | 540 | pub fn getFde(unwind: *const Unwind, fde_offset: u64, addr_size_bytes: u8, endian: Endian) !struct { Format, CommonInformationEntry, FrameDescriptionEntry } { |
| 538 | 541 | const section = unwind.frame_section; |
| 539 | 542 | |
| 540 | var fde_reader: Reader = .fixed(section.bytes[fde_offset..]); | |
| 543 | if (fde_offset > section.bytes.len) return error.EndOfStream; | |
| 544 | var fde_reader: Reader = .fixed(section.bytes[@intCast(fde_offset)..]); | |
| 541 | 545 | const fde_info = switch (try EntryHeader.read(&fde_reader, fde_offset, section.id, endian)) { |
| 542 | 546 | .fde => |info| info, |
| 543 | 547 | .cie, .terminator => return bad(), // This is meant to be an FDE |
| 544 | 548 | }; |
| 545 | 549 | |
| 546 | 550 | const cie_offset = fde_info.cie_offset; |
| 547 | var cie_reader: Reader = .fixed(section.bytes[cie_offset..]); | |
| 551 | if (cie_offset > section.bytes.len) return error.EndOfStream; | |
| 552 | var cie_reader: Reader = .fixed(section.bytes[@intCast(cie_offset)..]); | |
| 548 | 553 | const cie_info = switch (try EntryHeader.read(&cie_reader, cie_offset, section.id, endian)) { |
| 549 | 554 | .cie => |info| info, |
| 550 | 555 | .fde, .terminator => return bad(), // This is meant to be a CIE |
| 551 | 556 | }; |
| 552 | 557 | |
| 553 | 558 | const cie: CommonInformationEntry = try .parse( |
| 554 | try cie_reader.take(cie_info.bytes_len), | |
| 559 | try cie_reader.take(cast(usize, cie_info.bytes_len) orelse return error.EndOfStream), | |
| 555 | 560 | section.id, |
| 556 | 561 | addr_size_bytes, |
| 557 | 562 | ); |
| 558 | 563 | const fde: FrameDescriptionEntry = try .parse( |
| 559 | 564 | section.vaddr + fde_offset + fde_reader.seek, |
| 560 | try fde_reader.take(fde_info.bytes_len), | |
| 565 | try fde_reader.take(cast(usize, fde_info.bytes_len) orelse return error.EndOfStream), | |
| 561 | 566 | cie, |
| 562 | 567 | endian, |
| 563 | 568 | ); |
| ... | ... | @@ -566,9 +571,8 @@ pub fn getFde(unwind: *const Unwind, fde_offset: u64, addr_size_bytes: u8, endia |
| 566 | 571 | } |
| 567 | 572 | |
| 568 | 573 | const EhPointerContext = struct { |
| 569 | // The address of the pointer field itself | |
| 574 | /// The address of the pointer field itself | |
| 570 | 575 | pc_rel_base: u64, |
| 571 | ||
| 572 | 576 | // These relative addressing modes are only used in specific cases, and |
| 573 | 577 | // might not be available / required in all parsing contexts |
| 574 | 578 | data_rel_base: ?u64 = null, |
| ... | ... | @@ -604,7 +608,7 @@ fn readEhPointerAbs(r: *Reader, enc_ty: EH.PE.Type, addr_size_bytes: u8, endian: |
| 604 | 608 | fn readEhPointer(r: *Reader, enc: EH.PE, addr_size_bytes: u8, ctx: EhPointerContext, endian: Endian) !u64 { |
| 605 | 609 | const offset = try readEhPointerAbs(r, enc.type, addr_size_bytes, endian); |
| 606 | 610 | if (enc.indirect) return bad(); // GCC extension; not supported |
| 607 | const base = switch (enc.rel) { | |
| 611 | const base: u64 = switch (enc.rel) { | |
| 608 | 612 | .abs, .aligned => 0, |
| 609 | 613 | .pcrel => ctx.pc_rel_base, |
| 610 | 614 | .textrel => ctx.text_rel_base orelse return bad(), |
| ... | ... | @@ -613,7 +617,10 @@ fn readEhPointer(r: *Reader, enc: EH.PE, addr_size_bytes: u8, ctx: EhPointerCont |
| 613 | 617 | _ => return bad(), |
| 614 | 618 | }; |
| 615 | 619 | return switch (offset) { |
| 616 | .signed => |s| @intCast(try std.math.add(i64, s, @as(i64, @intCast(base)))), | |
| 620 | .signed => |s| if (s >= 0) | |
| 621 | try std.math.add(u64, base, @intCast(s)) | |
| 622 | else | |
| 623 | try std.math.sub(u64, base, @intCast(-s)), | |
| 617 | 624 | // absptr can actually contain signed values in some cases (aarch64 MachO) |
| 618 | 625 | .unsigned => |u| u +% base, |
| 619 | 626 | }; |
lib/std/debug/ElfFile.zig+8-8| ... | ... | @@ -19,7 +19,7 @@ strtab: ?[]const u8, |
| 19 | 19 | symtab: ?SymtabSection, |
| 20 | 20 | |
| 21 | 21 | /// Binary search table lazily populated by `searchSymtab`. |
| 22 | symbol_search_table: ?[]u64, | |
| 22 | symbol_search_table: ?[]usize, | |
| 23 | 23 | |
| 24 | 24 | /// The memory-mapped ELF file, which is referenced by `dwarf`. This field is here only so that |
| 25 | 25 | /// this memory can be unmapped by `ElfFile.deinit`. |
| ... | ... | @@ -259,7 +259,7 @@ pub fn searchSymtab(ef: *ElfFile, gpa: Allocator, vaddr: u64) error{ |
| 259 | 259 | swap_endian: bool, |
| 260 | 260 | target: u64, |
| 261 | 261 | symbols: []align(1) const Sym, |
| 262 | fn predicate(ctx: @This(), sym_index: u64) bool { | |
| 262 | fn predicate(ctx: @This(), sym_index: usize) bool { | |
| 263 | 263 | // We need to return `true` for the first N items, then `false` for the rest -- |
| 264 | 264 | // the index we'll get out is the first `false` one. So, we'll return `true` iff |
| 265 | 265 | // the target address is after the *end* of this symbol. This synchronizes with |
| ... | ... | @@ -270,7 +270,7 @@ pub fn searchSymtab(ef: *ElfFile, gpa: Allocator, vaddr: u64) error{ |
| 270 | 270 | return ctx.target >= sym_end; |
| 271 | 271 | } |
| 272 | 272 | }; |
| 273 | const sym_index_index = std.sort.partitionPoint(u64, search_table, @as(SearchContext, .{ | |
| 273 | const sym_index_index = std.sort.partitionPoint(usize, search_table, @as(SearchContext, .{ | |
| 274 | 274 | .swap_endian = swap_endian, |
| 275 | 275 | .target = vaddr, |
| 276 | 276 | .symbols = symbols, |
| ... | ... | @@ -291,8 +291,8 @@ pub fn searchSymtab(ef: *ElfFile, gpa: Allocator, vaddr: u64) error{ |
| 291 | 291 | fn buildSymbolSearchTable(gpa: Allocator, endian: Endian, comptime Sym: type, symbols: []align(1) const Sym) error{ |
| 292 | 292 | OutOfMemory, |
| 293 | 293 | BadSymtab, |
| 294 | }![]u64 { | |
| 295 | var result: std.ArrayList(u64) = .empty; | |
| 294 | }![]usize { | |
| 295 | var result: std.ArrayList(usize) = .empty; | |
| 296 | 296 | defer result.deinit(gpa); |
| 297 | 297 | |
| 298 | 298 | const swap_endian = endian != @import("builtin").cpu.arch.endian(); |
| ... | ... | @@ -308,7 +308,7 @@ fn buildSymbolSearchTable(gpa: Allocator, endian: Endian, comptime Sym: type, sy |
| 308 | 308 | const SortContext = struct { |
| 309 | 309 | swap_endian: bool, |
| 310 | 310 | symbols: []align(1) const Sym, |
| 311 | fn lessThan(ctx: @This(), lhs_sym_index: u64, rhs_sym_index: u64) bool { | |
| 311 | fn lessThan(ctx: @This(), lhs_sym_index: usize, rhs_sym_index: usize) bool { | |
| 312 | 312 | // We sort by *end* address, not start address. This matches up with logic in `searchSymtab`. |
| 313 | 313 | var lhs_sym = ctx.symbols[lhs_sym_index]; |
| 314 | 314 | var rhs_sym = ctx.symbols[rhs_sym_index]; |
| ... | ... | @@ -321,7 +321,7 @@ fn buildSymbolSearchTable(gpa: Allocator, endian: Endian, comptime Sym: type, sy |
| 321 | 321 | return lhs_val < rhs_val; |
| 322 | 322 | } |
| 323 | 323 | }; |
| 324 | std.mem.sort(u64, result.items, @as(SortContext, .{ | |
| 324 | std.mem.sort(usize, result.items, @as(SortContext, .{ | |
| 325 | 325 | .swap_endian = swap_endian, |
| 326 | 326 | .symbols = symbols, |
| 327 | 327 | }), SortContext.lessThan); |
| ... | ... | @@ -504,7 +504,7 @@ fn loadInner( |
| 504 | 504 | continue; |
| 505 | 505 | } |
| 506 | 506 | |
| 507 | const buf = try arena.alloc(u8, ch_size); | |
| 507 | const buf = try arena.alloc(u8, std.math.cast(usize, ch_size) orelse return error.Overflow); | |
| 508 | 508 | var fw: std.Io.Writer = .fixed(buf); |
| 509 | 509 | var decompress: std.compress.flate.Decompress = .init(&section_reader, .zlib, &.{}); |
| 510 | 510 | const n = decompress.reader.streamRemaining(&fw) catch |err| switch (err) { |
lib/std/debug/SelfInfo/ElfModule.zig+10-11| ... | ... | @@ -200,7 +200,7 @@ fn loadUnwindInfo(module: *const ElfModule, gpa: Allocator, di: *DebugInfo) Erro |
| 200 | 200 | error.EndOfStream, error.Overflow => return error.InvalidDebugInfo, |
| 201 | 201 | error.UnsupportedAddrSize => return error.UnsupportedDebugInfo, |
| 202 | 202 | }; |
| 203 | buf[0] = .initEhFrameHdr(header, section_vaddr, @ptrFromInt(module.load_offset + header.eh_frame_vaddr)); | |
| 203 | buf[0] = .initEhFrameHdr(header, section_vaddr, @ptrFromInt(@as(usize, @intCast(module.load_offset + header.eh_frame_vaddr)))); | |
| 204 | 204 | break :unwinds buf[0..1]; |
| 205 | 205 | } else unwinds: { |
| 206 | 206 | // There is no `.eh_frame_hdr` section. There may still be an `.eh_frame` or `.debug_frame` |
| ... | ... | @@ -208,20 +208,19 @@ fn loadUnwindInfo(module: *const ElfModule, gpa: Allocator, di: *DebugInfo) Erro |
| 208 | 208 | try module.loadElf(gpa, di); |
| 209 | 209 | const opt_debug_frame = &di.loaded_elf.?.debug_frame; |
| 210 | 210 | const opt_eh_frame = &di.loaded_elf.?.eh_frame; |
| 211 | var i: usize = 0; | |
| 211 | 212 | // If both are present, we can't just pick one -- the info could be split between them. |
| 212 | 213 | // `.debug_frame` is likely to be the more complete section, so we'll prioritize that one. |
| 213 | 214 | if (opt_debug_frame.*) |*debug_frame| { |
| 214 | buf[0] = .initSection(.debug_frame, debug_frame.vaddr, debug_frame.bytes); | |
| 215 | if (opt_eh_frame.*) |*eh_frame| { | |
| 216 | buf[1] = .initSection(.eh_frame, eh_frame.vaddr, eh_frame.bytes); | |
| 217 | break :unwinds buf[0..2]; | |
| 218 | } | |
| 219 | break :unwinds buf[0..1]; | |
| 220 | } else if (opt_eh_frame.*) |*eh_frame| { | |
| 221 | buf[0] = .initSection(.eh_frame, eh_frame.vaddr, eh_frame.bytes); | |
| 222 | break :unwinds buf[0..1]; | |
| 215 | buf[i] = .initSection(.debug_frame, debug_frame.vaddr, debug_frame.bytes); | |
| 216 | i += 1; | |
| 217 | } | |
| 218 | if (opt_eh_frame.*) |*eh_frame| { | |
| 219 | buf[i] = .initSection(.eh_frame, eh_frame.vaddr, eh_frame.bytes); | |
| 220 | i += 1; | |
| 223 | 221 | } |
| 224 | return error.MissingDebugInfo; | |
| 222 | if (i == 0) return error.MissingDebugInfo; | |
| 223 | break :unwinds buf[0..i]; | |
| 225 | 224 | }; |
| 226 | 225 | errdefer for (unwinds) |*u| u.deinit(gpa); |
| 227 | 226 | for (unwinds) |*u| try prepareUnwindLookup(u, gpa); |
lib/std/elf.zig+2-1| ... | ... | @@ -744,7 +744,8 @@ pub const SectionHeaderBufferIterator = struct { |
| 744 | 744 | |
| 745 | 745 | const size: u64 = if (it.elf_header.is_64) @sizeOf(Elf64_Shdr) else @sizeOf(Elf32_Shdr); |
| 746 | 746 | const offset = it.elf_header.shoff + size * it.index; |
| 747 | var reader = std.Io.Reader.fixed(it.buf[offset..]); | |
| 747 | if (offset > it.buf.len) return error.EndOfStream; | |
| 748 | var reader = std.Io.Reader.fixed(it.buf[@intCast(offset)..]); | |
| 748 | 749 | |
| 749 | 750 | return takeShdr(&reader, it.elf_header); |
| 750 | 751 | } |