github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/src/liblink/list9.c (about)

     1  // cmd/9l/list.c from Vita Nuova.
     2  //
     3  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     4  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     5  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     6  //	Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
     7  //	Portions Copyright © 2004,2006 Bruce Ellis
     8  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
     9  //	Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
    10  //	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    11  //
    12  // Permission is hereby granted, free of charge, to any person obtaining a copy
    13  // of this software and associated documentation files (the "Software"), to deal
    14  // in the Software without restriction, including without limitation the rights
    15  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    16  // copies of the Software, and to permit persons to whom the Software is
    17  // furnished to do so, subject to the following conditions:
    18  //
    19  // The above copyright notice and this permission notice shall be included in
    20  // all copies or substantial portions of the Software.
    21  //
    22  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    23  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    24  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    25  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    26  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    27  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    28  // THE SOFTWARE.
    29  
    30  #include <u.h>
    31  #include <libc.h>
    32  #include <bio.h>
    33  #include <link.h>
    34  #include "../cmd/9l/9.out.h"
    35  
    36  enum
    37  {
    38  	STRINGSZ	= 1000,
    39  };
    40  
    41  static int	Aconv(Fmt*);
    42  static int	Dconv(Fmt*);
    43  static int	Pconv(Fmt*);
    44  static int	Rconv(Fmt*);
    45  static int	DSconv(Fmt*);
    46  static int	Mconv(Fmt*);
    47  static int	DRconv(Fmt*);
    48  
    49  //
    50  // Format conversions
    51  //	%A int		Opcodes (instruction mnemonics)
    52  //
    53  //	%D Addr*	Addresses (instruction operands)
    54  //		Flags: "%lD": seperate the high and low words of a constant by "-"
    55  //
    56  //	%P Prog*	Instructions
    57  //
    58  //	%R int		Registers
    59  //
    60  //	%$ char*	String constant addresses (for internal use only)
    61  //	%^ int   	C_* classes (for liblink internal use)
    62  
    63  #pragma	varargck	type	"$"	char*
    64  #pragma	varargck	type	"M"	Addr*
    65  
    66  void
    67  listinit9(void)
    68  {
    69  	fmtinstall('A', Aconv);
    70  	fmtinstall('D', Dconv);
    71  	fmtinstall('P', Pconv);
    72  	fmtinstall('R', Rconv);
    73  
    74  	// for liblink internal use
    75  	fmtinstall('^', DRconv);
    76  
    77  	// for internal use
    78  	fmtinstall('$', DSconv);
    79  	fmtinstall('M', Mconv);
    80  }
    81  
    82  static Prog*	bigP;
    83  
    84  static int
    85  Pconv(Fmt *fp)
    86  {
    87  	char str[STRINGSZ], *s;
    88  	Prog *p;
    89  	int a;
    90  
    91  	p = va_arg(fp->args, Prog*);
    92  	bigP = p;
    93  	a = p->as;
    94  
    95  	if(fp->flags & FmtSharp) {
    96  		s = str;
    97  		s += sprint(s, "%.5lld (%L) %A", p->pc, p->lineno, a);
    98  		if(p->from.type != D_NONE)
    99  			s += sprint(s, " from={%#D}", &p->from);
   100  		if(p->reg)
   101  			s += sprint(s, " reg=%d", p->reg);
   102  		if(p->from3.type != D_NONE)
   103  			s += sprint(s, " from3={%#D}", &p->from3);
   104  		if(p->to.type != D_NONE)
   105  			sprint(s, " to={%#D}", &p->to);
   106  		return fmtstrcpy(fp, str);
   107  	}
   108  
   109  	if(a == ADATA || a == AINIT || a == ADYNT)
   110  		sprint(str, "%.5lld (%L)	%A	%D/%d,%D", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
   111  	else if(a == ATEXT) {
   112  		if(p->reg != 0)
   113  			sprint(str, "%.5lld (%L)        %A      %D,%d,%lD", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
   114  		else
   115  			sprint(str, "%.5lld (%L)        %A      %D,%lD", p->pc, p->lineno, a, &p->from, &p->to);
   116  	} else if(a == AGLOBL) {
   117  		if(p->reg != 0)
   118  			sprint(str, "%.5lld (%L)        %A      %D,%d,%D", p->pc, p->lineno, a, &p->from, p->reg, &p->to);
   119  		else
   120  			sprint(str, "%.5lld (%L)        %A      %D,%D", p->pc, p->lineno, a, &p->from, &p->to);
   121  	} else {
   122  		s = str;
   123  		if(p->mark & NOSCHED)
   124  			s += sprint(s, "*");
   125  		if(p->reg == NREG && p->from3.type == D_NONE)
   126  			sprint(s, "%.5lld (%L)	%A	%D,%D", p->pc, p->lineno, a, &p->from, &p->to);
   127  		else
   128  		if(a != ATEXT && p->from.type == D_OREG) {
   129  			sprint(s, "%.5lld (%L)	%A	%lld(R%d+R%d),%D", p->pc, p->lineno, a,
   130  				p->from.offset, p->from.reg, p->reg, &p->to);
   131  		} else
   132  		if(p->to.type == D_OREG) {
   133  			sprint(s, "%.5lld (%L)	%A	%D,%lld(R%d+R%d)", p->pc, p->lineno, a,
   134  					&p->from, p->to.offset, p->to.reg, p->reg);
   135  		} else {
   136  			s += sprint(s, "%.5lld (%L)	%A	%D", p->pc, p->lineno, a, &p->from);
   137  			if(p->reg != NREG)
   138  				s += sprint(s, ",%c%d", p->from.type==D_FREG?'F':'R', p->reg);
   139  			if(p->from3.type != D_NONE)
   140  				s += sprint(s, ",%D", &p->from3);
   141  			sprint(s, ",%D", &p->to);
   142  		}
   143  		if(p->spadj != 0)
   144  			return fmtprint(fp, "%s # spadj=%d", str, p->spadj);
   145  	}
   146  	return fmtstrcpy(fp, str);
   147  }
   148  
   149  static int
   150  Aconv(Fmt *fp)
   151  {
   152  	char *s;
   153  	int a;
   154  
   155  	a = va_arg(fp->args, int);
   156  	s = "???";
   157  	if(a >= AXXX && a < ALAST)
   158  		s = anames9[a];
   159  	return fmtstrcpy(fp, s);
   160  }
   161  
   162  static int
   163  Dconv(Fmt *fp)
   164  {
   165  	char str[STRINGSZ];
   166  	Addr *a;
   167  	int32 v;
   168  
   169  	a = va_arg(fp->args, Addr*);
   170  
   171  	if(fp->flags & FmtSharp) {
   172  		char *s = str;
   173  		if(a->type == D_NONE) {
   174  			sprint(s, "type=NONE");
   175  			goto ret;
   176  		}
   177  		if(a->type >= 0 && a->type < D_LAST && dnames9[a->type] != nil)
   178  			s += sprint(s, "type=%s ", dnames9[a->type]);
   179  		else
   180  			s += sprint(s, "type=%d ", a->type);
   181  		if(a->name >= 0 && a->name < D_LAST && dnames9[(int)a->name] != nil)
   182  			s += sprint(s, "name=%s ", dnames9[(int)a->name]);
   183  		else
   184  			s += sprint(s, "name=%d ", a->name);
   185  		s += sprint(s, "offset=%lld etype=%E width=%lld", a->offset, a->etype, a->width);
   186  		if(a->class != 0)
   187  			s += sprint(s, " class=%s", cnames9[(int)a->class]);
   188  		if(a->reg != NREG)
   189  			s += sprint(s, " reg=%d", a->reg);
   190  		if(a->sym != nil)
   191  			s += sprint(s, " sym=%s", a->sym->name);
   192  		if(a->type == D_BRANCH && a->u.branch != nil)
   193  			sprint(s, " branch=%.5lld", a->u.branch->pc);
   194  		goto ret;
   195  	}
   196  
   197  	if(fp->flags & FmtLong) {
   198  		if(a->type == D_CONST)
   199  			sprint(str, "$%d-%d", (int32)a->offset, (int32)(a->offset>>32));
   200  		else {
   201  			// ATEXT dst is not constant
   202  			sprint(str, "!!%D", a);
   203  		}
   204  		goto ret;
   205  	}
   206  
   207  	switch(a->type) {
   208  	default:
   209  		sprint(str, "GOK-type(%d)", a->type);
   210  		break;
   211  
   212  	case D_NONE:
   213  		str[0] = 0;
   214  		if(a->name != D_NONE || a->reg != NREG || a->sym != nil)
   215  			sprint(str, "%M(R%d)(NONE)", a, a->reg);
   216  		break;
   217  
   218  	case D_CONST:
   219  	case D_DCONST:
   220  		if(a->reg != NREG)
   221  			sprint(str, "$%M(R%d)", a, a->reg);
   222  		else
   223  			sprint(str, "$%M", a);
   224  		break;
   225  
   226  	case D_OREG:
   227  		if(a->reg != NREG)
   228  			sprint(str, "%M(R%d)", a, a->reg);
   229  		else
   230  			sprint(str, "%M", a);
   231  		break;
   232  
   233  	case D_REG:
   234  		sprint(str, "R%d", a->reg);
   235  		if(a->name != D_NONE || a->sym != nil)
   236  			sprint(str, "%M(R%d)(REG)", a, a->reg);
   237  		break;
   238  
   239  	case D_FREG:
   240  		sprint(str, "F%d", a->reg);
   241  		if(a->name != D_NONE || a->sym != nil)
   242  			sprint(str, "%M(F%d)(REG)", a, a->reg);
   243  		break;
   244  
   245  	case D_CREG:
   246  		if(a->reg == NREG)
   247  			strcpy(str, "CR");
   248  		else
   249  			sprint(str, "CR%d", a->reg);
   250  		if(a->name != D_NONE || a->sym != nil)
   251  			sprint(str, "%M(C%d)(REG)", a, a->reg);
   252  		break;
   253  
   254  	case D_SPR:
   255  		if(a->name == D_NONE && a->sym == nil) {
   256  			switch((ulong)a->offset) {
   257  			case D_XER: sprint(str, "XER"); break;
   258  			case D_LR: sprint(str, "LR"); break;
   259  			case D_CTR: sprint(str, "CTR"); break;
   260  			default: sprint(str, "SPR(%lld)", a->offset); break;
   261  			}
   262  			break;
   263  		}
   264  		sprint(str, "SPR-GOK(%d)", a->reg);
   265  		if(a->name != D_NONE || a->sym != nil)
   266  			sprint(str, "%M(SPR-GOK%d)(REG)", a, a->reg);
   267  		break;
   268  
   269  	case D_DCR:
   270  		if(a->name == D_NONE && a->sym == nil) {
   271  			sprint(str, "DCR(%lld)", a->offset);
   272  			break;
   273  		}
   274  		sprint(str, "DCR-GOK(%d)", a->reg);
   275  		if(a->name != D_NONE || a->sym != nil)
   276  			sprint(str, "%M(DCR-GOK%d)(REG)", a, a->reg);
   277  		break;
   278  
   279  	case D_OPT:
   280  		sprint(str, "OPT(%d)", a->reg);
   281  		break;
   282  
   283  	case D_FPSCR:
   284  		if(a->reg == NREG)
   285  			strcpy(str, "FPSCR");
   286  		else
   287  			sprint(str, "FPSCR(%d)", a->reg);
   288  		break;
   289  
   290  	case D_MSR:
   291  		sprint(str, "MSR");
   292  		break;
   293  
   294  	case D_BRANCH:
   295  		if(bigP->pcond != nil) {
   296  			v = bigP->pcond->pc;
   297  			//if(v >= INITTEXT)
   298  			//	v -= INITTEXT-HEADR;
   299  			if(a->sym != nil)
   300  				sprint(str, "%s+%.5ux(BRANCH)", a->sym->name, v);
   301  			else
   302  				sprint(str, "%.5ux(BRANCH)", v);
   303  		} else if(a->u.branch != nil)
   304  			sprint(str, "%lld", a->u.branch->pc);
   305  		else if(a->sym != nil)
   306  			sprint(str, "%s+%lld(APC)", a->sym->name, a->offset);
   307  		else
   308  			sprint(str, "%lld(APC)", a->offset);
   309  		break;
   310  
   311  	case D_FCONST:
   312  		//sprint(str, "$%lux-%lux", a->ieee.h, a->ieee.l);
   313  		sprint(str, "$%.17g", a->u.dval);
   314  		break;
   315  
   316  	case D_SCONST:
   317  		sprint(str, "$\"%$\"", a->u.sval);
   318  		break;
   319  	}
   320  
   321  ret:
   322  	return fmtstrcpy(fp, str);
   323  }
   324  
   325  static int
   326  Mconv(Fmt *fp)
   327  {
   328  	char str[STRINGSZ];
   329  	Addr *a;
   330  	LSym *s;
   331  	int32 l;
   332  
   333  	a = va_arg(fp->args, Addr*);
   334  	s = a->sym;
   335  	//if(s == nil) {
   336  	//	l = a->offset;
   337  	//	if((vlong)l != a->offset)
   338  	//		sprint(str, "0x%llux", a->offset);
   339  	//	else
   340  	//		sprint(str, "%lld", a->offset);
   341  	//	goto out;
   342  	//}
   343  	switch(a->name) {
   344  	default:
   345  		sprint(str, "GOK-name(%d)", a->name);
   346  		break;
   347  
   348  	case D_NONE:
   349  		l = a->offset;
   350  		if((vlong)l != a->offset)
   351  			sprint(str, "0x%llux", a->offset);
   352  		else
   353  			sprint(str, "%lld", a->offset);
   354  		break;
   355  
   356  	case D_EXTERN:
   357  		if(a->offset != 0)
   358  			sprint(str, "%s+%lld(SB)", s->name, a->offset);
   359  		else
   360  			sprint(str, "%s(SB)", s->name);
   361  		break;
   362  
   363  	case D_STATIC:
   364  		sprint(str, "%s<>+%lld(SB)", s->name, a->offset);
   365  		break;
   366  
   367  	case D_AUTO:
   368  		if(s == nil)
   369  			sprint(str, "%lld(SP)", -a->offset);
   370  		else
   371  			sprint(str, "%s-%lld(SP)", s->name, -a->offset);
   372  		break;
   373  
   374  	case D_PARAM:
   375  		if(s == nil)
   376  			sprint(str, "%lld(FP)", a->offset);
   377  		else
   378  			sprint(str, "%s+%lld(FP)", s->name, a->offset);
   379  		break;
   380  	}
   381  //out:
   382  	return fmtstrcpy(fp, str);
   383  }
   384  
   385  static int
   386  Rconv(Fmt *fp)
   387  {
   388  	char str[STRINGSZ];
   389  	int r;
   390  
   391  	r = va_arg(fp->args, int);
   392  	if(r < NREG)
   393  		sprint(str, "r%d", r);
   394  	else
   395  		sprint(str, "f%d", r-NREG);
   396  	return fmtstrcpy(fp, str);
   397  }
   398  
   399  static int
   400  DRconv(Fmt *fp)
   401  {
   402  	char *s;
   403  	int a;
   404  
   405  	a = va_arg(fp->args, int);
   406  	s = "C_??";
   407  	if(a >= C_NONE && a <= C_NCLASS)
   408  		s = cnames9[a];
   409  	return fmtstrcpy(fp, s);
   410  }
   411  
   412  static int
   413  DSconv(Fmt *fp)
   414  {
   415  	int i, c;
   416  	char str[STRINGSZ], *p, *a;
   417  
   418  	a = va_arg(fp->args, char*);
   419  	p = str;
   420  	for(i=0; i<sizeof(int32); i++) {
   421  		c = a[i] & 0xff;
   422  		if(c >= 'a' && c <= 'z' ||
   423  		   c >= 'A' && c <= 'Z' ||
   424  		   c >= '0' && c <= '9' ||
   425  		   c == ' ' || c == '%') {
   426  			*p++ = c;
   427  			continue;
   428  		}
   429  		*p++ = '\\';
   430  		switch(c) {
   431  		case 0:
   432  			*p++ = 'z';
   433  			continue;
   434  		case '\\':
   435  		case '"':
   436  			*p++ = c;
   437  			continue;
   438  		case '\n':
   439  			*p++ = 'n';
   440  			continue;
   441  		case '\t':
   442  			*p++ = 't';
   443  			continue;
   444  		}
   445  		*p++ = (c>>6) + '0';
   446  		*p++ = ((c>>3) & 7) + '0';
   447  		*p++ = (c & 7) + '0';
   448  	}
   449  	*p = 0;
   450  	return fmtstrcpy(fp, str);
   451  }