118962Ssos/*- 278627Sobrien * Copyright (c) 2000, 2001 David O'Brien 318962Ssos * Copyright (c) 1996 S�ren Schmidt 418962Ssos * All rights reserved. 518962Ssos * 618962Ssos * Redistribution and use in source and binary forms, with or without 718962Ssos * modification, are permitted provided that the following conditions 818962Ssos * are met: 918962Ssos * 1. Redistributions of source code must retain the above copyright 1018962Ssos * notice, this list of conditions and the following disclaimer 1118962Ssos * in this position and unchanged. 1218962Ssos * 2. Redistributions in binary form must reproduce the above copyright 1318962Ssos * notice, this list of conditions and the following disclaimer in the 1418962Ssos * documentation and/or other materials provided with the distribution. 1518962Ssos * 3. The name of the author may not be used to endorse or promote products 1697748Sschweikh * derived from this software without specific prior written permission 1718962Ssos * 1818962Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1918962Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2018962Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2118962Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2218962Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2318962Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2418962Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2518962Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2618962Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2718962Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2818962Ssos */ 2918962Ssos 3087248Smarkm#include <sys/cdefs.h> 3187248Smarkm__FBSDID("$FreeBSD$"); 3287248Smarkm 3376224Sobrien#include <sys/types.h> 3476224Sobrien#include <sys/elf_common.h> 3587248Smarkm#include <sys/errno.h> 3687248Smarkm#include <err.h> 3725984Sjdp#include <fcntl.h> 3825984Sjdp#include <stdio.h> 3918962Ssos#include <stdlib.h> 4022499Sjoerg#include <string.h> 4122499Sjoerg#include <unistd.h> 4218962Ssos 4359342Sobrienstatic int elftype(const char *); 4459342Sobrienstatic const char *iselftype(int); 4555377Swesstatic void printelftypes(void); 4687248Smarkmstatic void usage(void); 4718962Ssos 4859342Sobrienstruct ELFtypes { 4959342Sobrien const char *str; 5059342Sobrien int value; 5159342Sobrien}; 5259342Sobrien/* XXX - any more types? */ 5359342Sobrienstatic struct ELFtypes elftypes[] = { 5459342Sobrien { "FreeBSD", ELFOSABI_FREEBSD }, 5562313Sgreen { "Linux", ELFOSABI_LINUX }, 5662313Sgreen { "Solaris", ELFOSABI_SOLARIS }, 5762313Sgreen { "SVR4", ELFOSABI_SYSV } 5859342Sobrien}; 5959342Sobrien 6022499Sjoergint 6118962Ssosmain(int argc, char **argv) 6218962Ssos{ 6318962Ssos 6459342Sobrien const char *strtype = "FreeBSD"; 6559342Sobrien int type = ELFOSABI_FREEBSD; 6622499Sjoerg int retval = 0; 67231812Seadler int ch, change = 0, force = 0, listed = 0; 6818962Ssos 6959342Sobrien while ((ch = getopt(argc, argv, "f:lt:v")) != -1) 7018962Ssos switch (ch) { 7135364Seivind case 'f': 7259342Sobrien if (change) 7372093Sasmodai errx(1, "f option incompatible with t option"); 7435364Seivind force = 1; 7559342Sobrien type = atoi(optarg); 7659342Sobrien if (errno == ERANGE || type < 0 || type > 255) { 7759342Sobrien warnx("invalid argument to option f: %s", 7859342Sobrien optarg); 7959342Sobrien usage(); 8059342Sobrien } 8135364Seivind break; 8255377Swes case 'l': 8355377Swes printelftypes(); 8455377Swes listed = 1; 8555377Swes break; 8618962Ssos case 'v': 87231812Seadler /* does nothing */ 8818962Ssos break; 8918962Ssos case 't': 9059342Sobrien if (force) 9172093Sasmodai errx(1, "t option incompatible with f option"); 9218962Ssos change = 1; 9359342Sobrien strtype = optarg; 9418962Ssos break; 9518962Ssos default: 9618962Ssos usage(); 9718962Ssos } 9818962Ssos argc -= optind; 9918962Ssos argv += optind; 10055377Swes if (!argc) { 10155377Swes if (listed) 10255377Swes exit(0); 10355377Swes else { 10455377Swes warnx("no file(s) specified"); 10555377Swes usage(); 10655377Swes } 10755377Swes } 10835364Seivind 10959342Sobrien if (!force && (type = elftype(strtype)) == -1) { 11059342Sobrien warnx("invalid ELF type '%s'", strtype); 11155377Swes printelftypes(); 11255377Swes usage(); 11355377Swes } 11435364Seivind 11518962Ssos while (argc) { 11618962Ssos int fd; 11725984Sjdp char buffer[EI_NIDENT]; 11818962Ssos 11959342Sobrien if ((fd = open(argv[0], change || force ? O_RDWR : O_RDONLY, 0)) < 0) { 12028620Sjoerg warn("error opening file %s", argv[0]); 12122499Sjoerg retval = 1; 12218962Ssos goto fail; 12318962Ssos } 12425984Sjdp if (read(fd, buffer, EI_NIDENT) < EI_NIDENT) { 12526837Scharnier warnx("file '%s' too short", argv[0]); 12622499Sjoerg retval = 1; 12718962Ssos goto fail; 12818962Ssos } 12918962Ssos if (buffer[0] != ELFMAG0 || buffer[1] != ELFMAG1 || 13018962Ssos buffer[2] != ELFMAG2 || buffer[3] != ELFMAG3) { 13126837Scharnier warnx("file '%s' is not ELF format", argv[0]); 13222499Sjoerg retval = 1; 13318962Ssos goto fail; 13435364Seivind } 13559342Sobrien if (!change && !force) { 13659342Sobrien fprintf(stdout, 13759342Sobrien "File '%s' is of brand '%s' (%u).\n", 13859342Sobrien argv[0], iselftype(buffer[EI_OSABI]), 13959342Sobrien buffer[EI_OSABI]); 14059342Sobrien if (!iselftype(type)) { 14159342Sobrien warnx("ELF ABI Brand '%u' is unknown", 14259342Sobrien type); 14359342Sobrien printelftypes(); 14418962Ssos } 14518962Ssos } 14618962Ssos else { 14759342Sobrien buffer[EI_OSABI] = type; 14818962Ssos lseek(fd, 0, SEEK_SET); 14925984Sjdp if (write(fd, buffer, EI_NIDENT) != EI_NIDENT) { 15059342Sobrien warn("error writing %s %d", argv[0], fd); 15126837Scharnier retval = 1; 15218962Ssos goto fail; 15318962Ssos } 15418962Ssos } 15518962Ssosfail: 15662375Simp close(fd); 15718962Ssos argc--; 15818962Ssos argv++; 15918962Ssos } 16022499Sjoerg 16122499Sjoerg return retval; 16218962Ssos} 16318962Ssos 16426837Scharnierstatic void 16587248Smarkmusage(void) 16618962Ssos{ 167146466Sru (void)fprintf(stderr, 168146466Sru "usage: brandelf [-lv] [-f ELF_ABI_number] [-t string] file ...\n"); 16922499Sjoerg exit(1); 17018962Ssos} 17135364Seivind 17259342Sobrienstatic const char * 17378627Sobrieniselftype(int etype) 17459342Sobrien{ 17578627Sobrien size_t elfwalk; 17655377Swes 17759342Sobrien for (elfwalk = 0; 17859342Sobrien elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 17959342Sobrien elfwalk++) 18078627Sobrien if (etype == elftypes[elfwalk].value) 18159342Sobrien return elftypes[elfwalk].str; 18259342Sobrien return 0; 18359342Sobrien} 18459342Sobrien 18535366Seivindstatic int 18659342Sobrienelftype(const char *elfstrtype) 18755377Swes{ 18878627Sobrien size_t elfwalk; 18935364Seivind 19035364Seivind for (elfwalk = 0; 19135364Seivind elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 19235364Seivind elfwalk++) 193145807Sgreen if (strcasecmp(elfstrtype, elftypes[elfwalk].str) == 0) 19459342Sobrien return elftypes[elfwalk].value; 19559342Sobrien return -1; 19635364Seivind} 19755377Swes 19855377Swesstatic void 19987248Smarkmprintelftypes(void) 20055377Swes{ 20178627Sobrien size_t elfwalk; 20255377Swes 20355377Swes fprintf(stderr, "known ELF types are: "); 20455377Swes for (elfwalk = 0; 20555377Swes elfwalk < sizeof(elftypes)/sizeof(elftypes[0]); 20655377Swes elfwalk++) 20759342Sobrien fprintf(stderr, "%s(%u) ", elftypes[elfwalk].str, 20859342Sobrien elftypes[elfwalk].value); 20955377Swes fprintf(stderr, "\n"); 21055377Swes} 211