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