github.com/zach-klippenstein/go@v0.0.0-20150108044943-fcfbeb3adf58/src/liblink/list6.c (about)

     1  // Inferno utils/6c/list.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/6c/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/6l/6.out.h"
    36  
    37  //
    38  // Format conversions
    39  //	%A int		Opcodes (instruction mnemonics)
    40  //
    41  //	%D Addr*	Addresses (instruction operands)
    42  //		Flags: "%lD": seperate the high and low words of a constant by "-"
    43  //
    44  //	%P Prog*	Instructions
    45  //
    46  //	%R int		Registers
    47  //
    48  //	%$ char*	String constant addresses (for internal use only)
    49  
    50  static int	Aconv(Fmt *fp);
    51  static int	Dconv(Fmt *fp);
    52  static int	Pconv(Fmt *fp);
    53  static int	Rconv(Fmt *fp);
    54  static int	DSconv(Fmt *fp);
    55  
    56  enum
    57  {
    58  	STRINGSZ = 1000
    59  };
    60  
    61  #pragma	varargck	type	"$"	char*
    62  
    63  void
    64  listinit6(void)
    65  {
    66  	fmtinstall('A', Aconv);
    67  	fmtinstall('D', Dconv);
    68  	fmtinstall('P', Pconv);
    69  	fmtinstall('R', Rconv);
    70  
    71  	// for internal use
    72  	fmtinstall('$', DSconv);
    73  }
    74  
    75  static	Prog*	bigP;
    76  
    77  static int
    78  Pconv(Fmt *fp)
    79  {
    80  	char str[STRINGSZ];
    81  	Prog *p;
    82  
    83  	p = va_arg(fp->args, Prog*);
    84  	bigP = p;
    85  
    86  	if(fp->flags & FmtSharp) {
    87  		char *s = str;
    88  		s += sprint(s, "%.5lld (%L) %A", p->pc, p->lineno, p->as);
    89  		if(p->from.type != D_NONE)
    90  			s += sprint(s, " from={%#D}", &p->from);
    91  		if(p->reg)
    92  			s += sprint(s, " reg=%d", p->reg);
    93  		if(p->to.type != D_NONE)
    94  			sprint(s, " to={%#D}", &p->to);
    95  		return fmtstrcpy(fp, str);
    96  	}
    97  
    98  	switch(p->as) {
    99  	case ADATA:
   100  		sprint(str, "%.5lld (%L)	%A	%D/%d,%D",
   101  			p->pc, p->lineno, p->as, &p->from, p->from.scale, &p->to);
   102  		break;
   103  
   104  	case ATEXT:
   105  		if(p->from.scale) {
   106  			sprint(str, "%.5lld (%L)	%A	%D,%d,%lD",
   107  				p->pc, p->lineno, p->as, &p->from, p->from.scale, &p->to);
   108  			break;
   109  		}
   110  		sprint(str, "%.5lld (%L)	%A	%D,%lD",
   111  			p->pc, p->lineno, p->as, &p->from, &p->to);
   112  		break;
   113  
   114  	default:
   115  		sprint(str, "%.5lld (%L)	%A	%D,%D",
   116  			p->pc, p->lineno, p->as, &p->from, &p->to);
   117  		break;
   118  	}
   119  	bigP = nil;
   120  	return fmtstrcpy(fp, str);
   121  }
   122  
   123  static int
   124  Aconv(Fmt *fp)
   125  {
   126  	int i;
   127  
   128  	i = va_arg(fp->args, int);
   129  	return fmtstrcpy(fp, anames6[i]);
   130  }
   131  
   132  static int
   133  Dconv(Fmt *fp)
   134  {
   135  	char str[STRINGSZ], s[STRINGSZ];
   136  	Addr *a;
   137  	int i;
   138  
   139  	a = va_arg(fp->args, Addr*);
   140  	i = a->type;
   141  
   142  	if(fp->flags & FmtSharp) {
   143  		char *s = str;
   144  		s += sprint(s, "type=");
   145  		if(i == D_NONE) {
   146  			sprint(s, "NONE");
   147  			goto brk;
   148  		}
   149  		if(i >= D_INDIR) {
   150  			i -= D_INDIR;
   151  			s += sprint(s, "INDIR+");
   152  		}
   153  		if(i >= 0 && i < D_LAST && dnames6[i] != nil)
   154  			s += sprint(s, "%s ", dnames6[i]);
   155  		else
   156  			s += sprint(s, "%d ", i);
   157  		s += sprint(s, "offset=%lld etype=%E width=%lld", a->offset, a->etype, a->width);
   158  		if(a->sym != nil)
   159  			s += sprint(s, " sym=%s", a->sym->name);
   160  		if(a->type == D_BRANCH && a->u.branch != nil)
   161  			sprint(s, " branch=%.5lld", a->u.branch->pc);
   162  		goto brk;
   163  	}
   164  
   165  	if(fp->flags & FmtLong) {
   166  		if(i == D_CONST)
   167  			sprint(str, "$%lld-%lld", a->offset&0xffffffffLL, a->offset>>32);
   168  		else {
   169  			// ATEXT dst is not constant
   170  			sprint(str, "!!%D", a);
   171  		}
   172  		goto brk;
   173  	}
   174  
   175  	if(i >= D_INDIR) {
   176  		if(a->offset)
   177  			sprint(str, "%lld(%R)", a->offset, i-D_INDIR);
   178  		else
   179  			sprint(str, "(%R)", i-D_INDIR);
   180  		goto brk;
   181  	}
   182  	switch(i) {
   183  	default:
   184  		if(a->offset)
   185  			sprint(str, "$%lld,%R", a->offset, i);
   186  		else
   187  			sprint(str, "%R", i);
   188  		break;
   189  
   190  	case D_NONE:
   191  		str[0] = 0;
   192  		break;
   193  
   194  	case D_BRANCH:
   195  		if(a->sym != nil)
   196  			sprint(str, "%s(SB)", a->sym->name);
   197  		else if(bigP != nil && bigP->pcond != nil)
   198  			sprint(str, "%lld", bigP->pcond->pc);
   199  		else if(a->u.branch != nil)
   200  			sprint(str, "%lld", a->u.branch->pc);
   201  		else
   202  			sprint(str, "%lld(PC)", a->offset);
   203  		break;
   204  
   205  	case D_EXTERN:
   206  		sprint(str, "%s+%lld(SB)", a->sym->name, a->offset);
   207  		break;
   208  
   209  	case D_STATIC:
   210  		sprint(str, "%s<>+%lld(SB)", a->sym->name, a->offset);
   211  		break;
   212  
   213  	case D_AUTO:
   214  		if(a->sym)
   215  			sprint(str, "%s+%lld(SP)", a->sym->name, a->offset);
   216  		else
   217  			sprint(str, "%lld(SP)", a->offset);
   218  		break;
   219  
   220  	case D_PARAM:
   221  		if(a->sym)
   222  			sprint(str, "%s+%lld(FP)", a->sym->name, a->offset);
   223  		else
   224  			sprint(str, "%lld(FP)", a->offset);
   225  		break;
   226  
   227  	case D_CONST:
   228  		sprint(str, "$%lld", a->offset);
   229  		break;
   230  
   231  	case D_FCONST:
   232  		sprint(str, "$(%.17g)", a->u.dval);
   233  		break;
   234  
   235  	case D_SCONST:
   236  		sprint(str, "$\"%$\"", a->u.sval);
   237  		break;
   238  
   239  	case D_ADDR:
   240  		a->type = a->index;
   241  		a->index = D_NONE;
   242  		sprint(str, "$%D", a);
   243  		a->index = a->type;
   244  		a->type = D_ADDR;
   245  		goto conv;
   246  	}
   247  brk:
   248  	if(a->index != D_NONE) {
   249  		sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
   250  		strcat(str, s);
   251  	}
   252  conv:
   253  	return fmtstrcpy(fp, str);
   254  }
   255  
   256  static char*	regstr[] =
   257  {
   258  	"AL",	/* [D_AL] */
   259  	"CL",
   260  	"DL",
   261  	"BL",
   262  	"SPB",
   263  	"BPB",
   264  	"SIB",
   265  	"DIB",
   266  	"R8B",
   267  	"R9B",
   268  	"R10B",
   269  	"R11B",
   270  	"R12B",
   271  	"R13B",
   272  	"R14B",
   273  	"R15B",
   274  
   275  	"AX",	/* [D_AX] */
   276  	"CX",
   277  	"DX",
   278  	"BX",
   279  	"SP",
   280  	"BP",
   281  	"SI",
   282  	"DI",
   283  	"R8",
   284  	"R9",
   285  	"R10",
   286  	"R11",
   287  	"R12",
   288  	"R13",
   289  	"R14",
   290  	"R15",
   291  
   292  	"AH",
   293  	"CH",
   294  	"DH",
   295  	"BH",
   296  
   297  	"F0",	/* [D_F0] */
   298  	"F1",
   299  	"F2",
   300  	"F3",
   301  	"F4",
   302  	"F5",
   303  	"F6",
   304  	"F7",
   305  
   306  	"M0",
   307  	"M1",
   308  	"M2",
   309  	"M3",
   310  	"M4",
   311  	"M5",
   312  	"M6",
   313  	"M7",
   314  
   315  	"X0",
   316  	"X1",
   317  	"X2",
   318  	"X3",
   319  	"X4",
   320  	"X5",
   321  	"X6",
   322  	"X7",
   323  	"X8",
   324  	"X9",
   325  	"X10",
   326  	"X11",
   327  	"X12",
   328  	"X13",
   329  	"X14",
   330  	"X15",
   331  
   332  	"CS",	/* [D_CS] */
   333  	"SS",
   334  	"DS",
   335  	"ES",
   336  	"FS",
   337  	"GS",
   338  
   339  	"GDTR",	/* [D_GDTR] */
   340  	"IDTR",	/* [D_IDTR] */
   341  	"LDTR",	/* [D_LDTR] */
   342  	"MSW",	/* [D_MSW] */
   343  	"TASK",	/* [D_TASK] */
   344  
   345  	"CR0",	/* [D_CR] */
   346  	"CR1",
   347  	"CR2",
   348  	"CR3",
   349  	"CR4",
   350  	"CR5",
   351  	"CR6",
   352  	"CR7",
   353  	"CR8",
   354  	"CR9",
   355  	"CR10",
   356  	"CR11",
   357  	"CR12",
   358  	"CR13",
   359  	"CR14",
   360  	"CR15",
   361  
   362  	"DR0",	/* [D_DR] */
   363  	"DR1",
   364  	"DR2",
   365  	"DR3",
   366  	"DR4",
   367  	"DR5",
   368  	"DR6",
   369  	"DR7",
   370  
   371  	"TR0",	/* [D_TR] */
   372  	"TR1",
   373  	"TR2",
   374  	"TR3",
   375  	"TR4",
   376  	"TR5",
   377  	"TR6",
   378  	"TR7",
   379  
   380  	"TLS",	/* [D_TLS] */
   381  	"NONE",	/* [D_NONE] */
   382  };
   383  
   384  static int
   385  Rconv(Fmt *fp)
   386  {
   387  	char str[STRINGSZ];
   388  	int r;
   389  
   390  	r = va_arg(fp->args, int);
   391  	if(r >= D_AL && r <= D_NONE)
   392  		sprint(str, "%s", regstr[r-D_AL]);
   393  	else
   394  		sprint(str, "gok(%d)", r);
   395  
   396  	return fmtstrcpy(fp, str);
   397  }
   398  
   399  static int
   400  DSconv(Fmt *fp)
   401  {
   402  	int i, c;
   403  	char str[STRINGSZ], *p, *a;
   404  
   405  	a = va_arg(fp->args, char*);
   406  	p = str;
   407  	for(i=0; i<sizeof(double); i++) {
   408  		c = a[i] & 0xff;
   409  		if(c >= 'a' && c <= 'z' ||
   410  		   c >= 'A' && c <= 'Z' ||
   411  		   c >= '0' && c <= '9') {
   412  			*p++ = c;
   413  			continue;
   414  		}
   415  		*p++ = '\\';
   416  		switch(c) {
   417  		default:
   418  			if(c < 040 || c >= 0177)
   419  				break;	/* not portable */
   420  			p[-1] = c;
   421  			continue;
   422  		case 0:
   423  			*p++ = 'z';
   424  			continue;
   425  		case '\\':
   426  		case '"':
   427  			*p++ = c;
   428  			continue;
   429  		case '\n':
   430  			*p++ = 'n';
   431  			continue;
   432  		case '\t':
   433  			*p++ = 't';
   434  			continue;
   435  		}
   436  		*p++ = (c>>6) + '0';
   437  		*p++ = ((c>>3) & 7) + '0';
   438  		*p++ = (c & 7) + '0';
   439  	}
   440  	*p = 0;
   441  	return fmtstrcpy(fp, str);
   442  }