Blame


1 a84cbb2a 2004-04-19 devnull /*
2 a84cbb2a 2004-04-19 devnull * Dwarf call frame unwinding.
3 a84cbb2a 2004-04-19 devnull *
4 a84cbb2a 2004-04-19 devnull * The call frame unwinding values are encoded using a state machine
5 a84cbb2a 2004-04-19 devnull * like the pc<->line mapping, but it's a different machine.
6 a84cbb2a 2004-04-19 devnull * The expressions to generate the old values are similar in function to the
7 a84cbb2a 2004-04-19 devnull * ``dwarf expressions'' used for locations in the code, but of course not
8 a84cbb2a 2004-04-19 devnull * the same encoding.
9 a84cbb2a 2004-04-19 devnull */
10 a84cbb2a 2004-04-19 devnull #include <u.h>
11 a84cbb2a 2004-04-19 devnull #include <libc.h>
12 a84cbb2a 2004-04-19 devnull #include <bio.h>
13 a84cbb2a 2004-04-19 devnull #include "elf.h"
14 a84cbb2a 2004-04-19 devnull #include "dwarf.h"
15 a84cbb2a 2004-04-19 devnull
16 a84cbb2a 2004-04-19 devnull #define trace 0
17 a84cbb2a 2004-04-19 devnull
18 a84cbb2a 2004-04-19 devnull typedef struct State State;
19 a84cbb2a 2004-04-19 devnull struct State
20 a84cbb2a 2004-04-19 devnull {
21 a84cbb2a 2004-04-19 devnull ulong loc;
22 a84cbb2a 2004-04-19 devnull ulong endloc;
23 a84cbb2a 2004-04-19 devnull ulong iquantum;
24 a84cbb2a 2004-04-19 devnull ulong dquantum;
25 a84cbb2a 2004-04-19 devnull char *augmentation;
26 a84cbb2a 2004-04-19 devnull int version;
27 a84cbb2a 2004-04-19 devnull ulong rareg;
28 a84cbb2a 2004-04-19 devnull DwarfBuf init;
29 a84cbb2a 2004-04-19 devnull DwarfExpr *cfa;
30 a84cbb2a 2004-04-19 devnull DwarfExpr *ra;
31 a84cbb2a 2004-04-19 devnull DwarfExpr *r;
32 a84cbb2a 2004-04-19 devnull DwarfExpr *initr;
33 a84cbb2a 2004-04-19 devnull int nr;
34 a84cbb2a 2004-04-19 devnull DwarfExpr **stack;
35 a84cbb2a 2004-04-19 devnull int nstack;
36 a84cbb2a 2004-04-19 devnull };
37 a84cbb2a 2004-04-19 devnull
38 a84cbb2a 2004-04-19 devnull static int findfde(Dwarf*, ulong, State*, DwarfBuf*);
39 a84cbb2a 2004-04-19 devnull static int dexec(DwarfBuf*, State*, int);
40 a84cbb2a 2004-04-19 devnull
41 a84cbb2a 2004-04-19 devnull int
42 a84cbb2a 2004-04-19 devnull dwarfunwind(Dwarf *d, ulong pc, DwarfExpr *cfa, DwarfExpr *ra, DwarfExpr *r, int nr)
43 a84cbb2a 2004-04-19 devnull {
44 a84cbb2a 2004-04-19 devnull int i, ret;
45 a84cbb2a 2004-04-19 devnull DwarfBuf fde, b;
46 a84cbb2a 2004-04-19 devnull DwarfExpr *initr;
47 a84cbb2a 2004-04-19 devnull State s;
48 a84cbb2a 2004-04-19 devnull
49 a84cbb2a 2004-04-19 devnull initr = mallocz(nr*sizeof(initr[0]), 1);
50 a84cbb2a 2004-04-19 devnull if(initr == 0)
51 a84cbb2a 2004-04-19 devnull return -1;
52 a84cbb2a 2004-04-19 devnull
53 a84cbb2a 2004-04-19 devnull memset(&s, 0, sizeof s);
54 a84cbb2a 2004-04-19 devnull s.loc = 0;
55 a84cbb2a 2004-04-19 devnull s.cfa = cfa;
56 a84cbb2a 2004-04-19 devnull s.ra = ra;
57 a84cbb2a 2004-04-19 devnull s.r = r;
58 a84cbb2a 2004-04-19 devnull s.nr = nr;
59 a84cbb2a 2004-04-19 devnull
60 a84cbb2a 2004-04-19 devnull if(findfde(d, pc, &s, &fde) < 0){
61 a84cbb2a 2004-04-19 devnull free(initr);
62 a84cbb2a 2004-04-19 devnull return -1;
63 a84cbb2a 2004-04-19 devnull }
64 a84cbb2a 2004-04-19 devnull
65 a84cbb2a 2004-04-19 devnull memset(r, 0, nr*sizeof(r[0]));
66 a84cbb2a 2004-04-19 devnull for(i=0; i<nr; i++)
67 a84cbb2a 2004-04-19 devnull r[i].type = RuleSame;
68 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "s.init %p-%p, fde %p-%p\n", s.init.p, s.init.ep, fde.p, fde.ep);
69 a84cbb2a 2004-04-19 devnull b = s.init;
70 a84cbb2a 2004-04-19 devnull if(dexec(&b, &s, 0) < 0)
71 a84cbb2a 2004-04-19 devnull goto err;
72 a84cbb2a 2004-04-19 devnull
73 a84cbb2a 2004-04-19 devnull s.initr = initr;
74 a84cbb2a 2004-04-19 devnull memmove(initr, r, nr*sizeof(initr[0]));
75 a84cbb2a 2004-04-19 devnull
76 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "s.loc 0x%lux pc 0x%lux\n", s.loc, pc);
77 a84cbb2a 2004-04-19 devnull while(s.loc < pc){
78 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "s.loc 0x%lux pc 0x%lux\n", s.loc, pc);
79 a84cbb2a 2004-04-19 devnull if(dexec(&fde, &s, 1) < 0)
80 a84cbb2a 2004-04-19 devnull goto err;
81 a84cbb2a 2004-04-19 devnull }
82 a84cbb2a 2004-04-19 devnull *ra = s.r[s.rareg];
83 a84cbb2a 2004-04-19 devnull
84 a84cbb2a 2004-04-19 devnull ret = 0;
85 a84cbb2a 2004-04-19 devnull goto out;
86 a84cbb2a 2004-04-19 devnull
87 a84cbb2a 2004-04-19 devnull err:
88 a84cbb2a 2004-04-19 devnull ret = -1;
89 a84cbb2a 2004-04-19 devnull out:
90 a84cbb2a 2004-04-19 devnull free(initr);
91 a84cbb2a 2004-04-19 devnull for(i=0; i<s.nstack; i++)
92 a84cbb2a 2004-04-19 devnull free(s.stack[i]);
93 a84cbb2a 2004-04-19 devnull free(s.stack);
94 a84cbb2a 2004-04-19 devnull return ret;
95 a84cbb2a 2004-04-19 devnull }
96 a84cbb2a 2004-04-19 devnull
97 a84cbb2a 2004-04-19 devnull /*
98 a84cbb2a 2004-04-19 devnull * XXX This turns out to be much more expensive than the actual
99 a84cbb2a 2004-04-19 devnull * running of the machine in dexec. It probably makes sense to
100 a84cbb2a 2004-04-19 devnull * cache the last 10 or so fde's we've found, since stack traces
101 a84cbb2a 2004-04-19 devnull * will keep asking for the same info over and over.
102 a84cbb2a 2004-04-19 devnull */
103 a84cbb2a 2004-04-19 devnull static int
104 a84cbb2a 2004-04-19 devnull findfde(Dwarf *d, ulong pc, State *s, DwarfBuf *fde)
105 a84cbb2a 2004-04-19 devnull {
106 a84cbb2a 2004-04-19 devnull static int nbad;
107 a84cbb2a 2004-04-19 devnull char *aug;
108 a84cbb2a 2004-04-19 devnull uchar *next;
109 a84cbb2a 2004-04-19 devnull int i, vers;
110 a84cbb2a 2004-04-19 devnull ulong len, id, base, size;
111 a84cbb2a 2004-04-19 devnull DwarfBuf b;
112 a84cbb2a 2004-04-19 devnull
113 a84cbb2a 2004-04-19 devnull b.d = d;
114 a84cbb2a 2004-04-19 devnull b.p = d->frame.data;
115 a84cbb2a 2004-04-19 devnull b.ep = b.p + d->frame.len;
116 a84cbb2a 2004-04-19 devnull b.addrsize = d->addrsize;
117 a84cbb2a 2004-04-19 devnull if(b.addrsize == 0)
118 a84cbb2a 2004-04-19 devnull b.addrsize = 4; /* where should i find this? */
119 a84cbb2a 2004-04-19 devnull
120 a84cbb2a 2004-04-19 devnull for(; b.p < b.ep; b.p = next){
121 a84cbb2a 2004-04-19 devnull if((i = (b.p - d->frame.data) % b.addrsize))
122 a84cbb2a 2004-04-19 devnull b.p += b.addrsize - i;
123 a84cbb2a 2004-04-19 devnull len = dwarfget4(&b);
124 a84cbb2a 2004-04-19 devnull if(len > b.ep-b.p){
125 a84cbb2a 2004-04-19 devnull werrstr("bad length in cie/fde header");
126 a84cbb2a 2004-04-19 devnull return -1;
127 a84cbb2a 2004-04-19 devnull }
128 a84cbb2a 2004-04-19 devnull next = b.p+len;
129 a84cbb2a 2004-04-19 devnull id = dwarfget4(&b);
130 a84cbb2a 2004-04-19 devnull if(id == 0xFFFFFFFF){ /* CIE */
131 a84cbb2a 2004-04-19 devnull vers = dwarfget1(&b);
132 a84cbb2a 2004-04-19 devnull if(vers != 1 && vers != 2 && vers != 3){
133 a84cbb2a 2004-04-19 devnull if(++nbad == 1)
134 a84cbb2a 2004-04-19 devnull fprint(2, "unknown cie version %d (wanted 1-3)\n", vers);
135 a84cbb2a 2004-04-19 devnull continue;
136 a84cbb2a 2004-04-19 devnull }
137 a84cbb2a 2004-04-19 devnull aug = dwarfgetstring(&b);
138 a84cbb2a 2004-04-19 devnull if(aug && *aug){
139 a84cbb2a 2004-04-19 devnull if(++nbad == 1)
140 a84cbb2a 2004-04-19 devnull fprint(2, "unknown augmentation: %s\n", aug);
141 a84cbb2a 2004-04-19 devnull continue;
142 a84cbb2a 2004-04-19 devnull }
143 a84cbb2a 2004-04-19 devnull s->iquantum = dwarfget128(&b);
144 a84cbb2a 2004-04-19 devnull s->dquantum = dwarfget128s(&b);
145 a84cbb2a 2004-04-19 devnull s->rareg = dwarfget128(&b);
146 a84cbb2a 2004-04-19 devnull if(s->rareg > s->nr){
147 a84cbb2a 2004-04-19 devnull werrstr("return address is register %d but only have %d registers",
148 a84cbb2a 2004-04-19 devnull s->rareg, s->nr);
149 a84cbb2a 2004-04-19 devnull return -1;
150 a84cbb2a 2004-04-19 devnull }
151 a84cbb2a 2004-04-19 devnull s->init.p = b.p;
152 a84cbb2a 2004-04-19 devnull s->init.ep = next;
153 a84cbb2a 2004-04-19 devnull }else{ /* FDE */
154 a84cbb2a 2004-04-19 devnull base = dwarfgetaddr(&b);
155 a84cbb2a 2004-04-19 devnull size = dwarfgetaddr(&b);
156 a84cbb2a 2004-04-19 devnull fde->p = b.p;
157 a84cbb2a 2004-04-19 devnull fde->ep = next;
158 a84cbb2a 2004-04-19 devnull s->loc = base;
159 a84cbb2a 2004-04-19 devnull s->endloc = base+size;
160 a84cbb2a 2004-04-19 devnull if(base <= pc && pc < base+size)
161 a84cbb2a 2004-04-19 devnull return 0;
162 a84cbb2a 2004-04-19 devnull }
163 a84cbb2a 2004-04-19 devnull }
164 a84cbb2a 2004-04-19 devnull werrstr("cannot find call frame information for pc 0x%lux", pc);
165 a84cbb2a 2004-04-19 devnull return -1;
166 a84cbb2a 2004-04-19 devnull
167 a84cbb2a 2004-04-19 devnull }
168 a84cbb2a 2004-04-19 devnull
169 a84cbb2a 2004-04-19 devnull static int
170 a84cbb2a 2004-04-19 devnull checkreg(State *s, long r)
171 a84cbb2a 2004-04-19 devnull {
172 a84cbb2a 2004-04-19 devnull if(r < 0 || r >= s->nr){
173 a84cbb2a 2004-04-19 devnull werrstr("bad register number 0x%lux", r);
174 a84cbb2a 2004-04-19 devnull return -1;
175 a84cbb2a 2004-04-19 devnull }
176 a84cbb2a 2004-04-19 devnull return 0;
177 a84cbb2a 2004-04-19 devnull }
178 a84cbb2a 2004-04-19 devnull
179 a84cbb2a 2004-04-19 devnull static int
180 a84cbb2a 2004-04-19 devnull dexec(DwarfBuf *b, State *s, int locstop)
181 a84cbb2a 2004-04-19 devnull {
182 a84cbb2a 2004-04-19 devnull int c;
183 a84cbb2a 2004-04-19 devnull long arg1, arg2;
184 a84cbb2a 2004-04-19 devnull DwarfExpr *e, **p;
185 a84cbb2a 2004-04-19 devnull
186 a84cbb2a 2004-04-19 devnull for(;;){
187 a84cbb2a 2004-04-19 devnull if(b->p == b->ep){
188 a84cbb2a 2004-04-19 devnull if(s->initr)
189 a84cbb2a 2004-04-19 devnull s->loc = s->endloc;
190 a84cbb2a 2004-04-19 devnull return 0;
191 a84cbb2a 2004-04-19 devnull }
192 a84cbb2a 2004-04-19 devnull c = dwarfget1(b);
193 a84cbb2a 2004-04-19 devnull if(b->p == nil){
194 a84cbb2a 2004-04-19 devnull werrstr("ran out of instructions during cfa program");
195 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "%r\n");
196 a84cbb2a 2004-04-19 devnull return -1;
197 a84cbb2a 2004-04-19 devnull }
198 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "+ loc=0x%lux op 0x%ux ", s->loc, c);
199 a84cbb2a 2004-04-19 devnull switch(c>>6){
200 a84cbb2a 2004-04-19 devnull case 1: /* advance location */
201 a84cbb2a 2004-04-19 devnull arg1 = c&0x3F;
202 a84cbb2a 2004-04-19 devnull advance:
203 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "loc += %ld\n", arg1*s->iquantum);
204 a84cbb2a 2004-04-19 devnull s->loc += arg1 * s->iquantum;
205 a84cbb2a 2004-04-19 devnull if(locstop)
206 a84cbb2a 2004-04-19 devnull return 0;
207 a84cbb2a 2004-04-19 devnull continue;
208 a84cbb2a 2004-04-19 devnull
209 a84cbb2a 2004-04-19 devnull case 2: /* offset rule */
210 a84cbb2a 2004-04-19 devnull arg1 = c&0x3F;
211 a84cbb2a 2004-04-19 devnull arg2 = dwarfget128(b);
212 a84cbb2a 2004-04-19 devnull offset:
213 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "r%ld += %ld\n", arg1, arg2*s->dquantum);
214 a84cbb2a 2004-04-19 devnull if(checkreg(s, arg1) < 0)
215 a84cbb2a 2004-04-19 devnull return -1;
216 a84cbb2a 2004-04-19 devnull s->r[arg1].type = RuleCfaOffset;
217 a84cbb2a 2004-04-19 devnull s->r[arg1].offset = arg2 * s->dquantum;
218 a84cbb2a 2004-04-19 devnull continue;
219 a84cbb2a 2004-04-19 devnull
220 a84cbb2a 2004-04-19 devnull case 3: /* restore initial setting */
221 a84cbb2a 2004-04-19 devnull arg1 = c&0x3F;
222 a84cbb2a 2004-04-19 devnull restore:
223 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "r%ld = init\n", arg1);
224 a84cbb2a 2004-04-19 devnull if(checkreg(s, arg1) < 0)
225 a84cbb2a 2004-04-19 devnull return -1;
226 a84cbb2a 2004-04-19 devnull s->r[arg1] = s->initr[arg1];
227 a84cbb2a 2004-04-19 devnull continue;
228 a84cbb2a 2004-04-19 devnull }
229 a84cbb2a 2004-04-19 devnull
230 a84cbb2a 2004-04-19 devnull switch(c){
231 a84cbb2a 2004-04-19 devnull case 0: /* nop */
232 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "nop\n");
233 a84cbb2a 2004-04-19 devnull continue;
234 a84cbb2a 2004-04-19 devnull
235 a84cbb2a 2004-04-19 devnull case 0x01: /* set location */
236 a84cbb2a 2004-04-19 devnull s->loc = dwarfgetaddr(b);
237 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "loc = 0x%lux\n", s->loc);
238 a84cbb2a 2004-04-19 devnull if(locstop)
239 a84cbb2a 2004-04-19 devnull return 0;
240 a84cbb2a 2004-04-19 devnull continue;
241 a84cbb2a 2004-04-19 devnull
242 a84cbb2a 2004-04-19 devnull case 0x02: /* advance loc1 */
243 a84cbb2a 2004-04-19 devnull arg1 = dwarfget1(b);
244 a84cbb2a 2004-04-19 devnull goto advance;
245 a84cbb2a 2004-04-19 devnull
246 a84cbb2a 2004-04-19 devnull case 0x03: /* advance loc2 */
247 a84cbb2a 2004-04-19 devnull arg1 = dwarfget2(b);
248 a84cbb2a 2004-04-19 devnull goto advance;
249 a84cbb2a 2004-04-19 devnull
250 a84cbb2a 2004-04-19 devnull case 0x04: /* advance loc4 */
251 a84cbb2a 2004-04-19 devnull arg1 = dwarfget4(b);
252 a84cbb2a 2004-04-19 devnull goto advance;
253 a84cbb2a 2004-04-19 devnull
254 a84cbb2a 2004-04-19 devnull case 0x05: /* offset extended */
255 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
256 a84cbb2a 2004-04-19 devnull arg2 = dwarfget128(b);
257 a84cbb2a 2004-04-19 devnull goto offset;
258 a84cbb2a 2004-04-19 devnull
259 a84cbb2a 2004-04-19 devnull case 0x06: /* restore extended */
260 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
261 a84cbb2a 2004-04-19 devnull goto restore;
262 a84cbb2a 2004-04-19 devnull
263 a84cbb2a 2004-04-19 devnull case 0x07: /* undefined */
264 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
265 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "r%ld = undef\n", arg1);
266 a84cbb2a 2004-04-19 devnull if(checkreg(s, arg1) < 0)
267 a84cbb2a 2004-04-19 devnull return -1;
268 a84cbb2a 2004-04-19 devnull s->r[arg1].type = RuleUndef;
269 a84cbb2a 2004-04-19 devnull continue;
270 a84cbb2a 2004-04-19 devnull
271 a84cbb2a 2004-04-19 devnull case 0x08: /* same value */
272 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
273 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "r%ld = same\n", arg1);
274 a84cbb2a 2004-04-19 devnull if(checkreg(s, arg1) < 0)
275 a84cbb2a 2004-04-19 devnull return -1;
276 a84cbb2a 2004-04-19 devnull s->r[arg1].type = RuleSame;
277 a84cbb2a 2004-04-19 devnull continue;
278 a84cbb2a 2004-04-19 devnull
279 a84cbb2a 2004-04-19 devnull case 0x09: /* register */
280 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
281 a84cbb2a 2004-04-19 devnull arg2 = dwarfget128(b);
282 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "r%ld = r%ld\n", arg1, arg2);
283 a84cbb2a 2004-04-19 devnull if(checkreg(s, arg1) < 0 || checkreg(s, arg2) < 0)
284 a84cbb2a 2004-04-19 devnull return -1;
285 a84cbb2a 2004-04-19 devnull s->r[arg1].type = RuleRegister;
286 a84cbb2a 2004-04-19 devnull s->r[arg1].reg = arg2;
287 a84cbb2a 2004-04-19 devnull continue;
288 a84cbb2a 2004-04-19 devnull
289 a84cbb2a 2004-04-19 devnull case 0x0A: /* remember state */
290 a84cbb2a 2004-04-19 devnull e = malloc(s->nr*sizeof(e[0]));
291 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "push\n");
292 a84cbb2a 2004-04-19 devnull if(e == nil)
293 a84cbb2a 2004-04-19 devnull return -1;
294 a84cbb2a 2004-04-19 devnull p = realloc(s->stack, (s->nstack+1)*sizeof(s->stack[0]));
295 a84cbb2a 2004-04-19 devnull if(p == nil){
296 a84cbb2a 2004-04-19 devnull free(e);
297 a84cbb2a 2004-04-19 devnull return -1;
298 a84cbb2a 2004-04-19 devnull }
299 a84cbb2a 2004-04-19 devnull s->stack[s->nstack++] = e;
300 a84cbb2a 2004-04-19 devnull memmove(e, s->r, s->nr*sizeof(e[0]));
301 a84cbb2a 2004-04-19 devnull continue;
302 a84cbb2a 2004-04-19 devnull
303 a84cbb2a 2004-04-19 devnull case 0x0B: /* restore state */
304 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "pop\n");
305 a84cbb2a 2004-04-19 devnull if(s->nstack == 0){
306 a84cbb2a 2004-04-19 devnull werrstr("restore state underflow");
307 a84cbb2a 2004-04-19 devnull return -1;
308 a84cbb2a 2004-04-19 devnull }
309 a84cbb2a 2004-04-19 devnull e = s->stack[s->nstack-1];
310 a84cbb2a 2004-04-19 devnull memmove(s->r, e, s->nr*sizeof(e[0]));
311 a84cbb2a 2004-04-19 devnull p = realloc(s->stack, (s->nstack-1)*sizeof(s->stack[0]));
312 a84cbb2a 2004-04-19 devnull if(p == nil)
313 a84cbb2a 2004-04-19 devnull return -1;
314 a84cbb2a 2004-04-19 devnull free(e);
315 a84cbb2a 2004-04-19 devnull s->nstack--;
316 a84cbb2a 2004-04-19 devnull continue;
317 a84cbb2a 2004-04-19 devnull
318 a84cbb2a 2004-04-19 devnull case 0x0C: /* def cfa */
319 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
320 a84cbb2a 2004-04-19 devnull arg2 = dwarfget128(b);
321 a84cbb2a 2004-04-19 devnull defcfa:
322 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "cfa %ld(r%ld)\n", arg2, arg1);
323 a84cbb2a 2004-04-19 devnull if(checkreg(s, arg1) < 0)
324 a84cbb2a 2004-04-19 devnull return -1;
325 a84cbb2a 2004-04-19 devnull s->cfa->type = RuleRegOff;
326 a84cbb2a 2004-04-19 devnull s->cfa->reg = arg1;
327 a84cbb2a 2004-04-19 devnull s->cfa->offset = arg2;
328 a84cbb2a 2004-04-19 devnull continue;
329 a84cbb2a 2004-04-19 devnull
330 a84cbb2a 2004-04-19 devnull case 0x0D: /* def cfa register */
331 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
332 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "cfa reg r%ld\n", arg1);
333 a84cbb2a 2004-04-19 devnull if(s->cfa->type != RuleRegOff){
334 a84cbb2a 2004-04-19 devnull werrstr("change CFA register but CFA not in register+offset form");
335 a84cbb2a 2004-04-19 devnull return -1;
336 a84cbb2a 2004-04-19 devnull }
337 a84cbb2a 2004-04-19 devnull if(checkreg(s, arg1) < 0)
338 a84cbb2a 2004-04-19 devnull return -1;
339 a84cbb2a 2004-04-19 devnull s->cfa->reg = arg1;
340 a84cbb2a 2004-04-19 devnull continue;
341 a84cbb2a 2004-04-19 devnull
342 a84cbb2a 2004-04-19 devnull case 0x0E: /* def cfa offset */
343 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
344 a84cbb2a 2004-04-19 devnull cfaoffset:
345 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "cfa off %ld\n", arg1);
346 a84cbb2a 2004-04-19 devnull if(s->cfa->type != RuleRegOff){
347 a84cbb2a 2004-04-19 devnull werrstr("change CFA offset but CFA not in register+offset form");
348 a84cbb2a 2004-04-19 devnull return -1;
349 a84cbb2a 2004-04-19 devnull }
350 a84cbb2a 2004-04-19 devnull s->cfa->offset = arg1;
351 a84cbb2a 2004-04-19 devnull continue;
352 a84cbb2a 2004-04-19 devnull
353 a84cbb2a 2004-04-19 devnull case 0x0F: /* def cfa expression */
354 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "cfa expr\n");
355 a84cbb2a 2004-04-19 devnull s->cfa->type = RuleLocation;
356 a84cbb2a 2004-04-19 devnull s->cfa->loc.len = dwarfget128(b);
357 a84cbb2a 2004-04-19 devnull s->cfa->loc.data = dwarfgetnref(b, s->cfa->loc.len);
358 a84cbb2a 2004-04-19 devnull continue;
359 a84cbb2a 2004-04-19 devnull
360 a84cbb2a 2004-04-19 devnull case 0x10: /* def reg expression */
361 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
362 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "reg expr r%ld\n", arg1);
363 a84cbb2a 2004-04-19 devnull if(checkreg(s, arg1) < 0)
364 a84cbb2a 2004-04-19 devnull return -1;
365 a84cbb2a 2004-04-19 devnull s->r[arg1].type = RuleLocation;
366 a84cbb2a 2004-04-19 devnull s->r[arg1].loc.len = dwarfget128(b);
367 a84cbb2a 2004-04-19 devnull s->r[arg1].loc.data = dwarfgetnref(b, s->r[arg1].loc.len);
368 a84cbb2a 2004-04-19 devnull continue;
369 a84cbb2a 2004-04-19 devnull
370 a84cbb2a 2004-04-19 devnull case 0x11: /* offset extended */
371 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
372 a84cbb2a 2004-04-19 devnull arg2 = dwarfget128s(b);
373 a84cbb2a 2004-04-19 devnull goto offset;
374 a84cbb2a 2004-04-19 devnull
375 a84cbb2a 2004-04-19 devnull case 0x12: /* cfa sf */
376 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
377 a84cbb2a 2004-04-19 devnull arg2 = dwarfget128s(b);
378 a84cbb2a 2004-04-19 devnull goto defcfa;
379 a84cbb2a 2004-04-19 devnull
380 a84cbb2a 2004-04-19 devnull case 0x13: /* cfa offset sf */
381 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128s(b);
382 a84cbb2a 2004-04-19 devnull goto cfaoffset;
383 a84cbb2a 2004-04-19 devnull
384 a84cbb2a 2004-04-19 devnull default: /* unknown */
385 a84cbb2a 2004-04-19 devnull werrstr("unknown opcode 0x%ux in cfa program", c);
386 a84cbb2a 2004-04-19 devnull return -1;
387 a84cbb2a 2004-04-19 devnull }
388 a84cbb2a 2004-04-19 devnull }
389 a84cbb2a 2004-04-19 devnull return -1; /* not reached */
390 a84cbb2a 2004-04-19 devnull }
391 a84cbb2a 2004-04-19 devnull