xref: /inferno-os/utils/libmach/iobj.c (revision 48f27553574bf59de5f101ae072f82f5f1993d6f)
1  /*
2   * iobj.c - identify and parse a riscv object file
3   */
4  #include <lib9.h>
5  #include <bio.h>
6  #include <mach.h>
7  #include "ic/i.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  _isi(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  _readi(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, 5);		/* 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: case D_REG: case D_FREG:
92  		break;
93  	case D_OREG:
94  	case D_CONST:
95  	case D_BRANCH:
96  	case D_CTLREG:
97  		off = Bgetc(bp);
98  		off |= Bgetc(bp) << 8;
99  		off |= Bgetc(bp) << 16;
100  		off |= Bgetc(bp) << 24;
101  		if(off < 0)
102  			off = -off;
103  		if(a.sym && (a.name==D_PARAM || a.name==D_AUTO))
104  			_offset(a.sym, off);
105  		break;
106  	case D_VCONST:
107  	case D_SCONST:
108  		skip(bp, NSNAME);
109  		break;
110  	case D_FCONST:
111  		skip(bp, 8);
112  		break;
113  	}
114  	return a;
115  }
116  
117  static char
118  type2char(int t)
119  {
120  	switch(t){
121  	case D_EXTERN:		return 'U';
122  	case D_STATIC:		return 'b';
123  	case D_AUTO:		return 'a';
124  	case D_PARAM:		return 'p';
125  	default:		return UNKNOWN;
126  	}
127  }
128  
129  static void
130  skip(Biobuf *bp, int n)
131  {
132  	while (n-- > 0)
133  		Bgetc(bp);
134  }
135