libmach: Rewrite elf support - 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 71539b6717e562995e294b8b2d0173cd38885354
 (DIR) parent 5d5161359e267f3f6dc4979fa46fe4a351acc884
 (HTM) Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
       Date:   Tue, 28 Jan 2025 12:46:29 +0100
       
       libmach: Rewrite elf support
       
       This rewrite was needed to support any elf file,
       independently of the target machine, and without
       worring about 32 or 64 bit elf version.
       
       Diffstat:
         A include/bits/scc/elf.h              |     107 +++++++++++++++++++++++++++++++
         M include/bits/scc/elf/elfent.h       |      16 ++++++++++------
         M include/bits/scc/elf/elfhdr.h       |       2 +-
         M include/bits/scc/elf64.h            |       2 --
         M include/bits/scc/mach.h             |       4 +++-
         M src/cmd/scc-objdump/Makefile        |       2 +-
         A src/cmd/scc-objdump/elf.c           |     738 ++++++++++++++++++++++++++++++
         D src/cmd/scc-objdump/elf64.c         |     734 ------------------------------
         M src/cmd/scc-objdump/main.c          |      10 +++++-----
         M src/cmd/scc-objdump/objdump.h       |       8 ++++----
         M src/libmach/Makefile                |       4 ++--
         M src/libmach/delobj.c                |       4 ++--
         A src/libmach/elf/Makefile            |      25 +++++++++++++++++++++++++
         A src/libmach/elf/elfarchs.c          |      19 +++++++++++++++++++
         A src/libmach/elf/elfdel.c            |      23 +++++++++++++++++++++++
         A src/libmach/elf/elfgetsec.c         |      77 +++++++++++++++++++++++++++++++
         A src/libmach/elf/elfgetsym.c         |     123 +++++++++++++++++++++++++++++++
         A src/libmach/elf/elfnew.c            |      20 ++++++++++++++++++++
         A src/libmach/elf/elfprobe.c          |      47 +++++++++++++++++++++++++++++++
         A src/libmach/elf/elfread.c           |     761 ++++++++++++++++++++++++++++++
         A src/libmach/elf/elftype.c           |      21 +++++++++++++++++++++
         A src/libmach/elf/fun.h               |      17 +++++++++++++++++
         D src/libmach/elf64/Makefile          |      35 -------------------------------
         D src/libmach/elf64/elf64.c           |      24 ------------------------
         D src/libmach/elf64/elf64archs.c      |      16 ----------------
         D src/libmach/elf64/elf64del.c        |      24 ------------------------
         D src/libmach/elf64/elf64getsec.c     |      76 -------------------------------
         D src/libmach/elf64/elf64getsym.c     |     112 -------------------------------
         D src/libmach/elf64/elf64new.c        |      20 --------------------
         D src/libmach/elf64/elf64probe.c      |      45 -------------------------------
         D src/libmach/elf64/elf64read.c       |     386 -------------------------------
         D src/libmach/elf64/elf64type.c       |      21 ---------------------
         D src/libmach/elf64/fun.h             |      17 -----------------
         M src/libmach/getindex.c              |       2 +-
         M src/libmach/getsec.c                |       4 ++--
         M src/libmach/getsym.c                |       4 ++--
         M src/libmach/loadmap.c               |       2 +-
         M src/libmach/newobj.c                |       4 ++--
         M src/libmach/objprobe.c              |       4 ++--
         M src/libmach/objtype.c               |       4 ++--
         M src/libmach/pc2line.c               |       2 +-
         M src/libmach/readobj.c               |       4 ++--
         M src/libmach/setindex.c              |       2 +-
         M src/libmach/setsec.c                |       2 +-
         M src/libmach/setsym.c                |       2 +-
         M src/libmach/strip.c                 |       2 +-
         M src/libmach/writeobj.c              |       2 +-
       
       47 files changed, 2026 insertions(+), 1554 deletions(-)
       ---
 (DIR) diff --git a/include/bits/scc/elf.h b/include/bits/scc/elf.h
       @@ -0,0 +1,107 @@
       +#define EI_NIDENT               16
       +
       +typedef struct elf Elf;
       +typedef struct elfhdr Elfhdr;
       +typedef struct elfphdr Elfphdr;
       +typedef struct elfsec Elfsec;
       +typedef struct elfsym Elfsym;
       +typedef struct elfpack Elfpack;
       +typedef struct elfunpack Elfunpack;
       +typedef struct elfrel Elfrel;
       +
       +struct elfhdr {
       +        unsigned char ident[EI_NIDENT];
       +        unsigned short type;
       +        unsigned short machine;
       +        unsigned long version;
       +        unsigned long long entry;
       +        unsigned long long phoff;
       +        unsigned long long shoff;
       +        unsigned long flags;
       +        unsigned short ehsize;
       +
       +        unsigned short phentsize;
       +        unsigned short phnum;
       +
       +        unsigned short shentsize;
       +        unsigned short shnum;
       +        unsigned short shstrndx;
       +};
       +
       +struct elfphdr {
       +        unsigned long type;
       +        unsigned long flags;
       +        unsigned long long offset;
       +
       +        unsigned long long vaddr;
       +        unsigned long long paddr;
       +
       +        unsigned long long filesz;
       +        unsigned long long memsz;
       +        unsigned long long align;
       +};
       +
       +struct elfsec {
       +        char *name;
       +        char *strtbl;
       +
       +        unsigned long sh_name;
       +        unsigned long type;
       +        unsigned long long flags;
       +        unsigned long long addr;
       +        unsigned long long offset;
       +        unsigned long long size;
       +        unsigned long link;
       +        unsigned long info;
       +        unsigned long long addralign;
       +        unsigned long long entsize;
       +};
       +
       +struct elfrel {
       +        Elfsym *sym;
       +        Elfsec *sec;
       +
       +        unsigned long long off;
       +        unsigned long info;
       +        long addend;
       +};
       +
       +struct elfsym {
       +        char *name;
       +        Elfsec *symsec;
       +
       +        unsigned long st_name;
       +        unsigned char info;
       +        unsigned char other;
       +        unsigned short shndx;
       +        unsigned long long value;
       +        unsigned long long size;
       +};
       +
       +struct elf {
       +        Elfhdr hdr;
       +        Elfphdr *phdr;
       +
       +        Elfsec *secs;
       +        int nsec;
       +        int secstrtbl;
       +
       +        Elfsym *syms;
       +        int nsym;
       +
       +        Elfrel *rels;
       +        int nrel;
       +
       +        Elfpack *pack;
       +        Elfunpack *unpack;
       +};
       +
       +struct arch {
       +        char *name;
       +        int mach;
       +        int endian;
       +        int type;
       +};
       +
       +/* globals */
       +extern struct arch elfarchs[];
 (DIR) diff --git a/include/bits/scc/elf/elfent.h b/include/bits/scc/elf/elfent.h
       @@ -4,13 +4,17 @@
        #define STN_UNDEF       0               /* undefined */
        
        /* Extract symbol info - st_info */
       -#define ELF32_ST_BIND(x)        ((x) >> 4)
       -#define ELF32_ST_TYPE(x)        (((unsigned int) x) & 0xf)
       -#define ELF32_ST_INFO(b,t)      (((b) << 4) + ((t) & 0xf))
       +#define ELF_ST_BIND(x)        ((x) >> 4)
       +#define ELF_ST_TYPE(x)        (((unsigned int) x) & 0xf)
       +#define ELF_ST_INFO(b,t)      (((b) << 4) + ((t) & 0xf))
        
       -#define ELF64_ST_BIND(x)        ((x) >> 4)
       -#define ELF64_ST_TYPE(x)        (((unsigned int) x) & 0xf)
       -#define ELF64_ST_INFO(b,t)      (((b) << 4) + ((t) & 0xf))
       +#define ELF32_ST_BIND(x)        ELF_ST_BIND(x)
       +#define ELF32_ST_TYPE(x)        ELF_ST_TYPE(x)
       +#define ELF32_ST_INFO(b,t)      ELF_ST_INFO(b, t)
       +
       +#define ELF64_ST_BIND(x)        ELF_ST_BIND(x)
       +#define ELF64_ST_TYPE(x)        ELF_ST_TYPE(x)
       +#define ELF64_ST_INFO(b,t)      ELF_ST_INFO(b, t)
        
        /* Symbol Binding - ELF32_ST_BIND - st_info */
        #define STB_LOCAL       0               /* Local symbol */
 (DIR) diff --git a/include/bits/scc/elf/elfhdr.h b/include/bits/scc/elf/elfhdr.h
       @@ -261,7 +261,7 @@
        /* Magic for e_phnum: get real value from sh_info of first section header */
        #define PN_XNUM                0xffff
        
       -#define ELFH32SZ              54
       +#define ELFH32SZ              52
        #define ELFH64SZ              64
        
        typedef struct elfhdr32 Elf32_Ehdr;
 (DIR) diff --git a/include/bits/scc/elf64.h b/include/bits/scc/elf64.h
       @@ -4,8 +4,6 @@
        #include <scc/elf/elfshdr.h>
        #include <scc/elf/elfent.h>
        
       -#define ELF_ST_BIND ELF64_ST_BIND
       -#define ELF_ST_TYPE ELF64_ST_TYPE
        #define Elf_Ehdr Elf64_Ehdr
        #define Elf_Phdr Elf64_Phdr
        #define Elf_Shdr Elf64_Shdr
 (DIR) diff --git a/include/bits/scc/mach.h b/include/bits/scc/mach.h
       @@ -21,7 +21,7 @@ typedef struct mapsec Mapsec;
        
        enum objformat {
                COFF32,
       -        ELF64,
       +        ELF,
                NFORMATS,
        };
        
       @@ -32,6 +32,8 @@ enum objarch {
                ARCHZ80,
                ARCHARM32,
                ARCHARM64,
       +        ARCHUNK32,
       +        ARCHUNK64,
        };
        
        enum order {
 (DIR) diff --git a/src/cmd/scc-objdump/Makefile b/src/cmd/scc-objdump/Makefile
       @@ -6,7 +6,7 @@ include $(PROJECTDIR)/scripts/rules.mk
        OBJS =\
                main.o\
                coff32.o\
       -        elf64.o\
       +        elf.o\
        
        TARGET = scc-objdump
        MORE_LDLIBS = -lmach -lscc
 (DIR) diff --git a/src/cmd/scc-objdump/elf.c b/src/cmd/scc-objdump/elf.c
       @@ -0,0 +1,738 @@
       +#include <stdio.h>
       +#include <stdlib.h>
       +#include <string.h>
       +
       +#include <scc/mach.h>
       +#include <scc/elf/elftypes.h>
       +#include <scc/elf/elfhdr.h>
       +#include <scc/elf/elfphdr.h>
       +#include <scc/elf/elfshdr.h>
       +#include <scc/elf/elfent.h>
       +#include <scc/elf.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
       +elfhasrelloc(Obj *obj, Section *sec)
       +{
       +        size_t i;
       +        Elf *elf = obj->data;
       +        Elfsec *shdr;
       +
       +        for (i = 0; i < elf->nsec; i++) {
       +                shdr = &elf->secs[i];
       +                if (shdr->type != SHT_RELA && shdr->type != SHT_REL)
       +                        continue;
       +                if (shdr->info == sec->index)
       +                        return 1;
       +        }
       +
       +        return 0;
       +}
       +
       +static void
       +printents(Obj *obj)
       +{
       +        int n;
       +        size_t i;
       +        Section sec;
       +        Elfsym *ent;
       +        Elf *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->info;
       +                bind = ELF_ST_BIND(info);
       +                type = ELF_ST_TYPE(info);
       +                vis = ELF_ST_VISIBILITY(ent->other);
       +                nsec = ent->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: %#llx\n"
       +                        "\tst_size: %llu\n"
       +                        "\n",
       +                        i,
       +                        (long) ent->st_name, ent->name,
       +                        info,
       +                        bind, sbind,
       +                        type, stype,
       +                        vis, svis,
       +                        nsec, ssec,
       +                        (unsigned long long) ent->value,
       +                        (unsigned long long) ent->size);
       +        }
       +}
       +
       +static void
       +printstbl(Obj *obj)
       +{
       +        int n;
       +        size_t i;
       +        Symbol sym;
       +        Section sec;
       +        Elfsym *ent;
       +        Elfsec *shdr;
       +        Elf *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->secs[ent->shndx];
       +                n = i;
       +                getsym(obj, &n, &sym);
       +                n = ent->shndx;
       +                getsec(obj, &n, &sec);
       +
       +                info = ent->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 = (ent->symsec->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->value,
       +                       cbind,
       +                       cweak,
       +                       cctor,
       +                       cwarn,
       +                       cindir,
       +                       cdebug,
       +                       ctype,
       +                       sec.name,
       +                       (long long) ent->size,
       +                       sym.name,
       +                       i);
       +        }
       +}
       +
       +void
       +elfsyms(Obj *obj)
       +{
       +        printstbl(obj);
       +
       +        if (pflag)
       +                printents(obj);
       +}
       +
       +void
       +elfscns(Obj *obj)
       +{
       +        size_t i;
       +        Elf *elf = obj->data;
       +        Elfsec *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->secs[i];
       +
       +                type = shdr->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->flags;
       +
       +                printf("Section %zu:\n"
       +                       "\tsh_name: %lu %s\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, shdr->name,
       +                       type, stype,
       +                       (long long) shdr->flags,
       +                       (long long) shdr->addr,
       +                       (long long) shdr->offset,
       +                       (long long) shdr->size,
       +                       (long) shdr->link,
       +                       (long) shdr->info,
       +                       (long long) shdr->addralign,
       +                       (long long) shdr->entsize);
       +
       +                putchar('\t');
       +                printflags(&f);
       +                putchar('\n');
       +        }
       +}
       +
       +static void
       +printfhdr(Elfhdr *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->ident[EI_CLASS];
       +        data = hdr->ident[EI_DATA];
       +        abi = hdr->ident[EI_OSABI];
       +        type = hdr->type;
       +        mach = hdr->machine;
       +        version = hdr->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("elfhdr:\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->ident[EI_VERSION],
       +               abi, sabi,
       +               hdr->ident[EI_ABIVERSION],
       +               type, stype,
       +               mach, smach,
       +               version, sversion,
       +               (long long) hdr->entry,
       +               (long long) hdr->phoff,
       +               (long long) hdr->shoff,
       +               (long) hdr->flags,
       +               (long) hdr->ehsize,
       +               (long) hdr->phentsize,
       +               (long) hdr->phnum,
       +               (long) hdr->shentsize,
       +               (long) hdr->shnum,
       +               (long) hdr->shstrndx);
       +}
       +
       +static void
       +printphdr(Elfphdr *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->type;
       +                stype = (type <= PT_TLS) ? types[type] : "Unknown";
       +                f.flags = phdr->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->flags,
       +                       (long long) phdr->offset,
       +                       (long long) phdr->vaddr,
       +                       (long long) phdr->paddr,
       +                       (long long) phdr->filesz,
       +                       (long long) phdr->memsz,
       +                       (long long) phdr->align);
       +
       +                putchar('\t');
       +                printflags(&f);
       +                putchar('\n');
       +                ++phdr;
       +        }
       +}
       +
       +void
       +elffhdr(Obj *obj, unsigned long long *start, Flags *f)
       +{
       +        size_t i;
       +        char *name;
       +        Elf *elf = obj->data;
       +        Elfhdr *hdr = &elf->hdr;
       +        Elfsec *shdr;
       +
       +        *start = hdr->entry;
       +
       +        for (i = 0; i < elf->nsec; i++) {
       +                shdr = &elf->secs[i];
       +                name = shdr->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->type == SHT_RELA, HAS_RELOC);
       +                setflag(f, shdr->type == SHT_REL, HAS_RELOC);
       +        }
       +
       +        setflag(f, hdr->type == ET_EXEC, EXEC_P);
       +        setflag(f, hdr->type == ET_DYN, DYNAMIC);
       +        setflag(f, elf->nsym > 0, HAS_SYMS);
       +
       +        if (!pflag)
       +                return;
       +
       +        printfhdr(hdr);
       +        printphdr(elf->phdr, hdr->phnum);
       +}
 (DIR) diff --git a/src/cmd/scc-objdump/elf64.c b/src/cmd/scc-objdump/elf64.c
       @@ -1,734 +0,0 @@
       -#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
       @@ -34,11 +34,11 @@ static struct binops *op, ops[NFORMATS] = {
                        .dumpfhdr = coff32fhdr,
                        .hasrelloc = coff32hasrelloc,
                },
       -        [ELF64] = {
       -                .dumpsyms = elf64syms,
       -                .dumpsecs = elf64scns,
       -                .dumpfhdr = elf64fhdr,
       -                .hasrelloc = elf64hasrelloc,
       +        [ELF] = {
       +                .dumpsyms = elfsyms,
       +                .dumpsecs = elfscns,
       +                .dumpfhdr = elffhdr,
       +                .hasrelloc = elfhasrelloc,
                },
        };
        
 (DIR) diff --git a/src/cmd/scc-objdump/objdump.h b/src/cmd/scc-objdump/objdump.h
       @@ -36,10 +36,10 @@ 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 *);
       +extern void elfsyms(Obj *);
       +extern void elfscns(Obj *);
       +extern void elffhdr(Obj *, unsigned long long *, Flags *);
       +extern int elfhasrelloc(Obj *, Section *);
        
        /* main.c */
        extern void error(char *, ...);
 (DIR) diff --git a/src/libmach/Makefile b/src/libmach/Makefile
       @@ -1,7 +1,7 @@
        .POSIX:
        
        DIRS =\
       -        elf64\
       +        elf\
                coff32\
        
        PROJECTDIR =../..
       @@ -45,4 +45,4 @@ $(TARGET): $(OBJS)
                cp $@ $(LIBDIR)/scc
        
        dep:
       -        ./mkdep elf64 coff32
       +        ./mkdep elf coff32
 (DIR) diff --git a/src/libmach/delobj.c b/src/libmach/delobj.c
       @@ -5,12 +5,12 @@
        
        #include "libmach.h"
        
       -#include "elf64/fun.h"
       +#include "elf/fun.h"
        #include "coff32/fun.h"
        
        static void (*ops[NFORMATS])(Obj *) = {
                [COFF32] = coff32del,
       -        [ELF64] = elf64del,
       +        [ELF] = elfdel,
        };
        
        void
 (DIR) diff --git a/src/libmach/elf/Makefile b/src/libmach/elf/Makefile
       @@ -0,0 +1,25 @@
       +.POSIX:
       +
       +PROJECTDIR =../../..
       +include $(PROJECTDIR)/scripts/rules.mk
       +
       +OBJS =\
       +        elfarchs.o\
       +        elfdel.o\
       +        elfgetsec.o\
       +        elfgetsym.o\
       +        elfnew.o\
       +        elfprobe.o\
       +        elfread.o\
       +        elftype.o\
       +
       +all: $(OBJS)
       +
       +dep:
       +        @(printf 'ELFOBJS=\\';\
       +        echo;\
       +        echo $(OBJS) |\
       +        sed -E 's@ *([^ ]*)@\telf/\1\\\n@g') > deps.mk
       +
       +distclean:
       +        rm -f deps.mk
 (DIR) diff --git a/src/libmach/elf/elfarchs.c b/src/libmach/elf/elfarchs.c
       @@ -0,0 +1,19 @@
       +#include <stdio.h>
       +
       +
       +#include <scc/mach.h>
       +#include <scc/elf/elftypes.h>
       +#include <scc/elf/elfhdr.h>
       +#include <scc/elf.h>
       +
       +#include "../libmach.h"
       +
       +struct arch elfarchs[] = {
       +        {
       +                .name = "elf-amd64",
       +                .mach = EM_X86_64,
       +                .endian = ELFDATA2LSB,
       +                .type = OBJ(ELF, ARCHAMD64, LITTLE_ENDIAN),
       +        },
       +        NULL,
       +};
 (DIR) diff --git a/src/libmach/elf/elfdel.c b/src/libmach/elf/elfdel.c
       @@ -0,0 +1,23 @@
       +#include <stdio.h>
       +#include <stdlib.h>
       +
       +#include <scc/mach.h>
       +#include <scc/elf.h>
       +
       +#include "../libmach.h"
       +#include "fun.h"
       +
       +void
       +elfdel(Obj *obj)
       +{
       +        struct elf *elf = obj->data;
       +
       +        if (elf) {
       +                free(elf->phdr);
       +                free(elf->secs);
       +                free(elf->syms);
       +                free(elf->rels);
       +        }
       +        free(obj->data);
       +        obj->data = NULL;
       +}
 (DIR) diff --git a/src/libmach/elf/elfgetsec.c b/src/libmach/elf/elfgetsec.c
       @@ -0,0 +1,77 @@
       +#include <stdio.h>
       +
       +#include <scc/mach.h>
       +#include <scc/elf/elftypes.h>
       +#include <scc/elf/elfshdr.h>
       +#include <scc/elf.h>
       +
       +#include "../libmach.h"
       +#include "fun.h"
       +
       +Section *
       +elfgetsec(Obj *obj, int *idx, Section *sec)
       +{
       +        int stype, n = *idx;
       +        unsigned long flags, type;
       +        unsigned sflags;
       +        Elf *elf = obj->data;
       +        Elfsec *shdr;
       +
       +        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->secs[n];
       +        flags = shdr->flags;
       +        type = shdr->type;
       +
       +        if (flags & SHF_ALLOC) {
       +                if (type == SHT_NOBITS)
       +                        stype = 'B';
       +                else if (flags & SHF_WRITE)
       +                        stype = 'D';
       +                else
       +                        stype = 'T';
       +        } else {
       +                stype = 'N';
       +        }
       +
       +        sflags = 0;
       +        if (flags & SHF_WRITE)
       +                sflags |= SWRITE;
       +        if (flags  & SHF_EXECINSTR)
       +                sflags |= SEXEC;
       +        if (flags & SHF_ALLOC)
       +                sflags |= SLOAD|SREAD;
       +        if (type != SHT_NOBITS)
       +                sflags |= SALLOC;
       +        if (stype == 'T' || stype == 'D')
       +                sflags |= SRELOC;
       +
       +        /*
       +         * We cannot differentiate between load and base address
       +         * in a section, while we can use the physical address
       +         * for that when dealing with segments.
       +         */
       +        if (n == SHN_UNDEF)
       +                sec->name = "*UND*";
       +        else
       +                sec->name = shdr->name;
       +
       +        sec->index = n;
       +        sec->size = shdr->size;
       +        sec->base = shdr->addr;
       +        sec->load = shdr->addr;
       +        sec->offset = shdr->offset;
       +        sec->type = stype;
       +        sec->flags = sflags;
       +        sec->align = shdr->addralign;
       +
       +        return sec;
       +}
 (DIR) diff --git a/src/libmach/elf/elfgetsym.c b/src/libmach/elf/elfgetsym.c
       @@ -0,0 +1,123 @@
       +#include <ctype.h>
       +#include <stdio.h>
       +#include <stdlib.h>
       +#include <string.h>
       +
       +#include <scc/mach.h>
       +#include <scc/elf/elftypes.h>
       +#include <scc/elf/elfent.h>
       +#include <scc/elf/elfshdr.h>
       +#include <scc/elf.h>
       +
       +#include "../libmach.h"
       +#include "fun.h"
       +
       +static int
       +typeof(Elf *elf, Elfsym *ent, char *name)
       +{
       +        int c, bind, weak;
       +        unsigned long flags, type;
       +        Elfsec *shdr;
       +
       +        weak = ELF_ST_BIND(ent->info) == STB_WEAK;
       +
       +        switch (ent->shndx) {
       +        case SHN_UNDEF:
       +                c = 'U';
       +                break;
       +        case SHN_ABS:
       +                c = 'a';
       +                break;
       +        case SHN_COMMON:
       +                c = 'C';
       +                break;
       +        case SHN_XINDEX:
       +                abort();
       +        default:
       +                shdr = &elf->secs[ent->shndx];
       +                flags = shdr->flags;
       +                type = shdr->type;
       +
       +                if (ELF_ST_BIND(ent->info) == STB_WEAK) {
       +                        c = (flags & SHF_EXECINSTR) ? 'W' : 'V';
       +                } else {
       +                        if (flags & SHF_ALLOC) {
       +                                if (type == SHT_NOBITS)
       +                                        c = 'b';
       +                                else if (flags & SHF_WRITE)
       +                                        c = 'd';
       +                                else if (flags & SHF_EXECINSTR)
       +                                        c = 't';
       +                                else
       +                                        c = 'r';
       +                        } else if (strncmp(name, ".debug", 6) == 0) {
       +                                c = 'N';
       +                        } else if (strcmp(name, ".comment") == 0) {
       +                                c = 'N';
       +                        } else if (strcmp(name, ".line") == 0) {
       +                                c = 'N';
       +                        } else if (strcmp(name, ".stab") == 0) {
       +                                c = 'N';
       +                        } else {
       +                                c = '?';
       +                        }
       +                        if (ELF_ST_BIND(ent->info) != STB_LOCAL)
       +                                c = toupper(c);
       +                }
       +        }
       +
       +        return c;
       +}
       +
       +static int
       +stypeof(Elfsym *ent)
       +{
       +        switch (ELF_ST_TYPE(ent->info)) {
       +        case STT_OBJECT:
       +                return SYMOBJECT;
       +        case STT_FUNC:
       +                return SYMFUNC;
       +        case STT_SECTION:
       +                return SYMSECTION;
       +        case STT_FILE:
       +                return SYMFILE;
       +        case STT_COMMON:
       +                return SYMCOMMON;
       +        default:
       +        case STT_NOTYPE:
       +                return SYMNOTYPE;
       +        }
       +}
       +
       +#include <assert.h>
       +
       +Symbol *
       +elfgetsym(Obj *obj, int *idx, Symbol *sym)
       +{
       +        int n = *idx;
       +        Elfsym *ent;
       +        Elf *elf = obj->data;
       +
       +        if (n == 0)
       +                n++;
       +
       +        if (!elf->syms || n >= elf->nsym)
       +                return NULL;
       +        ent = &elf->syms[n];
       +
       +        if (ELF_ST_TYPE(ent->info) == STT_SECTION) {
       +                Elfsec *shdr = &elf->secs[ent->shndx];
       +                sym->name = shdr->name;
       +        } else {
       +                sym->name = ent->name;
       +        }
       +
       +        // assert(strlen(sym->name) > 0);
       +        sym->type = typeof(elf, ent, sym->name);
       +        sym->stype = stypeof(ent);
       +        sym->value = ent->value;
       +        sym->size = ent->size;
       +        sym->index = *idx = n;
       +
       +        return sym;
       +}
 (DIR) diff --git a/src/libmach/elf/elfnew.c b/src/libmach/elf/elfnew.c
       @@ -0,0 +1,20 @@
       +#include <stdio.h>
       +#include <stdlib.h>
       +
       +#include <scc/mach.h>
       +#include <scc/elf.h>
       +
       +#include "../libmach.h"
       +#include "fun.h"
       +
       +int
       +elfnew(Obj *obj, int type)
       +{
       +        struct elf *elf;
       +
       +        if ((elf = calloc(1, sizeof(*elf))) == NULL)
       +                return -1;
       +        obj->data = elf;
       +        obj->index = "/";
       +        return 0;
       +}
 (DIR) diff --git a/src/libmach/elf/elfprobe.c b/src/libmach/elf/elfprobe.c
       @@ -0,0 +1,47 @@
       +#include <stdio.h>
       +
       +#include <scc/mach.h>
       +#include <scc/elf/elftypes.h>
       +#include <scc/elf/elfhdr.h>
       +#include <scc/elf.h>
       +
       +#include "../libmach.h"
       +#include "fun.h"
       +
       +int
       +elfprobe(unsigned char *buf, char **name)
       +{
       +        int arch, data, endian;
       +        struct elfhdr32 hdr;
       +        struct arch *ap;
       +
       +        data = buf[EI_DATA];
       +        endian = (data == ELFDATA2LSB) ? LITTLE_ENDIAN : BIG_ENDIAN;
       +        arch = (buf[EI_CLASS] == ELFCLASS32) ? ARCHUNK32 : ARCHUNK64;
       +
       +        unpack(endian,
       +               buf,
       +               "'16sss",
       +               hdr.e_ident,
       +               &hdr.e_type,
       +               &hdr.e_machine,
       +               &hdr.e_version);
       +
       +        if (!IS_ELF(hdr)
       +        ||  buf[EI_VERSION] != EV_CURRENT
       +        ||  hdr.e_version != EV_CURRENT
       +        ||  buf[EI_CLASS] != ELFCLASS32 && buf[EI_CLASS] != ELFCLASS64
       +        ||  (data != ELFDATA2LSB && data != ELFDATA2MSB)) {
       +                return -1;
       +        }
       +
       +        for (ap = elfarchs; ap->name; ap++) {
       +                if (ap->mach == hdr.e_machine &&  ap->endian == data) {
       +                        if (name)
       +                                *name = ap->name;
       +                        return ap->type;
       +                }
       +        }
       +
       +        return OBJ(ELF, arch, endian);
       +}
 (DIR) diff --git a/src/libmach/elf/elfread.c b/src/libmach/elf/elfread.c
       @@ -0,0 +1,761 @@
       +#include <assert.h>
       +#include <errno.h>
       +#include <limits.h>
       +#include <stdio.h>
       +#include <stdlib.h>
       +#include <string.h>
       +
       +#include <scc/mach.h>
       +#include <scc/elf.h>
       +
       +#include <scc/elf/elftypes.h>
       +#include <scc/elf/elfhdr.h>
       +#include <scc/elf/elfphdr.h>
       +#include <scc/elf/elfshdr.h>
       +#include <scc/elf/elfent.h>
       +#include <scc/elf/elfrel.h>
       +
       +#include "../libmach.h"
       +#include "fun.h"
       +
       +struct elfunpack {
       +        void (*hdr)(int, unsigned char *, Elfhdr *);
       +        void (*phdr)(int, unsigned char *, Elfphdr *);
       +        void (*sec)(int, unsigned char *, Elfsec *);
       +        void (*sym)(int, unsigned char *, Elfsym *);
       +        void (*rel)(int, unsigned char *, Elfrel *);
       +        void (*rela)(int, unsigned char *, Elfrel *);
       +
       +        int hdrsiz;
       +        int phdrsiz;
       +        int shentsiz;
       +        int symsiz;
       +        int relsiz;
       +        int relasiz;
       +};
       +
       +struct elfunpack unpack64;
       +struct elfunpack unpack32;
       +
       +static void
       +unpack_hdr64(int order, unsigned char *buf, Elfhdr *hdr)
       +{
       +        Elf64_Ehdr ehdr;
       +        int n;
       +
       +        n = unpack(order,
       +                   buf,
       +                   "'16sslqqqlssssss",
       +                   ehdr.e_ident,
       +                   &ehdr.e_type,
       +                   &ehdr.e_machine,
       +                   &ehdr.e_version,
       +                   &ehdr.e_entry,
       +                   &ehdr.e_phoff,
       +                   &ehdr.e_shoff,
       +                   &ehdr.e_flags,
       +                   &ehdr.e_ehsize,
       +                   &ehdr.e_phentsize,
       +                   &ehdr.e_phnum,
       +                   &ehdr.e_shentsize,
       +                   &ehdr.e_shnum,
       +                   &ehdr.e_shstrndx);
       +
       +        assert(n == ELFH64SZ);
       +
       +        memcpy(hdr->ident, ehdr.e_ident, EI_NIDENT);
       +        hdr->type = ehdr.e_type;
       +        hdr->machine = ehdr.e_machine;
       +        hdr->version = ehdr.e_version;
       +        hdr->entry = ehdr.e_entry;
       +        hdr->phoff = ehdr.e_phoff;
       +        hdr->shoff = ehdr.e_shoff;
       +        hdr->flags = ehdr.e_flags;
       +        hdr->ehsize = ehdr.e_ehsize;
       +        hdr->phentsize = ehdr.e_phentsize;
       +        hdr->phnum = ehdr.e_phnum;
       +        hdr->shentsize = ehdr.e_shentsize;
       +        hdr->shnum = ehdr.e_shnum;
       +        hdr->shstrndx = ehdr.e_shstrndx;
       +}
       +
       +static void
       +unpack_hdr32(int order, unsigned char *buf, Elfhdr *hdr)
       +{
       +        Elf32_Ehdr ehdr;
       +        int n;
       +
       +        n = unpack(order,
       +                   buf,
       +                   "'16sslllllssssss",
       +                   ehdr.e_ident,
       +                   &ehdr.e_type,
       +                   &ehdr.e_machine,
       +                   &ehdr.e_version,
       +                   &ehdr.e_entry,
       +                   &ehdr.e_phoff,
       +                   &ehdr.e_shoff,
       +                   &ehdr.e_flags,
       +                   &ehdr.e_ehsize,
       +                   &ehdr.e_phentsize,
       +                   &ehdr.e_phnum,
       +                   &ehdr.e_shentsize,
       +                   &ehdr.e_shnum,
       +                   &ehdr.e_shstrndx);
       +
       +        assert(n == ELFH32SZ);
       +
       +        memcpy(hdr->ident, ehdr.e_ident, EI_NIDENT);
       +        hdr->type = ehdr.e_type;
       +        hdr->machine = ehdr.e_machine;
       +        hdr->version = ehdr.e_version;
       +        hdr->entry = ehdr.e_entry;
       +        hdr->phoff = ehdr.e_phoff;
       +        hdr->shoff = ehdr.e_shoff;
       +        hdr->flags = ehdr.e_flags;
       +        hdr->ehsize = ehdr.e_ehsize;
       +        hdr->phentsize = ehdr.e_phentsize;
       +        hdr->phnum = ehdr.e_phnum;
       +        hdr->shentsize = ehdr.e_shentsize;
       +        hdr->shnum = ehdr.e_shnum;
       +        hdr->shstrndx = ehdr.e_shstrndx;
       +}
       +
       +static void
       +unpack_phdr64(int order, unsigned char *buf, Elfphdr *hdr)
       +{
       +        int n;
       +        Elf64_Phdr phdr;
       +
       +        n = unpack(order,
       +                   buf,
       +                   "llqqqqqq",
       +                   &phdr.p_type,
       +                   &phdr.p_flags,
       +                   &phdr.p_offset,
       +                   &phdr.p_vaddr,
       +                   &phdr.p_paddr,
       +                   &phdr.p_filesz,
       +                   &phdr.p_memsz,
       +                   &phdr.p_align);
       +
       +        assert(n == ELFP64SZ);
       +
       +        hdr->type = phdr.p_type;
       +        hdr->flags = phdr.p_flags;
       +        hdr->offset = phdr.p_offset;
       +        hdr->vaddr = phdr.p_vaddr;
       +        hdr->paddr = phdr.p_paddr;
       +        hdr->filesz = phdr.p_filesz;
       +        hdr->memsz = phdr.p_memsz;
       +        hdr->align = phdr.p_align;
       +}
       +
       +static void
       +unpack_phdr32(int order, unsigned char *buf, Elfphdr *hdr)
       +{
       +        int n;
       +        Elf32_Phdr phdr;
       +
       +        n = unpack(order,
       +                   buf,
       +                   "llllllll",
       +                   &phdr.p_type,
       +                   &phdr.p_offset,
       +                   &phdr.p_vaddr,
       +                   &phdr.p_paddr,
       +                   &phdr.p_filesz,
       +                   &phdr.p_memsz,
       +                   &phdr.p_flags,
       +                   &phdr.p_align);
       +
       +        assert(n == ELFP32SZ);
       +
       +        hdr->type = phdr.p_type;
       +        hdr->flags = phdr.p_flags;
       +        hdr->offset = phdr.p_offset;
       +        hdr->vaddr = phdr.p_vaddr;
       +        hdr->paddr = phdr.p_paddr;
       +        hdr->filesz = phdr.p_filesz;
       +        hdr->memsz = phdr.p_memsz;
       +        hdr->align = phdr.p_align;
       +}
       +
       +static void
       +unpack_shdr64(int order, unsigned char *buf, Elfsec *sec)
       +{
       +        int n;
       +        Elf64_Shdr shdr;
       +
       +        n = unpack(order,
       +                   buf,
       +                   "llqqqqllqq",
       +                   &shdr.sh_name,
       +                   &shdr.sh_type,
       +                   &shdr.sh_flags,
       +                   &shdr.sh_addr,
       +                   &shdr.sh_offset,
       +                   &shdr.sh_size,
       +                   &shdr.sh_link,
       +                   &shdr.sh_info,
       +                   &shdr.sh_addralign,
       +                   &shdr.sh_entsize);
       +
       +        assert(n == ELFS64SZ);
       +
       +        sec->sh_name = shdr.sh_name;
       +        sec->type = shdr.sh_type;
       +        sec->flags = shdr.sh_flags;
       +        sec->addr = shdr.sh_addr;
       +        sec->offset = shdr.sh_offset;
       +        sec->size = shdr.sh_size;
       +        sec->link = shdr.sh_link;
       +        sec->info = shdr.sh_info;
       +        sec->addralign = shdr.sh_addralign;
       +        sec->entsize = shdr.sh_entsize;
       +}
       +
       +static void
       +unpack_shdr32(int order, unsigned char *buf, Elfsec *sec)
       +{
       +        int n;
       +        Elf32_Shdr shdr;
       +
       +        n = unpack(order,
       +                   buf,
       +                   "llllllllll",
       +                   &shdr.sh_name,
       +                   &shdr.sh_type,
       +                   &shdr.sh_flags,
       +                   &shdr.sh_addr,
       +                   &shdr.sh_offset,
       +                   &shdr.sh_size,
       +                   &shdr.sh_link,
       +                   &shdr.sh_info,
       +                   &shdr.sh_addralign,
       +                   &shdr.sh_entsize);
       +
       +        assert(n == ELFS32SZ);
       +
       +        sec->sh_name = shdr.sh_name;
       +        sec->type = shdr.sh_type;
       +        sec->flags = shdr.sh_flags;
       +        sec->addr = shdr.sh_addr;
       +        sec->offset = shdr.sh_offset;
       +        sec->size = shdr.sh_size;
       +        sec->link = shdr.sh_link;
       +        sec->info = shdr.sh_info;
       +        sec->addralign = shdr.sh_addralign;
       +        sec->entsize = shdr.sh_entsize;
       +}
       +
       +static void
       +unpack_sym64(int order, unsigned char *buf, Elfsym *sym)
       +{
       +        int n;
       +        Elf64_Sym ent;
       +
       +        n = unpack(order,
       +                   buf,
       +                   "lccsqq",
       +                   &ent.st_name,
       +                   &ent.st_info,
       +                   &ent.st_other,
       +                   &ent.st_shndx,
       +                   &ent.st_value,
       +                   &ent.st_size);
       +
       +        assert(n == ELFE64SZ);
       +
       +        sym->st_name = ent.st_name;
       +        sym->info = ent.st_info;
       +        sym->other = ent.st_other;
       +        sym->shndx = ent.st_shndx;
       +        sym->value = ent.st_value;
       +        sym->size = ent.st_size;
       +}
       +
       +static void
       +unpack_sym32(int order, unsigned char *buf, Elfsym *sym)
       +{
       +        int n;
       +        Elf32_Sym ent;
       +
       +        n = unpack(order,
       +                   buf,
       +                   "lllccs",
       +                   &ent.st_name,
       +                   &ent.st_value,
       +                   &ent.st_size,
       +                   &ent.st_info,
       +                   &ent.st_other,
       +                   &ent.st_shndx);
       +
       +        assert(n == ELFE32SZ);
       +
       +        sym->st_name = ent.st_name;
       +        sym->info = ent.st_info;
       +        sym->other = ent.st_other;
       +        sym->shndx = ent.st_shndx;
       +        sym->value = ent.st_value;
       +        sym->size = ent.st_size;
       +}
       +
       +static void
       +unpack_rel64(int order, unsigned char *buf, Elfrel *rp)
       +{
       +        int n;
       +        Elf64_Rel r;
       +
       +        n = unpack(order,
       +                   buf,
       +                   "qq",
       +                   &r.r_offset,
       +                   &r.r_info);
       +
       +        assert(n == ELFR64SZ);
       +
       +        rp->off = r.r_offset;
       +        rp->info = r.r_info;
       +        rp->addend = 0;
       +}
       +
       +static void
       +unpack_rel32(int order, unsigned char *buf, Elfrel *rp)
       +{
       +        int n;
       +        Elf32_Rel r;
       +
       +        n = unpack(order,
       +                   buf,
       +                   "ll",
       +                   &r.r_offset,
       +                   &r.r_info);
       +
       +        assert(n == ELFR32SZ);
       +
       +        rp->off = r.r_offset;
       +        rp->info = r.r_info;
       +        rp->addend = 0;
       +}
       +
       +static void
       +unpack_rela64(int order, unsigned char *buf, Elfrel *rp)
       +{
       +        int n;
       +        Elf64_Rela r;
       +
       +        n = unpack(order,
       +                   buf,
       +                   "qqq",
       +                   &r.r_offset,
       +                   &r.r_info,
       +                   &r.r_addend);
       +
       +        assert(n == ELFRA64SZ);
       +
       +        rp->off = r.r_offset;
       +        rp->info = r.r_info;
       +        rp->addend = r.r_addend;
       +}
       +
       +static void
       +unpack_rela32(int order, unsigned char *buf, Elfrel *rp)
       +{
       +        int n;
       +        Elf32_Rela r;
       +
       +        n = unpack(order,
       +                   buf,
       +                   "lll",
       +                   &r.r_offset,
       +                   &r.r_info,
       +                   &r.r_addend);
       +
       +        assert(n == ELFRA32SZ);
       +
       +        rp->off = r.r_offset;
       +        rp->info = r.r_info;
       +        rp->addend = r.r_addend;
       +}
       +
       +static int
       +readhdr(Obj *obj, FILE *fp)
       +{
       +        Elf *elf = obj->data;
       +        Elfhdr *hdr = &elf->hdr;
       +        Elfunpack *u = elf->unpack;
       +        unsigned char buf[ELFH64SZ];
       +
       +        if (fread(buf, u->hdrsiz, 1, fp) != 1)
       +                return 0;
       +        (*u->hdr)(ORDER(obj->type), buf, hdr);
       +
       +        if (hdr->shnum > INT_MAX ||  hdr->phnum > INT_MAX)
       +                return 0;
       +
       +        switch (hdr->type) {
       +        case ET_REL:
       +        case ET_EXEC:
       +        case ET_DYN:
       +                return 1;
       +        default:
       +                return 0;
       +        }
       +}
       +
       +static int
       +readphdr(Obj *obj, FILE *fp)
       +{
       +        int i, r;
       +        Elfphdr *phdr;
       +        Elf *elf = obj->data;
       +        Elfhdr *hdr = &elf->hdr;
       +        Elfunpack *u = elf->unpack;
       +        unsigned char *buf;
       +
       +        r = 0;
       +        if (hdr->phnum > 0
       +        &&  (hdr->phoff == 0 || hdr->phentsize < u->phdrsiz)) {
       +                errno = ERANGE;
       +                goto err0;
       +        }
       +        if (hdr->phoff == 0 || hdr->phnum == 0)
       +                return 1;
       +
       +        if ((buf = malloc(hdr->phentsize)) == NULL)
       +                goto err0;
       +        if ((phdr = calloc(hdr->phnum, sizeof(*phdr))) == NULL)
       +                goto err1;
       +        elf->phdr = phdr;
       +
       +        if (!objpos(obj, fp, hdr->phoff))
       +                goto err1;
       +
       +        for (i = 0; i < hdr->phnum; i++) {
       +                if (fread(buf, hdr->phentsize, 1, fp) != 1)
       +                        goto err1;
       +                (*u->phdr)(ORDER(obj->type), buf, &phdr[i]);
       +        }
       +        r = 1;
       +
       +err1:
       +        free(buf);
       +err0:
       +        return r;
       +}
       +
       +static int
       +readshdr(Obj *obj, FILE *fp)
       +{
       +        int r, nsec;
       +        Elfsec *sec;
       +        Elf *elf = obj->data;
       +        Elfhdr *hdr = &elf->hdr;
       +        Elfunpack *u = elf->unpack;
       +        unsigned char *buf;
       +
       +        if (hdr->shoff == 0)
       +                return 1;
       +
       +        if (!objpos(obj, fp, hdr->shoff))
       +                return 0;
       +
       +        if (hdr->shnum != SHN_UNDEF) {
       +                if (hdr->shnum > INT_MAX)
       +                        return 0;
       +                nsec = hdr->shnum;
       +        } else {
       +                Elfsec sec0;
       +                fpos_t pos;
       +                unsigned char buf0[ELFS64SZ];
       +
       +                fgetpos(fp, &pos);
       +                fread(buf0, u->shentsiz, 1, fp);
       +                fsetpos(fp, &pos);
       +
       +                if (ferror(fp))
       +                        return 0;
       +
       +                (*u->sec)(ORDER(obj->type), buf0, &sec0);
       +                if (sec0.size > INT_MAX)
       +                        return 0;
       +                nsec = sec0.size;
       +        }
       +
       +        if (nsec == 0)
       +                return 1;
       +
       +        r = 0;
       +        if ((buf = malloc(hdr->shentsize)) == NULL)
       +                return 0;
       +        if ((sec = calloc(nsec, sizeof(*sec))) == NULL)
       +                goto err;
       +        elf->secs = sec;
       +        elf->nsec = nsec;
       +
       +        for ( ; nsec-- > 0; ++sec) {
       +                if (fread(buf, hdr->shentsize, 1, fp) != 1)
       +                        goto err;
       +                (*u->sec)(ORDER(obj->type), buf, sec);
       +        }
       +        r = 1;
       +err:
       +        free(buf);
       +        return r;
       +}
       +
       +static int
       +readstrtbl(Obj *obj, FILE *fp)
       +{
       +        char *s;
       +        int idx;
       +        Elfsec *tbl, *sec;
       +        Elf *elf = obj->data;
       +        Elfhdr *hdr = &elf->hdr;
       +
       +        if (hdr->shstrndx != SHN_XINDEX) {
       +                idx = hdr->shstrndx;
       +        } else {
       +                if (hdr->shnum == 0)
       +                        return 0;
       +                sec = elf->secs;
       +                if (sec->link > INT_MAX)
       +                        return 0;
       +                idx = sec->link;
       +        }
       +        if (idx > elf->nsec || elf->secs[idx].type != SHT_STRTAB)
       +                return 0;
       +        elf->secstrtbl = idx;
       +
       +        for (sec = elf->secs; sec < &elf->secs[elf->nsec]; ++sec) {
       +                if (sec->type != SHT_STRTAB)
       +                        continue;
       +
       +                if (sec->size > SIZE_MAX)
       +                        return 0;
       +                if ((s = malloc(sec->size)) == NULL)
       +                        return 0;
       +                sec->strtbl = s;
       +
       +                if (!objpos(obj, fp, sec->offset))
       +                        return 0;
       +                if (fread(s, sec->size, 1, fp) != 1)
       +                        return 0;
       +        }
       +
       +        return 1;
       +}
       +
       +static int
       +secsize(Elfsec *sec, int onent, int entsiz)
       +{
       +        unsigned long long nent;
       +
       +        if (sec->entsize == 0 || sec->entsize < entsiz)
       +                return -1;
       +        nent = sec->size / sec->entsize;
       +        if (nent > INT_MAX - onent)
       +                return -1;
       +
       +        return nent;
       +}
       +
       +static int
       +readsyms(Obj *obj, Elfsec *sec, FILE *fp)
       +{
       +        int r = 0, n, oldn;
       +        Elfsym *sym;
       +        Elfsec *tbl;
       +        Elf *elf = obj->data;
       +        Elfunpack *u = elf->unpack;
       +        Elfhdr *hdr = &elf->hdr;
       +        unsigned char *buf;
       +
       +        if ((n = secsize(sec, elf->nsym, u->symsiz)) <= 0)
       +                return n;
       +        if ((buf = malloc(sec->entsize)) == NULL)
       +                return 0;
       +
       +        oldn = elf->nsym;
       +        sym = realloc(elf->syms, (oldn + n) * sizeof(Elfsym));
       +        if (!sym)
       +                goto err;
       +        elf->syms = sym;
       +        elf->nsym += n;
       +
       +        if (!objpos(obj, fp, sec->offset))
       +                goto err;
       +
       +        if (sec->link >= hdr->shnum)
       +                goto err;
       +        tbl = &elf->secs[sec->link];
       +        if (tbl->type != SHT_STRTAB)
       +                goto err;
       +
       +        for (sym = &elf->syms[oldn] ; n-- > 0 ; ++sym) {
       +                if (fread(buf, sec->entsize, 1, fp) != 1)
       +                        goto err;
       +                (*u->sym)(ORDER(obj->type), buf, sym);
       +                sym->symsec = sec;
       +                if (sym->st_name >= tbl->size)
       +                        goto err;
       +                sym->name = &tbl->strtbl[sym->st_name];
       +
       +                switch (sym->shndx) {
       +                case SHN_XINDEX:
       +                        /*
       +                         * Elf supports an extension mechanism to allow
       +                         * indexes bigger than 4 bytes. We don't care
       +                         * and we reject elf files using this feature.
       +                         */
       +                        goto err;
       +                case SHN_UNDEF:
       +                case SHN_ABS:
       +                case SHN_COMMON:
       +                        break;
       +                default:
       +                        if (sym->shndx >= elf->nsec)
       +                                goto err;
       +                        break;
       +                }
       +        }
       +        r = 1;
       +
       +err:
       +        free(buf);
       +        return r;
       +}
       +
       +static int
       +readrels(Obj *obj, Elfsec *sec, FILE *fp)
       +{
       +        int r = 0, oldn, n, min;
       +        Elf *elf = obj->data;
       +        Elfunpack *u = elf->unpack;
       +        Elfrel *rp;
       +        void (*fn)(int, unsigned char *, Elfrel *);
       +        unsigned char *buf;
       +
       +        if (sec->type == SHT_RELA) {
       +                fn = u->rela;
       +                min = u->relasiz;
       +        } else {
       +                fn = u->rel;
       +                min = u->relsiz;
       +        }
       +
       +        if (!objpos(obj, fp, sec->offset))
       +                goto err;
       +
       +        if ((n = secsize(sec, elf->nrel, min)) <= 0)
       +                return n;
       +        if ((buf = malloc(sec->entsize)) == NULL)
       +                return 0;
       +
       +        oldn = elf->nrel;
       +        rp = realloc(elf->rels, (oldn + n) * sizeof(Elfrel));
       +        if (!rp)
       +                goto err;
       +        elf->rels = rp;
       +        elf->nrel += n;
       +
       +        for (rp = &elf->rels[oldn]; n-- > 0; ++rp) {
       +                if (fread(buf, sec->entsize, 1, fp) != 1)
       +                        goto err;
       +                (*fn)(ORDER(obj->type), buf, rp);
       +        }
       +        r = 1;
       +
       +err:
       +        free(buf);
       +        return r;
       +}
       +
       +static int
       +procsecs(Obj *obj, FILE *fp)
       +{
       +        Elf *elf = obj->data;
       +        Elfsec *tbl, *sec;
       +
       +        tbl = &elf->secs[elf->secstrtbl];
       +        for (sec = elf->secs; sec < &elf->secs[elf->nsec]; ++sec) {
       +                if (sec->sh_name >= tbl->size)
       +                        return 0;
       +                sec->name = &tbl->strtbl[sec->sh_name];
       +
       +                switch (sec->type) {
       +                case SHT_DYNSYM:
       +                case SHT_SYMTAB:
       +                        if (!readsyms(obj, sec, fp))
       +                                return 0;
       +                        break;
       +                case SHT_RELA:
       +                case SHT_REL:
       +                        if (!readrels(obj, sec, fp))
       +                                return 0;
       +                        break;
       +                }
       +        }
       +
       +        return 1;
       +}
       +
       +int
       +elfread(Obj *obj, FILE *fp)
       +{
       +        fpos_t pos;
       +        Elf *elf = obj->data;
       +        unsigned char buf[EI_CLASS+1];
       +
       +        fgetpos(fp, &pos);
       +        fread(buf, sizeof(buf), 1, fp);
       +        fsetpos(fp, &pos);
       +
       +        elf->unpack = (buf[EI_CLASS] == ELFCLASS64) ? &unpack64 : &unpack32;
       +
       +        if (!readhdr(obj, fp))
       +                return -1;
       +        if (!readphdr(obj, fp))
       +                return -1;
       +        if (!readshdr(obj, fp))
       +                return -1;
       +        if (!readstrtbl(obj, fp))
       +                return -1;
       +        if (!procsecs(obj, fp))
       +                return -1;
       +
       +        return 0;
       +}
       +
       +struct elfunpack unpack64 = {
       +        .hdr = unpack_hdr64,
       +        .phdr = unpack_phdr64,
       +        .sec = unpack_shdr64,
       +        .sym = unpack_sym64,
       +        .rel = unpack_rel64,
       +        .rela = unpack_rela64,
       +
       +        .hdrsiz = ELFH64SZ,
       +        .phdrsiz = ELFP64SZ,
       +        .shentsiz = ELFS64SZ,
       +        .symsiz = ELFE64SZ,
       +        .relsiz = ELFR64SZ,
       +        .relasiz = ELFRA64SZ,
       +};
       +
       +struct elfunpack unpack32 = {
       +        .hdr = unpack_hdr32,
       +        .phdr = unpack_phdr32,
       +        .sec = unpack_shdr32,
       +        .sym = unpack_sym32,
       +        .rel = unpack_rel32,
       +        .rela = unpack_rela32,
       +
       +        .hdrsiz = ELFH32SZ,
       +        .phdrsiz = ELFP32SZ,
       +        .shentsiz = ELFS32SZ,
       +        .symsiz = ELFE32SZ,
       +        .relsiz = ELFR32SZ,
       +        .relasiz = ELFRA32SZ,
       +};
 (DIR) diff --git a/src/libmach/elf/elftype.c b/src/libmach/elf/elftype.c
       @@ -0,0 +1,21 @@
       +#include <stdio.h>
       +#include <string.h>
       +
       +#include <scc/mach.h>
       +#include <scc/elf.h>
       +
       +#include "../libmach.h"
       +#include "fun.h"
       +
       +int
       +elftype(char *name)
       +{
       +        struct arch *ap;
       +
       +        for (ap = elfarchs; ap ->name; ap++) {
       +                if (strcmp(ap->name, name) == 0)
       +                        return ap->type;
       +        }
       +
       +        return -1;
       +}
 (DIR) diff --git a/src/libmach/elf/fun.h b/src/libmach/elf/fun.h
       @@ -0,0 +1,17 @@
       +extern int elfnew(Obj *, int);
       +extern int elfread(Obj *, FILE *);
       +extern int elfsetidx(long, char **, long *, FILE *);
       +extern int elfgetidx(long *, char ***, long **, FILE *);
       +extern int elfpc2line(Obj *, unsigned long long , char *, int *);
       +extern int elfstrip(Obj *);
       +extern void elfdel(Obj *);
       +extern int elfwrite(Obj *, Map *, FILE *);
       +extern int elfprobe(unsigned char *, char **);
       +extern int elftype(char *);
       +
       +extern int elfxsetidx(int long , char *[], long [], FILE *);
       +extern int elfxgetidx(int, long *, char ***, long **, FILE *);
       +
       +extern Symbol *elfgetsym(Obj *, int *, Symbol *);
       +extern Section *elfgetsec(Obj *, int *, Section *);
       +extern Map *elfloadmap(Obj *, FILE *);
 (DIR) diff --git a/src/libmach/elf64/Makefile b/src/libmach/elf64/Makefile
       @@ -1,35 +0,0 @@
       -.POSIX:
       -
       -PROJECTDIR =../../..
       -include $(PROJECTDIR)/scripts/rules.mk
       -
       -OBJS =\
       -        elf64.o\
       -        elf64archs.o\
       -        elf64del.o\
       -        elf64getsec.o\
       -        elf64getsym.o\
       -        elf64new.o\
       -        elf64probe.o\
       -        elf64read.o\
       -        elf64type.o\
       -
       -ELFHDRS =\
       -        $(INCDIR)/bits/scc/elf/elfent.h\
       -        $(INCDIR)/bits/scc/elf/elfhdr.h\
       -        $(INCDIR)/bits/scc/elf/elfphdr.h\
       -        $(INCDIR)/bits/scc/elf/elfshdr.h\
       -        $(INCDIR)/bits/scc/elf/elftypes.h\
       -
       -all: $(OBJS)
       -
       -$(OBJS): $(ELFHDRS)
       -
       -dep:
       -        @(printf 'ELF64OBJS=\\';\
       -        echo;\
       -        echo $(OBJS) |\
       -        sed -E 's@ *([^ ]*)@\telf64/\1\\\n@g') > deps.mk
       -
       -distclean:
       -        rm -f deps.mk
 (DIR) diff --git a/src/libmach/elf64/elf64.c b/src/libmach/elf64/elf64.c
       @@ -1,24 +0,0 @@
       -#include <stdio.h>
       -
       -#include <scc/mach.h>
       -#include <scc/elf64.h>
       -
       -#include "../libmach.h"
       -#include "fun.h"
       -
       -char *
       -elf64str(Obj *obj, int n, long stroff)
       -{
       -        char *tbl;
       -        size_t siz;
       -        struct elf64 *elf;
       -
       -        elf = obj->data;
       -
       -        tbl = elf->strtbl[n];
       -        siz = elf->strsiz[n];
       -
       -        if (!tbl || siz < stroff)
       -                return "";
       -        return &tbl[stroff];
       -}
 (DIR) diff --git a/src/libmach/elf64/elf64archs.c b/src/libmach/elf64/elf64archs.c
       @@ -1,16 +0,0 @@
       -#include <stdio.h>
       -
       -#include <scc/mach.h>
       -#include <scc/elf64.h>
       -
       -#include "../libmach.h"
       -
       -struct arch elf64archs[] = {
       -        {
       -                .name = "elf-amd64",
       -                .mach = EM_X86_64,
       -                .endian = ELFDATA2LSB,
       -                .type = OBJ(ELF64, ARCHAMD64, LITTLE_ENDIAN),
       -        },
       -        NULL,
       -};
 (DIR) diff --git a/src/libmach/elf64/elf64del.c b/src/libmach/elf64/elf64del.c
       @@ -1,24 +0,0 @@
       -#include <stdio.h>
       -#include <stdlib.h>
       -
       -#include <scc/mach.h>
       -#include <scc/elf64.h>
       -
       -#include "../libmach.h"
       -#include "fun.h"
       -
       -void
       -elf64del(Obj *obj)
       -{
       -        struct elf64 *elf = obj->data;
       -
       -        if (elf) {
       -                free(elf->phdr);
       -                free(elf->shdr);
       -                free(elf->syms);
       -                free(elf->strtbl[0]);
       -                free(elf->strtbl[1]);
       -        }
       -        free(obj->data);
       -        obj->data = NULL;
       -}
 (DIR) diff --git a/src/libmach/elf64/elf64getsec.c b/src/libmach/elf64/elf64getsec.c
       @@ -1,76 +0,0 @@
       -#include <stdio.h>
       -
       -#include <scc/mach.h>
       -#include <scc/elf64.h>
       -
       -#include "../libmach.h"
       -#include "fun.h"
       -
       -Section *
       -elf64getsec(Obj *obj, int *idx, Section *sec)
       -{
       -        int stype, n = *idx;
       -        unsigned long flags, type;
       -        unsigned sflags;
       -        Elf64 *elf = obj->data;
       -        Elf_Ehdr *hdr = &elf->hdr;
       -        Elf_Shdr *shdr;
       -
       -        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;
       -        type = shdr->sh_type;
       -
       -        if (flags & SHF_ALLOC) {
       -                if (type == SHT_NOBITS)
       -                        stype = 'B';
       -                else if (flags & SHF_WRITE)
       -                        stype = 'D';
       -                else
       -                        stype = 'T';
       -        } else {
       -                stype = 'N';
       -        }
       -
       -        sflags = 0;
       -        if (flags & SHF_WRITE)
       -                sflags |= SWRITE;
       -        if (flags  & SHF_EXECINSTR)
       -                sflags |= SEXEC;
       -        if (flags & SHF_ALLOC)
       -                sflags |= SLOAD|SREAD;
       -        if (type != SHT_NOBITS)
       -                sflags |= SALLOC;
       -        if (stype == 'T' || stype == 'D')
       -                sflags |= SRELOC;
       -
       -        /*
       -         * We cannot differentiate between load and base address
       -         * in a section, while we can use the physical address
       -         * for that when dealing with segments.
       -         */
       -        if (n == SHN_UNDEF)
       -                sec->name = "*UND*";
       -        else
       -                sec->name = elf64str(obj, SEC_STRTBL, shdr->sh_name);
       -
       -        sec->index = n;
       -        sec->size = shdr->sh_size;
       -        sec->base = shdr->sh_addr;
       -        sec->load = shdr->sh_addr;
       -        sec->offset = shdr->sh_offset;
       -        sec->type = stype;
       -        sec->flags = sflags;
       -        sec->align = shdr->sh_addralign;
       -
       -        return sec;
       -}
 (DIR) diff --git a/src/libmach/elf64/elf64getsym.c b/src/libmach/elf64/elf64getsym.c
       @@ -1,112 +0,0 @@
       -#include <ctype.h>
       -#include <stdio.h>
       -#include <stdlib.h>
       -#include <string.h>
       -
       -#include <scc/mach.h>
       -#include <scc/elf64.h>
       -
       -#include "../libmach.h"
       -#include "fun.h"
       -
       -static int
       -typeof(Elf64 *elf, Elf_Sym *ent, char *name)
       -{
       -        int c, bind;
       -        unsigned long flags, type;
       -        Elf_Shdr *shdr;
       -
       -        switch (ent->st_shndx) {
       -        case SHN_UNDEF:
       -                c = 'U';
       -                break;
       -        case SHN_ABS:
       -                c = 'a';
       -                break;
       -        case SHN_COMMON:
       -                c = 'C';
       -                break;
       -        case SHN_XINDEX:
       -                abort();
       -        default:
       -                shdr = &elf->shdr[ent->st_shndx];
       -                flags = shdr->sh_flags;
       -                type = shdr->sh_type;
       -
       -                if (flags & SHF_ALLOC) {
       -                        if (type == SHT_NOBITS)
       -                                c = 'b';
       -                        else if (flags & SHF_WRITE)
       -                                c = 'd';
       -                        else if (flags & SHF_EXECINSTR)
       -                                c = 't';
       -                        else
       -                                c = 'r';
       -                } else if (strncmp(name, ".debug", 6) == 0) {
       -                        c = 'N';
       -                } else if (strcmp(name, ".comment") == 0) {
       -                        c = 'N';
       -                } else if (strcmp(name, ".line") == 0) {
       -                        c = 'N';
       -                } else if (strcmp(name, ".stab") == 0) {
       -                        c = 'N';
       -                } else {
       -                        c = '?';
       -                }
       -        }
       -
       -        if (ELF_ST_BIND(ent->st_info) != STB_LOCAL)
       -                c = toupper(c);
       -
       -        return c;
       -}
       -
       -static int
       -stypeof(Elf_Sym *ent)
       -{
       -        switch (ELF_ST_TYPE(ent->st_info)) {
       -        case STT_OBJECT:
       -                return SYMOBJECT;
       -        case STT_FUNC:
       -                return SYMFUNC;
       -        case STT_SECTION:
       -                return SYMSECTION;
       -        case STT_FILE:
       -                return SYMFILE;
       -        case STT_COMMON:
       -                return SYMCOMMON;
       -        default:
       -        case STT_NOTYPE:
       -                return SYMNOTYPE;
       -        }
       -}
       -
       -Symbol *
       -elf64getsym(Obj *obj, int *idx, Symbol *sym)
       -{
       -        int n = *idx;
       -        Elf_Sym *ent;
       -        Elf64 *elf = obj->data;
       -
       -        if (n == 0)
       -                n++;
       -
       -        if (!elf->symtab || n >= elf->nsym)
       -                return NULL;
       -        ent = &elf->syms[n];
       -
       -        if (ELF_ST_TYPE(ent->st_info) == STT_SECTION) {
       -                Elf_Shdr *shdr = &elf->shdr[ent->st_shndx];
       -                sym->name = elf64str(obj, SEC_STRTBL, shdr->sh_name);
       -        } else {
       -                sym->name = elf64str(obj, SYM_STRTBL, ent->st_name);
       -        }
       -
       -        sym->type = typeof(elf, ent, sym->name);
       -        sym->stype = stypeof(ent);
       -        sym->value = ent->st_value;
       -        sym->size = ent->st_size;
       -        sym->index = *idx = n;
       -
       -        return sym;
       -}
 (DIR) diff --git a/src/libmach/elf64/elf64new.c b/src/libmach/elf64/elf64new.c
       @@ -1,20 +0,0 @@
       -#include <stdio.h>
       -#include <stdlib.h>
       -
       -#include <scc/mach.h>
       -#include <scc/elf64.h>
       -
       -#include "../libmach.h"
       -#include "fun.h"
       -
       -int
       -elf64new(Obj *obj, int type)
       -{
       -        struct elf64 *elf;
       -
       -        if ((elf = calloc(1, sizeof(*elf))) == NULL)
       -                return -1;
       -        obj->data = elf;
       -        obj->index = "/";
       -        return 0;
       -}
 (DIR) diff --git a/src/libmach/elf64/elf64probe.c b/src/libmach/elf64/elf64probe.c
       @@ -1,45 +0,0 @@
       -#include <stdio.h>
       -
       -#include <scc/mach.h>
       -#include <scc/elf64.h>
       -
       -#include "../libmach.h"
       -#include "fun.h"
       -
       -int
       -elf64probe(unsigned char *buf, char **name)
       -{
       -        int endian;
       -        Elf_Ehdr hdr;
       -        struct arch *ap;
       -
       -        unpack(buf[EI_DATA] == ELFDATA2LSB ? LITTLE_ENDIAN : BIG_ENDIAN,
       -               buf,
       -               "'16sss",
       -               hdr.e_ident,
       -               &hdr.e_type,
       -               &hdr.e_machine,
       -               &hdr.e_version);
       -
       -        if (!IS_ELF(hdr)
       -        ||  buf[EI_CLASS] != ELFCLASS64
       -        ||  buf[EI_DATA] == ELFDATANONE
       -        ||  buf[EI_VERSION] != EV_CURRENT
       -        ||  (buf[EI_DATA] != ELFDATA2LSB && buf[EI_DATA] != ELFDATA2MSB)) {
       -                return -1;
       -        }
       -
       -        if (hdr.e_version != EV_CURRENT)
       -                return -1;
       -
       -        endian = hdr.e_ident[EI_DATA];
       -        for (ap = elf64archs; ap->name; ap++) {
       -                if (ap->mach == hdr.e_machine &&  ap->endian == endian) {
       -                        if (name)
       -                                *name = ap->name;
       -                        return ap->type;
       -                }
       -        }
       -
       -        return -1;
       -}
 (DIR) diff --git a/src/libmach/elf64/elf64read.c b/src/libmach/elf64/elf64read.c
       @@ -1,386 +0,0 @@
       -#include <assert.h>
       -#include <stdio.h>
       -#include <stdlib.h>
       -
       -#include <scc/mach.h>
       -#include <scc/elf64.h>
       -
       -#include "../libmach.h"
       -#include "fun.h"
       -
       -static int
       -unpack_hdr(int order, unsigned char *buf, Elf_Ehdr *hdr)
       -{
       -        int n;
       -
       -        n = unpack(order,
       -                   buf,
       -                   "'16sslqqqlssssss",
       -                   hdr->e_ident,
       -                   &hdr->e_type,
       -                   &hdr->e_machine,
       -                   &hdr->e_version,
       -                   &hdr->e_entry,
       -                   &hdr->e_phoff,
       -                   &hdr->e_shoff,
       -                   &hdr->e_flags,
       -                   &hdr->e_ehsize,
       -                   &hdr->e_phentsize,
       -                   &hdr->e_phnum,
       -                   &hdr->e_shentsize,
       -                   &hdr->e_shnum,
       -                   &hdr->e_shstrndx);
       -
       -        assert(n == ELFHSZ);
       -
       -        return n;
       -}
       -
       -static int
       -unpack_phdr(int order, unsigned char *buf, Elf_Phdr *phdr)
       -{
       -        int n;
       -
       -        n = unpack(order,
       -                   buf,
       -                   "llqqqqqq",
       -                   &phdr->p_type,
       -                   &phdr->p_flags,
       -                   &phdr->p_offset,
       -                   &phdr->p_vaddr,
       -                   &phdr->p_paddr,
       -                   &phdr->p_filesz,
       -                   &phdr->p_memsz,
       -                   &phdr->p_align);
       -
       -        assert(n == ELFPSZ);
       -
       -        return n;
       -}
       -
       -static int
       -unpack_shdr(int order, unsigned char *buf, Elf_Shdr *shdr)
       -{
       -        int n;
       -
       -        n = unpack(order,
       -                   buf,
       -                   "llqqqqllqq",
       -                   &shdr->sh_name,
       -                   &shdr->sh_type,
       -                   &shdr->sh_flags,
       -                   &shdr->sh_addr,
       -                   &shdr->sh_offset,
       -                   &shdr->sh_size,
       -                   &shdr->sh_link,
       -                   &shdr->sh_info,
       -                   &shdr->sh_addralign,
       -                   &shdr->sh_entsize);
       -
       -        assert(n == ELFSSZ);
       -
       -        return n;
       -}
       -
       -static int
       -unpack_sym(int order, unsigned char *buf, Elf_Sym *sym)
       -{
       -        int n;
       -
       -        n = unpack(order,
       -                   buf,
       -                   "lccsqq",
       -                   &sym->st_name,
       -                   &sym->st_info,
       -                   &sym->st_other,
       -                   &sym->st_shndx,
       -                   &sym->st_value,
       -                   &sym->st_size);
       -        assert(n == ELFESZ);
       -
       -        return n;
       -}
       -
       -static int
       -readhdr(Obj *obj, FILE *fp)
       -{
       -        Elf64 *elf;
       -        Elf_Ehdr *hdr;
       -        unsigned char buf[ELFHSZ];
       -
       -        elf = obj->data;
       -        hdr = &elf->hdr;
       -
       -        if (fread(buf, ELFHSZ, 1, fp) != 1)
       -                return 0;
       -        unpack_hdr(ORDER(obj->type), buf, hdr);
       -
       -        switch (hdr->e_type) {
       -        case ET_REL:
       -        case ET_EXEC:
       -        case ET_DYN:
       -                return 1;
       -        default:
       -                return 0;
       -        }
       -}
       -
       -static int
       -readphdr(Obj *obj, FILE *fp)
       -{
       -        long long i;
       -        Elf_Ehdr *hdr;
       -        Elf_Phdr *phdr;
       -        Elf64 *elf;
       -        unsigned char buf[ELFPSZ];
       -
       -        elf = obj->data;
       -        hdr = &elf->hdr;
       -
       -        if (hdr->e_phoff == 0 || hdr->e_phnum == 0)
       -                return 1;
       -
       -        phdr = calloc(hdr->e_phnum, sizeof(*phdr));
       -        if (!phdr)
       -                return 0;
       -        elf->phdr = phdr;
       -
       -        if (!objpos(obj, fp, hdr->e_phoff))
       -                return 0;
       -        for (i = 0; i < hdr->e_phnum; i++) {
       -                if (fread(buf, ELFPSZ, 1, fp) != 1)
       -                        return 0;
       -                unpack_phdr(ORDER(obj->type), buf, &phdr[i]);
       -        }
       -
       -        return 1;
       -}
       -
       -static int
       -readshdr(Obj *obj, FILE *fp)
       -{
       -        unsigned long long i, nsec;
       -        Elf_Ehdr *hdr;
       -        Elf_Shdr *shdr;
       -        Elf64 *elf;
       -        unsigned char buf[ELFSSZ + ELFHSZ];
       -
       -        elf = obj->data;
       -        hdr = &elf->hdr;
       -        elf->nsec = 0;
       -        elf->shdr = NULL;
       -
       -        if (hdr->e_shoff == 0)
       -                return 1;
       -
       -        if (!objpos(obj, fp, hdr->e_shoff))
       -                return 0;
       -
       -        if (hdr->e_shnum != SHN_UNDEF) {
       -                nsec = hdr->e_shnum;
       -        } else {
       -                Elf_Shdr sec0;
       -                fpos_t pos;
       -
       -                fgetpos(fp, &pos);
       -                fread(buf, ELFHSZ, 1, fp);
       -                fsetpos(fp, &pos);
       -
       -                if (ferror(fp))
       -                        return 0;
       -
       -                unpack_shdr(ORDER(obj->type), buf, &sec0);
       -                nsec = sec0.sh_size;
       -        }
       -
       -        if (nsec > SIZE_MAX)
       -                return 0;
       -        if (nsec == 0)
       -                return 1;
       -
       -        shdr = calloc(nsec, sizeof(*shdr));
       -        if (!shdr)
       -                return 0;
       -        elf->shdr = shdr;
       -        elf->nsec = nsec;
       -
       -        for (i = 0; i < nsec; i++) {
       -                if (fread(buf, ELFSSZ, 1, fp) != 1)
       -                        return 0;
       -                unpack_shdr(ORDER(obj->type), buf, &shdr[i]);
       -                if (shdr[i].sh_type == SHT_SYMTAB) {
       -                        /*
       -                         * elf supports multiple symbol table, but we don't
       -                         * care and we only support one, and we reject elf
       -                         * files with more of one symbol table.
       -                         */
       -                        if (elf->symtab)
       -                                return 0;
       -                        elf->symtab = &shdr[i];
       -                }
       -        }
       -
       -        return 1;
       -}
       -
       -static int
       -readsecstr(Obj *obj, FILE *fp)
       -{
       -        long idx;
       -        size_t siz;
       -        char *str;
       -        Elf_Shdr *shdr;
       -        Elf64 *elf;
       -        Elf_Ehdr *hdr;
       -
       -        elf = obj->data;
       -        hdr = &elf->hdr;
       -        idx = hdr->e_shstrndx;
       -        if (idx == SHN_UNDEF)
       -                return 0;
       -        if (idx == SHN_XINDEX) {
       -                if (hdr->e_shnum == 0)
       -                        return 0;
       -                idx = elf->shdr[0].sh_link;
       -        }
       -
       -        if (idx >= hdr->e_shnum)
       -                return 0;
       -        shdr = &elf->shdr[idx];
       -
       -        if (shdr->sh_size > SIZE_MAX)
       -                return 0;
       -
       -        siz = shdr->sh_size;
       -        if (siz == 0)
       -                return 1;
       -        str = malloc(siz);
       -        if (!str)
       -                return 0;
       -
       -        elf->strtbl[SEC_STRTBL] = str;
       -        elf->strsiz[SEC_STRTBL] = siz;
       -
       -        if (!objpos(obj, fp, shdr->sh_offset))
       -                return 0;
       -        if (fread(str, siz, 1, fp) != 1)
       -                return 0;
       -
       -        return 1;
       -}
       -
       -static int
       -readsymstr(Obj *obj, FILE *fp)
       -{
       -        long idx;
       -        size_t siz;
       -        char *str;
       -        Elf64 *elf;
       -        Elf_Shdr *shdr;
       -
       -        elf = obj->data;
       -        if (!elf->symtab)
       -                return 1;
       -
       -        idx = elf->symtab->sh_link;
       -        if (idx >= elf->nsec)
       -                return 0;
       -        shdr = &elf->shdr[idx];
       -
       -        if (shdr->sh_size > SIZE_MAX)
       -                return 0;
       -
       -        siz = shdr->sh_size;
       -        if (siz == 0)
       -                return 1;
       -        str = malloc(siz);
       -        if (!str)
       -                return 0;
       -
       -        elf->strtbl[SYM_STRTBL] = str;
       -        elf->strsiz[SYM_STRTBL] = siz;
       -
       -        if (!objpos(obj, fp, shdr->sh_offset))
       -                return 0;
       -        if (fread(str, siz, 1, fp) != 1)
       -                return 0;
       -
       -        return 1;
       -}
       -
       -static int
       -readsym(Obj *obj, FILE *fp)
       -{
       -        long nsym, i;
       -        int sec;
       -        Elf64 *elf;
       -        Elf_Sym *syms;
       -        Elf_Shdr *shdr;
       -        unsigned char buf[ELFSSZ];
       -
       -        elf = obj->data;
       -        if (!elf->symtab)
       -                return 1;
       -        shdr = elf->symtab;
       -
       -        assert(shdr->sh_type == SHT_SYMTAB);
       -
       -        nsym = shdr->sh_size / shdr->sh_entsize;
       -        if (nsym >= SIZE_MAX)
       -                return 0;
       -
       -        syms = calloc(nsym, sizeof(*syms));
       -        if (!syms)
       -                return 0;
       -        elf->syms = syms;
       -        elf->nsym = nsym;
       -
       -        if (!objpos(obj, fp, shdr->sh_offset))
       -                return 0;
       -
       -        for (i = 0; i < nsym; i++) {
       -                if (fread(buf, ELFESZ, 1, fp) != 1)
       -                        return 0;
       -                unpack_sym(ORDER(obj->type), buf, &syms[i]);
       -
       -                sec = syms[i].st_shndx;
       -                switch (sec) {
       -                case SHN_XINDEX:
       -                        /*
       -                         * Elf supports an extension mechanism to allow
       -                         * indexes bigger than 4 bytes. We don't care
       -                         * and we reject elf files using this feature.
       -                         */
       -                        return 0;
       -                case SHN_UNDEF:
       -                case SHN_ABS:
       -                case SHN_COMMON:
       -                        break;
       -                default:
       -                        if (sec >= elf->nsec)
       -                                return 0;
       -                        break;
       -                }
       -        }
       -
       -        return 1;
       -}
       -
       -int
       -elf64read(Obj *obj, FILE *fp)
       -{
       -        if (!readhdr(obj, fp))
       -                return -1;
       -        if (!readphdr(obj, fp))
       -                return -1;
       -        if (!readshdr(obj, fp))
       -                return -1;
       -        if (!readsym(obj, fp))
       -                return -1;
       -        if (!readsecstr(obj, fp))
       -                return -1;
       -        if (!readsymstr(obj, fp))
       -                return -1;
       -
       -        return 0;
       -}
 (DIR) diff --git a/src/libmach/elf64/elf64type.c b/src/libmach/elf64/elf64type.c
       @@ -1,21 +0,0 @@
       -#include <stdio.h>
       -#include <string.h>
       -
       -#include <scc/mach.h>
       -#include <scc/elf64.h>
       -
       -#include "../libmach.h"
       -#include "fun.h"
       -
       -int
       -elf64type(char *name)
       -{
       -        struct arch *ap;
       -
       -        for (ap = elf64archs; ap ->name; ap++) {
       -                if (strcmp(ap->name, name) == 0)
       -                        return ap->type;
       -        }
       -
       -        return -1;
       -}
 (DIR) diff --git a/src/libmach/elf64/fun.h b/src/libmach/elf64/fun.h
       @@ -1,17 +0,0 @@
       -extern int elf64new(Obj *, int);
       -extern int elf64read(Obj *, FILE *);
       -extern int elf64setidx(long, char **, long *, FILE *);
       -extern int elf64getidx(long *, char ***, long **, FILE *);
       -extern int elf64pc2line(Obj *, unsigned long long , char *, int *);
       -extern int elf64strip(Obj *);
       -extern void elf64del(Obj *);
       -extern int elf64write(Obj *, Map *, FILE *);
       -extern int elf64probe(unsigned char *, char **);
       -extern int elf64type(char *);
       -
       -extern int elf64xsetidx(int long , char *[], long [], FILE *);
       -extern int elf64xgetidx(int, long *, char ***, long **, FILE *);
       -
       -extern Symbol *elf64getsym(Obj *, int *, Symbol *);
       -extern Section *elf64getsec(Obj *, int *, Section *);
       -extern Map *elf64loadmap(Obj *, FILE *);
 (DIR) diff --git a/src/libmach/getindex.c b/src/libmach/getindex.c
       @@ -5,7 +5,7 @@
        
        #include "libmach.h"
        
       -#include "elf64/fun.h"
       +#include "elf/fun.h"
        #include "coff32/fun.h"
        
        static int (*ops[NFORMATS])(long *, char ***, long **, FILE *) = {
 (DIR) diff --git a/src/libmach/getsec.c b/src/libmach/getsec.c
       @@ -4,12 +4,12 @@
        
        #include "libmach.h"
        
       -#include "elf64/fun.h"
       +#include "elf/fun.h"
        #include "coff32/fun.h"
        
        static Section *(*ops[NFORMATS])(Obj *, int *, Section *) = {
                [COFF32] = coff32getsec,
       -        [ELF64] = elf64getsec,
       +        [ELF] = elfgetsec,
        };
        
        Section *
 (DIR) diff --git a/src/libmach/getsym.c b/src/libmach/getsym.c
       @@ -4,12 +4,12 @@
        
        #include "libmach.h"
        
       -#include "elf64/fun.h"
       +#include "elf/fun.h"
        #include "coff32/fun.h"
        
        static Symbol *(*ops[NFORMATS])(Obj *, int *, Symbol *) = {
                [COFF32] = coff32getsym,
       -        [ELF64] = elf64getsym,
       +        [ELF] = elfgetsym,
        };
        
        Symbol *
 (DIR) diff --git a/src/libmach/loadmap.c b/src/libmach/loadmap.c
       @@ -4,7 +4,7 @@
        
        #include "libmach.h"
        
       -#include "elf64/fun.h"
       +#include "elf/fun.h"
        #include "coff32/fun.h"
        
        static Map *(*ops[NFORMATS])(Obj *, FILE *) = {
 (DIR) diff --git a/src/libmach/newobj.c b/src/libmach/newobj.c
       @@ -7,12 +7,12 @@
        
        #include "libmach.h"
        
       -#include "elf64/fun.h"
       +#include "elf/fun.h"
        #include "coff32/fun.h"
        
        static int (*ops[NFORMATS])(Obj *, int) = {
                [COFF32] = coff32new,
       -        [ELF64] = elf64new,
       +        [ELF] = elfnew,
        };
        
        Obj *
 (DIR) diff --git a/src/libmach/objprobe.c b/src/libmach/objprobe.c
       @@ -4,12 +4,12 @@
        
        #include "libmach.h"
        
       -#include "elf64/fun.h"
       +#include "elf/fun.h"
        #include "coff32/fun.h"
        
        static int (*ops[NFORMATS])(unsigned char *, char **) = {
                [COFF32] = coff32probe,
       -        [ELF64] = elf64probe,
       +        [ELF] = elfprobe,
        };
        
        int
 (DIR) diff --git a/src/libmach/objtype.c b/src/libmach/objtype.c
       @@ -4,12 +4,12 @@
        
        #include "libmach.h"
        
       -#include "elf64/fun.h"
       +#include "elf/fun.h"
        #include "coff32/fun.h"
        
        static int (*ops[NFORMATS])(char *) = {
                [COFF32] = coff32type,
       -        [ELF64] = elf64type,
       +        [ELF] = elftype,
        };
        
        int
 (DIR) diff --git a/src/libmach/pc2line.c b/src/libmach/pc2line.c
       @@ -4,7 +4,7 @@
        
        #include "libmach.h"
        
       -#include "elf64/fun.h"
       +#include "elf/fun.h"
        #include "coff32/fun.h"
        
        static int (*ops[NFORMATS])(Obj *, unsigned long long , char *, int *) = {
 (DIR) diff --git a/src/libmach/readobj.c b/src/libmach/readobj.c
       @@ -4,12 +4,12 @@
        
        #include "libmach.h"
        
       -#include "elf64/fun.h"
       +#include "elf/fun.h"
        #include "coff32/fun.h"
        
        static int (*ops[NFORMATS])(Obj *, FILE *) = {
                [COFF32] = coff32read,
       -        [ELF64] = elf64read,
       +        [ELF] = elfread,
        };
        
        int
 (DIR) diff --git a/src/libmach/setindex.c b/src/libmach/setindex.c
       @@ -5,7 +5,7 @@
        
        #include "libmach.h"
        
       -#include "elf64/fun.h"
       +#include "elf/fun.h"
        #include "coff32/fun.h"
        
        static int (*ops[NFORMATS])(long, char **, long *, FILE *) = {
 (DIR) diff --git a/src/libmach/setsec.c b/src/libmach/setsec.c
       @@ -4,7 +4,7 @@
        
        #include "libmach.h"
        
       -#include "elf64/fun.h"
       +#include "elf/fun.h"
        #include "coff32/fun.h"
        
        static Section *(*ops[NFORMATS])(Obj *, int *, Section *) = {
 (DIR) diff --git a/src/libmach/setsym.c b/src/libmach/setsym.c
       @@ -4,7 +4,7 @@
        
        #include "libmach.h"
        
       -#include "elf64/fun.h"
       +#include "elf/fun.h"
        #include "coff32/fun.h"
        
        static Symbol *(*ops[NFORMATS])(Obj *, int *, Symbol *) = {
 (DIR) diff --git a/src/libmach/strip.c b/src/libmach/strip.c
       @@ -4,7 +4,7 @@
        
        #include "libmach.h"
        
       -#include "elf64/fun.h"
       +#include "elf/fun.h"
        #include "coff32/fun.h"
        
        static int (*ops[NFORMATS])(Obj *) = {
 (DIR) diff --git a/src/libmach/writeobj.c b/src/libmach/writeobj.c
       @@ -4,7 +4,7 @@
        
        #include "libmach.h"
        
       -#include "elf64/fun.h"
       +#include "elf/fun.h"
        #include "coff32/fun.h"
        
        static int (*ops[NFORMATS])(Obj *, Map *, FILE *) = {