1 /*- 2 * Copyright (c) 1996 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software withough specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #include <elf.h> 32 #include <fcntl.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <unistd.h> 37 #include <sys/errno.h> 38 #include <err.h> 39 40 static int elftype(const char *); 41 static const char *iselftype(int); 42 static void printelftypes(void); 43 static void usage __P((void)); 44 45 struct ELFtypes { 46 const char *str; 47 int value; 48 }; 49 /* XXX - any more types? */ 50 static struct ELFtypes elftypes[] = { 51 { "FreeBSD", ELFOSABI_FREEBSD }, 52 { "Linux", ELFOSABI_LINUX }, 53 { "Solaris", ELFOSABI_SOLARIS }, 54 { "SVR4", ELFOSABI_SYSV } 55 }; 56 57 int 58 main(int argc, char **argv) 59 { 60 61 const char *strtype = "FreeBSD"; 62 int type = ELFOSABI_FREEBSD; 63 int retval = 0; 64 int ch, change = 0, verbose = 0, force = 0, listed = 0; 65 66 while ((ch = getopt(argc, argv, "f:lt:v")) != -1) 67 switch (ch) { 68 case 'f': 69 if (change) 70 errx(1, "f option incompatable with t option"); 71 force = 1; 72 type = atoi(optarg); 73 if (errno == ERANGE || type < 0 || type > 255) { 74 warnx("invalid argument to option f: %s", 75 optarg); 76 usage(); 77 } 78 break; 79 case 'l': 80 printelftypes(); 81 listed = 1; 82 break; 83 case 'v': 84 verbose = 1; 85 break; 86 case 't': 87 if (force) 88 errx(1, "t option incompatable with f option"); 89 change = 1; 90 strtype = optarg; 91 break; 92 default: 93 usage(); 94 } 95 argc -= optind; 96 argv += optind; 97 if (!argc) { 98 if (listed) 99 exit(0); 100 else { 101 warnx("no file(s) specified"); 102 usage(); 103 } 104 } 105 106 if (!force && (type = elftype(strtype)) == -1) { 107 warnx("invalid ELF type '%s'", strtype); 108 printelftypes(); 109 usage(); 110 } 111 112 while (argc) { 113 int fd; 114 char buffer[EI_NIDENT]; 115 116 if ((fd = open(argv[0], change || force ? O_RDWR : O_RDONLY, 0)) < 0) { 117 warn("error opening file %s", argv[0]); 118 retval = 1; 119 goto fail; 120 } 121 if (read(fd, buffer, EI_NIDENT) < EI_NIDENT) { 122 warnx("file '%s' too short", argv[0]); 123 retval = 1; 124 goto fail; 125 } 126 if (buffer[0] != ELFMAG0 || buffer[1] != ELFMAG1 || 127 buffer[2] != ELFMAG2 || buffer[3] != ELFMAG3) { 128 warnx("file '%s' is not ELF format", argv[0]); 129 retval = 1; 130 goto fail; 131 } 132 if (!change && !force) { 133 fprintf(stdout, 134 "File '%s' is of brand '%s' (%u).\n", 135 argv[0], iselftype(buffer[EI_OSABI]), 136 buffer[EI_OSABI]); 137 if (!iselftype(type)) { 138 warnx("ELF ABI Brand '%u' is unknown", 139 type); 140 printelftypes(); 141 } 142 } 143 else { 144 buffer[EI_OSABI] = type; 145 lseek(fd, 0, SEEK_SET); 146 if (write(fd, buffer, EI_NIDENT) != EI_NIDENT) { 147 warn("error writing %s %d", argv[0], fd); 148 retval = 1; 149 goto fail; 150 } 151 } 152 fail: 153 close(fd); 154 argc--; 155 argv++; 156 } 157 158 return retval; 159 } 160 161 static void 162 usage() 163 { 164 fprintf(stderr, "usage: brandelf [-f ELF ABI number] [-v] [-l] [-t string] file ...\n"); 165 exit(1); 166 } 167 168 static const char * 169 iselftype(int elftype) 170 { 171 int elfwalk; 172 173 for (elfwalk = 0; 174 elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 175 elfwalk++) 176 if (elftype == elftypes[elfwalk].value) 177 return elftypes[elfwalk].str; 178 return 0; 179 } 180 181 static int 182 elftype(const char *elfstrtype) 183 { 184 int elfwalk; 185 186 for (elfwalk = 0; 187 elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 188 elfwalk++) 189 if (strcmp(elfstrtype, elftypes[elfwalk].str) == 0) 190 return elftypes[elfwalk].value; 191 return -1; 192 } 193 194 static void 195 printelftypes() 196 { 197 int elfwalk; 198 199 fprintf(stderr, "known ELF types are: "); 200 for (elfwalk = 0; 201 elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 202 elfwalk++) 203 fprintf(stderr, "%s(%u) ", elftypes[elfwalk].str, 204 elftypes[elfwalk].value); 205 fprintf(stderr, "\n"); 206 } 207