xref: /plan9/sys/src/cmd/strip.c (revision 4de34a7edde43207e841ec91ecd12e6cf5f5ebe7)
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