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 {...@@ -1857,15 +1857,26 @@ const ElfDumper = struct {
18571857
1858 fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 {1858 fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 {
1859 const gpa = step.owner.allocator;1859 const gpa = step.owner.allocator;
1860 var reader: std.Io.Reader = .fixed(bytes);
18611860
1862 const hdr = try reader.takeStruct(elf.Elf64_Ehdr, .little);1861 // `std.elf.Header` takes care of endianness issues for us.
1863 if (!mem.eql(u8, hdr.e_ident[0..4], "\x7fELF")) {1862 var reader: std.Io.Reader = .fixed(bytes);
1864 return error.InvalidMagicNumber;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;
1865 }1871 }
18661872
1867 const shdrs = @as([*]align(1) const elf.Elf64_Shdr, @ptrCast(bytes.ptr + hdr.e_shoff))[0..hdr.e_shnum];1873 var phdrs = try gpa.alloc(elf.Elf64_Phdr, hdr.shnum);
1868 const phdrs = @as([*]align(1) const elf.Elf64_Phdr, @ptrCast(bytes.ptr + hdr.e_phoff))[0..hdr.e_phnum];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
1870 var ctx = ObjectContext{1881 var ctx = ObjectContext{
1871 .gpa = gpa,1882 .gpa = gpa,
...@@ -1875,13 +1886,21 @@ const ElfDumper = struct {...@@ -1875,13 +1886,21 @@ const ElfDumper = struct {
1875 .phdrs = phdrs,1886 .phdrs = phdrs,
1876 .shstrtab = undefined,1887 .shstrtab = undefined,
1877 };1888 };
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
1880 for (ctx.shdrs, 0..) |shdr, i| switch (shdr.sh_type) {1895 for (ctx.shdrs, 0..) |shdr, i| switch (shdr.sh_type) {
1881 elf.SHT_SYMTAB, elf.SHT_DYNSYM => {1896 elf.SHT_SYMTAB, elf.SHT_DYNSYM => {
1882 const raw = ctx.getSectionContents(i);1897 const raw = ctx.getSectionContents(i);
1883 const nsyms = @divExact(raw.len, @sizeOf(elf.Elf64_Sym));1898 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
1885 const strings = ctx.getSectionContents(shdr.sh_link);1904 const strings = ctx.getSectionContents(shdr.sh_link);
18861905
1887 switch (shdr.sh_type) {1906 switch (shdr.sh_type) {
...@@ -1900,6 +1919,17 @@ const ElfDumper = struct {...@@ -1900,6 +1919,17 @@ const ElfDumper = struct {
1900 else => unreachable,1919 else => unreachable,
1901 }1920 }
1902 },1921 },
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
1904 else => {},1934 else => {},
1905 };1935 };
...@@ -1923,9 +1953,9 @@ const ElfDumper = struct {...@@ -1923,9 +1953,9 @@ const ElfDumper = struct {
1923 try ctx.dumpSymtab(.dysymtab, writer);1953 try ctx.dumpSymtab(.dysymtab, writer);
1924 } else return step.fail("no dynamic symbol table found", .{}),1954 } else return step.fail("no dynamic symbol table found", .{}),
19251955
1926 .dynamic_section => if (ctx.getSectionByName(".dynamic")) |shndx| {1956 .dynamic_section => if (ctx.dyns.len > 0) {
1927 try ctx.dumpDynamicSection(shndx, writer);1957 try ctx.dumpDynamicSection(writer);
1928 } else return step.fail("no .dynamic section found", .{}),1958 } else return step.fail("no dynamic section found", .{}),
19291959
1930 .dump_section => {1960 .dump_section => {
1931 const name = mem.sliceTo(@as([*:0]const u8, @ptrCast(check.data.items.ptr + check.payload.dump_section)), 0);1961 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 {...@@ -1942,17 +1972,19 @@ const ElfDumper = struct {
1942 const ObjectContext = struct {1972 const ObjectContext = struct {
1943 gpa: Allocator,1973 gpa: Allocator,
1944 data: []const u8,1974 data: []const u8,
1945 hdr: elf.Elf64_Ehdr,1975 hdr: elf.Header,
1946 shdrs: []align(1) const elf.Elf64_Shdr,1976 shdrs: []const elf.Elf64_Shdr,
1947 phdrs: []align(1) const elf.Elf64_Phdr,1977 phdrs: []const elf.Elf64_Phdr,
1948 shstrtab: []const u8,1978 shstrtab: []const u8,
1949 symtab: Symtab = .{},1979 symtab: Symtab = .{},
1950 dysymtab: Symtab = .{},1980 dysymtab: Symtab = .{},
1981 dyns: []const elf.Elf64_Dyn = &.{},
1982 dyns_strings: []const u8 = &.{},
19511983
1952 fn dumpHeader(ctx: ObjectContext, writer: anytype) !void {1984 fn dumpHeader(ctx: ObjectContext, writer: anytype) !void {
1953 try writer.writeAll("header\n");1985 try writer.writeAll("header\n");
1954 try writer.print("type {s}\n", .{@tagName(ctx.hdr.e_type)});1986 try writer.print("type {s}\n", .{@tagName(ctx.hdr.type)});
1955 try writer.print("entry {x}\n", .{ctx.hdr.e_entry});1987 try writer.print("entry {x}\n", .{ctx.hdr.entry});
1956 }1988 }
19571989
1958 fn dumpPhdrs(ctx: ObjectContext, writer: anytype) !void {1990 fn dumpPhdrs(ctx: ObjectContext, writer: anytype) !void {
...@@ -2011,16 +2043,10 @@ const ElfDumper = struct {...@@ -2011,16 +2043,10 @@ const ElfDumper = struct {
2011 }2043 }
2012 }2044 }
20132045
2014 fn dumpDynamicSection(ctx: ObjectContext, shndx: usize, writer: anytype) !void {2046 fn dumpDynamicSection(ctx: ObjectContext, 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
2021 try writer.writeAll(ElfDumper.dynamic_section_label ++ "\n");2047 try writer.writeAll(ElfDumper.dynamic_section_label ++ "\n");
20222048
2023 for (entries) |entry| {2049 for (ctx.dyns) |entry| {
2024 const key = @as(u64, @bitCast(entry.d_tag));2050 const key = @as(u64, @bitCast(entry.d_tag));
2025 const value = entry.d_val;2051 const value = entry.d_val;
20262052
...@@ -2067,7 +2093,7 @@ const ElfDumper = struct {...@@ -2067,7 +2093,7 @@ const ElfDumper = struct {
2067 elf.DT_RPATH,2093 elf.DT_RPATH,
2068 elf.DT_RUNPATH,2094 elf.DT_RUNPATH,
2069 => {2095 => {
2070 const name = getString(strtab, @intCast(value));2096 const name = getString(ctx.dyns_strings, @intCast(value));
2071 try writer.print(" {s}", .{name});2097 try writer.print(" {s}", .{name});
2072 },2098 },
20732099
...@@ -2256,8 +2282,8 @@ const ElfDumper = struct {...@@ -2256,8 +2282,8 @@ const ElfDumper = struct {
2256 };2282 };
22572283
2258 const Symtab = struct {2284 const Symtab = struct {
2259 symbols: []align(1) const elf.Elf64_Sym = &[0]elf.Elf64_Sym{},2285 symbols: []const elf.Elf64_Sym = &.{},
2260 strings: []const u8 = &[0]u8{},2286 strings: []const u8 = &.{},
22612287
2262 fn get(st: Symtab, index: usize) ?elf.Elf64_Sym {2288 fn get(st: Symtab, index: usize) ?elf.Elf64_Sym {
2263 if (index >= st.symbols.len) return null;2289 if (index >= st.symbols.len) return null;