1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <mach.h> 5 6 void 7 error(char* fmt, ...) 8 { 9 va_list arg; 10 char *e, s[256]; 11 12 va_start(arg, fmt); 13 e = seprint(s, s+sizeof(s), "%s: ", argv0); 14 e = vseprint(e, s+sizeof(s), fmt, arg); 15 e = seprint(e, s+sizeof(s), "\n"); 16 va_end(arg); 17 18 write(2, s, e-s); 19 } 20 21 static void 22 usage(void) 23 { 24 error("usage: %s -o ofile file\n\t%s file ...\n", argv0, argv0); 25 exits("usage"); 26 } 27 28 static int 29 strip(char* file, char* out) 30 { 31 Dir *dir; 32 int fd, i; 33 Fhdr fhdr; 34 Exec *exec; 35 ulong mode; 36 void *data; 37 vlong length; 38 39 if((fd = open(file, OREAD)) < 0){ 40 error("%s: open: %r", file); 41 return 1; 42 } 43 44 if(!crackhdr(fd, &fhdr)){ 45 error("%s: %r", file); 46 close(fd); 47 return 1; 48 } 49 for(i = MIN_MAGIC; i <= MAX_MAGIC; i++){ 50 if(fhdr.magic == _MAGIC(0, i) || fhdr.magic == _MAGIC(HDR_MAGIC, i)) 51 break; 52 } 53 if(i > MAX_MAGIC){ 54 error("%s: not a recognizeable binary", file); 55 close(fd); 56 return 1; 57 } 58 59 if((dir = dirfstat(fd)) == nil){ 60 error("%s: stat: %r", file); 61 close(fd); 62 return 1; 63 } 64 65 length = fhdr.datoff+fhdr.datsz; 66 if(length == dir->length){ 67 if(out == nil){ /* nothing to do */ 68 error("%s: already stripped", file); 69 free(dir); 70 close(fd); 71 return 0; 72 } 73 } 74 if(length > dir->length){ 75 error("%s: strange length", file); 76 close(fd); 77 free(dir); 78 return 1; 79 } 80 81 mode = dir->mode; 82 free(dir); 83 84 if((data = malloc(length)) == nil){ 85 error("%s: malloc failure", file); 86 close(fd); 87 return 1; 88 } 89 seek(fd, 0LL, 0); 90 if(read(fd, data, length) != length){ 91 error("%s: read: %r", file); 92 close(fd); 93 free(data); 94 return 1; 95 } 96 close(fd); 97 98 exec = data; 99 exec->syms = 0; 100 exec->spsz = 0; 101 exec->pcsz = 0; 102 103 if(out == nil){ 104 if(remove(file) < 0) { 105 error("%s: remove: %r", file); 106 free(data); 107 return 1; 108 } 109 out = file; 110 } 111 if((fd = create(out, OWRITE, mode)) < 0){ 112 error("%s: create: %r", out); 113 free(data); 114 return 1; 115 } 116 if(write(fd, data, length) != length){ 117 error("%s: write: %r", out); 118 close(fd); 119 free(data); 120 return 1; 121 } 122 close(fd); 123 free(data); 124 125 return 0; 126 } 127 128 void 129 main(int argc, char* argv[]) 130 { 131 int r; 132 char *p; 133 134 p = nil; 135 136 ARGBEGIN{ 137 default: 138 usage(); 139 break; 140 case 'o': 141 p = ARGF(); 142 if(p == nil) 143 usage(); 144 break; 145 }ARGEND; 146 147 switch(argc){ 148 case 0: 149 usage(); 150 return; 151 case 1: 152 if(p != nil){ 153 r = strip(*argv, p); 154 break; 155 } 156 /*FALLTHROUGH*/ 157 default: 158 r = 0; 159 while(argc > 0){ 160 r |= strip(*argv, nil); 161 argc--; 162 argv++; 163 } 164 break; 165 } 166 167 if(r) 168 exits("error"); 169 exits(0); 170 } 171