summaryrefslogtreecommitdiff
path: root/sysutils
diff options
context:
space:
mode:
Diffstat (limited to 'sysutils')
-rw-r--r--sysutils/fixelfprot/DESCR2
-rw-r--r--sysutils/fixelfprot/Makefile32
-rw-r--r--sysutils/fixelfprot/PLIST2
-rw-r--r--sysutils/fixelfprot/files/fixelfprot.c182
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);
+}