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