1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 #include <stdlib.h>
  30 #include <fcntl.h>
  31 #include <strings.h>
  32 #include <stdio.h>
  33 #include <errno.h>
  34 #include <sys/types.h>
  35 #include <sys/inttypes.h>
  36 #include <sys/elf.h>
  37 #include <sys/elf_notes.h>
  38 #include <sys/mman.h>
  39 #include <sys/stat.h>
  40 #include <sys/statvfs.h>
  41 
  42 static char *pname;
  43 static char *fname;
  44 static char *image;     /* pointer to the ELF file in memory */
  45 
  46 #define ELFSEEK(offset) ((void *)(image + offset))
  47 
  48 /*
  49  * Extract the PT_LOAD bits and format them into a .s
  50  */
  51 static void
  52 extract32(Elf32_Ehdr *eh)
  53 {
  54         Elf32_Phdr *phdr;
  55         caddr_t allphdrs;
  56         int i;
  57         int c;
  58         unsigned char *bytes;
  59         uint_t cnt = 10;
  60 
  61         allphdrs = NULL;
  62 
  63         if (eh->e_type != ET_EXEC) {
  64                 (void) fprintf(stderr, "%s: not ET_EXEC, e_type = 0x%x\n",
  65                     pname, eh->e_type);
  66                 exit(1);
  67         }
  68         if (eh->e_phnum == 0 || eh->e_phoff == 0) {
  69                 (void) fprintf(stderr, "%s: no program headers\n", pname);
  70                 exit(1);
  71         }
  72 
  73         /*
  74          * Get the program headers.
  75          */
  76         allphdrs = ELFSEEK(eh->e_phoff);
  77         if (allphdrs == NULL) {
  78                 (void) fprintf(stderr, "%s: Failed to get %d program hdrs\n",
  79                     pname, eh->e_phnum);
  80                 exit(1);
  81         }
  82 
  83         /*
  84          * Find the PT_LOAD section
  85          */
  86         for (i = 0; i < eh->e_phnum; i++) {
  87                 /*LINTED [ELF program header alignment]*/
  88                 phdr = (Elf32_Phdr *)(allphdrs + eh->e_phentsize * i);
  89 
  90                 if (phdr->p_type != PT_LOAD)
  91                         continue;
  92 
  93                 if (phdr->p_memsz == 0)
  94                         continue;
  95 
  96                 bytes = ELFSEEK(phdr->p_offset);
  97                 for (c = 0; c < phdr->p_filesz; ++c) {
  98                         if (c % cnt == 0)
  99                                 (void) printf("\n       .byte   ");
 100                         else
 101                                 (void) printf(",");
 102                         (void) printf("0x%x", bytes[c]);
 103                 }
 104                 for (; c < phdr->p_memsz; ++c) {
 105                         if (c % cnt == 0) {
 106                                 (void) printf("\n       .byte   ");
 107                                 cnt = 20;
 108                         } else {
 109                                 (void) printf(", ");
 110                         }
 111                         (void) printf("0");
 112                 }
 113                 (void) printf("\n");
 114                 return;
 115         }
 116 
 117         (void) fprintf(stderr, "%s: Failed finding PT_LOAD section\n", pname);
 118         exit(1);
 119 }
 120 
 121 static void
 122 extract64(Elf64_Ehdr *eh)
 123 {
 124         Elf64_Phdr *phdr;
 125         caddr_t allphdrs;
 126         int i;
 127         int c;
 128         unsigned char *bytes;
 129         uint_t cnt = 10;
 130 
 131         allphdrs = NULL;
 132 
 133         if (eh->e_type != ET_EXEC) {
 134                 (void) fprintf(stderr, "%s: not ET_EXEC, e_type = 0x%x\n",
 135                     pname, eh->e_type);
 136                 exit(1);
 137         }
 138         if (eh->e_phnum == 0 || eh->e_phoff == 0) {
 139                 (void) fprintf(stderr, "%s: no program headers\n", pname);
 140                 exit(1);
 141         }
 142 
 143         /*
 144          * Get the program headers.
 145          */
 146         allphdrs = ELFSEEK(eh->e_phoff);
 147         if (allphdrs == NULL) {
 148                 (void) fprintf(stderr, "%s: Failed to get %d program hdrs\n",
 149                     pname, eh->e_phnum);
 150                 exit(1);
 151         }
 152 
 153         /*
 154          * Find the PT_LOAD section
 155          */
 156         for (i = 0; i < eh->e_phnum; i++) {
 157                 /*LINTED [ELF program header alignment]*/
 158                 phdr = (Elf64_Phdr *)(allphdrs + eh->e_phentsize * i);
 159 
 160                 if (phdr->p_type != PT_LOAD)
 161                         continue;
 162 
 163                 if (phdr->p_memsz == 0)
 164                         continue;
 165 
 166                 bytes = ELFSEEK(phdr->p_offset);
 167                 for (c = 0; c < phdr->p_filesz; ++c) {
 168                         if (c % cnt == 0)
 169                                 (void) printf("\n       .byte   ");
 170                         else
 171                                 (void) printf(",");
 172                         (void) printf("0x%x", bytes[c]);
 173                 }
 174                 for (; c < phdr->p_memsz; ++c) {
 175                         if (c % cnt == 0) {
 176                                 (void) printf("\n       .byte   ");
 177                                 cnt = 20;
 178                         } else {
 179                                 (void) printf(", ");
 180                         }
 181                         (void) printf("0");
 182                 }
 183                 (void) printf("\n");
 184                 return;
 185         }
 186 
 187         (void) fprintf(stderr, "%s: Failed finding PT_LOAD section\n", pname);
 188         exit(1);
 189 }
 190 
 191 int
 192 main(int argc, char **argv)
 193 {
 194         int fd;
 195         uchar_t *ident;
 196         void *hdr = NULL;
 197         struct stat stats;
 198         ssize_t r;
 199         size_t pgsz;
 200         uint_t len;
 201 
 202         /*
 203          * we expect one argument -- the elf file
 204          */
 205         if (argc != 2) {
 206                 (void) fprintf(stderr, "usage: %s <unix-elf-file>\n", argv[0]);
 207                 exit(1);
 208         }
 209 
 210         pname = strrchr(argv[0], '/');
 211         if (pname == NULL)
 212                 pname = argv[0];
 213         else
 214                 ++pname;
 215 
 216         fname = argv[1];
 217         fd = open(fname, O_RDONLY);
 218         if (fd < 0) {
 219                 (void) fprintf(stderr, "%s: open(%s, O_RDONLY) failed, %s\n",
 220                     pname, fname, strerror(errno));
 221                 exit(1);
 222         }
 223 
 224         if (stat(fname, &stats) < 0) {
 225                 (void) fprintf(stderr, "%s: stat(%s, ...) failed, %s\n",
 226                     pname, fname, strerror(errno));
 227                 exit(1);
 228         }
 229 
 230         pgsz = getpagesize();
 231         len = (stats.st_size + (pgsz - 1)) & (~(pgsz - 1));
 232 
 233         /*
 234          * mmap the file
 235          */
 236         image = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
 237         if (image == MAP_FAILED) {
 238                 (void) fprintf(stderr, "%s: mmap() of %s failed, %s\n",
 239                     pname, fname, strerror(errno));
 240                 exit(1);
 241         }
 242 
 243         ident = ELFSEEK(0);
 244         if (ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 ||
 245             ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3) {
 246                 (void) fprintf(stderr, "%s: not an ELF file!\n", pname);
 247                 exit(1);
 248         }
 249 
 250         if (ident[EI_CLASS] == ELFCLASS32) {
 251                 hdr = ELFSEEK(0);
 252                 extract32(hdr);
 253         } else if (ident[EI_CLASS] == ELFCLASS64) {
 254                 hdr = ELFSEEK(0);
 255                 extract64(hdr);
 256         } else {
 257                 (void) fprintf(stderr, "%s: Wrong ELF class 0x%x\n", pname,
 258                     ident[EI_CLASS]);
 259                 exit(1);
 260         }
 261         return (0);
 262 }