Add sigtimedwait.o and sigwaitinfo.o.
[dragonfly.git] / usr.sbin / elf2exe / elf2exe.c
CommitLineData
984263bc
MD
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.
1de703da
MD
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 $
984263bc
MD
28 */
29
30/*
31 * Make an ARC firmware executable from an ELF file.
32 */
33
984263bc
MD
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
48typedef 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
61typedef 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
77typedef 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
97int
98open_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
108Elf64_Ehdr *
109load_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
123Elf64_Phdr *
124load_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
137Elf64_Shdr *
138load_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
151char *
152find_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
178int
179open_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
192static char *shstrtab;
193
194char *
195section_name(Elf64_Shdr *shdr, int i)
196{
197 return (shstrtab + shdr[i].sh_name);
198}
199
200int
201section_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 */
212u_int64_t
213section_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 */
223u_int64_t
224section_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 */
234u_int64_t
235section_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 */
246u_int64_t
247section_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
256void
257usage(void)
258{
259 fprintf(stderr, "usage: elf2exe infile outfile\n");
260 exit(1);
261}
262
263int
264main(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}