1*a5175f1eSandvar /* $NetBSD: elf2ecoff.c,v 1.35 2024/02/08 20:11:56 andvar Exp $ */
2559daf50Sjonathan
355e1f3d7Sjonathan /*
4623d454fSjonathan * Copyright (c) 1997 Jonathan Stone
5623d454fSjonathan * All rights reserved.
655e1f3d7Sjonathan * Copyright (c) 1995
755e1f3d7Sjonathan * Ted Lemon (hereinafter referred to as the author)
855e1f3d7Sjonathan *
955e1f3d7Sjonathan * Redistribution and use in source and binary forms, with or without
1055e1f3d7Sjonathan * modification, are permitted provided that the following conditions
1155e1f3d7Sjonathan * are met:
1255e1f3d7Sjonathan * 1. Redistributions of source code must retain the above copyright
1355e1f3d7Sjonathan * notice, this list of conditions and the following disclaimer.
1455e1f3d7Sjonathan * 2. Redistributions in binary form must reproduce the above copyright
1555e1f3d7Sjonathan * notice, this list of conditions and the following disclaimer in the
1655e1f3d7Sjonathan * documentation and/or other materials provided with the distribution.
1755e1f3d7Sjonathan * 3. The name of the author may not be used to endorse or promote products
1855e1f3d7Sjonathan * derived from this software without specific prior written permission.
1955e1f3d7Sjonathan *
2055e1f3d7Sjonathan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
2155e1f3d7Sjonathan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2255e1f3d7Sjonathan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2355e1f3d7Sjonathan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
2455e1f3d7Sjonathan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2555e1f3d7Sjonathan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2655e1f3d7Sjonathan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2755e1f3d7Sjonathan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2855e1f3d7Sjonathan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2955e1f3d7Sjonathan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3055e1f3d7Sjonathan * SUCH DAMAGE.
3155e1f3d7Sjonathan */
3255e1f3d7Sjonathan
3355e1f3d7Sjonathan /* elf2ecoff.c
3455e1f3d7Sjonathan
3555e1f3d7Sjonathan This program converts an elf executable to an ECOFF executable.
3655e1f3d7Sjonathan No symbol table is retained. This is useful primarily in building
3755e1f3d7Sjonathan net-bootable kernels for machines (e.g., DECstation and Alpha) which
3855e1f3d7Sjonathan only support the ECOFF object file format. */
3955e1f3d7Sjonathan
40171d6532Slukem #if HAVE_NBTOOL_CONFIG_H
41171d6532Slukem #include "nbtool_config.h"
4265910421Stv #endif
4365910421Stv
4455e1f3d7Sjonathan #include <sys/types.h>
45552d6a2aSsimonb #include <err.h>
463ed4fcf6Skleink #include <errno.h>
4755e1f3d7Sjonathan #include <fcntl.h>
4855e1f3d7Sjonathan #include <unistd.h>
4958e8bd3bSjonathan #include <sys/exec_elf.h>
5055e1f3d7Sjonathan #include <stdio.h>
5155e1f3d7Sjonathan #include <sys/exec_ecoff.h>
5225afea2dSjonathan #include <stdlib.h>
5355e1f3d7Sjonathan #include <string.h>
5455e1f3d7Sjonathan #include <limits.h>
5555e1f3d7Sjonathan
5625afea2dSjonathan #define ISLAST(p) (p->n_un.n_name == 0 || p->n_un.n_name[0] == 0)
5725afea2dSjonathan
5855e1f3d7Sjonathan struct sect {
59c9ed2107Schristos uint32_t vaddr;
60c9ed2107Schristos uint32_t len;
6155e1f3d7Sjonathan };
6255e1f3d7Sjonathan
63623d454fSjonathan struct elf_syms {
64623d454fSjonathan int nsymbols;
65623d454fSjonathan Elf32_Sym *elf_syms;
66623d454fSjonathan off_t stringsize;
67623d454fSjonathan char *stringtab;
68623d454fSjonathan };
69623d454fSjonathan
70623d454fSjonathan struct ecoff_syms {
71623d454fSjonathan int nsymbols;
72623d454fSjonathan struct ecoff_extsym *ecoff_syms;
73623d454fSjonathan off_t stringsize;
74623d454fSjonathan char *stringtab;
75623d454fSjonathan };
76623d454fSjonathan
7776987894Schristos static int debug = 0;
7876987894Schristos static int needswap;
7925afea2dSjonathan
8076987894Schristos static int phcmp(Elf32_Phdr *, Elf32_Phdr *);
8176987894Schristos static char *saveRead(int, off_t, off_t, const char *);
8276987894Schristos static void safewrite(int, const void *, off_t, const char *);
8376987894Schristos static void copy(int, int, off_t, off_t);
8476987894Schristos static void combine(struct sect *, struct sect *, int);
8576987894Schristos static void translate_syms(struct elf_syms *, struct ecoff_syms *);
86c9ed2107Schristos static void elf_symbol_table_to_ecoff(int, int, struct ecoff32_exechdr *,
8776987894Schristos off_t, off_t, off_t, off_t);
88c9ed2107Schristos static int make_ecoff_section_hdrs(struct ecoff32_exechdr *,
89c9ed2107Schristos struct ecoff32_scnhdr *);
90c9ed2107Schristos static void write_ecoff_symhdr(int, struct ecoff32_exechdr *,
91c9ed2107Schristos struct ecoff32_symhdr *, int32_t, int32_t, int32_t, int32_t);
9276987894Schristos static void pad16(int, int, const char *);
9376987894Schristos static void bswap32_region(int32_t* , int);
9476987894Schristos static void elf_read_syms(struct elf_syms *, int, off_t, off_t, off_t,
9576987894Schristos off_t);
96623d454fSjonathan
97623d454fSjonathan
9825afea2dSjonathan int
main(int argc,char ** argv)9976987894Schristos main(int argc, char **argv)
10055e1f3d7Sjonathan {
10158e8bd3bSjonathan Elf32_Ehdr ex;
10258e8bd3bSjonathan Elf32_Phdr *ph;
10358e8bd3bSjonathan Elf32_Shdr *sh;
10455e1f3d7Sjonathan char *shstrtab;
10555e1f3d7Sjonathan int strtabix, symtabix;
106c37f283fStsutsui size_t i;
107c37f283fStsutsui int pad;
10825afea2dSjonathan struct sect text, data, bss; /* a.out-compatible sections */
10925afea2dSjonathan
110c9ed2107Schristos struct ecoff32_exechdr ep;
111c9ed2107Schristos struct ecoff32_scnhdr esecs[6];
112c9ed2107Schristos struct ecoff32_symhdr symhdr;
11325afea2dSjonathan
11455e1f3d7Sjonathan int infile, outfile;
115c9ed2107Schristos uint32_t cur_vma = UINT32_MAX;
11625afea2dSjonathan int nsecs = 0;
11733176a12Sbouyer int mipsel;
11833176a12Sbouyer
11955e1f3d7Sjonathan
12055e1f3d7Sjonathan text.len = data.len = bss.len = 0;
12155e1f3d7Sjonathan text.vaddr = data.vaddr = bss.vaddr = 0;
12255e1f3d7Sjonathan
12355e1f3d7Sjonathan /* Check args... */
124043bfc92Slukem if (argc < 3 || argc > 4) {
12555e1f3d7Sjonathan usage:
12655e1f3d7Sjonathan fprintf(stderr,
12776987894Schristos "Usage: %s <elf executable> <ECOFF executable> [-s]\n",
12876987894Schristos getprogname());
12955e1f3d7Sjonathan exit(1);
13055e1f3d7Sjonathan }
131043bfc92Slukem if (argc == 4) {
13255e1f3d7Sjonathan if (strcmp(argv[3], "-s"))
13355e1f3d7Sjonathan goto usage;
13455e1f3d7Sjonathan }
13555e1f3d7Sjonathan /* Try the input file... */
13676987894Schristos if ((infile = open(argv[1], O_RDONLY)) < 0)
13776987894Schristos err(1, "Can't open %s for read", argv[1]);
13855e1f3d7Sjonathan /* Read the header, which is at the beginning of the file... */
13955e1f3d7Sjonathan i = read(infile, &ex, sizeof ex);
14076987894Schristos if (i != sizeof ex)
14176987894Schristos err(1, "Short header read from %s", argv[1]);
14233176a12Sbouyer if (ex.e_ident[EI_DATA] == ELFDATA2LSB)
14333176a12Sbouyer mipsel = 1;
14433176a12Sbouyer else if (ex.e_ident[EI_DATA] == ELFDATA2MSB)
14533176a12Sbouyer mipsel = 0;
14676987894Schristos else
14776987894Schristos errx(1, "invalid ELF byte order %d", ex.e_ident[EI_DATA]);
14833176a12Sbouyer #if BYTE_ORDER == BIG_ENDIAN
14933176a12Sbouyer if (mipsel)
15033176a12Sbouyer needswap = 1;
15133176a12Sbouyer else
15233176a12Sbouyer needswap = 0;
15333176a12Sbouyer #elif BYTE_ORDER == LITTLE_ENDIAN
15433176a12Sbouyer if (mipsel)
15533176a12Sbouyer needswap = 0;
15633176a12Sbouyer else
15733176a12Sbouyer needswap = 1;
15833176a12Sbouyer #else
15933176a12Sbouyer #error "unknown endian"
16033176a12Sbouyer #endif
16133176a12Sbouyer
16233176a12Sbouyer if (needswap) {
16333176a12Sbouyer ex.e_type = bswap16(ex.e_type);
16433176a12Sbouyer ex.e_machine = bswap16(ex.e_machine);
16533176a12Sbouyer ex.e_version = bswap32(ex.e_version);
16633176a12Sbouyer ex.e_entry = bswap32(ex.e_entry);
16733176a12Sbouyer ex.e_phoff = bswap32(ex.e_phoff);
16833176a12Sbouyer ex.e_shoff = bswap32(ex.e_shoff);
16933176a12Sbouyer ex.e_flags = bswap32(ex.e_flags);
17033176a12Sbouyer ex.e_ehsize = bswap16(ex.e_ehsize);
17133176a12Sbouyer ex.e_phentsize = bswap16(ex.e_phentsize);
17233176a12Sbouyer ex.e_phnum = bswap16(ex.e_phnum);
17333176a12Sbouyer ex.e_shentsize = bswap16(ex.e_shentsize);
17433176a12Sbouyer ex.e_shnum = bswap16(ex.e_shnum);
17533176a12Sbouyer ex.e_shstrndx = bswap16(ex.e_shstrndx);
17633176a12Sbouyer }
17733176a12Sbouyer
17855e1f3d7Sjonathan /* Read the program headers... */
17958e8bd3bSjonathan ph = (Elf32_Phdr *) saveRead(infile, ex.e_phoff,
18058e8bd3bSjonathan ex.e_phnum * sizeof(Elf32_Phdr), "ph");
18133176a12Sbouyer if (needswap)
182f11583faSsimonb bswap32_region((int32_t*)ph, sizeof(Elf32_Phdr) * ex.e_phnum);
18355e1f3d7Sjonathan /* Read the section headers... */
18458e8bd3bSjonathan sh = (Elf32_Shdr *) saveRead(infile, ex.e_shoff,
18558e8bd3bSjonathan ex.e_shnum * sizeof(Elf32_Shdr), "sh");
18633176a12Sbouyer if (needswap)
187f11583faSsimonb bswap32_region((int32_t*)sh, sizeof(Elf32_Shdr) * ex.e_shnum);
18833176a12Sbouyer
18925afea2dSjonathan /* Read in the section string table. */
19025afea2dSjonathan shstrtab = saveRead(infile, sh[ex.e_shstrndx].sh_offset,
19125afea2dSjonathan sh[ex.e_shstrndx].sh_size, "shstrtab");
19225afea2dSjonathan
19325afea2dSjonathan
194043bfc92Slukem /* Look for the symbol table and string table... Also map section
195043bfc92Slukem * indices to symbol types for a.out */
19625afea2dSjonathan symtabix = 0;
19725afea2dSjonathan strtabix = 0;
198043bfc92Slukem for (i = 0; i < ex.e_shnum; i++) {
19925afea2dSjonathan char *name = shstrtab + sh[i].sh_name;
20025afea2dSjonathan if (!strcmp(name, ".symtab"))
20125afea2dSjonathan symtabix = i;
202043bfc92Slukem else
203043bfc92Slukem if (!strcmp(name, ".strtab"))
20425afea2dSjonathan strtabix = i;
20525afea2dSjonathan
20625afea2dSjonathan }
20755e1f3d7Sjonathan
20876987894Schristos /*
20976987894Schristos * Figure out if we can cram the program header into an ECOFF
210043bfc92Slukem * header... Basically, we can't handle anything but loadable
211043bfc92Slukem * segments, but we can ignore some kinds of segments. We can't
212043bfc92Slukem * handle holes in the address space. Segments may be out of order,
21376987894Schristos * so we sort them first.
21476987894Schristos */
21555e1f3d7Sjonathan
21625afea2dSjonathan qsort(ph, ex.e_phnum, sizeof(Elf32_Phdr),
21725afea2dSjonathan (int (*) (const void *, const void *)) phcmp);
21855e1f3d7Sjonathan
219043bfc92Slukem for (i = 0; i < ex.e_phnum; i++) {
2201d13ed3dSchristos switch (ph[i].p_type) {
2211d13ed3dSchristos case PT_NOTE:
2221d13ed3dSchristos case PT_NULL:
2231d13ed3dSchristos case PT_PHDR:
2241d13ed3dSchristos case PT_MIPS_ABIFLAGS:
2251d13ed3dSchristos case PT_MIPS_REGINFO:
22655e1f3d7Sjonathan /* Section types we can ignore... */
22725afea2dSjonathan if (debug) {
2281d13ed3dSchristos fprintf(stderr, " skipping PH %zu type %#x "
2291d13ed3dSchristos "flags %#x\n",
23025afea2dSjonathan i, ph[i].p_type, ph[i].p_flags);
23125afea2dSjonathan }
23255e1f3d7Sjonathan continue;
2331d13ed3dSchristos default:
23455e1f3d7Sjonathan /* Section types we can't handle... */
23576987894Schristos if (ph[i].p_type != PT_LOAD)
2361d13ed3dSchristos errx(1, "Program header %zu type %#x can't be "
23776987894Schristos "converted", i, ph[i].p_type);
2381d13ed3dSchristos }
23955e1f3d7Sjonathan /* Writable (data) segment? */
240043bfc92Slukem if (ph[i].p_flags & PF_W) {
24155e1f3d7Sjonathan struct sect ndata, nbss;
24255e1f3d7Sjonathan
24358e8bd3bSjonathan ndata.vaddr = ph[i].p_vaddr;
24458e8bd3bSjonathan ndata.len = ph[i].p_filesz;
24558e8bd3bSjonathan nbss.vaddr = ph[i].p_vaddr + ph[i].p_filesz;
24658e8bd3bSjonathan nbss.len = ph[i].p_memsz - ph[i].p_filesz;
24755e1f3d7Sjonathan
24825afea2dSjonathan if (debug) {
249c9b3c34dSandvar fprintf(stderr, " combining PH %zu type %d "
250425b4f39Schristos "flags %#x with data, ndata = %d, "
251c9ed2107Schristos "nbss =%d\n", i, ph[i].p_type,
25276987894Schristos ph[i].p_flags, ndata.len, nbss.len);
25325afea2dSjonathan }
25455e1f3d7Sjonathan combine(&data, &ndata, 0);
25555e1f3d7Sjonathan combine(&bss, &nbss, 1);
256043bfc92Slukem } else {
25755e1f3d7Sjonathan struct sect ntxt;
25855e1f3d7Sjonathan
25958e8bd3bSjonathan ntxt.vaddr = ph[i].p_vaddr;
26058e8bd3bSjonathan ntxt.len = ph[i].p_filesz;
26125afea2dSjonathan if (debug) {
262c9b3c34dSandvar fprintf(stderr, " combining PH %zu type %d "
263425b4f39Schristos "flags %#x with text, len = %d\n",
26425afea2dSjonathan i, ph[i].p_type, ph[i].p_flags, ntxt.len);
26525afea2dSjonathan }
26625afea2dSjonathan combine(&text, &ntxt, 0);
26755e1f3d7Sjonathan }
26855e1f3d7Sjonathan /* Remember the lowest segment start address. */
26958e8bd3bSjonathan if (ph[i].p_vaddr < cur_vma)
27058e8bd3bSjonathan cur_vma = ph[i].p_vaddr;
27155e1f3d7Sjonathan }
27255e1f3d7Sjonathan
27355e1f3d7Sjonathan /* Sections must be in order to be converted... */
27455e1f3d7Sjonathan if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr ||
27576987894Schristos text.vaddr + text.len > data.vaddr ||
27676987894Schristos data.vaddr + data.len > bss.vaddr)
27776987894Schristos errx(1, "Sections ordering prevents a.out conversion");
27855e1f3d7Sjonathan /* If there's a data section but no text section, then the loader
279043bfc92Slukem * combined everything into one section. That needs to be the text
280043bfc92Slukem * section, so just make the data section zero length following text. */
28163fc11e9Stsutsui if (data.len && text.len == 0) {
28255e1f3d7Sjonathan text = data;
28355e1f3d7Sjonathan data.vaddr = text.vaddr + text.len;
28455e1f3d7Sjonathan data.len = 0;
28555e1f3d7Sjonathan }
28655e1f3d7Sjonathan /* If there is a gap between text and data, we'll fill it when we copy
287043bfc92Slukem * the data, so update the length of the text segment as represented
288043bfc92Slukem * in a.out to reflect that, since a.out doesn't allow gaps in the
289043bfc92Slukem * program address space. */
29055e1f3d7Sjonathan if (text.vaddr + text.len < data.vaddr)
29155e1f3d7Sjonathan text.len = data.vaddr - text.vaddr;
29255e1f3d7Sjonathan
29355e1f3d7Sjonathan /* We now have enough information to cons up an a.out header... */
294559daf50Sjonathan ep.a.magic = ECOFF_OMAGIC;
29525afea2dSjonathan ep.a.vstamp = 2 * 256 + 10; /* compatible with version 2.10 */
296559daf50Sjonathan ep.a.tsize = text.len;
297559daf50Sjonathan ep.a.dsize = data.len;
298559daf50Sjonathan ep.a.bsize = bss.len;
29958e8bd3bSjonathan ep.a.entry = ex.e_entry;
300559daf50Sjonathan ep.a.text_start = text.vaddr;
301559daf50Sjonathan ep.a.data_start = data.vaddr;
302559daf50Sjonathan ep.a.bss_start = bss.vaddr;
303559daf50Sjonathan ep.a.gprmask = 0xf3fffffe;
304bfd52621Sperry memset(&ep.a.cprmask, 0, sizeof ep.a.cprmask);
305559daf50Sjonathan ep.a.gp_value = 0; /* unused. */
30655e1f3d7Sjonathan
30733176a12Sbouyer if (mipsel)
308559daf50Sjonathan ep.f.f_magic = ECOFF_MAGIC_MIPSEL;
30933176a12Sbouyer else
3109f3b0a4dSbouyer ep.f.f_magic = ECOFF_MAGIC_MIPSEB;
3119f3b0a4dSbouyer
31225afea2dSjonathan ep.f.f_nscns = 6;
313559daf50Sjonathan ep.f.f_timdat = 0; /* bogus */
314559daf50Sjonathan ep.f.f_symptr = 0;
315c9ed2107Schristos ep.f.f_nsyms = sizeof(struct ecoff32_symhdr);
316559daf50Sjonathan ep.f.f_opthdr = sizeof ep.a;
317*a5175f1eSandvar ep.f.f_flags = 0x100f; /* Stripped, not shareable. */
31855e1f3d7Sjonathan
319bfd52621Sperry memset(esecs, 0, sizeof(esecs));
320559daf50Sjonathan
321043bfc92Slukem /* Make ECOFF section headers, with empty stubs for
322043bfc92Slukem * .rdata/.sdata/.sbss. */
32325afea2dSjonathan make_ecoff_section_hdrs(&ep, esecs);
32425afea2dSjonathan
32525afea2dSjonathan nsecs = ep.f.f_nscns;
32655e1f3d7Sjonathan
32733176a12Sbouyer if (needswap) {
32833176a12Sbouyer ep.f.f_magic = bswap16(ep.f.f_magic);
32933176a12Sbouyer ep.f.f_nscns = bswap16(ep.f.f_nscns);
33033176a12Sbouyer ep.f.f_timdat = bswap32(ep.f.f_timdat);
33133176a12Sbouyer ep.f.f_symptr = bswap32(ep.f.f_symptr);
33233176a12Sbouyer ep.f.f_nsyms = bswap32(ep.f.f_nsyms);
33333176a12Sbouyer ep.f.f_opthdr = bswap16(ep.f.f_opthdr);
33433176a12Sbouyer ep.f.f_flags = bswap16(ep.f.f_flags);
33533176a12Sbouyer ep.a.magic = bswap16(ep.a.magic);
33633176a12Sbouyer ep.a.vstamp = bswap16(ep.a.vstamp);
33733176a12Sbouyer ep.a.tsize = bswap32(ep.a.tsize);
33833176a12Sbouyer ep.a.dsize = bswap32(ep.a.dsize);
33933176a12Sbouyer ep.a.bsize = bswap32(ep.a.bsize);
34033176a12Sbouyer ep.a.entry = bswap32(ep.a.entry);
34133176a12Sbouyer ep.a.text_start = bswap32(ep.a.text_start);
34233176a12Sbouyer ep.a.data_start = bswap32(ep.a.data_start);
34333176a12Sbouyer ep.a.bss_start = bswap32(ep.a.bss_start);
34433176a12Sbouyer ep.a.gprmask = bswap32(ep.a.gprmask);
345f11583faSsimonb bswap32_region((int32_t*)ep.a.cprmask, sizeof(ep.a.cprmask));
34633176a12Sbouyer ep.a.gp_value = bswap32(ep.a.gp_value);
34733176a12Sbouyer for (i = 0; i < sizeof(esecs) / sizeof(esecs[0]); i++) {
34833176a12Sbouyer esecs[i].s_paddr = bswap32(esecs[i].s_paddr);
34933176a12Sbouyer esecs[i].s_vaddr = bswap32(esecs[i].s_vaddr);
35033176a12Sbouyer esecs[i].s_size = bswap32(esecs[i].s_size);
35133176a12Sbouyer esecs[i].s_scnptr = bswap32(esecs[i].s_scnptr);
35233176a12Sbouyer esecs[i].s_relptr = bswap32(esecs[i].s_relptr);
35333176a12Sbouyer esecs[i].s_lnnoptr = bswap32(esecs[i].s_lnnoptr);
35433176a12Sbouyer esecs[i].s_nreloc = bswap16(esecs[i].s_nreloc);
35533176a12Sbouyer esecs[i].s_nlnno = bswap16(esecs[i].s_nlnno);
35633176a12Sbouyer esecs[i].s_flags = bswap32(esecs[i].s_flags);
35733176a12Sbouyer }
35833176a12Sbouyer }
35933176a12Sbouyer
36055e1f3d7Sjonathan /* Make the output file... */
36176987894Schristos if ((outfile = open(argv[2], O_WRONLY | O_CREAT, 0777)) < 0)
36276987894Schristos err(1, "Unable to create %s", argv[2]);
36376987894Schristos
364552d6a2aSsimonb /* Truncate file... */
365552d6a2aSsimonb if (ftruncate(outfile, 0)) {
366552d6a2aSsimonb warn("ftruncate %s", argv[2]);
367552d6a2aSsimonb }
36855e1f3d7Sjonathan /* Write the headers... */
36976987894Schristos safewrite(outfile, &ep.f, sizeof(ep.f), "ep.f: write");
370552d6a2aSsimonb if (debug)
37182d396eaSmatt fprintf(stderr, "wrote %zu byte file header.\n", sizeof(ep.f));
37255e1f3d7Sjonathan
37376987894Schristos safewrite(outfile, &ep.a, sizeof(ep.a), "ep.a: write");
374552d6a2aSsimonb if (debug)
37582d396eaSmatt fprintf(stderr, "wrote %zu byte a.out header.\n", sizeof(ep.a));
37655e1f3d7Sjonathan
37776987894Schristos safewrite(outfile, &esecs, sizeof(esecs[0]) * nsecs, "esecs: write");
378552d6a2aSsimonb if (debug)
37982d396eaSmatt fprintf(stderr, "wrote %zu bytes of section headers.\n",
380623d454fSjonathan sizeof(esecs[0]) * nsecs);
38155e1f3d7Sjonathan
38225afea2dSjonathan
38325afea2dSjonathan pad = ((sizeof ep.f + sizeof ep.a + sizeof esecs) & 15);
384623d454fSjonathan if (pad) {
38555e1f3d7Sjonathan pad = 16 - pad;
38676987894Schristos pad16(outfile, pad, "ipad: write");
387552d6a2aSsimonb if (debug)
388623d454fSjonathan fprintf(stderr, "wrote %d byte pad.\n", pad);
38955e1f3d7Sjonathan }
39055e1f3d7Sjonathan /* Copy the loadable sections. Zero-fill any gaps less than 64k;
391043bfc92Slukem * complain about any zero-filling, and die if we're asked to
392043bfc92Slukem * zero-fill more than 64k. */
393043bfc92Slukem for (i = 0; i < ex.e_phnum; i++) {
394043bfc92Slukem /* Unprocessable sections were handled above, so just verify
395043bfc92Slukem * that the section can be loaded before copying. */
3961899563cSdrochner if (ph[i].p_type == PT_LOAD && ph[i].p_filesz) {
397043bfc92Slukem if (cur_vma != ph[i].p_vaddr) {
398c9ed2107Schristos uint32_t gap = ph[i].p_vaddr - cur_vma;
39955e1f3d7Sjonathan char obuf[1024];
40076987894Schristos if (gap > 65536)
401c9ed2107Schristos errx(1, "Intersegment gap (%d bytes) "
40276987894Schristos "too large", gap);
403552d6a2aSsimonb if (debug)
404c9ed2107Schristos fprintf(stderr, "Warning: %d byte "
40576987894Schristos "intersegment gap.\n", gap);
40655e1f3d7Sjonathan memset(obuf, 0, sizeof obuf);
407043bfc92Slukem while (gap) {
40876987894Schristos int count = write(outfile, obuf,
40976987894Schristos (gap > sizeof obuf
41055e1f3d7Sjonathan ? sizeof obuf : gap));
41176987894Schristos if (count < 0)
41276987894Schristos err(1, "Error writing gap");
41355e1f3d7Sjonathan gap -= count;
41455e1f3d7Sjonathan }
41555e1f3d7Sjonathan }
416552d6a2aSsimonb if (debug)
41776987894Schristos fprintf(stderr, "writing %d bytes...\n",
41876987894Schristos ph[i].p_filesz);
41958e8bd3bSjonathan copy(outfile, infile, ph[i].p_offset, ph[i].p_filesz);
42058e8bd3bSjonathan cur_vma = ph[i].p_vaddr + ph[i].p_filesz;
42155e1f3d7Sjonathan }
42255e1f3d7Sjonathan }
42355e1f3d7Sjonathan
42425afea2dSjonathan
425623d454fSjonathan if (debug)
426425b4f39Schristos fprintf(stderr, "writing syms at offset %#x\n",
427425b4f39Schristos (uint32_t)(ep.f.f_symptr + sizeof(symhdr)));
428623d454fSjonathan
429623d454fSjonathan /* Copy and translate the symbol table... */
430623d454fSjonathan elf_symbol_table_to_ecoff(outfile, infile, &ep,
431623d454fSjonathan sh[symtabix].sh_offset, sh[symtabix].sh_size,
432623d454fSjonathan sh[strtabix].sh_offset, sh[strtabix].sh_size);
433623d454fSjonathan
43425afea2dSjonathan /*
43525afea2dSjonathan * Write a page of padding for boot PROMS that read entire pages.
43625afea2dSjonathan * Without this, they may attempt to read past the end of the
43725afea2dSjonathan * data section, incur an error, and refuse to boot.
43825afea2dSjonathan */
43925afea2dSjonathan {
44025afea2dSjonathan char obuf[4096];
44125afea2dSjonathan memset(obuf, 0, sizeof obuf);
44276987894Schristos if (write(outfile, obuf, sizeof(obuf)) != sizeof(obuf))
44376987894Schristos err(1, "Error writing PROM padding");
44425afea2dSjonathan }
44525afea2dSjonathan
44655e1f3d7Sjonathan /* Looks like we won... */
44776987894Schristos return 0;
44855e1f3d7Sjonathan }
44955e1f3d7Sjonathan
45076987894Schristos static void
copy(int out,int in,off_t offset,off_t size)45163fc11e9Stsutsui copy(int out, int in, off_t offset, off_t size)
45255e1f3d7Sjonathan {
45355e1f3d7Sjonathan char ibuf[4096];
454c37f283fStsutsui size_t remaining, cur, count;
45555e1f3d7Sjonathan
45689c5a767Ssoren /* Go to the start of the ELF symbol table... */
45776987894Schristos if (lseek(in, offset, SEEK_SET) < 0)
45876987894Schristos err(1, "copy: lseek");
45955e1f3d7Sjonathan remaining = size;
460043bfc92Slukem while (remaining) {
46155e1f3d7Sjonathan cur = remaining;
46255e1f3d7Sjonathan if (cur > sizeof ibuf)
46355e1f3d7Sjonathan cur = sizeof ibuf;
46455e1f3d7Sjonathan remaining -= cur;
46576987894Schristos if ((count = read(in, ibuf, cur)) != cur)
46676987894Schristos err(1, "copy: short read");
46776987894Schristos safewrite(out, ibuf, cur, "copy: write");
46855e1f3d7Sjonathan }
46955e1f3d7Sjonathan }
47076987894Schristos
47155e1f3d7Sjonathan /* Combine two segments, which must be contiguous. If pad is true, it's
47255e1f3d7Sjonathan okay for there to be padding between. */
47376987894Schristos static void
combine(struct sect * base,struct sect * new,int pad)47463fc11e9Stsutsui combine(struct sect *base, struct sect *new, int pad)
47555e1f3d7Sjonathan {
47663fc11e9Stsutsui
47763fc11e9Stsutsui if (base->len == 0)
47855e1f3d7Sjonathan *base = *new;
479043bfc92Slukem else
480043bfc92Slukem if (new->len) {
481043bfc92Slukem if (base->vaddr + base->len != new->vaddr) {
48255e1f3d7Sjonathan if (pad)
48355e1f3d7Sjonathan base->len = new->vaddr - base->vaddr;
48476987894Schristos else
48576987894Schristos errx(1, "Non-contiguous data can't be "
48676987894Schristos "converted");
48755e1f3d7Sjonathan }
48855e1f3d7Sjonathan base->len += new->len;
48955e1f3d7Sjonathan }
49055e1f3d7Sjonathan }
49155e1f3d7Sjonathan
49276987894Schristos static int
phcmp(Elf32_Phdr * h1,Elf32_Phdr * h2)49363fc11e9Stsutsui phcmp(Elf32_Phdr *h1, Elf32_Phdr *h2)
49455e1f3d7Sjonathan {
49563fc11e9Stsutsui
49658e8bd3bSjonathan if (h1->p_vaddr > h2->p_vaddr)
49755e1f3d7Sjonathan return 1;
498043bfc92Slukem else
499043bfc92Slukem if (h1->p_vaddr < h2->p_vaddr)
50055e1f3d7Sjonathan return -1;
50155e1f3d7Sjonathan else
50255e1f3d7Sjonathan return 0;
50355e1f3d7Sjonathan }
50455e1f3d7Sjonathan
50576987894Schristos static char *
saveRead(int file,off_t offset,off_t len,const char * name)506c37f283fStsutsui saveRead(int file, off_t offset, off_t len, const char *name)
50755e1f3d7Sjonathan {
50855e1f3d7Sjonathan char *tmp;
50955e1f3d7Sjonathan int count;
51055e1f3d7Sjonathan off_t off;
51163fc11e9Stsutsui
51276987894Schristos if ((off = lseek(file, offset, SEEK_SET)) < 0)
51376987894Schristos err(1, "%s: fseek", name);
51476987894Schristos if ((tmp = malloc(len)) == NULL)
515bb0b3debSchristos err(1, "%s: Can't allocate %jd bytes", name, (intmax_t)len);
51655e1f3d7Sjonathan count = read(file, tmp, len);
51776987894Schristos if (count != len)
51876987894Schristos err(1, "%s: short read", name);
51955e1f3d7Sjonathan return tmp;
52055e1f3d7Sjonathan }
52125afea2dSjonathan
52276987894Schristos static void
safewrite(int outfile,const void * buf,off_t len,const char * msg)523c37f283fStsutsui safewrite(int outfile, const void *buf, off_t len, const char *msg)
524623d454fSjonathan {
52576987894Schristos ssize_t written;
52663fc11e9Stsutsui
527c37f283fStsutsui written = write(outfile, buf, len);
52876987894Schristos if (written != len)
52976987894Schristos err(1, "%s", msg);
530623d454fSjonathan }
531623d454fSjonathan
53225afea2dSjonathan
53325afea2dSjonathan /*
534623d454fSjonathan * Output only three ECOFF sections, corresponding to ELF psecs
535623d454fSjonathan * for text, data, and bss.
53625afea2dSjonathan */
53776987894Schristos static int
make_ecoff_section_hdrs(struct ecoff32_exechdr * ep,struct ecoff32_scnhdr * esecs)538c9ed2107Schristos make_ecoff_section_hdrs(struct ecoff32_exechdr *ep, struct ecoff32_scnhdr *esecs)
53925afea2dSjonathan {
54063fc11e9Stsutsui
54125afea2dSjonathan ep->f.f_nscns = 6; /* XXX */
54225afea2dSjonathan
54325afea2dSjonathan strcpy(esecs[0].s_name, ".text");
54425afea2dSjonathan strcpy(esecs[1].s_name, ".data");
54525afea2dSjonathan strcpy(esecs[2].s_name, ".bss");
54625afea2dSjonathan
54725afea2dSjonathan esecs[0].s_paddr = esecs[0].s_vaddr = ep->a.text_start;
54825afea2dSjonathan esecs[1].s_paddr = esecs[1].s_vaddr = ep->a.data_start;
54925afea2dSjonathan esecs[2].s_paddr = esecs[2].s_vaddr = ep->a.bss_start;
55025afea2dSjonathan esecs[0].s_size = ep->a.tsize;
55125afea2dSjonathan esecs[1].s_size = ep->a.dsize;
55225afea2dSjonathan esecs[2].s_size = ep->a.bsize;
55325afea2dSjonathan
554c9ed2107Schristos esecs[0].s_scnptr = ECOFF32_TXTOFF(ep);
555c9ed2107Schristos esecs[1].s_scnptr = ECOFF32_DATOFF(ep);
55625afea2dSjonathan #if 0
55725afea2dSjonathan esecs[2].s_scnptr = esecs[1].s_scnptr +
558c9ed2107Schristos ECOFF_ROUND(esecs[1].s_size, ECOFF32_SEGMENT_ALIGNMENT(ep));
55925afea2dSjonathan #endif
56025afea2dSjonathan
561623d454fSjonathan esecs[0].s_relptr = esecs[1].s_relptr = esecs[2].s_relptr = 0;
562623d454fSjonathan esecs[0].s_lnnoptr = esecs[1].s_lnnoptr = esecs[2].s_lnnoptr = 0;
56325afea2dSjonathan esecs[0].s_nreloc = esecs[1].s_nreloc = esecs[2].s_nreloc = 0;
56425afea2dSjonathan esecs[0].s_nlnno = esecs[1].s_nlnno = esecs[2].s_nlnno = 0;
56525afea2dSjonathan
56625afea2dSjonathan esecs[1].s_flags = 0x100; /* ECOFF rdata */
56725afea2dSjonathan esecs[3].s_flags = 0x200; /* ECOFF sdata */
56825afea2dSjonathan esecs[4].s_flags = 0x400; /* ECOFF sbss */
56925afea2dSjonathan
57025afea2dSjonathan /*
571623d454fSjonathan * Set the symbol-table offset to point at the end of any
572623d454fSjonathan * sections we loaded above, so later code can use it to write
573623d454fSjonathan * symbol table info..
57425afea2dSjonathan */
57525afea2dSjonathan ep->f.f_symptr = esecs[1].s_scnptr + esecs[1].s_size;
57625afea2dSjonathan return (ep->f.f_nscns);
57725afea2dSjonathan }
578623d454fSjonathan
579623d454fSjonathan
580623d454fSjonathan /*
581623d454fSjonathan * Write the ECOFF symbol header.
582623d454fSjonathan * Guess at how big the symbol table will be.
583623d454fSjonathan * Mark all symbols as EXTERN (for now).
584623d454fSjonathan */
58576987894Schristos static void
write_ecoff_symhdr(int out,struct ecoff32_exechdr * ep,struct ecoff32_symhdr * symhdrp,int32_t nesyms,int32_t extsymoff,int32_t extstroff,int32_t strsize)586c9ed2107Schristos write_ecoff_symhdr(int out, struct ecoff32_exechdr *ep,
587c9ed2107Schristos struct ecoff32_symhdr *symhdrp, int32_t nesyms,
588c9ed2107Schristos int32_t extsymoff, int32_t extstroff, int32_t strsize)
589623d454fSjonathan {
59063fc11e9Stsutsui
591623d454fSjonathan if (debug)
59276987894Schristos fprintf(stderr,
593425b4f39Schristos "writing symhdr for %d entries at offset %#x\n",
594c9ed2107Schristos nesyms, ep->f.f_symptr);
595623d454fSjonathan
596c9ed2107Schristos ep->f.f_nsyms = sizeof(struct ecoff32_symhdr);
597623d454fSjonathan
598bfd52621Sperry memset(symhdrp, 0, sizeof(*symhdrp));
599623d454fSjonathan symhdrp->esymMax = nesyms;
600623d454fSjonathan symhdrp->magic = 0x7009;/* XXX */
601623d454fSjonathan symhdrp->cbExtOffset = extsymoff;
602623d454fSjonathan symhdrp->cbSsExtOffset = extstroff;
603623d454fSjonathan
604623d454fSjonathan symhdrp->issExtMax = strsize;
605623d454fSjonathan if (debug)
606623d454fSjonathan fprintf(stderr,
607c9ed2107Schristos "ECOFF symhdr: symhdr %zx, strsize %x, symsize %zx\n",
608623d454fSjonathan sizeof(*symhdrp), strsize,
609c9ed2107Schristos (nesyms * sizeof(struct ecoff32_extsym)));
610623d454fSjonathan
61133176a12Sbouyer if (needswap) {
612f11583faSsimonb bswap32_region(&symhdrp->ilineMax,
61333176a12Sbouyer sizeof(*symhdrp) - sizeof(symhdrp->magic) -
61433176a12Sbouyer sizeof(symhdrp->ilineMax));
61533176a12Sbouyer symhdrp->magic = bswap16(symhdrp->magic);
61633176a12Sbouyer symhdrp->ilineMax = bswap16(symhdrp->ilineMax);
61733176a12Sbouyer }
61833176a12Sbouyer
619623d454fSjonathan safewrite(out, symhdrp, sizeof(*symhdrp),
62076987894Schristos "writing symbol header");
621623d454fSjonathan }
622623d454fSjonathan
623623d454fSjonathan
62476987894Schristos static void
elf_read_syms(struct elf_syms * elfsymsp,int in,off_t symoff,off_t symsize,off_t stroff,off_t strsize)62563fc11e9Stsutsui elf_read_syms(struct elf_syms *elfsymsp, int in, off_t symoff, off_t symsize,
62663fc11e9Stsutsui off_t stroff, off_t strsize)
627623d454fSjonathan {
628c9ed2107Schristos int nsyms;
62933176a12Sbouyer int i;
630623d454fSjonathan nsyms = symsize / sizeof(Elf32_Sym);
631623d454fSjonathan
632623d454fSjonathan /* Suck in the ELF symbol list... */
633623d454fSjonathan elfsymsp->elf_syms = (Elf32_Sym *)
634623d454fSjonathan saveRead(in, symoff, nsyms * sizeof(Elf32_Sym),
635623d454fSjonathan "ELF symboltable");
636623d454fSjonathan elfsymsp->nsymbols = nsyms;
63733176a12Sbouyer if (needswap) {
63833176a12Sbouyer for (i = 0; i < nsyms; i++) {
63933176a12Sbouyer Elf32_Sym *s = &elfsymsp->elf_syms[i];
64033176a12Sbouyer s->st_name = bswap32(s->st_name);
64133176a12Sbouyer s->st_value = bswap32(s->st_value);
64233176a12Sbouyer s->st_size = bswap32(s->st_size);
64333176a12Sbouyer s->st_shndx = bswap16(s->st_shndx);
64433176a12Sbouyer }
64533176a12Sbouyer }
646623d454fSjonathan
647623d454fSjonathan /* Suck in the ELF string table... */
648623d454fSjonathan elfsymsp->stringtab = (char *)
649623d454fSjonathan saveRead(in, stroff, strsize, "ELF string table");
650623d454fSjonathan elfsymsp->stringsize = strsize;
651623d454fSjonathan }
652623d454fSjonathan
653623d454fSjonathan
65476987894Schristos static void
elf_symbol_table_to_ecoff(int out,int in,struct ecoff32_exechdr * ep,off_t symoff,off_t symsize,off_t stroff,off_t strsize)655c9ed2107Schristos elf_symbol_table_to_ecoff(int out, int in, struct ecoff32_exechdr *ep,
65663fc11e9Stsutsui off_t symoff, off_t symsize, off_t stroff, off_t strsize)
657623d454fSjonathan {
658623d454fSjonathan
659623d454fSjonathan struct elf_syms elfsymtab;
660623d454fSjonathan struct ecoff_syms ecoffsymtab;
661c9ed2107Schristos uint32_t ecoff_symhdr_off, symtaboff, stringtaboff;
662c9ed2107Schristos uint32_t nextoff, symtabsize, ecoff_strsize;
66333176a12Sbouyer int nsyms, i;
664c9ed2107Schristos struct ecoff32_symhdr symhdr;
665623d454fSjonathan int padding;
666623d454fSjonathan
667623d454fSjonathan /* Read in the ELF symbols. */
668623d454fSjonathan elf_read_syms(&elfsymtab, in, symoff, symsize, stroff, strsize);
669623d454fSjonathan
670623d454fSjonathan /* Approximate translation to ECOFF. */
671623d454fSjonathan translate_syms(&elfsymtab, &ecoffsymtab);
672623d454fSjonathan nsyms = ecoffsymtab.nsymbols;
673623d454fSjonathan
674623d454fSjonathan /* Compute output ECOFF symbol- and string-table offsets. */
675623d454fSjonathan ecoff_symhdr_off = ep->f.f_symptr;
676623d454fSjonathan
677623d454fSjonathan nextoff = ecoff_symhdr_off + sizeof(struct ecoff_symhdr);
678623d454fSjonathan stringtaboff = nextoff;
679623d454fSjonathan ecoff_strsize = ECOFF_ROUND(ecoffsymtab.stringsize,
680c9ed2107Schristos (ECOFF32_SEGMENT_ALIGNMENT(ep)));
681623d454fSjonathan
682623d454fSjonathan
683623d454fSjonathan nextoff = stringtaboff + ecoff_strsize;
684623d454fSjonathan symtaboff = nextoff;
685623d454fSjonathan symtabsize = nsyms * sizeof(struct ecoff_extsym);
686c9ed2107Schristos symtabsize = ECOFF_ROUND(symtabsize, ECOFF32_SEGMENT_ALIGNMENT(ep));
687623d454fSjonathan
688623d454fSjonathan /* Write out the symbol header ... */
689623d454fSjonathan write_ecoff_symhdr(out, ep, &symhdr, nsyms, symtaboff,
690623d454fSjonathan stringtaboff, ecoffsymtab.stringsize);
691623d454fSjonathan
692623d454fSjonathan /* Write out the string table... */
693623d454fSjonathan padding = ecoff_strsize - ecoffsymtab.stringsize;
694623d454fSjonathan safewrite(out, ecoffsymtab.stringtab, ecoffsymtab.stringsize,
69576987894Schristos "string table: write");
696623d454fSjonathan if (padding)
69776987894Schristos pad16(out, padding, "string table: padding");
698623d454fSjonathan
699623d454fSjonathan
700623d454fSjonathan /* Write out the symbol table... */
701623d454fSjonathan padding = symtabsize - (nsyms * sizeof(struct ecoff_extsym));
70233176a12Sbouyer
70333176a12Sbouyer for (i = 0; i < nsyms; i++) {
70433176a12Sbouyer struct ecoff_extsym *es = &ecoffsymtab.ecoff_syms[i];
70533176a12Sbouyer es->es_flags = bswap16(es->es_flags);
70633176a12Sbouyer es->es_ifd = bswap16(es->es_ifd);
70733176a12Sbouyer bswap32_region(&es->es_strindex,
70833176a12Sbouyer sizeof(*es) - sizeof(es->es_flags) - sizeof(es->es_ifd));
70933176a12Sbouyer }
710623d454fSjonathan safewrite(out, ecoffsymtab.ecoff_syms,
711623d454fSjonathan nsyms * sizeof(struct ecoff_extsym),
71276987894Schristos "symbol table: write");
713623d454fSjonathan if (padding)
71476987894Schristos pad16(out, padding, "symbols: padding");
715623d454fSjonathan }
716623d454fSjonathan
717623d454fSjonathan
718623d454fSjonathan
719623d454fSjonathan /*
720c9b3c34dSandvar * In-memory translation of ELF symbols to ECOFF.
721623d454fSjonathan */
72276987894Schristos static void
translate_syms(struct elf_syms * elfp,struct ecoff_syms * ecoffp)72363fc11e9Stsutsui translate_syms(struct elf_syms *elfp, struct ecoff_syms *ecoffp)
724623d454fSjonathan {
725623d454fSjonathan
726623d454fSjonathan int i;
727623d454fSjonathan char *oldstringbase;
728623d454fSjonathan char *newstrings, *nsp;
729623d454fSjonathan
730623d454fSjonathan int nsyms, idx;
731623d454fSjonathan
732623d454fSjonathan nsyms = elfp->nsymbols;
733623d454fSjonathan oldstringbase = elfp->stringtab;
734623d454fSjonathan
735623d454fSjonathan /* Allocate space for corresponding ECOFF symbols. */
736bfd52621Sperry memset(ecoffp, 0, sizeof(*ecoffp));
737623d454fSjonathan
738623d454fSjonathan ecoffp->nsymbols = 0;
739623d454fSjonathan ecoffp->ecoff_syms = malloc(sizeof(struct ecoff_extsym) * nsyms);
740623d454fSjonathan
741623d454fSjonathan /* we are going to be no bigger than the ELF symbol table. */
742623d454fSjonathan ecoffp->stringsize = elfp->stringsize;
743623d454fSjonathan ecoffp->stringtab = malloc(elfp->stringsize);
744623d454fSjonathan
745623d454fSjonathan newstrings = (char *) ecoffp->stringtab;
746623d454fSjonathan nsp = (char *) ecoffp->stringtab;
74776987894Schristos if (newstrings == NULL)
74876987894Schristos errx(1, "No memory for new string table");
749623d454fSjonathan /* Copy and translate symbols... */
750623d454fSjonathan idx = 0;
751623d454fSjonathan for (i = 0; i < nsyms; i++) {
752fe3f8679Schristos int binding;
753623d454fSjonathan
7541899563cSdrochner binding = ELF32_ST_BIND((elfp->elf_syms[i].st_info));
755623d454fSjonathan
756623d454fSjonathan /* skip strange symbols */
757623d454fSjonathan if (binding == 0) {
758623d454fSjonathan continue;
759623d454fSjonathan }
760623d454fSjonathan /* Copy the symbol into the new table */
761623d454fSjonathan strcpy(nsp, oldstringbase + elfp->elf_syms[i].st_name);
762623d454fSjonathan ecoffp->ecoff_syms[idx].es_strindex = nsp - newstrings;
763623d454fSjonathan nsp += strlen(nsp) + 1;
764623d454fSjonathan
765623d454fSjonathan /* translate symbol types to ECOFF XXX */
766623d454fSjonathan ecoffp->ecoff_syms[idx].es_type = 1;
767623d454fSjonathan ecoffp->ecoff_syms[idx].es_class = 5;
768623d454fSjonathan
769623d454fSjonathan /* Symbol values in executables should be compatible. */
770623d454fSjonathan ecoffp->ecoff_syms[idx].es_value = elfp->elf_syms[i].st_value;
771623d454fSjonathan ecoffp->ecoff_syms[idx].es_symauxindex = 0xfffff;
772623d454fSjonathan
773623d454fSjonathan idx++;
774623d454fSjonathan }
775623d454fSjonathan
776623d454fSjonathan ecoffp->nsymbols = idx;
777623d454fSjonathan ecoffp->stringsize = nsp - newstrings;
778623d454fSjonathan }
779623d454fSjonathan /*
780623d454fSjonathan * pad to a 16-byte boundary
781623d454fSjonathan */
78276987894Schristos static void
pad16(int fd,int size,const char * msg)783623d454fSjonathan pad16(int fd, int size, const char *msg)
784623d454fSjonathan {
78563fc11e9Stsutsui
786623d454fSjonathan safewrite(fd, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0", size, msg);
787623d454fSjonathan }
78833176a12Sbouyer
78933176a12Sbouyer /* swap a 32bit region */
79076987894Schristos static void
bswap32_region(int32_t * p,int len)791f11583faSsimonb bswap32_region(int32_t* p, int len)
79233176a12Sbouyer {
793c37f283fStsutsui size_t i;
79433176a12Sbouyer
795f11583faSsimonb for (i = 0; i < len / sizeof(int32_t); i++, p++)
79633176a12Sbouyer *p = bswap32(*p);
79733176a12Sbouyer }
798