Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/elftoolchain/brandelf/brandelf.c
39488 views
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
47
ELFTC_VCSID("$Id: brandelf.c 3440 2016-04-07 14:51:47Z emaste $");
48
49
static int elftype(const char *);
50
static const char *iselftype(int);
51
static void printelftypes(void);
52
static void printversion(void);
53
static void usage(void);
54
55
struct ELFtypes {
56
const char *str;
57
int value;
58
};
59
/* XXX - any more types? */
60
static struct ELFtypes elftypes[] = {
61
{ "86Open", ELFOSABI_86OPEN },
62
{ "AIX", ELFOSABI_AIX },
63
{ "ARM", ELFOSABI_ARM },
64
{ "AROS", ELFOSABI_AROS },
65
{ "CloudABI", ELFOSABI_CLOUDABI },
66
{ "FreeBSD", ELFOSABI_FREEBSD },
67
{ "GNU", ELFOSABI_GNU },
68
{ "HP/UX", ELFOSABI_HPUX},
69
{ "Hurd", ELFOSABI_HURD },
70
{ "IRIX", ELFOSABI_IRIX },
71
{ "Linux", ELFOSABI_GNU },
72
{ "Modesto", ELFOSABI_MODESTO },
73
{ "NSK", ELFOSABI_NSK },
74
{ "NetBSD", ELFOSABI_NETBSD},
75
{ "None", ELFOSABI_NONE},
76
{ "OpenBSD", ELFOSABI_OPENBSD },
77
{ "OpenVMS", ELFOSABI_OPENVMS },
78
{ "Standalone", ELFOSABI_STANDALONE },
79
{ "SVR4", ELFOSABI_NONE },
80
{ "Solaris", ELFOSABI_SOLARIS },
81
{ "Tru64", ELFOSABI_TRU64 }
82
};
83
84
static struct option brandelf_longopts[] = {
85
{ "help", no_argument, NULL, 'h' },
86
{ "version", no_argument, NULL, 'V' },
87
{ NULL, 0, NULL, 0 }
88
};
89
90
int
91
main(int argc, char **argv)
92
{
93
GElf_Ehdr ehdr;
94
Elf *elf;
95
Elf_Kind kind;
96
int type = ELFOSABI_NONE;
97
int retval = 0;
98
int ch, change = 0, force = 0, listed = 0;
99
100
if (elf_version(EV_CURRENT) == EV_NONE)
101
errx(EXIT_FAILURE, "elf_version error");
102
103
while ((ch = getopt_long(argc, argv, "Vf:hlt:v", brandelf_longopts,
104
NULL)) != -1)
105
switch (ch) {
106
case 'f':
107
if (change)
108
errx(EXIT_FAILURE, "ERROR: the -f option is "
109
"incompatible with the -t option.");
110
force = 1;
111
type = atoi(optarg);
112
if (errno == ERANGE || type < 0 || type > 255) {
113
warnx("ERROR: invalid argument to option "
114
"-f: %s", optarg);
115
usage();
116
}
117
break;
118
case 'h':
119
usage();
120
break;
121
case 'l':
122
printelftypes();
123
listed = 1;
124
break;
125
case 'v':
126
/* This flag is ignored. */
127
break;
128
case 't':
129
if (force)
130
errx(EXIT_FAILURE, "the -t option is "
131
"incompatible with the -f option.");
132
if ((type = elftype(optarg)) == -1) {
133
warnx("ERROR: invalid ELF type '%s'", optarg);
134
usage();
135
}
136
137
change = 1;
138
break;
139
case 'V':
140
printversion();
141
break;
142
default:
143
usage();
144
}
145
argc -= optind;
146
argv += optind;
147
if (!argc) {
148
if (listed)
149
exit(0);
150
else {
151
warnx("no file(s) specified");
152
usage();
153
}
154
}
155
156
while (argc) {
157
int fd;
158
159
elf = NULL;
160
161
if ((fd = open(argv[0], (change || force) ? O_RDWR :
162
O_RDONLY, 0)) < 0) {
163
warn("error opening file %s", argv[0]);
164
retval = 1;
165
goto fail;
166
}
167
168
if ((elf = elf_begin(fd, (change || force) ? ELF_C_RDWR :
169
ELF_C_READ, NULL)) == NULL) {
170
warnx("elf_begin failed: %s", elf_errmsg(-1));
171
retval = 1;
172
goto fail;
173
}
174
175
if ((kind = elf_kind(elf)) != ELF_K_ELF) {
176
if (kind == ELF_K_AR)
177
warnx("file '%s' is an archive.", argv[0]);
178
else
179
warnx("file '%s' is not an ELF file.",
180
argv[0]);
181
retval = 1;
182
goto fail;
183
}
184
185
if (gelf_getehdr(elf, &ehdr) == NULL) {
186
warnx("gelf_getehdr: %s", elf_errmsg(-1));
187
retval = 1;
188
goto fail;
189
}
190
191
if (!change && !force) {
192
fprintf(stdout,
193
"File '%s' is of brand '%s' (%u).\n",
194
argv[0], iselftype(ehdr.e_ident[EI_OSABI]),
195
ehdr.e_ident[EI_OSABI]);
196
if (!iselftype(type)) {
197
warnx("ELF ABI Brand '%u' is unknown",
198
type);
199
printelftypes();
200
}
201
} else {
202
203
/*
204
* Keep the existing layout of the ELF object.
205
*/
206
if (elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT) == 0) {
207
warnx("elf_flagelf failed: %s",
208
elf_errmsg(-1));
209
retval = 1;
210
goto fail;
211
}
212
213
/*
214
* Update the ABI type.
215
*/
216
ehdr.e_ident[EI_OSABI] = (unsigned char) type;
217
if (gelf_update_ehdr(elf, &ehdr) == 0) {
218
warnx("gelf_update_ehdr error: %s",
219
elf_errmsg(-1));
220
retval = 1;
221
goto fail;
222
}
223
224
/*
225
* Write back changes.
226
*/
227
if (elf_update(elf, ELF_C_WRITE) == -1) {
228
warnx("elf_update error: %s", elf_errmsg(-1));
229
retval = 1;
230
goto fail;
231
}
232
}
233
fail:
234
235
if (elf)
236
elf_end(elf);
237
238
if (fd >= 0 && close(fd) == -1) {
239
warnx("%s: close error", argv[0]);
240
retval = 1;
241
}
242
243
argc--;
244
argv++;
245
}
246
247
return (retval);
248
}
249
250
#define USAGE_MESSAGE "\
251
Usage: %s [options] file...\n\
252
Set or display the ABI field for an ELF object.\n\n\
253
Supported options are:\n\
254
-f NUM Set the ELF ABI to the number 'NUM'.\n\
255
-h | --help Print a usage message and exit.\n\
256
-l List known ELF ABI names.\n\
257
-t ABI Set the ELF ABI to the value named by \"ABI\".\n\
258
-V | --version Print a version identifier and exit.\n"
259
260
static void
261
usage(void)
262
{
263
(void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
264
exit(1);
265
}
266
267
static void
268
printversion(void)
269
{
270
(void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());
271
exit(0);
272
}
273
274
static const char *
275
iselftype(int etype)
276
{
277
size_t elfwalk;
278
279
for (elfwalk = 0;
280
elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
281
elfwalk++)
282
if (etype == elftypes[elfwalk].value)
283
return (elftypes[elfwalk].str);
284
return (0);
285
}
286
287
static int
288
elftype(const char *elfstrtype)
289
{
290
size_t elfwalk;
291
292
for (elfwalk = 0;
293
elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
294
elfwalk++)
295
if (strcasecmp(elfstrtype, elftypes[elfwalk].str) == 0)
296
return (elftypes[elfwalk].value);
297
return (-1);
298
}
299
300
static void
301
printelftypes(void)
302
{
303
size_t elfwalk;
304
305
(void) printf("Known ELF types are: ");
306
for (elfwalk = 0;
307
elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
308
elfwalk++)
309
(void) printf("%s(%u) ", elftypes[elfwalk].str,
310
elftypes[elfwalk].value);
311
(void) printf("\n");
312
}
313
314