symbol.c (8669B)
1 #include <ctype.h> 2 #include <errno.h> 3 #include <limits.h> 4 #include <stdio.h> 5 #include <stdint.h> 6 #include <stdlib.h> 7 #include <string.h> 8 9 #include <scc/cstd.h> 10 #include <scc/mach.h> 11 #include <scc/scc.h> 12 13 #include "as.h" 14 15 #define HASHSIZ 64 16 #define NALLOC 10 17 18 /* 19 * sym must be the first field because we generate 20 * a pointer to lsymbol from the symbol 21 */ 22 struct lsymbol { 23 Symbol sym; 24 Section *sec; 25 struct lsymbol *next; 26 struct lsymbol *hash; 27 }; 28 29 /* 30 * sec must be the first field because we generate 31 * a pointer to lsection from the section 32 */ 33 struct lsection { 34 Section sec; 35 FILE *fp; 36 unsigned long long curpc; 37 unsigned long long pc; 38 struct lsection *next; 39 }; 40 41 Section *cursec; 42 Section *sbss, *sdata, *stext; 43 Symbol *linesym; 44 int pass; 45 46 static Obj *obj; 47 static Map *map; 48 static struct lsection *seclist; 49 static struct lsymbol *hashtbl[HASHSIZ], *symlast, *symlist; 50 51 static Symbol *cursym; 52 static Alloc *tmpalloc; 53 static int secindex, symindex; 54 55 #ifndef NDEBUG 56 void 57 dumpstab(char *msg) 58 { 59 struct lsymbol **bp, *lp; 60 61 fprintf(stderr, "%s\n", msg); 62 for (bp = hashtbl; bp < &hashtbl[HASHSIZ]; ++bp) { 63 if (*bp == NULL) 64 continue; 65 66 fprintf(stderr, "[%d]", (int) (bp - hashtbl)); 67 for (lp = *bp; lp; lp = lp->hash) { 68 fprintf(stderr, " -> %s:%0X:%0llX", 69 lp->sym.name, 70 lp->sym.flags, 71 lp->sym.value); 72 } 73 putc('\n', stderr); 74 } 75 } 76 #endif 77 78 Symbol * 79 lookup(char *name) 80 { 81 int r; 82 unsigned h; 83 Symbol *sym; 84 struct lsymbol *lp; 85 char *curname, buf[INTIDENTSIZ+1]; 86 87 if (*name == '.' && cursym) { 88 if (!cursym) 89 error("local label '%s' without global label", name); 90 curname = cursym->name; 91 r = snprintf(buf, sizeof(buf), "%s%s", curname, name); 92 if (r < 0 || r >= sizeof(buf)) 93 error("too long local label '%s%s'", curname, name); 94 name = buf; 95 } 96 97 h = genhash(name) & HASHSIZ-1; 98 for (lp = hashtbl[h]; lp; lp = lp->hash) { 99 if (!casecmp(lp->sym.name, name)) 100 return &lp->sym; 101 } 102 103 lp = xmalloc(sizeof(*lp)); 104 lp->next = NULL; 105 lp->hash = hashtbl[h]; 106 lp->sec = NULL; 107 hashtbl[h] = lp; 108 109 if (symlast) 110 symlast->next = lp; 111 symlast = lp; 112 113 if (!symlist) 114 symlist = lp; 115 116 sym = &lp->sym; 117 sym->name = xstrdup(name); 118 sym->flags = 0; 119 sym->size = sym->value = 0; 120 sym->section = cursec ? cursec->index : -1; 121 122 return sym; 123 } 124 125 Symbol * 126 deflabel(char *name) 127 { 128 int local = 0; 129 Symbol *sym; 130 struct lsection *lsec; 131 char label[MAXSYM+1]; 132 133 if (*name == '.') { 134 int r; 135 136 local = 1; 137 if (!cursym) { 138 error("local label '%s' without global label", name); 139 return NULL; 140 } 141 r = snprintf(label, sizeof(label), 142 "%s%s", 143 cursym->name, name); 144 if (r == sizeof(label)) { 145 error("local label '%s' in '%s' produces too long symbol", 146 name, cursym->name); 147 return NULL; 148 } 149 name = label; 150 } 151 152 sym = lookup(name); 153 if (pass == 1 && (sym->flags & FDEF)) 154 error("redefinition of label '%s'", name); 155 if (cursec->flags & SABS) 156 sym->flags |= FABS; 157 158 lsec = (struct lsection *) cursec; 159 sym->value = lsec->curpc; 160 sym->section = cursec->index; 161 162 if (!local) 163 cursym = sym; 164 return sym; 165 } 166 167 int 168 toobig(Node *np, int type) 169 { 170 unsigned long long val = np->sym->value; 171 172 switch (type) { 173 case AIMM2: 174 return val > 3; 175 case AIMM3: 176 return val > 7; 177 case AIMM5: 178 return val > 0x1F; 179 case AIMM8: 180 return val > 0xFF; 181 case AIMM16: 182 return val > 0xFFFF; 183 case AIMM32: 184 return val > 0xFFFFFFFF; 185 case AIMM64: 186 return 1; 187 default: 188 abort(); 189 } 190 } 191 192 unsigned long long 193 getpc(void) 194 { 195 struct lsection *lsec; 196 197 lsec = (struct lsection *) cursec; 198 return lsec->curpc; 199 } 200 201 static void 202 incpc(int nbytes) 203 { 204 struct lsection *lsec; 205 unsigned long long siz; 206 TUINT pc, curpc; 207 208 lsec = (struct lsection *) cursec; 209 210 pc = lsec->pc; 211 curpc = lsec->curpc; 212 213 lsec->curpc += nbytes; 214 lsec->pc += nbytes; 215 216 if (pass == 2) 217 return; 218 219 siz = lsec->pc - cursec->base; 220 if (siz > cursec->size) 221 cursec->size = siz; 222 223 if (pc > lsec->pc || 224 curpc > lsec->curpc || 225 lsec->curpc > maxaddr || 226 lsec->pc > maxaddr) { 227 die("as: address overflow in section '%s'"); 228 } 229 } 230 231 static int 232 secflags(char *attr) 233 { 234 int c, flags; 235 236 if (!attr) 237 return 0; 238 239 for (flags = 0; c = *attr++; ) { 240 switch (c) { 241 case 'w': 242 flags |= SWRITE; 243 break; 244 case 'r': 245 flags |= SREAD; 246 break; 247 case 'x': 248 flags |= SEXEC; 249 break; 250 case 'c': 251 flags |= SALLOC; 252 break; 253 case 'l': 254 flags |= SLOAD; 255 break; 256 case 'a': 257 flags |= SABS; 258 break; 259 } 260 } 261 262 return flags; 263 } 264 265 static int 266 sectype(int flags) 267 { 268 if (flags & SEXEC) 269 return 'T'; 270 if ((flags & (SALLOC|SLOAD|SREAD)) == (SALLOC|SLOAD|SREAD)) 271 return 'D'; 272 if ((flags & (SALLOC|SLOAD|SREAD)) == (SALLOC|SREAD)) 273 return 'B'; 274 return '?'; 275 } 276 277 static Section * 278 newsec(Symbol *sym, char *attr) 279 { 280 int idx; 281 Section *sec; 282 struct lsection *lsec; 283 struct lsymbol *lsym; 284 285 if (secindex == INT_MAX) { 286 fputs("as: too many sections\n", stderr); 287 exit(EXIT_FAILURE); 288 } 289 290 lsec = xmalloc(sizeof(*lsec)); 291 lsec->pc = lsec->curpc = 0; 292 lsec->next = seclist; 293 lsec->fp = NULL; 294 seclist = lsec; 295 296 sec = &lsec->sec; 297 sec->name = sym->name; 298 sec->base = sec->size = 0; 299 sec->flags = 0; 300 sec->fill = 0; 301 sec->align = 0; 302 sec->index = secindex; 303 sec->flags |= secflags(attr); 304 sec->type = sectype(sec->flags); 305 306 /* sym->flags = ? */ 307 sym->section = sec->index; 308 sym->type = tolower(sec->type); 309 sym->index = symindex; 310 lsym = (struct lsymbol *) sym; 311 lsym->sec = sec; 312 313 if (setmap(map, sym->name, NULL, 0, 0, 0) < 0) { 314 fprintf(stderr, 315 "as: error allocating section mapping '%s'\n", 316 sym->name); 317 exit(EXIT_FAILURE); 318 } 319 320 if (!setsec(obj, &secindex, sec)) { 321 fprintf(stderr, 322 "as: error adding section '%s' to output\n", 323 sym->name); 324 exit(EXIT_FAILURE); 325 } 326 327 if (!setsym(obj, &symindex, sym)) { 328 fprintf(stderr, 329 "as: error adding section symbol '%s' to output\n", 330 sym->name); 331 exit(EXIT_FAILURE); 332 } 333 334 secindex++; 335 symindex++; 336 337 return sec; 338 } 339 340 Section * 341 defsec(char *name, char *attr) 342 { 343 struct lsymbol *lsym; 344 Section *sec; 345 Symbol *sym; 346 347 cursec = NULL; 348 sym = lookup(name); 349 if (sym->flags & ~FSECT) 350 error("invalid section name '%s'", name); 351 352 lsym = (struct lsymbol *) sym; 353 sec = lsym->sec; 354 if (sec == NULL) { 355 sec = newsec(sym, attr); 356 lsym->sec = sec; 357 sym->section = sec->index; 358 sym->flags = FSECT; 359 } 360 361 return cursec = sec; 362 } 363 364 void 365 ibinfmt(void) 366 { 367 int t; 368 369 if ((t = objtype("coff32-z80")) < 0) { 370 fprintf(stderr, 371 "as: invalid binary format %s\n", "coff32-z80"); 372 exit(EXIT_FAILURE); 373 } 374 375 if ((obj = newobj(t)) < 0) { 376 fputs("as: error allocating output\n", stderr); 377 exit(EXIT_FAILURE); 378 } 379 380 if ((map = newmap(NULL, 4)) == NULL) { 381 perror("as"); 382 exit(EXIT_FAILURE); 383 } 384 385 stext = defsec(".text", "rxcl"); 386 sdata = defsec(".data", "rwcl"); 387 sbss = defsec(".bss", "rwc"); 388 } 389 390 void 391 cleansecs(void) 392 { 393 int r; 394 Section *sec; 395 struct lsection *lsec; 396 397 for (lsec = seclist; lsec; lsec = lsec->next) { 398 sec = &lsec->sec; 399 lsec->curpc = lsec->pc = sec->base; 400 if (pass == 1 || (sec->flags & SALLOC) == 0) 401 continue; 402 403 lsec->fp = tmpfile(); 404 r = setmap(map, 405 sec->name, 406 lsec->fp, 407 sec->base, 408 sec->size, 0); 409 410 if (!lsec->fp || r < 0) { 411 perror("as: creating section mapping"); 412 exit(EXIT_FAILURE); 413 } 414 } 415 cursec = stext; 416 } 417 418 void 419 emit(char *bytes, int n) 420 { 421 struct lsection *lsec = (struct lsection *) cursec; 422 423 if (lsec->fp) 424 fwrite(bytes, n, 1, lsec->fp); 425 incpc(n); 426 } 427 428 Symbol * 429 tmpsym(TUINT val) 430 { 431 Symbol *sym; 432 433 if (!tmpalloc) 434 tmpalloc = alloc(sizeof(*sym), NALLOC); 435 sym = new(tmpalloc); 436 sym->value = val; 437 sym->section = -1; 438 sym->flags = FABS; 439 440 return sym; 441 } 442 443 void 444 killtmp(void) 445 { 446 if (!tmpalloc) 447 return; 448 dealloc(tmpalloc); 449 tmpalloc = NULL; 450 } 451 452 static int 453 dumpsec(FILE *src, FILE *dst) 454 { 455 int c; 456 457 if (!src) 458 return 0; 459 460 rewind(src); 461 while ((c = getc(src)) != EOF) 462 putc(c, dst); 463 464 if (ferror(src)) 465 return -1; 466 467 return 0; 468 } 469 470 void 471 writecoff(char *fname) 472 { 473 FILE *fp; 474 475 if ((fp = fopen(fname, "wb")) == NULL) 476 goto error; 477 478 if (writeobj(obj, map, fp) < 0) { 479 fputs("as: corrupted object type\n", stderr); 480 goto error; 481 } 482 483 if (fclose(fp) == EOF) 484 goto error; 485 outfile = NULL; 486 return; 487 488 error: 489 fprintf(stderr, "as: %s: error writing output file\n", fname); 490 if (errno) 491 perror("as"); 492 exit(EXIT_FAILURE); 493 } 494 495 void 496 writeout(char *fname) 497 { 498 FILE *fp; 499 struct lsection *lp; 500 501 if ((fp = fopen(fname, "wb")) == NULL) 502 goto error; 503 504 505 for (lp = seclist; lp; lp = lp->next) { 506 if (dumpsec(lp->fp, fp) < 0) 507 goto error; 508 } 509 fflush(fp); 510 511 if (ferror(fp)) 512 goto error; 513 514 fclose(fp); 515 outfile = NULL; 516 517 return; 518 519 error: 520 fprintf(stderr, "as: %s: %s\n", fname, strerror(errno)); 521 exit(EXIT_FAILURE); 522 }