xref: /freebsd/usr.bin/brandelf/brandelf.c (revision 77a0943ded95b9e6438f7db70c4a28e4d93946d4)
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 	{ "Linux",	ELFOSABI_LINUX },
53 	{ "Solaris",	ELFOSABI_SOLARIS },
54 	{ "SVR4",	ELFOSABI_SYSV }
55 };
56 
57 int
58 main(int argc, char **argv)
59 {
60 
61 	const char *strtype = "FreeBSD";
62 	int type = ELFOSABI_FREEBSD;
63 	int retval = 0;
64 	int ch, change = 0, verbose = 0, force = 0, listed = 0;
65 
66 	while ((ch = getopt(argc, argv, "f:lt:v")) != -1)
67 		switch (ch) {
68 		case 'f':
69 			if (change)
70 				errx(1, "f option incompatable with t option");
71 			force = 1;
72 			type = atoi(optarg);
73 			if (errno == ERANGE || type < 0 || type > 255) {
74 				warnx("invalid argument to option f: %s",
75 				    optarg);
76 				usage();
77 			}
78 			break;
79 		case 'l':
80 			printelftypes();
81 			listed = 1;
82 			break;
83 		case 'v':
84 			verbose = 1;
85 			break;
86 		case 't':
87 			if (force)
88 				errx(1, "t option incompatable with f option");
89 			change = 1;
90 			strtype = optarg;
91 			break;
92 		default:
93 			usage();
94 	}
95 	argc -= optind;
96 	argv += optind;
97 	if (!argc) {
98 		if (listed)
99 			exit(0);
100 		else {
101 			warnx("no file(s) specified");
102 			usage();
103 		}
104 	}
105 
106 	if (!force && (type = elftype(strtype)) == -1) {
107 		warnx("invalid ELF type '%s'", strtype);
108 		printelftypes();
109 		usage();
110 	}
111 
112 	while (argc) {
113 		int fd;
114 		char buffer[EI_NIDENT];
115 
116 		if ((fd = open(argv[0], change || force ? O_RDWR : O_RDONLY, 0)) < 0) {
117 			warn("error opening file %s", argv[0]);
118 			retval = 1;
119 			goto fail;
120 		}
121 		if (read(fd, buffer, EI_NIDENT) < EI_NIDENT) {
122 			warnx("file '%s' too short", argv[0]);
123 			retval = 1;
124 			goto fail;
125 		}
126 		if (buffer[0] != ELFMAG0 || buffer[1] != ELFMAG1 ||
127 		    buffer[2] != ELFMAG2 || buffer[3] != ELFMAG3) {
128 			warnx("file '%s' is not ELF format", argv[0]);
129 			retval = 1;
130 			goto fail;
131 		}
132 		if (!change && !force) {
133 			fprintf(stdout,
134 				"File '%s' is of brand '%s' (%u).\n",
135 				argv[0], iselftype(buffer[EI_OSABI]),
136 				buffer[EI_OSABI]);
137 			if (!iselftype(type)) {
138 				warnx("ELF ABI Brand '%u' is unknown",
139 				      type);
140 				printelftypes();
141 			}
142 		}
143 		else {
144 			buffer[EI_OSABI] = type;
145 			lseek(fd, 0, SEEK_SET);
146 			if (write(fd, buffer, EI_NIDENT) != EI_NIDENT) {
147 				warn("error writing %s %d", argv[0], fd);
148 				retval = 1;
149 				goto fail;
150 			}
151 		}
152 fail:
153 		close(fd);
154 		argc--;
155 		argv++;
156 	}
157 
158 	return retval;
159 }
160 
161 static void
162 usage()
163 {
164 fprintf(stderr, "usage: brandelf [-f ELF ABI number] [-v] [-l] [-t string] file ...\n");
165 	exit(1);
166 }
167 
168 static const char *
169 iselftype(int elftype)
170 {
171 	int elfwalk;
172 
173 	for (elfwalk = 0;
174 	     elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
175 	     elfwalk++)
176 		if (elftype == elftypes[elfwalk].value)
177 			return elftypes[elfwalk].str;
178 	return 0;
179 }
180 
181 static int
182 elftype(const char *elfstrtype)
183 {
184 	int elfwalk;
185 
186 	for (elfwalk = 0;
187 	     elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
188 	     elfwalk++)
189 		if (strcmp(elfstrtype, elftypes[elfwalk].str) == 0)
190 			return elftypes[elfwalk].value;
191 	return -1;
192 }
193 
194 static void
195 printelftypes()
196 {
197 	int elfwalk;
198 
199 	fprintf(stderr, "known ELF types are: ");
200 	for (elfwalk = 0;
201 	     elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
202 	     elfwalk++)
203 		fprintf(stderr, "%s(%u) ", elftypes[elfwalk].str,
204 			elftypes[elfwalk].value);
205 	fprintf(stderr, "\n");
206 }
207