objdump: Add support for elf - scc - simple c99 compiler
 (HTM) git clone git://git.simple-cc.org/scc
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit f2f60fcbe4ac4096f4e0681f498c21167ac30166
 (DIR) parent dbe2170b3140a6719b908f380c6a36594f6f4731
 (HTM) Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
       Date:   Fri, 24 Jan 2025 10:03:45 +0100
       
       objdump: Add support for elf
       
       Diffstat:
         M include/bits/scc/mach.h             |       1 -
         M src/cmd/scc-objdump/Makefile        |       1 +
         M src/cmd/scc-objdump/coff32.c        |      14 ++++++++++++++
         A src/cmd/scc-objdump/elf64.c         |     734 ++++++++++++++++++++++++++++++
         M src/cmd/scc-objdump/main.c          |      26 +++++++++++++++++++++++++-
         M src/cmd/scc-objdump/objdump.h       |       7 +++++++
         M src/libmach/coff32/coff32getsec.c   |       1 -
         M src/libmach/elf64/elf64getsec.c     |      15 ++++++++-------
       
       8 files changed, 789 insertions(+), 10 deletions(-)
       ---
 (DIR) diff --git a/include/bits/scc/mach.h b/include/bits/scc/mach.h
       @@ -98,7 +98,6 @@ struct section {
                unsigned long long size;
                unsigned long long offset;
        
       -        unsigned long nreloc;
                unsigned flags;
                int index;
                int align;
 (DIR) diff --git a/src/cmd/scc-objdump/Makefile b/src/cmd/scc-objdump/Makefile
       @@ -6,6 +6,7 @@ include $(PROJECTDIR)/scripts/rules.mk
        OBJS =\
                main.o\
                coff32.o\
       +        elf64.o\
        
        TARGET = scc-objdump
        MORE_LDLIBS = -lmach -lscc
 (DIR) diff --git a/src/cmd/scc-objdump/coff32.c b/src/cmd/scc-objdump/coff32.c
       @@ -6,6 +6,15 @@
        
        #include "objdump.h"
        
       +int
       +coff32hasrelloc(Obj *obj, Section *sec)
       +{
       +        struct coff32 *coff = obj->data;
       +        SCNHDR *scn = &coff->scns[sec->index];
       +
       +        return scn->s_nrelloc != 0;
       +}
       +
        void
        coff32syms(Obj *obj)
        {
       @@ -13,6 +22,11 @@ coff32syms(Obj *obj)
                struct coff32 *coff = obj->data;
                FILHDR *hdr = &coff->hdr;
        
       +        if (hdr->f_nsyms == 0) {
       +                puts("no symbols");
       +                return;
       +        }
       +
                for (i = 0; i < hdr->f_nsyms; i++) {
                        SYMENT *ent;
                        AUXENT *aux;
 (DIR) diff --git a/src/cmd/scc-objdump/elf64.c b/src/cmd/scc-objdump/elf64.c
       @@ -0,0 +1,734 @@
       +#include <stdio.h>
       +#include <stdlib.h>
       +#include <string.h>
       +
       +#include <scc/mach.h>
       +#include <scc/elf64.h>
       +
       +#include "objdump.h"
       +
       +enum elfsecflags {
       +        ELF_WRITE = 0,
       +        ELF_ALLOC = 1,
       +        ELF_EXEC = 2,
       +        ELF_MERGE = 3,
       +        ELF_STRINGS = 4,
       +        ELF_INFO_LINK = 5,
       +        ELF_LINK_ORDER = 6,
       +        ELF_OS_NONCONFOR = 7,
       +        ELF_GROUP = 8,
       +        ELF_TLS = 9,
       +        ELF_COMPRESSED = 10,
       +        ELF_NR_FLAGS = 11,
       +};
       +
       +enum phdrflags {
       +        FLAG_X = 0,
       +        FLAG_W = 1,
       +        FLAG_R = 2,
       +        NR_RIGHTS = 3,
       +};
       +
       +int
       +elf64hasrelloc(Obj *obj, Section *sec)
       +{
       +        size_t i;
       +        Elf64 *elf = obj->data;
       +        Elf_Shdr *shdr;
       +
       +        for (i = 0; i < elf->nsec; i++) {
       +                shdr = &elf->shdr[i];
       +                if (shdr->sh_type != SHT_RELA && shdr->sh_type != SHT_REL)
       +                        continue;
       +                if (shdr->sh_info == sec->index)
       +                        return 1;
       +        }
       +
       +        return 0;
       +}
       +
       +static void
       +printents(Obj *obj)
       +{
       +        int n;
       +        size_t i;
       +        Section sec;
       +        Elf_Sym *ent;
       +        Elf64 *elf = obj->data;
       +        char *sbind, *stype, *svis, *ssec;
       +        unsigned info, bind, type, vis, nsec;
       +
       +        static char *binds[] = {
       +                [STB_LOCAL] = "Local symbol",
       +                [STB_GLOBAL] = "Global symbol",
       +                [STB_WEAK] = "like global - lower precedence",
       +                [STB_NUM] = "number of symbol bindings",
       +                [STB_LOPROC] = "reserved range for processor",
       +                [STB_HIPROC] = " specific symbol bindings",
       +        };
       +        static char *types[] = {
       +                [STT_NOTYPE] = "not specified",
       +                [STT_OBJECT] = "data object",
       +                [STT_FUNC] = "function",
       +                [STT_SECTION] = "section",
       +                [STT_FILE] = "file",
       +                [STT_COMMON] = "common symbol",
       +                [STT_TLS] = "thread local storage",
       +                [STT_LOPROC] = "reserved range for processor",
       +                [STT_HIPROC] = " specific symbol types",
       +        };
       +        static char *visibilities[] = {
       +                [STV_DEFAULT] = "Visibility set by binding type",
       +                [STV_INTERNAL] = "OS specific version of STV_HIDDEN",
       +                [STV_HIDDEN] = "can only be seen inside own .so",
       +                [STV_PROTECTED] = "HIDDEN inside, DEFAULT outside",
       +        };
       +
       +        for (i = 0; i < elf->nsym; i++) {
       +                ent = &elf->syms[i];
       +
       +                info = ent->st_info;
       +                bind = ELF64_ST_BIND(info);
       +                type = ELF64_ST_TYPE(info);
       +                vis = ELF_ST_VISIBILITY(ent->st_other);
       +                nsec = ent->st_shndx;
       +
       +                sbind = (bind <= STB_HIPROC) ? binds[bind] : "Unknown";
       +                stype = (type <= STT_HIPROC) ? types[type] : "Unknown";
       +                svis = (vis <= STV_PROTECTED) ? visibilities[vis] : "Unknown";
       +                if (!sbind)
       +                        sbind = "Unknown";
       +                if (!stype)
       +                        stype = "Unknown";
       +                if (!svis)
       +                        svis = "Unknown";
       +
       +                switch (nsec) {
       +                case SHN_ABS:
       +                        ssec = "*ABS*";
       +                        break;
       +                case SHN_COMMON:
       +                        ssec = "*COM*";
       +                        break;
       +                default:
       +                        n = nsec;
       +                        ssec = "*UNK*";
       +                        if (getsec(obj, &n, &sec))
       +                                ssec = sec.name;
       +                }
       +
       +                printf("Symbol %zu:\n"
       +                        "\tst_name: %lu '%s'\n"
       +                        "\tst_info: %u\n"
       +                        "\t\tst_bind: %u %s\n"
       +                        "\t\tst_type: %u %s\n"
       +                        "\tst_other: %u %s\n"
       +                        "\tst_shndx: %u %s\n"
       +                        "\tst_value: %llu\n"
       +                        "\tst_size: %llu\n"
       +                        "\n",
       +                        i,
       +                        (long) ent->st_name,
       +                        elf64str(obj, SYM_STRTBL, ent->st_name),
       +                        info,
       +                        bind, sbind,
       +                        type, stype,
       +                        vis, svis,
       +                        nsec, ssec,
       +                        (unsigned long long) ent->st_value,
       +                        (unsigned long long) ent->st_size);
       +        }
       +}
       +
       +static void
       +printstbl(Obj *obj)
       +{
       +        int n;
       +        size_t i;
       +        Symbol sym;
       +        Section sec;
       +        Elf_Sym *ent;
       +        Elf_Shdr *shdr;
       +        Elf64 *elf = obj->data;
       +        unsigned info, bind, type;
       +        char cbind, cweak, cctor, cwarn, cindir, cdebug, ctype;
       +
       +        if (elf->nsym == 0) {
       +                puts("no symbols");
       +                return;
       +        }
       +
       +        for (i = 1; i < elf->nsym; i++) {
       +                ent = &elf->syms[i];
       +                shdr =&elf->shdr[ent->st_shndx];
       +                n = i;
       +                getsym(obj, &n, &sym);
       +                n = ent->st_shndx;
       +                getsec(obj, &n, &sec);
       +
       +                info = ent->st_info;
       +                bind = ELF64_ST_BIND(info);
       +                type = ELF64_ST_TYPE(info);
       +
       +                cbind = (bind == STB_LOCAL) ? 'l' : 'g';
       +                cweak = (bind == STB_WEAK) ? 'w' : ' ';
       +                cctor = ' ';
       +                cwarn = ' ';
       +                cindir = ' ';
       +
       +                switch (sym.type) {
       +                case 'N':
       +                case 'n':
       +                        cdebug = 'd';
       +                        break;
       +                case 'U':
       +                        cdebug = ' ';
       +                        cbind = ' ';
       +                        break;
       +                default:
       +                        cdebug = (elf->symtab->sh_type == SHT_DYNAMIC) ? 'D' : ' ';
       +                }
       +
       +                switch (type) {
       +                case STT_OBJECT:
       +                        ctype = 'O';
       +                        break;
       +                case STT_FUNC:
       +                        ctype = 'F';
       +                        break;
       +                case STT_FILE:
       +                        ctype = 'f';
       +                        cdebug = 'd';
       +                        break;
       +                default:
       +                        ctype = ' ';
       +                        break;
       +                }
       +
       +                printf("%016llx %c%c%c%c%c%c%c %-15s %08llu %-20s [%4zu]\n",
       +                       (long long) ent->st_value,
       +                       cbind,
       +                       cweak,
       +                       cctor,
       +                       cwarn,
       +                       cindir,
       +                       cdebug,
       +                       ctype,
       +                       sec.name,
       +                       (long long) ent->st_size,
       +                       sym.name,
       +                       i);
       +        }
       +}
       +
       +void
       +elf64syms(Obj *obj)
       +{
       +        printstbl(obj);
       +
       +        if (pflag)
       +                printents(obj);
       +}
       +
       +void
       +elf64scns(Obj *obj)
       +{
       +        size_t i;
       +        Elf64 *elf = obj->data;
       +        Elf_Shdr *shdr;
       +        static char *types[] = {
       +                [SHT_NULL] = "inactive",
       +                [SHT_PROGBITS] = "program defined information",
       +                [SHT_SYMTAB] = "symbol table section",
       +                [SHT_STRTAB] = "string table section",
       +                [SHT_RELA] = "relocation section with addends",
       +                [SHT_HASH] = "symbol hash table section",
       +                [SHT_DYNAMIC] = "dynamic section",
       +                [SHT_NOTE] = "note section",
       +                [SHT_NOBITS] = "no space section",
       +                [SHT_REL] = "relation section without addends",
       +                [SHT_SHLIB] = "reserved - purpose unknown",
       +                [SHT_DYNSYM] = "dynamic symbol table section",
       +                [SHT_NUM] = "number of section types",
       +                [SHT_INIT_ARRAY] = "pointers to init functions",
       +                [SHT_FINI_ARRAY] = "pointers to termination functions",
       +                [SHT_PREINIT_ARRAY] = "ptrs to funcs called before init",
       +                [SHT_GROUP] = "defines a section group",
       +                [SHT_SYMTAB_SHNDX] = "Section indexes (see SHN_XINDEX).",
       +        };
       +        static Flags f = {
       +                .nr = ELF_NR_FLAGS,
       +                .text = {
       +                        [ELF_WRITE] = "WRITE",
       +                        [ELF_ALLOC] = "ALLOC",
       +                        [ELF_EXEC] = "EXEC",
       +                        [ELF_MERGE] = "MERGE",
       +                        [ELF_STRINGS] = "STRINGS",
       +                        [ELF_INFO_LINK] = "INFO_LINK",
       +                        [ELF_LINK_ORDER] = "LINK_ORDER",
       +                        [ELF_OS_NONCONFOR] = "OS_NONCONFORMING",
       +                        [ELF_GROUP] = "GROUP",
       +                        [ELF_TLS] = "TLS",
       +                        [ELF_COMPRESSED] = "COMPRESSED",
       +                }
       +        };
       +
       +        for (i = 0; i < elf->nsec; i++) {
       +                long type;
       +                char *stype;
       +                shdr = &elf->shdr[i];
       +
       +                type = shdr->sh_type;
       +                if (type <= SHT_SYMTAB_SHNDX) {
       +                        stype = types[type];
       +                } else {
       +                        switch (type) {
       +                        case SHT_SUNW_dof:
       +                                stype = "SHT_SUNW_dof";
       +                                break;
       +                        case SHT_GNU_LIBLIST:
       +                                stype = "SHT_GNU_LIBLIST";
       +                                break;
       +                        case SHT_SUNW_move:
       +                                stype = "SHT_SUNW_move";
       +                                break;
       +                        case SHT_SUNW_syminfo:
       +                                stype = "SHT_SUNW_syminfo";
       +                                break;
       +                        case SHT_GNU_VERDEF:
       +                                stype = "SHT_GNU_VERDEF";
       +                                break;
       +                        case SHT_GNU_VERNEED:
       +                                stype = "SHT_GNU_VERNEED";
       +                                break;
       +                        case SHT_GNU_VERSYM:
       +                                stype = "SHT_GNU_VERSYM";
       +                                break;
       +                        default:
       +                                stype = NULL;
       +                        }
       +                }
       +
       +                if (!stype)
       +                        stype = "Unknown";
       +
       +                f.flags = shdr->sh_flags;
       +
       +                printf("Section %zu:\n"
       +                       "\tsh_name: %lu\n"
       +                       "\tsh_type: %lu %s\n"
       +                       "\tsh_flags: %#llx\n"
       +                       "\tsh_addr: %#llx\n"
       +                       "\tsh_offset: %#llx\n"
       +                       "\tsh_size: %#llx\n"
       +                       "\tsh_link: %lu\n"
       +                       "\tsh_info: %lu\n"
       +                       "\tsh_addralign: %llu\n"
       +                       "\tsh_entsize: %llu\n",
       +                       i,
       +                       (long) shdr->sh_name,
       +                       type, stype,
       +                       (long long) shdr->sh_flags,
       +                       (long long) shdr->sh_addr,
       +                       (long long) shdr->sh_offset,
       +                       (long long) shdr->sh_size,
       +                       (long) shdr->sh_link,
       +                       (long) shdr->sh_info,
       +                       (long long) shdr->sh_addralign,
       +                       (long long) shdr->sh_entsize);
       +
       +                putchar('\t');
       +                printflags(&f);
       +                putchar('\n');
       +        }
       +}
       +
       +static void
       +printfhdr(Elf_Ehdr *hdr)
       +{
       +        unsigned long version;
       +        unsigned class, data, abi, type, mach;
       +        char *sclass, *sdata, *sabi, *stype, *smach, *sversion;
       +
       +        static char *abis[] = {
       +                [ELFOSABI_SYSV] = "UNIX System V ABI",
       +                [ELFOSABI_HPUX] = "HP-UX operating system",
       +                [ELFOSABI_NETBSD] = "NetBSD",
       +                [ELFOSABI_LINUX] = "GNU/Linux",
       +                [ELFOSABI_HURD] = "GNU/Hurd",
       +                [ELFOSABI_86OPEN] = "86Open common IA32 ABI",
       +                [ELFOSABI_SOLARIS] = "Solaris",
       +                [ELFOSABI_MONTEREY] = "Monterey",
       +                [ELFOSABI_IRIX] = "IRIX",
       +                [ELFOSABI_FREEBSD] = "FreeBSD",
       +                [ELFOSABI_TRU64] = "TRU64 UNIX",
       +                [ELFOSABI_MODESTO] = "Novell Modesto",
       +                [ELFOSABI_OPENBSD] = "OpenBSD",
       +                [ELFOSABI_OPENVMS] = "Open VMS",
       +                [ELFOSABI_NSK] = "Hewlett-Packard Non-Stop Kernel",
       +                [ELFOSABI_AROS] = "Amiga Research OS",
       +                [ELFOSABI_FENIXOS] = "The FenixOS multi-core OS",
       +                [ELFOSABI_CLOUDABI] = "Nuxi CloudABI",
       +                [ELFOSABI_OPENVOS] = "Stratus Technologies OpenVOS",
       +                [ELFOSABI_ARM] = "ARM",
       +                [ELFOSABI_STANDALONE] = "Standalone (embedded) application",
       +        };
       +        static char *classes[] = {
       +                [ELFCLASSNONE] = "invalid",
       +                [ELFCLASS32] = "32-bit objs",
       +                [ELFCLASS64] = "64-bit objs",
       +        };
       +        static char *datas[] = {
       +                [ELFDATANONE] = "invalid",
       +                [ELFDATA2LSB] = "Little-Endian",
       +                [ELFDATA2MSB] = "Big-Endian",
       +        };
       +        static char *types[] = {
       +                [ET_NONE] = "No file type",
       +                [ET_REL] = "Relocatable file",
       +                [ET_EXEC] = "Executable file",
       +                [ET_DYN] = "Shared object file",
       +                [ET_CORE] = "Core file",
       +        };
       +        static char *machs[] = {
       +                [EM_NONE] = "No machine",
       +                [EM_M32] = "AT&T WE 32100",
       +                [EM_SPARC] = "SPARC",
       +                [EM_386] = "Intel 80386",
       +                [EM_68K] = "Motorola 68000",
       +                [EM_88K] = "Motorola 88000",
       +                [EM_IAMCU] = "Intel MCU",
       +                [EM_860] = "Intel 80860",
       +                [EM_MIPS] = "MIPS I Architecture",
       +                [EM_S370] = "IBM System/370 Processor",
       +                [EM_MIPS_RS3_LE] = "MIPS RS3000 Little-endian",
       +                [EM_PARISC] = "Hewlett-Packard PA-RISC",
       +                [EM_VPP500] = "Fujitsu VPP500",
       +                [EM_SPARC32PLUS] = "Enhanced instruction set SPARC",
       +                [EM_960] = "Intel 80960",
       +                [EM_PPC] = "PowerPC",
       +                [EM_PPC64] = "64-bit PowerPC",
       +                [EM_S390] = "IBM System/390",
       +                [EM_SPU] = "IBM SPU/SPC",
       +                [EM_V800] = "NEC V800",
       +                [EM_FR20] = "Fujitsu FR20",
       +                [EM_RH32] = "TRW RH-32",
       +                [EM_RCE] = "Motorola RCE",
       +                [EM_ARM] = "ARM AARCH32",
       +                [EM_ALPHA] = "Digital Alpha",
       +                [EM_SH] = "Hitachi SH",
       +                [EM_SPARCV9] = "SPARC Version 9",
       +                [EM_TRICORE] = "Siemens TriCore",
       +                [EM_ARC] = "Argonaut RISC Core",
       +                [EM_H8_300] = "Hitachi H8/300",
       +                [EM_H8_300H] = "Hitachi H8/300H",
       +                [EM_H8S] = "Hitachi H8S",
       +                [EM_H8_500] = "Hitachi H8/500",
       +                [EM_IA_64] = "Intel IA-64",
       +                [EM_MIPS_X] = "Stanford MIPS-X",
       +                [EM_COLDFIRE] = "Motorola ColdFire",
       +                [EM_68HC12] = "Motorola M68HC12",
       +                [EM_MMA] = "Fujitsu MMA",
       +                [EM_PCP] = "Siemens PCP",
       +                [EM_NCPU] = "Sony nCPU",
       +                [EM_NDR1] = "Denso NDR1",
       +                [EM_STARCORE] = "Motorola Star*Core",
       +                [EM_ME16] = "Toyota ME16",
       +                [EM_ST100] = "STMicroelectronics ST100",
       +                [EM_TINYJ] = "Advanced Logic Corp. TinyJ",
       +                [EM_X86_64] = "AMD x86-64",
       +                [EM_PDSP] = "Sony DSP Processor",
       +                [EM_PDP10] = "DEC PDP-10",
       +                [EM_PDP11] = "DEC PDP-11",
       +                [EM_FX66] = "Siemens FX66",
       +                [EM_ST9PLUS] = "STMicroelectronics ST9+",
       +                [EM_ST7] = "STMicroelectronics ST7",
       +                [EM_68HC16] = "Motorola MC68HC16",
       +                [EM_68HC11] = "Motorola MC68HC11",
       +                [EM_68HC08] = "Motorola MC68HC08",
       +                [EM_68HC05] = "Motorola MC68HC05",
       +                [EM_SVX] = "Silicon Graphics SVx",
       +                [EM_ST19] = "STMicroelectronics ST19",
       +                [EM_VAX] = "Digital VAX",
       +                [EM_CRIS] = "Axis Communications 32-bit",
       +                [EM_JAVELIN] = "Infineon Technologies 32-bit",
       +                [EM_FIREPATH] = "Element 14 64-bit DSP Processor",
       +                [EM_ZSP] = "LSI Logic 16-bit DSP Processor",
       +                [EM_MMIX] = "Donald Knuth's educational 64-bit",
       +                [EM_HUANY] = "Harvard machine-independent",
       +                [EM_PRISM] = "SiTera Prism",
       +                [EM_AVR] = "Atmel AVR 8-bit",
       +                [EM_FR30] = "Fujitsu FR30",
       +                [EM_D10V] = "Mitsubishi D10V",
       +                [EM_D30V] = "Mitsubishi D30V",
       +                [EM_V850] = "NEC v850",
       +                [EM_M32R] = "Mitsubishi M32R",
       +                [EM_MN10300] = "Matsushita MN10300",
       +                [EM_MN10200] = "Matsushita MN10200",
       +                [EM_PJ] = "picoJava",
       +                [EM_OPENRISC] = "OpenRISC 32-bit",
       +                [EM_ARC_A5] = "ARC ARCompact",
       +                [EM_ARC_COMPACT] = "ARC ARCompact",
       +                [EM_XTENSA] = "Tensilica Xtensa",
       +                [EM_VIDEOCORE] = "Alphamosaic VideoCore",
       +                [EM_TMM_GPP] = "Thompson Multimedia GPP",
       +                [EM_NS32K] = "National 32000 series",
       +                [EM_TPC] = "Tenor Network TPC",
       +                [EM_SNP1K] = "Trebia SNP 1000",
       +                [EM_ST200] = "STMicroelectronics ST200",
       +                [EM_IP2K] = "Ubicom IP2xxx",
       +                [EM_MAX] = "MAX Processor",
       +                [EM_CR] = "National CompactRISC",
       +                [EM_F2MC16] = "Fujitsu F2MC16",
       +                [EM_MSP430] = "Texas msp430",
       +                [EM_BLACKFIN] = "Analog Devices Blackfin",
       +                [EM_SE_C33] = "S1C33 of Seiko Epson",
       +                [EM_SEP] = "Sharp embedded",
       +                [EM_ARCA] = "Arca RISC",
       +                [EM_UNICORE] = "PKU-Unity Ltd. and MPRC",
       +                [EM_EXCESS] = "eXcess CPU",
       +                [EM_DXP] = "Deep Execution Processor",
       +                [EM_ALTERA_NIOS2] = "Altera Nios II",
       +                [EM_CRX] = "National CompactRISC CRX",
       +                [EM_XGATE] = "Motorola XGATE",
       +                [EM_C166] = "Infineon C16x/XC16x",
       +                [EM_M16C] = "Renesas M16C",
       +                [EM_DSPIC30F] = "Microchip dsPIC30F",
       +                [EM_CE] = "Freescale Communication Engine",
       +                [EM_M32C] = "Renesas M32C",
       +                [EM_TSK3000] = "Altium TSK3000 core",
       +                [EM_RS08] = "Freescale RS08",
       +                [EM_SHARC] = "Analog Devices SHARC",
       +                [EM_ECOG2] = "Cyan Technology eCOG2",
       +                [EM_SCORE7] = "Sunplus S+core7",
       +                [EM_DSP24] = "NJR 24-bit DSP",
       +                [EM_VIDEOCORE3] = "Broadcom VideoCore III",
       +                [EM_LATTICEMICO3] = "RISC processor for Lattice FPGA",
       +                [EM_SE_C17] = "Seiko Epson C17",
       +                [EM_TI_C6000] = "TMS320C6000 DSP family",
       +                [EM_TI_C2000] = "TMS320C2000 DSP family",
       +                [EM_TI_C5500] = "TMS320C55x DSP family",
       +                [EM_TI_ARP32] = "Texas Application Specific RISC",
       +                [EM_TI_PRU] = "Texas Programmable Realtime Unit",
       +                [EM_MMDSP_PLUS] = "STMicroelectronics 64bit VLIW",
       +                [EM_CYPRESS_M8C] = "Cypress M8C microprocessor",
       +                [EM_R32C] = "Renesas R32C series",
       +                [EM_TRIMEDIA] = "NXP Semiconductors TriMedia",
       +                [EM_QDSP6] = "QUALCOMM DSP6 Processor",
       +                [EM_8051] = "Intel 8051 and variants",
       +                [EM_STXP7X] = "STMicroelectronics STxP7x",
       +                [EM_NDS32] = "Andes Technology embedded RISC",
       +                [EM_ECOG1] = "Cyan Technology eCOG1X family",
       +                [EM_ECOG1X] = "Cyan Technology eCOG1X family",
       +                [EM_MAXQ30] = "MAXQ30 Core Micro-controllers",
       +                [EM_XIMO16] = "NJR 16-bit DSP Processor",
       +                [EM_MANIK] = "M2000 Reconfigurable RISC",
       +                [EM_CRAYNV2] = "Cray Inc. NV2 vector architecture",
       +                [EM_RX] = "Renesas RX family",
       +                [EM_METAG] = "Imagination Technologies META",
       +                [EM_MCST_ELBRUS] = "MCST Elbrus",
       +                [EM_ECOG16] = "Cyan Technology eCOG16 family",
       +                [EM_CR16] = "National CompactRISC CR16",
       +                [EM_ETPU] = "Freescale Extended Time Unit",
       +                [EM_SLE9X] = "Infineon Technologies SLE9X core",
       +                [EM_L10M] = "Intel L10M",
       +                [EM_K10M] = "Intel K10M",
       +                [EM_AARCH64] = "ARM AARCH64",
       +                [EM_AVR32] = "Atmel 32-bit",
       +                [EM_STM8] = "STMicroeletronics STM8 ",
       +                [EM_TILE64] = "Tilera TILE64",
       +                [EM_TILEPRO] = "Tilera TILEPro",
       +                [EM_MICROBLAZE] = "Xilinx MicroBlaze 32-bit",
       +                [EM_CUDA] = "NVIDIA CUDA architecture",
       +                [EM_TILEGX] = "Tilera TILE-Gx family",
       +                [EM_CLOUDSHIELD] = "CloudShield architecture family",
       +                [EM_COREA_1ST] = "KIPO-KAIST Core-A 1st gen family",
       +                [EM_COREA_2ND] = "KIPO-KAIST Core-A 2nd gen family",
       +                [EM_ARC_COMPACT2] = "Synopsys ARCompact V2",
       +                [EM_OPEN8] = "Open8 8-bit RISC soft processor core",
       +                [EM_RL78] = "Renesas RL78 family",
       +                [EM_VIDEOCORE5] = "Broadcom VideoCore V processor",
       +                [EM_78KOR] = "Renesas 78KOR family",
       +                [EM_56800EX] = "Freescale 56800EX (DSC)",
       +                [EM_BA1] = "Beyond BA1 CPU architecture",
       +                [EM_BA2] = "Beyond BA2 CPU architecture",
       +                [EM_XCORE] = "XMOS xCORE processor family",
       +                [EM_MCHP_PIC] = "Microchip 8-bit PIC(r) family",
       +                [EM_KM32] = "KM211 KM32 32-bit processor",
       +                [EM_KMX32] = "KM211 KMX32 32-bit processor",
       +                [EM_KMX16] = "KM211 KMX16 16-bit processor",
       +                [EM_KMX8] = "KM211 KMX8 8-bit processor",
       +                [EM_KVARC] = "KM211 KVARC processor",
       +                [EM_CDP] = "Paneve CDP architecture family",
       +                [EM_COGE] = "Cognitive Smart Memory Processor",
       +                [EM_COOL] = "Bluechip Systems CoolEngine",
       +                [EM_NORC] = "Nanoradio Optimized RISC",
       +                [EM_CSR_KALIMBA] = "CSR Kalimba architecture family",
       +                [EM_Z80] = "Zilog Z80",
       +                [EM_VISIUM] = "VISIUMcore processor",
       +                [EM_FT32] = "FTDI Chip FT32",
       +                [EM_MOXIE] = "Moxie processor family",
       +                [EM_AMDGPU] = "AMD GPU architecture",
       +                [EM_RISCV] = "RISC-V",
       +                [EM_BPF] = "Linux BPF",
       +                [EM_CSKY] = "C-SKY",
       +        };
       +        static char *versions[] = {
       +                [EV_NONE] = "Invalid",
       +                [EV_CURRENT] = "Current",
       +        };
       +
       +        class = hdr->e_ident[EI_CLASS];
       +        data = hdr->e_ident[EI_DATA];
       +        abi = hdr->e_ident[EI_OSABI];
       +        type = hdr->e_type;
       +        mach = hdr->e_machine;
       +        version = hdr->e_version;
       +
       +        sclass = (class <= ELFCLASS64) ? classes[class] : "Unknown";
       +        sdata = (data <= ELFDATA2MSB) ? datas[data] : "Unknown";
       +        stype = (type <= ET_CORE) ? types[type] : "Unknown";
       +        smach = (mach <= EM_CSKY) ? machs[mach] : "Unknown";
       +        if (!smach)
       +                smach = "Unknown";
       +        sversion = (version <= EV_CURRENT) ? versions[version] : "Unknown";
       +
       +        switch (abi) {
       +        case ELFOSABI_ARM:
       +                sabi = "ARM";
       +                break;
       +        case ELFOSABI_STANDALONE:
       +                sabi = "Standalone (embedded) application";
       +                break;
       +        default:
       +                sabi = (abi <= ELFOSABI_OPENVOS) ? abis[abi] : "Unknown";
       +        }
       +
       +        printf("elfhdr64:\n"
       +               "\tei_class: %u, %s\n"
       +               "\tei_data: %u, %s\n"
       +               "\tei_version: %u\n"
       +               "\tei_osabi: %u, %s\n"
       +               "\tei_abiversion: %u\n"
       +               "\te_type: %u, %s\n"
       +               "\te_machine: %u, %s\n"
       +               "\te_version: %lu, %s\n"
       +               "\te_entry: 0x%08llx\n"
       +               "\te_phoff: %llu\n"
       +               "\te_shoff: %llu\n"
       +               "\te_flags: %#lx\n"
       +               "\te_ehsize: %lu\n"
       +               "\te_phentsize: %lu\n"
       +               "\te_phnum: %lu\n"
       +               "\te_shentsize: %lu\n"
       +               "\te_shnum: %lu\n"
       +               "\te_shstrndx: %lu\n"
       +               "\n",
       +               class, sclass,
       +               data, sdata,
       +               hdr->e_ident[EI_VERSION],
       +               abi, sabi,
       +               hdr->e_ident[EI_ABIVERSION],
       +               type, stype,
       +               mach, smach,
       +               version, sversion,
       +               (long long) hdr->e_entry,
       +               (long long) hdr->e_phoff,
       +               (long long) hdr->e_shoff,
       +               (long) hdr->e_flags,
       +               (long) hdr->e_ehsize,
       +               (long) hdr->e_phentsize,
       +               (long) hdr->e_phnum,
       +               (long) hdr->e_shentsize,
       +               (long) hdr->e_shnum,
       +               (long) hdr->e_shstrndx);
       +}
       +
       +static void
       +printphdr(Elf_Phdr *phdr, unsigned long n)
       +{
       +        unsigned long i;
       +        static char *types[] = {
       +                [PT_NULL] = "unused",
       +                [PT_LOAD] = "loadable segment",
       +                [PT_DYNAMIC] = "dynamic linking section",
       +                [PT_INTERP] = "the RTLD",
       +                [PT_NOTE] = "auxiliary information",
       +                [PT_SHLIB] = "reserved - purpose undefined",
       +                [PT_PHDR] = "program header",
       +                [PT_TLS] = "thread local storage",
       +        };
       +        static Flags f ={
       +                .nr = NR_RIGHTS,
       +                .text = {
       +                        [FLAG_X] = "Executable",
       +                        [FLAG_W] = "Writable",
       +                        [FLAG_R] = "Readable",
       +                }
       +        };
       +
       +        for (i = 0; i < n; i++) {
       +                unsigned long type;
       +                char *stype;
       +
       +                type = phdr->p_type;
       +                stype = (type <= PT_TLS) ? types[type] : "Unknown";
       +                f.flags = phdr->p_flags;
       +
       +                printf("Program header %ld\n"
       +                       "\tp_type: %#lx, %s\n"
       +                       "\tp_flags: %#lx\n"
       +                       "\tp_offset: %#08llx\n"
       +                       "\tp_vaddr: %#08llx\n"
       +                       "\tp_paddr: %#08llx\n"
       +                       "\tp_filesz: %#08llx\n"
       +                       "\tp_memsz: %#08llx\n"
       +                       "\tp_align: %#08llx\n",
       +                       i,
       +                       type, stype,
       +                       (long) phdr->p_flags,
       +                       (long long) phdr->p_offset,
       +                       (long long) phdr->p_vaddr,
       +                       (long long) phdr->p_paddr,
       +                       (long long) phdr->p_filesz,
       +                       (long long) phdr->p_memsz,
       +                       (long long) phdr->p_align);
       +
       +                putchar('\t');
       +                printflags(&f);
       +                putchar('\n');
       +                ++phdr;
       +        }
       +}
       +
       +void
       +elf64fhdr(Obj *obj, unsigned long long *start, Flags *f)
       +{
       +        size_t i;
       +        char *name;
       +        Elf64 *elf = obj->data;
       +        Elf_Ehdr *hdr = &elf->hdr;
       +        Elf_Shdr *shdr;
       +
       +        *start = hdr->e_entry;
       +
       +        for (i = 0; i < elf->nsec; i++) {
       +                shdr = &elf->shdr[i];
       +                name = elf64str(obj, SEC_STRTBL, shdr->sh_name);
       +                setflag(f, strncmp(name, ".debug", 6) == 0, HAS_DEBUG);
       +                setflag(f, strncmp(name, ".line", 5) == 0, HAS_LINENO);
       +                setflag(f, strcmp(name, ".debug_line") == 0, HAS_LINENO);
       +                setflag(f, shdr->sh_type == SHT_RELA, HAS_RELOC);
       +                setflag(f, shdr->sh_type == SHT_REL, HAS_RELOC);
       +        }
       +
       +        setflag(f, hdr->e_type == ET_EXEC, EXEC_P);
       +        setflag(f, hdr->e_type == ET_DYN, DYNAMIC);
       +        setflag(f, elf->nsym > 0, HAS_SYMS);
       +
       +        if (!pflag)
       +                return;
       +
       +        printfhdr(hdr);
       +        printphdr(elf->phdr, hdr->e_phnum);
       +}
 (DIR) diff --git a/src/cmd/scc-objdump/main.c b/src/cmd/scc-objdump/main.c
       @@ -90,6 +90,9 @@ dumpfhdr(Obj *obj, char *fmt)
                case COFF32:
                        coff32fhdr(obj, &start, &f);
                        break;
       +        case ELF64:
       +                elf64fhdr(obj, &start, &f);
       +                break;
                default:
                        error("unknown fhdr binary format");
                        return;
       @@ -128,6 +131,21 @@ selected(char *secname)
                return 0;
        }
        
       +static int
       +hasrelloc(Obj *obj, Section *sec)
       +{
       +        switch (FORMAT(obj->type)) {
       +        case COFF32:
       +                coff32hasrelloc(obj, sec);
       +                break;
       +        case ELF64:
       +                elf64hasrelloc(obj, sec);
       +                break;
       +        default:
       +                return 0;
       +        }
       +}
       +
        static void
        dumpscns(Obj *obj)
        {
       @@ -168,7 +186,7 @@ dumpscns(Obj *obj)
                        debug = sec.type == 'N';
                        setflag(&f, flags & SALLOC, SEC_ALLOC);
                        setflag(&f, flags & SLOAD, SEC_LOAD);
       -                setflag(&f, (flags & SRELOC) && sec.nreloc > 0, SEC_RELOC);
       +                setflag(&f, hasrelloc(obj, &sec), SEC_RELOC);
                        setflag(&f, (flags & SWRITE) == 0 && !debug, SEC_READONLY);
                        setflag(&f, flags & SEXEC, SEC_CODE);
                        setflag(&f, (flags & (SEXEC|SLOAD)) == SLOAD, SEC_DATA);
       @@ -185,6 +203,9 @@ dumpscns(Obj *obj)
                case COFF32:
                        coff32scns(obj);
                        break;
       +        case ELF64:
       +                elf64scns(obj);
       +                break;
                default:
                        error("unknown fhdr binary format");
                }
       @@ -253,6 +274,9 @@ dumpsyms(Obj *obj)
                case COFF32:
                        coff32syms(obj);
                        break;
       +        case ELF64:
       +                elf64syms(obj);
       +                break;
                default:
                        error("unknown symbol binary format");
                }
 (DIR) diff --git a/src/cmd/scc-objdump/objdump.h b/src/cmd/scc-objdump/objdump.h
       @@ -33,6 +33,13 @@ struct flags {
        extern void coff32syms(Obj *);
        extern void coff32scns(Obj *);
        extern void coff32fhdr(Obj *, unsigned long long *, Flags *);
       +extern int coff32hasrelloc(Obj *, Section *);
       +
       +/* elf64.c */
       +extern void elf64syms(Obj *);
       +extern void elf64scns(Obj *);
       +extern void elf64fhdr(Obj *, unsigned long long *, Flags *);
       +extern int elf64hasrelloc(Obj *, Section *);
        
        /* main.c */
        extern void error(char *, ...);
 (DIR) diff --git a/src/libmach/coff32/coff32getsec.c b/src/libmach/coff32/coff32getsec.c
       @@ -85,7 +85,6 @@ coff32getsec(Obj *obj, int *idx, Section *sec)
                sec->base = scn->s_vaddr;
                sec->load = scn->s_paddr;
                sec->offset = scn->s_scnptr;
       -        sec->nreloc = scn->s_nrelloc;
                sec->type = type;
                sec->flags = sflags;
                sec->align = 4;
 (DIR) diff --git a/src/libmach/elf64/elf64getsec.c b/src/libmach/elf64/elf64getsec.c
       @@ -15,8 +15,15 @@ elf64getsec(Obj *obj, int *idx, Section *sec)
                Elf_Ehdr *hdr = &elf->hdr;
                Elf_Shdr *shdr;
        
       -        if (n >= elf->nsec)
       +        if (n >= elf->nsec) {
       +                if (n == SHN_ABS)
       +                        sec->name = "*ABS";
       +                else if (n == SHN_COMMON)
       +                        sec->name = "*COM*";
       +                else
       +                        sec->name = "*UNK*";
                        return NULL;
       +        }
        
                shdr = &elf->shdr[n];
                flags = shdr->sh_flags;
       @@ -49,11 +56,6 @@ elf64getsec(Obj *obj, int *idx, Section *sec)
                 * We cannot differentiate between load and base address
                 * in a section, while we can use the physical address
                 * for that when dealing with segments.
       -         * Also, we don't have an easy way to know the number of
       -         * relocations affecting one section. To know that, we
       -         * have to run over the relocation sections and find one
       -         * with the sh_link pointing to this section. Maybe,
       -         * we should just remove the nrelloc field.
                 */
                if (n == SHN_UNDEF)
                        sec->name = "*UND*";
       @@ -65,7 +67,6 @@ elf64getsec(Obj *obj, int *idx, Section *sec)
                sec->base = shdr->sh_addr;
                sec->load = shdr->sh_addr;
                sec->offset = shdr->sh_offset;
       -        sec->nreloc = 0;
                sec->type = stype;
                sec->flags = sflags;
                sec->align = shdr->sh_addralign;