xref: /aosp_15_r20/external/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- DWARFFormValue.cpp ------------------------------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker 
10*9880d681SAndroid Build Coastguard Worker #include "SyntaxHighlighting.h"
11*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/ArrayRef.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringRef.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/DWARF/DWARFContext.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Dwarf.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Format.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
20*9880d681SAndroid Build Coastguard Worker #include <cassert>
21*9880d681SAndroid Build Coastguard Worker #include <limits>
22*9880d681SAndroid Build Coastguard Worker using namespace llvm;
23*9880d681SAndroid Build Coastguard Worker using namespace dwarf;
24*9880d681SAndroid Build Coastguard Worker using namespace syntax;
25*9880d681SAndroid Build Coastguard Worker 
26*9880d681SAndroid Build Coastguard Worker namespace {
getRefAddrSize(uint8_t AddrSize,uint16_t Version)27*9880d681SAndroid Build Coastguard Worker uint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) {
28*9880d681SAndroid Build Coastguard Worker   // FIXME: Support DWARF64.
29*9880d681SAndroid Build Coastguard Worker   return (Version == 2) ? AddrSize : 4;
30*9880d681SAndroid Build Coastguard Worker }
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker template <uint8_t AddrSize, uint8_t RefAddrSize>
makeFixedFormSizesArrayRef()33*9880d681SAndroid Build Coastguard Worker ArrayRef<uint8_t> makeFixedFormSizesArrayRef() {
34*9880d681SAndroid Build Coastguard Worker   static const uint8_t sizes[] = {
35*9880d681SAndroid Build Coastguard Worker     0,           // 0x00 unused
36*9880d681SAndroid Build Coastguard Worker     AddrSize,    // 0x01 DW_FORM_addr
37*9880d681SAndroid Build Coastguard Worker     0,           // 0x02 unused
38*9880d681SAndroid Build Coastguard Worker     0,           // 0x03 DW_FORM_block2
39*9880d681SAndroid Build Coastguard Worker     0,           // 0x04 DW_FORM_block4
40*9880d681SAndroid Build Coastguard Worker     2,           // 0x05 DW_FORM_data2
41*9880d681SAndroid Build Coastguard Worker     4,           // 0x06 DW_FORM_data4
42*9880d681SAndroid Build Coastguard Worker     8,           // 0x07 DW_FORM_data8
43*9880d681SAndroid Build Coastguard Worker     0,           // 0x08 DW_FORM_string
44*9880d681SAndroid Build Coastguard Worker     0,           // 0x09 DW_FORM_block
45*9880d681SAndroid Build Coastguard Worker     0,           // 0x0a DW_FORM_block1
46*9880d681SAndroid Build Coastguard Worker     1,           // 0x0b DW_FORM_data1
47*9880d681SAndroid Build Coastguard Worker     1,           // 0x0c DW_FORM_flag
48*9880d681SAndroid Build Coastguard Worker     0,           // 0x0d DW_FORM_sdata
49*9880d681SAndroid Build Coastguard Worker     4,           // 0x0e DW_FORM_strp
50*9880d681SAndroid Build Coastguard Worker     0,           // 0x0f DW_FORM_udata
51*9880d681SAndroid Build Coastguard Worker     RefAddrSize, // 0x10 DW_FORM_ref_addr
52*9880d681SAndroid Build Coastguard Worker     1,           // 0x11 DW_FORM_ref1
53*9880d681SAndroid Build Coastguard Worker     2,           // 0x12 DW_FORM_ref2
54*9880d681SAndroid Build Coastguard Worker     4,           // 0x13 DW_FORM_ref4
55*9880d681SAndroid Build Coastguard Worker     8,           // 0x14 DW_FORM_ref8
56*9880d681SAndroid Build Coastguard Worker     0,           // 0x15 DW_FORM_ref_udata
57*9880d681SAndroid Build Coastguard Worker     0,           // 0x16 DW_FORM_indirect
58*9880d681SAndroid Build Coastguard Worker     4,           // 0x17 DW_FORM_sec_offset
59*9880d681SAndroid Build Coastguard Worker     0,           // 0x18 DW_FORM_exprloc
60*9880d681SAndroid Build Coastguard Worker     0,           // 0x19 DW_FORM_flag_present
61*9880d681SAndroid Build Coastguard Worker   };
62*9880d681SAndroid Build Coastguard Worker   return makeArrayRef(sizes);
63*9880d681SAndroid Build Coastguard Worker }
64*9880d681SAndroid Build Coastguard Worker }
65*9880d681SAndroid Build Coastguard Worker 
getFixedFormSizes(uint8_t AddrSize,uint16_t Version)66*9880d681SAndroid Build Coastguard Worker ArrayRef<uint8_t> DWARFFormValue::getFixedFormSizes(uint8_t AddrSize,
67*9880d681SAndroid Build Coastguard Worker                                                     uint16_t Version) {
68*9880d681SAndroid Build Coastguard Worker   uint8_t RefAddrSize = getRefAddrSize(AddrSize, Version);
69*9880d681SAndroid Build Coastguard Worker   if (AddrSize == 4 && RefAddrSize == 4)
70*9880d681SAndroid Build Coastguard Worker     return makeFixedFormSizesArrayRef<4, 4>();
71*9880d681SAndroid Build Coastguard Worker   if (AddrSize == 4 && RefAddrSize == 8)
72*9880d681SAndroid Build Coastguard Worker     return makeFixedFormSizesArrayRef<4, 8>();
73*9880d681SAndroid Build Coastguard Worker   if (AddrSize == 8 && RefAddrSize == 4)
74*9880d681SAndroid Build Coastguard Worker     return makeFixedFormSizesArrayRef<8, 4>();
75*9880d681SAndroid Build Coastguard Worker   if (AddrSize == 8 && RefAddrSize == 8)
76*9880d681SAndroid Build Coastguard Worker     return makeFixedFormSizesArrayRef<8, 8>();
77*9880d681SAndroid Build Coastguard Worker   return None;
78*9880d681SAndroid Build Coastguard Worker }
79*9880d681SAndroid Build Coastguard Worker 
80*9880d681SAndroid Build Coastguard Worker static const DWARFFormValue::FormClass DWARF4FormClasses[] = {
81*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Unknown,       // 0x0
82*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Address,       // 0x01 DW_FORM_addr
83*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Unknown,       // 0x02 unused
84*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Block,         // 0x03 DW_FORM_block2
85*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Block,         // 0x04 DW_FORM_block4
86*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Constant,      // 0x05 DW_FORM_data2
87*9880d681SAndroid Build Coastguard Worker   // --- These can be FC_SectionOffset in DWARF3 and below:
88*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Constant,      // 0x06 DW_FORM_data4
89*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Constant,      // 0x07 DW_FORM_data8
90*9880d681SAndroid Build Coastguard Worker   // ---
91*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_String,        // 0x08 DW_FORM_string
92*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Block,         // 0x09 DW_FORM_block
93*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Block,         // 0x0a DW_FORM_block1
94*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Constant,      // 0x0b DW_FORM_data1
95*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Flag,          // 0x0c DW_FORM_flag
96*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Constant,      // 0x0d DW_FORM_sdata
97*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_String,        // 0x0e DW_FORM_strp
98*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Constant,      // 0x0f DW_FORM_udata
99*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Reference,     // 0x10 DW_FORM_ref_addr
100*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Reference,     // 0x11 DW_FORM_ref1
101*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Reference,     // 0x12 DW_FORM_ref2
102*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Reference,     // 0x13 DW_FORM_ref4
103*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Reference,     // 0x14 DW_FORM_ref8
104*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Reference,     // 0x15 DW_FORM_ref_udata
105*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Indirect,      // 0x16 DW_FORM_indirect
106*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_SectionOffset, // 0x17 DW_FORM_sec_offset
107*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Exprloc,       // 0x18 DW_FORM_exprloc
108*9880d681SAndroid Build Coastguard Worker   DWARFFormValue::FC_Flag,          // 0x19 DW_FORM_flag_present
109*9880d681SAndroid Build Coastguard Worker };
110*9880d681SAndroid Build Coastguard Worker 
isFormClass(DWARFFormValue::FormClass FC) const111*9880d681SAndroid Build Coastguard Worker bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {
112*9880d681SAndroid Build Coastguard Worker   // First, check DWARF4 form classes.
113*9880d681SAndroid Build Coastguard Worker   if (Form < makeArrayRef(DWARF4FormClasses).size() &&
114*9880d681SAndroid Build Coastguard Worker       DWARF4FormClasses[Form] == FC)
115*9880d681SAndroid Build Coastguard Worker     return true;
116*9880d681SAndroid Build Coastguard Worker   // Check more forms from DWARF4 and DWARF5 proposals.
117*9880d681SAndroid Build Coastguard Worker   switch (Form) {
118*9880d681SAndroid Build Coastguard Worker   case DW_FORM_ref_sig8:
119*9880d681SAndroid Build Coastguard Worker   case DW_FORM_GNU_ref_alt:
120*9880d681SAndroid Build Coastguard Worker     return (FC == FC_Reference);
121*9880d681SAndroid Build Coastguard Worker   case DW_FORM_GNU_addr_index:
122*9880d681SAndroid Build Coastguard Worker     return (FC == FC_Address);
123*9880d681SAndroid Build Coastguard Worker   case DW_FORM_GNU_str_index:
124*9880d681SAndroid Build Coastguard Worker   case DW_FORM_GNU_strp_alt:
125*9880d681SAndroid Build Coastguard Worker     return (FC == FC_String);
126*9880d681SAndroid Build Coastguard Worker   }
127*9880d681SAndroid Build Coastguard Worker   // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section offset.
128*9880d681SAndroid Build Coastguard Worker   // Don't check for DWARF version here, as some producers may still do this
129*9880d681SAndroid Build Coastguard Worker   // by mistake.
130*9880d681SAndroid Build Coastguard Worker   return (Form == DW_FORM_data4 || Form == DW_FORM_data8) &&
131*9880d681SAndroid Build Coastguard Worker          FC == FC_SectionOffset;
132*9880d681SAndroid Build Coastguard Worker }
133*9880d681SAndroid Build Coastguard Worker 
extractValue(DataExtractor data,uint32_t * offset_ptr,const DWARFUnit * cu)134*9880d681SAndroid Build Coastguard Worker bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
135*9880d681SAndroid Build Coastguard Worker                                   const DWARFUnit *cu) {
136*9880d681SAndroid Build Coastguard Worker   bool indirect = false;
137*9880d681SAndroid Build Coastguard Worker   bool is_block = false;
138*9880d681SAndroid Build Coastguard Worker   Value.data = nullptr;
139*9880d681SAndroid Build Coastguard Worker   // Read the value for the form into value and follow and DW_FORM_indirect
140*9880d681SAndroid Build Coastguard Worker   // instances we run into
141*9880d681SAndroid Build Coastguard Worker   do {
142*9880d681SAndroid Build Coastguard Worker     indirect = false;
143*9880d681SAndroid Build Coastguard Worker     switch (Form) {
144*9880d681SAndroid Build Coastguard Worker     case DW_FORM_addr:
145*9880d681SAndroid Build Coastguard Worker     case DW_FORM_ref_addr: {
146*9880d681SAndroid Build Coastguard Worker       if (!cu)
147*9880d681SAndroid Build Coastguard Worker         return false;
148*9880d681SAndroid Build Coastguard Worker       uint16_t AddrSize =
149*9880d681SAndroid Build Coastguard Worker           (Form == DW_FORM_addr)
150*9880d681SAndroid Build Coastguard Worker               ? cu->getAddressByteSize()
151*9880d681SAndroid Build Coastguard Worker               : getRefAddrSize(cu->getAddressByteSize(), cu->getVersion());
152*9880d681SAndroid Build Coastguard Worker       RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr);
153*9880d681SAndroid Build Coastguard Worker       if (AI != cu->getRelocMap()->end()) {
154*9880d681SAndroid Build Coastguard Worker         const std::pair<uint8_t, int64_t> &R = AI->second;
155*9880d681SAndroid Build Coastguard Worker         Value.uval = data.getUnsigned(offset_ptr, AddrSize) + R.second;
156*9880d681SAndroid Build Coastguard Worker       } else
157*9880d681SAndroid Build Coastguard Worker         Value.uval = data.getUnsigned(offset_ptr, AddrSize);
158*9880d681SAndroid Build Coastguard Worker       break;
159*9880d681SAndroid Build Coastguard Worker     }
160*9880d681SAndroid Build Coastguard Worker     case DW_FORM_exprloc:
161*9880d681SAndroid Build Coastguard Worker     case DW_FORM_block:
162*9880d681SAndroid Build Coastguard Worker       Value.uval = data.getULEB128(offset_ptr);
163*9880d681SAndroid Build Coastguard Worker       is_block = true;
164*9880d681SAndroid Build Coastguard Worker       break;
165*9880d681SAndroid Build Coastguard Worker     case DW_FORM_block1:
166*9880d681SAndroid Build Coastguard Worker       Value.uval = data.getU8(offset_ptr);
167*9880d681SAndroid Build Coastguard Worker       is_block = true;
168*9880d681SAndroid Build Coastguard Worker       break;
169*9880d681SAndroid Build Coastguard Worker     case DW_FORM_block2:
170*9880d681SAndroid Build Coastguard Worker       Value.uval = data.getU16(offset_ptr);
171*9880d681SAndroid Build Coastguard Worker       is_block = true;
172*9880d681SAndroid Build Coastguard Worker       break;
173*9880d681SAndroid Build Coastguard Worker     case DW_FORM_block4:
174*9880d681SAndroid Build Coastguard Worker       Value.uval = data.getU32(offset_ptr);
175*9880d681SAndroid Build Coastguard Worker       is_block = true;
176*9880d681SAndroid Build Coastguard Worker       break;
177*9880d681SAndroid Build Coastguard Worker     case DW_FORM_data1:
178*9880d681SAndroid Build Coastguard Worker     case DW_FORM_ref1:
179*9880d681SAndroid Build Coastguard Worker     case DW_FORM_flag:
180*9880d681SAndroid Build Coastguard Worker       Value.uval = data.getU8(offset_ptr);
181*9880d681SAndroid Build Coastguard Worker       break;
182*9880d681SAndroid Build Coastguard Worker     case DW_FORM_data2:
183*9880d681SAndroid Build Coastguard Worker     case DW_FORM_ref2:
184*9880d681SAndroid Build Coastguard Worker       Value.uval = data.getU16(offset_ptr);
185*9880d681SAndroid Build Coastguard Worker       break;
186*9880d681SAndroid Build Coastguard Worker     case DW_FORM_data4:
187*9880d681SAndroid Build Coastguard Worker     case DW_FORM_ref4: {
188*9880d681SAndroid Build Coastguard Worker       Value.uval = data.getU32(offset_ptr);
189*9880d681SAndroid Build Coastguard Worker       if (!cu)
190*9880d681SAndroid Build Coastguard Worker         break;
191*9880d681SAndroid Build Coastguard Worker       RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr-4);
192*9880d681SAndroid Build Coastguard Worker       if (AI != cu->getRelocMap()->end())
193*9880d681SAndroid Build Coastguard Worker         Value.uval += AI->second.second;
194*9880d681SAndroid Build Coastguard Worker       break;
195*9880d681SAndroid Build Coastguard Worker     }
196*9880d681SAndroid Build Coastguard Worker     case DW_FORM_data8:
197*9880d681SAndroid Build Coastguard Worker     case DW_FORM_ref8:
198*9880d681SAndroid Build Coastguard Worker       Value.uval = data.getU64(offset_ptr);
199*9880d681SAndroid Build Coastguard Worker       break;
200*9880d681SAndroid Build Coastguard Worker     case DW_FORM_sdata:
201*9880d681SAndroid Build Coastguard Worker       Value.sval = data.getSLEB128(offset_ptr);
202*9880d681SAndroid Build Coastguard Worker       break;
203*9880d681SAndroid Build Coastguard Worker     case DW_FORM_udata:
204*9880d681SAndroid Build Coastguard Worker     case DW_FORM_ref_udata:
205*9880d681SAndroid Build Coastguard Worker       Value.uval = data.getULEB128(offset_ptr);
206*9880d681SAndroid Build Coastguard Worker       break;
207*9880d681SAndroid Build Coastguard Worker     case DW_FORM_string:
208*9880d681SAndroid Build Coastguard Worker       Value.cstr = data.getCStr(offset_ptr);
209*9880d681SAndroid Build Coastguard Worker       break;
210*9880d681SAndroid Build Coastguard Worker     case DW_FORM_indirect:
211*9880d681SAndroid Build Coastguard Worker       Form = data.getULEB128(offset_ptr);
212*9880d681SAndroid Build Coastguard Worker       indirect = true;
213*9880d681SAndroid Build Coastguard Worker       break;
214*9880d681SAndroid Build Coastguard Worker     case DW_FORM_sec_offset:
215*9880d681SAndroid Build Coastguard Worker     case DW_FORM_strp:
216*9880d681SAndroid Build Coastguard Worker     case DW_FORM_GNU_ref_alt:
217*9880d681SAndroid Build Coastguard Worker     case DW_FORM_GNU_strp_alt: {
218*9880d681SAndroid Build Coastguard Worker       // FIXME: This is 64-bit for DWARF64.
219*9880d681SAndroid Build Coastguard Worker       Value.uval = data.getU32(offset_ptr);
220*9880d681SAndroid Build Coastguard Worker       if (!cu)
221*9880d681SAndroid Build Coastguard Worker         break;
222*9880d681SAndroid Build Coastguard Worker       RelocAddrMap::const_iterator AI =
223*9880d681SAndroid Build Coastguard Worker           cu->getRelocMap()->find(*offset_ptr - 4);
224*9880d681SAndroid Build Coastguard Worker       if (AI != cu->getRelocMap()->end())
225*9880d681SAndroid Build Coastguard Worker         Value.uval += AI->second.second;
226*9880d681SAndroid Build Coastguard Worker       break;
227*9880d681SAndroid Build Coastguard Worker     }
228*9880d681SAndroid Build Coastguard Worker     case DW_FORM_flag_present:
229*9880d681SAndroid Build Coastguard Worker       Value.uval = 1;
230*9880d681SAndroid Build Coastguard Worker       break;
231*9880d681SAndroid Build Coastguard Worker     case DW_FORM_ref_sig8:
232*9880d681SAndroid Build Coastguard Worker       Value.uval = data.getU64(offset_ptr);
233*9880d681SAndroid Build Coastguard Worker       break;
234*9880d681SAndroid Build Coastguard Worker     case DW_FORM_GNU_addr_index:
235*9880d681SAndroid Build Coastguard Worker     case DW_FORM_GNU_str_index:
236*9880d681SAndroid Build Coastguard Worker       Value.uval = data.getULEB128(offset_ptr);
237*9880d681SAndroid Build Coastguard Worker       break;
238*9880d681SAndroid Build Coastguard Worker     default:
239*9880d681SAndroid Build Coastguard Worker       return false;
240*9880d681SAndroid Build Coastguard Worker     }
241*9880d681SAndroid Build Coastguard Worker   } while (indirect);
242*9880d681SAndroid Build Coastguard Worker 
243*9880d681SAndroid Build Coastguard Worker   if (is_block) {
244*9880d681SAndroid Build Coastguard Worker     StringRef str = data.getData().substr(*offset_ptr, Value.uval);
245*9880d681SAndroid Build Coastguard Worker     Value.data = nullptr;
246*9880d681SAndroid Build Coastguard Worker     if (!str.empty()) {
247*9880d681SAndroid Build Coastguard Worker       Value.data = reinterpret_cast<const uint8_t *>(str.data());
248*9880d681SAndroid Build Coastguard Worker       *offset_ptr += Value.uval;
249*9880d681SAndroid Build Coastguard Worker     }
250*9880d681SAndroid Build Coastguard Worker   }
251*9880d681SAndroid Build Coastguard Worker 
252*9880d681SAndroid Build Coastguard Worker   return true;
253*9880d681SAndroid Build Coastguard Worker }
254*9880d681SAndroid Build Coastguard Worker 
255*9880d681SAndroid Build Coastguard Worker bool
skipValue(DataExtractor debug_info_data,uint32_t * offset_ptr,const DWARFUnit * cu) const256*9880d681SAndroid Build Coastguard Worker DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr,
257*9880d681SAndroid Build Coastguard Worker                           const DWARFUnit *cu) const {
258*9880d681SAndroid Build Coastguard Worker   return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu);
259*9880d681SAndroid Build Coastguard Worker }
260*9880d681SAndroid Build Coastguard Worker 
261*9880d681SAndroid Build Coastguard Worker bool
skipValue(uint16_t form,DataExtractor debug_info_data,uint32_t * offset_ptr,const DWARFUnit * cu)262*9880d681SAndroid Build Coastguard Worker DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
263*9880d681SAndroid Build Coastguard Worker                           uint32_t *offset_ptr, const DWARFUnit *cu) {
264*9880d681SAndroid Build Coastguard Worker   return skipValue(form, debug_info_data, offset_ptr, cu->getVersion(),
265*9880d681SAndroid Build Coastguard Worker                    cu->getAddressByteSize());
266*9880d681SAndroid Build Coastguard Worker }
skipValue(uint16_t form,DataExtractor debug_info_data,uint32_t * offset_ptr,uint16_t Version,uint8_t AddrSize)267*9880d681SAndroid Build Coastguard Worker bool DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
268*9880d681SAndroid Build Coastguard Worker                                uint32_t *offset_ptr, uint16_t Version,
269*9880d681SAndroid Build Coastguard Worker                                uint8_t AddrSize) {
270*9880d681SAndroid Build Coastguard Worker   bool indirect = false;
271*9880d681SAndroid Build Coastguard Worker   do {
272*9880d681SAndroid Build Coastguard Worker     switch (form) {
273*9880d681SAndroid Build Coastguard Worker     // Blocks if inlined data that have a length field and the data bytes
274*9880d681SAndroid Build Coastguard Worker     // inlined in the .debug_info
275*9880d681SAndroid Build Coastguard Worker     case DW_FORM_exprloc:
276*9880d681SAndroid Build Coastguard Worker     case DW_FORM_block: {
277*9880d681SAndroid Build Coastguard Worker       uint64_t size = debug_info_data.getULEB128(offset_ptr);
278*9880d681SAndroid Build Coastguard Worker       *offset_ptr += size;
279*9880d681SAndroid Build Coastguard Worker       return true;
280*9880d681SAndroid Build Coastguard Worker     }
281*9880d681SAndroid Build Coastguard Worker     case DW_FORM_block1: {
282*9880d681SAndroid Build Coastguard Worker       uint8_t size = debug_info_data.getU8(offset_ptr);
283*9880d681SAndroid Build Coastguard Worker       *offset_ptr += size;
284*9880d681SAndroid Build Coastguard Worker       return true;
285*9880d681SAndroid Build Coastguard Worker     }
286*9880d681SAndroid Build Coastguard Worker     case DW_FORM_block2: {
287*9880d681SAndroid Build Coastguard Worker       uint16_t size = debug_info_data.getU16(offset_ptr);
288*9880d681SAndroid Build Coastguard Worker       *offset_ptr += size;
289*9880d681SAndroid Build Coastguard Worker       return true;
290*9880d681SAndroid Build Coastguard Worker     }
291*9880d681SAndroid Build Coastguard Worker     case DW_FORM_block4: {
292*9880d681SAndroid Build Coastguard Worker       uint32_t size = debug_info_data.getU32(offset_ptr);
293*9880d681SAndroid Build Coastguard Worker       *offset_ptr += size;
294*9880d681SAndroid Build Coastguard Worker       return true;
295*9880d681SAndroid Build Coastguard Worker     }
296*9880d681SAndroid Build Coastguard Worker 
297*9880d681SAndroid Build Coastguard Worker     // Inlined NULL terminated C-strings
298*9880d681SAndroid Build Coastguard Worker     case DW_FORM_string:
299*9880d681SAndroid Build Coastguard Worker       debug_info_data.getCStr(offset_ptr);
300*9880d681SAndroid Build Coastguard Worker       return true;
301*9880d681SAndroid Build Coastguard Worker 
302*9880d681SAndroid Build Coastguard Worker     // Compile unit address sized values
303*9880d681SAndroid Build Coastguard Worker     case DW_FORM_addr:
304*9880d681SAndroid Build Coastguard Worker       *offset_ptr += AddrSize;
305*9880d681SAndroid Build Coastguard Worker       return true;
306*9880d681SAndroid Build Coastguard Worker     case DW_FORM_ref_addr:
307*9880d681SAndroid Build Coastguard Worker       *offset_ptr += getRefAddrSize(AddrSize, Version);
308*9880d681SAndroid Build Coastguard Worker       return true;
309*9880d681SAndroid Build Coastguard Worker 
310*9880d681SAndroid Build Coastguard Worker     // 0 byte values - implied from the form.
311*9880d681SAndroid Build Coastguard Worker     case DW_FORM_flag_present:
312*9880d681SAndroid Build Coastguard Worker       return true;
313*9880d681SAndroid Build Coastguard Worker 
314*9880d681SAndroid Build Coastguard Worker     // 1 byte values
315*9880d681SAndroid Build Coastguard Worker     case DW_FORM_data1:
316*9880d681SAndroid Build Coastguard Worker     case DW_FORM_flag:
317*9880d681SAndroid Build Coastguard Worker     case DW_FORM_ref1:
318*9880d681SAndroid Build Coastguard Worker       *offset_ptr += 1;
319*9880d681SAndroid Build Coastguard Worker       return true;
320*9880d681SAndroid Build Coastguard Worker 
321*9880d681SAndroid Build Coastguard Worker     // 2 byte values
322*9880d681SAndroid Build Coastguard Worker     case DW_FORM_data2:
323*9880d681SAndroid Build Coastguard Worker     case DW_FORM_ref2:
324*9880d681SAndroid Build Coastguard Worker       *offset_ptr += 2;
325*9880d681SAndroid Build Coastguard Worker       return true;
326*9880d681SAndroid Build Coastguard Worker 
327*9880d681SAndroid Build Coastguard Worker     // 4 byte values
328*9880d681SAndroid Build Coastguard Worker     case DW_FORM_data4:
329*9880d681SAndroid Build Coastguard Worker     case DW_FORM_ref4:
330*9880d681SAndroid Build Coastguard Worker       *offset_ptr += 4;
331*9880d681SAndroid Build Coastguard Worker       return true;
332*9880d681SAndroid Build Coastguard Worker 
333*9880d681SAndroid Build Coastguard Worker     // 8 byte values
334*9880d681SAndroid Build Coastguard Worker     case DW_FORM_data8:
335*9880d681SAndroid Build Coastguard Worker     case DW_FORM_ref8:
336*9880d681SAndroid Build Coastguard Worker     case DW_FORM_ref_sig8:
337*9880d681SAndroid Build Coastguard Worker       *offset_ptr += 8;
338*9880d681SAndroid Build Coastguard Worker       return true;
339*9880d681SAndroid Build Coastguard Worker 
340*9880d681SAndroid Build Coastguard Worker     // signed or unsigned LEB 128 values
341*9880d681SAndroid Build Coastguard Worker     //  case DW_FORM_APPLE_db_str:
342*9880d681SAndroid Build Coastguard Worker     case DW_FORM_sdata:
343*9880d681SAndroid Build Coastguard Worker     case DW_FORM_udata:
344*9880d681SAndroid Build Coastguard Worker     case DW_FORM_ref_udata:
345*9880d681SAndroid Build Coastguard Worker     case DW_FORM_GNU_str_index:
346*9880d681SAndroid Build Coastguard Worker     case DW_FORM_GNU_addr_index:
347*9880d681SAndroid Build Coastguard Worker       debug_info_data.getULEB128(offset_ptr);
348*9880d681SAndroid Build Coastguard Worker       return true;
349*9880d681SAndroid Build Coastguard Worker 
350*9880d681SAndroid Build Coastguard Worker     case DW_FORM_indirect:
351*9880d681SAndroid Build Coastguard Worker       indirect = true;
352*9880d681SAndroid Build Coastguard Worker       form = debug_info_data.getULEB128(offset_ptr);
353*9880d681SAndroid Build Coastguard Worker       break;
354*9880d681SAndroid Build Coastguard Worker 
355*9880d681SAndroid Build Coastguard Worker     // FIXME: 4 for DWARF32, 8 for DWARF64.
356*9880d681SAndroid Build Coastguard Worker     case DW_FORM_sec_offset:
357*9880d681SAndroid Build Coastguard Worker     case DW_FORM_strp:
358*9880d681SAndroid Build Coastguard Worker     case DW_FORM_GNU_ref_alt:
359*9880d681SAndroid Build Coastguard Worker     case DW_FORM_GNU_strp_alt:
360*9880d681SAndroid Build Coastguard Worker       *offset_ptr += 4;
361*9880d681SAndroid Build Coastguard Worker       return true;
362*9880d681SAndroid Build Coastguard Worker 
363*9880d681SAndroid Build Coastguard Worker     default:
364*9880d681SAndroid Build Coastguard Worker       return false;
365*9880d681SAndroid Build Coastguard Worker     }
366*9880d681SAndroid Build Coastguard Worker   } while (indirect);
367*9880d681SAndroid Build Coastguard Worker   return true;
368*9880d681SAndroid Build Coastguard Worker }
369*9880d681SAndroid Build Coastguard Worker 
370*9880d681SAndroid Build Coastguard Worker void
dump(raw_ostream & OS,const DWARFUnit * cu) const371*9880d681SAndroid Build Coastguard Worker DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const {
372*9880d681SAndroid Build Coastguard Worker   uint64_t uvalue = Value.uval;
373*9880d681SAndroid Build Coastguard Worker   bool cu_relative_offset = false;
374*9880d681SAndroid Build Coastguard Worker 
375*9880d681SAndroid Build Coastguard Worker   switch (Form) {
376*9880d681SAndroid Build Coastguard Worker   case DW_FORM_addr:      OS << format("0x%016" PRIx64, uvalue); break;
377*9880d681SAndroid Build Coastguard Worker   case DW_FORM_GNU_addr_index: {
378*9880d681SAndroid Build Coastguard Worker     OS << format(" indexed (%8.8x) address = ", (uint32_t)uvalue);
379*9880d681SAndroid Build Coastguard Worker     uint64_t Address;
380*9880d681SAndroid Build Coastguard Worker     if (cu->getAddrOffsetSectionItem(uvalue, Address))
381*9880d681SAndroid Build Coastguard Worker       OS << format("0x%016" PRIx64, Address);
382*9880d681SAndroid Build Coastguard Worker     else
383*9880d681SAndroid Build Coastguard Worker       OS << "<no .debug_addr section>";
384*9880d681SAndroid Build Coastguard Worker     break;
385*9880d681SAndroid Build Coastguard Worker   }
386*9880d681SAndroid Build Coastguard Worker   case DW_FORM_flag_present: OS << "true"; break;
387*9880d681SAndroid Build Coastguard Worker   case DW_FORM_flag:
388*9880d681SAndroid Build Coastguard Worker   case DW_FORM_data1:     OS << format("0x%02x", (uint8_t)uvalue); break;
389*9880d681SAndroid Build Coastguard Worker   case DW_FORM_data2:     OS << format("0x%04x", (uint16_t)uvalue); break;
390*9880d681SAndroid Build Coastguard Worker   case DW_FORM_data4:     OS << format("0x%08x", (uint32_t)uvalue); break;
391*9880d681SAndroid Build Coastguard Worker   case DW_FORM_ref_sig8:
392*9880d681SAndroid Build Coastguard Worker   case DW_FORM_data8:     OS << format("0x%016" PRIx64, uvalue); break;
393*9880d681SAndroid Build Coastguard Worker   case DW_FORM_string:
394*9880d681SAndroid Build Coastguard Worker     OS << '"';
395*9880d681SAndroid Build Coastguard Worker     OS.write_escaped(Value.cstr);
396*9880d681SAndroid Build Coastguard Worker     OS << '"';
397*9880d681SAndroid Build Coastguard Worker     break;
398*9880d681SAndroid Build Coastguard Worker   case DW_FORM_exprloc:
399*9880d681SAndroid Build Coastguard Worker   case DW_FORM_block:
400*9880d681SAndroid Build Coastguard Worker   case DW_FORM_block1:
401*9880d681SAndroid Build Coastguard Worker   case DW_FORM_block2:
402*9880d681SAndroid Build Coastguard Worker   case DW_FORM_block4:
403*9880d681SAndroid Build Coastguard Worker     if (uvalue > 0) {
404*9880d681SAndroid Build Coastguard Worker       switch (Form) {
405*9880d681SAndroid Build Coastguard Worker       case DW_FORM_exprloc:
406*9880d681SAndroid Build Coastguard Worker       case DW_FORM_block:  OS << format("<0x%" PRIx64 "> ", uvalue);     break;
407*9880d681SAndroid Build Coastguard Worker       case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue);  break;
408*9880d681SAndroid Build Coastguard Worker       case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break;
409*9880d681SAndroid Build Coastguard Worker       case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break;
410*9880d681SAndroid Build Coastguard Worker       default: break;
411*9880d681SAndroid Build Coastguard Worker       }
412*9880d681SAndroid Build Coastguard Worker 
413*9880d681SAndroid Build Coastguard Worker       const uint8_t* data_ptr = Value.data;
414*9880d681SAndroid Build Coastguard Worker       if (data_ptr) {
415*9880d681SAndroid Build Coastguard Worker         // uvalue contains size of block
416*9880d681SAndroid Build Coastguard Worker         const uint8_t* end_data_ptr = data_ptr + uvalue;
417*9880d681SAndroid Build Coastguard Worker         while (data_ptr < end_data_ptr) {
418*9880d681SAndroid Build Coastguard Worker           OS << format("%2.2x ", *data_ptr);
419*9880d681SAndroid Build Coastguard Worker           ++data_ptr;
420*9880d681SAndroid Build Coastguard Worker         }
421*9880d681SAndroid Build Coastguard Worker       }
422*9880d681SAndroid Build Coastguard Worker       else
423*9880d681SAndroid Build Coastguard Worker         OS << "NULL";
424*9880d681SAndroid Build Coastguard Worker     }
425*9880d681SAndroid Build Coastguard Worker     break;
426*9880d681SAndroid Build Coastguard Worker 
427*9880d681SAndroid Build Coastguard Worker   case DW_FORM_sdata:     OS << Value.sval; break;
428*9880d681SAndroid Build Coastguard Worker   case DW_FORM_udata:     OS << Value.uval; break;
429*9880d681SAndroid Build Coastguard Worker   case DW_FORM_strp: {
430*9880d681SAndroid Build Coastguard Worker     OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
431*9880d681SAndroid Build Coastguard Worker     dumpString(OS, cu);
432*9880d681SAndroid Build Coastguard Worker     break;
433*9880d681SAndroid Build Coastguard Worker   }
434*9880d681SAndroid Build Coastguard Worker   case DW_FORM_GNU_str_index: {
435*9880d681SAndroid Build Coastguard Worker     OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue);
436*9880d681SAndroid Build Coastguard Worker     dumpString(OS, cu);
437*9880d681SAndroid Build Coastguard Worker     break;
438*9880d681SAndroid Build Coastguard Worker   }
439*9880d681SAndroid Build Coastguard Worker   case DW_FORM_GNU_strp_alt: {
440*9880d681SAndroid Build Coastguard Worker     OS << format("alt indirect string, offset: 0x%" PRIx64 "", uvalue);
441*9880d681SAndroid Build Coastguard Worker     dumpString(OS, cu);
442*9880d681SAndroid Build Coastguard Worker     break;
443*9880d681SAndroid Build Coastguard Worker   }
444*9880d681SAndroid Build Coastguard Worker   case DW_FORM_ref_addr:
445*9880d681SAndroid Build Coastguard Worker     OS << format("0x%016" PRIx64, uvalue);
446*9880d681SAndroid Build Coastguard Worker     break;
447*9880d681SAndroid Build Coastguard Worker   case DW_FORM_ref1:
448*9880d681SAndroid Build Coastguard Worker     cu_relative_offset = true;
449*9880d681SAndroid Build Coastguard Worker     OS << format("cu + 0x%2.2x", (uint8_t)uvalue);
450*9880d681SAndroid Build Coastguard Worker     break;
451*9880d681SAndroid Build Coastguard Worker   case DW_FORM_ref2:
452*9880d681SAndroid Build Coastguard Worker     cu_relative_offset = true;
453*9880d681SAndroid Build Coastguard Worker     OS << format("cu + 0x%4.4x", (uint16_t)uvalue);
454*9880d681SAndroid Build Coastguard Worker     break;
455*9880d681SAndroid Build Coastguard Worker   case DW_FORM_ref4:
456*9880d681SAndroid Build Coastguard Worker     cu_relative_offset = true;
457*9880d681SAndroid Build Coastguard Worker     OS << format("cu + 0x%4.4x", (uint32_t)uvalue);
458*9880d681SAndroid Build Coastguard Worker     break;
459*9880d681SAndroid Build Coastguard Worker   case DW_FORM_ref8:
460*9880d681SAndroid Build Coastguard Worker     cu_relative_offset = true;
461*9880d681SAndroid Build Coastguard Worker     OS << format("cu + 0x%8.8" PRIx64, uvalue);
462*9880d681SAndroid Build Coastguard Worker     break;
463*9880d681SAndroid Build Coastguard Worker   case DW_FORM_ref_udata:
464*9880d681SAndroid Build Coastguard Worker     cu_relative_offset = true;
465*9880d681SAndroid Build Coastguard Worker     OS << format("cu + 0x%" PRIx64, uvalue);
466*9880d681SAndroid Build Coastguard Worker     break;
467*9880d681SAndroid Build Coastguard Worker   case DW_FORM_GNU_ref_alt:
468*9880d681SAndroid Build Coastguard Worker     OS << format("<alt 0x%" PRIx64 ">", uvalue);
469*9880d681SAndroid Build Coastguard Worker     break;
470*9880d681SAndroid Build Coastguard Worker 
471*9880d681SAndroid Build Coastguard Worker     // All DW_FORM_indirect attributes should be resolved prior to calling
472*9880d681SAndroid Build Coastguard Worker     // this function
473*9880d681SAndroid Build Coastguard Worker   case DW_FORM_indirect:
474*9880d681SAndroid Build Coastguard Worker     OS << "DW_FORM_indirect";
475*9880d681SAndroid Build Coastguard Worker     break;
476*9880d681SAndroid Build Coastguard Worker 
477*9880d681SAndroid Build Coastguard Worker     // Should be formatted to 64-bit for DWARF64.
478*9880d681SAndroid Build Coastguard Worker   case DW_FORM_sec_offset:
479*9880d681SAndroid Build Coastguard Worker     OS << format("0x%08x", (uint32_t)uvalue);
480*9880d681SAndroid Build Coastguard Worker     break;
481*9880d681SAndroid Build Coastguard Worker 
482*9880d681SAndroid Build Coastguard Worker   default:
483*9880d681SAndroid Build Coastguard Worker     OS << format("DW_FORM(0x%4.4x)", Form);
484*9880d681SAndroid Build Coastguard Worker     break;
485*9880d681SAndroid Build Coastguard Worker   }
486*9880d681SAndroid Build Coastguard Worker 
487*9880d681SAndroid Build Coastguard Worker   if (cu_relative_offset) {
488*9880d681SAndroid Build Coastguard Worker     OS << " => {";
489*9880d681SAndroid Build Coastguard Worker     WithColor(OS, syntax::Address).get()
490*9880d681SAndroid Build Coastguard Worker       << format("0x%8.8" PRIx64, uvalue + (cu ? cu->getOffset() : 0));
491*9880d681SAndroid Build Coastguard Worker     OS << "}";
492*9880d681SAndroid Build Coastguard Worker   }
493*9880d681SAndroid Build Coastguard Worker }
494*9880d681SAndroid Build Coastguard Worker 
dumpString(raw_ostream & OS,const DWARFUnit * U) const495*9880d681SAndroid Build Coastguard Worker void DWARFFormValue::dumpString(raw_ostream &OS, const DWARFUnit *U) const {
496*9880d681SAndroid Build Coastguard Worker   Optional<const char *> DbgStr = getAsCString(U);
497*9880d681SAndroid Build Coastguard Worker   if (DbgStr.hasValue()) {
498*9880d681SAndroid Build Coastguard Worker     raw_ostream &COS = WithColor(OS, syntax::String);
499*9880d681SAndroid Build Coastguard Worker     COS << '"';
500*9880d681SAndroid Build Coastguard Worker     COS.write_escaped(DbgStr.getValue());
501*9880d681SAndroid Build Coastguard Worker     COS << '"';
502*9880d681SAndroid Build Coastguard Worker   }
503*9880d681SAndroid Build Coastguard Worker }
504*9880d681SAndroid Build Coastguard Worker 
getAsCString(const DWARFUnit * U) const505*9880d681SAndroid Build Coastguard Worker Optional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const {
506*9880d681SAndroid Build Coastguard Worker   if (!isFormClass(FC_String))
507*9880d681SAndroid Build Coastguard Worker     return None;
508*9880d681SAndroid Build Coastguard Worker   if (Form == DW_FORM_string)
509*9880d681SAndroid Build Coastguard Worker     return Value.cstr;
510*9880d681SAndroid Build Coastguard Worker   // FIXME: Add support for DW_FORM_GNU_strp_alt
511*9880d681SAndroid Build Coastguard Worker   if (Form == DW_FORM_GNU_strp_alt || U == nullptr)
512*9880d681SAndroid Build Coastguard Worker     return None;
513*9880d681SAndroid Build Coastguard Worker   uint32_t Offset = Value.uval;
514*9880d681SAndroid Build Coastguard Worker   if (Form == DW_FORM_GNU_str_index) {
515*9880d681SAndroid Build Coastguard Worker     uint32_t StrOffset;
516*9880d681SAndroid Build Coastguard Worker     if (!U->getStringOffsetSectionItem(Offset, StrOffset))
517*9880d681SAndroid Build Coastguard Worker       return None;
518*9880d681SAndroid Build Coastguard Worker     Offset = StrOffset;
519*9880d681SAndroid Build Coastguard Worker   }
520*9880d681SAndroid Build Coastguard Worker   if (const char *Str = U->getStringExtractor().getCStr(&Offset)) {
521*9880d681SAndroid Build Coastguard Worker     return Str;
522*9880d681SAndroid Build Coastguard Worker   }
523*9880d681SAndroid Build Coastguard Worker   return None;
524*9880d681SAndroid Build Coastguard Worker }
525*9880d681SAndroid Build Coastguard Worker 
getAsAddress(const DWARFUnit * U) const526*9880d681SAndroid Build Coastguard Worker Optional<uint64_t> DWARFFormValue::getAsAddress(const DWARFUnit *U) const {
527*9880d681SAndroid Build Coastguard Worker   if (!isFormClass(FC_Address))
528*9880d681SAndroid Build Coastguard Worker     return None;
529*9880d681SAndroid Build Coastguard Worker   if (Form == DW_FORM_GNU_addr_index) {
530*9880d681SAndroid Build Coastguard Worker     uint32_t Index = Value.uval;
531*9880d681SAndroid Build Coastguard Worker     uint64_t Result;
532*9880d681SAndroid Build Coastguard Worker     if (!U || !U->getAddrOffsetSectionItem(Index, Result))
533*9880d681SAndroid Build Coastguard Worker       return None;
534*9880d681SAndroid Build Coastguard Worker     return Result;
535*9880d681SAndroid Build Coastguard Worker   }
536*9880d681SAndroid Build Coastguard Worker   return Value.uval;
537*9880d681SAndroid Build Coastguard Worker }
538*9880d681SAndroid Build Coastguard Worker 
getAsReference(const DWARFUnit * U) const539*9880d681SAndroid Build Coastguard Worker Optional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const {
540*9880d681SAndroid Build Coastguard Worker   if (!isFormClass(FC_Reference))
541*9880d681SAndroid Build Coastguard Worker     return None;
542*9880d681SAndroid Build Coastguard Worker   switch (Form) {
543*9880d681SAndroid Build Coastguard Worker   case DW_FORM_ref1:
544*9880d681SAndroid Build Coastguard Worker   case DW_FORM_ref2:
545*9880d681SAndroid Build Coastguard Worker   case DW_FORM_ref4:
546*9880d681SAndroid Build Coastguard Worker   case DW_FORM_ref8:
547*9880d681SAndroid Build Coastguard Worker   case DW_FORM_ref_udata:
548*9880d681SAndroid Build Coastguard Worker     if (!U)
549*9880d681SAndroid Build Coastguard Worker       return None;
550*9880d681SAndroid Build Coastguard Worker     return Value.uval + U->getOffset();
551*9880d681SAndroid Build Coastguard Worker   case DW_FORM_ref_addr:
552*9880d681SAndroid Build Coastguard Worker     return Value.uval;
553*9880d681SAndroid Build Coastguard Worker   // FIXME: Add proper support for DW_FORM_ref_sig8 and DW_FORM_GNU_ref_alt.
554*9880d681SAndroid Build Coastguard Worker   default:
555*9880d681SAndroid Build Coastguard Worker     return None;
556*9880d681SAndroid Build Coastguard Worker   }
557*9880d681SAndroid Build Coastguard Worker }
558*9880d681SAndroid Build Coastguard Worker 
getAsSectionOffset() const559*9880d681SAndroid Build Coastguard Worker Optional<uint64_t> DWARFFormValue::getAsSectionOffset() const {
560*9880d681SAndroid Build Coastguard Worker   if (!isFormClass(FC_SectionOffset))
561*9880d681SAndroid Build Coastguard Worker     return None;
562*9880d681SAndroid Build Coastguard Worker   return Value.uval;
563*9880d681SAndroid Build Coastguard Worker }
564*9880d681SAndroid Build Coastguard Worker 
getAsUnsignedConstant() const565*9880d681SAndroid Build Coastguard Worker Optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {
566*9880d681SAndroid Build Coastguard Worker   if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag))
567*9880d681SAndroid Build Coastguard Worker       || Form == DW_FORM_sdata)
568*9880d681SAndroid Build Coastguard Worker     return None;
569*9880d681SAndroid Build Coastguard Worker   return Value.uval;
570*9880d681SAndroid Build Coastguard Worker }
571*9880d681SAndroid Build Coastguard Worker 
getAsSignedConstant() const572*9880d681SAndroid Build Coastguard Worker Optional<int64_t> DWARFFormValue::getAsSignedConstant() const {
573*9880d681SAndroid Build Coastguard Worker   if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) ||
574*9880d681SAndroid Build Coastguard Worker       (Form == DW_FORM_udata && uint64_t(std::numeric_limits<int64_t>::max()) < Value.uval))
575*9880d681SAndroid Build Coastguard Worker     return None;
576*9880d681SAndroid Build Coastguard Worker   switch (Form) {
577*9880d681SAndroid Build Coastguard Worker   case DW_FORM_data4:
578*9880d681SAndroid Build Coastguard Worker     return int32_t(Value.uval);
579*9880d681SAndroid Build Coastguard Worker   case DW_FORM_data2:
580*9880d681SAndroid Build Coastguard Worker     return int16_t(Value.uval);
581*9880d681SAndroid Build Coastguard Worker   case DW_FORM_data1:
582*9880d681SAndroid Build Coastguard Worker     return int8_t(Value.uval);
583*9880d681SAndroid Build Coastguard Worker   case DW_FORM_sdata:
584*9880d681SAndroid Build Coastguard Worker   case DW_FORM_data8:
585*9880d681SAndroid Build Coastguard Worker   default:
586*9880d681SAndroid Build Coastguard Worker     return Value.sval;
587*9880d681SAndroid Build Coastguard Worker   }
588*9880d681SAndroid Build Coastguard Worker }
589*9880d681SAndroid Build Coastguard Worker 
getAsBlock() const590*9880d681SAndroid Build Coastguard Worker Optional<ArrayRef<uint8_t>> DWARFFormValue::getAsBlock() const {
591*9880d681SAndroid Build Coastguard Worker   if (!isFormClass(FC_Block) && !isFormClass(FC_Exprloc))
592*9880d681SAndroid Build Coastguard Worker     return None;
593*9880d681SAndroid Build Coastguard Worker   return makeArrayRef(Value.data, Value.uval);
594*9880d681SAndroid Build Coastguard Worker }
595*9880d681SAndroid Build Coastguard Worker 
596