Stackdb
Stackdb is a stackable, multi-target and -level source debugger and memory forensics library.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
dwarf_expr.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2013 The University of Utah
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include <stdlib.h>
20 #include <stdbool.h>
21 #include <string.h>
22 #include <inttypes.h>
23 #include <assert.h>
24 
25 #include "common.h"
26 #include "dwdebug.h"
27 #include "dwdebug_priv.h"
28 
29 #include "memory-access.h"
30 
31 #include <dwarf.h>
32 #include <gelf.h>
33 #include <elfutils/libebl.h>
34 #include <elfutils/libdw.h>
35 #include <elfutils/libdwfl.h>
36 
37 /*
38  * DWARF operations, nicely indexed.
39  */
40 static const char *const known_ops[] = {
41  [DW_OP_addr] = "addr",
42  [DW_OP_deref] = "deref",
43  [DW_OP_const1u] = "const1u",
44  [DW_OP_const1s] = "const1s",
45  [DW_OP_const2u] = "const2u",
46  [DW_OP_const2s] = "const2s",
47  [DW_OP_const4u] = "const4u",
48  [DW_OP_const4s] = "const4s",
49  [DW_OP_const8u] = "const8u",
50  [DW_OP_const8s] = "const8s",
51  [DW_OP_constu] = "constu",
52  [DW_OP_consts] = "consts",
53  [DW_OP_dup] = "dup",
54  [DW_OP_drop] = "drop",
55  [DW_OP_over] = "over",
56  [DW_OP_pick] = "pick",
57  [DW_OP_swap] = "swap",
58  [DW_OP_rot] = "rot",
59  [DW_OP_xderef] = "xderef",
60  [DW_OP_abs] = "abs",
61  [DW_OP_and] = "and",
62  [DW_OP_div] = "div",
63  [DW_OP_minus] = "minus",
64  [DW_OP_mod] = "mod",
65  [DW_OP_mul] = "mul",
66  [DW_OP_neg] = "neg",
67  [DW_OP_not] = "not",
68  [DW_OP_or] = "or",
69  [DW_OP_plus] = "plus",
70  [DW_OP_plus_uconst] = "plus_uconst",
71  [DW_OP_shl] = "shl",
72  [DW_OP_shr] = "shr",
73  [DW_OP_shra] = "shra",
74  [DW_OP_xor] = "xor",
75  [DW_OP_bra] = "bra",
76  [DW_OP_eq] = "eq",
77  [DW_OP_ge] = "ge",
78  [DW_OP_gt] = "gt",
79  [DW_OP_le] = "le",
80  [DW_OP_lt] = "lt",
81  [DW_OP_ne] = "ne",
82  [DW_OP_skip] = "skip",
83  [DW_OP_lit0] = "lit0",
84  [DW_OP_lit1] = "lit1",
85  [DW_OP_lit2] = "lit2",
86  [DW_OP_lit3] = "lit3",
87  [DW_OP_lit4] = "lit4",
88  [DW_OP_lit5] = "lit5",
89  [DW_OP_lit6] = "lit6",
90  [DW_OP_lit7] = "lit7",
91  [DW_OP_lit8] = "lit8",
92  [DW_OP_lit9] = "lit9",
93  [DW_OP_lit10] = "lit10",
94  [DW_OP_lit11] = "lit11",
95  [DW_OP_lit12] = "lit12",
96  [DW_OP_lit13] = "lit13",
97  [DW_OP_lit14] = "lit14",
98  [DW_OP_lit15] = "lit15",
99  [DW_OP_lit16] = "lit16",
100  [DW_OP_lit17] = "lit17",
101  [DW_OP_lit18] = "lit18",
102  [DW_OP_lit19] = "lit19",
103  [DW_OP_lit20] = "lit20",
104  [DW_OP_lit21] = "lit21",
105  [DW_OP_lit22] = "lit22",
106  [DW_OP_lit23] = "lit23",
107  [DW_OP_lit24] = "lit24",
108  [DW_OP_lit25] = "lit25",
109  [DW_OP_lit26] = "lit26",
110  [DW_OP_lit27] = "lit27",
111  [DW_OP_lit28] = "lit28",
112  [DW_OP_lit29] = "lit29",
113  [DW_OP_lit30] = "lit30",
114  [DW_OP_lit31] = "lit31",
115  [DW_OP_reg0] = "reg0",
116  [DW_OP_reg1] = "reg1",
117  [DW_OP_reg2] = "reg2",
118  [DW_OP_reg3] = "reg3",
119  [DW_OP_reg4] = "reg4",
120  [DW_OP_reg5] = "reg5",
121  [DW_OP_reg6] = "reg6",
122  [DW_OP_reg7] = "reg7",
123  [DW_OP_reg8] = "reg8",
124  [DW_OP_reg9] = "reg9",
125  [DW_OP_reg10] = "reg10",
126  [DW_OP_reg11] = "reg11",
127  [DW_OP_reg12] = "reg12",
128  [DW_OP_reg13] = "reg13",
129  [DW_OP_reg14] = "reg14",
130  [DW_OP_reg15] = "reg15",
131  [DW_OP_reg16] = "reg16",
132  [DW_OP_reg17] = "reg17",
133  [DW_OP_reg18] = "reg18",
134  [DW_OP_reg19] = "reg19",
135  [DW_OP_reg20] = "reg20",
136  [DW_OP_reg21] = "reg21",
137  [DW_OP_reg22] = "reg22",
138  [DW_OP_reg23] = "reg23",
139  [DW_OP_reg24] = "reg24",
140  [DW_OP_reg25] = "reg25",
141  [DW_OP_reg26] = "reg26",
142  [DW_OP_reg27] = "reg27",
143  [DW_OP_reg28] = "reg28",
144  [DW_OP_reg29] = "reg29",
145  [DW_OP_reg30] = "reg30",
146  [DW_OP_reg31] = "reg31",
147  [DW_OP_breg0] = "breg0",
148  [DW_OP_breg1] = "breg1",
149  [DW_OP_breg2] = "breg2",
150  [DW_OP_breg3] = "breg3",
151  [DW_OP_breg4] = "breg4",
152  [DW_OP_breg5] = "breg5",
153  [DW_OP_breg6] = "breg6",
154  [DW_OP_breg7] = "breg7",
155  [DW_OP_breg8] = "breg8",
156  [DW_OP_breg9] = "breg9",
157  [DW_OP_breg10] = "breg10",
158  [DW_OP_breg11] = "breg11",
159  [DW_OP_breg12] = "breg12",
160  [DW_OP_breg13] = "breg13",
161  [DW_OP_breg14] = "breg14",
162  [DW_OP_breg15] = "breg15",
163  [DW_OP_breg16] = "breg16",
164  [DW_OP_breg17] = "breg17",
165  [DW_OP_breg18] = "breg18",
166  [DW_OP_breg19] = "breg19",
167  [DW_OP_breg20] = "breg20",
168  [DW_OP_breg21] = "breg21",
169  [DW_OP_breg22] = "breg22",
170  [DW_OP_breg23] = "breg23",
171  [DW_OP_breg24] = "breg24",
172  [DW_OP_breg25] = "breg25",
173  [DW_OP_breg26] = "breg26",
174  [DW_OP_breg27] = "breg27",
175  [DW_OP_breg28] = "breg28",
176  [DW_OP_breg29] = "breg29",
177  [DW_OP_breg30] = "breg30",
178  [DW_OP_breg31] = "breg31",
179  [DW_OP_regx] = "regx",
180  [DW_OP_fbreg] = "fbreg",
181  [DW_OP_bregx] = "bregx",
182  [DW_OP_piece] = "piece",
183  [DW_OP_deref_size] = "deref_size",
184  [DW_OP_xderef_size] = "xderef_size",
185  [DW_OP_nop] = "nop",
186  [DW_OP_push_object_address] = "push_object_address",
187  [DW_OP_call2] = "call2",
188  [DW_OP_call4] = "call4",
189  [DW_OP_call_ref] = "call_ref",
190  [DW_OP_form_tls_address] = "form_tls_address",
191  [DW_OP_call_frame_cfa] = "call_frame_cfa",
192  [DW_OP_bit_piece] = "bit_piece",
193 #if _INT_ELFUTILS_VERSION > 138
194  [DW_OP_GNU_push_tls_address] = "GNU_push_tls_address",
195  [DW_OP_GNU_uninit] = "GNU_uninit",
196  [DW_OP_GNU_encoded_addr] = "GNU_encoded_addr",
197 #endif
198 #if _INT_ELFUTILS_VERSION > 141
199  [DW_OP_implicit_value] = "implicit_value",
200  [DW_OP_stack_value] = "stack_value",
201 #endif
202 #if _INT_ELFUTILS_VERSION > 148
203  [DW_OP_GNU_implicit_pointer] = "GNU_implicit_pointer",
204 #endif
205 };
206 
207 const char *dwarf_op_string(unsigned int op) {
208  if (op < (sizeof(known_ops) / sizeof(known_ops[0])))
209  return known_ops[op];
210  return NULL;
211 }
212 
213 loctype_t dwarf_location_resolve(const unsigned char *data,unsigned int len,
214  struct location_ctxt *lctxt,
215  struct symbol *symbol,struct location *o_loc) {
216  unsigned int addrsize = 0;
217 
218  /* const unsigned int ref_size = vers < 3 ? addrsize : offset_size; */
219 
220  /* XXX: we can't get other_byte_order from dbg since we don't have
221  * the struct def for it... so we assume it's not a diff byte order
222  * than the phys host for now.
223  */
224  int obo = 0;
225 
226  /* save the originals for later for runtime computation if we need */
227  const unsigned char *origdata = data;
228  int origlen = len;
229 
230  /*
231  * We try to use a static stack; if we run out, we malloc one.
232  */
233  int stackdepth = 0;
234  Dwarf_Word stack[16];
235  Dwarf_Word *overflowstack = NULL;
236  int overflowstacklen = 0;
237 
238  struct location_ops *lops = NULL;
239 
240  if (!lctxt || !lctxt->ops) {
241  verror("no location ops for current frame %d!\n",lctxt->current_frame);
242  errno = EINVAL;
243  return -1;
244  }
245  lops = lctxt->ops;
246 
247  if (len == 0) {
248  vwarn("empty dwarf block num!\n");
249  goto errout;
250  }
251 
252  /*
253  * We don't want to have to trace from @symbol all the way back to
254  * the root and grab the DWARF addrsize out of root->extra.root each
255  * time we call this function. So try to rely on the target's info,
256  * if it exists; else, just assume host word size == target word
257  * size.
258  */
259  if (lops && lops->getaddrsize)
260  addrsize = lops->getaddrsize(lctxt);
261  /* Else just make a best-effort guess. */
262  if (addrsize <= 0)
263  addrsize = sizeof(Dwarf_Word);
264 
265 #define NEED(n) \
266  if (len < (n)) goto errout
267 #define CONSUME(n) \
268  NEED (n); else len -= (n)
269 #define NEEDSTACK(n) \
270  do { \
271  if (n > stackdepth) { \
272  verror("op %s needed %d stack values, but only %d available!\n", \
273  known_ops[op],(n),stackdepth); \
274  goto errout; \
275  } \
276  } while (0)
277 #define PUSH(value) \
278  do { \
279  if (overflowstack) { \
280  if (stackdepth == overflowstacklen) { \
281  overflowstack = \
282  realloc(overflowstack, \
283  (overflowstacklen + 4) * sizeof(Dwarf_Word)); \
284  overflowstacklen += 4; \
285  } \
286  overflowstack[stackdepth] = value; \
287  } \
288  else if (stackdepth == (sizeof(stack) / sizeof(Dwarf_Word))) { \
289  overflowstacklen = stackdepth + 4; \
290  overflowstack = calloc(overflowstacklen,sizeof(Dwarf_Word)); \
291  memcpy(overflowstack,&stack,sizeof(stack)); \
292  overflowstack[stackdepth] = value; \
293  } \
294  else { \
295  stack[stackdepth] = value; \
296  } \
297  ++stackdepth; \
298  } while (0)
299 #define PEEK() ((overflowstack) ? overflowstack[stackdepth - 1] \
300  : stack[stackdepth - 1])
301 #define POP() ((overflowstack) ? overflowstack[--stackdepth] \
302  : stack[--stackdepth])
303 #define PICK(i) ((overflowstack) ? overflowstack[stackdepth - 1 - i] \
304  : stack[stackdepth - 1 - i])
305 #define INPLACE1(OP,value) \
306  do { \
307  NEEDSTACK(1); \
308  if (overflowstack) \
309  overflowstack[stackdepth - 1] = \
310  overflowstack[stackdepth - 1] OP (value); \
311  else \
312  stack[stackdepth - 1] = \
313  stack[stackdepth - 1] OP (value); \
314  } while (0)
315 #define INPLACE1SIGNED(OP,value) \
316  do { \
317  NEEDSTACK(1); \
318  if (overflowstack) \
319  overflowstack[stackdepth - 1] = (Dwarf_Word) \
320  ((int64_t)overflowstack[stackdepth - 1] OP (int64_t)(value)); \
321  else \
322  stack[stackdepth - 1] = (Dwarf_Word) \
323  ((int64_t)stack[stackdepth - 1] OP (int64_t)(value)); \
324  } while (0)
325 #define INPLACE1UNARY(OP) \
326  do { \
327  NEEDSTACK(1); \
328  if (overflowstack) \
329  overflowstack[stackdepth - 1] = \
330  OP overflowstack[stackdepth - 1]; \
331  else \
332  stack[stackdepth - 1] = \
333  OP stack[stackdepth - 1]; \
334  } while (0)
335 #define INPLACE2(OP) \
336  do { \
337  NEEDSTACK(2); \
338  if (overflowstack) \
339  overflowstack[stackdepth - 2] = \
340  overflowstack[stackdepth - 2] OP overflowstack[stackdepth - 1]; \
341  else \
342  stack[stackdepth - 2] = \
343  stack[stackdepth - 1] OP stack[stackdepth - 2]; \
344  --stackdepth; \
345  } while (0)
346 #define OPCONSTU(size,tt) \
347  NEED(size); \
348  u64 = (uint64_t)*((tt *)data); \
349  data += size; \
350  CONSUME(size); \
351  vdebug(6,LA_DEBUG,LF_DWARFOPS,"%s -> 0x%"PRIu64"\n", \
352  known_ops[op],u64); \
353  PUSH((Dwarf_Word)u64)
354 #define OPCONSTS(size,tt) \
355  NEED(size); \
356  s64 = (int64_t)*((tt *)data); \
357  data += size; \
358  CONSUME(size); \
359  vdebug(6,LA_DEBUG,LF_DWARFOPS,"%s -> 0x%"PRIx64"\n", \
360  known_ops[op],s64); \
361  PUSH((Dwarf_Word)s64)
362 
363  /*
364  * Process the operation list.
365  */
366  REG lreg = -1;
367  unsigned char *ldata = NULL;
368  int llen = 0;
369  uint_fast8_t op;
370 
371  while (len-- > 0) {
372  op = *data++;
373  const unsigned char *start = data;
374 
375  if (op < (sizeof(known_ops) / sizeof(known_ops[0]))
376  && known_ops[op] != NULL)
378  "%s with len = %d\n",known_ops[op],len);
379  else
381  "unknown op 0x%hhx with len = %d\n",op,len);
382 
383  Dwarf_Word addr;
384  uint64_t u64;
385  int64_t s64;
386  Dwarf_Word tvalue;
387  ADDR taddr;
388  REG treg;
389  loctype_t rc;
390  uint8_t index;
391  uint8_t number;
392  struct symbol *parent;
393  uint16_t skipval;
394  struct location tloc;
395  int nrc;
396 
397 #if __WORDSIZE == 64
398 #define PRIxDwarfWord PRIx64
399 #else
400 #define PRIxDwarfWord PRIx32
401 #endif
402 
403  switch (op) {
404  /*
405  * Literal encodings.
406  */
407  case DW_OP_lit0 ... DW_OP_lit31:
408  PUSH(op - (uint8_t)DW_OP_lit0);
409  break;
410  case DW_OP_addr:
411  NEED(addrsize);
412  if (addrsize == 4)
413  addr = read_4ubyte_unaligned(obo,data);
414  else {
415  assert(addrsize == 8);
416  addr = read_8ubyte_unaligned(obo,data);
417  }
419  "%s -> 0x%"PRIxDwarfWord"\n",known_ops[op],addr);
420  data += addrsize;
421  CONSUME(addrsize);
422  /*
423  * NB: if we have a location_ops struct, we need to try to
424  * relocate this address, because location_resolution
425  * functions must produce real, relocated addresses (if
426  * location_ops and location_ops->relocate was specified).
427  */
428  if (lops && lops->relocate) {
429  taddr = addr;
430  if (!lops->relocate(lctxt,taddr,&taddr))
431  addr = (Dwarf_Word)taddr;
432  }
433  PUSH(addr);
434  break;
435  case DW_OP_const1u:
436  OPCONSTU(1,uint8_t);
437  break;
438  case DW_OP_const2u:
439  OPCONSTU(2,uint16_t);
440  break;
441  case DW_OP_const4u:
442  OPCONSTU(4,uint32_t);
443  break;
444  case DW_OP_const8u:
445  OPCONSTU(8,uint64_t);
446  break;
447  case DW_OP_const1s:
448  OPCONSTS(1,int8_t);
449  break;
450  case DW_OP_const2s:
451  OPCONSTS(2,int16_t);
452  break;
453  case DW_OP_const4s:
454  OPCONSTS(4,int32_t);
455  break;
456  case DW_OP_const8s:
457  OPCONSTS(8,int64_t);
458  break;
459  case DW_OP_constu:
460  NEED(1);
461  get_uleb128(u64,data); /* XXX check overrun */
462  CONSUME(data - start);
464  "%s -> 0x%"PRIu64"\n",known_ops[op],u64);
465  PUSH((Dwarf_Word)u64);
466  break;
467  case DW_OP_consts:
468  NEED(1);
469  get_sleb128(s64,data); /* XXX check overrun */
470  CONSUME(data - start);
471  vdebug(6,LA_DEBUG,LF_DWARFOPS,"%s -> 0x%"PRIx64"\n",
472  known_ops[op],s64);
473  PUSH((Dwarf_Word)s64);
474  break;
475  /*
476  * Register-based addressing.
477  */
478  case DW_OP_fbreg:
479  NEED(1);
480  get_sleb128(s64,data); /* XXX check overrun */
481  CONSUME(data - start);
483  "%s -> fbreg offset %"PRIi64"\n",known_ops[op],s64);
484 
485  if (!symbol) {
486  verror("cannot find frame_base; no symbol supplied!\n");
487  errno = EINVAL;
488  goto errout;
489  }
490  /*
491  * To determine the value of the frame base pseudo register, we
492  * must find @symbol's containing function.
493  */
494  parent = symbol;
495  while ((parent = symbol_find_parent(parent))) {
496  if (SYMBOL_IS_FUNC(parent))
497  break;
498  }
499  if (!parent || !SYMBOL_IS_FUNC(parent)) {
500  verror("cannot find frame_base; no parent function contains ");
501  ERRORDUMPSYMBOL_NL(symbol);
502  errno = EINVAL;
503  goto errout;
504  }
505 
506  SYMBOL_RX_FUNC(parent,pf);
507  if (!pf || !pf->fbloc) {
508  verror("cannot find frame_base; no frame base in parent"
509  " function of ");
510  ERRORDUMPSYMBOL_NL(symbol);
511  errno = EINVAL;
512  goto errout;
513  }
514 
515  /* Resolve the parent's fbloc; load it; and apply the offset! */
516  memset(&tloc,0,sizeof(tloc));
517  rc = location_resolve(pf->fbloc,lctxt,parent,&tloc);
518  if (rc == LOCTYPE_REG) {
519  treg = LOCATION_REG(&tloc);
520  nrc = location_ctxt_read_reg(lctxt,treg,&taddr);
521  if (nrc) {
522  verror("cannot read reg %"PRIiREG" to get frame_base value\n",
523  treg);
524  goto errout;
525  }
526  }
527  else if (rc == LOCTYPE_IMPLICIT_WORD) {
528  taddr = LOCATION_WORD(&tloc);
529  }
530  else if (rc == LOCTYPE_ADDR) {
531  taddr = LOCATION_ADDR(&tloc);
532  }
533  else {
534  verror("cannot get frame base value: %s (%s)\n",
535  strerror(errno),LOCTYPE(rc));
536  goto errout;
537  }
538 
540  "frame_base 0x%"PRIxADDR",fboffset %"PRIi64"\n",
541  taddr,s64);
542 
543  PUSH((Dwarf_Word)(taddr + s64));
544  break;
545  case DW_OP_breg0 ... DW_OP_breg31:
546  NEED(1);
547  get_sleb128(s64,data); /* XXX check overrun */
548  CONSUME(data - start);
550  "%s -> reg (%hhd) offset %"PRIi64"\n",
551  known_ops[op],(uint8_t)(op - DW_OP_breg0),s64);
552 
553  taddr = 0;
554  treg = (op - DW_OP_breg0);
555  nrc = location_ctxt_read_reg(lctxt,treg,&taddr);
556  if (nrc) {
557  verror("error reading reg %"PRIiREG" to compute %s!\n",
558  treg,known_ops[op]);
559  goto errout;
560  }
561 
563  "%s -> reg (%hhd) offset %"PRIi64" = 0x%"PRIxDwarfWord"\n",
564  known_ops[op],treg,s64,(Dwarf_Word)(taddr + s64));
565 
566  PUSH((Dwarf_Word)(taddr + s64));
567  break;
568  case DW_OP_bregx:
569  NEED(2);
570  get_uleb128(u64,data); /* XXX check overrun */
571  get_sleb128(s64,data); /* XXX check overrun */
572  CONSUME(data - start);
574  "%s -> reg%" PRId8 ", offset %"PRIi64"\n",
575  known_ops[op],(uint8_t)u64,s64);
576 
577  taddr = 0;
578  treg = (REG)u64;
579  nrc = location_ctxt_read_reg(lctxt,treg,&taddr);
580  if (nrc) {
581  verror("error reading reg %"PRIiREG" to compute %s!\n",
582  treg,known_ops[op]);
583  goto errout;
584  }
585 
587  "%s -> reg (%hhd) offset %"PRIi64" = 0x%"PRIxDwarfWord"\n",
588  known_ops[op],treg,s64,(Dwarf_Word)(taddr + s64));
589 
590  PUSH((Dwarf_Word)(taddr + s64));
591  break;
592  /*
593  * Stack operations.
594  */
595  case DW_OP_dup:
596  NEEDSTACK(1);
597  tvalue = PEEK();
598  PUSH(tvalue);
599  break;
600  case DW_OP_drop:
601  NEEDSTACK(1);
602  POP();
603  break;
604  case DW_OP_pick:
605  NEED(1);
606  index = *((uint8_t *)data);
607  CONSUME(1);
608  NEEDSTACK(index + 1);
609  tvalue = PICK(index);
610  PUSH(tvalue);
611  break;
612  case DW_OP_over:
613  NEEDSTACK(2);
614  tvalue = PICK(1);
615  PUSH(tvalue);
616  break;
617  case DW_OP_swap:
618  NEEDSTACK(2);
619  if (overflowstack) {
620  tvalue = overflowstack[stackdepth - 1];
621  overflowstack[stackdepth - 1] = overflowstack[stackdepth - 2];
622  overflowstack[stackdepth - 2] = tvalue;
623  }
624  else {
625  tvalue = stack[stackdepth - 1];
626  stack[stackdepth - 1] = stack[stackdepth - 2];
627  stack[stackdepth - 2] = tvalue;
628  }
629  break;
630  case DW_OP_rot:
631  NEEDSTACK(3);
632  if (overflowstack) {
633  tvalue = overflowstack[stackdepth - 1];
634  overflowstack[stackdepth - 1] = overflowstack[stackdepth - 2];
635  overflowstack[stackdepth - 2] = overflowstack[stackdepth - 3];
636  overflowstack[stackdepth - 3] = tvalue;
637  }
638  else {
639  tvalue = stack[stackdepth - 1];
640  stack[stackdepth - 1] = stack[stackdepth - 2];
641  stack[stackdepth - 2] = stack[stackdepth - 3];
642  stack[stackdepth - 3] = tvalue;
643  }
644  break;
645  case DW_OP_deref:
646  NEEDSTACK(1);
647  taddr = POP();
648  if (!lops || !lops->readword) {
649  verror("cannot read ptr to compute %s op; no location op!\n",
650  known_ops[op]);
651  errno = EINVAL;
652  goto errout;
653  }
654  else if (lops->readword(lctxt,taddr,&taddr)) {
655  verror("error reading addr %"PRIxADDR" to compute %s!\n",
656  taddr,known_ops[op]);
657  goto errout;
658  }
659  PUSH((Dwarf_Word)taddr);
660  break;
661  case DW_OP_deref_size:
662  NEED(1);
663  number = *(uint8_t *)data;
664  CONSUME(1);
665  NEEDSTACK(1);
666  taddr = POP();
667  if (!lops || !lops->readword) {
668  verror("cannot read ptr to compute %s op; no location op!\n",
669  known_ops[op]);
670  errno = EINVAL;
671  goto errout;
672  }
673  else if (lops->readword(lctxt,taddr,&taddr)) {
674  verror("error reading addr %"PRIxADDR" to compute %s!\n",
675  taddr,known_ops[op]);
676  goto errout;
677  }
678  addr = 0;
679  /* XXX: this is little-endian only, obviously. */
680  memcpy(&addr,&taddr,number);
681  PUSH(addr);
682  break;
683  case DW_OP_xderef:
684  case DW_OP_xderef_size:
685  verror("%s op unsupported (we don't know multiple addrspaces)!\n",
686  known_ops[op]);
687  errno = ENOTSUP;
688  goto errout;
689  case DW_OP_push_object_address:
690  case DW_OP_form_tls_address:
691  verror("%s op unsupported!\n",known_ops[op]);
692  errno = ENOTSUP;
693  goto errout;
694  case DW_OP_call_frame_cfa:
695  verror("%s op unsupported (no CFA support yet)!\n",known_ops[op]);
696  errno = ENOTSUP;
697  goto errout;
698  /*
699  * Arithmetic and logical operations.
700  */
701  case DW_OP_abs:
702  NEEDSTACK(1);
703  tvalue = POP();
704  s64 = (int64_t)tvalue;
705  if (s64 < 0)
706  tvalue = (uint64_t)-s64;
707  PUSH((Dwarf_Word)tvalue);
708  break;
709  case DW_OP_and:
710  INPLACE2(&);
711  break;
712  case DW_OP_div:
713  INPLACE2(/);
714  break;
715  case DW_OP_minus:
716  INPLACE2(-);
717  break;
718  case DW_OP_mod:
719  INPLACE2(%);
720  break;
721  case DW_OP_mul:
722  INPLACE2(*);
723  break;
724  case DW_OP_neg:
725  NEEDSTACK(1);
726  s64 = (int64_t)POP();
727  u64 = (uint64_t)-s64;
728  PUSH((Dwarf_Word)u64);
729  break;
730  case DW_OP_or:
731  INPLACE2(|);
732  break;
733  case DW_OP_plus:
734  INPLACE2(+);
735  break;
736  case DW_OP_plus_uconst:
737  NEED(1);
738  get_uleb128(u64,data); /* XXX check overrun */
739  CONSUME(data - start);
741  "%s -> 0x%"PRIu64"\n",known_ops[op],u64);
742  INPLACE1(+,(Dwarf_Word)u64);
743  break;
744  case DW_OP_shl:
745  NEEDSTACK(2);
746  tvalue = POP();
747  INPLACE1(<<,tvalue);
748  break;
749  case DW_OP_shr:
750  NEEDSTACK(2);
751  tvalue = POP();
752  INPLACE1(>>,tvalue);
753  break;
754  case DW_OP_shra:
755  NEEDSTACK(2);
756  tvalue = POP();
757  s64 = (int64_t)POP();
758  /* XXX: is this right? */
759  s64 = s64 >> tvalue;
760  PUSH((Dwarf_Word)s64);
761  break;
762  case DW_OP_xor:
763  INPLACE2(^);
764  break;
765  /*
766  * Control flow operations.
767  */
768  case DW_OP_le:
769  NEEDSTACK(2);
770  tvalue = POP();
771  INPLACE1SIGNED(<=,tvalue);
772  break;
773  case DW_OP_ge:
774  NEEDSTACK(2);
775  tvalue = POP();
776  INPLACE1SIGNED(>=,tvalue);
777  break;
778  case DW_OP_eq:
779  NEEDSTACK(2);
780  tvalue = POP();
781  INPLACE1SIGNED(==,tvalue);
782  break;
783  case DW_OP_lt:
784  NEEDSTACK(2);
785  tvalue = POP();
786  INPLACE1SIGNED(<,tvalue);
787  break;
788  case DW_OP_gt:
789  NEEDSTACK(2);
790  tvalue = POP();
791  INPLACE1SIGNED(>,tvalue);
792  break;
793  case DW_OP_ne:
794  NEEDSTACK(2);
795  tvalue = POP();
796  INPLACE1SIGNED(!=,tvalue);
797  break;
798  case DW_OP_skip:
799  NEED(2);
800  skipval = *(int16_t *)data;
801  /*
802  * NB: don't CONSUME(); we go back/forward from the op byte.
803  */
804  len += 1 - skipval;
805  data = (data - 1) + skipval;
806  if (data < origdata || data >= (origdata + origlen)) {
807  verror("bad %s skip distance %hd!\n",known_ops[op],skipval);
808  errno = ERANGE;
809  goto errout;
810  }
811  break;
812  case DW_OP_bra:
813  NEED(2);
814  skipval = *(int16_t *)data;
815  NEEDSTACK(1);
816  tvalue = POP();
817  if (tvalue != 0) {
818  /* Do the branch. */
819  len += 1 - skipval;
820  data = (data - 1) + skipval;
821  if (data < origdata || data >= (origdata + origlen)) {
822  verror("bad %s skip distance %hd!\n",known_ops[op],skipval);
823  errno = ERANGE;
824  goto errout;
825  }
826  }
827  else {
828  /* Don't branch; just CONSUME() and continue. */
829  CONSUME(2);
830  }
831  break;
832  case DW_OP_call2:
833  case DW_OP_call4:
834  case DW_OP_call_ref:
835  verror("known op %s not supported (calls not supported yet)!\n",
836  known_ops[op]);
837  errno = ENOTSUP;
838  goto errout;
839  /*
840  * Special operations.
841  */
842  case DW_OP_nop:
843  break;
844  /*
845  * Location operations that can be used to name a register as
846  * being the location of the location expression.
847  */
848  case DW_OP_reg0 ... DW_OP_reg31:
849  lreg = op - (uint8_t)DW_OP_reg0;
851  "%s -> 0x%"PRIu8"\n",known_ops[op],lreg);
852  break;
853  case DW_OP_regx:
854  NEED(1);
855  get_uleb128(u64,data); /* XXX check overrun */
856  CONSUME(data - start);
857  lreg = (REG)u64;
859  "%s -> 0x%"PRIu8"\n",known_ops[op],lreg);
860  break;
861  /*
862  * Implicit location descriptions.
863  */
864 #if _INT_ELFUTILS_VERSION > 141
865  case DW_OP_implicit_value:
866  NEED(1);
867  get_uleb128(u64,data); /* XXX check overrun */
868  CONSUME(data - start);
869  ldata = (unsigned char *)data;
870  llen = (int)u64;
871  CONSUME(u64);
872  break;
873  case DW_OP_stack_value:
874  NEEDSTACK(1);
875  break;
876 #endif
877  case DW_OP_piece:
878  case DW_OP_bit_piece:
879  verror("known op %s not supported (composite location descriptions"
880  " not supported in location expressions yet)!\n",
881  known_ops[op]);
882  errno = ENOTSUP;
883  goto errout;
884  /*
885  * GNU operations.
886  */
887 #if _INT_ELFUTILS_VERSION > 138
888  case DW_OP_GNU_push_tls_address:
889  case DW_OP_GNU_uninit:
890  case DW_OP_GNU_encoded_addr:
891 #if _INT_ELFUTILS_VERSION > 148
892  case DW_OP_GNU_implicit_pointer:
893  verror("known GNU op %s not supported!\n",known_ops[op]);
894  errno = ENOTSUP;
895  goto errout;
896 #endif
897 #endif
898  /* No Operand. */
899  default:
900  break;
901  }
902 
903  continue;
904  }
905 
906  /*
907  * Return.
908  */
909  out:
910  /*
911  * Check our last op to see how we should return!
912  */
913  switch (op) {
914  /*
915  * If we had named a register, return a register location.
916  */
917  case DW_OP_reg0 ... DW_OP_reg31:
918  case DW_OP_regx:
919  if (o_loc)
920  location_set_reg(o_loc,lreg);
921  if (overflowstack)
922  free(overflowstack);
923  return LOCTYPE_REG;
924  /*
925  * If we had found an implicit value, handle that.
926  */
927 #if _INT_ELFUTILS_VERSION > 141
928  case DW_OP_implicit_value:
929  if (o_loc)
930  location_set_implicit_data(o_loc,(char *)ldata,llen,0);
931  return LOCTYPE_IMPLICIT_DATA;
932  case DW_OP_stack_value:
933  if (stackdepth < 1) {
934  verror("stackdepth at return was %d; no implicit value available!\n",
935  stackdepth);
936  errno = EADDRNOTAVAIL;
937  if (overflowstack)
938  free(overflowstack);
939  return -LOCTYPE_IMPLICIT_WORD;
940  }
941  if (o_loc)
943  return LOCTYPE_IMPLICIT_WORD;
944 #endif
945  default:
946  break;
947  }
948 
949  /*
950  * If we reach here, we must be returning the top stack value as an
951  * address.
952  */
953  if (stackdepth < 1) {
954  verror("stackdepth at return was %d; no value available!\n",
955  stackdepth);
956  errno = EADDRNOTAVAIL;
957  if (overflowstack)
958  free(overflowstack);
959  return -LOCTYPE_ADDR;
960  }
961  if (o_loc)
962  location_set_addr(o_loc,(ADDR)PEEK());
963  if (overflowstack)
964  free(overflowstack);
965  return LOCTYPE_ADDR;
966 
967  /*
968  * The default error returned is -LOCTYPE_ADDR; unless we *know*
969  * that the resulting value of our expression will be LOCTYPE_REG or
970  * LOCTYPE_IMPLICIT_*, we can only assume the output *will* have
971  * been a LOCTYPE_ADDR.
972  */
973  errout:
974  if (overflowstack)
975  free(overflowstack);
976  return -LOCTYPE_ADDR;
977 }
978 
979 /*
980  * This originally came from readelf.c, but I rewrote much of it. Some
981  * operations can be evaluated statically to produce a fixed location
982  * that never changes, except for a simple offset. Others actually need
983  * runtime information. So, we evaluate everything that is simple to
984  * do, and punt the rest for runtime evaluation against actual machine
985  * data.
986  */
988  const unsigned char *data,Dwarf_Word len,
989  unsigned int attr) {
990  struct location *retval = NULL;
991  unsigned int addrsize = srd->addrsize;
992 
993  /* const unsigned int ref_size = vers < 3 ? addrsize : offset_size; */
994 
995  /* XXX: we can't get other_byte_order from dbg since we don't have
996  * the struct def for it... so we assume it's not a diff byte order
997  * than the phys host for now.
998  */
999  int obo = 0;
1000 
1001  /* save the originals for later for runtime computation if we need */
1002  const unsigned char *origdata = data;
1003  Dwarf_Word origlen = len;
1004 
1005  if (len == 0) {
1006  vwarn("empty dwarf block num!\n");
1007  goto errout;
1008  }
1009 
1010  retval = location_create();
1011 
1012 #define SNEED(n) if (len < (Dwarf_Word) (n)) goto errout
1013 #define SCONSUME(n) SNEED(n); else len -= (n)
1014 
1015 /* If this is the only thing in this op list, be done now. */
1016 #define ONLYOP(location,setter,...) \
1017  if (start == (origdata + 1) && len == 0) { \
1018  location_set_ ## setter((location), ## __VA_ARGS__); \
1019  goto out; \
1020  } \
1021  else { \
1022  vdebug(6,LA_DEBUG,LF_DWARFSOPS, \
1023  "unsupported %s op with other ops!\n",known_ops[op]); \
1024  }
1025 #define SOPCONSTU(size,tt) \
1026  SNEED(size); \
1027  u64 = (uint64_t)*((tt *)data); \
1028  data += size; \
1029  SCONSUME(size); \
1030  vdebug(6,LA_DEBUG,LF_DWARFSOPS,"%s -> 0x%" PRIuMAX "\n",known_ops[op],u64); \
1031  if (attr == DW_AT_data_member_location) { \
1032  ONLYOP(retval,member_offset,(int32_t)u64); \
1033  } \
1034  else { \
1035  vdebug(6,LA_DEBUG,LF_DWARFSOPS, \
1036  "assuming constXu is for loctype_addr!\n"); \
1037  ONLYOP(retval,addr,u64); \
1038  }
1039 #define SOPCONSTS(size,tt) \
1040  SNEED(size); \
1041  s64 = (int64_t)*((tt *)data); \
1042  data += size; \
1043  SCONSUME(size); \
1044  vdebug(6,LA_DEBUG,LF_DWARFSOPS,"%s -> 0x%" PRIxMAX "\n",known_ops[op],s64); \
1045  if (attr == DW_AT_data_member_location) { \
1046  ONLYOP(retval,member_offset,(int32_t)s64); \
1047  } \
1048  else { \
1049  vdebug(6,LA_DEBUG,LF_DWARFSOPS, \
1050  "assuming constXs is for loctype_addr!\n"); \
1051  ONLYOP(retval,addr,(uint64_t)s64); \
1052  }
1053 
1054  /*
1055  * Process the ops a little bit.
1056  */
1057  while (len-- > 0) {
1058  uint_fast8_t op = *data++;
1059  const unsigned char *start = data;
1060 
1061  if (op < (sizeof(known_ops) / sizeof(known_ops[0]))
1062  && known_ops[op] != NULL)
1064  "%s with len = %d\n",known_ops[op],len);
1065  else
1067  "unknown op 0x%hhx with len = %d\n",op,len);
1068 
1069  Dwarf_Word addr;
1070  uint8_t reg;
1071  uint64_t u64;
1072  int64_t s64;
1073 
1074  switch (op) {
1075  case DW_OP_addr:
1076  SNEED(addrsize);
1077  if (addrsize == 4)
1078  addr = read_4ubyte_unaligned(obo,data);
1079  else {
1080  assert(addrsize == 8);
1081  addr = read_8ubyte_unaligned(obo,data);
1082  }
1083  data += addrsize;
1084  SCONSUME(addrsize);
1086  "%s -> 0x%"PRIxDwarfWord"\n",known_ops[op],addr);
1087  if (start == (origdata + 1) && len == 0) {
1088  retval->loctype = LOCTYPE_ADDR;
1089  retval->l.addr = addr;
1090  goto out;
1091  }
1092  else {
1094  "unsupported %s op with other ops!\n",known_ops[op]);
1095  }
1096  //ONLYOP(retval,addr,((uint64_t)addr));
1097  break;
1098  case DW_OP_reg0...DW_OP_reg31:
1099  reg = op - (uint8_t)DW_OP_reg0;
1101  "%s -> 0x%"PRIu8"\n",known_ops[op],reg);
1102  ONLYOP(retval,reg,reg);
1103  break;
1104  //case DW_OP_piece:
1105  case DW_OP_regx:
1106  SNEED(1);
1107  get_uleb128(u64,data); /* XXX check overrun */
1108  SCONSUME(data - start);
1110  "%s -> 0x%"PRIu64"\n",known_ops[op],u64);
1111  ONLYOP(retval,reg,(uint8_t)u64);
1112  break;
1113  case DW_OP_plus_uconst:
1114  case DW_OP_constu:
1115  SNEED(1);
1116  get_uleb128(u64,data); /* XXX check overrun */
1117  SCONSUME(data - start);
1119  "%s -> 0x%"PRIu64"\n",known_ops[op],u64);
1120  if (attr == DW_AT_data_member_location) {
1121  ONLYOP(retval,member_offset,(int32_t)u64);
1122  }
1123  else {
1124  ONLYOP(retval,addr,(uint64_t)u64);
1126  "assuming known op %s is for loctype_addr!\n",
1127  known_ops[op]);
1128  }
1129  break;
1130  case DW_OP_consts:
1131  SNEED(1);
1132  get_sleb128(s64,data); /* XXX check overrun */
1133  SCONSUME(data - start);
1135  "%s -> %"PRIi64"\n",known_ops[op],s64);
1136  if (attr == DW_AT_data_member_location) {
1137  ONLYOP(retval,member_offset,(int32_t)s64);
1138  }
1139  else {
1140  ONLYOP(retval,addr,(uint64_t)s64);
1142  "assuming known op %s is for loctype_addr!\n",
1143  known_ops[op]);
1144  }
1145  break;
1146  case DW_OP_const1u:
1147  SOPCONSTU(1,uint8_t);
1148  break;
1149  case DW_OP_const2u:
1150  SOPCONSTU(2,uint16_t);
1151  break;
1152  case DW_OP_const4u:
1153  SOPCONSTU(4,uint32_t);
1154  break;
1155  case DW_OP_const8u:
1156  SOPCONSTU(8,uint64_t);
1157  break;
1158  case DW_OP_const1s:
1159  SOPCONSTS(1,int8_t);
1160  break;
1161  case DW_OP_const2s:
1162  SOPCONSTS(2,int16_t);
1163  break;
1164  case DW_OP_const4s:
1165  SOPCONSTS(4,int32_t);
1166  break;
1167  case DW_OP_const8s:
1168  SOPCONSTS(8,int64_t);
1169  break;
1170  case DW_OP_fbreg:
1171  SNEED(1);
1172  get_sleb128(s64,data); /* XXX check overrun */
1173  SCONSUME(data - start);
1175  "%s -> fbreg offset %"PRIi64"\n",known_ops[op],s64);
1176  ONLYOP(retval,fbreg_offset,s64);
1177  break;
1178  case DW_OP_breg0 ... DW_OP_breg31:
1179  SNEED(1);
1180  get_sleb128(s64,data); /* XXX check overrun */
1181  SCONSUME(data - start);
1183  "%s -> reg (%"PRIu8") offset %"PRIi64"\n",known_ops[op],
1184  (uint8_t)(op - DW_OP_breg0),s64);
1185  ONLYOP(retval,reg_offset,(uint8_t)(op - DW_OP_breg0),s64);
1186  break;
1187  case DW_OP_bregx:
1188  SNEED(2);
1189  get_uleb128(u64,data); /* XXX check overrun */
1190  get_sleb128(s64,data); /* XXX check overrun */
1191  SCONSUME(data - start);
1193  "%s -> reg%"PRIu8", offset %"PRIi64"\n",known_ops[op],
1194  (uint8_t)u64,s64);
1195  ONLYOP(retval,reg_offset,(uint8_t)u64,s64);
1196  break;
1197  default:
1198  /* No operand. */
1199  break;
1200  }
1201 
1202  continue;
1203  }
1204 
1205  vdebug(6,LA_DEBUG,LF_DWARFSOPS,"had to save dwarf ops for runtime!\n");
1206  location_set_runtime(retval,(char *)origdata,origlen,0);
1207 
1208  out:
1209  return retval;
1210 
1211  errout:
1212  if (retval)
1213  location_free(retval);
1214  return NULL;
1215 }
#define PEEK()
#define LOCATION_ADDR(loc)
Definition: dwdebug_priv.h:622
int(* getaddrsize)(struct location_ctxt *lctxt)
Definition: dwdebug_priv.h:710
#define INPLACE2(OP)
char * data
Definition: dwdebug_priv.h:605
#define vwarnopt(level, area, flags, format,...)
Definition: log.h:37
struct symbol * symbol_find_parent(struct symbol *symbol)
Definition: debug.c:3106
#define SNEED(n)
union location::@6 l
#define INPLACE1(OP, value)
int location_set_implicit_data(struct location *loc, char *data, int len, int nocopy)
Definition: location.c:128
#define OPCONSTS(size, tt)
#define SYMBOL_RX_FUNC(sym, rvar)
struct location_ops * ops
Definition: dwdebug_priv.h:744
#define PRIiREG
Definition: common.h:94
int(* relocate)(struct location_ctxt *lctxt, ADDR obj_addr, ADDR *real_addr)
Definition: dwdebug_priv.h:704
struct location * dwarf_get_static_ops(struct symbol_root_dwarf *srd, const unsigned char *data, Dwarf_Word len, unsigned int attr)
Definition: dwarf_expr.c:987
#define read_4ubyte_unaligned(obo, Addr)
#define CONSUME(n)
#define POP()
#define assert(x)
Definition: dlmalloc.c:1456
#define get_uleb128(var, addr)
Definition: memory-access.h:67
#define verror(format,...)
Definition: log.h:30
int location_ctxt_read_reg(struct location_ctxt *lctxt, REG reg, REGVAL *o_regval)
Definition: location.c:632
#define OPCONSTU(size, tt)
#define SOPCONSTU(size, tt)
#define vwarn(format,...)
Definition: log.h:33
#define LOCATION_WORD(loc)
Definition: dwdebug_priv.h:626
int location_set_implicit_word(struct location *loc, ADDR word)
Definition: location.c:119
void free(void *ptr)
Definition: debugserver.c:207
Definition: log.h:69
int location_set_reg(struct location *l, REG reg)
Definition: location.c:55
void location_free(struct location *location)
Definition: location.c:359
#define SOPCONSTS(size, tt)
#define SCONSUME(n)
#define ERRORDUMPSYMBOL_NL(s)
Definition: dwdebug_priv.h:54
int location_set_runtime(struct location *l, char *data, int len, int nocopy)
Definition: location.c:164
#define PICK(i)
int len
Definition: dumptarget.c:52
int location_set_addr(struct location *l, ADDR addr)
Definition: location.c:46
#define vdebug(devel, areas, flags, format,...)
Definition: log.h:302
const char * dwarf_op_string(unsigned int op)
Definition: dwarf_expr.c:207
loctype_t dwarf_location_resolve(const unsigned char *data, unsigned int len, struct location_ctxt *lctxt, struct symbol *symbol, struct location *o_loc)
Definition: dwarf_expr.c:213
#define PUSH(value)
struct location * location_create(void)
Definition: location.c:39
#define INPLACE1SIGNED(OP, value)
Definition: log.h:129
#define get_sleb128(var, addr)
Definition: memory-access.h:98
#define NEED(n)
int8_t REG
Definition: common.h:93
#define NEEDSTACK(n)
#define read_8ubyte_unaligned(obo, Addr)
uint32_t ADDR
Definition: common.h:64
loctype_t loctype
Definition: dwdebug_priv.h:585
#define PRIxADDR
Definition: common.h:67
#define LOCATION_REG(loc)
Definition: dwdebug_priv.h:623
loctype_t location_resolve(struct location *loc, struct location_ctxt *lctxt, struct symbol *symbol, struct location *o_loc)
Definition: location.c:825
#define PRIxDwarfWord
#define ONLYOP(location, setter,...)
#define SYMBOL_IS_FUNC(sym)
int(* readword)(struct location_ctxt *lctxt, ADDR real_addr, ADDR *pval)
Definition: dwdebug_priv.h:702
loctype_t
Definition: dwdebug.h:234