1254721Semaste//===-- DWARFLocationDescription.cpp ----------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "DWARFLocationDescription.h"
11254721Semaste#include "DWARFDefines.h"
12254721Semaste#include "lldb/lldb-private.h"
13254721Semaste#include "lldb/Core/Stream.h"
14254721Semaste
15254721Semaste
16254721Semasteusing namespace lldb_private;
17254721Semaste
18263363Semastestatic int print_dwarf_exp_op (Stream &s, const DWARFDataExtractor& data, lldb::offset_t *offset_ptr, int address_size, int dwarf_ref_size);
19254721Semaste
20254721Semasteint
21254721Semasteprint_dwarf_expression (Stream &s,
22263363Semaste                        const DWARFDataExtractor& data,
23254721Semaste                        int address_size,
24254721Semaste                        int dwarf_ref_size,
25254721Semaste                        bool location_expression)
26254721Semaste{
27254721Semaste    int op_count = 0;
28254721Semaste    lldb::offset_t offset = 0;
29254721Semaste    while (data.ValidOffset(offset))
30254721Semaste    {
31254721Semaste        if (location_expression && op_count > 0)
32254721Semaste        {
33254721Semaste            //  err (baton, "Dwarf location expressions may only have one operand!");
34254721Semaste            return 1;
35254721Semaste        }
36254721Semaste        if (op_count > 0)
37254721Semaste        {
38254721Semaste            s.PutCString(", ");
39254721Semaste        }
40254721Semaste        if (print_dwarf_exp_op (s, data, &offset, address_size, dwarf_ref_size) == 1)
41254721Semaste            return 1;
42254721Semaste        op_count++;
43254721Semaste    }
44254721Semaste
45254721Semaste    return 0;
46254721Semaste}
47254721Semaste
48254721Semastestatic int
49254721Semasteprint_dwarf_exp_op (Stream &s,
50263363Semaste                    const DWARFDataExtractor& data,
51254721Semaste                    lldb::offset_t *offset_ptr,
52254721Semaste                    int address_size,
53254721Semaste                    int dwarf_ref_size)
54254721Semaste{
55254721Semaste    uint8_t opcode = data.GetU8(offset_ptr);
56254721Semaste    DRC_class opcode_class;
57254721Semaste    uint64_t  uint;
58254721Semaste    int64_t   sint;
59254721Semaste
60254721Semaste    int size;
61254721Semaste
62254721Semaste    opcode_class = DW_OP_value_to_class (opcode) & (~DRC_DWARFv3);
63254721Semaste
64254721Semaste    s.Printf("%s ", DW_OP_value_to_name (opcode));
65254721Semaste
66254721Semaste    /* Does this take zero parameters?  If so we can shortcut this function.  */
67254721Semaste    if (opcode_class == DRC_ZEROOPERANDS)
68254721Semaste        return 0;
69254721Semaste
70254721Semaste    if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_bregx)
71254721Semaste    {
72254721Semaste        uint = data.GetULEB128(offset_ptr);
73254721Semaste        sint = data.GetSLEB128(offset_ptr);
74254721Semaste        s.Printf("%" PRIu64 " %" PRIi64, uint, sint);
75254721Semaste        return 0;
76254721Semaste    }
77254721Semaste    if (opcode_class != DRC_ONEOPERAND)
78254721Semaste    {
79254721Semaste        s.Printf("UNKNOWN OP %u", opcode);
80254721Semaste        return 1;
81254721Semaste    }
82254721Semaste
83254721Semaste    switch (opcode)
84254721Semaste    {
85254721Semaste        case DW_OP_addr:    size = address_size;    break;
86254721Semaste        case DW_OP_const1u: size = 1;               break;
87254721Semaste        case DW_OP_const1s: size = -1;              break;
88254721Semaste        case DW_OP_const2u: size = 2;               break;
89254721Semaste        case DW_OP_const2s: size = -2;              break;
90254721Semaste        case DW_OP_const4u: size = 4;               break;
91254721Semaste        case DW_OP_const4s: size = -4;              break;
92254721Semaste        case DW_OP_const8u: size = 8;               break;
93254721Semaste        case DW_OP_const8s: size = -8;              break;
94254721Semaste        case DW_OP_constu:  size = 128;             break;
95254721Semaste        case DW_OP_consts:  size = -128;            break;
96254721Semaste        case DW_OP_fbreg:   size = -128;            break;
97254721Semaste        case DW_OP_breg0:
98254721Semaste        case DW_OP_breg1:
99254721Semaste        case DW_OP_breg2:
100254721Semaste        case DW_OP_breg3:
101254721Semaste        case DW_OP_breg4:
102254721Semaste        case DW_OP_breg5:
103254721Semaste        case DW_OP_breg6:
104254721Semaste        case DW_OP_breg7:
105254721Semaste        case DW_OP_breg8:
106254721Semaste        case DW_OP_breg9:
107254721Semaste        case DW_OP_breg10:
108254721Semaste        case DW_OP_breg11:
109254721Semaste        case DW_OP_breg12:
110254721Semaste        case DW_OP_breg13:
111254721Semaste        case DW_OP_breg14:
112254721Semaste        case DW_OP_breg15:
113254721Semaste        case DW_OP_breg16:
114254721Semaste        case DW_OP_breg17:
115254721Semaste        case DW_OP_breg18:
116254721Semaste        case DW_OP_breg19:
117254721Semaste        case DW_OP_breg20:
118254721Semaste        case DW_OP_breg21:
119254721Semaste        case DW_OP_breg22:
120254721Semaste        case DW_OP_breg23:
121254721Semaste        case DW_OP_breg24:
122254721Semaste        case DW_OP_breg25:
123254721Semaste        case DW_OP_breg26:
124254721Semaste        case DW_OP_breg27:
125254721Semaste        case DW_OP_breg28:
126254721Semaste        case DW_OP_breg29:
127254721Semaste        case DW_OP_breg30:
128254721Semaste        case DW_OP_breg31:
129254721Semaste            size = -128; break;
130254721Semaste        case DW_OP_pick:
131254721Semaste            size = 1;       break;
132254721Semaste        case DW_OP_deref_size:
133254721Semaste            size = 1;       break;
134254721Semaste        case DW_OP_xderef_size:
135254721Semaste            size = 1;       break;
136254721Semaste        case DW_OP_plus_uconst:
137254721Semaste            size = 128;     break;
138254721Semaste        case DW_OP_skip:
139254721Semaste            size = -2;      break;
140254721Semaste        case DW_OP_bra:
141254721Semaste            size = -2;      break;
142254721Semaste        case DW_OP_call2:
143254721Semaste            size = 2;       break;
144254721Semaste        case DW_OP_call4:
145254721Semaste            size = 4;       break;
146254721Semaste        case DW_OP_call_ref:
147254721Semaste            size = dwarf_ref_size;  break;
148254721Semaste        case DW_OP_piece:
149254721Semaste            size = 128; break;
150254721Semaste        case DW_OP_regx:
151254721Semaste            size = 128; break;
152254721Semaste        default:
153254721Semaste            s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode);
154254721Semaste            return 1;
155254721Semaste    }
156254721Semaste
157254721Semaste    switch (size)
158254721Semaste    {
159254721Semaste    case -1:    sint = (int8_t)     data.GetU8(offset_ptr);     s.Printf("%+" PRIi64, sint); break;
160254721Semaste    case -2:    sint = (int16_t)    data.GetU16(offset_ptr);    s.Printf("%+" PRIi64, sint); break;
161254721Semaste    case -4:    sint = (int32_t)    data.GetU32(offset_ptr);    s.Printf("%+" PRIi64, sint); break;
162254721Semaste    case -8:    sint = (int64_t)    data.GetU64(offset_ptr);    s.Printf("%+" PRIi64, sint); break;
163254721Semaste    case -128:  sint = data.GetSLEB128(offset_ptr);             s.Printf("%+" PRIi64, sint); break;
164254721Semaste    case 1:     uint = data.GetU8(offset_ptr);                  s.Printf("0x%2.2" PRIx64, uint); break;
165254721Semaste    case 2:     uint = data.GetU16(offset_ptr);                 s.Printf("0x%4.4" PRIx64, uint); break;
166254721Semaste    case 4:     uint = data.GetU32(offset_ptr);                 s.Printf("0x%8.8" PRIx64, uint); break;
167254721Semaste    case 8:     uint = data.GetU64(offset_ptr);                 s.Printf("0x%16.16" PRIx64, uint); break;
168254721Semaste    case 128:   uint = data.GetULEB128(offset_ptr);             s.Printf("0x%" PRIx64, uint); break;
169254721Semaste    }
170254721Semaste
171254721Semaste    return 0;
172254721Semaste}
173