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