github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/libmach/5obj.c (about)

     1  // Inferno libmach/5obj.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/libmach/5obj.c
     3  //
     4  // 	Copyright © 1994-1999 Lucent Technologies Inc.
     5  // 	Power PC support Copyright © 1995-2004 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  // 	Revisions Copyright © 2000-2004 Lucent Technologies Inc. and others.
     9  //	Portions Copyright © 2009 The Go Authors.  All rights reserved.
    10  //
    11  // Permission is hereby granted, free of charge, to any person obtaining a copy
    12  // of this software and associated documentation files (the "Software"), to deal
    13  // in the Software without restriction, including without limitation the rights
    14  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    15  // copies of the Software, and to permit persons to whom the Software is
    16  // furnished to do so, subject to the following conditions:
    17  //
    18  // The above copyright notice and this permission notice shall be included in
    19  // all copies or substantial portions of the Software.
    20  //
    21  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    22  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    23  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    24  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    25  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    26  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    27  // THE SOFTWARE.
    28  
    29  /*
    30   * 5obj.c - identify and parse an arm object file
    31   */
    32  #include <u.h>
    33  #include <libc.h>
    34  #include <bio.h>
    35  #include <mach.h>
    36  #include "../cmd/5l/5.out.h"
    37  #include "obj.h"
    38  
    39  typedef struct Addr	Addr;
    40  struct Addr
    41  {
    42  	char	type;
    43  	char	sym;
    44  	char	name;
    45  	char	gotype;
    46  };
    47  static Addr addr(Biobuf*);
    48  static char type2char(int);
    49  static void skip(Biobuf*, int);
    50  
    51  int
    52  _is5(char *s)
    53  {
    54  	return  s[0] == ANAME				/* ANAME */
    55  		&& s[1] == D_FILE			/* type */
    56  		&& s[2] == 1				/* sym */
    57  		&& s[3] == '<';				/* name of file */
    58  }
    59  
    60  int
    61  _read5(Biobuf *bp, Prog *p)
    62  {
    63  	int as, n;
    64  	Addr a;
    65  
    66  	as = BGETC(bp);			/* as */
    67  	if(as < 0)
    68  		return 0;
    69  	p->kind = aNone;
    70  	p->sig = 0;
    71  	if(as == ANAME || as == ASIGNAME){
    72  		if(as == ASIGNAME){
    73  			Bread(bp, &p->sig, 4);
    74  			p->sig = leswal(p->sig);
    75  		}
    76  		p->kind = aName;
    77  		p->type = type2char(BGETC(bp));		/* type */
    78  		p->sym = BGETC(bp);			/* sym */
    79  		n = 0;
    80  		for(;;) {
    81  			as = BGETC(bp);
    82  			if(as < 0)
    83  				return 0;
    84  			n++;
    85  			if(as == 0)
    86  				break;
    87  		}
    88  		p->id = malloc(n);
    89  		if(p->id == 0)
    90  			return 0;
    91  		Bseek(bp, -n, 1);
    92  		if(Bread(bp, p->id, n) != n)
    93  			return 0;
    94  		return 1;
    95  	}
    96  	if(as == ATEXT)
    97  		p->kind = aText;
    98  	else if(as == AGLOBL)
    99  		p->kind = aData;
   100  	skip(bp, 6);		/* scond(1), reg(1), lineno(4) */
   101  	a = addr(bp);
   102  	addr(bp);
   103  	if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN)
   104  		p->kind = aNone;
   105  	p->sym = a.sym;
   106  	return 1;
   107  }
   108  
   109  static Addr
   110  addr(Biobuf *bp)
   111  {
   112  	Addr a;
   113  	long off;
   114  
   115  	a.type = BGETC(bp);	/* a.type */
   116  	skip(bp,1);		/* reg */
   117  	a.sym = BGETC(bp);	/* sym index */
   118  	a.name = BGETC(bp);	/* sym type */
   119  	a.gotype = BGETC(bp);	/* go type */
   120  	switch(a.type){
   121  	default:
   122  	case D_NONE:
   123  	case D_REG:
   124  	case D_FREG:
   125  	case D_PSR:
   126  	case D_FPCR:
   127  		break;
   128  	case D_REGREG:
   129  	case D_REGREG2:
   130  		BGETC(bp);
   131  		break;
   132  	case D_CONST2:
   133  		BGETLE4(bp);	// fall through
   134  	case D_OREG:
   135  	case D_CONST:
   136  	case D_BRANCH:
   137  	case D_SHIFT:
   138  		off = BGETLE4(bp);
   139  		if(off < 0)
   140  			off = -off;
   141  		if(a.sym && (a.name==D_PARAM || a.name==D_AUTO))
   142  			_offset(a.sym, off);
   143  		break;
   144  	case D_SCONST:
   145  		skip(bp, NSNAME);
   146  		break;
   147  	case D_FCONST:
   148  		skip(bp, 8);
   149  		break;
   150  	}
   151  	return a;
   152  }
   153  
   154  static char
   155  type2char(int t)
   156  {
   157  	switch(t){
   158  	case D_EXTERN:		return 'U';
   159  	case D_STATIC:		return 'b';
   160  	case D_AUTO:		return 'a';
   161  	case D_PARAM:		return 'p';
   162  	default:		return UNKNOWN;
   163  	}
   164  }
   165  
   166  static void
   167  skip(Biobuf *bp, int n)
   168  {
   169  	while (n-- > 0)
   170  		BGETC(bp);
   171  }