github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/src/liblink/list8.c (about) 1 // Inferno utils/8c/list.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/8c/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 #include <u.h> 32 #include <libc.h> 33 #include <bio.h> 34 #include <link.h> 35 #include "../cmd/8l/8.out.h" 36 37 static int Aconv(Fmt *fp); 38 static int Dconv(Fmt *fp); 39 static int Pconv(Fmt *fp); 40 static int Rconv(Fmt *fp); 41 static int DSconv(Fmt *fp); 42 43 enum 44 { 45 STRINGSZ = 1000 46 }; 47 48 #pragma varargck type "$" char* 49 50 void 51 listinit8(void) 52 { 53 fmtinstall('A', Aconv); 54 fmtinstall('D', Dconv); 55 fmtinstall('P', Pconv); 56 fmtinstall('R', Rconv); 57 58 // for internal use 59 fmtinstall('$', DSconv); 60 } 61 62 static Prog* bigP; 63 64 static int 65 Pconv(Fmt *fp) 66 { 67 char str[STRINGSZ]; 68 Prog *p; 69 70 p = va_arg(fp->args, Prog*); 71 bigP = p; 72 switch(p->as) { 73 case ADATA: 74 sprint(str, "%.5lld (%L) %A %D/%d,%D", 75 p->pc, p->lineno, p->as, &p->from, p->from.scale, &p->to); 76 break; 77 78 case ATEXT: 79 if(p->from.scale) { 80 sprint(str, "%.5lld (%L) %A %D,%d,%lD", 81 p->pc, p->lineno, p->as, &p->from, p->from.scale, &p->to); 82 break; 83 } 84 sprint(str, "%.5lld (%L) %A %D,%lD", 85 p->pc, p->lineno, p->as, &p->from, &p->to); 86 break; 87 88 default: 89 sprint(str, "%.5lld (%L) %A %D,%D", 90 p->pc, p->lineno, p->as, &p->from, &p->to); 91 break; 92 } 93 bigP = nil; 94 return fmtstrcpy(fp, str); 95 } 96 97 static int 98 Aconv(Fmt *fp) 99 { 100 int i; 101 102 i = va_arg(fp->args, int); 103 return fmtstrcpy(fp, anames8[i]); 104 } 105 106 static int 107 Dconv(Fmt *fp) 108 { 109 char str[STRINGSZ], s[STRINGSZ]; 110 Addr *a; 111 int i; 112 113 a = va_arg(fp->args, Addr*); 114 i = a->type; 115 116 if(fp->flags & FmtLong) { 117 if(i == D_CONST2) 118 sprint(str, "$%lld-%d", a->offset, a->offset2); 119 else { 120 // ATEXT dst is not constant 121 sprint(str, "!!%D", a); 122 } 123 goto brk; 124 } 125 126 if(i >= D_INDIR) { 127 if(a->offset) 128 sprint(str, "%lld(%R)", a->offset, i-D_INDIR); 129 else 130 sprint(str, "(%R)", i-D_INDIR); 131 goto brk; 132 } 133 switch(i) { 134 default: 135 if(a->offset) 136 sprint(str, "$%lld,%R", a->offset, i); 137 else 138 sprint(str, "%R", i); 139 break; 140 141 case D_NONE: 142 str[0] = 0; 143 break; 144 145 case D_BRANCH: 146 if(a->sym != nil) 147 sprint(str, "%s(SB)", a->sym->name); 148 else if(bigP != nil && bigP->pcond != nil) 149 sprint(str, "%lld", bigP->pcond->pc); 150 else if(a->u.branch != nil) 151 sprint(str, "%lld", a->u.branch->pc); 152 else 153 sprint(str, "%lld(PC)", a->offset); 154 break; 155 156 case D_EXTERN: 157 sprint(str, "%s+%lld(SB)", a->sym->name, a->offset); 158 break; 159 160 case D_STATIC: 161 sprint(str, "%s<>+%lld(SB)", a->sym->name, a->offset); 162 break; 163 164 case D_AUTO: 165 if(a->sym) 166 sprint(str, "%s+%lld(SP)", a->sym->name, a->offset); 167 else 168 sprint(str, "%lld(SP)", a->offset); 169 break; 170 171 case D_PARAM: 172 if(a->sym) 173 sprint(str, "%s+%lld(FP)", a->sym->name, a->offset); 174 else 175 sprint(str, "%lld(FP)", a->offset); 176 break; 177 178 case D_CONST: 179 sprint(str, "$%lld", a->offset); 180 break; 181 182 case D_CONST2: 183 if(!(fp->flags & FmtLong)) { 184 // D_CONST2 outside of ATEXT should not happen 185 sprint(str, "!!$%lld-%d", a->offset, a->offset2); 186 } 187 break; 188 189 case D_FCONST: 190 sprint(str, "$(%.17g)", a->u.dval); 191 break; 192 193 case D_SCONST: 194 sprint(str, "$\"%$\"", a->u.sval); 195 break; 196 197 case D_ADDR: 198 a->type = a->index; 199 a->index = D_NONE; 200 sprint(str, "$%D", a); 201 a->index = a->type; 202 a->type = D_ADDR; 203 goto conv; 204 } 205 brk: 206 if(a->index != D_NONE) { 207 sprint(s, "(%R*%d)", (int)a->index, (int)a->scale); 208 strcat(str, s); 209 } 210 conv: 211 return fmtstrcpy(fp, str); 212 } 213 214 static char* regstr[] = 215 { 216 "AL", /* [D_AL] */ 217 "CL", 218 "DL", 219 "BL", 220 "AH", 221 "CH", 222 "DH", 223 "BH", 224 225 "AX", /* [D_AX] */ 226 "CX", 227 "DX", 228 "BX", 229 "SP", 230 "BP", 231 "SI", 232 "DI", 233 234 "F0", /* [D_F0] */ 235 "F1", 236 "F2", 237 "F3", 238 "F4", 239 "F5", 240 "F6", 241 "F7", 242 243 "CS", /* [D_CS] */ 244 "SS", 245 "DS", 246 "ES", 247 "FS", 248 "GS", 249 250 "GDTR", /* [D_GDTR] */ 251 "IDTR", /* [D_IDTR] */ 252 "LDTR", /* [D_LDTR] */ 253 "MSW", /* [D_MSW] */ 254 "TASK", /* [D_TASK] */ 255 256 "CR0", /* [D_CR] */ 257 "CR1", 258 "CR2", 259 "CR3", 260 "CR4", 261 "CR5", 262 "CR6", 263 "CR7", 264 265 "DR0", /* [D_DR] */ 266 "DR1", 267 "DR2", 268 "DR3", 269 "DR4", 270 "DR5", 271 "DR6", 272 "DR7", 273 274 "TR0", /* [D_TR] */ 275 "TR1", 276 "TR2", 277 "TR3", 278 "TR4", 279 "TR5", 280 "TR6", 281 "TR7", 282 283 "X0", /* [D_X0] */ 284 "X1", 285 "X2", 286 "X3", 287 "X4", 288 "X5", 289 "X6", 290 "X7", 291 292 "TLS", /* [D_TLS] */ 293 "NONE", /* [D_NONE] */ 294 }; 295 296 static int 297 Rconv(Fmt *fp) 298 { 299 char str[STRINGSZ]; 300 int r; 301 302 r = va_arg(fp->args, int); 303 if(r >= D_AL && r <= D_NONE) 304 sprint(str, "%s", regstr[r-D_AL]); 305 else 306 sprint(str, "gok(%d)", r); 307 308 return fmtstrcpy(fp, str); 309 } 310 311 static int 312 DSconv(Fmt *fp) 313 { 314 int i, c; 315 char str[STRINGSZ], *p, *a; 316 317 a = va_arg(fp->args, char*); 318 p = str; 319 for(i=0; i<sizeof(double); i++) { 320 c = a[i] & 0xff; 321 if(c >= 'a' && c <= 'z' || 322 c >= 'A' && c <= 'Z' || 323 c >= '0' && c <= '9') { 324 *p++ = c; 325 continue; 326 } 327 *p++ = '\\'; 328 switch(c) { 329 default: 330 if(c < 040 || c >= 0177) 331 break; /* not portable */ 332 p[-1] = c; 333 continue; 334 case 0: 335 *p++ = 'z'; 336 continue; 337 case '\\': 338 case '"': 339 *p++ = c; 340 continue; 341 case '\n': 342 *p++ = 'n'; 343 continue; 344 case '\t': 345 *p++ = 't'; 346 continue; 347 } 348 *p++ = (c>>6) + '0'; 349 *p++ = ((c>>3) & 7) + '0'; 350 *p++ = (c & 7) + '0'; 351 } 352 *p = 0; 353 return fmtstrcpy(fp, str); 354 }