authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-09-11 13:42:51+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-09-30 13:44:53+01:00
log9901b9389ed963ff262d1ce4973029a570035f19
treec640810510f6c8fcbb2885cd273d86b70ae8ad07
parent7601b397ef95b57c05e9a4ed3670782d2dddf84c
signaturelock-open Commit is signed but in an unrecognized format.

std: fix 32-bit build and some unsafe casts


4 files changed, 40 insertions(+), 33 deletions(-)

lib/std/debug/Dwarf/Unwind.zig+20-13
......@@ -433,7 +433,7 @@ pub const FrameDescriptionEntry = struct {
433433 .lsb_z => {
434434 // There is augmentation data, but it's irrelevant to us -- it
435435 // 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);
437437 _ = try r.discardAll(aug_data_len);
438438 },
439439 }
......@@ -463,17 +463,20 @@ pub fn prepareLookup(unwind: *Unwind, gpa: Allocator, addr_size_bytes: u8, endia
463463 switch (try EntryHeader.read(&r, entry_offset, section.id, endian)) {
464464 .cie => |cie_info| {
465465 // 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);
467467 continue;
468468 },
469469 .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)..]);
471472 const cie_info = switch (try EntryHeader.read(&cie_r, fde_info.cie_offset, section.id, endian)) {
472473 .cie => |cie_info| cie_info,
473474 .fde, .terminator => return bad(), // this is meant to be a CIE
474475 };
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);
477480 try fde_list.append(gpa, .{
478481 .pc_begin = fde.pc_begin,
479482 .fde_offset = entry_offset,
......@@ -537,27 +540,29 @@ pub fn lookupPc(unwind: *const Unwind, pc: u64, addr_size_bytes: u8, endian: End
537540pub fn getFde(unwind: *const Unwind, fde_offset: u64, addr_size_bytes: u8, endian: Endian) !struct { Format, CommonInformationEntry, FrameDescriptionEntry } {
538541 const section = unwind.frame_section;
539542
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)..]);
541545 const fde_info = switch (try EntryHeader.read(&fde_reader, fde_offset, section.id, endian)) {
542546 .fde => |info| info,
543547 .cie, .terminator => return bad(), // This is meant to be an FDE
544548 };
545549
546550 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)..]);
548553 const cie_info = switch (try EntryHeader.read(&cie_reader, cie_offset, section.id, endian)) {
549554 .cie => |info| info,
550555 .fde, .terminator => return bad(), // This is meant to be a CIE
551556 };
552557
553558 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),
555560 section.id,
556561 addr_size_bytes,
557562 );
558563 const fde: FrameDescriptionEntry = try .parse(
559564 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),
561566 cie,
562567 endian,
563568 );
......@@ -566,9 +571,8 @@ pub fn getFde(unwind: *const Unwind, fde_offset: u64, addr_size_bytes: u8, endia
566571}
567572
568573const EhPointerContext = struct {
569 // The address of the pointer field itself
574 /// The address of the pointer field itself
570575 pc_rel_base: u64,
571
572576 // These relative addressing modes are only used in specific cases, and
573577 // might not be available / required in all parsing contexts
574578 data_rel_base: ?u64 = null,
......@@ -604,7 +608,7 @@ fn readEhPointerAbs(r: *Reader, enc_ty: EH.PE.Type, addr_size_bytes: u8, endian:
604608fn readEhPointer(r: *Reader, enc: EH.PE, addr_size_bytes: u8, ctx: EhPointerContext, endian: Endian) !u64 {
605609 const offset = try readEhPointerAbs(r, enc.type, addr_size_bytes, endian);
606610 if (enc.indirect) return bad(); // GCC extension; not supported
607 const base = switch (enc.rel) {
611 const base: u64 = switch (enc.rel) {
608612 .abs, .aligned => 0,
609613 .pcrel => ctx.pc_rel_base,
610614 .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
613617 _ => return bad(),
614618 };
615619 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)),
617624 // absptr can actually contain signed values in some cases (aarch64 MachO)
618625 .unsigned => |u| u +% base,
619626 };
lib/std/debug/ElfFile.zig+8-8
......@@ -19,7 +19,7 @@ strtab: ?[]const u8,
1919symtab: ?SymtabSection,
2020
2121/// Binary search table lazily populated by `searchSymtab`.
22symbol_search_table: ?[]u64,
22symbol_search_table: ?[]usize,
2323
2424/// The memory-mapped ELF file, which is referenced by `dwarf`. This field is here only so that
2525/// this memory can be unmapped by `ElfFile.deinit`.
......@@ -259,7 +259,7 @@ pub fn searchSymtab(ef: *ElfFile, gpa: Allocator, vaddr: u64) error{
259259 swap_endian: bool,
260260 target: u64,
261261 symbols: []align(1) const Sym,
262 fn predicate(ctx: @This(), sym_index: u64) bool {
262 fn predicate(ctx: @This(), sym_index: usize) bool {
263263 // We need to return `true` for the first N items, then `false` for the rest --
264264 // the index we'll get out is the first `false` one. So, we'll return `true` iff
265265 // 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{
270270 return ctx.target >= sym_end;
271271 }
272272 };
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, .{
274274 .swap_endian = swap_endian,
275275 .target = vaddr,
276276 .symbols = symbols,
......@@ -291,8 +291,8 @@ pub fn searchSymtab(ef: *ElfFile, gpa: Allocator, vaddr: u64) error{
291291fn buildSymbolSearchTable(gpa: Allocator, endian: Endian, comptime Sym: type, symbols: []align(1) const Sym) error{
292292 OutOfMemory,
293293 BadSymtab,
294}![]u64 {
295 var result: std.ArrayList(u64) = .empty;
294}![]usize {
295 var result: std.ArrayList(usize) = .empty;
296296 defer result.deinit(gpa);
297297
298298 const swap_endian = endian != @import("builtin").cpu.arch.endian();
......@@ -308,7 +308,7 @@ fn buildSymbolSearchTable(gpa: Allocator, endian: Endian, comptime Sym: type, sy
308308 const SortContext = struct {
309309 swap_endian: bool,
310310 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 {
312312 // We sort by *end* address, not start address. This matches up with logic in `searchSymtab`.
313313 var lhs_sym = ctx.symbols[lhs_sym_index];
314314 var rhs_sym = ctx.symbols[rhs_sym_index];
......@@ -321,7 +321,7 @@ fn buildSymbolSearchTable(gpa: Allocator, endian: Endian, comptime Sym: type, sy
321321 return lhs_val < rhs_val;
322322 }
323323 };
324 std.mem.sort(u64, result.items, @as(SortContext, .{
324 std.mem.sort(usize, result.items, @as(SortContext, .{
325325 .swap_endian = swap_endian,
326326 .symbols = symbols,
327327 }), SortContext.lessThan);
......@@ -504,7 +504,7 @@ fn loadInner(
504504 continue;
505505 }
506506
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);
508508 var fw: std.Io.Writer = .fixed(buf);
509509 var decompress: std.compress.flate.Decompress = .init(&section_reader, .zlib, &.{});
510510 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
200200 error.EndOfStream, error.Overflow => return error.InvalidDebugInfo,
201201 error.UnsupportedAddrSize => return error.UnsupportedDebugInfo,
202202 };
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))));
204204 break :unwinds buf[0..1];
205205 } else unwinds: {
206206 // 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
208208 try module.loadElf(gpa, di);
209209 const opt_debug_frame = &di.loaded_elf.?.debug_frame;
210210 const opt_eh_frame = &di.loaded_elf.?.eh_frame;
211 var i: usize = 0;
211212 // If both are present, we can't just pick one -- the info could be split between them.
212213 // `.debug_frame` is likely to be the more complete section, so we'll prioritize that one.
213214 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;
223221 }
224 return error.MissingDebugInfo;
222 if (i == 0) return error.MissingDebugInfo;
223 break :unwinds buf[0..i];
225224 };
226225 errdefer for (unwinds) |*u| u.deinit(gpa);
227226 for (unwinds) |*u| try prepareUnwindLookup(u, gpa);
lib/std/elf.zig+2-1
......@@ -744,7 +744,8 @@ pub const SectionHeaderBufferIterator = struct {
744744
745745 const size: u64 = if (it.elf_header.is_64) @sizeOf(Elf64_Shdr) else @sizeOf(Elf32_Shdr);
746746 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)..]);
748749
749750 return takeShdr(&reader, it.elf_header);
750751 }