Blame


1 a84cbb2a 2004-04-19 devnull /*
2 a84cbb2a 2004-04-19 devnull * Dwarf call frame unwinding.
3 a84cbb2a 2004-04-19 devnull *
4 fa325e9b 2020-01-10 cross * The call frame unwinding values are encoded using a state machine
5 fa325e9b 2020-01-10 cross * like the pc<->line mapping, but it's a different machine.
6 fa325e9b 2020-01-10 cross * 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 fa325e9b 2020-01-10 cross * 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 fa325e9b 2020-01-10 cross * 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 ebd39545 2004-04-20 devnull if(d->frame.data == nil){
114 ebd39545 2004-04-20 devnull werrstr("no frame debugging information");
115 ebd39545 2004-04-20 devnull return -1;
116 ebd39545 2004-04-20 devnull }
117 a84cbb2a 2004-04-19 devnull b.d = d;
118 a84cbb2a 2004-04-19 devnull b.p = d->frame.data;
119 a84cbb2a 2004-04-19 devnull b.ep = b.p + d->frame.len;
120 a84cbb2a 2004-04-19 devnull b.addrsize = d->addrsize;
121 a84cbb2a 2004-04-19 devnull if(b.addrsize == 0)
122 a84cbb2a 2004-04-19 devnull b.addrsize = 4; /* where should i find this? */
123 a84cbb2a 2004-04-19 devnull
124 a84cbb2a 2004-04-19 devnull for(; b.p < b.ep; b.p = next){
125 a84cbb2a 2004-04-19 devnull if((i = (b.p - d->frame.data) % b.addrsize))
126 a84cbb2a 2004-04-19 devnull b.p += b.addrsize - i;
127 a84cbb2a 2004-04-19 devnull len = dwarfget4(&b);
128 a84cbb2a 2004-04-19 devnull if(len > b.ep-b.p){
129 a84cbb2a 2004-04-19 devnull werrstr("bad length in cie/fde header");
130 a84cbb2a 2004-04-19 devnull return -1;
131 a84cbb2a 2004-04-19 devnull }
132 a84cbb2a 2004-04-19 devnull next = b.p+len;
133 a84cbb2a 2004-04-19 devnull id = dwarfget4(&b);
134 a84cbb2a 2004-04-19 devnull if(id == 0xFFFFFFFF){ /* CIE */
135 a84cbb2a 2004-04-19 devnull vers = dwarfget1(&b);
136 a84cbb2a 2004-04-19 devnull if(vers != 1 && vers != 2 && vers != 3){
137 a84cbb2a 2004-04-19 devnull if(++nbad == 1)
138 a84cbb2a 2004-04-19 devnull fprint(2, "unknown cie version %d (wanted 1-3)\n", vers);
139 a84cbb2a 2004-04-19 devnull continue;
140 a84cbb2a 2004-04-19 devnull }
141 a84cbb2a 2004-04-19 devnull aug = dwarfgetstring(&b);
142 a84cbb2a 2004-04-19 devnull if(aug && *aug){
143 a84cbb2a 2004-04-19 devnull if(++nbad == 1)
144 a84cbb2a 2004-04-19 devnull fprint(2, "unknown augmentation: %s\n", aug);
145 a84cbb2a 2004-04-19 devnull continue;
146 a84cbb2a 2004-04-19 devnull }
147 a84cbb2a 2004-04-19 devnull s->iquantum = dwarfget128(&b);
148 a84cbb2a 2004-04-19 devnull s->dquantum = dwarfget128s(&b);
149 a84cbb2a 2004-04-19 devnull s->rareg = dwarfget128(&b);
150 a84cbb2a 2004-04-19 devnull if(s->rareg > s->nr){
151 a84cbb2a 2004-04-19 devnull werrstr("return address is register %d but only have %d registers",
152 a84cbb2a 2004-04-19 devnull s->rareg, s->nr);
153 a84cbb2a 2004-04-19 devnull return -1;
154 a84cbb2a 2004-04-19 devnull }
155 a84cbb2a 2004-04-19 devnull s->init.p = b.p;
156 a84cbb2a 2004-04-19 devnull s->init.ep = next;
157 a84cbb2a 2004-04-19 devnull }else{ /* FDE */
158 a84cbb2a 2004-04-19 devnull base = dwarfgetaddr(&b);
159 a84cbb2a 2004-04-19 devnull size = dwarfgetaddr(&b);
160 a84cbb2a 2004-04-19 devnull fde->p = b.p;
161 a84cbb2a 2004-04-19 devnull fde->ep = next;
162 a84cbb2a 2004-04-19 devnull s->loc = base;
163 a84cbb2a 2004-04-19 devnull s->endloc = base+size;
164 a84cbb2a 2004-04-19 devnull if(base <= pc && pc < base+size)
165 a84cbb2a 2004-04-19 devnull return 0;
166 a84cbb2a 2004-04-19 devnull }
167 a84cbb2a 2004-04-19 devnull }
168 a84cbb2a 2004-04-19 devnull werrstr("cannot find call frame information for pc 0x%lux", pc);
169 a84cbb2a 2004-04-19 devnull return -1;
170 fa325e9b 2020-01-10 cross
171 a84cbb2a 2004-04-19 devnull }
172 a84cbb2a 2004-04-19 devnull
173 a84cbb2a 2004-04-19 devnull static int
174 a84cbb2a 2004-04-19 devnull checkreg(State *s, long r)
175 a84cbb2a 2004-04-19 devnull {
176 a84cbb2a 2004-04-19 devnull if(r < 0 || r >= s->nr){
177 a84cbb2a 2004-04-19 devnull werrstr("bad register number 0x%lux", r);
178 a84cbb2a 2004-04-19 devnull return -1;
179 a84cbb2a 2004-04-19 devnull }
180 a84cbb2a 2004-04-19 devnull return 0;
181 a84cbb2a 2004-04-19 devnull }
182 a84cbb2a 2004-04-19 devnull
183 a84cbb2a 2004-04-19 devnull static int
184 a84cbb2a 2004-04-19 devnull dexec(DwarfBuf *b, State *s, int locstop)
185 a84cbb2a 2004-04-19 devnull {
186 a84cbb2a 2004-04-19 devnull int c;
187 a84cbb2a 2004-04-19 devnull long arg1, arg2;
188 a84cbb2a 2004-04-19 devnull DwarfExpr *e, **p;
189 a84cbb2a 2004-04-19 devnull
190 a84cbb2a 2004-04-19 devnull for(;;){
191 a84cbb2a 2004-04-19 devnull if(b->p == b->ep){
192 a84cbb2a 2004-04-19 devnull if(s->initr)
193 a84cbb2a 2004-04-19 devnull s->loc = s->endloc;
194 a84cbb2a 2004-04-19 devnull return 0;
195 a84cbb2a 2004-04-19 devnull }
196 a84cbb2a 2004-04-19 devnull c = dwarfget1(b);
197 a84cbb2a 2004-04-19 devnull if(b->p == nil){
198 a84cbb2a 2004-04-19 devnull werrstr("ran out of instructions during cfa program");
199 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "%r\n");
200 a84cbb2a 2004-04-19 devnull return -1;
201 a84cbb2a 2004-04-19 devnull }
202 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "+ loc=0x%lux op 0x%ux ", s->loc, c);
203 a84cbb2a 2004-04-19 devnull switch(c>>6){
204 a84cbb2a 2004-04-19 devnull case 1: /* advance location */
205 a84cbb2a 2004-04-19 devnull arg1 = c&0x3F;
206 a84cbb2a 2004-04-19 devnull advance:
207 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "loc += %ld\n", arg1*s->iquantum);
208 a84cbb2a 2004-04-19 devnull s->loc += arg1 * s->iquantum;
209 a84cbb2a 2004-04-19 devnull if(locstop)
210 a84cbb2a 2004-04-19 devnull return 0;
211 a84cbb2a 2004-04-19 devnull continue;
212 fa325e9b 2020-01-10 cross
213 a84cbb2a 2004-04-19 devnull case 2: /* offset rule */
214 a84cbb2a 2004-04-19 devnull arg1 = c&0x3F;
215 a84cbb2a 2004-04-19 devnull arg2 = dwarfget128(b);
216 a84cbb2a 2004-04-19 devnull offset:
217 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "r%ld += %ld\n", arg1, arg2*s->dquantum);
218 a84cbb2a 2004-04-19 devnull if(checkreg(s, arg1) < 0)
219 a84cbb2a 2004-04-19 devnull return -1;
220 a84cbb2a 2004-04-19 devnull s->r[arg1].type = RuleCfaOffset;
221 a84cbb2a 2004-04-19 devnull s->r[arg1].offset = arg2 * s->dquantum;
222 a84cbb2a 2004-04-19 devnull continue;
223 a84cbb2a 2004-04-19 devnull
224 a84cbb2a 2004-04-19 devnull case 3: /* restore initial setting */
225 a84cbb2a 2004-04-19 devnull arg1 = c&0x3F;
226 a84cbb2a 2004-04-19 devnull restore:
227 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "r%ld = init\n", arg1);
228 a84cbb2a 2004-04-19 devnull if(checkreg(s, arg1) < 0)
229 a84cbb2a 2004-04-19 devnull return -1;
230 a84cbb2a 2004-04-19 devnull s->r[arg1] = s->initr[arg1];
231 a84cbb2a 2004-04-19 devnull continue;
232 a84cbb2a 2004-04-19 devnull }
233 a84cbb2a 2004-04-19 devnull
234 a84cbb2a 2004-04-19 devnull switch(c){
235 a84cbb2a 2004-04-19 devnull case 0: /* nop */
236 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "nop\n");
237 a84cbb2a 2004-04-19 devnull continue;
238 a84cbb2a 2004-04-19 devnull
239 a84cbb2a 2004-04-19 devnull case 0x01: /* set location */
240 a84cbb2a 2004-04-19 devnull s->loc = dwarfgetaddr(b);
241 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "loc = 0x%lux\n", s->loc);
242 a84cbb2a 2004-04-19 devnull if(locstop)
243 a84cbb2a 2004-04-19 devnull return 0;
244 a84cbb2a 2004-04-19 devnull continue;
245 a84cbb2a 2004-04-19 devnull
246 a84cbb2a 2004-04-19 devnull case 0x02: /* advance loc1 */
247 a84cbb2a 2004-04-19 devnull arg1 = dwarfget1(b);
248 a84cbb2a 2004-04-19 devnull goto advance;
249 a84cbb2a 2004-04-19 devnull
250 a84cbb2a 2004-04-19 devnull case 0x03: /* advance loc2 */
251 a84cbb2a 2004-04-19 devnull arg1 = dwarfget2(b);
252 a84cbb2a 2004-04-19 devnull goto advance;
253 a84cbb2a 2004-04-19 devnull
254 a84cbb2a 2004-04-19 devnull case 0x04: /* advance loc4 */
255 a84cbb2a 2004-04-19 devnull arg1 = dwarfget4(b);
256 a84cbb2a 2004-04-19 devnull goto advance;
257 a84cbb2a 2004-04-19 devnull
258 a84cbb2a 2004-04-19 devnull case 0x05: /* offset extended */
259 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
260 a84cbb2a 2004-04-19 devnull arg2 = dwarfget128(b);
261 a84cbb2a 2004-04-19 devnull goto offset;
262 a84cbb2a 2004-04-19 devnull
263 a84cbb2a 2004-04-19 devnull case 0x06: /* restore extended */
264 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
265 a84cbb2a 2004-04-19 devnull goto restore;
266 a84cbb2a 2004-04-19 devnull
267 a84cbb2a 2004-04-19 devnull case 0x07: /* undefined */
268 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
269 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "r%ld = undef\n", arg1);
270 a84cbb2a 2004-04-19 devnull if(checkreg(s, arg1) < 0)
271 a84cbb2a 2004-04-19 devnull return -1;
272 a84cbb2a 2004-04-19 devnull s->r[arg1].type = RuleUndef;
273 a84cbb2a 2004-04-19 devnull continue;
274 a84cbb2a 2004-04-19 devnull
275 a84cbb2a 2004-04-19 devnull case 0x08: /* same value */
276 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
277 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "r%ld = same\n", arg1);
278 a84cbb2a 2004-04-19 devnull if(checkreg(s, arg1) < 0)
279 a84cbb2a 2004-04-19 devnull return -1;
280 a84cbb2a 2004-04-19 devnull s->r[arg1].type = RuleSame;
281 a84cbb2a 2004-04-19 devnull continue;
282 a84cbb2a 2004-04-19 devnull
283 a84cbb2a 2004-04-19 devnull case 0x09: /* register */
284 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
285 a84cbb2a 2004-04-19 devnull arg2 = dwarfget128(b);
286 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "r%ld = r%ld\n", arg1, arg2);
287 a84cbb2a 2004-04-19 devnull if(checkreg(s, arg1) < 0 || checkreg(s, arg2) < 0)
288 a84cbb2a 2004-04-19 devnull return -1;
289 a84cbb2a 2004-04-19 devnull s->r[arg1].type = RuleRegister;
290 a84cbb2a 2004-04-19 devnull s->r[arg1].reg = arg2;
291 a84cbb2a 2004-04-19 devnull continue;
292 a84cbb2a 2004-04-19 devnull
293 a84cbb2a 2004-04-19 devnull case 0x0A: /* remember state */
294 a84cbb2a 2004-04-19 devnull e = malloc(s->nr*sizeof(e[0]));
295 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "push\n");
296 a84cbb2a 2004-04-19 devnull if(e == nil)
297 a84cbb2a 2004-04-19 devnull return -1;
298 a84cbb2a 2004-04-19 devnull p = realloc(s->stack, (s->nstack+1)*sizeof(s->stack[0]));
299 a84cbb2a 2004-04-19 devnull if(p == nil){
300 a84cbb2a 2004-04-19 devnull free(e);
301 a84cbb2a 2004-04-19 devnull return -1;
302 a84cbb2a 2004-04-19 devnull }
303 a84cbb2a 2004-04-19 devnull s->stack[s->nstack++] = e;
304 a84cbb2a 2004-04-19 devnull memmove(e, s->r, s->nr*sizeof(e[0]));
305 a84cbb2a 2004-04-19 devnull continue;
306 a84cbb2a 2004-04-19 devnull
307 a84cbb2a 2004-04-19 devnull case 0x0B: /* restore state */
308 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "pop\n");
309 a84cbb2a 2004-04-19 devnull if(s->nstack == 0){
310 a84cbb2a 2004-04-19 devnull werrstr("restore state underflow");
311 a84cbb2a 2004-04-19 devnull return -1;
312 a84cbb2a 2004-04-19 devnull }
313 a84cbb2a 2004-04-19 devnull e = s->stack[s->nstack-1];
314 a84cbb2a 2004-04-19 devnull memmove(s->r, e, s->nr*sizeof(e[0]));
315 a84cbb2a 2004-04-19 devnull p = realloc(s->stack, (s->nstack-1)*sizeof(s->stack[0]));
316 a84cbb2a 2004-04-19 devnull if(p == nil)
317 a84cbb2a 2004-04-19 devnull return -1;
318 a84cbb2a 2004-04-19 devnull free(e);
319 a84cbb2a 2004-04-19 devnull s->nstack--;
320 a84cbb2a 2004-04-19 devnull continue;
321 a84cbb2a 2004-04-19 devnull
322 a84cbb2a 2004-04-19 devnull case 0x0C: /* def cfa */
323 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
324 a84cbb2a 2004-04-19 devnull arg2 = dwarfget128(b);
325 a84cbb2a 2004-04-19 devnull defcfa:
326 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "cfa %ld(r%ld)\n", arg2, arg1);
327 a84cbb2a 2004-04-19 devnull if(checkreg(s, arg1) < 0)
328 a84cbb2a 2004-04-19 devnull return -1;
329 a84cbb2a 2004-04-19 devnull s->cfa->type = RuleRegOff;
330 a84cbb2a 2004-04-19 devnull s->cfa->reg = arg1;
331 a84cbb2a 2004-04-19 devnull s->cfa->offset = arg2;
332 a84cbb2a 2004-04-19 devnull continue;
333 a84cbb2a 2004-04-19 devnull
334 fa325e9b 2020-01-10 cross case 0x0D: /* def cfa register */
335 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
336 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "cfa reg r%ld\n", arg1);
337 a84cbb2a 2004-04-19 devnull if(s->cfa->type != RuleRegOff){
338 a84cbb2a 2004-04-19 devnull werrstr("change CFA register but CFA not in register+offset form");
339 fa325e9b 2020-01-10 cross return -1;
340 a84cbb2a 2004-04-19 devnull }
341 a84cbb2a 2004-04-19 devnull if(checkreg(s, arg1) < 0)
342 a84cbb2a 2004-04-19 devnull return -1;
343 a84cbb2a 2004-04-19 devnull s->cfa->reg = arg1;
344 a84cbb2a 2004-04-19 devnull continue;
345 a84cbb2a 2004-04-19 devnull
346 a84cbb2a 2004-04-19 devnull case 0x0E: /* def cfa offset */
347 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
348 a84cbb2a 2004-04-19 devnull cfaoffset:
349 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "cfa off %ld\n", arg1);
350 a84cbb2a 2004-04-19 devnull if(s->cfa->type != RuleRegOff){
351 a84cbb2a 2004-04-19 devnull werrstr("change CFA offset but CFA not in register+offset form");
352 a84cbb2a 2004-04-19 devnull return -1;
353 a84cbb2a 2004-04-19 devnull }
354 a84cbb2a 2004-04-19 devnull s->cfa->offset = arg1;
355 a84cbb2a 2004-04-19 devnull continue;
356 a84cbb2a 2004-04-19 devnull
357 a84cbb2a 2004-04-19 devnull case 0x0F: /* def cfa expression */
358 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "cfa expr\n");
359 a84cbb2a 2004-04-19 devnull s->cfa->type = RuleLocation;
360 a84cbb2a 2004-04-19 devnull s->cfa->loc.len = dwarfget128(b);
361 a84cbb2a 2004-04-19 devnull s->cfa->loc.data = dwarfgetnref(b, s->cfa->loc.len);
362 a84cbb2a 2004-04-19 devnull continue;
363 a84cbb2a 2004-04-19 devnull
364 a84cbb2a 2004-04-19 devnull case 0x10: /* def reg expression */
365 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
366 a84cbb2a 2004-04-19 devnull if(trace) fprint(2, "reg expr r%ld\n", arg1);
367 a84cbb2a 2004-04-19 devnull if(checkreg(s, arg1) < 0)
368 a84cbb2a 2004-04-19 devnull return -1;
369 a84cbb2a 2004-04-19 devnull s->r[arg1].type = RuleLocation;
370 a84cbb2a 2004-04-19 devnull s->r[arg1].loc.len = dwarfget128(b);
371 a84cbb2a 2004-04-19 devnull s->r[arg1].loc.data = dwarfgetnref(b, s->r[arg1].loc.len);
372 a84cbb2a 2004-04-19 devnull continue;
373 a84cbb2a 2004-04-19 devnull
374 a84cbb2a 2004-04-19 devnull case 0x11: /* offset extended */
375 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
376 a84cbb2a 2004-04-19 devnull arg2 = dwarfget128s(b);
377 a84cbb2a 2004-04-19 devnull goto offset;
378 a84cbb2a 2004-04-19 devnull
379 a84cbb2a 2004-04-19 devnull case 0x12: /* cfa sf */
380 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128(b);
381 a84cbb2a 2004-04-19 devnull arg2 = dwarfget128s(b);
382 a84cbb2a 2004-04-19 devnull goto defcfa;
383 a84cbb2a 2004-04-19 devnull
384 a84cbb2a 2004-04-19 devnull case 0x13: /* cfa offset sf */
385 a84cbb2a 2004-04-19 devnull arg1 = dwarfget128s(b);
386 a84cbb2a 2004-04-19 devnull goto cfaoffset;
387 a84cbb2a 2004-04-19 devnull
388 a84cbb2a 2004-04-19 devnull default: /* unknown */
389 a84cbb2a 2004-04-19 devnull werrstr("unknown opcode 0x%ux in cfa program", c);
390 a84cbb2a 2004-04-19 devnull return -1;
391 a84cbb2a 2004-04-19 devnull }
392 a84cbb2a 2004-04-19 devnull }
393 fa325e9b 2020-01-10 cross /* not reached */
394 a84cbb2a 2004-04-19 devnull }