diff options
Diffstat (limited to 'sysutils')
-rw-r--r-- | sysutils/fixelfprot/DESCR | 2 | ||||
-rw-r--r-- | sysutils/fixelfprot/Makefile | 32 | ||||
-rw-r--r-- | sysutils/fixelfprot/PLIST | 2 | ||||
-rw-r--r-- | sysutils/fixelfprot/files/fixelfprot.c | 182 |
4 files changed, 218 insertions, 0 deletions
diff --git a/sysutils/fixelfprot/DESCR b/sysutils/fixelfprot/DESCR new file mode 100644 index 00000000000..b2af2a268e9 --- /dev/null +++ b/sysutils/fixelfprot/DESCR @@ -0,0 +1,2 @@ +Fix up the permission bits for the program load section containing the +.got section of a PPC ELF binary. diff --git a/sysutils/fixelfprot/Makefile b/sysutils/fixelfprot/Makefile new file mode 100644 index 00000000000..d8b0e67e582 --- /dev/null +++ b/sysutils/fixelfprot/Makefile @@ -0,0 +1,32 @@ +# $NetBSD: Makefile,v 1.1.1.1 2004/07/15 09:28:15 agc Exp $ + +DISTNAME= fixelfprot-20040714 +CATEGORIES= sysutils +MASTER_SITES= # empty +DISTFILES= # empty + +MAINTAINER= tech-pkg@NetBSD.org +HOMEPAGE= http://mail-index.netbsd.org/tech-kern/2004/07/11/0002.html +COMMENT= C program to fix ELF protection on .got table for PowerPC + +ONLY_FOR_PLATFORM= NetBSD-*-powerpc + +PKG_INSTALLATION_TYPES= overwrite pkgviews + +WRKSRC= ${WRKDIR} +NO_CHECKSUM= # defined - sources are part of pkgsrc entry +NO_BUILDLINK= # defined +NO_CONFIGURE= # defined + +INSTALLATION_DIRS= bin + +do-extract: + ${CP} ${FILESDIR}/fixelfprot.c ${WRKSRC} + +do-build: + cd ${WRKSRC} && ${CC} ${CFLAGS} fixelfprot.c -o fixelfprot + +do-install: + ${INSTALL_PROGRAM} ${WRKSRC}/fixelfprot ${PREFIX}/sbin + +.include "../../mk/bsd.pkg.mk" diff --git a/sysutils/fixelfprot/PLIST b/sysutils/fixelfprot/PLIST new file mode 100644 index 00000000000..c5e621ede46 --- /dev/null +++ b/sysutils/fixelfprot/PLIST @@ -0,0 +1,2 @@ +@comment $NetBSD: PLIST,v 1.1.1.1 2004/07/15 09:28:15 agc Exp $ +sbin/fixelfprot diff --git a/sysutils/fixelfprot/files/fixelfprot.c b/sysutils/fixelfprot/files/fixelfprot.c new file mode 100644 index 00000000000..6277e9214f7 --- /dev/null +++ b/sysutils/fixelfprot/files/fixelfprot.c @@ -0,0 +1,182 @@ +/* + * Fix up the permission bits for the program load section containing the + * .got section of a PPC ELF binary. + */ + +#include <stdio.h> +#include <err.h> +#define ELFSIZE 32 +#include <sys/exec_elf.h> +#include <sys/endian.h> +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> +#include <string.h> + +void xlseek(int, off_t, int); +void xread(int, void *, size_t); +void xwrite(int, void *, size_t); +void *xmalloc(size_t); + +void +xlseek(int fd, off_t off, int whence) +{ + int rv; + + rv = lseek(fd, off, whence); + if (rv < 0) { + err(1, "lseek"); + } +} + +void +xread(int fd, void *buf, size_t size) +{ + int rv; + + rv = read(fd, buf, size); + if (rv < 0) { + err(1, "read"); + } + if (rv != size) { + errx(1, "short read %d vs. %d", rv, size); + } +} + +void +xwrite(int fd, void *buf, size_t size) +{ + int rv; + + rv = write(fd, buf, size); + if (rv < 0) { + err(1, "write"); + } + if (rv != size) { + errx(1, "short write %d vs. %d", rv, size); + } +} + + +void * +xmalloc(size_t size) +{ + void *buf; + + buf = malloc(size); + if (buf == NULL) { + err(1, "malloc"); + } + return buf; +} + +int +main(int argc, char **argv) +{ + Elf32_Ehdr eh; + Elf32_Phdr *ph; + Elf32_Shdr *sh; + Elf32_Addr gotaddr; + size_t phsize, shsize, strsize; + char *strbuf; + int fd, i, idx; + + /* + * Check arguments and open the file. + */ + + if (argc != 2) { + errx(1, "usage: %s <file>", getprogname()); + } + fd = open(argv[1], O_RDWR); + if (fd < 0) { + err(1, "open %s", argv[1]); + } + + /* + * Read and validate the ELF header. + */ + + xread(fd, &eh, sizeof (eh)); + if (memcmp(eh.e_ident, ELFMAG, SELFMAG) != 0 || + eh.e_ident[EI_CLASS] != ELFCLASS) { + errx(1, "not an ELF file"); + } + if (be16toh(eh.e_machine) != EM_PPC) { + errx(1, "ELF file is wrong architecture"); + } + if (be16toh(eh.e_type) != ET_EXEC) { + errx(1, "ELF file is not an executable"); + } + if (be16toh(eh.e_shnum) > 512 || be16toh(eh.e_phnum) > 128) { + errx(1, "ELF file has too many sections"); + } + if (be16toh(eh.e_shstrndx) >= be16toh(eh.e_shnum)) { + errx(1, "string table index out of range"); + } + + /* + * Read the program headers, section headers and string table. + */ + + phsize = be16toh(eh.e_phnum) * sizeof(Elf_Phdr); + ph = xmalloc(phsize); + xlseek(fd, (off_t)be32toh(eh.e_phoff), SEEK_SET); + xread(fd, ph, phsize); + + shsize = be16toh(eh.e_shnum) * sizeof(Elf_Shdr); + sh = xmalloc(shsize); + xlseek(fd, (off_t)be32toh(eh.e_shoff), SEEK_SET); + xread(fd, sh, shsize); + + idx = be16toh(eh.e_shstrndx); + strsize = be32toh(sh[idx].sh_size); + strbuf = xmalloc(strsize); + xlseek(fd, (off_t)be32toh(sh[idx].sh_offset), SEEK_SET); + xread(fd, strbuf, strsize); + + /* + * Find the .got section. + */ + + gotaddr = 0; + for (i = 0; i < be16toh(eh.e_shnum); i++) { + if (strcmp(&strbuf[be32toh(sh[i].sh_name)], ".got") == 0) { + gotaddr = be32toh(sh[i].sh_addr); + break; + } + } + if (gotaddr == 0) { + errx(1, "couldn't find the .got section"); + } + + /* + * Find the program header load section containing the .got section. + */ + + idx = -1; + for (i = 0; i < be16toh(eh.e_phnum); i++) { + if (be32toh(ph[i].p_type) == PT_LOAD && + gotaddr >= be32toh(ph[i].p_vaddr) && + gotaddr < be32toh(ph[i].p_vaddr) + be32toh(ph[i].p_memsz)) { + idx = i; + } + } + if (idx == -1) { + errx(1, "couldn't find program header for .got"); + } + if (be32toh(ph[idx].p_flags) & PF_X) { + errx(1, "permission bits already include execute"); + } + + /* + * Add execute permission and write back the entry. + */ + + ph[idx].p_flags |= be32toh(PF_X); + xlseek(fd, (off_t)be32toh(eh.e_phoff), SEEK_SET); + xwrite(fd, ph, phsize); + + errx(0, "execute permission added"); + exit(0); +} |