1/*-
2 * Copyright (c) 2008 Hyogeol Lee
3 * Copyright (c) 2000, 2001 David O'Brien
4 * Copyright (c) 1996 S��ren Schmidt
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer
12 * in this position and unchanged.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <err.h>
34#include <errno.h>
35#include <fcntl.h>
36#include <gelf.h>
37#include <getopt.h>
38#include <libelf.h>
39#include <libelftc.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <unistd.h>
44
45#include "_elftc.h"
46
47ELFTC_VCSID("$Id: brandelf.c 3234 2015-07-31 12:35:09Z emaste $");
48
49static int elftype(const char *);
50static const char *iselftype(int);
51static void printelftypes(void);
52static void printversion(void);
53static void usage(void);
54
55struct ELFtypes {
56 const char *str;
57 int value;
58};
59/* XXX - any more types? */
60static struct ELFtypes elftypes[] = {
61 { "86Open", ELFOSABI_86OPEN },
62 { "AIX", ELFOSABI_AIX },
63 { "ARM", ELFOSABI_ARM },
64 { "AROS", ELFOSABI_AROS },
65 { "FreeBSD", ELFOSABI_FREEBSD },
66 { "GNU", ELFOSABI_GNU },
67 { "HP/UX", ELFOSABI_HPUX},
68 { "Hurd", ELFOSABI_HURD },
69 { "IRIX", ELFOSABI_IRIX },
70 { "Linux", ELFOSABI_GNU },
71 { "Modesto", ELFOSABI_MODESTO },
72 { "NSK", ELFOSABI_NSK },
73 { "NetBSD", ELFOSABI_NETBSD},
74 { "None", ELFOSABI_NONE},
75 { "OpenBSD", ELFOSABI_OPENBSD },
76 { "OpenVMS", ELFOSABI_OPENVMS },
77 { "Standalone", ELFOSABI_STANDALONE },
78 { "SVR4", ELFOSABI_NONE },
79 { "Solaris", ELFOSABI_SOLARIS },
80 { "Tru64", ELFOSABI_TRU64 }
81};
82
83static struct option brandelf_longopts[] = {
84 { "help", no_argument, NULL, 'h' },
85 { "version", no_argument, NULL, 'V' },
86 { NULL, 0, NULL, 0 }
87};
88
89int
90main(int argc, char **argv)
91{
92 GElf_Ehdr ehdr;
93 Elf *elf;
94 Elf_Kind kind;
95 int type = ELFOSABI_NONE;
96 int retval = 0;
97 int ch, change = 0, force = 0, listed = 0;
98
99 if (elf_version(EV_CURRENT) == EV_NONE)
100 errx(EXIT_FAILURE, "elf_version error");
101
102 while ((ch = getopt_long(argc, argv, "Vf:hlt:v", brandelf_longopts,
103 NULL)) != -1)
104 switch (ch) {
105 case 'f':
106 if (change)
107 errx(EXIT_FAILURE, "ERROR: the -f option is "
108 "incompatible with the -t option.");
109 force = 1;
110 type = atoi(optarg);
111 if (errno == ERANGE || type < 0 || type > 255) {
112 warnx("ERROR: invalid argument to option "
113 "-f: %s", optarg);
114 usage();
115 }
116 break;
117 case 'h':
118 usage();
119 break;
120 case 'l':
121 printelftypes();
122 listed = 1;
123 break;
124 case 'v':
125 /* This flag is ignored. */
126 break;
127 case 't':
128 if (force)
129 errx(EXIT_FAILURE, "the -t option is "
130 "incompatible with the -f option.");
131 if ((type = elftype(optarg)) == -1) {
132 warnx("ERROR: invalid ELF type '%s'", optarg);
133 usage();
134 }
135
136 change = 1;
137 break;
138 case 'V':
139 printversion();
140 break;
141 default:
142 usage();
143 }
144 argc -= optind;
145 argv += optind;
146 if (!argc) {
147 if (listed)
148 exit(0);
149 else {
150 warnx("no file(s) specified");
151 usage();
152 }
153 }
154
155 while (argc) {
156 int fd;
157
158 elf = NULL;
159
160 if ((fd = open(argv[0], (change || force) ? O_RDWR :
161 O_RDONLY, 0)) < 0) {
162 warn("error opening file %s", argv[0]);
163 retval = 1;
164 goto fail;
165 }
166
167 if ((elf = elf_begin(fd, (change || force) ? ELF_C_RDWR :
168 ELF_C_READ, NULL)) == NULL) {
169 warnx("elf_begin failed: %s", elf_errmsg(-1));
170 retval = 1;
171 goto fail;
172 }
173
174 if ((kind = elf_kind(elf)) != ELF_K_ELF) {
175 if (kind == ELF_K_AR)
176 warnx("file '%s' is an archive.", argv[0]);
177 else
178 warnx("file '%s' is not an ELF file.",
179 argv[0]);
180 retval = 1;
181 goto fail;
182 }
183
184 if (gelf_getehdr(elf, &ehdr) == NULL) {
185 warnx("gelf_getehdr: %s", elf_errmsg(-1));
186 retval = 1;
187 goto fail;
188 }
189
190 if (!change && !force) {
191 fprintf(stdout,
192 "File '%s' is of brand '%s' (%u).\n",
193 argv[0], iselftype(ehdr.e_ident[EI_OSABI]),
194 ehdr.e_ident[EI_OSABI]);
195 if (!iselftype(type)) {
196 warnx("ELF ABI Brand '%u' is unknown",
197 type);
198 printelftypes();
199 }
200 } else {
201
202 /*
203 * Keep the existing layout of the ELF object.
204 */
205 if (elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT) == 0) {
206 warnx("elf_flagelf failed: %s",
207 elf_errmsg(-1));
208 retval = 1;
209 goto fail;
210 }
211
212 /*
213 * Update the ABI type.
214 */
215 ehdr.e_ident[EI_OSABI] = type;
216 if (gelf_update_ehdr(elf, &ehdr) == 0) {
217 warnx("gelf_update_ehdr error: %s",
218 elf_errmsg(-1));
219 retval = 1;
220 goto fail;
221 }
222
223 /*
224 * Write back changes.
225 */
226 if (elf_update(elf, ELF_C_WRITE) == -1) {
227 warnx("elf_update error: %s", elf_errmsg(-1));
228 retval = 1;
229 goto fail;
230 }
231 }
232fail:
233
234 if (elf)
235 elf_end(elf);
236
237 if (fd >= 0 && close(fd) == -1) {
238 warnx("%s: close error", argv[0]);
239 retval = 1;
240 }
241
242 argc--;
243 argv++;
244 }
245
246 return (retval);
247}
248
249#define USAGE_MESSAGE "\
250Usage: %s [options] file...\n\
251 Set or display the ABI field for an ELF object.\n\n\
252 Supported options are:\n\
253 -f NUM Set the ELF ABI to the number 'NUM'.\n\
254 -h | --help Print a usage message and exit.\n\
255 -l List known ELF ABI names.\n\
256 -t ABI Set the ELF ABI to the value named by \"ABI\".\n\
257 -V | --version Print a version identifier and exit.\n"
258
259static void
260usage(void)
261{
262 (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
263 exit(1);
264}
265
266static void
267printversion(void)
268{
269 (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());
270 exit(0);
271}
272
273static const char *
274iselftype(int etype)
275{
276 size_t elfwalk;
277
278 for (elfwalk = 0;
279 elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
280 elfwalk++)
281 if (etype == elftypes[elfwalk].value)
282 return (elftypes[elfwalk].str);
283 return (0);
284}
285
286static int
287elftype(const char *elfstrtype)
288{
289 size_t elfwalk;
290
291 for (elfwalk = 0;
292 elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
293 elfwalk++)
294 if (strcasecmp(elfstrtype, elftypes[elfwalk].str) == 0)
295 return (elftypes[elfwalk].value);
296 return (-1);
297}
298
299static void
300printelftypes(void)
301{
302 size_t elfwalk;
303
304 (void) printf("Known ELF types are: ");
305 for (elfwalk = 0;
306 elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
307 elfwalk++)
308 (void) printf("%s(%u) ", elftypes[elfwalk].str,
309 elftypes[elfwalk].value);
310 (void) printf("\n");
311}
2 * Copyright (c) 2008 Hyogeol Lee
3 * Copyright (c) 2000, 2001 David O'Brien
4 * Copyright (c) 1996 S��ren Schmidt
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer
12 * in this position and unchanged.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <err.h>
34#include <errno.h>
35#include <fcntl.h>
36#include <gelf.h>
37#include <getopt.h>
38#include <libelf.h>
39#include <libelftc.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <unistd.h>
44
45#include "_elftc.h"
46
47ELFTC_VCSID("$Id: brandelf.c 3234 2015-07-31 12:35:09Z emaste $");
48
49static int elftype(const char *);
50static const char *iselftype(int);
51static void printelftypes(void);
52static void printversion(void);
53static void usage(void);
54
55struct ELFtypes {
56 const char *str;
57 int value;
58};
59/* XXX - any more types? */
60static struct ELFtypes elftypes[] = {
61 { "86Open", ELFOSABI_86OPEN },
62 { "AIX", ELFOSABI_AIX },
63 { "ARM", ELFOSABI_ARM },
64 { "AROS", ELFOSABI_AROS },
65 { "FreeBSD", ELFOSABI_FREEBSD },
66 { "GNU", ELFOSABI_GNU },
67 { "HP/UX", ELFOSABI_HPUX},
68 { "Hurd", ELFOSABI_HURD },
69 { "IRIX", ELFOSABI_IRIX },
70 { "Linux", ELFOSABI_GNU },
71 { "Modesto", ELFOSABI_MODESTO },
72 { "NSK", ELFOSABI_NSK },
73 { "NetBSD", ELFOSABI_NETBSD},
74 { "None", ELFOSABI_NONE},
75 { "OpenBSD", ELFOSABI_OPENBSD },
76 { "OpenVMS", ELFOSABI_OPENVMS },
77 { "Standalone", ELFOSABI_STANDALONE },
78 { "SVR4", ELFOSABI_NONE },
79 { "Solaris", ELFOSABI_SOLARIS },
80 { "Tru64", ELFOSABI_TRU64 }
81};
82
83static struct option brandelf_longopts[] = {
84 { "help", no_argument, NULL, 'h' },
85 { "version", no_argument, NULL, 'V' },
86 { NULL, 0, NULL, 0 }
87};
88
89int
90main(int argc, char **argv)
91{
92 GElf_Ehdr ehdr;
93 Elf *elf;
94 Elf_Kind kind;
95 int type = ELFOSABI_NONE;
96 int retval = 0;
97 int ch, change = 0, force = 0, listed = 0;
98
99 if (elf_version(EV_CURRENT) == EV_NONE)
100 errx(EXIT_FAILURE, "elf_version error");
101
102 while ((ch = getopt_long(argc, argv, "Vf:hlt:v", brandelf_longopts,
103 NULL)) != -1)
104 switch (ch) {
105 case 'f':
106 if (change)
107 errx(EXIT_FAILURE, "ERROR: the -f option is "
108 "incompatible with the -t option.");
109 force = 1;
110 type = atoi(optarg);
111 if (errno == ERANGE || type < 0 || type > 255) {
112 warnx("ERROR: invalid argument to option "
113 "-f: %s", optarg);
114 usage();
115 }
116 break;
117 case 'h':
118 usage();
119 break;
120 case 'l':
121 printelftypes();
122 listed = 1;
123 break;
124 case 'v':
125 /* This flag is ignored. */
126 break;
127 case 't':
128 if (force)
129 errx(EXIT_FAILURE, "the -t option is "
130 "incompatible with the -f option.");
131 if ((type = elftype(optarg)) == -1) {
132 warnx("ERROR: invalid ELF type '%s'", optarg);
133 usage();
134 }
135
136 change = 1;
137 break;
138 case 'V':
139 printversion();
140 break;
141 default:
142 usage();
143 }
144 argc -= optind;
145 argv += optind;
146 if (!argc) {
147 if (listed)
148 exit(0);
149 else {
150 warnx("no file(s) specified");
151 usage();
152 }
153 }
154
155 while (argc) {
156 int fd;
157
158 elf = NULL;
159
160 if ((fd = open(argv[0], (change || force) ? O_RDWR :
161 O_RDONLY, 0)) < 0) {
162 warn("error opening file %s", argv[0]);
163 retval = 1;
164 goto fail;
165 }
166
167 if ((elf = elf_begin(fd, (change || force) ? ELF_C_RDWR :
168 ELF_C_READ, NULL)) == NULL) {
169 warnx("elf_begin failed: %s", elf_errmsg(-1));
170 retval = 1;
171 goto fail;
172 }
173
174 if ((kind = elf_kind(elf)) != ELF_K_ELF) {
175 if (kind == ELF_K_AR)
176 warnx("file '%s' is an archive.", argv[0]);
177 else
178 warnx("file '%s' is not an ELF file.",
179 argv[0]);
180 retval = 1;
181 goto fail;
182 }
183
184 if (gelf_getehdr(elf, &ehdr) == NULL) {
185 warnx("gelf_getehdr: %s", elf_errmsg(-1));
186 retval = 1;
187 goto fail;
188 }
189
190 if (!change && !force) {
191 fprintf(stdout,
192 "File '%s' is of brand '%s' (%u).\n",
193 argv[0], iselftype(ehdr.e_ident[EI_OSABI]),
194 ehdr.e_ident[EI_OSABI]);
195 if (!iselftype(type)) {
196 warnx("ELF ABI Brand '%u' is unknown",
197 type);
198 printelftypes();
199 }
200 } else {
201
202 /*
203 * Keep the existing layout of the ELF object.
204 */
205 if (elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT) == 0) {
206 warnx("elf_flagelf failed: %s",
207 elf_errmsg(-1));
208 retval = 1;
209 goto fail;
210 }
211
212 /*
213 * Update the ABI type.
214 */
215 ehdr.e_ident[EI_OSABI] = type;
216 if (gelf_update_ehdr(elf, &ehdr) == 0) {
217 warnx("gelf_update_ehdr error: %s",
218 elf_errmsg(-1));
219 retval = 1;
220 goto fail;
221 }
222
223 /*
224 * Write back changes.
225 */
226 if (elf_update(elf, ELF_C_WRITE) == -1) {
227 warnx("elf_update error: %s", elf_errmsg(-1));
228 retval = 1;
229 goto fail;
230 }
231 }
232fail:
233
234 if (elf)
235 elf_end(elf);
236
237 if (fd >= 0 && close(fd) == -1) {
238 warnx("%s: close error", argv[0]);
239 retval = 1;
240 }
241
242 argc--;
243 argv++;
244 }
245
246 return (retval);
247}
248
249#define USAGE_MESSAGE "\
250Usage: %s [options] file...\n\
251 Set or display the ABI field for an ELF object.\n\n\
252 Supported options are:\n\
253 -f NUM Set the ELF ABI to the number 'NUM'.\n\
254 -h | --help Print a usage message and exit.\n\
255 -l List known ELF ABI names.\n\
256 -t ABI Set the ELF ABI to the value named by \"ABI\".\n\
257 -V | --version Print a version identifier and exit.\n"
258
259static void
260usage(void)
261{
262 (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
263 exit(1);
264}
265
266static void
267printversion(void)
268{
269 (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());
270 exit(0);
271}
272
273static const char *
274iselftype(int etype)
275{
276 size_t elfwalk;
277
278 for (elfwalk = 0;
279 elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
280 elfwalk++)
281 if (etype == elftypes[elfwalk].value)
282 return (elftypes[elfwalk].str);
283 return (0);
284}
285
286static int
287elftype(const char *elfstrtype)
288{
289 size_t elfwalk;
290
291 for (elfwalk = 0;
292 elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
293 elfwalk++)
294 if (strcasecmp(elfstrtype, elftypes[elfwalk].str) == 0)
295 return (elftypes[elfwalk].value);
296 return (-1);
297}
298
299static void
300printelftypes(void)
301{
302 size_t elfwalk;
303
304 (void) printf("Known ELF types are: ");
305 for (elfwalk = 0;
306 elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
307 elfwalk++)
308 (void) printf("%s(%u) ", elftypes[elfwalk].str,
309 elftypes[elfwalk].value);
310 (void) printf("\n");
311}