1 //===-- DWARFLocationDescription.cpp ----------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "DWARFLocationDescription.h"
11 #include "DWARFDefines.h"
12 #include "lldb/lldb-private.h"
13 #include "lldb/Core/Stream.h"
14
15
16 using namespace lldb_private;
17
18 static int print_dwarf_exp_op (Stream &s, const DataExtractor& data, lldb::offset_t *offset_ptr, int address_size, int dwarf_ref_size);
19
20 int
print_dwarf_expression(Stream & s,const DataExtractor & data,int address_size,int dwarf_ref_size,bool location_expression)21 print_dwarf_expression (Stream &s,
22 const DataExtractor& data,
23 int address_size,
24 int dwarf_ref_size,
25 bool location_expression)
26 {
27 int op_count = 0;
28 lldb::offset_t offset = 0;
29 while (data.ValidOffset(offset))
30 {
31 if (location_expression && op_count > 0)
32 {
33 // err (baton, "Dwarf location expressions may only have one operand!");
34 return 1;
35 }
36 if (op_count > 0)
37 {
38 s.PutCString(", ");
39 }
40 if (print_dwarf_exp_op (s, data, &offset, address_size, dwarf_ref_size) == 1)
41 return 1;
42 op_count++;
43 }
44
45 return 0;
46 }
47
48 static int
print_dwarf_exp_op(Stream & s,const DataExtractor & data,lldb::offset_t * offset_ptr,int address_size,int dwarf_ref_size)49 print_dwarf_exp_op (Stream &s,
50 const DataExtractor& data,
51 lldb::offset_t *offset_ptr,
52 int address_size,
53 int dwarf_ref_size)
54 {
55 uint8_t opcode = data.GetU8(offset_ptr);
56 DRC_class opcode_class;
57 uint64_t uint;
58 int64_t sint;
59
60 int size;
61
62 opcode_class = DW_OP_value_to_class (opcode) & (~DRC_DWARFv3);
63
64 s.Printf("%s ", DW_OP_value_to_name (opcode));
65
66 /* Does this take zero parameters? If so we can shortcut this function. */
67 if (opcode_class == DRC_ZEROOPERANDS)
68 return 0;
69
70 if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_bregx)
71 {
72 uint = data.GetULEB128(offset_ptr);
73 sint = data.GetSLEB128(offset_ptr);
74 s.Printf("%" PRIu64 " %" PRIi64, uint, sint);
75 return 0;
76 }
77 if (opcode_class != DRC_ONEOPERAND)
78 {
79 s.Printf("UNKNOWN OP %u", opcode);
80 return 1;
81 }
82
83 switch (opcode)
84 {
85 case DW_OP_addr: size = address_size; break;
86 case DW_OP_const1u: size = 1; break;
87 case DW_OP_const1s: size = -1; break;
88 case DW_OP_const2u: size = 2; break;
89 case DW_OP_const2s: size = -2; break;
90 case DW_OP_const4u: size = 4; break;
91 case DW_OP_const4s: size = -4; break;
92 case DW_OP_const8u: size = 8; break;
93 case DW_OP_const8s: size = -8; break;
94 case DW_OP_constu: size = 128; break;
95 case DW_OP_consts: size = -128; break;
96 case DW_OP_fbreg: size = -128; break;
97 case DW_OP_breg0:
98 case DW_OP_breg1:
99 case DW_OP_breg2:
100 case DW_OP_breg3:
101 case DW_OP_breg4:
102 case DW_OP_breg5:
103 case DW_OP_breg6:
104 case DW_OP_breg7:
105 case DW_OP_breg8:
106 case DW_OP_breg9:
107 case DW_OP_breg10:
108 case DW_OP_breg11:
109 case DW_OP_breg12:
110 case DW_OP_breg13:
111 case DW_OP_breg14:
112 case DW_OP_breg15:
113 case DW_OP_breg16:
114 case DW_OP_breg17:
115 case DW_OP_breg18:
116 case DW_OP_breg19:
117 case DW_OP_breg20:
118 case DW_OP_breg21:
119 case DW_OP_breg22:
120 case DW_OP_breg23:
121 case DW_OP_breg24:
122 case DW_OP_breg25:
123 case DW_OP_breg26:
124 case DW_OP_breg27:
125 case DW_OP_breg28:
126 case DW_OP_breg29:
127 case DW_OP_breg30:
128 case DW_OP_breg31:
129 size = -128; break;
130 case DW_OP_pick:
131 size = 1; break;
132 case DW_OP_deref_size:
133 size = 1; break;
134 case DW_OP_xderef_size:
135 size = 1; break;
136 case DW_OP_plus_uconst:
137 size = 128; break;
138 case DW_OP_skip:
139 size = -2; break;
140 case DW_OP_bra:
141 size = -2; break;
142 case DW_OP_call2:
143 size = 2; break;
144 case DW_OP_call4:
145 size = 4; break;
146 case DW_OP_call_ref:
147 size = dwarf_ref_size; break;
148 case DW_OP_piece:
149 size = 128; break;
150 case DW_OP_regx:
151 size = 128; break;
152 default:
153 s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode);
154 return 1;
155 }
156
157 switch (size)
158 {
159 case -1: sint = (int8_t) data.GetU8(offset_ptr); s.Printf("%+" PRIi64, sint); break;
160 case -2: sint = (int16_t) data.GetU16(offset_ptr); s.Printf("%+" PRIi64, sint); break;
161 case -4: sint = (int32_t) data.GetU32(offset_ptr); s.Printf("%+" PRIi64, sint); break;
162 case -8: sint = (int64_t) data.GetU64(offset_ptr); s.Printf("%+" PRIi64, sint); break;
163 case -128: sint = data.GetSLEB128(offset_ptr); s.Printf("%+" PRIi64, sint); break;
164 case 1: uint = data.GetU8(offset_ptr); s.Printf("0x%2.2" PRIx64, uint); break;
165 case 2: uint = data.GetU16(offset_ptr); s.Printf("0x%4.4" PRIx64, uint); break;
166 case 4: uint = data.GetU32(offset_ptr); s.Printf("0x%8.8" PRIx64, uint); break;
167 case 8: uint = data.GetU64(offset_ptr); s.Printf("0x%16.16" PRIx64, uint); break;
168 case 128: uint = data.GetULEB128(offset_ptr); s.Printf("0x%" PRIx64, uint); break;
169 }
170
171 return 0;
172 }
173