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  }