/*
 * Print the ELF Program Header Table in an ELF object.
 *
 * $Id: prog3.txt 2133 2011-11-10 08:28:22Z jkoshy $
 */

#include <err.h>
#include <fcntl.h>
#include <gelf.h> @\co{1}@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <vis.h>

void
print_ptype(size_t pt) @\co{7}@
{
    char *s;

#define C(V) case PT_##V: s = #V; break
    switch (pt) {
        C(NULL);        C(LOAD);        C(DYNAMIC);
        C(INTERP);      C(NOTE);        C(SHLIB);
        C(PHDR);        C(TLS);         C(SUNW_UNWIND);
        C(SUNWBSS);     C(SUNWSTACK);   C(SUNWDTRACE);
        C(SUNWCAP);
    default:
        s = "unknown";
        break;
    }
    (void) printf(" \"%s\"", s);
#undef  C
}

int
main(int argc, char **argv)
{
    int i, fd;
    Elf *e;
    char *id, bytes[5];
    size_t n;
    GElf_Phdr phdr; @\co{2}@

    if (argc != 2)
        errx(EXIT_FAILURE, "usage: %s file-name", argv[0]);

    if (elf_version(EV_CURRENT) == EV_NONE)
        errx(EXIT_FAILURE, "ELF library initialization "
            "failed: %s", elf_errmsg(-1));

    if ((fd = open(argv[1], O_RDONLY, 0)) < 0)
        err(EXIT_FAILURE, "open \"%s\" failed", argv[1]);

    if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
        errx(EXIT_FAILURE, "elf_begin() failed: %s.",
            elf_errmsg(-1));

    if (elf_kind(e) != ELF_K_ELF)
        errx(EXIT_FAILURE, "\"%s\" is not an ELF object.",
            argv[1]);

    if (elf_getphdrnum(e, &n) != 0) @\co{3}@
        errx(EXIT_FAILURE, "elf_getphdrnum() failed: %s.",
            elf_errmsg(-1));

    for (i = 0; i < n; i++) { @\co{4}@
        if (gelf_getphdr(e, i, &phdr) != &phdr) @\co{5}@
            errx(EXIT_FAILURE, "getphdr() failed: %s.",
                elf_errmsg(-1));

        (void) printf("PHDR %d:\n", i);
#define        PRINT_FMT        "    %-20s 0x%jx"
#define        PRINT_FIELD(N) do { \
        (void) printf(PRINT_FMT, #N, (uintmax_t) phdr.N); \
    } while (0)
#define         NL() do { (void) printf("\n"); } while (0)
        PRINT_FIELD(p_type); @\co{6}@
        print_ptype(phdr.p_type);       NL();
        PRINT_FIELD(p_offset);          NL();
        PRINT_FIELD(p_vaddr);           NL();
        PRINT_FIELD(p_paddr);           NL();
        PRINT_FIELD(p_filesz);          NL();
        PRINT_FIELD(p_memsz);           NL();
        PRINT_FIELD(p_flags);
        (void) printf(" [");
        if (phdr.p_flags & PF_X)
            (void) printf(" execute");
        if (phdr.p_flags & PF_R)
            (void) printf(" read");
        if (phdr.p_flags & PF_W)
            (void) printf(" write");
        printf(" ]");                   NL();
        PRINT_FIELD(p_align);           NL();
    }

    (void) elf_end(e);
    (void) close(fd);
    exit(EXIT_SUCCESS);
}


