Path: blob/main/contrib/elftoolchain/brandelf/brandelf.c
39488 views
/*-1* Copyright (c) 2008 Hyogeol Lee2* Copyright (c) 2000, 2001 David O'Brien3* Copyright (c) 1996 Søren Schmidt4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer11* in this position and unchanged.12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15* 3. The name of the author may not be used to endorse or promote products16* derived from this software without specific prior written permission17*18* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR19* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES20* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.21* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,22* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT23* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,24* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY25* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT26* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF27* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.28*/2930#include <sys/types.h>31#include <sys/stat.h>32#include <err.h>33#include <errno.h>34#include <fcntl.h>35#include <gelf.h>36#include <getopt.h>37#include <libelf.h>38#include <libelftc.h>39#include <stdio.h>40#include <stdlib.h>41#include <string.h>42#include <unistd.h>4344#include "_elftc.h"4546ELFTC_VCSID("$Id: brandelf.c 3440 2016-04-07 14:51:47Z emaste $");4748static int elftype(const char *);49static const char *iselftype(int);50static void printelftypes(void);51static void printversion(void);52static void usage(void);5354struct ELFtypes {55const char *str;56int value;57};58/* XXX - any more types? */59static struct ELFtypes elftypes[] = {60{ "86Open", ELFOSABI_86OPEN },61{ "AIX", ELFOSABI_AIX },62{ "ARM", ELFOSABI_ARM },63{ "AROS", ELFOSABI_AROS },64{ "CloudABI", ELFOSABI_CLOUDABI },65{ "FreeBSD", ELFOSABI_FREEBSD },66{ "GNU", ELFOSABI_GNU },67{ "HP/UX", ELFOSABI_HPUX},68{ "Hurd", ELFOSABI_HURD },69{ "IRIX", ELFOSABI_IRIX },70{ "Linux", ELFOSABI_GNU },71{ "Modesto", ELFOSABI_MODESTO },72{ "NSK", ELFOSABI_NSK },73{ "NetBSD", ELFOSABI_NETBSD},74{ "None", ELFOSABI_NONE},75{ "OpenBSD", ELFOSABI_OPENBSD },76{ "OpenVMS", ELFOSABI_OPENVMS },77{ "Standalone", ELFOSABI_STANDALONE },78{ "SVR4", ELFOSABI_NONE },79{ "Solaris", ELFOSABI_SOLARIS },80{ "Tru64", ELFOSABI_TRU64 }81};8283static struct option brandelf_longopts[] = {84{ "help", no_argument, NULL, 'h' },85{ "version", no_argument, NULL, 'V' },86{ NULL, 0, NULL, 0 }87};8889int90main(int argc, char **argv)91{92GElf_Ehdr ehdr;93Elf *elf;94Elf_Kind kind;95int type = ELFOSABI_NONE;96int retval = 0;97int ch, change = 0, force = 0, listed = 0;9899if (elf_version(EV_CURRENT) == EV_NONE)100errx(EXIT_FAILURE, "elf_version error");101102while ((ch = getopt_long(argc, argv, "Vf:hlt:v", brandelf_longopts,103NULL)) != -1)104switch (ch) {105case 'f':106if (change)107errx(EXIT_FAILURE, "ERROR: the -f option is "108"incompatible with the -t option.");109force = 1;110type = atoi(optarg);111if (errno == ERANGE || type < 0 || type > 255) {112warnx("ERROR: invalid argument to option "113"-f: %s", optarg);114usage();115}116break;117case 'h':118usage();119break;120case 'l':121printelftypes();122listed = 1;123break;124case 'v':125/* This flag is ignored. */126break;127case 't':128if (force)129errx(EXIT_FAILURE, "the -t option is "130"incompatible with the -f option.");131if ((type = elftype(optarg)) == -1) {132warnx("ERROR: invalid ELF type '%s'", optarg);133usage();134}135136change = 1;137break;138case 'V':139printversion();140break;141default:142usage();143}144argc -= optind;145argv += optind;146if (!argc) {147if (listed)148exit(0);149else {150warnx("no file(s) specified");151usage();152}153}154155while (argc) {156int fd;157158elf = NULL;159160if ((fd = open(argv[0], (change || force) ? O_RDWR :161O_RDONLY, 0)) < 0) {162warn("error opening file %s", argv[0]);163retval = 1;164goto fail;165}166167if ((elf = elf_begin(fd, (change || force) ? ELF_C_RDWR :168ELF_C_READ, NULL)) == NULL) {169warnx("elf_begin failed: %s", elf_errmsg(-1));170retval = 1;171goto fail;172}173174if ((kind = elf_kind(elf)) != ELF_K_ELF) {175if (kind == ELF_K_AR)176warnx("file '%s' is an archive.", argv[0]);177else178warnx("file '%s' is not an ELF file.",179argv[0]);180retval = 1;181goto fail;182}183184if (gelf_getehdr(elf, &ehdr) == NULL) {185warnx("gelf_getehdr: %s", elf_errmsg(-1));186retval = 1;187goto fail;188}189190if (!change && !force) {191fprintf(stdout,192"File '%s' is of brand '%s' (%u).\n",193argv[0], iselftype(ehdr.e_ident[EI_OSABI]),194ehdr.e_ident[EI_OSABI]);195if (!iselftype(type)) {196warnx("ELF ABI Brand '%u' is unknown",197type);198printelftypes();199}200} else {201202/*203* Keep the existing layout of the ELF object.204*/205if (elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT) == 0) {206warnx("elf_flagelf failed: %s",207elf_errmsg(-1));208retval = 1;209goto fail;210}211212/*213* Update the ABI type.214*/215ehdr.e_ident[EI_OSABI] = (unsigned char) type;216if (gelf_update_ehdr(elf, &ehdr) == 0) {217warnx("gelf_update_ehdr error: %s",218elf_errmsg(-1));219retval = 1;220goto fail;221}222223/*224* Write back changes.225*/226if (elf_update(elf, ELF_C_WRITE) == -1) {227warnx("elf_update error: %s", elf_errmsg(-1));228retval = 1;229goto fail;230}231}232fail:233234if (elf)235elf_end(elf);236237if (fd >= 0 && close(fd) == -1) {238warnx("%s: close error", argv[0]);239retval = 1;240}241242argc--;243argv++;244}245246return (retval);247}248249#define USAGE_MESSAGE "\250Usage: %s [options] file...\n\251Set or display the ABI field for an ELF object.\n\n\252Supported options are:\n\253-f NUM Set the ELF ABI to the number 'NUM'.\n\254-h | --help Print a usage message and exit.\n\255-l List known ELF ABI names.\n\256-t ABI Set the ELF ABI to the value named by \"ABI\".\n\257-V | --version Print a version identifier and exit.\n"258259static void260usage(void)261{262(void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());263exit(1);264}265266static void267printversion(void)268{269(void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());270exit(0);271}272273static const char *274iselftype(int etype)275{276size_t elfwalk;277278for (elfwalk = 0;279elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);280elfwalk++)281if (etype == elftypes[elfwalk].value)282return (elftypes[elfwalk].str);283return (0);284}285286static int287elftype(const char *elfstrtype)288{289size_t elfwalk;290291for (elfwalk = 0;292elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);293elfwalk++)294if (strcasecmp(elfstrtype, elftypes[elfwalk].str) == 0)295return (elftypes[elfwalk].value);296return (-1);297}298299static void300printelftypes(void)301{302size_t elfwalk;303304(void) printf("Known ELF types are: ");305for (elfwalk = 0;306elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);307elfwalk++)308(void) printf("%s(%u) ", elftypes[elfwalk].str,309elftypes[elfwalk].value);310(void) printf("\n");311}312313314