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