| ... | ... | @@ -712,8 +712,7 @@ const ElfDumper = struct { |
| 712 | 712 | |
| 713 | 713 | fn getName(st: Symtab, index: usize) ?[]const u8 { |
| 714 | 714 | const sym = st.get(index) orelse return null; |
| 715 | | assert(sym.st_name < st.strings.len); |
| 716 | | return mem.sliceTo(@ptrCast(st.strings.ptr + sym.st_name), 0); |
| 715 | return getString(st.strings, sym.st_name); |
| 717 | 716 | } |
| 718 | 717 | }; |
| 719 | 718 | |
| ... | ... | @@ -786,6 +785,7 @@ const ElfDumper = struct { |
| 786 | 785 | try dumpHeader(ctx, writer); |
| 787 | 786 | try dumpShdrs(ctx, writer); |
| 788 | 787 | try dumpPhdrs(ctx, writer); |
| 788 | try dumpDynamic(ctx, writer); |
| 789 | 789 | |
| 790 | 790 | return output.toOwnedSlice(); |
| 791 | 791 | } |
| ... | ... | @@ -803,6 +803,17 @@ const ElfDumper = struct { |
| 803 | 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 | 817 | fn dumpHeader(ctx: Context, writer: anytype) !void { |
| 807 | 818 | try writer.writeAll("header\n"); |
| 808 | 819 | try writer.print("type {s}\n", .{@tagName(ctx.hdr.e_type)}); |
| ... | ... | @@ -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 | 975 | fn fmtShType(sh_type: u32) std.fmt.Formatter(formatShType) { |
| 828 | 976 | return .{ .data = sh_type }; |
| 829 | 977 | } |