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 };
46 static Addr addr(Biobuf*);
47 static char type2char(int);
48 static void skip(Biobuf*, int);
49
50 int
51 _is5(char *s)
52 {
53 return s[0] == ANAME /* ANAME */
54 && s[1] == D_FILE /* type */
55 && s[2] == 1 /* sym */
56 && s[3] == '<'; /* name of file */
57 }
58
59 int
60 _read5(Biobuf *bp, Prog *p)
61 {
62 int as, n;
63 Addr a;
64
65 as = Bgetc(bp); /* as */
66 if(as < 0)
67 return 0;
68 p->kind = aNone;
69 p->sig = 0;
70 if(as == ANAME || as == ASIGNAME){
71 if(as == ASIGNAME){
72 Bread(bp, &p->sig, 4);
73 p->sig = leswal(p->sig);
74 }
75 p->kind = aName;
76 p->type = type2char(Bgetc(bp)); /* type */
77 p->sym = Bgetc(bp); /* sym */
78 n = 0;
79 for(;;) {
80 as = Bgetc(bp);
81 if(as < 0)
82 return 0;
83 n++;
84 if(as == 0)
85 break;
86 }
87 p->id = malloc(n);
88 if(p->id == 0)
89 return 0;
90 Bseek(bp, -n, 1);
91 if(Bread(bp, p->id, n) != n)
92 return 0;
93 return 1;
94 }
95 if(as == ATEXT)
96 p->kind = aText;
97 else if(as == AGLOBL)
98 p->kind = aData;
99 skip(bp, 6); /* scond(1), reg(1), lineno(4) */
100 a = addr(bp);
101 addr(bp);
102 if(a.type != D_OREG || a.name != D_STATIC && a.name != D_EXTERN)
103 p->kind = aNone;
104 p->sym = a.sym;
105 return 1;
106 }
107
108 static Addr
109 addr(Biobuf *bp)
110 {
111 Addr a;
112 long off;
113
114 a.type = Bgetc(bp); /* a.type */
115 skip(bp,1); /* reg */
116 a.sym = Bgetc(bp); /* sym index */
117 a.name = Bgetc(bp); /* sym type */
118 switch(a.type){
119 default:
120 case D_NONE:
121 case D_REG:
122 case D_FREG:
123 case D_PSR:
124 case D_FPCR:
125 break;
126 case D_REGREG:
127 Bgetc(bp);
128 break;
129 case D_CONST2:
130 Bgetc(bp);
131 Bgetc(bp);
132 Bgetc(bp);
133 Bgetc(bp); // fall through
134 case D_OREG:
135 case D_CONST:
136 case D_BRANCH:
137 case D_SHIFT:
138 off = Bgetc(bp);
139 off |= Bgetc(bp) << 8;
140 off |= Bgetc(bp) << 16;
141 off |= Bgetc(bp) << 24;
142 if(off < 0)
143 off = -off;
144 if(a.sym && (a.name==D_PARAM || a.name==D_AUTO))
145 _offset(a.sym, off);
146 break;
147 case D_SCONST:
148 skip(bp, NSNAME);
149 break;
150 case D_FCONST:
151 skip(bp, 8);
152 break;
153 }
154 return a;
155 }
156
157 static char
158 type2char(int t)
159 {
160 switch(t){
161 case D_EXTERN: return 'U';
162 case D_STATIC: return 'b';
163 case D_AUTO: return 'a';
164 case D_PARAM: return 'p';
165 default: return UNKNOWN;
166 }
167 }
168
169 static void
170 skip(Biobuf *bp, int n)
171 {
172 while (n-- > 0)
173 Bgetc(bp);
174 }