1 /*- 2 * Copyright (c) 2008 Hyogeol Lee 3 * Copyright (c) 2000, 2001 David O'Brien 4 * Copyright (c) 1996 Søren Schmidt 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer 12 * in this position and unchanged. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include <sys/types.h> 32 #include <sys/stat.h> 33 #include <err.h> 34 #include <errno.h> 35 #include <fcntl.h> 36 #include <gelf.h> 37 #include <getopt.h> 38 #include <libelf.h> 39 #include <libelftc.h> 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 #include <unistd.h> 44 45 #include "_elftc.h" 46 47 ELFTC_VCSID("$Id: brandelf.c 3234 2015-07-31 12:35:09Z emaste $"); 48 49 static int elftype(const char *); 50 static const char *iselftype(int); 51 static void printelftypes(void); 52 static void printversion(void); 53 static void usage(void); 54 55 struct ELFtypes { 56 const char *str; 57 int value; 58 }; 59 /* XXX - any more types? */ 60 static struct ELFtypes elftypes[] = { 61 { "86Open", ELFOSABI_86OPEN }, 62 { "AIX", ELFOSABI_AIX }, 63 { "ARM", ELFOSABI_ARM }, 64 { "AROS", ELFOSABI_AROS }, 65 { "FreeBSD", ELFOSABI_FREEBSD }, 66 { "GNU", ELFOSABI_GNU }, 67 { "HP/UX", ELFOSABI_HPUX}, 68 { "Hurd", ELFOSABI_HURD }, 69 { "IRIX", ELFOSABI_IRIX }, 70 { "Linux", ELFOSABI_GNU }, 71 { "Modesto", ELFOSABI_MODESTO }, 72 { "NSK", ELFOSABI_NSK }, 73 { "NetBSD", ELFOSABI_NETBSD}, 74 { "None", ELFOSABI_NONE}, 75 { "OpenBSD", ELFOSABI_OPENBSD }, 76 { "OpenVMS", ELFOSABI_OPENVMS }, 77 { "Standalone", ELFOSABI_STANDALONE }, 78 { "SVR4", ELFOSABI_NONE }, 79 { "Solaris", ELFOSABI_SOLARIS }, 80 { "Tru64", ELFOSABI_TRU64 } 81 }; 82 83 static struct option brandelf_longopts[] = { 84 { "help", no_argument, NULL, 'h' }, 85 { "version", no_argument, NULL, 'V' }, 86 { NULL, 0, NULL, 0 } 87 }; 88 89 int 90 main(int argc, char **argv) 91 { 92 GElf_Ehdr ehdr; 93 Elf *elf; 94 Elf_Kind kind; 95 int type = ELFOSABI_NONE; 96 int retval = 0; 97 int ch, change = 0, force = 0, listed = 0; 98 99 if (elf_version(EV_CURRENT) == EV_NONE) 100 errx(EXIT_FAILURE, "elf_version error"); 101 102 while ((ch = getopt_long(argc, argv, "Vf:hlt:v", brandelf_longopts, 103 NULL)) != -1) 104 switch (ch) { 105 case 'f': 106 if (change) 107 errx(EXIT_FAILURE, "ERROR: the -f option is " 108 "incompatible with the -t option."); 109 force = 1; 110 type = atoi(optarg); 111 if (errno == ERANGE || type < 0 || type > 255) { 112 warnx("ERROR: invalid argument to option " 113 "-f: %s", optarg); 114 usage(); 115 } 116 break; 117 case 'h': 118 usage(); 119 break; 120 case 'l': 121 printelftypes(); 122 listed = 1; 123 break; 124 case 'v': 125 /* This flag is ignored. */ 126 break; 127 case 't': 128 if (force) 129 errx(EXIT_FAILURE, "the -t option is " 130 "incompatible with the -f option."); 131 if ((type = elftype(optarg)) == -1) { 132 warnx("ERROR: invalid ELF type '%s'", optarg); 133 usage(); 134 } 135 136 change = 1; 137 break; 138 case 'V': 139 printversion(); 140 break; 141 default: 142 usage(); 143 } 144 argc -= optind; 145 argv += optind; 146 if (!argc) { 147 if (listed) 148 exit(0); 149 else { 150 warnx("no file(s) specified"); 151 usage(); 152 } 153 } 154 155 while (argc) { 156 int fd; 157 158 elf = NULL; 159 160 if ((fd = open(argv[0], (change || force) ? O_RDWR : 161 O_RDONLY, 0)) < 0) { 162 warn("error opening file %s", argv[0]); 163 retval = 1; 164 goto fail; 165 } 166 167 if ((elf = elf_begin(fd, (change || force) ? ELF_C_RDWR : 168 ELF_C_READ, NULL)) == NULL) { 169 warnx("elf_begin failed: %s", elf_errmsg(-1)); 170 retval = 1; 171 goto fail; 172 } 173 174 if ((kind = elf_kind(elf)) != ELF_K_ELF) { 175 if (kind == ELF_K_AR) 176 warnx("file '%s' is an archive.", argv[0]); 177 else 178 warnx("file '%s' is not an ELF file.", 179 argv[0]); 180 retval = 1; 181 goto fail; 182 } 183 184 if (gelf_getehdr(elf, &ehdr) == NULL) { 185 warnx("gelf_getehdr: %s", elf_errmsg(-1)); 186 retval = 1; 187 goto fail; 188 } 189 190 if (!change && !force) { 191 fprintf(stdout, 192 "File '%s' is of brand '%s' (%u).\n", 193 argv[0], iselftype(ehdr.e_ident[EI_OSABI]), 194 ehdr.e_ident[EI_OSABI]); 195 if (!iselftype(type)) { 196 warnx("ELF ABI Brand '%u' is unknown", 197 type); 198 printelftypes(); 199 } 200 } else { 201 202 /* 203 * Keep the existing layout of the ELF object. 204 */ 205 if (elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT) == 0) { 206 warnx("elf_flagelf failed: %s", 207 elf_errmsg(-1)); 208 retval = 1; 209 goto fail; 210 } 211 212 /* 213 * Update the ABI type. 214 */ 215 ehdr.e_ident[EI_OSABI] = type; 216 if (gelf_update_ehdr(elf, &ehdr) == 0) { 217 warnx("gelf_update_ehdr error: %s", 218 elf_errmsg(-1)); 219 retval = 1; 220 goto fail; 221 } 222 223 /* 224 * Write back changes. 225 */ 226 if (elf_update(elf, ELF_C_WRITE) == -1) { 227 warnx("elf_update error: %s", elf_errmsg(-1)); 228 retval = 1; 229 goto fail; 230 } 231 } 232 fail: 233 234 if (elf) 235 elf_end(elf); 236 237 if (fd >= 0 && close(fd) == -1) { 238 warnx("%s: close error", argv[0]); 239 retval = 1; 240 } 241 242 argc--; 243 argv++; 244 } 245 246 return (retval); 247 } 248 249 #define USAGE_MESSAGE "\ 250 Usage: %s [options] file...\n\ 251 Set or display the ABI field for an ELF object.\n\n\ 252 Supported options are:\n\ 253 -f NUM Set the ELF ABI to the number 'NUM'.\n\ 254 -h | --help Print a usage message and exit.\n\ 255 -l List known ELF ABI names.\n\ 256 -t ABI Set the ELF ABI to the value named by \"ABI\".\n\ 257 -V | --version Print a version identifier and exit.\n" 258 259 static void 260 usage(void) 261 { 262 (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); 263 exit(1); 264 } 265 266 static void 267 printversion(void) 268 { 269 (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); 270 exit(0); 271 } 272 273 static const char * 274 iselftype(int etype) 275 { 276 size_t elfwalk; 277 278 for (elfwalk = 0; 279 elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 280 elfwalk++) 281 if (etype == elftypes[elfwalk].value) 282 return (elftypes[elfwalk].str); 283 return (0); 284 } 285 286 static int 287 elftype(const char *elfstrtype) 288 { 289 size_t elfwalk; 290 291 for (elfwalk = 0; 292 elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 293 elfwalk++) 294 if (strcasecmp(elfstrtype, elftypes[elfwalk].str) == 0) 295 return (elftypes[elfwalk].value); 296 return (-1); 297 } 298 299 static void 300 printelftypes(void) 301 { 302 size_t elfwalk; 303 304 (void) printf("Known ELF types are: "); 305 for (elfwalk = 0; 306 elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 307 elfwalk++) 308 (void) printf("%s(%u) ", elftypes[elfwalk].str, 309 elftypes[elfwalk].value); 310 (void) printf("\n"); 311 } 312