xref: /inferno-os/utils/5coff/5coff.c (revision 2b69dba5038ffd0b59cf30a4c44bce549e5097f8)
1 #include	"auxi.h"
2 
3 #define RND(x, y)	((((x)+(y)-1)/(y))*(y))
4 
5 char *cmd;
6 int sflag, dflag;
7 
8 int ifd, ofd;
9 Fhdr ihdr;
10 
11 long	HEADR, INITTEXT, INITDAT, INITRND, INITENTRY;
12 long textsize, datsize, bsssize;
13 
14 int cout;
15 int thumb;
16 
17 static void	get_file(char *);
18 static void	put_file(char *);
19 static void	usage(char *);
20 static long	strxtol(char *);
21 static void	readsyms(void);
22 
23 char	*fail	= "error";
24 
25 void
26 main(int argc, char	*argv[])
27 {
28 	char *a, *ifile, *ofile;
29 
30 	cmd = argv[0];
31 
32 	INITTEXT = -1;
33 	INITDAT = -1;
34 	INITRND = -1;
35 	INITENTRY = -1;
36 
37 	ARGBEGIN {
38 	/*
39 	 * Options without args
40 	 */
41 	case 's':
42 		sflag = 1;
43 		break;
44 	/*
45 	 * Options with args
46 	 */
47 	case 'T':
48 		a = ARGF();
49 		if(a)
50 			INITTEXT = strxtol(a);
51 		break;
52 	case 'D':
53 		a = ARGF();
54 		if(a)
55 			INITDAT = strxtol(a);
56 		break;
57 	case 'R':
58 		a = ARGF();
59 		if(a)
60 			INITRND = strxtol(a);
61 		break;
62 	case 'E':
63 		a = ARGF();
64 		if(a)
65 			INITENTRY = strxtol(a);
66 		break;
67 	case 'd':
68 		dflag |= strxtol(ARGF());
69 		break;
70 	default:
71 		usage("Invalid option");
72 	} ARGEND
73 
74 	if (argc != 2)
75 		usage("Wrong number of arguments");
76 
77 	ifile = argv[0];
78 	ofile = argv[1];
79 
80 	get_file(ifile);
81 	put_file(ofile);
82 	exits(0);
83 }
84 
85 char usagemsg[] =
86 "usage: %s  options infile outfile\n\t options (for outfile): -H[1234] -s -T<text> -D<data> -R<rnd> -E<entry>\n";
87 
88 static void
89 usage(char *msg)
90 {
91 	fprint(2, "***Error: %s\n", msg);
92 	fprint(2, usagemsg, cmd);
93 	exits("usage");
94 }
95 
96 static long
97 strxtol(char *s)
98 {
99 	char *es;
100 	int base = 0;
101 	long r;
102 
103 	if (*s == '0')
104 		if (*++s == 'x'){
105 			base = 16;
106 			s++;
107 		}
108 		else
109 			base = 8;
110 	r = strtol(s, &es, base);
111 	if (*es)
112 		usage("bad number");
113 	return(r);
114 }
115 
116 static void
117 get_file(char *ifile)
118 {
119 	int h;
120 
121 	ifd = open(ifile, OREAD);
122 	if (ifd < 0) {
123 		fprint(2, "5coff: open %s: %r\n", ifile);
124 		exits("open");
125 	}
126 	h = crackhdr(ifd, &ihdr);
127 	if (!h || dflag){
128 		fprint(2, "Crackhdr: %d, type: %d, name: %s\n", h, ihdr.type, ihdr.name);
129 		fprint(2, "txt %llux, ent %llux, txtsz %lux, dataddr %llux\n",
130 			ihdr.txtaddr, ihdr.entry, ihdr.txtsz, ihdr.dataddr);
131 	}
132 	if (!h)
133 		usage("File type not recognized");
134 	machbytype(ihdr.type);
135 	if (dflag)
136 		fprint(2, "name: <%s> pgsize:%ux\n", mach->name, mach->pgsize);
137 
138 	HEADR = 22+28+3*48;
139 	if(INITTEXT == -1)
140 		INITTEXT = ihdr.txtaddr;
141 	else
142 		ihdr.txtaddr = INITTEXT;
143 	if(INITDAT == -1)
144 		INITDAT = ihdr.dataddr;
145 	else
146 		ihdr.dataddr = INITDAT;
147 	if(INITENTRY == -1)
148 		INITENTRY = ihdr.entry;
149 	else
150 		ihdr.entry = INITENTRY;
151 	textsize = ihdr.txtsz;
152 	datsize = ihdr.datsz;
153 	bsssize = ihdr.bsssz;
154 	if(INITRND > 0)
155 		ihdr.dataddr = INITDAT = RND(INITTEXT+textsize, INITRND);
156 	if(0){
157 		INITTEXT = INITENTRY;
158 		INITDAT = RND(INITTEXT+textsize, 4);
159 	}
160 	if(0){
161 		print("H=%lux T=%lux D=%lux t=%lux d=%lux b=%lux e=%lux\n", HEADR, INITTEXT, INITDAT, textsize, datsize, bsssize, INITENTRY);
162 		print("%llux %llux %llux %lux %lux %lux\n", ihdr.txtaddr, ihdr.dataddr, ihdr.entry, ihdr.txtsz, ihdr.datsz, ihdr.bsssz);
163 	}
164 
165 	readsyms();
166 }
167 
168 #define WB	128
169 #define WSAFE	(WB-4)
170 char Wbuf[WB];
171 char *wp = Wbuf;
172 
173 void
174 cflush(void)
175 {
176 	if(wp > Wbuf)
177 		write(ofd, Wbuf, wp-Wbuf);
178 	wp = Wbuf;
179 }
180 
181 void
182 lput(long l)
183 {
184 	wp[0] = l>>24;
185 	wp[1] = l>>16;
186 	wp[2] = l>>8;
187 	wp[3] = l;
188 	wp += 4;
189 	if(wp >= Wbuf+WSAFE)
190 		cflush();
191 }
192 
193 void
194 cput(int l)
195 {
196 	wp[0] = l;
197 	wp += 1;
198 	if(wp >= Wbuf+WSAFE)
199 		cflush();
200 }
201 
202 void
203 hputl(int l)
204 {
205 	wp[1] = l>>8;
206 	wp[0] = l;
207 	wp += 2;
208 	if(wp >= Wbuf+WSAFE)
209 		cflush();
210 }
211 
212 void
213 lputl(long l)
214 {
215 	wp[3] = l>>24;
216 	wp[2] = l>>16;
217 	wp[1] = l>>8;
218 	wp[0] = l;
219 	wp += 4;
220 	if(wp >= Wbuf+WSAFE)
221 		cflush();
222 }
223 
224 static void
225 copyseg(long sz)
226 {
227 	char	buf[1024];
228 
229 	cflush();
230 	while (sz > 0){
231 		long n;
232 		long r;
233 
234 		n = sz;
235 		if (n > sizeof buf)
236 			n = sizeof buf;
237 		sz -= n;
238 
239 		if ((r = read(ifd, buf, n)) != n){
240 			fprint(2, "%ld = read(...%ld) at %ld\n", r, n, (long)seek(ifd, 0, 1));
241 			perror("Premature eof");
242 			exits(fail);
243 		}
244 		if ((r = write(ofd, buf, n)) != n){
245 			fprint(2, "%ld = write(...%ld)\n", r, n);
246 			perror("Write error!");
247 			exits(fail);
248 		}
249 	}
250 	cflush();
251 }
252 
253 static void
254 put_file(char *ofile)
255 {
256 	ofd = create(ofile, OWRITE, 0666);
257 	if (ofd < 0) {
258 		fprint(2, "5coff: create %s: %r\n", ofile);
259 		exits("create");
260 	}
261 	cout = ofd;
262 
263 	/* TBS lput for Plan9 header before ? */
264 
265 	seek(ifd, ihdr.txtoff, 0);
266 	seek(ofd, HEADR, 0);
267 	copyseg(ihdr.txtsz);
268 
269 	seek(ifd, ihdr.datoff, 0);
270 	seek(ofd, HEADR+textsize, 0);
271 	copyseg(ihdr.datsz);
272 
273 	seek(ofd, HEADR+textsize+datsize, 0);
274 	coffsym();
275 	cflush();
276 	cofflc();
277 	cflush();
278 
279 	seek(ofd, 0, 0);
280 	coffhdr();
281 	cflush();
282 
283 	close(ifd);
284 	close(ofd);
285 }
286 
287 long
288 entryvalue(void)
289 {
290 	return INITENTRY;
291 }
292 
293 void
294 diag(char *s, ...)
295 {
296 	fprint(2, "%s\n", s);
297 	exits("error");
298 }
299 
300 static void
301 readsyms(void)
302 {
303 	int i;
304 	long n;
305 	Sym *s;
306 
307 	if(sflag)
308 		return;
309 	n = syminit(ifd, &ihdr);
310 	beginsym();
311 	for(i = 0; i < n; i++){
312 		s = getsym(i);
313 		newsym(i, s->name, s->value, s->type);
314 	}
315 	endsym();
316 }
317