| ... | @@ -1857,15 +1857,26 @@ const ElfDumper = struct { | ... | @@ -1857,15 +1857,26 @@ const ElfDumper = struct { |
| 1857 | | 1857 | |
| 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); | | |
| 1861 | | 1860 | |
| 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 | } |
| 1866 | | 1872 | |
| 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 | } |
| 1869 | | 1880 | |
| 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); |
| 1879 | | 1894 | |
| 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); |
| 1886 | | 1905 | |
| 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 | }, |
| 1903 | | 1933 | |
| 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", .{}), |
| 1925 | | 1955 | |
| 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", .{}), |
| 1929 | | 1959 | |
| 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 = &.{}, |
| 1951 | | 1983 | |
| 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 | } |
| 1957 | | 1989 | |
| 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 | } |
| 2013 | | 2045 | |
| 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"); |
| 2022 | | 2048 | |
| 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; |
| 2026 | | 2052 | |
| ... | @@ -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 | }, |
| 2073 | | 2099 | |
| ... | @@ -2256,8 +2282,8 @@ const ElfDumper = struct { | ... | @@ -2256,8 +2282,8 @@ const ElfDumper = struct { |
| 2256 | }; | 2282 | }; |
| 2257 | | 2283 | |
| 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 = &.{}, |
| 2261 | | 2287 | |
| 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; |