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