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 /*
  28  * Copyright (c) 2018, Joyent, Inc.
  29  */
  30 
  31 #include <unistd.h>
  32 #include <stdlib.h>
  33 #include <fcntl.h>
  34 #include <strings.h>
  35 #include <stdio.h>
  36 #include <errno.h>
  37 #include <sys/types.h>
  38 #include <sys/inttypes.h>
  39 #include <sys/elf.h>
  40 #include <sys/elf_notes.h>
  41 #include <sys/mman.h>
  42 #include <sys/stat.h>
  43 #include <sys/statvfs.h>
  44 
  45 static char *pname;
  46 static char *fname;
  47 static char *image;     /* pointer to the ELF file in memory */
  48 
  49 #define ELFSEEK(offset) ((void *)(image + offset))
  50 
  51 /*
  52  * Extract the PT_LOAD bits and format them into a .s
  53  */
  54 static void
  55 extract32(Elf32_Ehdr *eh)
  56 {
  57         Elf32_Phdr *phdr;
  58         caddr_t allphdrs;
  59         int i;
  60         int c;
  61         unsigned char *bytes;
  62         uint_t cnt = 10;
  63 
  64         allphdrs = NULL;
  65 
  66         if (eh->e_type != ET_EXEC) {
  67                 (void) fprintf(stderr, "%s: not ET_EXEC, e_type = 0x%x\n",
  68                     pname, eh->e_type);
  69                 exit(1);
  70         }
  71         if (eh->e_phnum == 0 || eh->e_phoff == 0) {
  72                 (void) fprintf(stderr, "%s: no program headers\n", pname);
  73                 exit(1);
  74         }
  75 
  76         /*
  77          * Get the program headers.
  78          */
  79         allphdrs = ELFSEEK(eh->e_phoff);
  80         if (allphdrs == NULL) {
  81                 (void) fprintf(stderr, "%s: Failed to get %d program hdrs\n",
  82                     pname, eh->e_phnum);
  83                 exit(1);
  84         }
  85 
  86         /*
  87          * Find the PT_LOAD section
  88          */
  89         for (i = 0; i < eh->e_phnum; i++) {
  90                 /*LINTED [ELF program header alignment]*/
  91                 phdr = (Elf32_Phdr *)(allphdrs + eh->e_phentsize * i);
  92 
  93                 if (phdr->p_type != PT_LOAD)
  94                         continue;
  95 
  96                 if (phdr->p_memsz == 0)
  97                         continue;
  98 
  99                 bytes = ELFSEEK(phdr->p_offset);
 100                 for (c = 0; c < phdr->p_filesz; ++c) {
 101                         if (c % cnt == 0)
 102                                 (void) printf("\n       .byte   ");
 103                         else
 104                                 (void) printf(",");
 105                         (void) printf("0x%x", bytes[c]);
 106                 }
 107                 for (; c < phdr->p_memsz; ++c) {
 108                         if (c % cnt == 0) {
 109                                 (void) printf("\n       .byte   ");
 110                                 cnt = 20;
 111                         } else {
 112                                 (void) printf(", ");
 113                         }
 114                         (void) printf("0");
 115                 }
 116                 (void) printf("\n");
 117                 return;
 118         }
 119 
 120         (void) fprintf(stderr, "%s: Failed finding PT_LOAD section\n", pname);
 121         exit(1);
 122 }
 123 
 124 static void
 125 extract64(Elf64_Ehdr *eh)
 126 {
 127         Elf64_Phdr *phdr;
 128         caddr_t allphdrs;
 129         int i;
 130         int c;
 131         unsigned char *bytes;
 132         uint_t cnt = 10;
 133 
 134         allphdrs = NULL;
 135 
 136         if (eh->e_type != ET_EXEC) {
 137                 (void) fprintf(stderr, "%s: not ET_EXEC, e_type = 0x%x\n",
 138                     pname, eh->e_type);
 139                 exit(1);
 140         }
 141         if (eh->e_phnum == 0 || eh->e_phoff == 0) {
 142                 (void) fprintf(stderr, "%s: no program headers\n", pname);
 143                 exit(1);
 144         }
 145 
 146         /*
 147          * Get the program headers.
 148          */
 149         allphdrs = ELFSEEK(eh->e_phoff);
 150         if (allphdrs == NULL) {
 151                 (void) fprintf(stderr, "%s: Failed to get %d program hdrs\n",
 152                     pname, eh->e_phnum);
 153                 exit(1);
 154         }
 155 
 156         /*
 157          * Find the PT_LOAD section
 158          */
 159         for (i = 0; i < eh->e_phnum; i++) {
 160                 /*LINTED [ELF program header alignment]*/
 161                 phdr = (Elf64_Phdr *)(allphdrs + eh->e_phentsize * i);
 162 
 163                 if (phdr->p_type != PT_LOAD)
 164                         continue;
 165 
 166                 if (phdr->p_memsz == 0)
 167                         continue;
 168 
 169                 bytes = ELFSEEK(phdr->p_offset);
 170                 for (c = 0; c < phdr->p_filesz; ++c) {
 171                         if (c % cnt == 0)
 172                                 (void) printf("\n       .byte   ");
 173                         else
 174                                 (void) printf(",");
 175                         (void) printf("0x%x", bytes[c]);
 176                 }
 177                 for (; c < phdr->p_memsz; ++c) {
 178                         if (c % cnt == 0) {
 179                                 (void) printf("\n       .byte   ");
 180                                 cnt = 20;
 181                         } else {
 182                                 (void) printf(", ");
 183                         }
 184                         (void) printf("0");
 185                 }
 186                 (void) printf("\n");
 187                 return;
 188         }
 189 
 190         (void) fprintf(stderr, "%s: Failed finding PT_LOAD section\n", pname);
 191         exit(1);
 192 }
 193 
 194 int
 195 main(int argc, char **argv)
 196 {
 197         int fd;
 198         uchar_t *ident;
 199         void *hdr = NULL;
 200         struct stat stats;
 201         ssize_t r;
 202         size_t pgsz;
 203         uint_t len;
 204 
 205         /*
 206          * we expect one argument -- the elf file
 207          */
 208         if (argc != 2) {
 209                 (void) fprintf(stderr, "usage: %s <unix-elf-file>\n", argv[0]);
 210                 exit(1);
 211         }
 212 
 213         pname = strrchr(argv[0], '/');
 214         if (pname == NULL)
 215                 pname = argv[0];
 216         else
 217                 ++pname;
 218 
 219         fname = argv[1];
 220         fd = open(fname, O_RDONLY);
 221         if (fd < 0) {
 222                 (void) fprintf(stderr, "%s: open(%s, O_RDONLY) failed, %s\n",
 223                     pname, fname, strerror(errno));
 224                 exit(1);
 225         }
 226 
 227         if (stat(fname, &stats) < 0) {
 228                 (void) fprintf(stderr, "%s: stat(%s, ...) failed, %s\n",
 229                     pname, fname, strerror(errno));
 230                 exit(1);
 231         }
 232 
 233         pgsz = getpagesize();
 234         len = (stats.st_size + (pgsz - 1)) & (~(pgsz - 1));
 235 
 236         /*
 237          * mmap the file
 238          */
 239         image = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
 240         if (image == MAP_FAILED) {
 241                 (void) fprintf(stderr, "%s: mmap() of %s failed, %s\n",
 242                     pname, fname, strerror(errno));
 243                 exit(1);
 244         }
 245 
 246         ident = ELFSEEK(0);
 247         if (ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 ||
 248             ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3) {
 249                 (void) fprintf(stderr, "%s: not an ELF file!\n", pname);
 250                 exit(1);
 251         }
 252 
 253         if (ident[EI_CLASS] == ELFCLASS32) {
 254                 hdr = ELFSEEK(0);
 255                 extract32(hdr);
 256         } else if (ident[EI_CLASS] == ELFCLASS64) {
 257                 hdr = ELFSEEK(0);
 258                 extract64(hdr);
 259         } else {
 260                 (void) fprintf(stderr, "%s: Wrong ELF class 0x%x\n", pname,
 261                     ident[EI_CLASS]);
 262                 exit(1);
 263         }
 264         return (0);
 265 }