2 * Copyright (c) 1999 Stefan Esser
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
28 * Make an ARC firmware executable from an ELF file.
32 static const char rcsid[] =
33 "$FreeBSD: src/usr.sbin/elf2exe/elf2exe.c,v 1.6.2.1 2000/07/20 10:35:23 kris Exp $";
36 #include <sys/types.h>
37 #include <sys/elf64.h>
46 #define ALPHA_FMAGIC 0x184
50 typedef struct filehdr {
61 #define ALPHA_AMAGIC 0407
63 typedef struct aouthdr {
70 u_int32_t a_text_start;
71 u_int32_t a_data_start;
72 u_int32_t a_bss_start;
74 u_int32_t a_cprmask[4];
79 typedef struct scnhdr {
93 #define ROUNDUP(a,b) ((((a) -1) | ((b) -1)) +1)
96 * initialization subroutines
100 open_elffile(char *filename)
102 int fileno = open(filename, O_RDONLY);
105 err(1, "%s", filename);
111 load_ehdr(int fileno)
114 size_t bytes = sizeof(*ehdr);
116 ehdr = malloc(bytes);
118 lseek(fileno, 0, SEEK_SET);
119 if (read(fileno, ehdr, bytes) != bytes)
120 errx(1, "file truncated (ehdr)");
126 load_phdr(int fileno, Elf64_Ehdr *ehdr)
128 size_t bytes = ehdr->e_phentsize * ehdr->e_phnum;
129 Elf64_Phdr *phdr = malloc(bytes);
132 lseek(fileno, ehdr->e_phoff, SEEK_SET);
133 if (read(fileno, phdr, bytes) != bytes)
134 errx(1, "file truncated (phdr)");
140 load_shdr(int fileno, Elf64_Ehdr *ehdr)
142 size_t bytes = ehdr->e_shentsize * ehdr->e_shnum;
143 Elf64_Shdr *shdr = malloc(bytes);
146 lseek(fileno, ehdr->e_shoff, SEEK_SET);
147 if (read(fileno, shdr, bytes) != bytes)
148 errx(1, "file truncated (shdr)");
154 find_shstrtable(int fileno, int sections, Elf64_Shdr *shdr)
157 char *shstrtab = NULL;
158 int i, shstrtabindex;
160 for (i = 0; shstrtab == NULL && i < sections; i++) {
161 if (shdr[i].sh_type == 3 && shdr[i].sh_flags == 0) {
164 bytes = shdr[shstrtabindex].sh_size;
165 shstrtab = malloc(bytes);
166 if (shstrtab == NULL)
167 errx(1, "malloc failed");
168 lseek(fileno, shdr[shstrtabindex].sh_offset, SEEK_SET);
169 read(fileno, shstrtab, bytes);
171 if (strcmp (shstrtab + shdr[i].sh_name, ".shstrtab")) {
181 open_exefile(char *filename)
183 int fileno = open(filename, O_RDWR | O_TRUNC | O_CREAT, 0666);
186 err(1, "%s", filename);
191 * utility subroutines
194 static char *shstrtab;
197 section_name(Elf64_Shdr *shdr, int i)
199 return (shstrtab + shdr[i].sh_name);
203 section_index(Elf64_Shdr *shdr, int sections, char *name)
207 for (i = 0; i < sections; i++)
208 if (strcmp (name, section_name(shdr, i)) == 0)
213 /* first byte of section */
215 section_start(Elf64_Shdr *shdr, int sections, char *name)
217 int i = section_index(shdr, sections, name);
221 return (shdr[i].sh_addr);
224 /* last byte of section */
226 section_end(Elf64_Shdr *shdr, int sections, char *name)
228 int i = section_index(shdr, sections, name);
232 return (shdr[i].sh_addr + shdr[i].sh_size -1);
235 /* last byte of section */
237 section_size(Elf64_Shdr *shdr, int sections, char *name)
239 int i = section_index(shdr, sections, name);
244 return (shdr[i].sh_size);
247 /* file position of section start */
249 section_fpos(Elf64_Shdr *shdr, int sections, char *name)
251 int i = section_index(shdr, sections, name);
255 return (shdr[i].sh_offset);
261 fprintf(stderr, "usage: elf2exe infile outfile\n");
266 main(int argc, char** argv)
274 SCNHDR textscn, datascn;
275 u_int64_t textstart, textsize, textsize2, textfsize, textfpos;
276 u_int64_t datastart, datasize, datafsize, datafpos;
277 u_int64_t bssstart, bsssize;
285 infd = open_elffile(argv[1]);
286 ehdr = load_ehdr(infd);
289 errx(1, "cannot read Elf Header\n");
291 sections = ehdr->e_shnum;
292 progentry = ehdr->e_entry;
294 phdr = load_phdr(infd, ehdr);
295 shdr = load_shdr(infd, ehdr);
296 outfd = open_exefile(argv[2]);
298 shstrtab = find_shstrtable(infd, sections, shdr);
300 for (i = 1; i < sections; i++) {
301 printf("section %d (%s): "
302 "type=%x flags=0%llx "
303 "offs=%llx size=%llx addr=%llx\n",
304 i, shstrtab + shdr[i].sh_name,
305 shdr[i].sh_type, (long long)shdr[i].sh_flags,
306 (long long)shdr[i].sh_offset, (long long)shdr[i].sh_size,
307 (long long)shdr[i].sh_addr);
310 textstart = section_start(shdr, sections, ".text");
311 textsize = section_size(shdr, sections, ".text");
312 textsize2 = section_end(shdr, sections, ".rodata") - textstart +1;
313 if (textsize < textsize2)
314 textsize = textsize2;
315 textfsize = ROUNDUP(textsize, 512);
316 textfpos = section_fpos(shdr, sections, ".text");
318 datastart = section_start(shdr, sections, ".data");
319 datasize = section_start(shdr, sections, ".bss") - datastart;
320 datafsize = ROUNDUP(datasize, 512);
321 datafpos = section_fpos(shdr, sections, ".data");
323 bssstart = section_start(shdr, sections, ".bss");
324 bsssize = section_size(shdr, sections, ".bss");
326 printf("text: %llx(%llx) @%llx data: %llx(%llx) @%llx "
328 (long long)textstart, (long long)textsize, (long long)textfpos,
329 (long long)datastart, (long long)datasize, (long long)datafpos,
330 (long long)bssstart, (long long)bsssize);
332 memset(&filehdr, 0, sizeof filehdr);
333 memset(&aouthdr, 0, sizeof aouthdr);
334 memset(&textscn, 0, sizeof textscn);
335 memset(&datascn, 0, sizeof datascn);
337 filehdr.f_magic = ALPHA_FMAGIC;
339 filehdr.f_timdat = time(0);
340 filehdr.f_symptr = 0;
342 filehdr.f_opthdr = AOUTSZ;
343 filehdr.f_flags = 0x010f;
345 aouthdr.a_magic = ALPHA_AMAGIC;
346 aouthdr.a_vstamp = 0x5004;
347 aouthdr.a_tsize = textfsize;
348 aouthdr.a_dsize = datafsize;
349 aouthdr.a_bsize = bsssize;
350 aouthdr.a_entry = progentry;
351 aouthdr.a_text_start = textstart;
352 aouthdr.a_data_start = datastart;
353 aouthdr.a_bss_start = bssstart;
355 strcpy(textscn.s_name, ".text");
356 textscn.s_fill = textsize;
357 textscn.s_vaddr = textstart;
358 textscn.s_size = textfsize;
359 textscn.s_scnptr = 0x200;
360 textscn.s_relptr = 0;
361 textscn.s_lnnoptr = 0;
362 textscn.s_nreloc = 0;
364 textscn.s_flags = 0x20;
366 strcpy(datascn.s_name, ".data");
367 datascn.s_fill = datasize;
368 datascn.s_vaddr = datastart;
369 datascn.s_size = datafsize;
370 datascn.s_scnptr = 0x200 + textfsize;
371 datascn.s_relptr = 0;
372 datascn.s_lnnoptr = 0;
373 datascn.s_nreloc = 0;
375 datascn.s_flags = 0x40;
377 write(outfd, &filehdr, FILHSZ);
378 write(outfd, &aouthdr, AOUTSZ);
379 write(outfd, &textscn, SCNHSZ);
380 write(outfd, &datascn, SCNHSZ);
382 lseek(outfd, textscn.s_scnptr, SEEK_SET);
383 p = malloc(ROUNDUP(textsize, 512));
385 errx(1, "malloc failed");
386 memset(p, 0, ROUNDUP(textsize, 512));
387 lseek(infd, textfpos, SEEK_SET);
388 read(infd, p, textsize);
389 write(outfd, p, ROUNDUP(textsize, 512));
392 lseek(outfd, datascn.s_scnptr, SEEK_SET);
393 p = malloc(ROUNDUP(datasize, 512));
395 errx(1, "malloc failed");
396 memset(p, 0, ROUNDUP(datasize, 512));
397 lseek(infd, datafpos, SEEK_SET);
398 read(infd, p, datasize);
399 write(outfd, p, ROUNDUP(datasize, 512));