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