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 { "SVR4", ELFOSABI_SYSV }, 53 { "Linux", ELFOSABI_LINUX } 54 }; 55 56 int 57 main(int argc, char **argv) 58 { 59 60 const char *strtype = "FreeBSD"; 61 int type = ELFOSABI_FREEBSD; 62 int retval = 0; 63 int ch, change = 0, verbose = 0, force = 0, listed = 0; 64 65 while ((ch = getopt(argc, argv, "f:lt:v")) != -1) 66 switch (ch) { 67 case 'f': 68 if (change) 69 errx(1, "f option incompatable with t option"); 70 force = 1; 71 type = atoi(optarg); 72 if (errno == ERANGE || type < 0 || type > 255) { 73 warnx("invalid argument to option f: %s", 74 optarg); 75 usage(); 76 } 77 break; 78 case 'l': 79 printelftypes(); 80 listed = 1; 81 break; 82 case 'v': 83 verbose = 1; 84 break; 85 case 't': 86 if (force) 87 errx(1, "t option incompatable with f option"); 88 change = 1; 89 strtype = optarg; 90 break; 91 default: 92 usage(); 93 } 94 argc -= optind; 95 argv += optind; 96 if (!argc) { 97 if (listed) 98 exit(0); 99 else { 100 warnx("no file(s) specified"); 101 usage(); 102 } 103 } 104 105 if (!force && (type = elftype(strtype)) == -1) { 106 warnx("invalid ELF type '%s'", strtype); 107 printelftypes(); 108 usage(); 109 } 110 111 while (argc) { 112 int fd; 113 char buffer[EI_NIDENT]; 114 115 if ((fd = open(argv[0], change || force ? O_RDWR : O_RDONLY, 0)) < 0) { 116 warn("error opening file %s", argv[0]); 117 retval = 1; 118 goto fail; 119 } 120 if (read(fd, buffer, EI_NIDENT) < EI_NIDENT) { 121 warnx("file '%s' too short", argv[0]); 122 retval = 1; 123 goto fail; 124 } 125 if (buffer[0] != ELFMAG0 || buffer[1] != ELFMAG1 || 126 buffer[2] != ELFMAG2 || buffer[3] != ELFMAG3) { 127 warnx("file '%s' is not ELF format", argv[0]); 128 retval = 1; 129 goto fail; 130 } 131 if (!change && !force) { 132 fprintf(stdout, 133 "File '%s' is of brand '%s' (%u).\n", 134 argv[0], iselftype(buffer[EI_OSABI]), 135 buffer[EI_OSABI]); 136 if (!iselftype(type)) { 137 warnx("ELF ABI Brand '%u' is unknown", 138 type); 139 printelftypes(); 140 } 141 } 142 else { 143 buffer[EI_OSABI] = type; 144 lseek(fd, 0, SEEK_SET); 145 if (write(fd, buffer, EI_NIDENT) != EI_NIDENT) { 146 warn("error writing %s %d", argv[0], fd); 147 retval = 1; 148 goto fail; 149 } 150 } 151 fail: 152 argc--; 153 argv++; 154 } 155 156 return retval; 157 } 158 159 static void 160 usage() 161 { 162 fprintf(stderr, "usage: brandelf [-f ELF ABI number] [-v] [-l] [-t string] file ...\n"); 163 exit(1); 164 } 165 166 static const char * 167 iselftype(int elftype) 168 { 169 int elfwalk; 170 171 for (elfwalk = 0; 172 elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 173 elfwalk++) 174 if (elftype == elftypes[elfwalk].value) 175 return elftypes[elfwalk].str; 176 return 0; 177 } 178 179 static int 180 elftype(const char *elfstrtype) 181 { 182 int elfwalk; 183 184 for (elfwalk = 0; 185 elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 186 elfwalk++) 187 if (strcmp(elfstrtype, elftypes[elfwalk].str) == 0) 188 return elftypes[elfwalk].value; 189 return -1; 190 } 191 192 static void 193 printelftypes() 194 { 195 int elfwalk; 196 197 fprintf(stderr, "known ELF types are: "); 198 for (elfwalk = 0; 199 elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 200 elfwalk++) 201 fprintf(stderr, "%s(%u) ", elftypes[elfwalk].str, 202 elftypes[elfwalk].value); 203 fprintf(stderr, "\n"); 204 } 205