| ... | ... | @@ -1857,15 +1857,26 @@ const ElfDumper = struct { |
| 1857 | 1857 | |
| 1858 | 1858 | fn parseAndDumpObject(step: *Step, check: Check, bytes: []const u8) ![]const u8 { |
| 1859 | 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); |
| 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; |
| 1865 | 1871 | } |
| 1866 | 1872 | |
| 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 | } |
| 1869 | 1880 | |
| 1870 | 1881 | var ctx = ObjectContext{ |
| 1871 | 1882 | .gpa = gpa, |
| ... | ... | @@ -1875,13 +1886,21 @@ const ElfDumper = struct { |
| 1875 | 1886 | .phdrs = phdrs, |
| 1876 | 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 | 1895 | for (ctx.shdrs, 0..) |shdr, i| switch (shdr.sh_type) { |
| 1881 | 1896 | elf.SHT_SYMTAB, elf.SHT_DYNSYM => { |
| 1882 | 1897 | const raw = ctx.getSectionContents(i); |
| 1883 | 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 | 1904 | const strings = ctx.getSectionContents(shdr.sh_link); |
| 1886 | 1905 | |
| 1887 | 1906 | switch (shdr.sh_type) { |
| ... | ... | @@ -1900,6 +1919,17 @@ const ElfDumper = struct { |
| 1900 | 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 | 1934 | else => {}, |
| 1905 | 1935 | }; |
| ... | ... | @@ -1923,9 +1953,9 @@ const ElfDumper = struct { |
| 1923 | 1953 | try ctx.dumpSymtab(.dysymtab, writer); |
| 1924 | 1954 | } else return step.fail("no dynamic symbol table found", .{}), |
| 1925 | 1955 | |
| 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", .{}), |
| 1929 | 1959 | |
| 1930 | 1960 | .dump_section => { |
| 1931 | 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 | 1972 | const ObjectContext = struct { |
| 1943 | 1973 | gpa: Allocator, |
| 1944 | 1974 | 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, |
| 1948 | 1978 | shstrtab: []const u8, |
| 1949 | 1979 | symtab: Symtab = .{}, |
| 1950 | 1980 | dysymtab: Symtab = .{}, |
| 1981 | dyns: []const elf.Elf64_Dyn = &.{}, |
| 1982 | dyns_strings: []const u8 = &.{}, |
| 1951 | 1983 | |
| 1952 | 1984 | fn dumpHeader(ctx: ObjectContext, writer: anytype) !void { |
| 1953 | 1985 | 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}); |
| 1956 | 1988 | } |
| 1957 | 1989 | |
| 1958 | 1990 | fn dumpPhdrs(ctx: ObjectContext, writer: anytype) !void { |
| ... | ... | @@ -2011,16 +2043,10 @@ const ElfDumper = struct { |
| 2011 | 2043 | } |
| 2012 | 2044 | } |
| 2013 | 2045 | |
| 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 { |
| 2021 | 2047 | try writer.writeAll(ElfDumper.dynamic_section_label ++ "\n"); |
| 2022 | 2048 | |
| 2023 | | for (entries) |entry| { |
| 2049 | for (ctx.dyns) |entry| { |
| 2024 | 2050 | const key = @as(u64, @bitCast(entry.d_tag)); |
| 2025 | 2051 | const value = entry.d_val; |
| 2026 | 2052 | |
| ... | ... | @@ -2067,7 +2093,7 @@ const ElfDumper = struct { |
| 2067 | 2093 | elf.DT_RPATH, |
| 2068 | 2094 | elf.DT_RUNPATH, |
| 2069 | 2095 | => { |
| 2070 | | const name = getString(strtab, @intCast(value)); |
| 2096 | const name = getString(ctx.dyns_strings, @intCast(value)); |
| 2071 | 2097 | try writer.print(" {s}", .{name}); |
| 2072 | 2098 | }, |
| 2073 | 2099 | |
| ... | ... | @@ -2256,8 +2282,8 @@ const ElfDumper = struct { |
| 2256 | 2282 | }; |
| 2257 | 2283 | |
| 2258 | 2284 | 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 = &.{}, |
| 2261 | 2287 | |
| 2262 | 2288 | fn get(st: Symtab, index: usize) ?elf.Elf64_Sym { |
| 2263 | 2289 | if (index >= st.symbols.len) return null; |