diff options
author | Dale Rahn <drahn@cvs.openbsd.org> | 2006-05-05 02:51:17 +0000 |
---|---|---|
committer | Dale Rahn <drahn@cvs.openbsd.org> | 2006-05-05 02:51:17 +0000 |
commit | b1ce35673e26a55251fd2e6e0e4eb50fab101c4c (patch) | |
tree | 1f09ae10a5ab480cc1c840cafb88a0ff1821fdc0 | |
parent | 33fade9e1ab2b17b91558c27d469d81de39591a4 (diff) |
Add -o <output> mode in addition to strip in place, '-' is stdout.
-rw-r--r-- | libexec/ld.so/prebind_strip/prebind_strip.c | 140 |
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; +} |