github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/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,%D", 61 p->line, p->as, &p->from, p->from.scale, &p->to); 62 break; 63 } 64 default: 65 fmtprint(fp, "(%d) %A %D,%D", 66 p->line, p->as, &p->from, &p->to); 67 break; 68 case ADATA: 69 case AINIT_: 70 case ADYNT_: 71 fmtprint(fp, "(%d) %A %D/%d,%D", 72 p->line, p->as, &p->from, p->from.scale, &p->to); 73 break; 74 } 75 bigP = P; 76 return 0; 77 } 78 79 int 80 Aconv(Fmt *fp) 81 { 82 int i; 83 84 i = va_arg(fp->args, int); 85 return fmtstrcpy(fp, anames[i]); 86 } 87 88 int 89 Dconv(Fmt *fp) 90 { 91 char str[STRINGSZ], s[STRINGSZ]; 92 Adr *a; 93 int i; 94 95 a = va_arg(fp->args, Adr*); 96 i = a->type; 97 98 if(fp->flags & FmtLong) { 99 if(i != D_CONST) { 100 // ATEXT dst is not constant 101 snprint(str, sizeof(str), "!!%D", a); 102 goto brk; 103 } 104 parsetextconst(a->offset); 105 if(textarg == 0) { 106 snprint(str, sizeof(str), "$%lld", textstksiz); 107 goto brk; 108 } 109 snprint(str, sizeof(str), "$%lld-%lld", textstksiz, textarg); 110 goto brk; 111 } 112 113 if(i >= D_INDIR) { 114 if(a->offset) 115 snprint(str, sizeof(str), "%lld(%R)", a->offset, i-D_INDIR); 116 else 117 snprint(str, sizeof(str), "(%R)", i-D_INDIR); 118 goto brk; 119 } 120 switch(i) { 121 122 default: 123 if(a->offset) 124 snprint(str, sizeof(str), "$%lld,%R", a->offset, i); 125 else 126 snprint(str, sizeof(str), "%R", i); 127 break; 128 129 case D_NONE: 130 str[0] = 0; 131 break; 132 133 case D_BRANCH: 134 if(bigP != P && bigP->pcond != P) 135 if(a->sym != S) 136 snprint(str, sizeof(str), "%llux+%s", bigP->pcond->pc, 137 a->sym->name); 138 else 139 snprint(str, sizeof(str), "%llux", bigP->pcond->pc); 140 else 141 snprint(str, sizeof(str), "%lld(PC)", a->offset); 142 break; 143 144 case D_EXTERN: 145 if(a->sym) { 146 snprint(str, sizeof(str), "%s+%lld(SB)", a->sym->name, a->offset); 147 break; 148 } 149 snprint(str, sizeof(str), "!!noname!!+%lld(SB)", a->offset); 150 break; 151 152 case D_STATIC: 153 if(a->sym) { 154 snprint(str, sizeof(str), "%s<%d>+%lld(SB)", a->sym->name, 155 a->sym->version, a->offset); 156 break; 157 } 158 snprint(str, sizeof(str), "!!noname!!<999>+%lld(SB)", a->offset); 159 break; 160 161 case D_AUTO: 162 if(a->sym) { 163 snprint(str, sizeof(str), "%s+%lld(SP)", a->sym->name, a->offset); 164 break; 165 } 166 snprint(str, sizeof(str), "!!noname!!+%lld(SP)", a->offset); 167 break; 168 169 case D_PARAM: 170 if(a->sym) { 171 snprint(str, sizeof(str), "%s+%lld(%s)", a->sym->name, a->offset, paramspace); 172 break; 173 } 174 snprint(str, sizeof(str), "!!noname!!+%lld(%s)", a->offset, paramspace); 175 break; 176 177 case D_CONST: 178 snprint(str, sizeof(str), "$%lld", a->offset); 179 break; 180 181 case D_FCONST: 182 snprint(str, sizeof(str), "$(%.8ux,%.8ux)", a->ieee.h, a->ieee.l); 183 break; 184 185 case D_SCONST: 186 snprint(str, sizeof(str), "$\"%S\"", a->scon); 187 break; 188 189 case D_ADDR: 190 a->type = a->index; 191 a->index = D_NONE; 192 snprint(str, sizeof(str), "$%D", a); 193 a->index = a->type; 194 a->type = D_ADDR; 195 goto conv; 196 } 197 brk: 198 if(a->index != D_NONE) { 199 snprint(s, sizeof(s), "(%R*%d)", a->index, a->scale); 200 strcat(str, s); 201 } 202 conv: 203 fmtstrcpy(fp, str); 204 // if(a->gotype) 205 // fmtprint(fp, "«%s»", a->gotype->name); 206 return 0; 207 208 } 209 210 char* regstr[] = 211 { 212 "AL", /* [D_AL] */ 213 "CL", 214 "DL", 215 "BL", 216 "SPB", 217 "BPB", 218 "SIB", 219 "DIB", 220 "R8B", 221 "R9B", 222 "R10B", 223 "R11B", 224 "R12B", 225 "R13B", 226 "R14B", 227 "R15B", 228 229 "AX", /* [D_AX] */ 230 "CX", 231 "DX", 232 "BX", 233 "SP", 234 "BP", 235 "SI", 236 "DI", 237 "R8", 238 "R9", 239 "R10", 240 "R11", 241 "R12", 242 "R13", 243 "R14", 244 "R15", 245 246 "AH", 247 "CH", 248 "DH", 249 "BH", 250 251 "F0", /* [D_F0] */ 252 "F1", 253 "F2", 254 "F3", 255 "F4", 256 "F5", 257 "F6", 258 "F7", 259 260 "M0", 261 "M1", 262 "M2", 263 "M3", 264 "M4", 265 "M5", 266 "M6", 267 "M7", 268 269 "X0", 270 "X1", 271 "X2", 272 "X3", 273 "X4", 274 "X5", 275 "X6", 276 "X7", 277 "X8", 278 "X9", 279 "X10", 280 "X11", 281 "X12", 282 "X13", 283 "X14", 284 "X15", 285 286 "CS", /* [D_CS] */ 287 "SS", 288 "DS", 289 "ES", 290 "FS", 291 "GS", 292 293 "GDTR", /* [D_GDTR] */ 294 "IDTR", /* [D_IDTR] */ 295 "LDTR", /* [D_LDTR] */ 296 "MSW", /* [D_MSW] */ 297 "TASK", /* [D_TASK] */ 298 299 "CR0", /* [D_CR] */ 300 "CR1", 301 "CR2", 302 "CR3", 303 "CR4", 304 "CR5", 305 "CR6", 306 "CR7", 307 "CR8", 308 "CR9", 309 "CR10", 310 "CR11", 311 "CR12", 312 "CR13", 313 "CR14", 314 "CR15", 315 316 "DR0", /* [D_DR] */ 317 "DR1", 318 "DR2", 319 "DR3", 320 "DR4", 321 "DR5", 322 "DR6", 323 "DR7", 324 325 "TR0", /* [D_TR] */ 326 "TR1", 327 "TR2", 328 "TR3", 329 "TR4", 330 "TR5", 331 "TR6", 332 "TR7", 333 334 "NONE", /* [D_NONE] */ 335 }; 336 337 int 338 Rconv(Fmt *fp) 339 { 340 char str[STRINGSZ]; 341 int r; 342 343 r = va_arg(fp->args, int); 344 if(r >= D_AL && r <= D_NONE) 345 snprint(str, sizeof(str), "%s", regstr[r-D_AL]); 346 else 347 snprint(str, sizeof(str), "gok(%d)", r); 348 349 return fmtstrcpy(fp, str); 350 } 351 352 int 353 Sconv(Fmt *fp) 354 { 355 int i, c; 356 char str[STRINGSZ], *p, *a; 357 358 a = va_arg(fp->args, char*); 359 p = str; 360 for(i=0; i<sizeof(double); i++) { 361 c = a[i] & 0xff; 362 if(c >= 'a' && c <= 'z' || 363 c >= 'A' && c <= 'Z' || 364 c >= '0' && c <= '9') { 365 *p++ = c; 366 continue; 367 } 368 *p++ = '\\'; 369 switch(c) { 370 default: 371 if(c < 040 || c >= 0177) 372 break; /* not portable */ 373 p[-1] = c; 374 continue; 375 case 0: 376 *p++ = 'z'; 377 continue; 378 case '\\': 379 case '"': 380 *p++ = c; 381 continue; 382 case '\n': 383 *p++ = 'n'; 384 continue; 385 case '\t': 386 *p++ = 't'; 387 continue; 388 } 389 *p++ = (c>>6) + '0'; 390 *p++ = ((c>>3) & 7) + '0'; 391 *p++ = (c & 7) + '0'; 392 } 393 *p = 0; 394 return fmtstrcpy(fp, str); 395 } 396 397 int 398 Iconv(Fmt *fp) 399 { 400 int i, n; 401 uchar *p; 402 char *s; 403 Fmt fmt; 404 405 n = fp->prec; 406 fp->prec = 0; 407 if(!(fp->flags&FmtPrec) || n < 0) 408 return fmtstrcpy(fp, "%I"); 409 fp->flags &= ~FmtPrec; 410 p = va_arg(fp->args, uchar*); 411 412 // format into temporary buffer and 413 // call fmtstrcpy to handle padding. 414 fmtstrinit(&fmt); 415 for(i=0; i<n; i++) 416 fmtprint(&fmt, "%.2ux", *p++); 417 s = fmtstrflush(&fmt); 418 fmtstrcpy(fp, s); 419 free(s); 420 return 0; 421 } 422 423 void 424 diag(char *fmt, ...) 425 { 426 char buf[STRINGSZ], *tn, *sep; 427 va_list arg; 428 429 tn = ""; 430 sep = ""; 431 if(cursym != S) { 432 tn = cursym->name; 433 sep = ": "; 434 } 435 va_start(arg, fmt); 436 vseprint(buf, buf+sizeof(buf), fmt, arg); 437 va_end(arg); 438 print("%s%s%s\n", tn, sep, buf); 439 440 nerrors++; 441 if(nerrors > 20) { 442 print("too many errors\n"); 443 errorexit(); 444 } 445 } 446 447 void 448 parsetextconst(vlong arg) 449 { 450 textstksiz = arg & 0xffffffffLL; 451 if(textstksiz & 0x80000000LL) 452 textstksiz = -(-textstksiz & 0xffffffffLL); 453 454 textarg = (arg >> 32) & 0xffffffffLL; 455 if(textarg & 0x80000000LL) 456 textarg = 0; 457 textarg = (textarg+7) & ~7LL; 458 }