github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/cmd/6l/list.c (about) 1 // Inferno utils/6l/list.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/list.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 // Printing. 32 33 #include "l.h" 34 #include "../ld/lib.h" 35 36 static Prog* bigP; 37 38 void 39 listinit(void) 40 { 41 42 fmtinstall('R', Rconv); 43 fmtinstall('A', Aconv); 44 fmtinstall('D', Dconv); 45 fmtinstall('S', Sconv); 46 fmtinstall('P', Pconv); 47 fmtinstall('I', Iconv); 48 } 49 50 int 51 Pconv(Fmt *fp) 52 { 53 Prog *p; 54 55 p = va_arg(fp->args, Prog*); 56 bigP = p; 57 switch(p->as) { 58 case ATEXT: 59 if(p->from.scale) { 60 fmtprint(fp, "(%d) %A %D,%d,%lD", 61 p->line, p->as, &p->from, p->from.scale, &p->to); 62 break; 63 } 64 fmtprint(fp, "(%d) %A %D,%lD", 65 p->line, p->as, &p->from, &p->to); 66 break; 67 default: 68 fmtprint(fp, "(%d) %A %D,%D", 69 p->line, p->as, &p->from, &p->to); 70 break; 71 case ADATA: 72 case AINIT_: 73 case ADYNT_: 74 fmtprint(fp, "(%d) %A %D/%d,%D", 75 p->line, p->as, &p->from, p->from.scale, &p->to); 76 break; 77 } 78 bigP = P; 79 return 0; 80 } 81 82 int 83 Aconv(Fmt *fp) 84 { 85 int i; 86 87 i = va_arg(fp->args, int); 88 return fmtstrcpy(fp, anames[i]); 89 } 90 91 int 92 Dconv(Fmt *fp) 93 { 94 char str[STRINGSZ], s[STRINGSZ]; 95 Adr *a; 96 int i; 97 98 a = va_arg(fp->args, Adr*); 99 i = a->type; 100 101 if(fp->flags & FmtLong) { 102 if(i != D_CONST) { 103 // ATEXT dst is not constant 104 snprint(str, sizeof(str), "!!%D", a); 105 goto brk; 106 } 107 parsetextconst(a->offset); 108 if(textarg == 0) { 109 snprint(str, sizeof(str), "$%lld", textstksiz); 110 goto brk; 111 } 112 snprint(str, sizeof(str), "$%lld-%lld", textstksiz, textarg); 113 goto brk; 114 } 115 116 if(i >= D_INDIR) { 117 if(a->offset) 118 snprint(str, sizeof(str), "%lld(%R)", a->offset, i-D_INDIR); 119 else 120 snprint(str, sizeof(str), "(%R)", i-D_INDIR); 121 goto brk; 122 } 123 switch(i) { 124 125 default: 126 if(a->offset) 127 snprint(str, sizeof(str), "$%lld,%R", a->offset, i); 128 else 129 snprint(str, sizeof(str), "%R", i); 130 break; 131 132 case D_NONE: 133 str[0] = 0; 134 break; 135 136 case D_BRANCH: 137 if(bigP != P && bigP->pcond != P) 138 if(a->sym != S) 139 snprint(str, sizeof(str), "%llux+%s", bigP->pcond->pc, 140 a->sym->name); 141 else 142 snprint(str, sizeof(str), "%llux", bigP->pcond->pc); 143 else 144 snprint(str, sizeof(str), "%lld(PC)", a->offset); 145 break; 146 147 case D_EXTERN: 148 if(a->sym) { 149 snprint(str, sizeof(str), "%s+%lld(SB)", a->sym->name, a->offset); 150 break; 151 } 152 snprint(str, sizeof(str), "!!noname!!+%lld(SB)", a->offset); 153 break; 154 155 case D_STATIC: 156 if(a->sym) { 157 snprint(str, sizeof(str), "%s<%d>+%lld(SB)", a->sym->name, 158 a->sym->version, a->offset); 159 break; 160 } 161 snprint(str, sizeof(str), "!!noname!!<999>+%lld(SB)", a->offset); 162 break; 163 164 case D_AUTO: 165 if(a->sym) { 166 snprint(str, sizeof(str), "%s+%lld(SP)", a->sym->name, a->offset); 167 break; 168 } 169 snprint(str, sizeof(str), "!!noname!!+%lld(SP)", a->offset); 170 break; 171 172 case D_PARAM: 173 if(a->sym) { 174 snprint(str, sizeof(str), "%s+%lld(%s)", a->sym->name, a->offset, paramspace); 175 break; 176 } 177 snprint(str, sizeof(str), "!!noname!!+%lld(%s)", a->offset, paramspace); 178 break; 179 180 case D_CONST: 181 snprint(str, sizeof(str), "$%lld", a->offset); 182 break; 183 184 case D_FCONST: 185 snprint(str, sizeof(str), "$(%.8ux,%.8ux)", a->ieee.h, a->ieee.l); 186 break; 187 188 case D_SCONST: 189 snprint(str, sizeof(str), "$\"%S\"", a->scon); 190 break; 191 192 case D_ADDR: 193 a->type = a->index; 194 a->index = D_NONE; 195 snprint(str, sizeof(str), "$%D", a); 196 a->index = a->type; 197 a->type = D_ADDR; 198 goto conv; 199 } 200 brk: 201 if(a->index != D_NONE) { 202 snprint(s, sizeof(s), "(%R*%d)", a->index, a->scale); 203 strcat(str, s); 204 } 205 conv: 206 fmtstrcpy(fp, str); 207 // if(a->gotype) 208 // fmtprint(fp, "«%s»", a->gotype->name); 209 return 0; 210 211 } 212 213 char* regstr[] = 214 { 215 "AL", /* [D_AL] */ 216 "CL", 217 "DL", 218 "BL", 219 "SPB", 220 "BPB", 221 "SIB", 222 "DIB", 223 "R8B", 224 "R9B", 225 "R10B", 226 "R11B", 227 "R12B", 228 "R13B", 229 "R14B", 230 "R15B", 231 232 "AX", /* [D_AX] */ 233 "CX", 234 "DX", 235 "BX", 236 "SP", 237 "BP", 238 "SI", 239 "DI", 240 "R8", 241 "R9", 242 "R10", 243 "R11", 244 "R12", 245 "R13", 246 "R14", 247 "R15", 248 249 "AH", 250 "CH", 251 "DH", 252 "BH", 253 254 "F0", /* [D_F0] */ 255 "F1", 256 "F2", 257 "F3", 258 "F4", 259 "F5", 260 "F6", 261 "F7", 262 263 "M0", 264 "M1", 265 "M2", 266 "M3", 267 "M4", 268 "M5", 269 "M6", 270 "M7", 271 272 "X0", 273 "X1", 274 "X2", 275 "X3", 276 "X4", 277 "X5", 278 "X6", 279 "X7", 280 "X8", 281 "X9", 282 "X10", 283 "X11", 284 "X12", 285 "X13", 286 "X14", 287 "X15", 288 289 "CS", /* [D_CS] */ 290 "SS", 291 "DS", 292 "ES", 293 "FS", 294 "GS", 295 296 "GDTR", /* [D_GDTR] */ 297 "IDTR", /* [D_IDTR] */ 298 "LDTR", /* [D_LDTR] */ 299 "MSW", /* [D_MSW] */ 300 "TASK", /* [D_TASK] */ 301 302 "CR0", /* [D_CR] */ 303 "CR1", 304 "CR2", 305 "CR3", 306 "CR4", 307 "CR5", 308 "CR6", 309 "CR7", 310 "CR8", 311 "CR9", 312 "CR10", 313 "CR11", 314 "CR12", 315 "CR13", 316 "CR14", 317 "CR15", 318 319 "DR0", /* [D_DR] */ 320 "DR1", 321 "DR2", 322 "DR3", 323 "DR4", 324 "DR5", 325 "DR6", 326 "DR7", 327 328 "TR0", /* [D_TR] */ 329 "TR1", 330 "TR2", 331 "TR3", 332 "TR4", 333 "TR5", 334 "TR6", 335 "TR7", 336 337 "NONE", /* [D_NONE] */ 338 }; 339 340 int 341 Rconv(Fmt *fp) 342 { 343 char str[STRINGSZ]; 344 int r; 345 346 r = va_arg(fp->args, int); 347 if(r >= D_AL && r <= D_NONE) 348 snprint(str, sizeof(str), "%s", regstr[r-D_AL]); 349 else 350 snprint(str, sizeof(str), "gok(%d)", r); 351 352 return fmtstrcpy(fp, str); 353 } 354 355 int 356 Sconv(Fmt *fp) 357 { 358 int i, c; 359 char str[STRINGSZ], *p, *a; 360 361 a = va_arg(fp->args, char*); 362 p = str; 363 for(i=0; i<sizeof(double); i++) { 364 c = a[i] & 0xff; 365 if(c >= 'a' && c <= 'z' || 366 c >= 'A' && c <= 'Z' || 367 c >= '0' && c <= '9') { 368 *p++ = c; 369 continue; 370 } 371 *p++ = '\\'; 372 switch(c) { 373 default: 374 if(c < 040 || c >= 0177) 375 break; /* not portable */ 376 p[-1] = c; 377 continue; 378 case 0: 379 *p++ = 'z'; 380 continue; 381 case '\\': 382 case '"': 383 *p++ = c; 384 continue; 385 case '\n': 386 *p++ = 'n'; 387 continue; 388 case '\t': 389 *p++ = 't'; 390 continue; 391 } 392 *p++ = (c>>6) + '0'; 393 *p++ = ((c>>3) & 7) + '0'; 394 *p++ = (c & 7) + '0'; 395 } 396 *p = 0; 397 return fmtstrcpy(fp, str); 398 } 399 400 int 401 Iconv(Fmt *fp) 402 { 403 int i, n; 404 uchar *p; 405 char *s; 406 Fmt fmt; 407 408 n = fp->prec; 409 fp->prec = 0; 410 if(!(fp->flags&FmtPrec) || n < 0) 411 return fmtstrcpy(fp, "%I"); 412 fp->flags &= ~FmtPrec; 413 p = va_arg(fp->args, uchar*); 414 415 // format into temporary buffer and 416 // call fmtstrcpy to handle padding. 417 fmtstrinit(&fmt); 418 for(i=0; i<n; i++) 419 fmtprint(&fmt, "%.2ux", *p++); 420 s = fmtstrflush(&fmt); 421 fmtstrcpy(fp, s); 422 free(s); 423 return 0; 424 } 425 426 void 427 diag(char *fmt, ...) 428 { 429 char buf[1024], *tn, *sep; 430 va_list arg; 431 432 tn = ""; 433 sep = ""; 434 if(cursym != S) { 435 tn = cursym->name; 436 sep = ": "; 437 } 438 va_start(arg, fmt); 439 vseprint(buf, buf+sizeof(buf), fmt, arg); 440 va_end(arg); 441 print("%s%s%s\n", tn, sep, buf); 442 443 nerrors++; 444 if(nerrors > 20) { 445 print("too many errors\n"); 446 errorexit(); 447 } 448 } 449 450 void 451 parsetextconst(vlong arg) 452 { 453 textstksiz = arg & 0xffffffffLL; 454 if(textstksiz & 0x80000000LL) 455 textstksiz = -(-textstksiz & 0xffffffffLL); 456 457 textarg = (arg >> 32) & 0xffffffffLL; 458 if(textarg & 0x80000000LL) 459 textarg = 0; 460 textarg = (textarg+7) & ~7LL; 461 }