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 47300311SemasteELFTC_VCSID("$Id: brandelf.c 3440 2016-04-07 14:51:47Z emaste $"); 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 }, 65300311Semaste { "CloudABI", ELFOSABI_CLOUDABI }, 66260684Skaiw { "FreeBSD", ELFOSABI_FREEBSD }, 67260684Skaiw { "GNU", ELFOSABI_GNU }, 68260684Skaiw { "HP/UX", ELFOSABI_HPUX}, 69260684Skaiw { "Hurd", ELFOSABI_HURD }, 70260684Skaiw { "IRIX", ELFOSABI_IRIX }, 71260684Skaiw { "Linux", ELFOSABI_GNU }, 72260684Skaiw { "Modesto", ELFOSABI_MODESTO }, 73260684Skaiw { "NSK", ELFOSABI_NSK }, 74260684Skaiw { "NetBSD", ELFOSABI_NETBSD}, 75260684Skaiw { "None", ELFOSABI_NONE}, 76260684Skaiw { "OpenBSD", ELFOSABI_OPENBSD }, 77260684Skaiw { "OpenVMS", ELFOSABI_OPENVMS }, 78260684Skaiw { "Standalone", ELFOSABI_STANDALONE }, 79260684Skaiw { "SVR4", ELFOSABI_NONE }, 80260684Skaiw { "Solaris", ELFOSABI_SOLARIS }, 81260684Skaiw { "Tru64", ELFOSABI_TRU64 } 82260684Skaiw}; 83260684Skaiw 84260684Skaiwstatic struct option brandelf_longopts[] = { 85260684Skaiw { "help", no_argument, NULL, 'h' }, 86260684Skaiw { "version", no_argument, NULL, 'V' }, 87260684Skaiw { NULL, 0, NULL, 0 } 88260684Skaiw}; 89260684Skaiw 90260684Skaiwint 91260684Skaiwmain(int argc, char **argv) 92260684Skaiw{ 93260684Skaiw GElf_Ehdr ehdr; 94260684Skaiw Elf *elf; 95260684Skaiw Elf_Kind kind; 96260684Skaiw int type = ELFOSABI_NONE; 97260684Skaiw int retval = 0; 98276077Semaste int ch, change = 0, force = 0, listed = 0; 99260684Skaiw 100260684Skaiw if (elf_version(EV_CURRENT) == EV_NONE) 101260684Skaiw errx(EXIT_FAILURE, "elf_version error"); 102260684Skaiw 103260684Skaiw while ((ch = getopt_long(argc, argv, "Vf:hlt:v", brandelf_longopts, 104260684Skaiw NULL)) != -1) 105260684Skaiw switch (ch) { 106260684Skaiw case 'f': 107260684Skaiw if (change) 108260684Skaiw errx(EXIT_FAILURE, "ERROR: the -f option is " 109260684Skaiw "incompatible with the -t option."); 110260684Skaiw force = 1; 111260684Skaiw type = atoi(optarg); 112260684Skaiw if (errno == ERANGE || type < 0 || type > 255) { 113260684Skaiw warnx("ERROR: invalid argument to option " 114260684Skaiw "-f: %s", optarg); 115260684Skaiw usage(); 116260684Skaiw } 117260684Skaiw break; 118260684Skaiw case 'h': 119260684Skaiw usage(); 120260684Skaiw break; 121260684Skaiw case 'l': 122260684Skaiw printelftypes(); 123260684Skaiw listed = 1; 124260684Skaiw break; 125260684Skaiw case 'v': 126276077Semaste /* This flag is ignored. */ 127260684Skaiw break; 128260684Skaiw case 't': 129260684Skaiw if (force) 130260684Skaiw errx(EXIT_FAILURE, "the -t option is " 131260684Skaiw "incompatible with the -f option."); 132260684Skaiw if ((type = elftype(optarg)) == -1) { 133260684Skaiw warnx("ERROR: invalid ELF type '%s'", optarg); 134260684Skaiw usage(); 135260684Skaiw } 136260684Skaiw 137260684Skaiw change = 1; 138260684Skaiw break; 139260684Skaiw case 'V': 140260684Skaiw printversion(); 141260684Skaiw break; 142260684Skaiw default: 143260684Skaiw usage(); 144260684Skaiw } 145260684Skaiw argc -= optind; 146260684Skaiw argv += optind; 147260684Skaiw if (!argc) { 148260684Skaiw if (listed) 149260684Skaiw exit(0); 150260684Skaiw else { 151260684Skaiw warnx("no file(s) specified"); 152260684Skaiw usage(); 153260684Skaiw } 154260684Skaiw } 155260684Skaiw 156260684Skaiw while (argc) { 157260684Skaiw int fd; 158260684Skaiw 159260684Skaiw elf = NULL; 160260684Skaiw 161260684Skaiw if ((fd = open(argv[0], (change || force) ? O_RDWR : 162260684Skaiw O_RDONLY, 0)) < 0) { 163260684Skaiw warn("error opening file %s", argv[0]); 164260684Skaiw retval = 1; 165260684Skaiw goto fail; 166260684Skaiw } 167260684Skaiw 168260684Skaiw if ((elf = elf_begin(fd, (change || force) ? ELF_C_RDWR : 169260684Skaiw ELF_C_READ, NULL)) == NULL) { 170260684Skaiw warnx("elf_begin failed: %s", elf_errmsg(-1)); 171260684Skaiw retval = 1; 172260684Skaiw goto fail; 173260684Skaiw } 174260684Skaiw 175260684Skaiw if ((kind = elf_kind(elf)) != ELF_K_ELF) { 176260684Skaiw if (kind == ELF_K_AR) 177260684Skaiw warnx("file '%s' is an archive.", argv[0]); 178260684Skaiw else 179260684Skaiw warnx("file '%s' is not an ELF file.", 180260684Skaiw argv[0]); 181260684Skaiw retval = 1; 182260684Skaiw goto fail; 183260684Skaiw } 184260684Skaiw 185260684Skaiw if (gelf_getehdr(elf, &ehdr) == NULL) { 186260684Skaiw warnx("gelf_getehdr: %s", elf_errmsg(-1)); 187260684Skaiw retval = 1; 188260684Skaiw goto fail; 189260684Skaiw } 190260684Skaiw 191260684Skaiw if (!change && !force) { 192260684Skaiw fprintf(stdout, 193260684Skaiw "File '%s' is of brand '%s' (%u).\n", 194260684Skaiw argv[0], iselftype(ehdr.e_ident[EI_OSABI]), 195260684Skaiw ehdr.e_ident[EI_OSABI]); 196260684Skaiw if (!iselftype(type)) { 197260684Skaiw warnx("ELF ABI Brand '%u' is unknown", 198260684Skaiw type); 199260684Skaiw printelftypes(); 200260684Skaiw } 201260684Skaiw } else { 202260684Skaiw 203260684Skaiw /* 204260684Skaiw * Keep the existing layout of the ELF object. 205260684Skaiw */ 206260684Skaiw if (elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT) == 0) { 207260684Skaiw warnx("elf_flagelf failed: %s", 208260684Skaiw elf_errmsg(-1)); 209260684Skaiw retval = 1; 210260684Skaiw goto fail; 211260684Skaiw } 212260684Skaiw 213260684Skaiw /* 214260684Skaiw * Update the ABI type. 215260684Skaiw */ 216295577Semaste ehdr.e_ident[EI_OSABI] = (unsigned char) type; 217260684Skaiw if (gelf_update_ehdr(elf, &ehdr) == 0) { 218260684Skaiw warnx("gelf_update_ehdr error: %s", 219260684Skaiw elf_errmsg(-1)); 220260684Skaiw retval = 1; 221260684Skaiw goto fail; 222260684Skaiw } 223260684Skaiw 224260684Skaiw /* 225260684Skaiw * Write back changes. 226260684Skaiw */ 227260684Skaiw if (elf_update(elf, ELF_C_WRITE) == -1) { 228260684Skaiw warnx("elf_update error: %s", elf_errmsg(-1)); 229260684Skaiw retval = 1; 230260684Skaiw goto fail; 231260684Skaiw } 232260684Skaiw } 233260684Skaiwfail: 234260684Skaiw 235260684Skaiw if (elf) 236260684Skaiw elf_end(elf); 237260684Skaiw 238260684Skaiw if (fd >= 0 && close(fd) == -1) { 239260684Skaiw warnx("%s: close error", argv[0]); 240260684Skaiw retval = 1; 241260684Skaiw } 242260684Skaiw 243260684Skaiw argc--; 244260684Skaiw argv++; 245260684Skaiw } 246260684Skaiw 247260684Skaiw return (retval); 248260684Skaiw} 249260684Skaiw 250260684Skaiw#define USAGE_MESSAGE "\ 251260684SkaiwUsage: %s [options] file...\n\ 252260684Skaiw Set or display the ABI field for an ELF object.\n\n\ 253260684Skaiw Supported options are:\n\ 254260684Skaiw -f NUM Set the ELF ABI to the number 'NUM'.\n\ 255260684Skaiw -h | --help Print a usage message and exit.\n\ 256260684Skaiw -l List known ELF ABI names.\n\ 257260684Skaiw -t ABI Set the ELF ABI to the value named by \"ABI\".\n\ 258260684Skaiw -V | --version Print a version identifier and exit.\n" 259260684Skaiw 260260684Skaiwstatic void 261260684Skaiwusage(void) 262260684Skaiw{ 263260684Skaiw (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); 264260684Skaiw exit(1); 265260684Skaiw} 266260684Skaiw 267260684Skaiwstatic void 268260684Skaiwprintversion(void) 269260684Skaiw{ 270260684Skaiw (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); 271260684Skaiw exit(0); 272260684Skaiw} 273260684Skaiw 274260684Skaiwstatic const char * 275260684Skaiwiselftype(int etype) 276260684Skaiw{ 277260684Skaiw size_t elfwalk; 278260684Skaiw 279260684Skaiw for (elfwalk = 0; 280260684Skaiw elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 281260684Skaiw elfwalk++) 282260684Skaiw if (etype == elftypes[elfwalk].value) 283260684Skaiw return (elftypes[elfwalk].str); 284260684Skaiw return (0); 285260684Skaiw} 286260684Skaiw 287260684Skaiwstatic int 288260684Skaiwelftype(const char *elfstrtype) 289260684Skaiw{ 290260684Skaiw size_t elfwalk; 291260684Skaiw 292260684Skaiw for (elfwalk = 0; 293260684Skaiw elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 294260684Skaiw elfwalk++) 295260684Skaiw if (strcasecmp(elfstrtype, elftypes[elfwalk].str) == 0) 296260684Skaiw return (elftypes[elfwalk].value); 297260684Skaiw return (-1); 298260684Skaiw} 299260684Skaiw 300260684Skaiwstatic void 301260684Skaiwprintelftypes(void) 302260684Skaiw{ 303260684Skaiw size_t elfwalk; 304260684Skaiw 305260684Skaiw (void) printf("Known ELF types are: "); 306260684Skaiw for (elfwalk = 0; 307260684Skaiw elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 308260684Skaiw elfwalk++) 309260684Skaiw (void) printf("%s(%u) ", elftypes[elfwalk].str, 310260684Skaiw elftypes[elfwalk].value); 311260684Skaiw (void) printf("\n"); 312260684Skaiw} 313