Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.bin / genassym / genassym.c
1 /*-
2  * Copyright (c) 1999 Marcel Moolenaar
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: src/usr.bin/genassym/genassym.c,v 1.1 1999/12/23 11:07:45 marcel Exp $
29  * $DragonFly: src/usr.bin/genassym/Attic/genassym.c,v 1.2 2003/06/17 04:29:27 dillon Exp $
30  */
31
32 #include <sys/types.h>
33 #if defined(arch_i386)
34 #include <sys/elf32.h>
35 #define __ELF_WORD_SIZE 32
36 #elif defined(arch_alpha)
37 #include <sys/elf64.h>
38 #define __ELF_WORD_SIZE 64
39 #else
40 #error unknown or missing architecture
41 #endif
42 #include <sys/elf_generic.h>
43
44 #include <err.h>
45 #include <fcntl.h>
46 #include <stdlib.h>
47 #include <stdio.h>
48 #include <string.h>
49 #include <unistd.h>
50
51 const char s_data[] = ".data";
52 const char s_strtab[] = ".strtab";
53 const char s_symtab[] = ".symtab";
54 const char assym[] = "assym_";
55
56 int fd;
57 char *objfile;
58 Elf_Ehdr ehdr;
59 Elf_Shdr *shdr;
60 char *shstr;
61
62 int
63 my_byte_order(void)
64 {
65         static unsigned short s = 0xbbaa;
66         int byte0;
67
68         byte0 = *(unsigned char *)&s;
69         if (byte0 == 0xaa)
70                 return (ELFDATA2LSB);
71         else if (byte0 == 0xbb)
72                 return (ELFDATA2MSB);
73         return (ELFDATANONE);
74 }
75
76 void *
77 read_section(int index)
78 {
79         void *buf;
80         size_t size;
81         ssize_t bytes;
82
83         size = shdr[index].sh_size;
84         buf = malloc(size);
85         if (buf == NULL)
86                 return (NULL);
87         if (lseek(fd, shdr[index].sh_offset, SEEK_SET) == -1)
88                 return (NULL);
89         bytes = read(fd, buf, size);
90         if (bytes == -1)
91                 return (NULL);
92         if (bytes != size)
93                 warnx("%s: section %d partially read", objfile, index);
94         return (buf);
95 }
96
97 int section_index(const char *section)
98 {
99         int i;
100
101         for (i = 1; i < ehdr.e_shnum; i++)
102                 if (!strcmp(section, shstr + shdr[i].sh_name))
103                         return (i);
104         return (-1);
105 }
106
107 char *
108 filter(char *name)
109 {
110         char *dot;
111
112         name += sizeof(assym) - 1;
113         dot = strchr(name, '.');
114         if (dot != NULL)
115                 *dot = '\0';
116         return (name);
117 }
118
119 void usage(void)
120 {
121         fprintf(stderr, "usage: genassym [-o outfile] objfile\n");
122         exit(1);
123         /* NOT REACHED */
124 }
125
126 int
127 main(int argc, char *argv[])
128 {
129         Elf_Sym *sym;
130         char *data, *name, *symbols;
131         char *outfile;
132         void *valp;
133         size_t size;
134         ssize_t bytes;
135         int ch, i, numsym, warn_ld_bug;
136         int si_data, si_strtab, si_symtab;
137         u_int64_t value;
138
139         outfile = NULL;
140         warn_ld_bug = 1;
141
142         while ((ch = getopt(argc, argv, "o:")) != -1) {
143                 switch (ch) {
144                 case 'o':
145                         outfile = optarg;
146                         break;
147                 default:
148                         usage();
149                         /* NOT REACHED */
150                 }
151         }
152         argc -= optind;
153         argv += optind;
154
155         if (argc == 0) {
156                 usage();
157                 /* NOT REACHED */
158         }
159         if (argc > 1)
160                 warnx("ignoring trailing arguments");
161
162         objfile = argv[0];
163         fd = open(objfile, O_RDONLY);
164         if (fd == -1)
165                 err(1, "%s", objfile);
166
167         bytes = read(fd, &ehdr, sizeof(ehdr));
168         if (bytes == -1)
169                 err(1, "%s", objfile);
170         if (bytes != sizeof(ehdr) ||
171             ehdr.e_ident[EI_MAG0] != ELFMAG0 ||
172             ehdr.e_ident[EI_MAG1] != ELFMAG1 ||
173             ehdr.e_ident[EI_MAG2] != ELFMAG2 ||
174             ehdr.e_ident[EI_MAG3] != ELFMAG3)
175                 errx(1, "%s: not an ELF file", objfile);
176         if (ehdr.e_ident[EI_VERSION] != EV_CURRENT)
177                 errx(1, "%s: unsupported ELF version", objfile);
178         if (ehdr.e_ident[EI_DATA] != my_byte_order())
179                 errx(1, "%s: unsupported byte order", objfile);
180         if (ehdr.e_shoff == 0)
181                 errx(1, "%s: no section table", objfile);
182         if (ehdr.e_shstrndx == SHN_UNDEF)
183                 errx(1, "%s: no section name string table", objfile);
184
185         size = sizeof(*shdr) * ehdr.e_shnum;
186         shdr = malloc(size);
187         if (shdr == NULL)
188                 err(1, "malloc");
189         if (lseek(fd, ehdr.e_shoff, SEEK_SET) == -1)
190                 err(1, "%s", objfile);
191         bytes = read(fd, shdr, size);
192         if (bytes == -1)
193                 err(1, "%s", objfile);
194         if (bytes != size)
195                 errx(1, "%s: truncated section table", objfile);
196
197         shstr = read_section(ehdr.e_shstrndx);
198         if (shstr == NULL)
199                 err(1, "%s[%d]", objfile, ehdr.e_shstrndx);
200
201         si_data = section_index(s_data);
202         if (si_data == -1)
203                 errx(1, "%s: section %s not present", objfile, s_data);
204         data = read_section(si_data);
205         if (data == NULL)
206                 err(1, "%s[%d]", objfile, si_data);
207
208         si_strtab = section_index(s_strtab);
209         if (si_strtab == -1)
210                 errx(1, "%s: section %s not present", objfile, s_strtab);
211         symbols = read_section(si_strtab);
212         if (symbols == NULL)
213                 err(1, "%s[%d]", objfile, si_strtab);
214
215         si_symtab = section_index(s_symtab);
216         if (si_symtab == -1)
217                 errx(1, "%s: section %s not present", objfile, s_symtab);
218         sym = read_section(si_symtab);
219         if (sym == NULL)
220                 err(1, "%s[%d]", objfile, si_symtab);
221
222         numsym = shdr[si_symtab].sh_size / sizeof(*sym);
223
224         if (outfile != NULL)
225                 freopen(outfile, "w", stdout);
226
227         for (i = 0; i < numsym; i++) {
228                 name = symbols + sym[i].st_name;
229                 if (sym[i].st_shndx == si_data &&
230                     !strncmp(name, assym, sizeof(assym) - 1)) {
231                         valp = (void*)(data + sym[i].st_value);
232                         /*
233                          * XXX - ld(1) on Alpha doesn't store the size of
234                          * the symbol in the object file. The following
235                          * fix handles this case quite genericly. It
236                          * assumes that the symbols have the same size as
237                          * a word on that architecture, determined by the
238                          * word size in the ELF object file.
239                          */
240                         if (sym[i].st_size == 0) {
241                                 sym[i].st_size = __ELF_WORD_SIZE >> 3;
242                                 if (warn_ld_bug) {
243                                         warnx("%s: symbol sizes not properly"
244                                             " set", objfile);
245                                         warn_ld_bug = 0;
246                                 }
247                         }
248                         switch (sym[i].st_size) {
249                         case 1:
250                                 value = *(u_int8_t*)valp;
251                                 break;
252                         case 2:
253                                 value = *(u_int16_t*)valp;
254                                 break;
255                         case 4:
256                                 value = *(u_int32_t*)valp;
257                                 break;
258                         case 8:
259                                 value = *(u_int64_t*)valp;
260                                 break;
261                         default:
262                                 warnx("unsupported size (%lld) for symbol %s",
263                                     (long long)sym[i].st_size, filter(name));
264                                 continue;
265                         }
266                         fprintf(stdout, "#define\t%s 0x%llx\n", filter(name),
267                             (long long)value);
268                 }
269         }
270
271         return (0);
272 }