| ... | @@ -712,8 +712,7 @@ const ElfDumper = struct { | ... | @@ -712,8 +712,7 @@ const ElfDumper = struct { |
| 712 | | 712 | |
| 713 | fn getName(st: Symtab, index: usize) ?[]const u8 { | 713 | fn getName(st: Symtab, index: usize) ?[]const u8 { |
| 714 | const sym = st.get(index) orelse return null; | 714 | const sym = st.get(index) orelse return null; |
| 715 | assert(sym.st_name < st.strings.len); | 715 | return getString(st.strings, sym.st_name); |
| 716 | return mem.sliceTo(@ptrCast(st.strings.ptr + sym.st_name), 0); | | |
| 717 | } | 716 | } |
| 718 | }; | 717 | }; |
| 719 | | 718 | |
| ... | @@ -786,6 +785,7 @@ const ElfDumper = struct { | ... | @@ -786,6 +785,7 @@ const ElfDumper = struct { |
| 786 | try dumpHeader(ctx, writer); | 785 | try dumpHeader(ctx, writer); |
| 787 | try dumpShdrs(ctx, writer); | 786 | try dumpShdrs(ctx, writer); |
| 788 | try dumpPhdrs(ctx, writer); | 787 | try dumpPhdrs(ctx, writer); |
| | 788 | try dumpDynamic(ctx, writer); |
| 789 | | 789 | |
| 790 | return output.toOwnedSlice(); | 790 | return output.toOwnedSlice(); |
| 791 | } | 791 | } |
| ... | @@ -803,6 +803,17 @@ const ElfDumper = struct { | ... | @@ -803,6 +803,17 @@ const ElfDumper = struct { |
| 803 | return ctx.data[shdr.sh_offset..][0..shdr.sh_size]; | 803 | return ctx.data[shdr.sh_offset..][0..shdr.sh_size]; |
| 804 | } | 804 | } |
| 805 | | 805 | |
| | 806 | fn getSectionByName(ctx: Context, name: []const u8) ?usize { |
| | 807 | for (0..ctx.shdrs.len) |shndx| { |
| | 808 | if (mem.eql(u8, getSectionName(ctx, shndx), name)) return shndx; |
| | 809 | } else return null; |
| | 810 | } |
| | 811 | |
| | 812 | fn getString(strtab: []const u8, off: u32) []const u8 { |
| | 813 | assert(off < strtab.len); |
| | 814 | return mem.sliceTo(@as([*:0]const u8, @ptrCast(strtab.ptr + off)), 0); |
| | 815 | } |
| | 816 | |
| 806 | fn dumpHeader(ctx: Context, writer: anytype) !void { | 817 | fn dumpHeader(ctx: Context, writer: anytype) !void { |
| 807 | try writer.writeAll("header\n"); | 818 | try writer.writeAll("header\n"); |
| 808 | try writer.print("type {s}\n", .{@tagName(ctx.hdr.e_type)}); | 819 | try writer.print("type {s}\n", .{@tagName(ctx.hdr.e_type)}); |
| ... | @@ -824,6 +835,143 @@ const ElfDumper = struct { | ... | @@ -824,6 +835,143 @@ const ElfDumper = struct { |
| 824 | } | 835 | } |
| 825 | } | 836 | } |
| 826 | | 837 | |
| | 838 | fn dumpDynamic(ctx: Context, writer: anytype) !void { |
| | 839 | const shndx = getSectionByName(ctx, ".dynamic") orelse return; |
| | 840 | const shdr = ctx.shdrs[shndx]; |
| | 841 | const strtab = getSectionContents(ctx, shdr.sh_link); |
| | 842 | const data = getSectionContents(ctx, shndx); |
| | 843 | const nentries = @divExact(data.len, @sizeOf(elf.Elf64_Dyn)); |
| | 844 | const entries = @as([*]align(1) const elf.Elf64_Dyn, @ptrCast(data.ptr))[0..nentries]; |
| | 845 | |
| | 846 | for (entries) |entry| { |
| | 847 | const key = @as(u64, @bitCast(entry.d_tag)); |
| | 848 | const value = entry.d_val; |
| | 849 | |
| | 850 | const key_str = switch (key) { |
| | 851 | elf.DT_NEEDED => "NEEDED", |
| | 852 | elf.DT_SONAME => "SONAME", |
| | 853 | elf.DT_INIT_ARRAY => "INIT_ARRAY", |
| | 854 | elf.DT_INIT_ARRAYSZ => "INIT_ARRAYSZ", |
| | 855 | elf.DT_FINI_ARRAY => "FINI_ARRAY", |
| | 856 | elf.DT_FINI_ARRAYSZ => "FINI_ARRAYSZ", |
| | 857 | elf.DT_HASH => "HASH", |
| | 858 | elf.DT_GNU_HASH => "GNU_HASH", |
| | 859 | elf.DT_STRTAB => "STRTAB", |
| | 860 | elf.DT_SYMTAB => "SYMTAB", |
| | 861 | elf.DT_STRSZ => "STRSZ", |
| | 862 | elf.DT_SYMENT => "SYMENT", |
| | 863 | elf.DT_PLTGOT => "PLTGOT", |
| | 864 | elf.DT_PLTRELSZ => "PLTRELSZ", |
| | 865 | elf.DT_PLTREL => "PLTREL", |
| | 866 | elf.DT_JMPREL => "JMPREL", |
| | 867 | elf.DT_RELA => "RELA", |
| | 868 | elf.DT_RELASZ => "RELASZ", |
| | 869 | elf.DT_RELAENT => "RELAENT", |
| | 870 | elf.DT_VERDEF => "VERDEF", |
| | 871 | elf.DT_VERDEFNUM => "VERDEFNUM", |
| | 872 | elf.DT_FLAGS => "FLAGS", |
| | 873 | elf.DT_FLAGS_1 => "FLAGS_1", |
| | 874 | elf.DT_VERNEED => "VERNEED", |
| | 875 | elf.DT_VERNEEDNUM => "VERNEEDNUM", |
| | 876 | elf.DT_VERSYM => "VERSYM", |
| | 877 | elf.DT_RELACOUNT => "RELACOUNT", |
| | 878 | elf.DT_RPATH => "RPATH", |
| | 879 | elf.DT_RUNPATH => "RUNPATH", |
| | 880 | elf.DT_INIT => "INIT", |
| | 881 | elf.DT_FINI => "FINI", |
| | 882 | elf.DT_NULL => "NULL", |
| | 883 | else => "UNKNOWN", |
| | 884 | }; |
| | 885 | try writer.print("{s}", .{key_str}); |
| | 886 | |
| | 887 | switch (key) { |
| | 888 | elf.DT_NEEDED, |
| | 889 | elf.DT_SONAME, |
| | 890 | elf.DT_RPATH, |
| | 891 | elf.DT_RUNPATH, |
| | 892 | => { |
| | 893 | const name = getString(strtab, @intCast(value)); |
| | 894 | try writer.print(" {s}", .{name}); |
| | 895 | }, |
| | 896 | |
| | 897 | elf.DT_INIT_ARRAY, |
| | 898 | elf.DT_FINI_ARRAY, |
| | 899 | elf.DT_HASH, |
| | 900 | elf.DT_GNU_HASH, |
| | 901 | elf.DT_STRTAB, |
| | 902 | elf.DT_SYMTAB, |
| | 903 | elf.DT_PLTGOT, |
| | 904 | elf.DT_JMPREL, |
| | 905 | elf.DT_RELA, |
| | 906 | elf.DT_VERDEF, |
| | 907 | elf.DT_VERNEED, |
| | 908 | elf.DT_VERSYM, |
| | 909 | elf.DT_INIT, |
| | 910 | elf.DT_FINI, |
| | 911 | elf.DT_NULL, |
| | 912 | => try writer.print(" {x}", .{value}), |
| | 913 | |
| | 914 | elf.DT_INIT_ARRAYSZ, |
| | 915 | elf.DT_FINI_ARRAYSZ, |
| | 916 | elf.DT_STRSZ, |
| | 917 | elf.DT_SYMENT, |
| | 918 | elf.DT_PLTRELSZ, |
| | 919 | elf.DT_RELASZ, |
| | 920 | elf.DT_RELAENT, |
| | 921 | elf.DT_RELACOUNT, |
| | 922 | => try writer.print(" {d}", .{value}), |
| | 923 | |
| | 924 | elf.DT_PLTREL => try writer.writeAll(switch (value) { |
| | 925 | elf.DT_REL => " REL", |
| | 926 | elf.DT_RELA => " RELA", |
| | 927 | else => " UNKNOWN", |
| | 928 | }), |
| | 929 | |
| | 930 | elf.DT_FLAGS => if (value > 0) { |
| | 931 | if (value & elf.DF_ORIGIN != 0) try writer.writeAll(" ORIGIN"); |
| | 932 | if (value & elf.DF_SYMBOLIC != 0) try writer.writeAll(" SYMBOLIC"); |
| | 933 | if (value & elf.DF_TEXTREL != 0) try writer.writeAll(" TEXTREL"); |
| | 934 | if (value & elf.DF_BIND_NOW != 0) try writer.writeAll(" BIND_NOW"); |
| | 935 | if (value & elf.DF_STATIC_TLS != 0) try writer.writeAll(" STATIC_TLS"); |
| | 936 | }, |
| | 937 | |
| | 938 | elf.DT_FLAGS_1 => if (value > 0) { |
| | 939 | if (value & elf.DF_1_NOW != 0) try writer.writeAll(" NOW"); |
| | 940 | if (value & elf.DF_1_GLOBAL != 0) try writer.writeAll(" GLOBAL"); |
| | 941 | if (value & elf.DF_1_GROUP != 0) try writer.writeAll(" GROUP"); |
| | 942 | if (value & elf.DF_1_NODELETE != 0) try writer.writeAll(" NODELETE"); |
| | 943 | if (value & elf.DF_1_LOADFLTR != 0) try writer.writeAll(" LOADFLTR"); |
| | 944 | if (value & elf.DF_1_INITFIRST != 0) try writer.writeAll(" INITFIRST"); |
| | 945 | if (value & elf.DF_1_NOOPEN != 0) try writer.writeAll(" NOOPEN"); |
| | 946 | if (value & elf.DF_1_ORIGIN != 0) try writer.writeAll(" ORIGIN"); |
| | 947 | if (value & elf.DF_1_DIRECT != 0) try writer.writeAll(" DIRECT"); |
| | 948 | if (value & elf.DF_1_TRANS != 0) try writer.writeAll(" TRANS"); |
| | 949 | if (value & elf.DF_1_INTERPOSE != 0) try writer.writeAll(" INTERPOSE"); |
| | 950 | if (value & elf.DF_1_NODEFLIB != 0) try writer.writeAll(" NODEFLIB"); |
| | 951 | if (value & elf.DF_1_NODUMP != 0) try writer.writeAll(" NODUMP"); |
| | 952 | if (value & elf.DF_1_CONFALT != 0) try writer.writeAll(" CONFALT"); |
| | 953 | if (value & elf.DF_1_ENDFILTEE != 0) try writer.writeAll(" ENDFILTEE"); |
| | 954 | if (value & elf.DF_1_DISPRELDNE != 0) try writer.writeAll(" DISPRELDNE"); |
| | 955 | if (value & elf.DF_1_DISPRELPND != 0) try writer.writeAll(" DISPRELPND"); |
| | 956 | if (value & elf.DF_1_NODIRECT != 0) try writer.writeAll(" NODIRECT"); |
| | 957 | if (value & elf.DF_1_IGNMULDEF != 0) try writer.writeAll(" IGNMULDEF"); |
| | 958 | if (value & elf.DF_1_NOKSYMS != 0) try writer.writeAll(" NOKSYMS"); |
| | 959 | if (value & elf.DF_1_NOHDR != 0) try writer.writeAll(" NOHDR"); |
| | 960 | if (value & elf.DF_1_EDITED != 0) try writer.writeAll(" EDITED"); |
| | 961 | if (value & elf.DF_1_NORELOC != 0) try writer.writeAll(" NORELOC"); |
| | 962 | if (value & elf.DF_1_SYMINTPOSE != 0) try writer.writeAll(" SYMINTPOSE"); |
| | 963 | if (value & elf.DF_1_GLOBAUDIT != 0) try writer.writeAll(" GLOBAUDIT"); |
| | 964 | if (value & elf.DF_1_SINGLETON != 0) try writer.writeAll(" SINGLETON"); |
| | 965 | if (value & elf.DF_1_STUB != 0) try writer.writeAll(" STUB"); |
| | 966 | if (value & elf.DF_1_PIE != 0) try writer.writeAll(" PIE"); |
| | 967 | }, |
| | 968 | |
| | 969 | else => try writer.print(" {x}", .{value}), |
| | 970 | } |
| | 971 | try writer.writeByte('\n'); |
| | 972 | } |
| | 973 | } |
| | 974 | |
| 827 | fn fmtShType(sh_type: u32) std.fmt.Formatter(formatShType) { | 975 | fn fmtShType(sh_type: u32) std.fmt.Formatter(formatShType) { |
| 828 | return .{ .data = sh_type }; | 976 | return .{ .data = sh_type }; |
| 829 | } | 977 | } |