diff options
author | syl <syl@openbsd.org> | 2013-11-01 14:47:47 +0000 |
---|---|---|
committer | syl <syl@openbsd.org> | 2013-11-01 14:47:47 +0000 |
commit | 75e5de18dccfd6f054cdafaebd76bf873f68dc4e (patch) | |
tree | 204ffcef0e7ae2091e994f5f79991272fd91205c /usr.sbin/mkuboot | |
parent | Send pflow(4) packets in the correct rdomain. (diff) | |
download | wireguard-openbsd-75e5de18dccfd6f054cdafaebd76bf873f68dc4e.tar.xz wireguard-openbsd-75e5de18dccfd6f054cdafaebd76bf873f68dc4e.zip |
Fix endianess for big endian architecture.
Works with macppc.
ok miod@
Diffstat (limited to 'usr.sbin/mkuboot')
-rw-r--r-- | usr.sbin/mkuboot/copy_elf.c | 156 |
1 files changed, 89 insertions, 67 deletions
diff --git a/usr.sbin/mkuboot/copy_elf.c b/usr.sbin/mkuboot/copy_elf.c index 1b7c603d49e..abf19612a75 100644 --- a/usr.sbin/mkuboot/copy_elf.c +++ b/usr.sbin/mkuboot/copy_elf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: copy_elf.c,v 1.1 2013/10/28 09:00:06 patrick Exp $ */ +/* $OpenBSD: copy_elf.c,v 1.2 2013/11/01 14:47:47 syl Exp $ */ /* * Copyright (c) 2013 Miodrag Vallat. @@ -24,6 +24,16 @@ #include <sys/exec_elf.h> +#if defined(ELFSIZE) && (ELFSIZE == 32) +#define elfoff2h(x) letoh32(x) +#define h2elfoff(x) htole32(x) +#elif defined(ELFSIZE) && (ELFSIZE == 64) +#define elfoff2h(x) letoh64(x) +#define h2elfoff(x) htole64(x) +#else +#error "unknown elf size" +#endif + struct image_header; #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) @@ -32,11 +42,12 @@ extern u_long copy_data(int, const char *, int, const char *, u_long, struct image_header *, Elf_Word); u_long copy_mem(void *, int, const char *, u_long, struct image_header *, Elf_Word); -extern u_long fill_zeroes(int, const char *, u_long, struct image_header *, Elf_Word); +extern u_long fill_zeroes(int, const char *, u_long, struct image_header *, + Elf_Word); u_long -ELFNAME(copy_elf)(int ifd, const char *iname, int ofd, const char *oname, u_long crc, - struct image_header *ih) +ELFNAME(copy_elf)(int ifd, const char *iname, int ofd, const char *oname, + u_long crc, struct image_header *ih) { ssize_t nbytes; Elf_Ehdr ehdr, elf; @@ -54,32 +65,31 @@ ELFNAME(copy_elf)(int ifd, const char *iname, int ofd, const char *oname, u_long elf = ehdr; - if (lseek(ifd, (off_t)elf.e_shoff, SEEK_SET) == -1) { + if (lseek(ifd, (off_t)elfoff2h(elf.e_shoff), SEEK_SET) == -1) err(1, "%s unable to seek to section header", iname); - } - sz = elf.e_shnum * sizeof(Elf_Shdr); + sz = letoh16(elf.e_shnum) * sizeof(Elf_Shdr); shp = calloc(sz, 1); - if (read(ifd, shp, sz) != sz) { + if (read(ifd, shp, sz) != sz) err(1, "%s: read section headers", iname); - } + wshp = calloc(sz, 1); memcpy(wshp, shp, sz); - /* first walk the load sections to find the kernel addresses */ /* next we walk the sections to find the * location of esym (first address of data space */ - for (i = 0; i < ehdr.e_phnum; i++) { - if (lseek(ifd, ehdr.e_phoff + i * ehdr.e_phentsize, SEEK_SET) == - (off_t)-1) + for (i = 0; i < letoh16(ehdr.e_phnum); i++) { + if (lseek(ifd, elfoff2h(ehdr.e_phoff) + i * + letoh16(ehdr.e_phentsize), SEEK_SET) == (off_t)-1) err(1, "%s", iname); if (read(ifd, &phdr, sizeof phdr) != sizeof(phdr)) err(1, "%s", iname); /* assumes it loads in incrementing address order */ - if (phdr.p_type == PT_LOAD) - vaddr = phdr.p_vaddr + phdr.p_memsz; + if (letoh32(phdr.p_type) == PT_LOAD) + vaddr = elfoff2h(phdr.p_vaddr) + + elfoff2h(phdr.p_memsz); } /* ok, we need to write the elf header and section header @@ -91,68 +101,75 @@ ELFNAME(copy_elf)(int ifd, const char *iname, int ofd, const char *oname, u_long ssym = vaddr; vaddr += roundup((sizeof(Elf_Ehdr) + sz), sizeof(Elf_Addr)); off = roundup((sizeof(Elf_Ehdr) + sz), sizeof(Elf_Addr)); - for (i = 0; i < elf.e_shnum; i++) { - if (esym == 0 && shp[i].sh_flags & SHF_WRITE) { - esym = shp[i].sh_addr; - } - if (shp[i].sh_type == SHT_SYMTAB || - shp[i].sh_type == SHT_STRTAB) { + for (i = 0; i < letoh16(elf.e_shnum); i++) { + if (esym == 0 && elfoff2h(shp[i].sh_flags) & SHF_WRITE) + esym = elfoff2h(shp[i].sh_addr); + + if (letoh32(shp[i].sh_type) == SHT_SYMTAB || + letoh32(shp[i].sh_type) == SHT_STRTAB) { #ifdef DEBUG - fprintf(stderr, "shdr %d %d/%d off %lx\n", i, shp[i].sh_type, - roundup(shp[i].sh_size, sizeof(Elf_Addr)), off); + fprintf(stderr, "shdr %d %d/%d off %lx\n", i, + letoh32(shp[i].sh_type), roundup(elfoff2h(shp[i].sh_size), + sizeof(Elf_Addr)), off); #endif /* data is at shp[i].sh_offset of len shp[i].sh_size */ - wshp[i].sh_offset = off; - off += roundup(shp[i].sh_size, sizeof(Elf_Addr)); - vaddr += roundup(shp[i].sh_size, sizeof(Elf_Addr)); + wshp[i].sh_offset = h2elfoff(off); + off += roundup(elfoff2h(shp[i].sh_size), + sizeof(Elf_Addr)); + vaddr += roundup(elfoff2h(shp[i].sh_size), + sizeof(Elf_Addr)); } } esymval = vaddr; #ifdef DEBUG - fprintf(stderr, "esymval %lx size %ld\n", esymval, esymval - ssym); + fprintf(stderr, "esymval %lx size %ld\n", esymval, esymval - ssym); #endif - for (i = 0; i < ehdr.e_phnum; i++) { + for (i = 0; i < letoh16(ehdr.e_phnum); i++) { #ifdef DEBUG - fprintf(stderr, "phdr %d/%d\n", i, ehdr.e_phnum); + fprintf(stderr, "phdr %d/%d\n", i, letoh16(ehdr.e_phnum)); #endif - if (lseek(ifd, ehdr.e_phoff + i * ehdr.e_phentsize, SEEK_SET) == - (off_t)-1) + if (lseek(ifd, elfoff2h(ehdr.e_phoff) + i * + letoh16(ehdr.e_phentsize), SEEK_SET) == (off_t)-1) err(1, "%s", iname); if (read(ifd, &phdr, sizeof phdr) != sizeof(phdr)) err(1, "%s", iname); #ifdef DEBUG fprintf(stderr, "vaddr %p offset %p filesz %p memsz %p\n", - phdr.p_vaddr, phdr.p_offset, phdr.p_filesz, phdr.p_memsz); + elfoff2h(phdr.p_vaddr), elfoff2h(phdr.p_offset), + elfoff2h(phdr.p_filesz), elfoff2h(phdr.p_memsz)); #endif if (i == 0) - vaddr = phdr.p_vaddr; - else if (vaddr != phdr.p_vaddr) { + vaddr = elfoff2h(phdr.p_vaddr); + else if (vaddr != elfoff2h(phdr.p_vaddr)) { #ifdef DEBUG - fprintf(stderr, "gap %p->%p\n", vaddr, phdr.p_vaddr); + fprintf(stderr, "gap %p->%p\n", vaddr, + elfoff2h(phdr.p_vaddr)); #endif /* fill the gap between the previous phdr if any */ crc = fill_zeroes(ofd, oname, crc, ih, - phdr.p_vaddr - vaddr); - vaddr = phdr.p_vaddr; + elfoff2h(phdr.p_vaddr) - vaddr); + vaddr = elfoff2h(phdr.p_vaddr); } - if (phdr.p_filesz != 0) { + if (elfoff2h(phdr.p_filesz) != 0) { #ifdef DEBUG fprintf(stderr, "copying %p from infile %p\n", - phdr.p_filesz, phdr.p_offset); + elfoff2h(hphdr.p_filesz), elfoff2h(phdr.p_offset)); #endif /* esym will be in the data portion of a region */ - if (esym >= phdr.p_vaddr && - esym < phdr.p_vaddr + phdr.p_filesz) { + if (esym >= elfoff2h(phdr.p_vaddr) && + esym < elfoff2h(phdr.p_vaddr) + + elfoff2h(phdr.p_filesz)) { /* load the region up to the esym * (may be empty) */ - Elf_Addr loadlen = esym - phdr.p_vaddr; + Elf_Addr loadlen = esym - + elfoff2h(phdr.p_vaddr); - if (lseek(ifd, phdr.p_offset, SEEK_SET) == - (off_t)-1) + if (lseek(ifd, elfoff2h(phdr.p_offset), + SEEK_SET) == (off_t)-1) err(1, "%s", iname); crc = copy_data(ifd, iname, ofd, oname, crc, ih, loadlen); @@ -160,29 +177,33 @@ ELFNAME(copy_elf)(int ifd, const char *iname, int ofd, const char *oname, u_long crc = copy_mem(&esymval, ofd, oname, crc, ih, sizeof(esymval)); - if (lseek(ifd, phdr.p_offset + loadlen + - sizeof(esymval), SEEK_SET) == (off_t)-1) + if (lseek(ifd, elfoff2h(phdr.p_offset) + + loadlen + sizeof(esymval), SEEK_SET) == + (off_t)-1) err(1, "%s", iname); crc = copy_data(ifd, iname, ofd, oname, crc, - ih, phdr.p_filesz - loadlen - + ih, elfoff2h(phdr.p_filesz) - loadlen - sizeof(esymval)); } else { - if (lseek(ifd, phdr.p_offset, SEEK_SET) == - (off_t)-1) + if (lseek(ifd, elfoff2h(phdr.p_offset), + SEEK_SET) == (off_t)-1) err(1, "%s", iname); crc = copy_data(ifd, iname, ofd, oname, crc, - ih, phdr.p_filesz); + ih, elfoff2h(phdr.p_filesz)); } - if (phdr.p_memsz - phdr.p_filesz != 0) { + if (elfoff2h(phdr.p_memsz) - elfoff2h(phdr.p_filesz) + != 0) { #ifdef DEBUG fprintf(stderr, "zeroing %p\n", - phdr.p_memsz - phdr.p_filesz); + elfoff2h(phdr.p_memsz) - + elfoff2h(phdr.p_filesz)); #endif crc = fill_zeroes(ofd, oname, crc, ih, - phdr.p_memsz - phdr.p_filesz); + elfoff2h(phdr.p_memsz) - + elfoff2h(phdr.p_filesz)); } - ovaddr = vaddr + phdr.p_memsz; + ovaddr = vaddr + elfoff2h(phdr.p_memsz); } else { ovaddr = vaddr; } @@ -191,27 +212,27 @@ ELFNAME(copy_elf)(int ifd, const char *iname, int ofd, const char *oname, u_long * need to provide. If it's not the last phdr, the gap * filling code will output the necessary zeroes anyway. */ - vaddr += phdr.p_memsz; + vaddr += elfoff2h(phdr.p_memsz); } vaddr = roundup(vaddr, sizeof(Elf_Addr)); if (vaddr != ovaddr) { #ifdef DEBUG - fprintf(stderr, "gap %p->%p\n", vaddr, phdr.p_vaddr); + fprintf(stderr, "gap %p->%p\n", vaddr, elfoff2h(phdr.p_vaddr)); #endif /* fill the gap between the previous phdr if not aligned */ crc = fill_zeroes(ofd, oname, crc, ih, vaddr - ovaddr); } - for (havesyms = i = 0; i < elf.e_shnum; i++) - if (shp[i].sh_type == SHT_SYMTAB) - havesyms = 1; + for (havesyms = i = 0; i < letoh16(elf.e_shnum); i++) + if (letoh32(shp[i].sh_type) == SHT_SYMTAB) + havesyms = 1; if (havesyms == 0) return crc; elf.e_phoff = 0; - elf.e_shoff = sizeof(Elf_Ehdr); + elf.e_shoff = h2elfoff(sizeof(Elf_Ehdr)); elf.e_phentsize = 0; elf.e_phnum = 0; crc = copy_mem(&elf, ofd, oname, crc, ih, sizeof(elf)); @@ -219,16 +240,17 @@ ELFNAME(copy_elf)(int ifd, const char *iname, int ofd, const char *oname, u_long off = sizeof(elf) + sz; off = roundup((sizeof(Elf_Ehdr) + sz), sizeof(Elf_Addr)); - for (i = 0; i < elf.e_shnum; i++) { - if (shp[i].sh_type == SHT_SYMTAB || - shp[i].sh_type == SHT_STRTAB) { + for (i = 0; i < letoh16(elf.e_shnum); i++) { + if (letoh32(shp[i].sh_type) == SHT_SYMTAB || + letoh32(shp[i].sh_type) == SHT_STRTAB) { /* data is at shp[i].sh_offset of len shp[i].sh_size */ - if (lseek(ifd, shp[i].sh_offset, SEEK_SET) == -1) { + if (lseek(ifd, elfoff2h(shp[i].sh_offset), SEEK_SET) + == -1) err(1, "%s", iname); - } - off += shp[i].sh_size; + + off += elfoff2h(shp[i].sh_size); crc = copy_data(ifd, iname, ofd, oname, crc, ih, - shp[i].sh_size); + elfoff2h(shp[i].sh_size)); } } |