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