33 #include <elfutils/libebl.h>
34 #include <elfutils/libdw.h>
35 #include <elfutils/libdwfl.h>
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",
54 [DW_OP_drop] =
"drop",
55 [DW_OP_over] =
"over",
56 [DW_OP_pick] =
"pick",
57 [DW_OP_swap] =
"swap",
59 [DW_OP_xderef] =
"xderef",
63 [DW_OP_minus] =
"minus",
69 [DW_OP_plus] =
"plus",
70 [DW_OP_plus_uconst] =
"plus_uconst",
73 [DW_OP_shra] =
"shra",
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",
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",
198 #if _INT_ELFUTILS_VERSION > 141
199 [DW_OP_implicit_value] =
"implicit_value",
200 [DW_OP_stack_value] =
"stack_value",
202 #if _INT_ELFUTILS_VERSION > 148
203 [DW_OP_GNU_implicit_pointer] =
"GNU_implicit_pointer",
208 if (op < (
sizeof(known_ops) /
sizeof(known_ops[0])))
209 return known_ops[op];
216 unsigned int addrsize = 0;
227 const unsigned char *origdata = data;
234 Dwarf_Word stack[16];
235 Dwarf_Word *overflowstack = NULL;
236 int overflowstacklen = 0;
240 if (!lctxt || !lctxt->
ops) {
248 vwarn(
"empty dwarf block num!\n");
263 addrsize =
sizeof(Dwarf_Word);
266 if (len < (n)) goto errout
268 NEED (n); else len -= (n)
269 #define NEEDSTACK(n) \
271 if (n > stackdepth) { \
272 verror("op %s needed %d stack values, but only %d available!\n", \
273 known_ops[op],(n),stackdepth); \
277 #define PUSH(value) \
279 if (overflowstack) { \
280 if (stackdepth == overflowstacklen) { \
282 realloc(overflowstack, \
283 (overflowstacklen + 4) * sizeof(Dwarf_Word)); \
284 overflowstacklen += 4; \
286 overflowstack[stackdepth] = value; \
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; \
295 stack[stackdepth] = value; \
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) \
309 overflowstack[stackdepth - 1] = \
310 overflowstack[stackdepth - 1] OP (value); \
312 stack[stackdepth - 1] = \
313 stack[stackdepth - 1] OP (value); \
315 #define INPLACE1SIGNED(OP,value) \
319 overflowstack[stackdepth - 1] = (Dwarf_Word) \
320 ((int64_t)overflowstack[stackdepth - 1] OP (int64_t)(value)); \
322 stack[stackdepth - 1] = (Dwarf_Word) \
323 ((int64_t)stack[stackdepth - 1] OP (int64_t)(value)); \
325 #define INPLACE1UNARY(OP) \
329 overflowstack[stackdepth - 1] = \
330 OP overflowstack[stackdepth - 1]; \
332 stack[stackdepth - 1] = \
333 OP stack[stackdepth - 1]; \
335 #define INPLACE2(OP) \
339 overflowstack[stackdepth - 2] = \
340 overflowstack[stackdepth - 2] OP overflowstack[stackdepth - 1]; \
342 stack[stackdepth - 2] = \
343 stack[stackdepth - 1] OP stack[stackdepth - 2]; \
346 #define OPCONSTU(size,tt) \
348 u64 = (uint64_t)*((tt *)data); \
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) \
356 s64 = (int64_t)*((tt *)data); \
359 vdebug(6,LA_DEBUG,LF_DWARFOPS,"%s -> 0x%"PRIx64"\n", \
360 known_ops[op],s64); \
361 PUSH((Dwarf_Word)s64)
367 unsigned char *ldata = NULL;
373 const unsigned char *start = data;
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);
381 "unknown op 0x%hhx with len = %d\n",op,len);
392 struct symbol *parent;
398 #define PRIxDwarfWord PRIx64
400 #define PRIxDwarfWord PRIx32
407 case DW_OP_lit0 ... DW_OP_lit31:
408 PUSH(op - (uint8_t)DW_OP_lit0);
430 if (!lops->
relocate(lctxt,taddr,&taddr))
431 addr = (Dwarf_Word)taddr;
464 "%s -> 0x%"PRIu64
"\n",known_ops[op],u64);
465 PUSH((Dwarf_Word)u64);
473 PUSH((Dwarf_Word)s64);
483 "%s -> fbreg offset %"PRIi64
"\n",known_ops[op],s64);
486 verror(
"cannot find frame_base; no symbol supplied!\n");
500 verror(
"cannot find frame_base; no parent function contains ");
507 if (!pf || !pf->fbloc) {
508 verror(
"cannot find frame_base; no frame base in parent"
516 memset(&tloc,0,
sizeof(tloc));
522 verror(
"cannot read reg %"PRIiREG" to get frame_base value\n",
534 verror(
"cannot get frame base value: %s (%s)\n",
535 strerror(errno),LOCTYPE(rc));
540 "frame_base 0x%"PRIxADDR",fboffset %"PRIi64
"\n",
543 PUSH((Dwarf_Word)(taddr + s64));
545 case DW_OP_breg0 ... DW_OP_breg31:
550 "%s -> reg (%hhd) offset %"PRIi64
"\n",
551 known_ops[op],(uint8_t)(op - DW_OP_breg0),s64);
554 treg = (op - DW_OP_breg0);
564 known_ops[op],treg,s64,(Dwarf_Word)(taddr + s64));
566 PUSH((Dwarf_Word)(taddr + s64));
574 "%s -> reg%" PRId8
", offset %"PRIi64
"\n",
575 known_ops[op],(uint8_t)u64,s64);
587 "%s -> reg (%hhd) offset %"PRIi64
" = 0x%"PRIxDwarfWord
"\n",
588 known_ops[op],treg,s64,(Dwarf_Word)(taddr + s64));
590 PUSH((Dwarf_Word)(taddr + s64));
606 index = *((uint8_t *)data);
609 tvalue =
PICK(index);
620 tvalue = overflowstack[stackdepth - 1];
621 overflowstack[stackdepth - 1] = overflowstack[stackdepth - 2];
622 overflowstack[stackdepth - 2] = tvalue;
625 tvalue = stack[stackdepth - 1];
626 stack[stackdepth - 1] = stack[stackdepth - 2];
627 stack[stackdepth - 2] = tvalue;
633 tvalue = overflowstack[stackdepth - 1];
634 overflowstack[stackdepth - 1] = overflowstack[stackdepth - 2];
635 overflowstack[stackdepth - 2] = overflowstack[stackdepth - 3];
636 overflowstack[stackdepth - 3] = tvalue;
639 tvalue = stack[stackdepth - 1];
640 stack[stackdepth - 1] = stack[stackdepth - 2];
641 stack[stackdepth - 2] = stack[stackdepth - 3];
642 stack[stackdepth - 3] = tvalue;
649 verror(
"cannot read ptr to compute %s op; no location op!\n",
654 else if (lops->
readword(lctxt,taddr,&taddr)) {
656 taddr,known_ops[op]);
659 PUSH((Dwarf_Word)taddr);
661 case DW_OP_deref_size:
663 number = *(uint8_t *)data;
668 verror(
"cannot read ptr to compute %s op; no location op!\n",
673 else if (lops->
readword(lctxt,taddr,&taddr)) {
675 taddr,known_ops[op]);
680 memcpy(&addr,&taddr,number);
684 case DW_OP_xderef_size:
685 verror(
"%s op unsupported (we don't know multiple addrspaces)!\n",
689 case DW_OP_push_object_address:
690 case DW_OP_form_tls_address:
691 verror(
"%s op unsupported!\n",known_ops[op]);
694 case DW_OP_call_frame_cfa:
695 verror(
"%s op unsupported (no CFA support yet)!\n",known_ops[op]);
704 s64 = (int64_t)tvalue;
706 tvalue = (uint64_t)-s64;
707 PUSH((Dwarf_Word)tvalue);
726 s64 = (int64_t)
POP();
727 u64 = (uint64_t)-s64;
728 PUSH((Dwarf_Word)u64);
736 case DW_OP_plus_uconst:
741 "%s -> 0x%"PRIu64
"\n",known_ops[op],u64);
757 s64 = (int64_t)
POP();
760 PUSH((Dwarf_Word)s64);
800 skipval = *(int16_t *)data;
805 data = (data - 1) + skipval;
806 if (data < origdata || data >= (origdata + origlen)) {
807 verror(
"bad %s skip distance %hd!\n",known_ops[op],skipval);
814 skipval = *(int16_t *)data;
820 data = (data - 1) + skipval;
821 if (data < origdata || data >= (origdata + origlen)) {
822 verror(
"bad %s skip distance %hd!\n",known_ops[op],skipval);
835 verror(
"known op %s not supported (calls not supported yet)!\n",
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);
859 "%s -> 0x%"PRIu8
"\n",known_ops[op],lreg);
864 #if _INT_ELFUTILS_VERSION > 141
865 case DW_OP_implicit_value:
869 ldata = (
unsigned char *)data;
873 case DW_OP_stack_value:
878 case DW_OP_bit_piece:
879 verror(
"known op %s not supported (composite location descriptions"
880 " not supported in location expressions yet)!\n",
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]);
917 case DW_OP_reg0 ... DW_OP_reg31:
927 #if _INT_ELFUTILS_VERSION > 141
928 case DW_OP_implicit_value:
932 case DW_OP_stack_value:
933 if (stackdepth < 1) {
934 verror(
"stackdepth at return was %d; no implicit value available!\n",
936 errno = EADDRNOTAVAIL;
953 if (stackdepth < 1) {
954 verror(
"stackdepth at return was %d; no value available!\n",
956 errno = EADDRNOTAVAIL;
988 const unsigned char *
data,Dwarf_Word
len,
991 unsigned int addrsize = srd->
addrsize;
1002 const unsigned char *origdata =
data;
1003 Dwarf_Word origlen =
len;
1006 vwarn(
"empty dwarf block num!\n");
1012 #define SNEED(n) if (len < (Dwarf_Word) (n)) goto errout
1013 #define SCONSUME(n) SNEED(n); else len -= (n)
1016 #define ONLYOP(location,setter,...) \
1017 if (start == (origdata + 1) && len == 0) { \
1018 location_set_ ## setter((location), ## __VA_ARGS__); \
1022 vdebug(6,LA_DEBUG,LF_DWARFSOPS, \
1023 "unsupported %s op with other ops!\n",known_ops[op]); \
1025 #define SOPCONSTU(size,tt) \
1027 u64 = (uint64_t)*((tt *)data); \
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); \
1035 vdebug(6,LA_DEBUG,LF_DWARFSOPS, \
1036 "assuming constXu is for loctype_addr!\n"); \
1037 ONLYOP(retval,addr,u64); \
1039 #define SOPCONSTS(size,tt) \
1041 s64 = (int64_t)*((tt *)data); \
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); \
1049 vdebug(6,LA_DEBUG,LF_DWARFSOPS, \
1050 "assuming constXs is for loctype_addr!\n"); \
1051 ONLYOP(retval,addr,(uint64_t)s64); \
1058 uint_fast8_t op = *data++;
1059 const unsigned char *start =
data;
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);
1067 "unknown op 0x%hhx with len = %d\n",op,len);
1087 if (start == (origdata + 1) && len == 0) {
1094 "unsupported %s op with other ops!\n",known_ops[op]);
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);
1110 "%s -> 0x%"PRIu64
"\n",known_ops[op],u64);
1111 ONLYOP(retval,reg,(uint8_t)u64);
1113 case DW_OP_plus_uconst:
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);
1124 ONLYOP(retval,addr,(uint64_t)u64);
1126 "assuming known op %s is for loctype_addr!\n",
1135 "%s -> %"PRIi64
"\n",known_ops[op],s64);
1136 if (attr == DW_AT_data_member_location) {
1137 ONLYOP(retval,member_offset,(int32_t)s64);
1140 ONLYOP(retval,addr,(uint64_t)s64);
1142 "assuming known op %s is for loctype_addr!\n",
1175 "%s -> fbreg offset %"PRIi64
"\n",known_ops[op],s64);
1176 ONLYOP(retval,fbreg_offset,s64);
1178 case DW_OP_breg0 ... DW_OP_breg31:
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);
1193 "%s -> reg%"PRIu8
", offset %"PRIi64
"\n",known_ops[op],
1195 ONLYOP(retval,reg_offset,(uint8_t)u64,s64);
#define LOCATION_ADDR(loc)
int(* getaddrsize)(struct location_ctxt *lctxt)
#define vwarnopt(level, area, flags, format,...)
struct symbol * symbol_find_parent(struct symbol *symbol)
#define INPLACE1(OP, value)
int location_set_implicit_data(struct location *loc, char *data, int len, int nocopy)
#define OPCONSTS(size, tt)
#define SYMBOL_RX_FUNC(sym, rvar)
struct location_ops * ops
int(* relocate)(struct location_ctxt *lctxt, ADDR obj_addr, ADDR *real_addr)
struct location * dwarf_get_static_ops(struct symbol_root_dwarf *srd, const unsigned char *data, Dwarf_Word len, unsigned int attr)
#define read_4ubyte_unaligned(obo, Addr)
#define get_uleb128(var, addr)
#define verror(format,...)
int location_ctxt_read_reg(struct location_ctxt *lctxt, REG reg, REGVAL *o_regval)
#define OPCONSTU(size, tt)
#define SOPCONSTU(size, tt)
#define vwarn(format,...)
#define LOCATION_WORD(loc)
int location_set_implicit_word(struct location *loc, ADDR word)
int location_set_reg(struct location *l, REG reg)
void location_free(struct location *location)
#define SOPCONSTS(size, tt)
#define ERRORDUMPSYMBOL_NL(s)
int location_set_runtime(struct location *l, char *data, int len, int nocopy)
int location_set_addr(struct location *l, ADDR addr)
#define vdebug(devel, areas, flags, format,...)
const char * dwarf_op_string(unsigned int op)
loctype_t dwarf_location_resolve(const unsigned char *data, unsigned int len, struct location_ctxt *lctxt, struct symbol *symbol, struct location *o_loc)
struct location * location_create(void)
#define INPLACE1SIGNED(OP, value)
#define get_sleb128(var, addr)
#define read_8ubyte_unaligned(obo, Addr)
#define LOCATION_REG(loc)
loctype_t location_resolve(struct location *loc, struct location_ctxt *lctxt, struct symbol *symbol, struct location *o_loc)
#define ONLYOP(location, setter,...)
#define SYMBOL_IS_FUNC(sym)
int(* readword)(struct location_ctxt *lctxt, ADDR real_addr, ADDR *pval)