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  }