Logo  

CS471/571 - Operating Systems

Displaying exercises/e7/solution/elf.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <elf.h>

void *mapfile(char *filename)
{
  struct stat st;
  
  int fd = open(filename, O_RDONLY);
  if (fstat(fd, &st) < 0) {
    perror("fstat");
    return NULL;
  }
  void *mem = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
  if (mem == MAP_FAILED) {
    perror("mmap");
    return NULL;
  }
  return mem;
}

void header(Elf64_Ehdr *hdr)
{
  printf("ELF Header:\n");

  printf("  Magic:   ");
  for(int i = 0; i < EI_NIDENT; i++) printf("%02x ", hdr->e_ident[i]);
  printf("\n");

  printf("  Class:                             ");
  switch(hdr->e_ident[EI_CLASS]) {
    case ELFCLASSNONE: printf("NONE\n"); break;
    case ELFCLASS32:   printf("ELF32\n"); break;
    case ELFCLASS64:   printf("ELF64\n"); break;
  }

  printf("  Data:                              ");
  switch(hdr->e_ident[EI_DATA]) {
    case ELFDATANONE: printf("Unknown data format.\n"); break;
    case ELFDATA2LSB: printf("2's complement, little-endian\n"); break;
    case ELFDATA2MSB: printf("2's complement, big-endian\n"); break;
  }

  printf("  Version:                           %d", hdr->e_ident[EI_VERSION]);
  switch(hdr->e_ident[EI_VERSION]) {
    case EV_NONE:    printf("(invalid)\n"); break;
    case EV_CURRENT: printf("(current)\n"); break;
  }

  printf("  OS/ABI:                            ");
  switch(hdr->e_ident[EI_OSABI]) {
    case ELFOSABI_SYSV:       printf("UNIX - System V\n"); break;
    case ELFOSABI_HPUX:       printf("HP-UX\n");  break;
    case ELFOSABI_NETBSD:     printf("NetBSD\n"); break;
    case ELFOSABI_LINUX:      printf("Linux\n");  break;
    case ELFOSABI_SOLARIS:    printf("Solaris\n");break;
    case ELFOSABI_IRIX:       printf("IRIX\n");   break;
    case ELFOSABI_FREEBSD:    printf("FreeBSD\n");break;
    case ELFOSABI_TRU64:      printf("TRU64 UNIX\n");break;
    case ELFOSABI_ARM:        printf("ARM architecture\n");break;
    case ELFOSABI_STANDALONE: printf("Stand-alone (embedded)\n");break;
  }
  printf("  ABI Version:                       %d\n", hdr->e_ident[EI_ABIVERSION]);

  printf("  Type:                              ");
  switch(hdr->e_type) {
    case ET_NONE: printf("NONE (Unknown type)\n"); break;
    case ET_REL : printf("REL (Relocatable file)\n"); break;
    case ET_EXEC: printf("EXEC (Executable file)\n"); break;
    case ET_DYN : printf("DYN (Shared object)\n"); break;
    case ET_CORE: printf("CORE (Core file)\n"); break;
  }

  printf("  Machine:                           ");
  switch(hdr->e_machine) {
    case EM_NONE       : printf("An unknown machine\n"); break;
    case EM_M32        : printf("AT&T WE 32100\n"); break;
    case EM_SPARC      : printf("Sun Microsystems SPARC\n"); break;
    case EM_386        : printf("Intel 80386\n"); break;
    case EM_68K        : printf("Motorola 68000\n"); break;
    case EM_88K        : printf("Motorola 88000\n"); break;
    case EM_860        : printf("Intel 80860\n"); break;
    case EM_MIPS       : printf("MIPS RS3000 (big-endian only)\n"); break;
    case EM_PARISC     : printf("HP/PA\n"); break;
    case EM_SPARC32PLUS: printf("SPARC with enhanced instruction set\n"); break;
    case EM_PPC        : printf("PowerPC\n"); break;
    case EM_PPC64      : printf("PowerPC 64-bit\n"); break;
    case EM_S390       : printf("IBM S/390\n"); break;
    case EM_ARM        : printf("Advanced RISC Machines\n"); break;
    case EM_SH         : printf("Renesas SuperH\n"); break;
    case EM_SPARCV9    : printf("SPARC v9 64-bit\n"); break;
    case EM_IA_64      : printf("Intel Itanium\n"); break;
    case EM_X86_64     : printf("Advanced Micro Devices X86-64\n"); break;
    case EM_VAX        : printf("DEC Vax\n"); break;
  }

  printf("  Version:                           0x%x\n", hdr->e_version);
  printf("  Entry point address:               0x%x\n", hdr->e_entry);
  printf("  Start of program headers:          %d (bytes into file)\n", hdr->e_phoff);
  printf("  Start of section headers:          %d (bytes into file)\n", hdr->e_shoff);
  printf("  Flags:                             0x%x\n", hdr->e_flags);
  printf("  Size of this header:               %d (bytes)\n", hdr->e_ehsize);
  printf("  Size of program headers:           %d (bytes)\n", hdr->e_phentsize);
  printf("  Number of program headers:         %d\n", hdr->e_phnum);
  printf("  Size of section headers:           %d (bytes)\n", hdr->e_shentsize);
  printf("  Number of section headers:         %d\n", hdr->e_shnum);
  printf("  Section header string table index: %d\n", hdr->e_shstrndx);
}


int main(int argc, char *argv[])
{
  if (argc < 2) {
    printf("Usage: elf <elf-file>\n");
    return 0;
  }

  void *memory = mapfile(argv[1]);
  if (memory == NULL) return 0;

  header(memory);

  return 0;
}