2 a84cbb2a 2004-04-19 devnull * Dwarf call frame unwinding.
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.
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"
16 a84cbb2a 2004-04-19 devnull #define trace 0
18 a84cbb2a 2004-04-19 devnull typedef struct State State;
19 a84cbb2a 2004-04-19 devnull struct State
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;
34 a84cbb2a 2004-04-19 devnull DwarfExpr **stack;
35 a84cbb2a 2004-04-19 devnull int nstack;
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);
42 a84cbb2a 2004-04-19 devnull dwarfunwind(Dwarf *d, ulong pc, DwarfExpr *cfa, DwarfExpr *ra, DwarfExpr *r, int nr)
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;
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;
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;
58 a84cbb2a 2004-04-19 devnull s.nr = nr;
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;
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;
73 a84cbb2a 2004-04-19 devnull s.initr = initr;
74 a84cbb2a 2004-04-19 devnull memmove(initr, r, nr*sizeof(initr[0]));
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;
82 a84cbb2a 2004-04-19 devnull *ra = s.r[s.rareg];
85 a84cbb2a 2004-04-19 devnull goto out;
88 a84cbb2a 2004-04-19 devnull ret = -1;
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;
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.
103 a84cbb2a 2004-04-19 devnull static int
104 a84cbb2a 2004-04-19 devnull findfde(Dwarf *d, ulong pc, State *s, DwarfBuf *fde)
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;
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;
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? */
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;
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;
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;
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;
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;
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;
173 a84cbb2a 2004-04-19 devnull static int
174 a84cbb2a 2004-04-19 devnull checkreg(State *s, long r)
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;
180 a84cbb2a 2004-04-19 devnull return 0;
183 a84cbb2a 2004-04-19 devnull static int
184 a84cbb2a 2004-04-19 devnull dexec(DwarfBuf *b, State *s, int locstop)
187 a84cbb2a 2004-04-19 devnull long arg1, arg2;
188 a84cbb2a 2004-04-19 devnull DwarfExpr *e, **p;
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;
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;
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;
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);
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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);
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;
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;
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;
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;
354 a84cbb2a 2004-04-19 devnull s->cfa->offset = arg1;
355 a84cbb2a 2004-04-19 devnull continue;
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;
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;
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;
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;
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;
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;
393 fa325e9b 2020-01-10 cross /* not reached */