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