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