authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-07-13 17:01:26+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-07-13 17:01:26+02:00
log76dc0d516089da6cd7dfb5ee1634c7e4ccef6a4a
treed0a574e74f7d7e7e2e7043b796cb2eaa0e0104b1
parent0627ca527ac9b973ff0823c274913d2ece8ae6be

check-object: dump some info on SHDRs


1 files changed, 137 insertions(+), 6 deletions(-)

lib/std/Build/Step/CheckObject.zig+137-6
......@@ -701,9 +701,34 @@ const MachODumper = struct {
701701const ElfDumper = struct {
702702 const symtab_label = "symtab";
703703
704 fn parseAndDump(step: *Step, bytes: []const u8, opts: Opts) ![]const u8 {
705 _ = opts;
704 const Symtab = struct {
705 symbols: []align(1) const elf.Elf64_Sym,
706 strings: []const u8,
707
708 fn get(st: Symtab, index: usize) ?elf.Elf64_Sym {
709 if (index >= st.symbols.len) return null;
710 return st.symbols[index];
711 }
712
713 fn getName(st: Symtab, index: usize) ?[]const u8 {
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);
717 }
718 };
706719
720 const Context = struct {
721 gpa: Allocator,
722 data: []const u8,
723 hdr: elf.Elf64_Ehdr,
724 shdrs: []align(1) const elf.Elf64_Shdr,
725 phdrs: []align(1) const elf.Elf64_Phdr,
726 shstrtab: []const u8,
727 symtab: ?Symtab = null,
728 dysymtab: ?Symtab = null,
729 };
730
731 fn parseAndDump(step: *Step, bytes: []const u8, opts: Opts) ![]const u8 {
707732 const gpa = step.owner.allocator;
708733 var stream = std.io.fixedBufferStream(bytes);
709734 const reader = stream.reader();
......@@ -713,18 +738,124 @@ const ElfDumper = struct {
713738 return error.InvalidMagicNumber;
714739 }
715740
741 const shdrs = @as([*]align(1) const elf.Elf64_Shdr, @ptrCast(bytes.ptr + hdr.e_shoff))[0..hdr.e_shnum];
742 const phdrs = @as([*]align(1) const elf.Elf64_Phdr, @ptrCast(bytes.ptr + hdr.e_phoff))[0..hdr.e_phnum];
743
744 var ctx = Context{
745 .gpa = gpa,
746 .data = bytes,
747 .hdr = hdr,
748 .shdrs = shdrs,
749 .phdrs = phdrs,
750 .shstrtab = undefined,
751 };
752 ctx.shstrtab = getSectionContents(ctx, ctx.hdr.e_shstrndx);
753
754 if (opts.dump_symtab) {
755 for (ctx.shdrs, 0..) |shdr, i| switch (shdr.sh_type) {
756 elf.SHT_SYMTAB, elf.SHT_DYNSYM => {
757 const raw = getSectionContents(ctx, i);
758 const nsyms = @divExact(raw.len, @sizeOf(elf.Elf64_Sym));
759 const symbols = @as([*]align(1) const elf.Elf64_Sym, @ptrCast(raw.ptr))[0..nsyms];
760 const strings = getSectionContents(ctx, shdr.sh_link);
761
762 switch (shdr.sh_type) {
763 elf.SHT_SYMTAB => {
764 ctx.symtab = .{
765 .symbols = symbols,
766 .strings = strings,
767 };
768 },
769 elf.SHT_DYNSYM => {
770 ctx.dysymtab = .{
771 .symbols = symbols,
772 .strings = strings,
773 };
774 },
775 else => unreachable,
776 }
777 },
778
779 else => {},
780 };
781 }
782
716783 var output = std.ArrayList(u8).init(gpa);
717784 const writer = output.writer();
718785
719 try dumpHeader(hdr, writer);
786 try dumpHeader(ctx, writer);
787 try dumpShdrs(ctx, writer);
720788
721789 return output.toOwnedSlice();
722790 }
723791
724 fn dumpHeader(hdr: elf.Elf64_Ehdr, writer: anytype) !void {
792 fn getSectionName(ctx: Context, shndx: usize) []const u8 {
793 const shdr = ctx.shdrs[shndx];
794 assert(shdr.sh_name < ctx.shstrtab.len);
795 return mem.sliceTo(@as([*:0]const u8, @ptrCast(ctx.shstrtab.ptr + shdr.sh_name)), 0);
796 }
797
798 fn getSectionContents(ctx: Context, shndx: usize) []const u8 {
799 const shdr = ctx.shdrs[shndx];
800 assert(shdr.sh_offset < ctx.data.len);
801 assert(shdr.sh_offset + shdr.sh_size <= ctx.data.len);
802 return ctx.data[shdr.sh_offset..][0..shdr.sh_size];
803 }
804
805 fn dumpHeader(ctx: Context, writer: anytype) !void {
725806 try writer.writeAll("header\n");
726 try writer.print("type {s}\n", .{@tagName(hdr.e_type)});
727 try writer.print("entry {x}\n", .{hdr.e_entry});
807 try writer.print("type {s}\n", .{@tagName(ctx.hdr.e_type)});
808 try writer.print("entry {x}\n", .{ctx.hdr.e_entry});
809 }
810
811 fn dumpShdrs(ctx: Context, writer: anytype) !void {
812 if (ctx.shdrs.len == 0) return;
813
814 for (ctx.shdrs, 0..) |shdr, shndx| {
815 try writer.print("shdr {d}\n", .{shndx});
816 try writer.print("name {s}\n", .{getSectionName(ctx, shndx)});
817 try writer.print("type {s}\n", .{try fmtShType(ctx.gpa, shdr.sh_type)});
818 }
819 }
820
821 fn fmtShType(gpa: Allocator, sh_type: u32) ![]const u8 {
822 return switch (sh_type) {
823 elf.SHT_NULL => "NULL",
824 elf.SHT_PROGBITS => "PROGBITS",
825 elf.SHT_SYMTAB => "SYMTAB",
826 elf.SHT_STRTAB => "STRTAB",
827 elf.SHT_RELA => "RELA",
828 elf.SHT_HASH => "HASH",
829 elf.SHT_DYNAMIC => "DYNAMIC",
830 elf.SHT_NOTE => "NOTE",
831 elf.SHT_NOBITS => "NOBITS",
832 elf.SHT_REL => "REL",
833 elf.SHT_SHLIB => "SHLIB",
834 elf.SHT_DYNSYM => "DYNSYM",
835 elf.SHT_INIT_ARRAY => "INIT_ARRAY",
836 elf.SHT_FINI_ARRAY => "FINI_ARRAY",
837 elf.SHT_PREINIT_ARRAY => "PREINIT_ARRAY",
838 elf.SHT_GROUP => "GROUP",
839 elf.SHT_SYMTAB_SHNDX => "SYMTAB_SHNDX",
840 elf.SHT_X86_64_UNWIND => "X86_64_UNWIND",
841 elf.SHT_LLVM_ADDRSIG => "LLVM_ADDRSIG",
842 elf.SHT_GNU_HASH => "GNU_HASH",
843 elf.SHT_GNU_VERDEF => "VERDEF",
844 elf.SHT_GNU_VERNEED => "VERNEED",
845 elf.SHT_GNU_VERSYM => "VERSYM",
846 else => |sht| blk: {
847 if (elf.SHT_LOOS <= sht and sht < elf.SHT_HIOS) {
848 break :blk try std.fmt.allocPrint(gpa, "LOOS+0x{x}", .{sht - elf.SHT_LOOS});
849 }
850 if (elf.SHT_LOPROC <= sht and sht < elf.SHT_HIPROC) {
851 break :blk try std.fmt.allocPrint(gpa, "LOPROC+0x{x}", .{sht - elf.SHT_LOPROC});
852 }
853 if (elf.SHT_LOUSER <= sht and sht < elf.SHT_HIUSER) {
854 break :blk try std.fmt.allocPrint(gpa, "LOUSER+0x{x}", .{sht - elf.SHT_LOUSER});
855 }
856 break :blk "UNKNOWN";
857 },
858 };
728859 }
729860};
730861