xref: /inferno-os/utils/libmach/5obj.c (revision 5d0c4cf3fc288434c41cba52dd998ab1d7375a7b)
1  /*
2   * 5obj.c - identify and parse a arm object file
3   */
4  #include <lib9.h>
5  #include <bio.h>
6  #include "mach.h"
7  #include "5c/5.out.h"
8  #include "obj.h"
9  
10  typedef struct Addr	Addr;
11  struct Addr
12  {
13  	char	type;
14  	char	sym;
15  	char	name;
16  };
17  static Addr addr(Biobuf*);
18  static char type2char(int);
19  static void skip(Biobuf*, int);
20  
21  int
22  _is5(char *s)
23  {
24  	return  s[0] == ANAME				/* ANAME */
25  		&& s[1] == D_FILE			/* type */
26  		&& s[2] == 1				/* sym */
27  		&& s[3] == '<';				/* name of file */
28  }
29  
30  int
31  _read5(Biobuf *bp, Prog *p)
32  {
33  	int as, n;
34  	Addr a;
35  
36  	as = Bgetc(bp);			/* as */
37  	if(as < 0)
38  		return 0;
39  	p->kind = aNone;
40  	p->sig = 0;
41  	if(as == ANAME || as == ASIGNAME){
42  		if(as == ASIGNAME){
43  			Bread(bp, &p->sig, 4);
44  			p->sig = leswal(p->sig);
45  		}
46  		p->kind = aName;
47  		p->type = type2char(Bgetc(bp));		/* type */
48  		p->sym = Bgetc(bp);			/* sym */
49  		n = 0;
50  		for(;;) {
51  			as = Bgetc(bp);
52  			if(as < 0)
53  				return 0;
54  			n++;
55  			if(as == 0)
56  				break;
57  		}
58  		p->id = malloc(n);
59  		if(p->id == 0)
60  			return 0;
61  		Bseek(bp, -n, 1);
62  		if(Bread(bp, p->id, n) != n)
63  			return 0;
64  		return 1;
65  	}
66  	if(as == ATEXT)
67  		p->kind = aText;
68  	else if(as == AGLOBL)
69  		p->kind = aData;
70  	skip(bp, 6);		/* scond(1), reg(1), lineno(4) */
71  	a = addr(bp);
72  	addr(bp);
73  	if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN)
74  		p->kind = aNone;
75  	p->sym = a.sym;
76  	return 1;
77  }
78  
79  static Addr
80  addr(Biobuf *bp)
81  {
82  	Addr a;
83  	long off;
84  
85  	a.type = Bgetc(bp);	/* a.type */
86  	skip(bp,1);		/* reg */
87  	a.sym = Bgetc(bp);	/* sym index */
88  	a.name = Bgetc(bp);	/* sym type */
89  	switch(a.type){
90  	default:
91  	case D_NONE:
92  	case D_REG:
93  	case D_FREG:
94  	case D_PSR:
95  	case D_FPCR:
96  		break;
97  	case D_OREG:
98  	case D_CONST:
99  	case D_BRANCH:
100  	case D_SHIFT:
101  		off = Bgetc(bp);
102  		off |= Bgetc(bp) << 8;
103  		off |= Bgetc(bp) << 16;
104  		off |= Bgetc(bp) << 24;
105  		if(off < 0)
106  			off = -off;
107  		if(a.sym && (a.name==D_PARAM || a.name==D_AUTO))
108  			_offset(a.sym, off);
109  		break;
110  	case D_SCONST:
111  		skip(bp, NSNAME);
112  		break;
113  	case D_FCONST:
114  		skip(bp, 8);
115  		break;
116  	}
117  	return a;
118  }
119  
120  static char
121  type2char(int t)
122  {
123  	switch(t){
124  	case D_EXTERN:		return 'U';
125  	case D_STATIC:		return 'b';
126  	case D_AUTO:		return 'a';
127  	case D_PARAM:		return 'p';
128  	default:		return UNKNOWN;
129  	}
130  }
131  
132  static void
133  skip(Biobuf *bp, int n)
134  {
135  	while (n-- > 0)
136  		Bgetc(bp);
137  }
138