symbol.c (8647B)
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 case 'm': 260 flags |= SRELOC; 261 break; 262 default: 263 abort(); 264 } 265 } 266 267 return flags; 268 } 269 270 static int 271 sectype(int flags) 272 { 273 if (flags & SEXEC) 274 return 'T'; 275 if ((flags & (SALLOC|SLOAD|SREAD)) == (SALLOC|SLOAD|SREAD)) 276 return 'D'; 277 if ((flags & (SALLOC|SLOAD|SREAD)) == (SALLOC|SREAD)) 278 return 'B'; 279 return '?'; 280 } 281 282 static Section * 283 newsec(Symbol *sym, char *attr) 284 { 285 int idx; 286 Section *sec; 287 struct lsection *lsec; 288 struct lsymbol *lsym; 289 290 if (secindex == INT_MAX) { 291 fputs("as: too many sections\n", stderr); 292 exit(EXIT_FAILURE); 293 } 294 295 lsec = xmalloc(sizeof(*lsec)); 296 lsec->pc = lsec->curpc = 0; 297 lsec->next = seclist; 298 lsec->fp = NULL; 299 seclist = lsec; 300 301 sec = &lsec->sec; 302 sec->name = sym->name; 303 sec->base = sec->size = 0; 304 sec->flags = 0; 305 sec->fill = 0; 306 sec->align = 0; 307 sec->index = secindex; 308 sec->flags |= secflags(attr); 309 sec->type = sectype(sec->flags); 310 311 /* sym->flags = ? */ 312 sym->section = sec->index; 313 sym->type = tolower(sec->type); 314 sym->index = symindex; 315 lsym = (struct lsymbol *) sym; 316 lsym->sec = sec; 317 318 if (mapsec(map, sec, NULL, 0) < 0) { 319 fprintf(stderr, 320 "as: error allocating section mapping '%s'\n", 321 sym->name); 322 exit(EXIT_FAILURE); 323 } 324 325 if (!setsec(obj, &secindex, sec)) { 326 fprintf(stderr, 327 "as: error adding section '%s' to output\n", 328 sym->name); 329 exit(EXIT_FAILURE); 330 } 331 332 if (!setsym(obj, &symindex, sym)) { 333 fprintf(stderr, 334 "as: error adding section symbol '%s' to output\n", 335 sym->name); 336 exit(EXIT_FAILURE); 337 } 338 339 secindex++; 340 symindex++; 341 342 return sec; 343 } 344 345 Section * 346 defsec(char *name, char *attr) 347 { 348 struct lsymbol *lsym; 349 Section *sec; 350 Symbol *sym; 351 352 cursec = NULL; 353 sym = lookup(name); 354 if (sym->flags & ~FSECT) 355 error("invalid section name '%s'", name); 356 357 lsym = (struct lsymbol *) sym; 358 sec = lsym->sec; 359 if (sec == NULL) { 360 sec = newsec(sym, attr); 361 lsym->sec = sec; 362 sym->section = sec->index; 363 sym->flags = FSECT; 364 } 365 366 return cursec = sec; 367 } 368 369 void 370 ibinfmt(void) 371 { 372 int t; 373 374 if ((t = objtype("coff-z80")) < 0) { 375 fprintf(stderr, 376 "as: invalid binary format %s\n", "coff32-z80"); 377 exit(EXIT_FAILURE); 378 } 379 380 if ((obj = newobj(t)) < 0) { 381 fputs("as: error allocating output\n", stderr); 382 exit(EXIT_FAILURE); 383 } 384 385 if ((map = newmap(4, 0)) == NULL) { 386 perror("as"); 387 exit(EXIT_FAILURE); 388 } 389 390 stext = defsec(".text", "mrxcl"); 391 sdata = defsec(".data", "mrwcl"); 392 sbss = defsec(".bss", "rwc"); 393 } 394 395 void 396 cleansecs(void) 397 { 398 int r; 399 Section *sec; 400 struct lsection *lsec; 401 402 for (lsec = seclist; lsec; lsec = lsec->next) { 403 sec = &lsec->sec; 404 lsec->curpc = lsec->pc = sec->base; 405 if (pass == 1 || (sec->flags & SALLOC) == 0) 406 continue; 407 408 lsec->fp = tmpfile(); 409 r = mapsec(map, sec, lsec->fp, sec->size); 410 411 if (!lsec->fp || r < 0) { 412 perror("as: creating section mapping"); 413 exit(EXIT_FAILURE); 414 } 415 } 416 cursec = stext; 417 } 418 419 void 420 emit(char *bytes, int n) 421 { 422 struct lsection *lsec = (struct lsection *) cursec; 423 424 if (lsec->fp) 425 fwrite(bytes, n, 1, lsec->fp); 426 incpc(n); 427 } 428 429 Symbol * 430 tmpsym(TUINT val) 431 { 432 Symbol *sym; 433 434 if (!tmpalloc) 435 tmpalloc = alloc(sizeof(*sym), NALLOC); 436 sym = new(tmpalloc); 437 sym->value = val; 438 sym->section = -1; 439 sym->flags = FABS; 440 441 return sym; 442 } 443 444 void 445 killtmp(void) 446 { 447 if (!tmpalloc) 448 return; 449 dealloc(tmpalloc); 450 tmpalloc = NULL; 451 } 452 453 static int 454 dumpsec(FILE *src, FILE *dst) 455 { 456 int c; 457 458 if (!src) 459 return 0; 460 461 rewind(src); 462 while ((c = getc(src)) != EOF) 463 putc(c, dst); 464 465 if (ferror(src)) 466 return -1; 467 468 return 0; 469 } 470 471 void 472 writecoff(char *fname) 473 { 474 FILE *fp; 475 476 if ((fp = fopen(fname, "wb")) == NULL) 477 goto error; 478 479 if (writeobj(obj, map, fp) < 0) { 480 fputs("as: corrupted object type\n", stderr); 481 goto error; 482 } 483 484 if (fclose(fp) == EOF) 485 goto error; 486 outfile = NULL; 487 return; 488 489 error: 490 fprintf(stderr, "as: %s: error writing output file\n", fname); 491 if (errno) 492 perror("as"); 493 exit(EXIT_FAILURE); 494 } 495 496 void 497 writeout(char *fname) 498 { 499 FILE *fp; 500 struct lsection *lp; 501 502 if ((fp = fopen(fname, "wb")) == NULL) 503 goto error; 504 505 506 for (lp = seclist; lp; lp = lp->next) { 507 if (dumpsec(lp->fp, fp) < 0) 508 goto error; 509 } 510 fflush(fp); 511 512 if (ferror(fp)) 513 goto error; 514 515 fclose(fp); 516 outfile = NULL; 517 518 return; 519 520 error: 521 fprintf(stderr, "as: %s: %s\n", fname, strerror(errno)); 522 exit(EXIT_FAILURE); 523 }