| ... | @@ -785,6 +785,7 @@ const ElfDumper = struct { | ... | @@ -785,6 +785,7 @@ const ElfDumper = struct { |
| 785 | | 785 | |
| 786 | try dumpHeader(ctx, writer); | 786 | try dumpHeader(ctx, writer); |
| 787 | try dumpShdrs(ctx, writer); | 787 | try dumpShdrs(ctx, writer); |
| | 788 | try dumpPhdrs(ctx, writer); |
| 788 | | 789 | |
| 789 | return output.toOwnedSlice(); | 790 | return output.toOwnedSlice(); |
| 790 | } | 791 | } |
| ... | @@ -814,52 +815,114 @@ const ElfDumper = struct { | ... | @@ -814,52 +815,114 @@ const ElfDumper = struct { |
| 814 | for (ctx.shdrs, 0..) |shdr, shndx| { | 815 | for (ctx.shdrs, 0..) |shdr, shndx| { |
| 815 | try writer.print("shdr {d}\n", .{shndx}); | 816 | try writer.print("shdr {d}\n", .{shndx}); |
| 816 | try writer.print("name {s}\n", .{getSectionName(ctx, shndx)}); | 817 | try writer.print("name {s}\n", .{getSectionName(ctx, shndx)}); |
| 817 | try writer.print("type {s}\n", .{try fmtShType(ctx.gpa, shdr.sh_type)}); | 818 | try writer.print("type {s}\n", .{fmtShType(shdr.sh_type)}); |
| 818 | try writer.print("addr {x}\n", .{shdr.sh_addr}); | 819 | try writer.print("addr {x}\n", .{shdr.sh_addr}); |
| 819 | try writer.print("offset {x}\n", .{shdr.sh_offset}); | 820 | try writer.print("offset {x}\n", .{shdr.sh_offset}); |
| 820 | try writer.print("size {x}\n", .{shdr.sh_size}); | 821 | try writer.print("size {x}\n", .{shdr.sh_size}); |
| 821 | try writer.print("addralign {x}\n", .{shdr.sh_addralign}); | 822 | try writer.print("addralign {x}\n", .{shdr.sh_addralign}); |
| | 823 | // TODO dump formatted sh_flags |
| 822 | } | 824 | } |
| 823 | } | 825 | } |
| 824 | | 826 | |
| 825 | fn fmtShType(gpa: Allocator, sh_type: u32) ![]const u8 { | 827 | fn fmtShType(sh_type: u32) std.fmt.Formatter(formatShType) { |
| 826 | return switch (sh_type) { | 828 | return .{ .data = sh_type }; |
| 827 | elf.SHT_NULL => "NULL", | 829 | } |
| 828 | elf.SHT_PROGBITS => "PROGBITS", | 830 | |
| 829 | elf.SHT_SYMTAB => "SYMTAB", | 831 | fn formatShType( |
| 830 | elf.SHT_STRTAB => "STRTAB", | 832 | sh_type: u32, |
| 831 | elf.SHT_RELA => "RELA", | 833 | comptime unused_fmt_string: []const u8, |
| 832 | elf.SHT_HASH => "HASH", | 834 | options: std.fmt.FormatOptions, |
| 833 | elf.SHT_DYNAMIC => "DYNAMIC", | 835 | writer: anytype, |
| 834 | elf.SHT_NOTE => "NOTE", | 836 | ) !void { |
| 835 | elf.SHT_NOBITS => "NOBITS", | 837 | _ = unused_fmt_string; |
| 836 | elf.SHT_REL => "REL", | 838 | _ = options; |
| 837 | elf.SHT_SHLIB => "SHLIB", | 839 | if (elf.SHT_LOOS <= sh_type and sh_type < elf.SHT_HIOS) { |
| 838 | elf.SHT_DYNSYM => "DYNSYM", | 840 | try writer.print("LOOS+0x{x}", .{sh_type - elf.SHT_LOOS}); |
| 839 | elf.SHT_INIT_ARRAY => "INIT_ARRAY", | 841 | } else if (elf.SHT_LOPROC <= sh_type and sh_type < elf.SHT_HIPROC) { |
| 840 | elf.SHT_FINI_ARRAY => "FINI_ARRAY", | 842 | try writer.print("LOPROC+0x{x}", .{sh_type - elf.SHT_LOPROC}); |
| 841 | elf.SHT_PREINIT_ARRAY => "PREINIT_ARRAY", | 843 | } else if (elf.SHT_LOUSER <= sh_type and sh_type < elf.SHT_HIUSER) { |
| 842 | elf.SHT_GROUP => "GROUP", | 844 | try writer.print("LOUSER+0x{x}", .{sh_type - elf.SHT_LOUSER}); |
| 843 | elf.SHT_SYMTAB_SHNDX => "SYMTAB_SHNDX", | 845 | } else { |
| 844 | elf.SHT_X86_64_UNWIND => "X86_64_UNWIND", | 846 | const name = switch (sh_type) { |
| 845 | elf.SHT_LLVM_ADDRSIG => "LLVM_ADDRSIG", | 847 | elf.SHT_NULL => "NULL", |
| 846 | elf.SHT_GNU_HASH => "GNU_HASH", | 848 | elf.SHT_PROGBITS => "PROGBITS", |
| 847 | elf.SHT_GNU_VERDEF => "VERDEF", | 849 | elf.SHT_SYMTAB => "SYMTAB", |
| 848 | elf.SHT_GNU_VERNEED => "VERNEED", | 850 | elf.SHT_STRTAB => "STRTAB", |
| 849 | elf.SHT_GNU_VERSYM => "VERSYM", | 851 | elf.SHT_RELA => "RELA", |
| 850 | else => |sht| blk: { | 852 | elf.SHT_HASH => "HASH", |
| 851 | if (elf.SHT_LOOS <= sht and sht < elf.SHT_HIOS) { | 853 | elf.SHT_DYNAMIC => "DYNAMIC", |
| 852 | break :blk try std.fmt.allocPrint(gpa, "LOOS+0x{x}", .{sht - elf.SHT_LOOS}); | 854 | elf.SHT_NOTE => "NOTE", |
| 853 | } | 855 | elf.SHT_NOBITS => "NOBITS", |
| 854 | if (elf.SHT_LOPROC <= sht and sht < elf.SHT_HIPROC) { | 856 | elf.SHT_REL => "REL", |
| 855 | break :blk try std.fmt.allocPrint(gpa, "LOPROC+0x{x}", .{sht - elf.SHT_LOPROC}); | 857 | elf.SHT_SHLIB => "SHLIB", |
| 856 | } | 858 | elf.SHT_DYNSYM => "DYNSYM", |
| 857 | if (elf.SHT_LOUSER <= sht and sht < elf.SHT_HIUSER) { | 859 | elf.SHT_INIT_ARRAY => "INIT_ARRAY", |
| 858 | break :blk try std.fmt.allocPrint(gpa, "LOUSER+0x{x}", .{sht - elf.SHT_LOUSER}); | 860 | elf.SHT_FINI_ARRAY => "FINI_ARRAY", |
| 859 | } | 861 | elf.SHT_PREINIT_ARRAY => "PREINIT_ARRAY", |
| 860 | break :blk "UNKNOWN"; | 862 | elf.SHT_GROUP => "GROUP", |
| 861 | }, | 863 | elf.SHT_SYMTAB_SHNDX => "SYMTAB_SHNDX", |
| 862 | }; | 864 | elf.SHT_X86_64_UNWIND => "X86_64_UNWIND", |
| | 865 | elf.SHT_LLVM_ADDRSIG => "LLVM_ADDRSIG", |
| | 866 | elf.SHT_GNU_HASH => "GNU_HASH", |
| | 867 | elf.SHT_GNU_VERDEF => "VERDEF", |
| | 868 | elf.SHT_GNU_VERNEED => "VERNEED", |
| | 869 | elf.SHT_GNU_VERSYM => "VERSYM", |
| | 870 | else => "UNKNOWN", |
| | 871 | }; |
| | 872 | try writer.writeAll(name); |
| | 873 | } |
| | 874 | } |
| | 875 | |
| | 876 | fn dumpPhdrs(ctx: Context, writer: anytype) !void { |
| | 877 | if (ctx.phdrs.len == 0) return; |
| | 878 | |
| | 879 | for (ctx.phdrs, 0..) |phdr, phndx| { |
| | 880 | try writer.print("phdr {d}\n", .{phndx}); |
| | 881 | try writer.print("type {s}\n", .{fmtPhType(phdr.p_type)}); |
| | 882 | try writer.print("vaddr {x}\n", .{phdr.p_vaddr}); |
| | 883 | try writer.print("paddr {x}\n", .{phdr.p_paddr}); |
| | 884 | try writer.print("offset {x}\n", .{phdr.p_offset}); |
| | 885 | try writer.print("memsz {x}\n", .{phdr.p_memsz}); |
| | 886 | try writer.print("filesz {x}\n", .{phdr.p_filesz}); |
| | 887 | try writer.print("align {x}\n", .{phdr.p_align}); |
| | 888 | // TODO dump formatted p_flags |
| | 889 | } |
| | 890 | } |
| | 891 | |
| | 892 | fn fmtPhType(ph_type: u32) std.fmt.Formatter(formatPhType) { |
| | 893 | return .{ .data = ph_type }; |
| | 894 | } |
| | 895 | |
| | 896 | fn formatPhType( |
| | 897 | ph_type: u32, |
| | 898 | comptime unused_fmt_string: []const u8, |
| | 899 | options: std.fmt.FormatOptions, |
| | 900 | writer: anytype, |
| | 901 | ) !void { |
| | 902 | _ = unused_fmt_string; |
| | 903 | _ = options; |
| | 904 | if (elf.PT_LOOS <= ph_type and ph_type < elf.PT_HIOS) { |
| | 905 | try writer.print("LOOS+0x{x}", .{ph_type - elf.PT_LOOS}); |
| | 906 | } else if (elf.PT_LOPROC <= ph_type and ph_type < elf.PT_HIPROC) { |
| | 907 | try writer.print("LOPROC+0x{x}", .{ph_type - elf.PT_LOPROC}); |
| | 908 | } else { |
| | 909 | const p_type = switch (ph_type) { |
| | 910 | elf.PT_NULL => "NULL", |
| | 911 | elf.PT_LOAD => "LOAD", |
| | 912 | elf.PT_DYNAMIC => "DYNAMIC", |
| | 913 | elf.PT_INTERP => "INTERP", |
| | 914 | elf.PT_NOTE => "NOTE", |
| | 915 | elf.PT_SHLIB => "SHLIB", |
| | 916 | elf.PT_PHDR => "PHDR", |
| | 917 | elf.PT_TLS => "TLS", |
| | 918 | elf.PT_NUM => "NUM", |
| | 919 | elf.PT_GNU_EH_FRAME => "GNU_EH_FRAME", |
| | 920 | elf.PT_GNU_STACK => "GNU_STACK", |
| | 921 | elf.PT_GNU_RELRO => "GNU_RELRO", |
| | 922 | else => "UNKNOWN", |
| | 923 | }; |
| | 924 | try writer.writeAll(p_type); |
| | 925 | } |
| 863 | } | 926 | } |
| 864 | }; | 927 | }; |
| 865 | | 928 | |