1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5
6 void
error(char * fmt,...)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
usage(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
strip(char * file,char * out)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
main(int argc,char * argv[])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