brandelf.c revision 87248
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
1618962Ssos *    derived from this software withough 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>
3176225Sobrien
3287248Smarkm__FBSDID("$FreeBSD: head/usr.bin/brandelf/brandelf.c 87248 2001-12-03 00:00:22Z markm $");
3387248Smarkm
3476224Sobrien#include <sys/types.h>
3576224Sobrien#include <sys/elf_common.h>
3687248Smarkm#include <sys/errno.h>
3787248Smarkm#include <err.h>
3825984Sjdp#include <fcntl.h>
3925984Sjdp#include <stdio.h>
4018962Ssos#include <stdlib.h>
4122499Sjoerg#include <string.h>
4222499Sjoerg#include <unistd.h>
4318962Ssos
4459342Sobrienstatic int elftype(const char *);
4559342Sobrienstatic const char *iselftype(int);
4655377Swesstatic void printelftypes(void);
4787248Smarkmstatic void usage(void);
4818962Ssos
4959342Sobrienstruct ELFtypes {
5059342Sobrien	const char *str;
5159342Sobrien	int value;
5259342Sobrien};
5359342Sobrien/* XXX - any more types? */
5459342Sobrienstatic struct ELFtypes elftypes[] = {
5559342Sobrien	{ "FreeBSD",	ELFOSABI_FREEBSD },
5662313Sgreen	{ "Linux",	ELFOSABI_LINUX },
5762313Sgreen	{ "Solaris",	ELFOSABI_SOLARIS },
5862313Sgreen	{ "SVR4",	ELFOSABI_SYSV }
5959342Sobrien};
6059342Sobrien
6122499Sjoergint
6218962Ssosmain(int argc, char **argv)
6318962Ssos{
6418962Ssos
6559342Sobrien	const char *strtype = "FreeBSD";
6659342Sobrien	int type = ELFOSABI_FREEBSD;
6722499Sjoerg	int retval = 0;
6855377Swes	int ch, change = 0, verbose = 0, force = 0, listed = 0;
6918962Ssos
7059342Sobrien	while ((ch = getopt(argc, argv, "f:lt:v")) != -1)
7118962Ssos		switch (ch) {
7235364Seivind		case 'f':
7359342Sobrien			if (change)
7472093Sasmodai				errx(1, "f option incompatible with t option");
7535364Seivind			force = 1;
7659342Sobrien			type = atoi(optarg);
7759342Sobrien			if (errno == ERANGE || type < 0 || type > 255) {
7859342Sobrien				warnx("invalid argument to option f: %s",
7959342Sobrien				    optarg);
8059342Sobrien				usage();
8159342Sobrien			}
8235364Seivind			break;
8355377Swes		case 'l':
8455377Swes			printelftypes();
8555377Swes			listed = 1;
8655377Swes			break;
8718962Ssos		case 'v':
8818962Ssos			verbose = 1;
8918962Ssos			break;
9018962Ssos		case 't':
9159342Sobrien			if (force)
9272093Sasmodai				errx(1, "t option incompatible with f option");
9318962Ssos			change = 1;
9459342Sobrien			strtype = optarg;
9518962Ssos			break;
9618962Ssos		default:
9718962Ssos			usage();
9818962Ssos	}
9918962Ssos	argc -= optind;
10018962Ssos	argv += optind;
10155377Swes	if (!argc) {
10255377Swes		if (listed)
10355377Swes			exit(0);
10455377Swes		else {
10555377Swes			warnx("no file(s) specified");
10655377Swes			usage();
10755377Swes		}
10855377Swes	}
10935364Seivind
11059342Sobrien	if (!force && (type = elftype(strtype)) == -1) {
11159342Sobrien		warnx("invalid ELF type '%s'", strtype);
11255377Swes		printelftypes();
11355377Swes		usage();
11455377Swes	}
11535364Seivind
11618962Ssos	while (argc) {
11718962Ssos		int fd;
11825984Sjdp		char buffer[EI_NIDENT];
11918962Ssos
12059342Sobrien		if ((fd = open(argv[0], change || force ? O_RDWR : O_RDONLY, 0)) < 0) {
12128620Sjoerg			warn("error opening file %s", argv[0]);
12222499Sjoerg			retval = 1;
12318962Ssos			goto fail;
12418962Ssos		}
12525984Sjdp		if (read(fd, buffer, EI_NIDENT) < EI_NIDENT) {
12626837Scharnier			warnx("file '%s' too short", argv[0]);
12722499Sjoerg			retval = 1;
12818962Ssos			goto fail;
12918962Ssos		}
13018962Ssos		if (buffer[0] != ELFMAG0 || buffer[1] != ELFMAG1 ||
13118962Ssos		    buffer[2] != ELFMAG2 || buffer[3] != ELFMAG3) {
13226837Scharnier			warnx("file '%s' is not ELF format", argv[0]);
13322499Sjoerg			retval = 1;
13418962Ssos			goto fail;
13535364Seivind		}
13659342Sobrien		if (!change && !force) {
13759342Sobrien			fprintf(stdout,
13859342Sobrien				"File '%s' is of brand '%s' (%u).\n",
13959342Sobrien				argv[0], iselftype(buffer[EI_OSABI]),
14059342Sobrien				buffer[EI_OSABI]);
14159342Sobrien			if (!iselftype(type)) {
14259342Sobrien				warnx("ELF ABI Brand '%u' is unknown",
14359342Sobrien				      type);
14459342Sobrien				printelftypes();
14518962Ssos			}
14618962Ssos		}
14718962Ssos		else {
14859342Sobrien			buffer[EI_OSABI] = type;
14918962Ssos			lseek(fd, 0, SEEK_SET);
15025984Sjdp			if (write(fd, buffer, EI_NIDENT) != EI_NIDENT) {
15159342Sobrien				warn("error writing %s %d", argv[0], fd);
15226837Scharnier				retval = 1;
15318962Ssos				goto fail;
15418962Ssos			}
15518962Ssos		}
15618962Ssosfail:
15762375Simp		close(fd);
15818962Ssos		argc--;
15918962Ssos		argv++;
16018962Ssos	}
16122499Sjoerg
16222499Sjoerg	return retval;
16318962Ssos}
16418962Ssos
16526837Scharnierstatic void
16687248Smarkmusage(void)
16718962Ssos{
16859342Sobrienfprintf(stderr, "usage: brandelf [-f ELF ABI number] [-v] [-l] [-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++)
19359342Sobrien		if (strcmp(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