xref: /freebsd/usr.bin/brandelf/brandelf.c (revision 23f282aa31e9b6fceacd449020e936e98d6f2298)
1 /*-
2  * Copyright (c) 1996 S�ren Schmidt
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer
10  *    in this position and unchanged.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software withough specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30 
31 #include <elf.h>
32 #include <fcntl.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <sys/errno.h>
38 #include <err.h>
39 
40 static int elftype(const char *);
41 static const char *iselftype(int);
42 static void printelftypes(void);
43 static void usage __P((void));
44 
45 struct ELFtypes {
46 	const char *str;
47 	int value;
48 };
49 /* XXX - any more types? */
50 static struct ELFtypes elftypes[] = {
51 	{ "FreeBSD",	ELFOSABI_FREEBSD },
52 	{ "SVR4",	ELFOSABI_SYSV },
53 	{ "Linux",	ELFOSABI_LINUX }
54 };
55 
56 int
57 main(int argc, char **argv)
58 {
59 
60 	const char *strtype = "FreeBSD";
61 	int type = ELFOSABI_FREEBSD;
62 	int retval = 0;
63 	int ch, change = 0, verbose = 0, force = 0, listed = 0;
64 
65 	while ((ch = getopt(argc, argv, "f:lt:v")) != -1)
66 		switch (ch) {
67 		case 'f':
68 			if (change)
69 				errx(1, "f option incompatable with t option");
70 			force = 1;
71 			type = atoi(optarg);
72 			if (errno == ERANGE || type < 0 || type > 255) {
73 				warnx("invalid argument to option f: %s",
74 				    optarg);
75 				usage();
76 			}
77 			break;
78 		case 'l':
79 			printelftypes();
80 			listed = 1;
81 			break;
82 		case 'v':
83 			verbose = 1;
84 			break;
85 		case 't':
86 			if (force)
87 				errx(1, "t option incompatable with f option");
88 			change = 1;
89 			strtype = optarg;
90 			break;
91 		default:
92 			usage();
93 	}
94 	argc -= optind;
95 	argv += optind;
96 	if (!argc) {
97 		if (listed)
98 			exit(0);
99 		else {
100 			warnx("no file(s) specified");
101 			usage();
102 		}
103 	}
104 
105 	if (!force && (type = elftype(strtype)) == -1) {
106 		warnx("invalid ELF type '%s'", strtype);
107 		printelftypes();
108 		usage();
109 	}
110 
111 	while (argc) {
112 		int fd;
113 		char buffer[EI_NIDENT];
114 
115 		if ((fd = open(argv[0], change || force ? O_RDWR : O_RDONLY, 0)) < 0) {
116 			warn("error opening file %s", argv[0]);
117 			retval = 1;
118 			goto fail;
119 		}
120 		if (read(fd, buffer, EI_NIDENT) < EI_NIDENT) {
121 			warnx("file '%s' too short", argv[0]);
122 			retval = 1;
123 			goto fail;
124 		}
125 		if (buffer[0] != ELFMAG0 || buffer[1] != ELFMAG1 ||
126 		    buffer[2] != ELFMAG2 || buffer[3] != ELFMAG3) {
127 			warnx("file '%s' is not ELF format", argv[0]);
128 			retval = 1;
129 			goto fail;
130 		}
131 		if (!change && !force) {
132 			fprintf(stdout,
133 				"File '%s' is of brand '%s' (%u).\n",
134 				argv[0], iselftype(buffer[EI_OSABI]),
135 				buffer[EI_OSABI]);
136 			if (!iselftype(type)) {
137 				warnx("ELF ABI Brand '%u' is unknown",
138 				      type);
139 				printelftypes();
140 			}
141 		}
142 		else {
143 			buffer[EI_OSABI] = type;
144 			lseek(fd, 0, SEEK_SET);
145 			if (write(fd, buffer, EI_NIDENT) != EI_NIDENT) {
146 				warn("error writing %s %d", argv[0], fd);
147 				retval = 1;
148 				goto fail;
149 			}
150 		}
151 fail:
152 		argc--;
153 		argv++;
154 	}
155 
156 	return retval;
157 }
158 
159 static void
160 usage()
161 {
162 fprintf(stderr, "usage: brandelf [-f ELF ABI number] [-v] [-l] [-t string] file ...\n");
163 	exit(1);
164 }
165 
166 static const char *
167 iselftype(int elftype)
168 {
169 	int elfwalk;
170 
171 	for (elfwalk = 0;
172 	     elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
173 	     elfwalk++)
174 		if (elftype == elftypes[elfwalk].value)
175 			return elftypes[elfwalk].str;
176 	return 0;
177 }
178 
179 static int
180 elftype(const char *elfstrtype)
181 {
182 	int elfwalk;
183 
184 	for (elfwalk = 0;
185 	     elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
186 	     elfwalk++)
187 		if (strcmp(elfstrtype, elftypes[elfwalk].str) == 0)
188 			return elftypes[elfwalk].value;
189 	return -1;
190 }
191 
192 static void
193 printelftypes()
194 {
195 	int elfwalk;
196 
197 	fprintf(stderr, "known ELF types are: ");
198 	for (elfwalk = 0;
199 	     elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
200 	     elfwalk++)
201 		fprintf(stderr, "%s(%u) ", elftypes[elfwalk].str,
202 			elftypes[elfwalk].value);
203 	fprintf(stderr, "\n");
204 }
205