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