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 3440 2016-04-07 14:51:47Z 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 { "CloudABI", ELFOSABI_CLOUDABI }, 66 { "FreeBSD", ELFOSABI_FREEBSD }, 67 { "GNU", ELFOSABI_GNU }, 68 { "HP/UX", ELFOSABI_HPUX}, 69 { "Hurd", ELFOSABI_HURD }, 70 { "IRIX", ELFOSABI_IRIX }, 71 { "Linux", ELFOSABI_GNU }, 72 { "Modesto", ELFOSABI_MODESTO }, 73 { "NSK", ELFOSABI_NSK }, 74 { "NetBSD", ELFOSABI_NETBSD}, 75 { "None", ELFOSABI_NONE}, 76 { "OpenBSD", ELFOSABI_OPENBSD }, 77 { "OpenVMS", ELFOSABI_OPENVMS }, 78 { "Standalone", ELFOSABI_STANDALONE }, 79 { "SVR4", ELFOSABI_NONE }, 80 { "Solaris", ELFOSABI_SOLARIS }, 81 { "Tru64", ELFOSABI_TRU64 } 82 }; 83 84 static struct option brandelf_longopts[] = { 85 { "help", no_argument, NULL, 'h' }, 86 { "version", no_argument, NULL, 'V' }, 87 { NULL, 0, NULL, 0 } 88 }; 89 90 int 91 main(int argc, char **argv) 92 { 93 GElf_Ehdr ehdr; 94 Elf *elf; 95 Elf_Kind kind; 96 int type = ELFOSABI_NONE; 97 int retval = 0; 98 int ch, change = 0, force = 0, listed = 0; 99 100 if (elf_version(EV_CURRENT) == EV_NONE) 101 errx(EXIT_FAILURE, "elf_version error"); 102 103 while ((ch = getopt_long(argc, argv, "Vf:hlt:v", brandelf_longopts, 104 NULL)) != -1) 105 switch (ch) { 106 case 'f': 107 if (change) 108 errx(EXIT_FAILURE, "ERROR: the -f option is " 109 "incompatible with the -t option."); 110 force = 1; 111 type = atoi(optarg); 112 if (errno == ERANGE || type < 0 || type > 255) { 113 warnx("ERROR: invalid argument to option " 114 "-f: %s", optarg); 115 usage(); 116 } 117 break; 118 case 'h': 119 usage(); 120 break; 121 case 'l': 122 printelftypes(); 123 listed = 1; 124 break; 125 case 'v': 126 /* This flag is ignored. */ 127 break; 128 case 't': 129 if (force) 130 errx(EXIT_FAILURE, "the -t option is " 131 "incompatible with the -f option."); 132 if ((type = elftype(optarg)) == -1) { 133 warnx("ERROR: invalid ELF type '%s'", optarg); 134 usage(); 135 } 136 137 change = 1; 138 break; 139 case 'V': 140 printversion(); 141 break; 142 default: 143 usage(); 144 } 145 argc -= optind; 146 argv += optind; 147 if (!argc) { 148 if (listed) 149 exit(0); 150 else { 151 warnx("no file(s) specified"); 152 usage(); 153 } 154 } 155 156 while (argc) { 157 int fd; 158 159 elf = NULL; 160 161 if ((fd = open(argv[0], (change || force) ? O_RDWR : 162 O_RDONLY, 0)) < 0) { 163 warn("error opening file %s", argv[0]); 164 retval = 1; 165 goto fail; 166 } 167 168 if ((elf = elf_begin(fd, (change || force) ? ELF_C_RDWR : 169 ELF_C_READ, NULL)) == NULL) { 170 warnx("elf_begin failed: %s", elf_errmsg(-1)); 171 retval = 1; 172 goto fail; 173 } 174 175 if ((kind = elf_kind(elf)) != ELF_K_ELF) { 176 if (kind == ELF_K_AR) 177 warnx("file '%s' is an archive.", argv[0]); 178 else 179 warnx("file '%s' is not an ELF file.", 180 argv[0]); 181 retval = 1; 182 goto fail; 183 } 184 185 if (gelf_getehdr(elf, &ehdr) == NULL) { 186 warnx("gelf_getehdr: %s", elf_errmsg(-1)); 187 retval = 1; 188 goto fail; 189 } 190 191 if (!change && !force) { 192 fprintf(stdout, 193 "File '%s' is of brand '%s' (%u).\n", 194 argv[0], iselftype(ehdr.e_ident[EI_OSABI]), 195 ehdr.e_ident[EI_OSABI]); 196 if (!iselftype(type)) { 197 warnx("ELF ABI Brand '%u' is unknown", 198 type); 199 printelftypes(); 200 } 201 } else { 202 203 /* 204 * Keep the existing layout of the ELF object. 205 */ 206 if (elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT) == 0) { 207 warnx("elf_flagelf failed: %s", 208 elf_errmsg(-1)); 209 retval = 1; 210 goto fail; 211 } 212 213 /* 214 * Update the ABI type. 215 */ 216 ehdr.e_ident[EI_OSABI] = (unsigned char) type; 217 if (gelf_update_ehdr(elf, &ehdr) == 0) { 218 warnx("gelf_update_ehdr error: %s", 219 elf_errmsg(-1)); 220 retval = 1; 221 goto fail; 222 } 223 224 /* 225 * Write back changes. 226 */ 227 if (elf_update(elf, ELF_C_WRITE) == -1) { 228 warnx("elf_update error: %s", elf_errmsg(-1)); 229 retval = 1; 230 goto fail; 231 } 232 } 233 fail: 234 235 if (elf) 236 elf_end(elf); 237 238 if (fd >= 0 && close(fd) == -1) { 239 warnx("%s: close error", argv[0]); 240 retval = 1; 241 } 242 243 argc--; 244 argv++; 245 } 246 247 return (retval); 248 } 249 250 #define USAGE_MESSAGE "\ 251 Usage: %s [options] file...\n\ 252 Set or display the ABI field for an ELF object.\n\n\ 253 Supported options are:\n\ 254 -f NUM Set the ELF ABI to the number 'NUM'.\n\ 255 -h | --help Print a usage message and exit.\n\ 256 -l List known ELF ABI names.\n\ 257 -t ABI Set the ELF ABI to the value named by \"ABI\".\n\ 258 -V | --version Print a version identifier and exit.\n" 259 260 static void 261 usage(void) 262 { 263 (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); 264 exit(1); 265 } 266 267 static void 268 printversion(void) 269 { 270 (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); 271 exit(0); 272 } 273 274 static const char * 275 iselftype(int etype) 276 { 277 size_t elfwalk; 278 279 for (elfwalk = 0; 280 elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 281 elfwalk++) 282 if (etype == elftypes[elfwalk].value) 283 return (elftypes[elfwalk].str); 284 return (0); 285 } 286 287 static int 288 elftype(const char *elfstrtype) 289 { 290 size_t elfwalk; 291 292 for (elfwalk = 0; 293 elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 294 elfwalk++) 295 if (strcasecmp(elfstrtype, elftypes[elfwalk].str) == 0) 296 return (elftypes[elfwalk].value); 297 return (-1); 298 } 299 300 static void 301 printelftypes(void) 302 { 303 size_t elfwalk; 304 305 (void) printf("Known ELF types are: "); 306 for (elfwalk = 0; 307 elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 308 elfwalk++) 309 (void) printf("%s(%u) ", elftypes[elfwalk].str, 310 elftypes[elfwalk].value); 311 (void) printf("\n"); 312 } 313