summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDale Rahn <drahn@cvs.openbsd.org>2006-05-05 02:51:17 +0000
committerDale Rahn <drahn@cvs.openbsd.org>2006-05-05 02:51:17 +0000
commitb1ce35673e26a55251fd2e6e0e4eb50fab101c4c (patch)
tree1f09ae10a5ab480cc1c840cafb88a0ff1821fdc0
parent33fade9e1ab2b17b91558c27d469d81de39591a4 (diff)
Add -o <output> mode in addition to strip in place, '-' is stdout.
-rw-r--r--libexec/ld.so/prebind_strip/prebind_strip.c140
1 files changed, 121 insertions, 19 deletions
diff --git a/libexec/ld.so/prebind_strip/prebind_strip.c b/libexec/ld.so/prebind_strip/prebind_strip.c
index 135626f7439..e6e55357cf8 100644
--- a/libexec/ld.so/prebind_strip/prebind_strip.c
+++ b/libexec/ld.so/prebind_strip/prebind_strip.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: prebind_strip.c,v 1.1 2006/05/03 16:10:52 drahn Exp $ */
+/* $OpenBSD: prebind_strip.c,v 1.2 2006/05/05 02:51:16 drahn Exp $ */
/*
* Copyright (c) 2006 Dale Rahn <drahn@dalerahn.com>
*
@@ -25,36 +25,65 @@
#include <string.h>
#include "prebind.h"
-void dump_prebind(char *file);
-void prebind_dump_footer(struct prebind_footer *footer, char *file);
-void prebind_dump_symcache(struct symcachetab *symcachetab, u_int32_t cnt);
-void prebind_dump_nameidx(struct nameidx *nameidx, u_int32_t numblibs,
- char *nametab);
-void prebind_dump_fixup(struct fixup *fixup, u_int32_t numfixups);
-void prebind_dump_libmap(u_int32_t *libmap, u_int32_t numlibs, void *a);
-
+void strip_prebind(char *file, char *output);
void prebind_remove_load_section(int fd, char *name);
+int prebind_cat(int fd, struct prebind_footer *footer, char *name);
+
+extern char *__progname;
+
+void __dead
+usage(void)
+{
+ fprintf(stderr, "Usage:%s [-o <outfile>] <filelist>\n", __progname);
+ exit(1);
+}
+
int
main(int argc, char **argv)
{
+ char *outputfile = NULL;
int i;
- for (i = 1; i < argc; i++) {
- printf("stripping %s\n", argv[i]);
- dump_prebind(argv[i]);
+ int ch;
+ while ((ch = getopt(argc, argv, "o:")) != -1) {
+ switch (ch) {
+ case 'o':
+ outputfile = optarg;
+ break;
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (outputfile != NULL && argc > 1) {
+ fprintf(stderr, "%s:-o will not work with multiple files\n",
+ __progname);
+ usage();
+ }
+ for (i = 0; i < argc; i++) {
+ strip_prebind(argv[i], outputfile);
}
return 0;
}
void
-dump_prebind(char *file)
+strip_prebind(char *file, char *outfile)
{
struct prebind_footer footer;
int fd;
ssize_t bytes;
+ int mode;
- fd = open(file, O_RDWR);
+ if (outfile == NULL)
+ mode = O_RDWR;
+ else
+ mode = O_RDONLY;
+
+ fd = open(file, mode);
if (fd == -1) {
perror(file);
return;
@@ -72,13 +101,17 @@ dump_prebind(char *file)
footer.bind_id[3] == BIND_ID3) {
} else {
- printf("%s: no prebind header\n", file);
+ fprintf(stderr, "%s: no prebind header\n", file);
goto done;
}
- prebind_remove_load_section(fd, file);
+ if (outfile == NULL) {
+ prebind_remove_load_section(fd, file);
- ftruncate(fd, footer.orig_size);
+ ftruncate(fd, footer.orig_size);
+ } else {
+ prebind_cat(fd, &footer, outfile);
+ }
done:
close(fd);
}
@@ -95,7 +128,7 @@ prebind_remove_load_section(int fd, char *name)
fd, 0);
if (buf == MAP_FAILED) {
perror(name);
- printf("%s: cannot mmap for write\n", name);
+ fprintf(stderr, "%s: cannot mmap for write\n", name);
return;
}
@@ -112,7 +145,7 @@ prebind_remove_load_section(int fd, char *name)
if ((phdr[loadsection].p_type != PT_LOAD) ||
((phdr[loadsection].p_flags & 0x08000000) == 0)) {
/* doesn't look like ours */
- printf("mapped, %s id doesn't match %lx\n", name,
+ fprintf(stderr, "mapped, %s id doesn't match %lx\n", name,
(long)(phdr[loadsection].p_vaddr));
goto done;
}
@@ -123,3 +156,72 @@ prebind_remove_load_section(int fd, char *name)
done:
munmap(buf, 8192);
}
+
+int
+prebind_cat(int fd, struct prebind_footer *footer, char *name)
+{
+ int outfd;
+ void *buf;
+ Elf_Ehdr *ehdr;
+ Elf_Phdr *phdr;
+ size_t len, wlen, rlen, remlen;
+ int header_done = 0;
+ int err = 0;
+ int loadsection;
+
+ if (strcmp(name, "-") == 0)
+ outfd = 1;
+ else
+ outfd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0644);
+
+ if (outfd == -1) {
+ fprintf(stderr, "unable to open file %s\n", name);
+ return 1;
+ }
+#define BUFSZ (256 * 1024)
+ buf = malloc(BUFSZ);
+
+ if (buf == NULL) {
+ fprintf(stderr, "failed to allocate copy buffer\n");
+ return 1;
+ }
+
+ lseek(fd, 0, SEEK_SET);
+ remlen = footer->orig_size;
+ while (remlen > 0) {
+ if (remlen > BUFSZ)
+ rlen = BUFSZ;
+ else
+ rlen = remlen;
+ len = read(fd, buf, rlen);
+ if (len <= 0) {
+ break; /* read failure */
+ err=1;
+ }
+ remlen -= len;
+ if (header_done == 0) {
+ header_done = 1;
+ ehdr = (Elf_Ehdr *) buf;
+ phdr = (Elf_Phdr *)((char *)buf + ehdr->e_phoff);
+
+ loadsection = ehdr->e_phnum - 1;
+
+ if ((len >= ehdr->e_phoff +
+ sizeof(Elf_Phdr) * ehdr->e_phnum) &&
+ ehdr->e_type == ET_EXEC &&
+ (phdr[loadsection].p_flags & 0x08000000) != 0 &&
+ (phdr[loadsection].p_type == PT_LOAD)) {
+ bzero(&phdr[loadsection], sizeof(Elf_Phdr));
+ ehdr->e_phnum--;
+ }
+ }
+ wlen = write(outfd, buf, len);
+ if (wlen != len) {
+ /* write failed */
+ err=1;
+ break;
+ }
+ }
+
+ return err;
+}