Add sigtimedwait.o and sigwaitinfo.o.
[dragonfly.git] / usr.sbin / elf2exe / elf2exe.c
1 /*-
2  * Copyright (c) 1999 Stefan Esser
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  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: src/usr.sbin/elf2exe/elf2exe.c,v 1.6.2.1 2000/07/20 10:35:23 kris Exp $
27  * $DragonFly: src/usr.sbin/elf2exe/Attic/elf2exe.c,v 1.2 2003/06/17 04:29:53 dillon Exp $
28  */
29
30 /*
31  * Make an ARC firmware executable from an ELF file.
32  */
33
34 #include <sys/types.h>
35 #include <sys/elf64.h>
36 #include <err.h>
37 #include <fcntl.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <time.h>
42 #include <unistd.h>
43
44 #define ALPHA_FMAGIC    0x184
45
46 #define TOTHSZ          0x200
47
48 typedef struct filehdr {
49     u_int16_t           f_magic;
50     u_int16_t           f_nscns;
51     u_int32_t           f_timdat;
52     u_int32_t           f_symptr;
53     u_int32_t           f_nsyms;
54     u_int16_t           f_opthdr;
55     u_int16_t           f_flags;
56 } FILHDR;
57 #define FILHSZ  20
58
59 #define ALPHA_AMAGIC    0407
60
61 typedef struct aouthdr {
62     u_int16_t           a_magic;
63     u_int16_t           a_vstamp;
64     u_int32_t           a_tsize;
65     u_int32_t           a_dsize;
66     u_int32_t           a_bsize;
67     u_int32_t           a_entry;
68     u_int32_t           a_text_start;
69     u_int32_t           a_data_start;
70     u_int32_t           a_bss_start;
71     u_int32_t           a_gprmask;
72     u_int32_t           a_cprmask[4];
73     u_int32_t           a_gp_value;
74 } AOUTHDR;
75 #define AOUTSZ  56
76
77 typedef struct scnhdr {
78     char                s_name[8];
79     u_int32_t           s_fill;
80     u_int32_t           s_vaddr;
81     u_int32_t           s_size;
82     u_int32_t           s_scnptr;
83     u_int32_t           s_relptr;
84     u_int32_t           s_lnnoptr;
85     u_int16_t           s_nreloc;
86     u_int16_t           s_nlnno;
87     u_int32_t           s_flags;
88 } SCNHDR;
89 #define SCNHSZ  40
90
91 #define ROUNDUP(a,b)    ((((a) -1) | ((b) -1)) +1)
92
93 /*
94  * initialization subroutines
95  */
96
97 int 
98 open_elffile(char *filename)
99 {
100         int fileno = open(filename, O_RDONLY);
101
102         if (fileno < 0)
103                 err(1, "%s", filename);
104         return (fileno);
105 }
106
107
108 Elf64_Ehdr *
109 load_ehdr(int fileno)
110 {
111         Elf64_Ehdr *ehdr;
112         size_t bytes = sizeof(*ehdr);
113
114         ehdr = malloc(bytes);
115         if (ehdr) {
116                 lseek(fileno, 0, SEEK_SET);
117                 if (read(fileno, ehdr, bytes) != bytes)
118                         errx(1, "file truncated (ehdr)");
119         }
120         return (ehdr);
121 }
122
123 Elf64_Phdr *
124 load_phdr(int fileno, Elf64_Ehdr *ehdr)
125 {
126         size_t bytes = ehdr->e_phentsize * ehdr->e_phnum;
127         Elf64_Phdr *phdr = malloc(bytes);
128
129         if (phdr) {
130                 lseek(fileno, ehdr->e_phoff, SEEK_SET);
131                 if (read(fileno, phdr, bytes) != bytes)
132                         errx(1, "file truncated (phdr)");
133         }
134         return (phdr);
135 }
136
137 Elf64_Shdr *
138 load_shdr(int fileno, Elf64_Ehdr *ehdr)
139 {
140         size_t bytes = ehdr->e_shentsize * ehdr->e_shnum;
141         Elf64_Shdr *shdr = malloc(bytes);
142
143         if (shdr) {
144                 lseek(fileno, ehdr->e_shoff, SEEK_SET);
145                 if (read(fileno, shdr, bytes) != bytes)
146                         errx(1, "file truncated (shdr)");
147         }
148         return (shdr);
149 }
150
151 char *
152 find_shstrtable(int fileno, int sections, Elf64_Shdr *shdr)
153 {
154         size_t bytes;
155         char *shstrtab = NULL;
156         int i, shstrtabindex;
157
158         for (i = 0; shstrtab == NULL && i < sections; i++) {
159                 if (shdr[i].sh_type == 3 && shdr[i].sh_flags == 0) {
160                         shstrtabindex = i;
161
162                         bytes = shdr[shstrtabindex].sh_size;
163                         shstrtab = malloc(bytes);
164                         if (shstrtab == NULL)
165                                 errx(1, "malloc failed");
166                         lseek(fileno, shdr[shstrtabindex].sh_offset, SEEK_SET);
167                         read(fileno, shstrtab, bytes);
168
169                         if (strcmp (shstrtab + shdr[i].sh_name, ".shstrtab")) {
170                                 free(shstrtab);
171                                 shstrtab = NULL;
172                         }
173                 }
174         }
175         return (shstrtab);
176 }
177
178 int
179 open_exefile(char *filename)
180 {
181         int fileno = open(filename, O_RDWR | O_TRUNC | O_CREAT, 0666);
182
183         if (fileno < 0)
184                 err(1, "%s", filename);
185         return (fileno);
186 }
187
188 /*
189  * utility subroutines 
190  */
191
192 static char *shstrtab;
193
194 char *
195 section_name(Elf64_Shdr *shdr, int i)
196 {
197         return (shstrtab + shdr[i].sh_name);
198 }
199
200 int
201 section_index(Elf64_Shdr *shdr, int sections, char *name)
202 {
203         int i;
204
205         for (i = 0; i < sections; i++)
206                 if (strcmp (name, section_name(shdr, i)) == 0)
207                         return (i);
208         return (-1);
209 }
210
211 /* first byte of section */
212 u_int64_t
213 section_start(Elf64_Shdr *shdr, int sections, char *name)
214 {
215         int i = section_index(shdr, sections, name);
216
217         if (i < 0)
218                 return (-1);
219         return (shdr[i].sh_addr);
220 }
221
222 /* last byte of section */
223 u_int64_t
224 section_end(Elf64_Shdr *shdr, int sections, char *name)
225 {
226         int i = section_index(shdr, sections, name);
227
228         if (i < 0)
229                 return (-1);
230         return (shdr[i].sh_addr + shdr[i].sh_size -1);
231 }
232
233 /* last byte of section */
234 u_int64_t
235 section_size(Elf64_Shdr *shdr, int sections, char *name)
236 {
237         int i = section_index(shdr, sections, name);
238
239         if (i < 0)
240                 return (-1);
241
242         return (shdr[i].sh_size);
243 }
244
245 /* file position of section start */
246 u_int64_t
247 section_fpos(Elf64_Shdr *shdr, int sections, char *name)
248 {
249         int i = section_index(shdr, sections, name);
250
251         if (i < 0)
252                 return (-1);
253         return (shdr[i].sh_offset);
254 }
255
256 void
257 usage(void)
258 {
259         fprintf(stderr, "usage: elf2exe infile outfile\n");
260         exit(1);
261 }
262
263 int
264 main(int argc, char** argv)
265 {
266         int infd, outfd, i;
267         Elf64_Ehdr *ehdr;
268         Elf64_Phdr *phdr;
269         Elf64_Shdr *shdr;
270         FILHDR filehdr;
271         AOUTHDR aouthdr;
272         SCNHDR textscn, datascn;
273         u_int64_t textstart, textsize, textsize2, textfsize, textfpos;
274         u_int64_t datastart, datasize, datafsize, datafpos;
275         u_int64_t bssstart, bsssize;
276         u_int64_t progentry;
277         char* p;
278         int sections;
279
280         if (argc != 3)
281                 usage();
282
283         infd = open_elffile(argv[1]);
284         ehdr = load_ehdr(infd);
285
286         if (ehdr == NULL)
287                 errx(1, "cannot read Elf Header\n");
288
289         sections = ehdr->e_shnum;
290         progentry = ehdr->e_entry;
291
292         phdr = load_phdr(infd, ehdr);
293         shdr = load_shdr(infd, ehdr);
294         outfd = open_exefile(argv[2]);
295
296         shstrtab = find_shstrtable(infd, sections, shdr);
297
298         for (i = 1; i < sections; i++) {
299                 printf("section %d (%s): "
300                     "type=%x flags=0%llx "
301                     "offs=%llx size=%llx addr=%llx\n",
302                     i, shstrtab + shdr[i].sh_name,
303                     shdr[i].sh_type, (long long)shdr[i].sh_flags,
304                     (long long)shdr[i].sh_offset, (long long)shdr[i].sh_size,
305                     (long long)shdr[i].sh_addr);
306         }
307
308         textstart = section_start(shdr, sections, ".text");
309         textsize  = section_size(shdr, sections,  ".text");
310         textsize2 = section_end(shdr, sections,  ".rodata") - textstart +1;
311         if (textsize < textsize2)
312                 textsize = textsize2;
313         textfsize = ROUNDUP(textsize, 512);
314         textfpos  = section_fpos(shdr, sections, ".text");
315
316         datastart = section_start(shdr, sections, ".data");
317         datasize  = section_start(shdr, sections, ".bss") - datastart;
318         datafsize = ROUNDUP(datasize, 512);
319         datafpos  = section_fpos(shdr, sections, ".data");
320
321         bssstart  = section_start(shdr, sections, ".bss");
322         bsssize   = section_size(shdr, sections, ".bss");
323
324         printf("text: %llx(%llx) @%llx  data: %llx(%llx) @%llx  "
325             "bss: %llx(%llx)\n",
326             (long long)textstart, (long long)textsize, (long long)textfpos,
327             (long long)datastart, (long long)datasize, (long long)datafpos,
328             (long long)bssstart, (long long)bsssize);
329
330         memset(&filehdr, 0, sizeof filehdr);
331         memset(&aouthdr, 0, sizeof aouthdr);
332         memset(&textscn, 0, sizeof textscn);
333         memset(&datascn, 0, sizeof datascn);
334
335         filehdr.f_magic = ALPHA_FMAGIC;
336         filehdr.f_nscns = 2;
337         filehdr.f_timdat = time(0);
338         filehdr.f_symptr = 0;
339         filehdr.f_nsyms = 0;
340         filehdr.f_opthdr = AOUTSZ;
341         filehdr.f_flags = 0x010f;
342
343         aouthdr.a_magic = ALPHA_AMAGIC;
344         aouthdr.a_vstamp = 0x5004;
345         aouthdr.a_tsize = textfsize;
346         aouthdr.a_dsize = datafsize;
347         aouthdr.a_bsize = bsssize;
348         aouthdr.a_entry = progentry;
349         aouthdr.a_text_start = textstart;
350         aouthdr.a_data_start = datastart;
351         aouthdr.a_bss_start = bssstart;
352
353         strcpy(textscn.s_name, ".text");
354         textscn.s_fill = textsize;
355         textscn.s_vaddr = textstart;
356         textscn.s_size = textfsize;
357         textscn.s_scnptr = 0x200;
358         textscn.s_relptr = 0;
359         textscn.s_lnnoptr = 0;
360         textscn.s_nreloc = 0;
361         textscn.s_nlnno = 0;
362         textscn.s_flags = 0x20;
363
364         strcpy(datascn.s_name, ".data");
365         datascn.s_fill = datasize;
366         datascn.s_vaddr = datastart;
367         datascn.s_size = datafsize;
368         datascn.s_scnptr = 0x200 + textfsize;
369         datascn.s_relptr = 0;
370         datascn.s_lnnoptr = 0;
371         datascn.s_nreloc = 0;
372         datascn.s_nlnno = 0;
373         datascn.s_flags = 0x40;
374
375         write(outfd, &filehdr, FILHSZ);
376         write(outfd, &aouthdr, AOUTSZ);
377         write(outfd, &textscn, SCNHSZ);
378         write(outfd, &datascn, SCNHSZ);
379
380         lseek(outfd, textscn.s_scnptr, SEEK_SET);
381         p = malloc(ROUNDUP(textsize, 512));
382         if (p == NULL)
383                 errx(1, "malloc failed");
384         memset(p, 0, ROUNDUP(textsize, 512));
385         lseek(infd, textfpos, SEEK_SET);
386         read(infd, p, textsize);
387         write(outfd, p, ROUNDUP(textsize, 512));
388         free(p);
389
390         lseek(outfd, datascn.s_scnptr, SEEK_SET);
391         p = malloc(ROUNDUP(datasize, 512));
392         if (p == NULL)
393                 errx(1, "malloc failed");
394         memset(p, 0, ROUNDUP(datasize, 512));
395         lseek(infd, datafpos, SEEK_SET);
396         read(infd, p, datasize);
397         write(outfd, p, ROUNDUP(datasize, 512));
398         free(p);
399
400         return (0);
401 }