brandelf.c revision 295577
1260684Skaiw/*- 2260684Skaiw * Copyright (c) 2008 Hyogeol Lee 3260684Skaiw * Copyright (c) 2000, 2001 David O'Brien 4289071Semaste * Copyright (c) 1996 S��ren Schmidt 5260684Skaiw * All rights reserved. 6260684Skaiw * 7260684Skaiw * Redistribution and use in source and binary forms, with or without 8260684Skaiw * modification, are permitted provided that the following conditions 9260684Skaiw * are met: 10260684Skaiw * 1. Redistributions of source code must retain the above copyright 11260684Skaiw * notice, this list of conditions and the following disclaimer 12260684Skaiw * in this position and unchanged. 13260684Skaiw * 2. Redistributions in binary form must reproduce the above copyright 14260684Skaiw * notice, this list of conditions and the following disclaimer in the 15260684Skaiw * documentation and/or other materials provided with the distribution. 16260684Skaiw * 3. The name of the author may not be used to endorse or promote products 17260684Skaiw * derived from this software without specific prior written permission 18260684Skaiw * 19260684Skaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20260684Skaiw * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21260684Skaiw * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22260684Skaiw * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23260684Skaiw * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24260684Skaiw * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25260684Skaiw * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26260684Skaiw * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27260684Skaiw * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28260684Skaiw * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29260684Skaiw */ 30260684Skaiw 31260684Skaiw#include <sys/types.h> 32260684Skaiw#include <sys/stat.h> 33260684Skaiw#include <err.h> 34260684Skaiw#include <errno.h> 35260684Skaiw#include <fcntl.h> 36260684Skaiw#include <gelf.h> 37260684Skaiw#include <getopt.h> 38260684Skaiw#include <libelf.h> 39260684Skaiw#include <libelftc.h> 40260684Skaiw#include <stdio.h> 41260684Skaiw#include <stdlib.h> 42260684Skaiw#include <string.h> 43260684Skaiw#include <unistd.h> 44260684Skaiw 45260684Skaiw#include "_elftc.h" 46260684Skaiw 47295577SemasteELFTC_VCSID("$Id: brandelf.c 3354 2016-01-18 21:50:15Z jkoshy $"); 48260684Skaiw 49260684Skaiwstatic int elftype(const char *); 50260684Skaiwstatic const char *iselftype(int); 51260684Skaiwstatic void printelftypes(void); 52260684Skaiwstatic void printversion(void); 53260684Skaiwstatic void usage(void); 54260684Skaiw 55260684Skaiwstruct ELFtypes { 56260684Skaiw const char *str; 57260684Skaiw int value; 58260684Skaiw}; 59260684Skaiw/* XXX - any more types? */ 60260684Skaiwstatic struct ELFtypes elftypes[] = { 61260684Skaiw { "86Open", ELFOSABI_86OPEN }, 62260684Skaiw { "AIX", ELFOSABI_AIX }, 63260684Skaiw { "ARM", ELFOSABI_ARM }, 64260684Skaiw { "AROS", ELFOSABI_AROS }, 65260684Skaiw { "FreeBSD", ELFOSABI_FREEBSD }, 66260684Skaiw { "GNU", ELFOSABI_GNU }, 67260684Skaiw { "HP/UX", ELFOSABI_HPUX}, 68260684Skaiw { "Hurd", ELFOSABI_HURD }, 69260684Skaiw { "IRIX", ELFOSABI_IRIX }, 70260684Skaiw { "Linux", ELFOSABI_GNU }, 71260684Skaiw { "Modesto", ELFOSABI_MODESTO }, 72260684Skaiw { "NSK", ELFOSABI_NSK }, 73260684Skaiw { "NetBSD", ELFOSABI_NETBSD}, 74260684Skaiw { "None", ELFOSABI_NONE}, 75260684Skaiw { "OpenBSD", ELFOSABI_OPENBSD }, 76260684Skaiw { "OpenVMS", ELFOSABI_OPENVMS }, 77260684Skaiw { "Standalone", ELFOSABI_STANDALONE }, 78260684Skaiw { "SVR4", ELFOSABI_NONE }, 79260684Skaiw { "Solaris", ELFOSABI_SOLARIS }, 80260684Skaiw { "Tru64", ELFOSABI_TRU64 } 81260684Skaiw}; 82260684Skaiw 83260684Skaiwstatic struct option brandelf_longopts[] = { 84260684Skaiw { "help", no_argument, NULL, 'h' }, 85260684Skaiw { "version", no_argument, NULL, 'V' }, 86260684Skaiw { NULL, 0, NULL, 0 } 87260684Skaiw}; 88260684Skaiw 89260684Skaiwint 90260684Skaiwmain(int argc, char **argv) 91260684Skaiw{ 92260684Skaiw GElf_Ehdr ehdr; 93260684Skaiw Elf *elf; 94260684Skaiw Elf_Kind kind; 95260684Skaiw int type = ELFOSABI_NONE; 96260684Skaiw int retval = 0; 97276077Semaste int ch, change = 0, force = 0, listed = 0; 98260684Skaiw 99260684Skaiw if (elf_version(EV_CURRENT) == EV_NONE) 100260684Skaiw errx(EXIT_FAILURE, "elf_version error"); 101260684Skaiw 102260684Skaiw while ((ch = getopt_long(argc, argv, "Vf:hlt:v", brandelf_longopts, 103260684Skaiw NULL)) != -1) 104260684Skaiw switch (ch) { 105260684Skaiw case 'f': 106260684Skaiw if (change) 107260684Skaiw errx(EXIT_FAILURE, "ERROR: the -f option is " 108260684Skaiw "incompatible with the -t option."); 109260684Skaiw force = 1; 110260684Skaiw type = atoi(optarg); 111260684Skaiw if (errno == ERANGE || type < 0 || type > 255) { 112260684Skaiw warnx("ERROR: invalid argument to option " 113260684Skaiw "-f: %s", optarg); 114260684Skaiw usage(); 115260684Skaiw } 116260684Skaiw break; 117260684Skaiw case 'h': 118260684Skaiw usage(); 119260684Skaiw break; 120260684Skaiw case 'l': 121260684Skaiw printelftypes(); 122260684Skaiw listed = 1; 123260684Skaiw break; 124260684Skaiw case 'v': 125276077Semaste /* This flag is ignored. */ 126260684Skaiw break; 127260684Skaiw case 't': 128260684Skaiw if (force) 129260684Skaiw errx(EXIT_FAILURE, "the -t option is " 130260684Skaiw "incompatible with the -f option."); 131260684Skaiw if ((type = elftype(optarg)) == -1) { 132260684Skaiw warnx("ERROR: invalid ELF type '%s'", optarg); 133260684Skaiw usage(); 134260684Skaiw } 135260684Skaiw 136260684Skaiw change = 1; 137260684Skaiw break; 138260684Skaiw case 'V': 139260684Skaiw printversion(); 140260684Skaiw break; 141260684Skaiw default: 142260684Skaiw usage(); 143260684Skaiw } 144260684Skaiw argc -= optind; 145260684Skaiw argv += optind; 146260684Skaiw if (!argc) { 147260684Skaiw if (listed) 148260684Skaiw exit(0); 149260684Skaiw else { 150260684Skaiw warnx("no file(s) specified"); 151260684Skaiw usage(); 152260684Skaiw } 153260684Skaiw } 154260684Skaiw 155260684Skaiw while (argc) { 156260684Skaiw int fd; 157260684Skaiw 158260684Skaiw elf = NULL; 159260684Skaiw 160260684Skaiw if ((fd = open(argv[0], (change || force) ? O_RDWR : 161260684Skaiw O_RDONLY, 0)) < 0) { 162260684Skaiw warn("error opening file %s", argv[0]); 163260684Skaiw retval = 1; 164260684Skaiw goto fail; 165260684Skaiw } 166260684Skaiw 167260684Skaiw if ((elf = elf_begin(fd, (change || force) ? ELF_C_RDWR : 168260684Skaiw ELF_C_READ, NULL)) == NULL) { 169260684Skaiw warnx("elf_begin failed: %s", elf_errmsg(-1)); 170260684Skaiw retval = 1; 171260684Skaiw goto fail; 172260684Skaiw } 173260684Skaiw 174260684Skaiw if ((kind = elf_kind(elf)) != ELF_K_ELF) { 175260684Skaiw if (kind == ELF_K_AR) 176260684Skaiw warnx("file '%s' is an archive.", argv[0]); 177260684Skaiw else 178260684Skaiw warnx("file '%s' is not an ELF file.", 179260684Skaiw argv[0]); 180260684Skaiw retval = 1; 181260684Skaiw goto fail; 182260684Skaiw } 183260684Skaiw 184260684Skaiw if (gelf_getehdr(elf, &ehdr) == NULL) { 185260684Skaiw warnx("gelf_getehdr: %s", elf_errmsg(-1)); 186260684Skaiw retval = 1; 187260684Skaiw goto fail; 188260684Skaiw } 189260684Skaiw 190260684Skaiw if (!change && !force) { 191260684Skaiw fprintf(stdout, 192260684Skaiw "File '%s' is of brand '%s' (%u).\n", 193260684Skaiw argv[0], iselftype(ehdr.e_ident[EI_OSABI]), 194260684Skaiw ehdr.e_ident[EI_OSABI]); 195260684Skaiw if (!iselftype(type)) { 196260684Skaiw warnx("ELF ABI Brand '%u' is unknown", 197260684Skaiw type); 198260684Skaiw printelftypes(); 199260684Skaiw } 200260684Skaiw } else { 201260684Skaiw 202260684Skaiw /* 203260684Skaiw * Keep the existing layout of the ELF object. 204260684Skaiw */ 205260684Skaiw if (elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT) == 0) { 206260684Skaiw warnx("elf_flagelf failed: %s", 207260684Skaiw elf_errmsg(-1)); 208260684Skaiw retval = 1; 209260684Skaiw goto fail; 210260684Skaiw } 211260684Skaiw 212260684Skaiw /* 213260684Skaiw * Update the ABI type. 214260684Skaiw */ 215295577Semaste ehdr.e_ident[EI_OSABI] = (unsigned char) type; 216260684Skaiw if (gelf_update_ehdr(elf, &ehdr) == 0) { 217260684Skaiw warnx("gelf_update_ehdr error: %s", 218260684Skaiw elf_errmsg(-1)); 219260684Skaiw retval = 1; 220260684Skaiw goto fail; 221260684Skaiw } 222260684Skaiw 223260684Skaiw /* 224260684Skaiw * Write back changes. 225260684Skaiw */ 226260684Skaiw if (elf_update(elf, ELF_C_WRITE) == -1) { 227260684Skaiw warnx("elf_update error: %s", elf_errmsg(-1)); 228260684Skaiw retval = 1; 229260684Skaiw goto fail; 230260684Skaiw } 231260684Skaiw } 232260684Skaiwfail: 233260684Skaiw 234260684Skaiw if (elf) 235260684Skaiw elf_end(elf); 236260684Skaiw 237260684Skaiw if (fd >= 0 && close(fd) == -1) { 238260684Skaiw warnx("%s: close error", argv[0]); 239260684Skaiw retval = 1; 240260684Skaiw } 241260684Skaiw 242260684Skaiw argc--; 243260684Skaiw argv++; 244260684Skaiw } 245260684Skaiw 246260684Skaiw return (retval); 247260684Skaiw} 248260684Skaiw 249260684Skaiw#define USAGE_MESSAGE "\ 250260684SkaiwUsage: %s [options] file...\n\ 251260684Skaiw Set or display the ABI field for an ELF object.\n\n\ 252260684Skaiw Supported options are:\n\ 253260684Skaiw -f NUM Set the ELF ABI to the number 'NUM'.\n\ 254260684Skaiw -h | --help Print a usage message and exit.\n\ 255260684Skaiw -l List known ELF ABI names.\n\ 256260684Skaiw -t ABI Set the ELF ABI to the value named by \"ABI\".\n\ 257260684Skaiw -V | --version Print a version identifier and exit.\n" 258260684Skaiw 259260684Skaiwstatic void 260260684Skaiwusage(void) 261260684Skaiw{ 262260684Skaiw (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); 263260684Skaiw exit(1); 264260684Skaiw} 265260684Skaiw 266260684Skaiwstatic void 267260684Skaiwprintversion(void) 268260684Skaiw{ 269260684Skaiw (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); 270260684Skaiw exit(0); 271260684Skaiw} 272260684Skaiw 273260684Skaiwstatic const char * 274260684Skaiwiselftype(int etype) 275260684Skaiw{ 276260684Skaiw size_t elfwalk; 277260684Skaiw 278260684Skaiw for (elfwalk = 0; 279260684Skaiw elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 280260684Skaiw elfwalk++) 281260684Skaiw if (etype == elftypes[elfwalk].value) 282260684Skaiw return (elftypes[elfwalk].str); 283260684Skaiw return (0); 284260684Skaiw} 285260684Skaiw 286260684Skaiwstatic int 287260684Skaiwelftype(const char *elfstrtype) 288260684Skaiw{ 289260684Skaiw size_t elfwalk; 290260684Skaiw 291260684Skaiw for (elfwalk = 0; 292260684Skaiw elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 293260684Skaiw elfwalk++) 294260684Skaiw if (strcasecmp(elfstrtype, elftypes[elfwalk].str) == 0) 295260684Skaiw return (elftypes[elfwalk].value); 296260684Skaiw return (-1); 297260684Skaiw} 298260684Skaiw 299260684Skaiwstatic void 300260684Skaiwprintelftypes(void) 301260684Skaiw{ 302260684Skaiw size_t elfwalk; 303260684Skaiw 304260684Skaiw (void) printf("Known ELF types are: "); 305260684Skaiw for (elfwalk = 0; 306260684Skaiw elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 307260684Skaiw elfwalk++) 308260684Skaiw (void) printf("%s(%u) ", elftypes[elfwalk].str, 309260684Skaiw elftypes[elfwalk].value); 310260684Skaiw (void) printf("\n"); 311260684Skaiw} 312