changelog shortlog tags branches changeset files file revisions raw help

Mercurial > hg > plan9front / annotate sys/src/cmd/7l/obj.c

changeset 4275: d1102fefd6c1
parent: eaccc3e8d226
author: cinap_lenrek@felloff.net
date: Tue, 17 Feb 2015 22:13:35 +0100
permissions: -rw-r--r--
description: [125678kqv][cl]: fix sprint() and strcpy() buffer overflows
taruti@0 1
 #include	"l.h"
taruti@0 2
 #include	<ar.h>
taruti@0 3
 
taruti@0 4
 #ifndef	DEFAULT
taruti@0 5
 #define	DEFAULT	'9'
taruti@0 6
 #endif
taruti@0 7
 
taruti@0 8
 char	*noname		= "<none>";
taruti@0 9
 char	symname[]	= SYMDEF;
taruti@0 10
 char	thechar		= '7';
taruti@0 11
 char	*thestring 	= "alpha";
taruti@0 12
 
taruti@0 13
 /*
taruti@0 14
  *	-H0 -T0x12000004C -D0x140000000	is abbrev unix
taruti@0 15
  *	-H1 -T0x20000000 -R4		is bootp() format
taruti@0 16
  *	-H2 -T8224 -R8192		is plan9 format
taruti@0 17
  */
taruti@0 18
 
taruti@0 19
 void
taruti@0 20
 main(int argc, char *argv[])
taruti@0 21
 {
taruti@0 22
 	int c;
taruti@0 23
 	char *a;
taruti@0 24
 
taruti@0 25
 	Binit(&bso, 1, OWRITE);
taruti@0 26
 	cout = -1;
taruti@0 27
 	listinit();
taruti@0 28
 	outfile = 0;
taruti@0 29
 	nerrors = 0;
taruti@0 30
 	curtext = P;
taruti@0 31
 	HEADTYPE = -1;
taruti@0 32
 	INITTEXT = -1;
taruti@0 33
 	INITDAT = -1;
taruti@0 34
 	INITRND = -1;
taruti@0 35
 	INITENTRY = 0;
taruti@0 36
 
taruti@0 37
 	ARGBEGIN {
taruti@0 38
 	default:
taruti@0 39
 		c = ARGC();
taruti@0 40
 		if(c >= 0 && c < sizeof(debug))
taruti@0 41
 			debug[c]++;
taruti@0 42
 		break;
taruti@0 43
 	case 'o':
taruti@0 44
 		outfile = ARGF();
taruti@0 45
 		break;
taruti@0 46
 	case 'E':
taruti@0 47
 		a = ARGF();
taruti@0 48
 		if(a)
taruti@0 49
 			INITENTRY = a;
taruti@0 50
 		break;
taruti@0 51
 	case 'T':
taruti@0 52
 		a = ARGF();
taruti@0 53
 		if(a)
taruti@0 54
 			INITTEXT = atolwhex(a);
taruti@0 55
 		break;
taruti@0 56
 	case 'D':
taruti@0 57
 		a = ARGF();
taruti@0 58
 		if(a)
taruti@0 59
 			INITDAT = atolwhex(a);
taruti@0 60
 		break;
taruti@0 61
 	case 'R':
taruti@0 62
 		a = ARGF();
taruti@0 63
 		if(a)
taruti@0 64
 			INITRND = atolwhex(a);
taruti@0 65
 		break;
taruti@0 66
 	case 'H':
taruti@0 67
 		a = ARGF();
taruti@0 68
 		if(a)
taruti@0 69
 			HEADTYPE = atolwhex(a);
taruti@0 70
 		/* do something about setting INITTEXT */
taruti@0 71
 		break;
taruti@0 72
 	} ARGEND
taruti@0 73
 
taruti@0 74
 	USED(argc);
taruti@0 75
 
taruti@0 76
 	if(*argv == 0) {
taruti@0 77
 		diag("usage: 7l [-options] objects");
taruti@0 78
 		errorexit();
taruti@0 79
 	}
taruti@0 80
 	if(!debug['9'] && !debug['B'] && !debug['U'])
taruti@0 81
 		debug[DEFAULT] = 1;
taruti@0 82
 	if(HEADTYPE == -1) {
taruti@0 83
 		if(debug['U'])
taruti@0 84
 			HEADTYPE = 0;
taruti@0 85
 		if(debug['B'])
taruti@0 86
 			HEADTYPE = 1;
taruti@0 87
 		if(debug['9'])
taruti@0 88
 			HEADTYPE = 2;
taruti@0 89
 	}
taruti@0 90
 	switch(HEADTYPE) {
taruti@0 91
 	default:
taruti@0 92
 		diag("unknown -H option");
taruti@0 93
 		errorexit();
taruti@0 94
 
taruti@0 95
 	case 0:	/* unix simple */
taruti@0 96
 		HEADR = 32L+80L;
taruti@0 97
 		if(INITTEXT == -1)
taruti@0 98
 			INITTEXT = 0x120000070LL;		/* BUG */
taruti@0 99
 		if(INITDAT == -1)
taruti@0 100
 			INITDAT = 0x140000000LL;		/* BUG */
taruti@0 101
 		if(INITRND == -1)
taruti@0 102
 			INITRND = 0;
taruti@0 103
 		break;
taruti@0 104
 
taruti@0 105
 	case 1:	/* boot */
taruti@0 106
 		HEADR = 32L+84L;
taruti@0 107
 		if(INITTEXT == -1)
taruti@0 108
 			INITTEXT = 0x20000074L;
taruti@0 109
 		if(INITDAT == -1)
taruti@0 110
 			INITDAT = 0;
taruti@0 111
 		if(INITRND == -1)
taruti@0 112
 			INITRND = 8;
taruti@0 113
 		break;
taruti@0 114
 	case 2:	/* plan 9 */
taruti@0 115
 		HEADR = 32L;
taruti@0 116
 		if(INITTEXT == -1)
taruti@0 117
 			INITTEXT = 8224;
taruti@0 118
 		if(INITDAT == -1)
taruti@0 119
 			INITDAT = 0;
taruti@0 120
 		if(INITRND == -1)
taruti@0 121
 			INITRND = 8192;
taruti@0 122
 		break;
taruti@0 123
 	case 3:	/* ``headerless'' tftp boot -- uses branch as magic */
taruti@0 124
 		HEADR = 32L;
taruti@0 125
 		if(INITTEXT == -1)
taruti@0 126
 			INITTEXT = 0x20000020L;
taruti@0 127
 		if(INITDAT == -1)
taruti@0 128
 			INITDAT = 0;
taruti@0 129
 		if(INITRND == -1)
taruti@0 130
 			INITRND = 8;
taruti@0 131
 		break;
taruti@0 132
 	}
taruti@0 133
 	if(INITDAT != 0 && INITRND != 0)
taruti@0 134
 		print("warning: -D0x%lux is ignored because of -R0x%lux\n",
taruti@0 135
 			INITDAT, INITRND);
taruti@0 136
 	if(debug['v'])
taruti@0 137
 		Bprint(&bso, "HEADER = -H0x%d -T0x%lux -D0x%lux -R0x%lux\n",
taruti@0 138
 			HEADTYPE, INITTEXT, INITDAT, INITRND);
taruti@0 139
 	Bflush(&bso);
taruti@0 140
 	zprg.as = AGOK;
taruti@0 141
 	zprg.reg = NREG;
taruti@0 142
 	zprg.from.name = D_NONE;
taruti@0 143
 	zprg.from.type = D_NONE;
taruti@0 144
 	zprg.from.reg = NREG;
taruti@0 145
 	zprg.to = zprg.from;
taruti@0 146
 	buildop();
taruti@0 147
 	histgen = 0;
taruti@0 148
 	textp = P;
taruti@0 149
 	datap = P;
taruti@0 150
 	pc = 0;
taruti@0 151
 	dtype = 4;
taruti@0 152
 	if(outfile == 0)
taruti@0 153
 		outfile = "7.out";
taruti@0 154
 	cout = create(outfile, 1, 0775);
taruti@0 155
 	if(cout < 0) {
taruti@0 156
 		diag("%s: cannot create", outfile);
taruti@0 157
 		errorexit();
taruti@0 158
 	}
taruti@0 159
 	nuxiinit();
taruti@0 160
 
taruti@0 161
 	version = 0;
taruti@0 162
 	cbp = buf.cbuf;
taruti@0 163
 	cbc = sizeof(buf.cbuf);
taruti@0 164
 	firstp = prg();
taruti@0 165
 	lastp = firstp;
taruti@0 166
 
taruti@0 167
 	if(INITENTRY == 0) {
taruti@0 168
 		INITENTRY = "_main";
taruti@0 169
 		if(debug['p'])
taruti@0 170
 			INITENTRY = "_mainp";
taruti@0 171
 		if(!debug['l'])
taruti@0 172
 			lookup(INITENTRY, 0)->type = SXREF;
taruti@0 173
 	} else
taruti@0 174
 		lookup(INITENTRY, 0)->type = SXREF;
taruti@0 175
 
taruti@0 176
 	while(*argv)
taruti@0 177
 		objfile(*argv++);
taruti@0 178
 	if(!debug['l'])
taruti@0 179
 		loadlib();
taruti@0 180
 	firstp = firstp->link;
taruti@0 181
 	if(firstp == P)
taruti@0 182
 		goto out;
taruti@0 183
 	patch();
taruti@0 184
 	if(debug['p'])
taruti@0 185
 		if(debug['1'])
taruti@0 186
 			doprof1();
taruti@0 187
 		else
taruti@0 188
 			doprof2();
taruti@0 189
 	follow();
taruti@0 190
 	if(firstp == P)
taruti@0 191
 		goto out;
taruti@0 192
 	noops();
taruti@0 193
 	dodata();		/* is before follow() on other arch */
taruti@0 194
 	span();
taruti@0 195
 	asmb();
taruti@0 196
 	undef();
taruti@0 197
 
taruti@0 198
 out:
taruti@0 199
 	if(debug['v']) {
taruti@0 200
 		Bprint(&bso, "%5.2f cpu time\n", cputime());
taruti@0 201
 		Bprint(&bso, "%ld memory used\n", thunk);
taruti@0 202
 		Bprint(&bso, "%d sizeof adr\n", sizeof(Adr));
taruti@0 203
 		Bprint(&bso, "%d sizeof prog\n", sizeof(Prog));
taruti@0 204
 	}
taruti@0 205
 	Bflush(&bso);
taruti@0 206
 	errorexit();
taruti@0 207
 }
taruti@0 208
 
taruti@0 209
 void
taruti@0 210
 loadlib(void)
taruti@0 211
 {
taruti@0 212
 	int i;
taruti@0 213
 	long h;
taruti@0 214
 	Sym *s;
taruti@0 215
 
taruti@0 216
 loop:
taruti@0 217
 	xrefresolv = 0;
taruti@0 218
 	for(i=0; i<libraryp; i++) {
taruti@0 219
 		if(debug['v'])
taruti@0 220
 			Bprint(&bso, "%5.2f autolib: %s\n", cputime(), library[i]);
taruti@0 221
 		objfile(library[i]);
taruti@0 222
 	}
taruti@0 223
 	if(xrefresolv)
taruti@0 224
 	for(h=0; h<nelem(hash); h++)
taruti@0 225
 	for(s = hash[h]; s != S; s = s->link)
taruti@0 226
 		if(s->type == SXREF)
taruti@0 227
 			goto loop;
taruti@0 228
 }
taruti@0 229
 
taruti@0 230
 void
taruti@0 231
 errorexit(void)
taruti@0 232
 {
taruti@0 233
 
taruti@0 234
 	Bflush(&bso);
taruti@0 235
 	if(nerrors) {
taruti@0 236
 		if(cout >= 0)
taruti@0 237
 			remove(outfile);
taruti@0 238
 		exits("error");
taruti@0 239
 	}
taruti@0 240
 	exits(0);
taruti@0 241
 }
taruti@0 242
 
taruti@0 243
 void
taruti@0 244
 objfile(char *file)
taruti@0 245
 {
taruti@0 246
 	long off, esym, cnt, l;
taruti@0 247
 	int f, work;
taruti@0 248
 	Sym *s;
taruti@0 249
 	char magbuf[SARMAG];
taruti@0 250
 	char name[100], pname[150];
taruti@0 251
 	struct ar_hdr arhdr;
taruti@0 252
 	char *e, *start, *stop;
taruti@0 253
 
taruti@0 254
 	if(file[0] == '-' && file[1] == 'l') {
taruti@0 255
 		if(debug['9'])
cinap_lenrek@4275 256
 			snprint(name, sizeof name, "/%s/lib/lib%s.a", thestring, file+2);
taruti@0 257
 		else
cinap_lenrek@4275 258
 			snprint(name, sizeof name, "/usr/%clib/lib%s.a", thechar, file+2);
taruti@0 259
 		file = name;
taruti@0 260
 	}
taruti@0 261
 	if(debug['v'])
taruti@0 262
 		Bprint(&bso, "%5.2f ldobj: %s\n", cputime(), file);
taruti@0 263
 	Bflush(&bso);
taruti@0 264
 	f = open(file, 0);
taruti@0 265
 	if(f < 0) {
taruti@0 266
 		diag("cannot open file: %s", file);
taruti@0 267
 		errorexit();
taruti@0 268
 	}
taruti@0 269
 	l = read(f, magbuf, SARMAG);
taruti@0 270
 	if(l != SARMAG || strncmp(magbuf, ARMAG, SARMAG)){
taruti@0 271
 		/* load it as a regular file */
taruti@0 272
 		l = seek(f, 0L, 2);
taruti@0 273
 		seek(f, 0L, 0);
taruti@0 274
 		ldobj(f, l, file);
taruti@0 275
 		close(f);
taruti@0 276
 		return;
taruti@0 277
 	}
taruti@0 278
 
taruti@0 279
 	if(debug['v'])
taruti@0 280
 		Bprint(&bso, "%5.2f ldlib: %s\n", cputime(), file);
taruti@0 281
 	l = read(f, &arhdr, SAR_HDR);
taruti@0 282
 	if(l != SAR_HDR) {
taruti@0 283
 		diag("%s: short read on archive file symbol header", file);
taruti@0 284
 		goto out;
taruti@0 285
 	}
taruti@0 286
 	if(strncmp(arhdr.name, symname, strlen(symname))) {
taruti@0 287
 		diag("%s: first entry not symbol header", file);
taruti@0 288
 		goto out;
taruti@0 289
 	}
taruti@0 290
 
taruti@0 291
 	esym = SARMAG + SAR_HDR + atolwhex(arhdr.size);
taruti@0 292
 	off = SARMAG + SAR_HDR;
taruti@0 293
 
taruti@0 294
 	/*
taruti@0 295
 	 * just bang the whole symbol file into memory
taruti@0 296
 	 */
taruti@0 297
 	seek(f, off, 0);
taruti@0 298
 	cnt = esym - off;
taruti@0 299
 	start = malloc(cnt + 10);
taruti@0 300
 	cnt = read(f, start, cnt);
taruti@0 301
 	if(cnt <= 0){
taruti@0 302
 		close(f);
taruti@0 303
 		return;
taruti@0 304
 	}
taruti@0 305
 	stop = &start[cnt];
taruti@0 306
 	memset(stop, 0, 10);
taruti@0 307
 
taruti@0 308
 	work = 1;
taruti@0 309
 	while(work){
taruti@0 310
 		if(debug['v'])
taruti@0 311
 			Bprint(&bso, "%5.2f library pass: %s\n", cputime(), file);
taruti@0 312
 		Bflush(&bso);
taruti@0 313
 		work = 0;
taruti@0 314
 		for(e = start; e < stop; e = strchr(e+5, 0) + 1) {
taruti@0 315
 			s = lookup(e+5, 0);
taruti@0 316
 			if(s->type != SXREF)
taruti@0 317
 				continue;
cinap_lenrek@4275 318
 			snprint(pname, sizeof pname, "%s(%s)", file, s->name);
taruti@0 319
 			if(debug['v'])
taruti@0 320
 				Bprint(&bso, "%5.2f library: %s\n", cputime(), pname);
taruti@0 321
 			Bflush(&bso);
taruti@0 322
 			l = e[1] & 0xff;
taruti@0 323
 			l |= (e[2] & 0xff) << 8;
taruti@0 324
 			l |= (e[3] & 0xff) << 16;
taruti@0 325
 			l |= (e[4] & 0xff) << 24;
taruti@0 326
 			seek(f, l, 0);
taruti@0 327
 			l = read(f, &arhdr, SAR_HDR);
taruti@0 328
 			if(l != SAR_HDR)
taruti@0 329
 				goto bad;
taruti@0 330
 			if(strncmp(arhdr.fmag, ARFMAG, sizeof(arhdr.fmag)))
taruti@0 331
 				goto bad;
taruti@0 332
 			l = atolwhex(arhdr.size);
taruti@0 333
 			ldobj(f, l, pname);
taruti@0 334
 			if(s->type == SXREF) {
taruti@0 335
 				diag("%s: failed to load: %s", file, s->name);
taruti@0 336
 				errorexit();
taruti@0 337
 			}
taruti@0 338
 			work = 1;
taruti@0 339
 			xrefresolv = 1;
taruti@0 340
 		}
taruti@0 341
 	}
taruti@0 342
 	return;
taruti@0 343
 
taruti@0 344
 bad:
taruti@0 345
 	diag("%s: bad or out of date archive", file);
taruti@0 346
 out:
taruti@0 347
 	close(f);
taruti@0 348
 }
taruti@0 349
 
taruti@0 350
 int
taruti@0 351
 zaddr(uchar *p, Adr *a, Sym *h[])
taruti@0 352
 {
taruti@0 353
 	int i, c;
taruti@0 354
 	vlong l;
taruti@0 355
 	Sym *s;
taruti@0 356
 	Auto *u;
taruti@0 357
 
taruti@0 358
 	c = p[2];
taruti@0 359
 	if(c < 0 || c > NSYM){
taruti@0 360
 		print("sym out of range: %d\n", c);
taruti@0 361
 		p[0] = ALAST+1;
taruti@0 362
 		return 0;
taruti@0 363
 	}
taruti@0 364
 	a->type = p[0];
taruti@0 365
 	a->reg = p[1];
taruti@0 366
 	a->sym = h[p[2]];
taruti@0 367
 	a->name = p[3];
taruti@0 368
 	c = 4;
taruti@0 369
 
taruti@0 370
 	if(a->reg < 0 || a->reg > NREG) {
taruti@0 371
 		print("register out of range %d\n", a->reg);
taruti@0 372
 		p[0] = ALAST+1;
taruti@0 373
 		return 0;	/*  force real diagnostic */
taruti@0 374
 	}
taruti@0 375
 
taruti@0 376
 	switch(a->type) {
taruti@0 377
 	default:
taruti@0 378
 		print("unknown type %d\n", a->type);
taruti@0 379
 		p[0] = ALAST+1;
taruti@0 380
 		return 0;	/*  force real diagnostic */
taruti@0 381
 
taruti@0 382
 	case D_NONE:
taruti@0 383
 	case D_REG:
taruti@0 384
 	case D_FREG:
taruti@0 385
 	case D_PREG:
taruti@0 386
 	case D_FCREG:
taruti@0 387
 	case D_PCC:
taruti@0 388
 		break;
taruti@0 389
 
taruti@0 390
 	case D_BRANCH:
taruti@0 391
 	case D_OREG:
taruti@0 392
 	case D_CONST:
taruti@0 393
 		a->offset = (uvlong)p[4] | ((uvlong)p[5]<<8L) |
taruti@0 394
 			((uvlong) p[6]<<16L) | ((uvlong) p[7]<<24L) |
taruti@0 395
 			((uvlong) p[8]<<32L) | ((uvlong) p[9]<<40L) |
taruti@0 396
 			((uvlong) p[10]<<48L) | ((uvlong) p[11]<<56L);
taruti@0 397
 		c += 8;
taruti@0 398
 		break;
taruti@0 399
 
taruti@0 400
 	case D_SCONST:
taruti@0 401
 		while(nhunk < NSNAME)
taruti@0 402
 			gethunk();
taruti@0 403
 		a->sval = (char*)hunk;
taruti@0 404
 		nhunk -= NSNAME;
taruti@0 405
 		hunk += NSNAME;
taruti@0 406
 
taruti@0 407
 		memmove(a->sval, p+4, NSNAME);
taruti@0 408
 		c += NSNAME;
taruti@0 409
 		break;
taruti@0 410
 
taruti@0 411
 	case D_FCONST:
taruti@0 412
 		while(nhunk < sizeof(Ieee))
taruti@0 413
 			gethunk();
taruti@0 414
 		a->ieee = (Ieee*)hunk;
taruti@0 415
 		nhunk -= sizeof(Ieee);
taruti@0 416
 		hunk += sizeof(Ieee);
taruti@0 417
 
taruti@0 418
 		a->ieee->l = p[4] | (p[5]<<8) |
taruti@0 419
 			(p[6]<<16) | (p[7]<<24);
taruti@0 420
 		a->ieee->h = p[8] | (p[9]<<8) |
taruti@0 421
 			(p[10]<<16) | (p[11]<<24);
taruti@0 422
 		c += 8;
taruti@0 423
 		break;
taruti@0 424
 	}
taruti@0 425
 	s = a->sym;
taruti@0 426
 	if(s == S)
taruti@0 427
 		return c;
taruti@0 428
 	i = a->name;
taruti@0 429
 	if(i != D_AUTO && i != D_PARAM)
taruti@0 430
 		return c;
taruti@0 431
 
taruti@0 432
 	l = a->offset;
taruti@0 433
 	for(u=curauto; u; u=u->link)
taruti@0 434
 		if(u->sym == s)
taruti@0 435
 		if(u->type == i) {
taruti@0 436
 			if(u->offset > l)
taruti@0 437
 				u->offset = l;
taruti@0 438
 			return c;
taruti@0 439
 		}
taruti@0 440
 
taruti@0 441
 	while(nhunk < sizeof(Auto))
taruti@0 442
 		gethunk();
taruti@0 443
 	u = (Auto*)hunk;
taruti@0 444
 	nhunk -= sizeof(Auto);
taruti@0 445
 	hunk += sizeof(Auto);
taruti@0 446
 
taruti@0 447
 	u->link = curauto;
taruti@0 448
 	curauto = u;
taruti@0 449
 	u->sym = s;
taruti@0 450
 	u->offset = l;
taruti@0 451
 	u->type = i;
taruti@0 452
 	return c;
taruti@0 453
 }
taruti@0 454
 
taruti@0 455
 void
taruti@0 456
 addlib(char *obj)
taruti@0 457
 {
taruti@0 458
 	char name[1024], comp[256], *p;
taruti@0 459
 	int i;
taruti@0 460
 
taruti@0 461
 	if(histfrogp <= 0)
taruti@0 462
 		return;
taruti@0 463
 
taruti@0 464
 	if(histfrog[0]->name[1] == '/') {
cinap_lenrek@4275 465
 		name[0] = 0;
taruti@0 466
 		i = 1;
taruti@0 467
 	} else
taruti@0 468
 	if(histfrog[0]->name[1] == '.') {
cinap_lenrek@4275 469
 		snprint(name, sizeof name, ".");
taruti@0 470
 		i = 0;
taruti@0 471
 	} else {
taruti@0 472
 		if(debug['9'])
cinap_lenrek@4275 473
 			snprint(name, sizeof name, "/%s/lib", thestring);
taruti@0 474
 		else
cinap_lenrek@4275 475
 			snprint(name, sizeof name, "/usr/%clib", thechar);
taruti@0 476
 		i = 0;
taruti@0 477
 	}
taruti@0 478
 
taruti@0 479
 	for(; i<histfrogp; i++) {
taruti@0 480
 		snprint(comp, sizeof comp, histfrog[i]->name+1);
taruti@0 481
 		for(;;) {
taruti@0 482
 			p = strstr(comp, "$O");
taruti@0 483
 			if(p == 0)
taruti@0 484
 				break;
taruti@0 485
 			memmove(p+1, p+2, strlen(p+2)+1);
taruti@0 486
 			p[0] = thechar;
taruti@0 487
 		}
taruti@0 488
 		for(;;) {
taruti@0 489
 			p = strstr(comp, "$M");
taruti@0 490
 			if(p == 0)
taruti@0 491
 				break;
taruti@0 492
 			if(strlen(comp)+strlen(thestring)-2+1 >= sizeof comp) {
taruti@0 493
 				diag("library component too long");
taruti@0 494
 				return;
taruti@0 495
 			}
taruti@0 496
 			memmove(p+strlen(thestring), p+2, strlen(p+2)+1);
taruti@0 497
 			memmove(p, thestring, strlen(thestring));
taruti@0 498
 		}
taruti@0 499
 		if(strlen(name) + strlen(comp) + 3 >= sizeof(name)) {
taruti@0 500
 			diag("library component too long");
taruti@0 501
 			return;
taruti@0 502
 		}
taruti@0 503
 		strcat(name, "/");
taruti@0 504
 		strcat(name, comp);
taruti@0 505
 	}
taruti@0 506
 	for(i=0; i<libraryp; i++)
taruti@0 507
 		if(strcmp(name, library[i]) == 0)
taruti@0 508
 			return;
taruti@0 509
 	if(libraryp == nelem(library)){
taruti@0 510
 		diag("too many autolibs; skipping %s", name);
taruti@0 511
 		return;
taruti@0 512
 	}
taruti@0 513
 
taruti@0 514
 	p = malloc(strlen(name) + 1);
taruti@0 515
 	strcpy(p, name);
taruti@0 516
 	library[libraryp] = p;
taruti@0 517
 	p = malloc(strlen(obj) + 1);
taruti@0 518
 	strcpy(p, obj);
taruti@0 519
 	libraryobj[libraryp] = p;
taruti@0 520
 	libraryp++;
taruti@0 521
 }
taruti@0 522
 
taruti@0 523
 void
taruti@0 524
 addhist(long line, int type)
taruti@0 525
 {
taruti@0 526
 	Auto *u;
taruti@0 527
 	Sym *s;
taruti@0 528
 	int i, j, k;
taruti@0 529
 
taruti@0 530
 	u = malloc(sizeof(Auto));
taruti@0 531
 	s = malloc(sizeof(Sym));
taruti@0 532
 	s->name = malloc(2*(histfrogp+1) + 1);
taruti@0 533
 
taruti@0 534
 	u->sym = s;
taruti@0 535
 	u->type = type;
taruti@0 536
 	u->offset = line;
taruti@0 537
 	u->link = curhist;
taruti@0 538
 	curhist = u;
taruti@0 539
 
taruti@0 540
 	j = 1;
taruti@0 541
 	for(i=0; i<histfrogp; i++) {
taruti@0 542
 		k = histfrog[i]->value;
taruti@0 543
 		s->name[j+0] = k>>8;
taruti@0 544
 		s->name[j+1] = k;
taruti@0 545
 		j += 2;
taruti@0 546
 	}
taruti@0 547
 }
taruti@0 548
 
taruti@0 549
 void
taruti@0 550
 histtoauto(void)
taruti@0 551
 {
taruti@0 552
 	Auto *l;
taruti@0 553
 
taruti@0 554
 	while(l = curhist) {
taruti@0 555
 		curhist = l->link;
taruti@0 556
 		l->link = curauto;
taruti@0 557
 		curauto = l;
taruti@0 558
 	}
taruti@0 559
 }
taruti@0 560
 
taruti@0 561
 void
taruti@0 562
 collapsefrog(Sym *s)
taruti@0 563
 {
taruti@0 564
 	int i;
taruti@0 565
 
taruti@0 566
 	/*
taruti@0 567
 	 * bad encoding of path components only allows
taruti@0 568
 	 * MAXHIST components. if there is an overflow,
taruti@0 569
 	 * first try to collapse xxx/..
taruti@0 570
 	 */
taruti@0 571
 	for(i=1; i<histfrogp; i++)
taruti@0 572
 		if(strcmp(histfrog[i]->name+1, "..") == 0) {
taruti@0 573
 			memmove(histfrog+i-1, histfrog+i+1,
taruti@0 574
 				(histfrogp-i-1)*sizeof(histfrog[0]));
taruti@0 575
 			histfrogp--;
taruti@0 576
 			goto out;
taruti@0 577
 		}
taruti@0 578
 
taruti@0 579
 	/*
taruti@0 580
 	 * next try to collapse .
taruti@0 581
 	 */
taruti@0 582
 	for(i=0; i<histfrogp; i++)
taruti@0 583
 		if(strcmp(histfrog[i]->name+1, ".") == 0) {
taruti@0 584
 			memmove(histfrog+i, histfrog+i+1,
taruti@0 585
 				(histfrogp-i-1)*sizeof(histfrog[0]));
taruti@0 586
 			goto out;
taruti@0 587
 		}
taruti@0 588
 
taruti@0 589
 	/*
taruti@0 590
 	 * last chance, just truncate from front
taruti@0 591
 	 */
taruti@0 592
 	memmove(histfrog+0, histfrog+1,
taruti@0 593
 		(histfrogp-1)*sizeof(histfrog[0]));
taruti@0 594
 
taruti@0 595
 out:
taruti@0 596
 	histfrog[histfrogp-1] = s;
taruti@0 597
 }
taruti@0 598
 
taruti@0 599
 void
taruti@0 600
 nopout(Prog *p)
taruti@0 601
 {
taruti@0 602
 	p->as = ANOP;
taruti@0 603
 	p->from.type = D_NONE;
taruti@0 604
 	p->to.type = D_NONE;
taruti@0 605
 }
taruti@0 606
 
taruti@0 607
 uchar*
taruti@0 608
 readsome(int f, uchar *buf, uchar *good, uchar *stop, int max)
taruti@0 609
 {
taruti@0 610
 	int n;
taruti@0 611
 
taruti@0 612
 	n = stop - good;
taruti@0 613
 	memmove(buf, good, stop - good);
taruti@0 614
 	stop = buf + n;
taruti@0 615
 	n = MAXIO - n;
taruti@0 616
 	if(n > max)
taruti@0 617
 		n = max;
taruti@0 618
 	n = read(f, stop, n);
taruti@0 619
 	if(n <= 0)
taruti@0 620
 		return 0;
taruti@0 621
 	return stop + n;
taruti@0 622
 }
taruti@0 623
 
taruti@0 624
 void
taruti@0 625
 ldobj(int f, long c, char *pn)
taruti@0 626
 {
taruti@0 627
 	long ipc;
taruti@0 628
 	Prog *p, *t;
taruti@0 629
 	uchar *bloc, *bsize, *stop;
taruti@0 630
 	Sym *h[NSYM], *s, *di;
taruti@0 631
 	int v, o, r, skip;
taruti@0 632
 
taruti@0 633
 	bsize = buf.xbuf;
taruti@0 634
 	bloc = buf.xbuf;
taruti@0 635
 	di = S;
taruti@0 636
 
taruti@0 637
 newloop:
taruti@0 638
 	memset(h, 0, sizeof(h));
taruti@0 639
 	version++;
taruti@0 640
 	histfrogp = 0;
taruti@0 641
 	ipc = pc;
taruti@0 642
 	skip = 0;
taruti@0 643
 
taruti@0 644
 loop:
taruti@0 645
 	if(c <= 0)
taruti@0 646
 		goto eof;
taruti@0 647
 	r = bsize - bloc;
taruti@0 648
 	if(r < 100 && r < c) {		/* enough for largest prog */
taruti@0 649
 		bsize = readsome(f, buf.xbuf, bloc, bsize, c);
taruti@0 650
 		if(bsize == 0)
taruti@0 651
 			goto eof;
taruti@0 652
 		bloc = buf.xbuf;
taruti@0 653
 		goto loop;
taruti@0 654
 	}
taruti@0 655
 	o = bloc[0];		/* as */
taruti@0 656
 	if(o <= AXXX || o >= ALAST) {
taruti@0 657
 		diag("%s: line %ld: opcode out of range %d", pn, pc-ipc, o);
taruti@0 658
 		print("	probably not a .7 file\n");
taruti@0 659
 		errorexit();
taruti@0 660
 	}
taruti@0 661
 	if(o == ANAME) {
taruti@0 662
 		stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
taruti@0 663
 		if(stop == 0){
taruti@0 664
 			bsize = readsome(f, buf.xbuf, bloc, bsize, c);
taruti@0 665
 			if(bsize == 0)
taruti@0 666
 				goto eof;
taruti@0 667
 			bloc = buf.xbuf;
taruti@0 668
 			stop = memchr(&bloc[3], 0, bsize-&bloc[3]);
taruti@0 669
 			if(stop == 0){
taruti@0 670
 				fprint(2, "%s: name too long\n", pn);
taruti@0 671
 				errorexit();
taruti@0 672
 			}
taruti@0 673
 		}
taruti@0 674
 		v = bloc[1];	/* type */
taruti@0 675
 		o = bloc[2];	/* sym */
taruti@0 676
 		bloc += 3;
taruti@0 677
 		c -= 3;
taruti@0 678
 
taruti@0 679
 		r = 0;
taruti@0 680
 		if(v == D_STATIC)
taruti@0 681
 			r = version;
taruti@0 682
 		s = lookup((char*)bloc, r);
taruti@0 683
 		c -= &stop[1] - bloc;
taruti@0 684
 		bloc = stop + 1;
taruti@0 685
 
taruti@0 686
 		if(debug['W'])
taruti@0 687
 			print("	ANAME	%s\n", s->name);
taruti@0 688
 		h[o] = s;
taruti@0 689
 		if((v == D_EXTERN || v == D_STATIC) && s->type == 0)
taruti@0 690
 			s->type = SXREF;
taruti@0 691
 		if(v == D_FILE) {
taruti@0 692
 			if(s->type != SFILE) {
taruti@0 693
 				histgen++;
taruti@0 694
 				s->type = SFILE;
taruti@0 695
 				s->value = histgen;
taruti@0 696
 			}
taruti@0 697
 			if(histfrogp < MAXHIST) {
taruti@0 698
 				histfrog[histfrogp] = s;
taruti@0 699
 				histfrogp++;
taruti@0 700
 			} else
taruti@0 701
 				collapsefrog(s);
taruti@0 702
 		}
taruti@0 703
 		goto loop;
taruti@0 704
 	}
taruti@0 705
 
taruti@0 706
 	if(nhunk < sizeof(Prog))
taruti@0 707
 		gethunk();
taruti@0 708
 	p = (Prog*)hunk;
taruti@0 709
 	nhunk -= sizeof(Prog);
taruti@0 710
 	hunk += sizeof(Prog);
taruti@0 711
 
taruti@0 712
 	p->as = o;
taruti@0 713
 	p->reg = bloc[1] & 0x7f;
taruti@0 714
 	if(bloc[1] & 0x80)
taruti@0 715
 		p->mark = NOSCHED;
taruti@0 716
 	p->line = bloc[2] | (bloc[3]<<8) | (bloc[4]<<16) | (bloc[5]<<24);
taruti@0 717
 
taruti@0 718
 	r = zaddr(bloc+6, &p->from, h) + 6;
taruti@0 719
 	r += zaddr(bloc+r, &p->to, h);
taruti@0 720
 	bloc += r;
taruti@0 721
 	c -= r;
taruti@0 722
 
taruti@0 723
 	if(p->reg < 0 || p->reg > NREG)
taruti@0 724
 		diag("register out of range %d", p->reg);
taruti@0 725
 
taruti@0 726
 	p->link = P;
taruti@0 727
 	p->cond = P;
taruti@0 728
 
taruti@0 729
 	if(debug['W'])
taruti@0 730
 		print("%P\n", p);
taruti@0 731
 
taruti@0 732
 	switch(o) {
taruti@0 733
 	case AHISTORY:
taruti@0 734
 		if(p->to.offset == -1) {
taruti@0 735
 			addlib(pn);
taruti@0 736
 			histfrogp = 0;
taruti@0 737
 			goto loop;
taruti@0 738
 		}
taruti@0 739
 		addhist(p->line, D_FILE);		/* 'z' */
taruti@0 740
 		if(p->to.offset)
taruti@0 741
 			addhist(p->to.offset, D_PREG);	/* 'Z' */
taruti@0 742
 		histfrogp = 0;
taruti@0 743
 		goto loop;
taruti@0 744
 
taruti@0 745
 	case AEND:
taruti@0 746
 		histtoauto();
taruti@0 747
 		if(curtext != P)
taruti@0 748
 			curtext->to.autom = curauto;
taruti@0 749
 		curauto = 0;
taruti@0 750
 		curtext = P;
taruti@0 751
 		if(c)
taruti@0 752
 			goto newloop;
taruti@0 753
 		return;
taruti@0 754
 
taruti@0 755
 	case AGLOBL:
taruti@0 756
 		s = p->from.sym;
taruti@0 757
 		if(s == S) {
taruti@0 758
 			diag("GLOBL must have a name\n%P", p);
taruti@0 759
 			errorexit();
taruti@0 760
 		}
taruti@0 761
 		if(s->type == 0 || s->type == SXREF) {
taruti@0 762
 			s->type = SBSS;
taruti@0 763
 			s->value = 0;
taruti@0 764
 		}
taruti@0 765
 		if(s->type != SBSS) {
taruti@0 766
 			diag("redefinition: %s\n%P", s->name, p);
taruti@0 767
 			s->type = SBSS;
taruti@0 768
 			s->value = 0;
taruti@0 769
 		}
taruti@0 770
 		if(p->to.offset > s->value)
taruti@0 771
 			s->value = p->to.offset;
taruti@0 772
 		break;
taruti@0 773
 
taruti@0 774
 	case ADYNT:
taruti@0 775
 		if(p->to.sym == S) {
taruti@0 776
 			diag("DYNT without a sym\n%P", p);
taruti@0 777
 			break;
taruti@0 778
 		}
taruti@0 779
 		di = p->to.sym;
taruti@0 780
 		p->reg = 4;
taruti@0 781
 		if(di->type == SXREF) {
taruti@0 782
 			if(debug['z'])
taruti@0 783
 				Bprint(&bso, "%P set to %d\n", p, dtype);
taruti@0 784
 			di->type = SCONST;
taruti@0 785
 			di->value = dtype;
taruti@0 786
 			dtype += 4;
taruti@0 787
 		}
taruti@0 788
 		if(p->from.sym == S)
taruti@0 789
 			break;
taruti@0 790
 
taruti@0 791
 		p->from.offset = di->value;
taruti@0 792
 		p->from.sym->type = SDATA;
taruti@0 793
 		if(curtext == P) {
taruti@0 794
 			diag("DYNT not in text: %P", p);
taruti@0 795
 			break;
taruti@0 796
 		}
taruti@0 797
 		p->to.sym = curtext->from.sym;
taruti@0 798
 		p->to.type = D_CONST;
taruti@0 799
 		p->link = datap;
taruti@0 800
 		datap = p;
taruti@0 801
 		break;
taruti@0 802
 
taruti@0 803
 	case AINIT:
taruti@0 804
 		if(p->from.sym == S) {
taruti@0 805
 			diag("INIT without a sym\n%P", p);
taruti@0 806
 			break;
taruti@0 807
 		}
taruti@0 808
 		if(di == S) {
taruti@0 809
 			diag("INIT without previous DYNT\n%P", p);
taruti@0 810
 			break;
taruti@0 811
 		}
taruti@0 812
 		p->from.offset = di->value;
taruti@0 813
 		p->from.sym->type = SDATA;
taruti@0 814
 		p->link = datap;
taruti@0 815
 		datap = p;
taruti@0 816
 		break;
taruti@0 817
 	
taruti@0 818
 	case ADATA:
taruti@0 819
 		if(p->from.sym == S) {
taruti@0 820
 			diag("DATA without a sym\n%P", p);
taruti@0 821
 			break;
taruti@0 822
 		}
taruti@0 823
 		p->link = datap;
taruti@0 824
 		datap = p;
taruti@0 825
 		break;
taruti@0 826
 
taruti@0 827
 	case AGOK:
taruti@0 828
 		diag("unknown opcode\n%P", p);
taruti@0 829
 		p->pc = pc;
taruti@0 830
 		pc++;
taruti@0 831
 		break;
taruti@0 832
 
taruti@0 833
 	case ATEXT:
taruti@0 834
 		if(curtext != P) {
taruti@0 835
 			histtoauto();
taruti@0 836
 			curtext->to.autom = curauto;
taruti@0 837
 			curauto = 0;
taruti@0 838
 		}
taruti@0 839
 		skip = 0;
taruti@0 840
 		curtext = p;
taruti@0 841
 		autosize = (p->to.offset+3L) & ~3L;
taruti@0 842
 		if (autosize & 4)
taruti@0 843
 			autosize += 4;
taruti@0 844
 		p->to.offset = autosize;
taruti@0 845
 		autosize += 8;
taruti@0 846
 		s = p->from.sym;
taruti@0 847
 		if(s == S) {
taruti@0 848
 			diag("TEXT must have a name\n%P", p);
taruti@0 849
 			errorexit();
taruti@0 850
 		}
taruti@0 851
 		if(s->type != 0 && s->type != SXREF) {
taruti@0 852
 			if(p->reg & DUPOK) {
taruti@0 853
 				skip = 1;
taruti@0 854
 				goto casedef;
taruti@0 855
 			}
taruti@0 856
 			diag("redefinition: %s\n%P", s->name, p);
taruti@0 857
 		}
taruti@0 858
 		s->type = STEXT;
taruti@0 859
 		s->value = pc;
taruti@0 860
 		lastp->link = p;
taruti@0 861
 		lastp = p;
taruti@0 862
 		p->pc = pc;
taruti@0 863
 		pc++;
taruti@0 864
 		if(textp == P) {
taruti@0 865
 			textp = p;
taruti@0 866
 			etextp = p;
taruti@0 867
 			goto loop;
taruti@0 868
 		}
taruti@0 869
 		etextp->cond = p;
taruti@0 870
 		etextp = p;
taruti@0 871
 		break;
taruti@0 872
 
taruti@0 873
 	case AMOVS:
taruti@0 874
 		if(skip)
taruti@0 875
 			goto casedef;
taruti@0 876
 
taruti@0 877
 		if(p->from.type == D_FCONST) {
taruti@0 878
 			/* size sb 9 max */
cinap_lenrek@4275 879
 			snprint(literal, sizeof literal, "$%lux", ieeedtof(p->from.ieee));
taruti@0 880
 			s = lookup(literal, 0);
taruti@0 881
 			if(s->type == 0) {
taruti@0 882
 				s->type = SBSS;
taruti@0 883
 				s->value = 4;
taruti@0 884
 				t = prg();
taruti@0 885
 				t->as = ADATA;
taruti@0 886
 				t->line = p->line;
taruti@0 887
 				t->from.type = D_OREG;
taruti@0 888
 				t->from.sym = s;
taruti@0 889
 				t->from.name = D_EXTERN;
taruti@0 890
 				t->reg = 4;
taruti@0 891
 				t->to = p->from;
taruti@0 892
 				t->link = datap;
taruti@0 893
 				datap = t;
taruti@0 894
 			}
taruti@0 895
 			p->from.type = D_OREG;
taruti@0 896
 			p->from.sym = s;
taruti@0 897
 			p->from.name = D_EXTERN;
taruti@0 898
 			p->from.offset = 0;
taruti@0 899
 		}
taruti@0 900
 		goto casedef;
taruti@0 901
 
taruti@0 902
 	case AMOVT:
taruti@0 903
 		if(skip)
taruti@0 904
 			goto casedef;
taruti@0 905
 
taruti@0 906
 		if(p->from.type == D_FCONST) {
taruti@0 907
 			/* size sb 18 max */
cinap_lenrek@4275 908
 			snprint(literal, sizeof literal, "$%lux.%lux",
taruti@0 909
 				p->from.ieee->l, p->from.ieee->h);
taruti@0 910
 			s = lookup(literal, 0);
taruti@0 911
 			if(s->type == 0) {
taruti@0 912
 				s->type = SBSS;
taruti@0 913
 				s->value = 8;
taruti@0 914
 				t = prg();
taruti@0 915
 				t->as = ADATA;
taruti@0 916
 				t->line = p->line;
taruti@0 917
 				t->from.type = D_OREG;
taruti@0 918
 				t->from.sym = s;
taruti@0 919
 				t->from.name = D_EXTERN;
taruti@0 920
 				t->reg = 8;
taruti@0 921
 				t->to = p->from;
taruti@0 922
 				t->link = datap;
taruti@0 923
 				datap = t;
taruti@0 924
 			}
taruti@0 925
 			p->from.type = D_OREG;
taruti@0 926
 			p->from.sym = s;
taruti@0 927
 			p->from.name = D_EXTERN;
taruti@0 928
 			p->from.offset = 0;
taruti@0 929
 		}
taruti@0 930
 		goto casedef;
taruti@0 931
 
taruti@0 932
 	case AMOVQ:
taruti@0 933
 		if(skip)
taruti@0 934
 			goto casedef;
taruti@0 935
 
taruti@0 936
 		if (p->from.type == D_FREG || p->to.type == D_FREG)
taruti@0 937
 			p->as = AMOVT;		/* stupid compiler optimiser kkludge */
taruti@0 938
 
taruti@0 939
 	case AMOVL:
taruti@0 940
 	case AMOVW:
taruti@0 941
 	case AMOVB:
taruti@0 942
 		/* BOTCH */
taruti@0 943
 		if (p->from.type == D_CONST)
taruti@0 944
 		if (p->from.offset == 0LL && p->from.name == D_NONE) {
taruti@0 945
 			p->from.type = D_REG;
taruti@0 946
 			p->from.reg = REGZERO;
taruti@0 947
 		}
taruti@0 948
 		goto casedef;
taruti@0 949
 
taruti@0 950
 	default:
taruti@0 951
 	casedef:
taruti@0 952
 		if(skip)
taruti@0 953
 			nopout(p);
taruti@0 954
 
taruti@0 955
 		if(p->to.type == D_BRANCH)
taruti@0 956
 			p->to.offset += ipc;
taruti@0 957
 		lastp->link = p;
taruti@0 958
 		lastp = p;
taruti@0 959
 		p->pc = pc;
taruti@0 960
 		pc++;
taruti@0 961
 		break;
taruti@0 962
 	}
taruti@0 963
 	goto loop;
taruti@0 964
 
taruti@0 965
 eof:
taruti@0 966
 	diag("truncated object file: %s", pn);
taruti@0 967
 }
taruti@0 968
 
taruti@0 969
 Sym*
taruti@0 970
 lookup(char *symb, int v)
taruti@0 971
 {
taruti@0 972
 	Sym *s;
taruti@0 973
 	char *p;
taruti@0 974
 	long h;
taruti@0 975
 	int c0, l;
taruti@0 976
 
taruti@0 977
 	h = v;
taruti@0 978
 	for(p=symb; c0 = *p; p++)
taruti@0 979
 		h = h+h+h + c0;
taruti@0 980
 	l = (p - symb) + 1;
taruti@0 981
 	if(h < 0)
taruti@0 982
 		h = ~h;
taruti@0 983
 	h %= NHASH;
taruti@0 984
 	for(s = hash[h]; s != S; s = s->link)
taruti@0 985
 		if(s->version == v)
taruti@0 986
 		if(memcmp(s->name, symb, l) == 0)
taruti@0 987
 			return s;
taruti@0 988
 
taruti@0 989
 	while(nhunk < sizeof(Sym))
taruti@0 990
 		gethunk();
taruti@0 991
 	s = (Sym*)hunk;
taruti@0 992
 	nhunk -= sizeof(Sym);
taruti@0 993
 	hunk += sizeof(Sym);
taruti@0 994
 
taruti@0 995
 	s->name = malloc(l);
taruti@0 996
 	memmove(s->name, symb, l);
taruti@0 997
 
taruti@0 998
 	s->link = hash[h];
taruti@0 999
 	s->type = 0;
taruti@0 1000
 	s->version = v;
taruti@0 1001
 	s->value = 0;
taruti@0 1002
 	hash[h] = s;
taruti@0 1003
 	return s;
taruti@0 1004
 }
taruti@0 1005
 
taruti@0 1006
 Prog*
taruti@0 1007
 prg(void)
taruti@0 1008
 {
taruti@0 1009
 	Prog *p;
taruti@0 1010
 
taruti@0 1011
 	while(nhunk < sizeof(Prog))
taruti@0 1012
 		gethunk();
taruti@0 1013
 	p = (Prog*)hunk;
taruti@0 1014
 	nhunk -= sizeof(Prog);
taruti@0 1015
 	hunk += sizeof(Prog);
taruti@0 1016
 
taruti@0 1017
 	*p = zprg;
taruti@0 1018
 	return p;
taruti@0 1019
 }
taruti@0 1020
 
taruti@0 1021
 void
taruti@0 1022
 gethunk(void)
taruti@0 1023
 {
taruti@0 1024
 	char *h;
taruti@0 1025
 	long nh;
taruti@0 1026
 
taruti@0 1027
 	nh = NHUNK;
taruti@0 1028
 	if(thunk >= 5L*NHUNK) {
taruti@0 1029
 		nh = 5L*NHUNK;
taruti@0 1030
 		if(thunk >= 25L*NHUNK)
taruti@0 1031
 			nh = 25L*NHUNK;
taruti@0 1032
 	}
taruti@0 1033
 	h = mysbrk(nh);
taruti@0 1034
 	if(h == (char*)-1) {
taruti@0 1035
 		diag("out of memory");
taruti@0 1036
 		errorexit();
taruti@0 1037
 	}
taruti@0 1038
 	hunk = h;
taruti@0 1039
 	nhunk = nh;
taruti@0 1040
 	thunk += nh;
taruti@0 1041
 }
taruti@0 1042
 
taruti@0 1043
 void
taruti@0 1044
 doprof1(void)
taruti@0 1045
 {
taruti@0 1046
 	Sym *s;
taruti@0 1047
 	long n;
taruti@0 1048
 	Prog *p, *q;
taruti@0 1049
 
taruti@0 1050
 	if(debug['v'])
taruti@0 1051
 		Bprint(&bso, "%5.2f profile 1\n", cputime());
taruti@0 1052
 	Bflush(&bso);
taruti@0 1053
 	s = lookup("__mcount", 0);
taruti@0 1054
 	n = 1;
taruti@0 1055
 	for(p = firstp->link; p != P; p = p->link) {
taruti@0 1056
 		if(p->as == ATEXT) {
taruti@0 1057
 			q = prg();
taruti@0 1058
 			q->line = p->line;
taruti@0 1059
 			q->link = datap;
taruti@0 1060
 			datap = q;
taruti@0 1061
 			q->as = ADATA;
taruti@0 1062
 			q->from.type = D_OREG;
taruti@0 1063
 			q->from.name = D_EXTERN;
taruti@0 1064
 			q->from.offset = n*4;
taruti@0 1065
 			q->from.sym = s;
taruti@0 1066
 			q->reg = 4;
taruti@0 1067
 			q->to = p->from;
taruti@0 1068
 			q->to.type = D_CONST;
taruti@0 1069
 
taruti@0 1070
 			q = prg();
taruti@0 1071
 			q->line = p->line;
taruti@0 1072
 			q->pc = p->pc;
taruti@0 1073
 			q->link = p->link;
taruti@0 1074
 			p->link = q;
taruti@0 1075
 			p = q;
taruti@0 1076
 			p->as = AMOVL;
taruti@0 1077
 			p->from.type = D_OREG;
taruti@0 1078
 			p->from.name = D_EXTERN;
taruti@0 1079
 			p->from.sym = s;
taruti@0 1080
 			p->from.offset = n*4 + 4;
taruti@0 1081
 			p->to.type = D_REG;
taruti@0 1082
 			p->to.reg = REGTMP;
taruti@0 1083
 
taruti@0 1084
 			q = prg();
taruti@0 1085
 			q->line = p->line;
taruti@0 1086
 			q->pc = p->pc;
taruti@0 1087
 			q->link = p->link;
taruti@0 1088
 			p->link = q;
taruti@0 1089
 			p = q;
taruti@0 1090
 			p->as = AADDQ;
taruti@0 1091
 			p->from.type = D_CONST;
taruti@0 1092
 			p->from.offset = 1;
taruti@0 1093
 			p->to.type = D_REG;
taruti@0 1094
 			p->to.reg = REGTMP;
taruti@0 1095
 
taruti@0 1096
 			q = prg();
taruti@0 1097
 			q->line = p->line;
taruti@0 1098
 			q->pc = p->pc;
taruti@0 1099
 			q->link = p->link;
taruti@0 1100
 			p->link = q;
taruti@0 1101
 			p = q;
taruti@0 1102
 			p->as = AMOVL;
taruti@0 1103
 			p->from.type = D_REG;
taruti@0 1104
 			p->from.reg = REGTMP;
taruti@0 1105
 			p->to.type = D_OREG;
taruti@0 1106
 			p->to.name = D_EXTERN;
taruti@0 1107
 			p->to.sym = s;
taruti@0 1108
 			p->to.offset = n*4 + 4;
taruti@0 1109
 
taruti@0 1110
 			n += 2;
taruti@0 1111
 			continue;
taruti@0 1112
 		}
taruti@0 1113
 	}
taruti@0 1114
 	q = prg();
taruti@0 1115
 	q->line = 0;
taruti@0 1116
 	q->link = datap;
taruti@0 1117
 	datap = q;
taruti@0 1118
 
taruti@0 1119
 	q->as = ADATA;
taruti@0 1120
 	q->from.type = D_OREG;
taruti@0 1121
 	q->from.name = D_EXTERN;
taruti@0 1122
 	q->from.sym = s;
taruti@0 1123
 	q->reg = 4;
taruti@0 1124
 	q->to.type = D_CONST;
taruti@0 1125
 	q->to.offset = n;
taruti@0 1126
 
taruti@0 1127
 	s->type = SBSS;
taruti@0 1128
 	s->value = n*4;
taruti@0 1129
 }
taruti@0 1130
 
taruti@0 1131
 void
taruti@0 1132
 doprof2(void)
taruti@0 1133
 {
taruti@0 1134
 	Sym *s2, *s4;
taruti@0 1135
 	Prog *p, *q, *q2, *ps2, *ps4;
taruti@0 1136
 
taruti@0 1137
 	if(debug['v'])
taruti@0 1138
 		Bprint(&bso, "%5.2f profile 2\n", cputime());
taruti@0 1139
 	Bflush(&bso);
taruti@0 1140
 
taruti@0 1141
 	if(debug['e']){
taruti@0 1142
 		s2 = lookup("_tracein", 0);
taruti@0 1143
 		s4 = lookup("_traceout", 0);
taruti@0 1144
 	}else{
taruti@0 1145
 		s2 = lookup("_profin", 0);
taruti@0 1146
 		s4 = lookup("_profout", 0);
taruti@0 1147
 	}
taruti@0 1148
 	if(s2->type != STEXT || s4->type != STEXT) {
taruti@0 1149
 		if(debug['e'])
taruti@0 1150
 			diag("_tracein/_traceout not defined %d %d", s2->type, s4->type);
taruti@0 1151
 		else
taruti@0 1152
 			diag("_profin/_profout not defined");
taruti@0 1153
 		return;
taruti@0 1154
 	}
taruti@0 1155
 
taruti@0 1156
 	ps2 = P;
taruti@0 1157
 	ps4 = P;
taruti@0 1158
 	for(p = firstp; p != P; p = p->link) {
taruti@0 1159
 		if(p->as == ATEXT) {
taruti@0 1160
 			if(p->from.sym == s2) {
taruti@0 1161
 				ps2 = p;
taruti@0 1162
 				p->reg = 1;
taruti@0 1163
 			}
taruti@0 1164
 			if(p->from.sym == s4) {
taruti@0 1165
 				ps4 = p;
taruti@0 1166
 				p->reg = 1;
taruti@0 1167
 			}
taruti@0 1168
 		}
taruti@0 1169
 	}
taruti@0 1170
 	for(p = firstp; p != P; p = p->link) {
taruti@0 1171
 		if(p->as == ATEXT) {
taruti@0 1172
 			if(p->reg != NREG) {
taruti@0 1173
 				for(;;) {
taruti@0 1174
 					q = p->link;
taruti@0 1175
 					if(q == P)
taruti@0 1176
 						break;
taruti@0 1177
 					if(q->as == ATEXT)
taruti@0 1178
 						break;
taruti@0 1179
 					p = q;
taruti@0 1180
 				}
taruti@0 1181
 				continue;
taruti@0 1182
 			}
taruti@0 1183
 
taruti@0 1184
 			/*
taruti@0 1185
 			 * JSR	profin, R2
taruti@0 1186
 			 */
taruti@0 1187
 			q = prg();
taruti@0 1188
 			q->line = p->line;
taruti@0 1189
 			q->pc = p->pc;
taruti@0 1190
 			q->link = p->link;
taruti@0 1191
 			if(debug['e']){		/* embedded tracing */
taruti@0 1192
 				q2 = prg();
taruti@0 1193
 				p->link = q2;
taruti@0 1194
 				q2->link = q;
taruti@0 1195
 
taruti@0 1196
 				q2->line = p->line;
taruti@0 1197
 				q2->pc = p->pc;
taruti@0 1198
 
taruti@0 1199
 				q2->as = AJMP;
taruti@0 1200
 				q2->to.type = D_BRANCH;
taruti@0 1201
 				q2->to.sym = p->to.sym;
taruti@0 1202
 				q2->cond = q->link;
taruti@0 1203
 			}else
taruti@0 1204
 				p->link = q;
taruti@0 1205
 			p = q;
taruti@0 1206
 			p->as = AJSR;
taruti@0 1207
 			p->to.type = D_BRANCH;
taruti@0 1208
 			p->cond = ps2;
taruti@0 1209
 			p->to.sym = s2;
taruti@0 1210
 
taruti@0 1211
 			continue;
taruti@0 1212
 		}
taruti@0 1213
 		if(p->as == ARET) {
taruti@0 1214
 			/*
taruti@0 1215
 			 * JSR (default)
taruti@0 1216
 			 */
taruti@0 1217
 			if(debug['e']){		/* embedded tracing */
taruti@0 1218
 				q = prg();
taruti@0 1219
 				q->line = p->line;
taruti@0 1220
 				q->pc = p->pc;
taruti@0 1221
 				q->link = p->link;
taruti@0 1222
 				p->link = q;
taruti@0 1223
 				p = q;
taruti@0 1224
 			}
taruti@0 1225
 			/*
taruti@0 1226
 			 * JSR	profout
taruti@0 1227
 			 */
taruti@0 1228
 			p->as = AJSR;
taruti@0 1229
 			p->to.type = D_BRANCH;
taruti@0 1230
 			p->cond = ps4;
taruti@0 1231
 			p->to.sym = s4;
taruti@0 1232
 
taruti@0 1233
 			
taruti@0 1234
 			/*
taruti@0 1235
 			 * RET
taruti@0 1236
 			 */
taruti@0 1237
 			q = prg();
taruti@0 1238
 			q->line = p->line;
taruti@0 1239
 			q->pc = p->pc;
taruti@0 1240
 			q->link = p->link;
taruti@0 1241
 			p->link = q;
taruti@0 1242
 			p = q;
taruti@0 1243
 			p->as = ARET;
taruti@0 1244
 
taruti@0 1245
 			continue;
taruti@0 1246
 		}
taruti@0 1247
 	}
taruti@0 1248
 }
taruti@0 1249
 
taruti@0 1250
 void
taruti@0 1251
 nuxiinit(void)
taruti@0 1252
 {
taruti@0 1253
 	int i, c;
taruti@0 1254
 
taruti@0 1255
 	for(i=0; i<4; i++) {
taruti@0 1256
 		c = find1(0x04030201L, i+1);
taruti@0 1257
 		if(i <= 4)
taruti@0 1258
 			inuxi4[i] = c;
taruti@0 1259
 		if(i <= 2)
taruti@0 1260
 			inuxi2[i] = c;
taruti@0 1261
 		if(i <= 1)
taruti@0 1262
 			inuxi1[i] = c;
taruti@0 1263
 	}
taruti@0 1264
 	for (i = 0; i < 4; i++) {
taruti@0 1265
 		c = find1(0x04030201L, i+1);
taruti@0 1266
 		fnuxi8[i] = c;
taruti@0 1267
 		fnuxi8[i+4] = c + sizeof(long);
taruti@0 1268
 	}
taruti@0 1269
 
taruti@0 1270
 	if(debug['v']) {
taruti@0 1271
 		Bprint(&bso, "inuxi = ");
taruti@0 1272
 		for(i=0; i<1; i++)
taruti@0 1273
 			Bprint(&bso, "%d", inuxi1[i]);
taruti@0 1274
 		Bprint(&bso, " ");
taruti@0 1275
 		for(i=0; i<2; i++)
taruti@0 1276
 			Bprint(&bso, "%d", inuxi2[i]);
taruti@0 1277
 		Bprint(&bso, " ");
taruti@0 1278
 		for(i=0; i<4; i++)
taruti@0 1279
 			Bprint(&bso, "%d", inuxi4[i]);
taruti@0 1280
 		Bprint(&bso, " ");
taruti@0 1281
 		Bprint(&bso, "\nfnuxi = ");
taruti@0 1282
 		for(i=0; i<8; i++)
taruti@0 1283
 			Bprint(&bso, "%d", fnuxi8[i]);
taruti@0 1284
 		Bprint(&bso, "\n");
taruti@0 1285
 	}
taruti@0 1286
 	Bflush(&bso);
taruti@0 1287
 }
taruti@0 1288
 
taruti@0 1289
 find1(long l, int c)
taruti@0 1290
 {
taruti@0 1291
 	char *p;
taruti@0 1292
 	int i;
taruti@0 1293
 
taruti@0 1294
 	p = (char*)&l;
taruti@0 1295
 	for(i=0; i<4; i++)
taruti@0 1296
 		if(*p++ == c)
taruti@0 1297
 			return i;
taruti@0 1298
 	return 0;
taruti@0 1299
 }
taruti@0 1300
 
taruti@0 1301
 long
taruti@0 1302
 ieeedtof(Ieee *ieee)
taruti@0 1303
 {
taruti@0 1304
 	int exp;
taruti@0 1305
 	long v;
taruti@0 1306
 
taruti@0 1307
 	if(ieee->h == 0)
taruti@0 1308
 		return 0;
taruti@0 1309
 	exp = (ieee->h>>20) & ((1L<<11)-1L);
taruti@0 1310
 	exp -= (1L<<10) - 2L;
taruti@0 1311
 	v = (ieee->h & 0xfffffL) << 3;
taruti@0 1312
 	v |= (ieee->l >> 29) & 0x7L;
taruti@0 1313
 	if((ieee->l >> 28) & 1) {
taruti@0 1314
 		v++;
taruti@0 1315
 		if(v & 0x800000L) {
taruti@0 1316
 			v = (v & 0x7fffffL) >> 1;
taruti@0 1317
 			exp++;
taruti@0 1318
 		}
taruti@0 1319
 	}
taruti@0 1320
 	if(exp <= -126 || exp >= 130)
taruti@0 1321
 		diag("double fp to single fp overflow");
taruti@0 1322
 	v |= ((exp + 126) & 0xffL) << 23;
taruti@0 1323
 	v |= ieee->h & 0x80000000L;
taruti@0 1324
 	return v;
taruti@0 1325
 }
taruti@0 1326
 
taruti@0 1327
 double
taruti@0 1328
 ieeedtod(Ieee *ieee)
taruti@0 1329
 {
taruti@0 1330
 	Ieee e;
taruti@0 1331
 	double fr;
taruti@0 1332
 	int exp;
taruti@0 1333
 
taruti@0 1334
 	if(ieee->h & (1L<<31)) {
taruti@0 1335
 		e.h = ieee->h & ~(1L<<31);
taruti@0 1336
 		e.l = ieee->l;
taruti@0 1337
 		return -ieeedtod(&e);
taruti@0 1338
 	}
taruti@0 1339
 	if(ieee->l == 0 && ieee->h == 0)
taruti@0 1340
 		return 0;
taruti@0 1341
 	fr = ieee->l & ((1L<<16)-1L);
taruti@0 1342
 	fr /= 1L<<16;
taruti@0 1343
 	fr += (ieee->l>>16) & ((1L<<16)-1L);
taruti@0 1344
 	fr /= 1L<<16;
taruti@0 1345
 	fr += (ieee->h & (1L<<20)-1L) | (1L<<20);
taruti@0 1346
 	fr /= 1L<<21;
taruti@0 1347
 	exp = (ieee->h>>20) & ((1L<<11)-1L);
taruti@0 1348
 	exp -= (1L<<10) - 2L;
taruti@0 1349
 	return ldexp(fr, exp);
taruti@0 1350
 }