]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/elftoolchain/brandelf/brandelf.c
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r308421, and update
[FreeBSD/FreeBSD.git] / contrib / elftoolchain / brandelf / brandelf.c
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 }