brandelf.c revision 62313
118962Ssos/*-
218962Ssos * Copyright (c) 1996 S�ren Schmidt
318962Ssos * All rights reserved.
418962Ssos *
518962Ssos * Redistribution and use in source and binary forms, with or without
618962Ssos * modification, are permitted provided that the following conditions
718962Ssos * are met:
818962Ssos * 1. Redistributions of source code must retain the above copyright
918962Ssos *    notice, this list of conditions and the following disclaimer
1018962Ssos *    in this position and unchanged.
1118962Ssos * 2. Redistributions in binary form must reproduce the above copyright
1218962Ssos *    notice, this list of conditions and the following disclaimer in the
1318962Ssos *    documentation and/or other materials provided with the distribution.
1418962Ssos * 3. The name of the author may not be used to endorse or promote products
1518962Ssos *    derived from this software withough specific prior written permission
1618962Ssos *
1718962Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1818962Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1918962Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2018962Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2118962Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2218962Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2318962Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2418962Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2518962Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2618962Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2718962Ssos *
2850477Speter * $FreeBSD: head/usr.bin/brandelf/brandelf.c 62313 2000-07-01 05:48:33Z green $
2918962Ssos */
3018962Ssos
3125984Sjdp#include <elf.h>
3225984Sjdp#include <fcntl.h>
3325984Sjdp#include <stdio.h>
3418962Ssos#include <stdlib.h>
3522499Sjoerg#include <string.h>
3622499Sjoerg#include <unistd.h>
3759342Sobrien#include <sys/errno.h>
3826837Scharnier#include <err.h>
3918962Ssos
4059342Sobrienstatic int elftype(const char *);
4159342Sobrienstatic const char *iselftype(int);
4255377Swesstatic void printelftypes(void);
4326837Scharnierstatic void usage __P((void));
4418962Ssos
4559342Sobrienstruct ELFtypes {
4659342Sobrien	const char *str;
4759342Sobrien	int value;
4859342Sobrien};
4959342Sobrien/* XXX - any more types? */
5059342Sobrienstatic struct ELFtypes elftypes[] = {
5159342Sobrien	{ "FreeBSD",	ELFOSABI_FREEBSD },
5262313Sgreen	{ "Linux",	ELFOSABI_LINUX },
5362313Sgreen	{ "Solaris",	ELFOSABI_SOLARIS },
5462313Sgreen	{ "SVR4",	ELFOSABI_SYSV }
5559342Sobrien};
5659342Sobrien
5722499Sjoergint
5818962Ssosmain(int argc, char **argv)
5918962Ssos{
6018962Ssos
6159342Sobrien	const char *strtype = "FreeBSD";
6259342Sobrien	int type = ELFOSABI_FREEBSD;
6322499Sjoerg	int retval = 0;
6455377Swes	int ch, change = 0, verbose = 0, force = 0, listed = 0;
6518962Ssos
6659342Sobrien	while ((ch = getopt(argc, argv, "f:lt:v")) != -1)
6718962Ssos		switch (ch) {
6835364Seivind		case 'f':
6959342Sobrien			if (change)
7059342Sobrien				errx(1, "f option incompatable with t option");
7135364Seivind			force = 1;
7259342Sobrien			type = atoi(optarg);
7359342Sobrien			if (errno == ERANGE || type < 0 || type > 255) {
7459342Sobrien				warnx("invalid argument to option f: %s",
7559342Sobrien				    optarg);
7659342Sobrien				usage();
7759342Sobrien			}
7835364Seivind			break;
7955377Swes		case 'l':
8055377Swes			printelftypes();
8155377Swes			listed = 1;
8255377Swes			break;
8318962Ssos		case 'v':
8418962Ssos			verbose = 1;
8518962Ssos			break;
8618962Ssos		case 't':
8759342Sobrien			if (force)
8859342Sobrien				errx(1, "t option incompatable with f option");
8918962Ssos			change = 1;
9059342Sobrien			strtype = optarg;
9118962Ssos			break;
9218962Ssos		default:
9318962Ssos			usage();
9418962Ssos	}
9518962Ssos	argc -= optind;
9618962Ssos	argv += optind;
9755377Swes	if (!argc) {
9855377Swes		if (listed)
9955377Swes			exit(0);
10055377Swes		else {
10155377Swes			warnx("no file(s) specified");
10255377Swes			usage();
10355377Swes		}
10455377Swes	}
10535364Seivind
10659342Sobrien	if (!force && (type = elftype(strtype)) == -1) {
10759342Sobrien		warnx("invalid ELF type '%s'", strtype);
10855377Swes		printelftypes();
10955377Swes		usage();
11055377Swes	}
11135364Seivind
11218962Ssos	while (argc) {
11318962Ssos		int fd;
11425984Sjdp		char buffer[EI_NIDENT];
11518962Ssos
11659342Sobrien		if ((fd = open(argv[0], change || force ? O_RDWR : O_RDONLY, 0)) < 0) {
11728620Sjoerg			warn("error opening file %s", argv[0]);
11822499Sjoerg			retval = 1;
11918962Ssos			goto fail;
12018962Ssos		}
12125984Sjdp		if (read(fd, buffer, EI_NIDENT) < EI_NIDENT) {
12226837Scharnier			warnx("file '%s' too short", argv[0]);
12322499Sjoerg			retval = 1;
12418962Ssos			goto fail;
12518962Ssos		}
12618962Ssos		if (buffer[0] != ELFMAG0 || buffer[1] != ELFMAG1 ||
12718962Ssos		    buffer[2] != ELFMAG2 || buffer[3] != ELFMAG3) {
12826837Scharnier			warnx("file '%s' is not ELF format", argv[0]);
12922499Sjoerg			retval = 1;
13018962Ssos			goto fail;
13135364Seivind		}
13259342Sobrien		if (!change && !force) {
13359342Sobrien			fprintf(stdout,
13459342Sobrien				"File '%s' is of brand '%s' (%u).\n",
13559342Sobrien				argv[0], iselftype(buffer[EI_OSABI]),
13659342Sobrien				buffer[EI_OSABI]);
13759342Sobrien			if (!iselftype(type)) {
13859342Sobrien				warnx("ELF ABI Brand '%u' is unknown",
13959342Sobrien				      type);
14059342Sobrien				printelftypes();
14118962Ssos			}
14218962Ssos		}
14318962Ssos		else {
14459342Sobrien			buffer[EI_OSABI] = type;
14518962Ssos			lseek(fd, 0, SEEK_SET);
14625984Sjdp			if (write(fd, buffer, EI_NIDENT) != EI_NIDENT) {
14759342Sobrien				warn("error writing %s %d", argv[0], fd);
14826837Scharnier				retval = 1;
14918962Ssos				goto fail;
15018962Ssos			}
15118962Ssos		}
15218962Ssosfail:
15318962Ssos		argc--;
15418962Ssos		argv++;
15518962Ssos	}
15622499Sjoerg
15722499Sjoerg	return retval;
15818962Ssos}
15918962Ssos
16026837Scharnierstatic void
16126837Scharnierusage()
16218962Ssos{
16359342Sobrienfprintf(stderr, "usage: brandelf [-f ELF ABI number] [-v] [-l] [-t string] file ...\n");
16422499Sjoerg	exit(1);
16518962Ssos}
16635364Seivind
16759342Sobrienstatic const char *
16859342Sobrieniselftype(int elftype)
16959342Sobrien{
17059342Sobrien	int elfwalk;
17155377Swes
17259342Sobrien	for (elfwalk = 0;
17359342Sobrien	     elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
17459342Sobrien	     elfwalk++)
17559342Sobrien		if (elftype == elftypes[elfwalk].value)
17659342Sobrien			return elftypes[elfwalk].str;
17759342Sobrien	return 0;
17859342Sobrien}
17959342Sobrien
18035366Seivindstatic int
18159342Sobrienelftype(const char *elfstrtype)
18255377Swes{
18335364Seivind	int elfwalk;
18435364Seivind
18535364Seivind	for (elfwalk = 0;
18635364Seivind	     elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
18735364Seivind	     elfwalk++)
18859342Sobrien		if (strcmp(elfstrtype, elftypes[elfwalk].str) == 0)
18959342Sobrien			return elftypes[elfwalk].value;
19059342Sobrien	return -1;
19135364Seivind}
19255377Swes
19355377Swesstatic void
19455377Swesprintelftypes()
19555377Swes{
19655377Swes	int elfwalk;
19755377Swes
19855377Swes	fprintf(stderr, "known ELF types are: ");
19955377Swes	for (elfwalk = 0;
20055377Swes	     elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
20155377Swes	     elfwalk++)
20259342Sobrien		fprintf(stderr, "%s(%u) ", elftypes[elfwalk].str,
20359342Sobrien			elftypes[elfwalk].value);
20455377Swes	fprintf(stderr, "\n");
20555377Swes}
206