brandelf.c revision 295577
1260684Skaiw/*-
2260684Skaiw * Copyright (c) 2008 Hyogeol Lee
3260684Skaiw * Copyright (c) 2000, 2001 David O'Brien
4289071Semaste * Copyright (c) 1996 S��ren Schmidt
5260684Skaiw * All rights reserved.
6260684Skaiw *
7260684Skaiw * Redistribution and use in source and binary forms, with or without
8260684Skaiw * modification, are permitted provided that the following conditions
9260684Skaiw * are met:
10260684Skaiw * 1. Redistributions of source code must retain the above copyright
11260684Skaiw *    notice, this list of conditions and the following disclaimer
12260684Skaiw *    in this position and unchanged.
13260684Skaiw * 2. Redistributions in binary form must reproduce the above copyright
14260684Skaiw *    notice, this list of conditions and the following disclaimer in the
15260684Skaiw *    documentation and/or other materials provided with the distribution.
16260684Skaiw * 3. The name of the author may not be used to endorse or promote products
17260684Skaiw *    derived from this software without specific prior written permission
18260684Skaiw *
19260684Skaiw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20260684Skaiw * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21260684Skaiw * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22260684Skaiw * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23260684Skaiw * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24260684Skaiw * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25260684Skaiw * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26260684Skaiw * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27260684Skaiw * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28260684Skaiw * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29260684Skaiw */
30260684Skaiw
31260684Skaiw#include <sys/types.h>
32260684Skaiw#include <sys/stat.h>
33260684Skaiw#include <err.h>
34260684Skaiw#include <errno.h>
35260684Skaiw#include <fcntl.h>
36260684Skaiw#include <gelf.h>
37260684Skaiw#include <getopt.h>
38260684Skaiw#include <libelf.h>
39260684Skaiw#include <libelftc.h>
40260684Skaiw#include <stdio.h>
41260684Skaiw#include <stdlib.h>
42260684Skaiw#include <string.h>
43260684Skaiw#include <unistd.h>
44260684Skaiw
45260684Skaiw#include "_elftc.h"
46260684Skaiw
47295577SemasteELFTC_VCSID("$Id: brandelf.c 3354 2016-01-18 21:50:15Z jkoshy $");
48260684Skaiw
49260684Skaiwstatic int elftype(const char *);
50260684Skaiwstatic const char *iselftype(int);
51260684Skaiwstatic void printelftypes(void);
52260684Skaiwstatic void printversion(void);
53260684Skaiwstatic void usage(void);
54260684Skaiw
55260684Skaiwstruct ELFtypes {
56260684Skaiw	const char *str;
57260684Skaiw	int value;
58260684Skaiw};
59260684Skaiw/* XXX - any more types? */
60260684Skaiwstatic struct ELFtypes elftypes[] = {
61260684Skaiw	{ "86Open",	ELFOSABI_86OPEN },
62260684Skaiw	{ "AIX",	ELFOSABI_AIX },
63260684Skaiw	{ "ARM",	ELFOSABI_ARM },
64260684Skaiw	{ "AROS",	ELFOSABI_AROS },
65260684Skaiw	{ "FreeBSD",	ELFOSABI_FREEBSD },
66260684Skaiw	{ "GNU",	ELFOSABI_GNU },
67260684Skaiw	{ "HP/UX",	ELFOSABI_HPUX},
68260684Skaiw	{ "Hurd",	ELFOSABI_HURD },
69260684Skaiw	{ "IRIX",	ELFOSABI_IRIX },
70260684Skaiw	{ "Linux",	ELFOSABI_GNU },
71260684Skaiw	{ "Modesto",	ELFOSABI_MODESTO },
72260684Skaiw	{ "NSK",	ELFOSABI_NSK },
73260684Skaiw	{ "NetBSD",	ELFOSABI_NETBSD},
74260684Skaiw	{ "None",	ELFOSABI_NONE},
75260684Skaiw	{ "OpenBSD",	ELFOSABI_OPENBSD },
76260684Skaiw	{ "OpenVMS",	ELFOSABI_OPENVMS },
77260684Skaiw	{ "Standalone",	ELFOSABI_STANDALONE },
78260684Skaiw	{ "SVR4",	ELFOSABI_NONE },
79260684Skaiw	{ "Solaris",	ELFOSABI_SOLARIS },
80260684Skaiw	{ "Tru64",	ELFOSABI_TRU64 }
81260684Skaiw};
82260684Skaiw
83260684Skaiwstatic struct option brandelf_longopts[] = {
84260684Skaiw	{ "help",	no_argument,	NULL,   'h' },
85260684Skaiw	{ "version",	no_argument,	NULL, 	'V' },
86260684Skaiw	{ NULL,		0,		NULL,	0   }
87260684Skaiw};
88260684Skaiw
89260684Skaiwint
90260684Skaiwmain(int argc, char **argv)
91260684Skaiw{
92260684Skaiw	GElf_Ehdr ehdr;
93260684Skaiw	Elf *elf;
94260684Skaiw	Elf_Kind kind;
95260684Skaiw	int type = ELFOSABI_NONE;
96260684Skaiw	int retval = 0;
97276077Semaste	int ch, change = 0, force = 0, listed = 0;
98260684Skaiw
99260684Skaiw	if (elf_version(EV_CURRENT) == EV_NONE)
100260684Skaiw		errx(EXIT_FAILURE, "elf_version error");
101260684Skaiw
102260684Skaiw	while ((ch = getopt_long(argc, argv, "Vf:hlt:v", brandelf_longopts,
103260684Skaiw		NULL)) != -1)
104260684Skaiw		switch (ch) {
105260684Skaiw		case 'f':
106260684Skaiw			if (change)
107260684Skaiw				errx(EXIT_FAILURE, "ERROR: the -f option is "
108260684Skaiw				    "incompatible with the -t option.");
109260684Skaiw			force = 1;
110260684Skaiw			type = atoi(optarg);
111260684Skaiw			if (errno == ERANGE || type < 0 || type > 255) {
112260684Skaiw				warnx("ERROR: invalid argument to option "
113260684Skaiw				    "-f: %s", optarg);
114260684Skaiw				usage();
115260684Skaiw			}
116260684Skaiw			break;
117260684Skaiw		case 'h':
118260684Skaiw			usage();
119260684Skaiw			break;
120260684Skaiw		case 'l':
121260684Skaiw			printelftypes();
122260684Skaiw			listed = 1;
123260684Skaiw			break;
124260684Skaiw		case 'v':
125276077Semaste			/* This flag is ignored. */
126260684Skaiw			break;
127260684Skaiw		case 't':
128260684Skaiw			if (force)
129260684Skaiw				errx(EXIT_FAILURE, "the -t option is "
130260684Skaiw				    "incompatible with the -f option.");
131260684Skaiw			if ((type = elftype(optarg)) == -1) {
132260684Skaiw				warnx("ERROR: invalid ELF type '%s'", optarg);
133260684Skaiw				usage();
134260684Skaiw			}
135260684Skaiw
136260684Skaiw			change = 1;
137260684Skaiw			break;
138260684Skaiw		case 'V':
139260684Skaiw			printversion();
140260684Skaiw			break;
141260684Skaiw		default:
142260684Skaiw			usage();
143260684Skaiw	}
144260684Skaiw	argc -= optind;
145260684Skaiw	argv += optind;
146260684Skaiw	if (!argc) {
147260684Skaiw		if (listed)
148260684Skaiw			exit(0);
149260684Skaiw		else {
150260684Skaiw			warnx("no file(s) specified");
151260684Skaiw			usage();
152260684Skaiw		}
153260684Skaiw	}
154260684Skaiw
155260684Skaiw	while (argc) {
156260684Skaiw		int fd;
157260684Skaiw
158260684Skaiw		elf = NULL;
159260684Skaiw
160260684Skaiw		if ((fd = open(argv[0], (change || force) ? O_RDWR :
161260684Skaiw		    O_RDONLY, 0)) < 0) {
162260684Skaiw			warn("error opening file %s", argv[0]);
163260684Skaiw			retval = 1;
164260684Skaiw			goto fail;
165260684Skaiw		}
166260684Skaiw
167260684Skaiw		if ((elf = elf_begin(fd, (change || force) ? ELF_C_RDWR :
168260684Skaiw		    ELF_C_READ, NULL)) == NULL) {
169260684Skaiw			warnx("elf_begin failed: %s", elf_errmsg(-1));
170260684Skaiw			retval = 1;
171260684Skaiw			goto fail;
172260684Skaiw		}
173260684Skaiw
174260684Skaiw		if ((kind = elf_kind(elf)) != ELF_K_ELF) {
175260684Skaiw			if (kind == ELF_K_AR)
176260684Skaiw				warnx("file '%s' is an archive.", argv[0]);
177260684Skaiw			else
178260684Skaiw				warnx("file '%s' is not an ELF file.",
179260684Skaiw				    argv[0]);
180260684Skaiw			retval = 1;
181260684Skaiw			goto fail;
182260684Skaiw		}
183260684Skaiw
184260684Skaiw		if (gelf_getehdr(elf, &ehdr) == NULL) {
185260684Skaiw			warnx("gelf_getehdr: %s", elf_errmsg(-1));
186260684Skaiw			retval = 1;
187260684Skaiw			goto fail;
188260684Skaiw		}
189260684Skaiw
190260684Skaiw		if (!change && !force) {
191260684Skaiw			fprintf(stdout,
192260684Skaiw			    "File '%s' is of brand '%s' (%u).\n",
193260684Skaiw			    argv[0], iselftype(ehdr.e_ident[EI_OSABI]),
194260684Skaiw			    ehdr.e_ident[EI_OSABI]);
195260684Skaiw			if (!iselftype(type)) {
196260684Skaiw				warnx("ELF ABI Brand '%u' is unknown",
197260684Skaiw				      type);
198260684Skaiw				printelftypes();
199260684Skaiw			}
200260684Skaiw		} else {
201260684Skaiw
202260684Skaiw			/*
203260684Skaiw			 * Keep the existing layout of the ELF object.
204260684Skaiw			 */
205260684Skaiw			if (elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT) == 0) {
206260684Skaiw				warnx("elf_flagelf failed: %s",
207260684Skaiw				    elf_errmsg(-1));
208260684Skaiw				retval = 1;
209260684Skaiw				goto fail;
210260684Skaiw			}
211260684Skaiw
212260684Skaiw			/*
213260684Skaiw			 * Update the ABI type.
214260684Skaiw			 */
215295577Semaste			ehdr.e_ident[EI_OSABI] = (unsigned char) type;
216260684Skaiw			if (gelf_update_ehdr(elf, &ehdr) == 0) {
217260684Skaiw				warnx("gelf_update_ehdr error: %s",
218260684Skaiw				    elf_errmsg(-1));
219260684Skaiw				retval = 1;
220260684Skaiw				goto fail;
221260684Skaiw			}
222260684Skaiw
223260684Skaiw			/*
224260684Skaiw			 * Write back changes.
225260684Skaiw			 */
226260684Skaiw			if (elf_update(elf, ELF_C_WRITE) == -1) {
227260684Skaiw				warnx("elf_update error: %s", elf_errmsg(-1));
228260684Skaiw				retval = 1;
229260684Skaiw				goto fail;
230260684Skaiw			}
231260684Skaiw		}
232260684Skaiwfail:
233260684Skaiw
234260684Skaiw		if (elf)
235260684Skaiw			elf_end(elf);
236260684Skaiw
237260684Skaiw		if (fd >= 0 && close(fd) == -1) {
238260684Skaiw			warnx("%s: close error", argv[0]);
239260684Skaiw			retval = 1;
240260684Skaiw		}
241260684Skaiw
242260684Skaiw		argc--;
243260684Skaiw		argv++;
244260684Skaiw	}
245260684Skaiw
246260684Skaiw	return (retval);
247260684Skaiw}
248260684Skaiw
249260684Skaiw#define	USAGE_MESSAGE	"\
250260684SkaiwUsage: %s [options] file...\n\
251260684Skaiw  Set or display the ABI field for an ELF object.\n\n\
252260684Skaiw  Supported options are:\n\
253260684Skaiw  -f NUM                    Set the ELF ABI to the number 'NUM'.\n\
254260684Skaiw  -h | --help               Print a usage message and exit.\n\
255260684Skaiw  -l                        List known ELF ABI names.\n\
256260684Skaiw  -t ABI                    Set the ELF ABI to the value named by \"ABI\".\n\
257260684Skaiw  -V | --version            Print a version identifier and exit.\n"
258260684Skaiw
259260684Skaiwstatic void
260260684Skaiwusage(void)
261260684Skaiw{
262260684Skaiw	(void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
263260684Skaiw	exit(1);
264260684Skaiw}
265260684Skaiw
266260684Skaiwstatic void
267260684Skaiwprintversion(void)
268260684Skaiw{
269260684Skaiw	(void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());
270260684Skaiw	exit(0);
271260684Skaiw}
272260684Skaiw
273260684Skaiwstatic const char *
274260684Skaiwiselftype(int etype)
275260684Skaiw{
276260684Skaiw	size_t elfwalk;
277260684Skaiw
278260684Skaiw	for (elfwalk = 0;
279260684Skaiw	     elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
280260684Skaiw	     elfwalk++)
281260684Skaiw		if (etype == elftypes[elfwalk].value)
282260684Skaiw			return (elftypes[elfwalk].str);
283260684Skaiw	return (0);
284260684Skaiw}
285260684Skaiw
286260684Skaiwstatic int
287260684Skaiwelftype(const char *elfstrtype)
288260684Skaiw{
289260684Skaiw	size_t elfwalk;
290260684Skaiw
291260684Skaiw	for (elfwalk = 0;
292260684Skaiw	     elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
293260684Skaiw	     elfwalk++)
294260684Skaiw		if (strcasecmp(elfstrtype, elftypes[elfwalk].str) == 0)
295260684Skaiw			return (elftypes[elfwalk].value);
296260684Skaiw	return (-1);
297260684Skaiw}
298260684Skaiw
299260684Skaiwstatic void
300260684Skaiwprintelftypes(void)
301260684Skaiw{
302260684Skaiw	size_t elfwalk;
303260684Skaiw
304260684Skaiw	(void) printf("Known ELF types are: ");
305260684Skaiw	for (elfwalk = 0;
306260684Skaiw	     elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
307260684Skaiw	     elfwalk++)
308260684Skaiw		(void) printf("%s(%u) ", elftypes[elfwalk].str,
309260684Skaiw		    elftypes[elfwalk].value);
310260684Skaiw	(void) printf("\n");
311260684Skaiw}
312