authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-11-18 00:06:07+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-11-19 01:42:45+01:00
logacfb88e9a51944260cdeb12811fc18709c629e2c
treea5e732b42f757c0049549d7f81fedca38c9ed1fd
parente09ba67161738e2fad2e699b27f9772a35dfdc16
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

std.Build.Step.CheckObject: make ELF reading endianness-aware


1 files changed, 53 insertions(+), 27 deletions(-)

lib/std/Build/Step/CheckObject.zig+53-27
......@@ -1857,15 +1857,26 @@ const ElfDumper = struct {
18571857
18581858 fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
18591859 const gpa = step.owner.allocator;
1860 var reader: std.Io.Reader = .fixed(bytes);
18611860
1862 const hdr = try reader.takeStruct(elf.Elf64_Ehdr, .little);
1863 if (!mem.eql(u8, hdr.e_ident[0..4], "\x7fELF")) {
1864 return error.InvalidMagicNumber;
1861 // `std.elf.Header` takes care of endianness issues for us.
1862 var reader: std.Io.Reader = .fixed(bytes);
1863 const hdr = try elf.Header.read(&reader);
1864
1865 var shdrs = try gpa.alloc(elf.Elf64_Shdr, hdr.shnum);
1866 defer gpa.free(shdrs);
1867 {
1868 var shdr_it = hdr.iterateSectionHeadersBuffer(bytes);
1869 var shdr_i: usize = 0;
1870 while (try shdr_it.next()) |shdr| : (shdr_i += 1) shdrs[shdr_i] = shdr;
18651871 }
18661872
1867 const shdrs = @as([*]align(1) const elf.Elf64_Shdr, @ptrCast(bytes.ptr + hdr.e_shoff))[0..hdr.e_shnum];
1868 const phdrs = @as([*]align(1) const elf.Elf64_Phdr, @ptrCast(bytes.ptr + hdr.e_phoff))[0..hdr.e_phnum];
1873 var phdrs = try gpa.alloc(elf.Elf64_Phdr, hdr.shnum);
1874 defer gpa.free(phdrs);
1875 {
1876 var phdr_it = hdr.iterateProgramHeadersBuffer(bytes);
1877 var phdr_i: usize = 0;
1878 while (try phdr_it.next()) |phdr| : (phdr_i += 1) phdrs[phdr_i] = phdr;
1879 }
18691880
18701881 var ctx = ObjectContext{
18711882 .gpa = gpa,
......@@ -1875,13 +1886,21 @@ const ElfDumper = struct {
18751886 .phdrs = phdrs,
18761887 .shstrtab = undefined,
18771888 };
1878 ctx.shstrtab = ctx.getSectionContents(ctx.hdr.e_shstrndx);
1889 ctx.shstrtab = ctx.getSectionContents(ctx.hdr.shstrndx);
1890
1891 defer gpa.free(ctx.symtab.symbols);
1892 defer gpa.free(ctx.dysymtab.symbols);
1893 defer gpa.free(ctx.dyns);
18791894
18801895 for (ctx.shdrs, 0..) |shdr, i| switch (shdr.sh_type) {
18811896 elf.SHT_SYMTAB, elf.SHT_DYNSYM => {
18821897 const raw = ctx.getSectionContents(i);
18831898 const nsyms = @divExact(raw.len, @sizeOf(elf.Elf64_Sym));
1884 const symbols = @as([*]align(1) const elf.Elf64_Sym, @ptrCast(raw.ptr))[0..nsyms];
1899 const symbols = try gpa.alloc(elf.Elf64_Sym, nsyms);
1900
1901 var r: std.Io.Reader = .fixed(raw);
1902 for (0..nsyms) |si| symbols[si] = r.takeStruct(elf.Elf64_Sym, ctx.hdr.endian) catch unreachable;
1903
18851904 const strings = ctx.getSectionContents(shdr.sh_link);
18861905
18871906 switch (shdr.sh_type) {
......@@ -1900,6 +1919,17 @@ const ElfDumper = struct {
19001919 else => unreachable,
19011920 }
19021921 },
1922 elf.SHT_DYNAMIC => {
1923 const raw = ctx.getSectionContents(i);
1924 const ndyns = @divExact(raw.len, @sizeOf(elf.Elf64_Dyn));
1925 const dyns = try gpa.alloc(elf.Elf64_Dyn, ndyns);
1926
1927 var r: std.Io.Reader = .fixed(raw);
1928 for (0..ndyns) |si| dyns[si] = r.takeStruct(elf.Elf64_Dyn, ctx.hdr.endian) catch unreachable;
1929
1930 ctx.dyns = dyns;
1931 ctx.dyns_strings = ctx.getSectionContents(shdr.sh_link);
1932 },
19031933
19041934 else => {},
19051935 };
......@@ -1923,9 +1953,9 @@ const ElfDumper = struct {
19231953 try ctx.dumpSymtab(.dysymtab, writer);
19241954 } else return step.fail("no dynamic symbol table found", .{}),
19251955
1926 .dynamic_section => if (ctx.getSectionByName(".dynamic")) |shndx| {
1927 try ctx.dumpDynamicSection(shndx, writer);
1928 } else return step.fail("no .dynamic section found", .{}),
1956 .dynamic_section => if (ctx.dyns.len > 0) {
1957 try ctx.dumpDynamicSection(writer);
1958 } else return step.fail("no dynamic section found", .{}),
19291959
19301960 .dump_section => {
19311961 const name = mem.sliceTo(@as([*:0]const u8, @ptrCast(check.data.items.ptr + check.payload.dump_section)), 0);
......@@ -1942,17 +1972,19 @@ const ElfDumper = struct {
19421972 const ObjectContext = struct {
19431973 gpa: Allocator,
19441974 data: []const u8,
1945 hdr: elf.Elf64_Ehdr,
1946 shdrs: []align(1) const elf.Elf64_Shdr,
1947 phdrs: []align(1) const elf.Elf64_Phdr,
1975 hdr: elf.Header,
1976 shdrs: []const elf.Elf64_Shdr,
1977 phdrs: []const elf.Elf64_Phdr,
19481978 shstrtab: []const u8,
19491979 symtab: Symtab = .{},
19501980 dysymtab: Symtab = .{},
1981 dyns: []const elf.Elf64_Dyn = &.{},
1982 dyns_strings: []const u8 = &.{},
19511983
19521984 fn dumpHeader(ctx: ObjectContext, writer: anytype) !void {
19531985 try writer.writeAll("header\n");
1954 try writer.print("type {s}\n", .{@tagName(ctx.hdr.e_type)});
1955 try writer.print("entry {x}\n", .{ctx.hdr.e_entry});
1986 try writer.print("type {s}\n", .{@tagName(ctx.hdr.type)});
1987 try writer.print("entry {x}\n", .{ctx.hdr.entry});
19561988 }
19571989
19581990 fn dumpPhdrs(ctx: ObjectContext, writer: anytype) !void {
......@@ -2011,16 +2043,10 @@ const ElfDumper = struct {
20112043 }
20122044 }
20132045
2014 fn dumpDynamicSection(ctx: ObjectContext, shndx: usize, writer: anytype) !void {
2015 const shdr = ctx.shdrs[shndx];
2016 const strtab = ctx.getSectionContents(shdr.sh_link);
2017 const data = ctx.getSectionContents(shndx);
2018 const nentries = @divExact(data.len, @sizeOf(elf.Elf64_Dyn));
2019 const entries = @as([*]align(1) const elf.Elf64_Dyn, @ptrCast(data.ptr))[0..nentries];
2020
2046 fn dumpDynamicSection(ctx: ObjectContext, writer: anytype) !void {
20212047 try writer.writeAll(ElfDumper.dynamic_section_label ++ "\n");
20222048
2023 for (entries) |entry| {
2049 for (ctx.dyns) |entry| {
20242050 const key = @as(u64, @bitCast(entry.d_tag));
20252051 const value = entry.d_val;
20262052
......@@ -2067,7 +2093,7 @@ const ElfDumper = struct {
20672093 elf.DT_RPATH,
20682094 elf.DT_RUNPATH,
20692095 => {
2070 const name = getString(strtab, @intCast(value));
2096 const name = getString(ctx.dyns_strings, @intCast(value));
20712097 try writer.print(" {s}", .{name});
20722098 },
20732099
......@@ -2256,8 +2282,8 @@ const ElfDumper = struct {
22562282 };
22572283
22582284 const Symtab = struct {
2259 symbols: []align(1) const elf.Elf64_Sym = &[0]elf.Elf64_Sym{},
2260 strings: []const u8 = &[0]u8{},
2285 symbols: []const elf.Elf64_Sym = &.{},
2286 strings: []const u8 = &.{},
22612287
22622288 fn get(st: Symtab, index: usize) ?elf.Elf64_Sym {
22632289 if (index >= st.symbols.len) return null;