1226584Sdim//===-- DWARFFormValue.cpp ------------------------------------------------===// 2226584Sdim// 3226584Sdim// The LLVM Compiler Infrastructure 4226584Sdim// 5226584Sdim// This file is distributed under the University of Illinois Open Source 6226584Sdim// License. See LICENSE.TXT for details. 7226584Sdim// 8226584Sdim//===----------------------------------------------------------------------===// 9226584Sdim 10252723Sdim#include "llvm/DebugInfo/DWARFFormValue.h" 11226584Sdim#include "DWARFCompileUnit.h" 12226584Sdim#include "DWARFContext.h" 13263509Sdim#include "llvm/ADT/ArrayRef.h" 14263509Sdim#include "llvm/ADT/StringRef.h" 15245431Sdim#include "llvm/Support/Debug.h" 16226584Sdim#include "llvm/Support/Dwarf.h" 17226584Sdim#include "llvm/Support/Format.h" 18226584Sdim#include "llvm/Support/raw_ostream.h" 19226584Sdim#include <cassert> 20226584Sdimusing namespace llvm; 21226584Sdimusing namespace dwarf; 22226584Sdim 23252723Sdimnamespace { 24263509Sdimuint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) { 25263509Sdim // FIXME: Support DWARF64. 26263509Sdim return (Version == 2) ? AddrSize : 4; 27252723Sdim} 28226584Sdim 29252723Sdimtemplate <uint8_t AddrSize, uint8_t RefAddrSize> 30263509SdimArrayRef<uint8_t> makeFixedFormSizesArrayRef() { 31263509Sdim static const uint8_t sizes[] = { 32263509Sdim 0, // 0x00 unused 33263509Sdim AddrSize, // 0x01 DW_FORM_addr 34263509Sdim 0, // 0x02 unused 35263509Sdim 0, // 0x03 DW_FORM_block2 36263509Sdim 0, // 0x04 DW_FORM_block4 37263509Sdim 2, // 0x05 DW_FORM_data2 38263509Sdim 4, // 0x06 DW_FORM_data4 39263509Sdim 8, // 0x07 DW_FORM_data8 40263509Sdim 0, // 0x08 DW_FORM_string 41263509Sdim 0, // 0x09 DW_FORM_block 42263509Sdim 0, // 0x0a DW_FORM_block1 43263509Sdim 1, // 0x0b DW_FORM_data1 44263509Sdim 1, // 0x0c DW_FORM_flag 45263509Sdim 0, // 0x0d DW_FORM_sdata 46263509Sdim 4, // 0x0e DW_FORM_strp 47263509Sdim 0, // 0x0f DW_FORM_udata 48263509Sdim RefAddrSize, // 0x10 DW_FORM_ref_addr 49263509Sdim 1, // 0x11 DW_FORM_ref1 50263509Sdim 2, // 0x12 DW_FORM_ref2 51263509Sdim 4, // 0x13 DW_FORM_ref4 52263509Sdim 8, // 0x14 DW_FORM_ref8 53263509Sdim 0, // 0x15 DW_FORM_ref_udata 54263509Sdim 0, // 0x16 DW_FORM_indirect 55263509Sdim 4, // 0x17 DW_FORM_sec_offset 56263509Sdim 0, // 0x18 DW_FORM_exprloc 57263509Sdim 0, // 0x19 DW_FORM_flag_present 58263509Sdim }; 59263509Sdim return makeArrayRef(sizes); 60252723Sdim} 61263509Sdim} 62252723Sdim 63263509SdimArrayRef<uint8_t> DWARFFormValue::getFixedFormSizes(uint8_t AddrSize, 64263509Sdim uint16_t Version) { 65252723Sdim uint8_t RefAddrSize = getRefAddrSize(AddrSize, Version); 66252723Sdim if (AddrSize == 4 && RefAddrSize == 4) 67263509Sdim return makeFixedFormSizesArrayRef<4, 4>(); 68252723Sdim if (AddrSize == 4 && RefAddrSize == 8) 69263509Sdim return makeFixedFormSizesArrayRef<4, 8>(); 70252723Sdim if (AddrSize == 8 && RefAddrSize == 4) 71263509Sdim return makeFixedFormSizesArrayRef<8, 4>(); 72252723Sdim if (AddrSize == 8 && RefAddrSize == 8) 73263509Sdim return makeFixedFormSizesArrayRef<8, 8>(); 74263509Sdim return None; 75226584Sdim} 76226584Sdim 77263509Sdimstatic const DWARFFormValue::FormClass DWARF4FormClasses[] = { 78263509Sdim DWARFFormValue::FC_Unknown, // 0x0 79263509Sdim DWARFFormValue::FC_Address, // 0x01 DW_FORM_addr 80263509Sdim DWARFFormValue::FC_Unknown, // 0x02 unused 81263509Sdim DWARFFormValue::FC_Block, // 0x03 DW_FORM_block2 82263509Sdim DWARFFormValue::FC_Block, // 0x04 DW_FORM_block4 83263509Sdim DWARFFormValue::FC_Constant, // 0x05 DW_FORM_data2 84263509Sdim // --- These can be FC_SectionOffset in DWARF3 and below: 85263509Sdim DWARFFormValue::FC_Constant, // 0x06 DW_FORM_data4 86263509Sdim DWARFFormValue::FC_Constant, // 0x07 DW_FORM_data8 87263509Sdim // --- 88263509Sdim DWARFFormValue::FC_String, // 0x08 DW_FORM_string 89263509Sdim DWARFFormValue::FC_Block, // 0x09 DW_FORM_block 90263509Sdim DWARFFormValue::FC_Block, // 0x0a DW_FORM_block1 91263509Sdim DWARFFormValue::FC_Constant, // 0x0b DW_FORM_data1 92263509Sdim DWARFFormValue::FC_Flag, // 0x0c DW_FORM_flag 93263509Sdim DWARFFormValue::FC_Constant, // 0x0d DW_FORM_sdata 94263509Sdim DWARFFormValue::FC_String, // 0x0e DW_FORM_strp 95263509Sdim DWARFFormValue::FC_Constant, // 0x0f DW_FORM_udata 96263509Sdim DWARFFormValue::FC_Reference, // 0x10 DW_FORM_ref_addr 97263509Sdim DWARFFormValue::FC_Reference, // 0x11 DW_FORM_ref1 98263509Sdim DWARFFormValue::FC_Reference, // 0x12 DW_FORM_ref2 99263509Sdim DWARFFormValue::FC_Reference, // 0x13 DW_FORM_ref4 100263509Sdim DWARFFormValue::FC_Reference, // 0x14 DW_FORM_ref8 101263509Sdim DWARFFormValue::FC_Reference, // 0x15 DW_FORM_ref_udata 102263509Sdim DWARFFormValue::FC_Indirect, // 0x16 DW_FORM_indirect 103263509Sdim DWARFFormValue::FC_SectionOffset, // 0x17 DW_FORM_sec_offset 104263509Sdim DWARFFormValue::FC_Exprloc, // 0x18 DW_FORM_exprloc 105263509Sdim DWARFFormValue::FC_Flag, // 0x19 DW_FORM_flag_present 106263509Sdim}; 107263509Sdim 108263509Sdimbool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const { 109263509Sdim // First, check DWARF4 form classes. 110263509Sdim if (Form < ArrayRef<FormClass>(DWARF4FormClasses).size() && 111263509Sdim DWARF4FormClasses[Form] == FC) 112263509Sdim return true; 113263509Sdim // Check DW_FORM_ref_sig8 from DWARF4. 114263509Sdim if (Form == DW_FORM_ref_sig8) 115263509Sdim return (FC == FC_Reference); 116263509Sdim // Check for some DWARF5 forms. 117263509Sdim if (Form == DW_FORM_GNU_addr_index) 118263509Sdim return (FC == FC_Address); 119263509Sdim if (Form == DW_FORM_GNU_str_index) 120263509Sdim return (FC == FC_String); 121263509Sdim // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section offset. 122263509Sdim // Don't check for DWARF version here, as some producers may still do this 123263509Sdim // by mistake. 124263509Sdim if ((Form == DW_FORM_data4 || Form == DW_FORM_data8) && 125263509Sdim FC == FC_SectionOffset) 126263509Sdim return true; 127263509Sdim return false; 128263509Sdim} 129263509Sdim 130263509Sdimbool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr, 131263509Sdim const DWARFUnit *cu) { 132226584Sdim bool indirect = false; 133226584Sdim bool is_block = false; 134226584Sdim Value.data = NULL; 135226584Sdim // Read the value for the form into value and follow and DW_FORM_indirect 136226584Sdim // instances we run into 137226584Sdim do { 138226584Sdim indirect = false; 139226584Sdim switch (Form) { 140226584Sdim case DW_FORM_addr: 141245431Sdim case DW_FORM_ref_addr: { 142252723Sdim uint16_t AddrSize = 143252723Sdim (Form == DW_FORM_addr) 144252723Sdim ? cu->getAddressByteSize() 145252723Sdim : getRefAddrSize(cu->getAddressByteSize(), cu->getVersion()); 146252723Sdim RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr); 147252723Sdim if (AI != cu->getRelocMap()->end()) { 148245431Sdim const std::pair<uint8_t, int64_t> &R = AI->second; 149252723Sdim Value.uval = data.getUnsigned(offset_ptr, AddrSize) + R.second; 150245431Sdim } else 151252723Sdim Value.uval = data.getUnsigned(offset_ptr, AddrSize); 152252723Sdim break; 153245431Sdim } 154245431Sdim case DW_FORM_exprloc: 155226584Sdim case DW_FORM_block: 156226584Sdim Value.uval = data.getULEB128(offset_ptr); 157226584Sdim is_block = true; 158226584Sdim break; 159226584Sdim case DW_FORM_block1: 160226584Sdim Value.uval = data.getU8(offset_ptr); 161226584Sdim is_block = true; 162226584Sdim break; 163226584Sdim case DW_FORM_block2: 164226584Sdim Value.uval = data.getU16(offset_ptr); 165226584Sdim is_block = true; 166226584Sdim break; 167226584Sdim case DW_FORM_block4: 168226584Sdim Value.uval = data.getU32(offset_ptr); 169226584Sdim is_block = true; 170226584Sdim break; 171226584Sdim case DW_FORM_data1: 172226584Sdim case DW_FORM_ref1: 173226584Sdim case DW_FORM_flag: 174226584Sdim Value.uval = data.getU8(offset_ptr); 175226584Sdim break; 176226584Sdim case DW_FORM_data2: 177226584Sdim case DW_FORM_ref2: 178226584Sdim Value.uval = data.getU16(offset_ptr); 179226584Sdim break; 180226584Sdim case DW_FORM_data4: 181263509Sdim case DW_FORM_ref4: { 182263509Sdim RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr); 183226584Sdim Value.uval = data.getU32(offset_ptr); 184263509Sdim if (AI != cu->getRelocMap()->end()) 185263509Sdim Value.uval += AI->second.second; 186226584Sdim break; 187263509Sdim } 188226584Sdim case DW_FORM_data8: 189226584Sdim case DW_FORM_ref8: 190226584Sdim Value.uval = data.getU64(offset_ptr); 191226584Sdim break; 192226584Sdim case DW_FORM_sdata: 193226584Sdim Value.sval = data.getSLEB128(offset_ptr); 194226584Sdim break; 195245431Sdim case DW_FORM_strp: { 196245431Sdim RelocAddrMap::const_iterator AI 197252723Sdim = cu->getRelocMap()->find(*offset_ptr); 198252723Sdim if (AI != cu->getRelocMap()->end()) { 199245431Sdim const std::pair<uint8_t, int64_t> &R = AI->second; 200252723Sdim Value.uval = data.getU32(offset_ptr) + R.second; 201245431Sdim } else 202245431Sdim Value.uval = data.getU32(offset_ptr); 203226584Sdim break; 204245431Sdim } 205226584Sdim case DW_FORM_udata: 206226584Sdim case DW_FORM_ref_udata: 207226584Sdim Value.uval = data.getULEB128(offset_ptr); 208226584Sdim break; 209226584Sdim case DW_FORM_string: 210226584Sdim Value.cstr = data.getCStr(offset_ptr); 211226584Sdim break; 212226584Sdim case DW_FORM_indirect: 213226584Sdim Form = data.getULEB128(offset_ptr); 214226584Sdim indirect = true; 215226584Sdim break; 216252723Sdim case DW_FORM_sec_offset: { 217252723Sdim // FIXME: This is 64-bit for DWARF64. 218252723Sdim RelocAddrMap::const_iterator AI 219252723Sdim = cu->getRelocMap()->find(*offset_ptr); 220252723Sdim if (AI != cu->getRelocMap()->end()) { 221252723Sdim const std::pair<uint8_t, int64_t> &R = AI->second; 222252723Sdim Value.uval = data.getU32(offset_ptr) + R.second; 223252723Sdim } else 224245431Sdim Value.uval = data.getU32(offset_ptr); 225245431Sdim break; 226252723Sdim } 227245431Sdim case DW_FORM_flag_present: 228245431Sdim Value.uval = 1; 229245431Sdim break; 230245431Sdim case DW_FORM_ref_sig8: 231245431Sdim Value.uval = data.getU64(offset_ptr); 232245431Sdim break; 233252723Sdim case DW_FORM_GNU_addr_index: 234252723Sdim case DW_FORM_GNU_str_index: 235252723Sdim Value.uval = data.getULEB128(offset_ptr); 236252723Sdim break; 237226584Sdim default: 238226584Sdim return false; 239226584Sdim } 240226584Sdim } while (indirect); 241226584Sdim 242226584Sdim if (is_block) { 243226584Sdim StringRef str = data.getData().substr(*offset_ptr, Value.uval); 244226584Sdim Value.data = NULL; 245226584Sdim if (!str.empty()) { 246226584Sdim Value.data = reinterpret_cast<const uint8_t *>(str.data()); 247226584Sdim *offset_ptr += Value.uval; 248226584Sdim } 249226584Sdim } 250226584Sdim 251226584Sdim return true; 252226584Sdim} 253226584Sdim 254226584Sdimbool 255226584SdimDWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr, 256263509Sdim const DWARFUnit *cu) const { 257226584Sdim return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu); 258226584Sdim} 259226584Sdim 260226584Sdimbool 261226584SdimDWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data, 262263509Sdim uint32_t *offset_ptr, const DWARFUnit *cu) { 263226584Sdim bool indirect = false; 264226584Sdim do { 265226584Sdim switch (form) { 266226584Sdim // Blocks if inlined data that have a length field and the data bytes 267226584Sdim // inlined in the .debug_info 268245431Sdim case DW_FORM_exprloc: 269226584Sdim case DW_FORM_block: { 270226584Sdim uint64_t size = debug_info_data.getULEB128(offset_ptr); 271226584Sdim *offset_ptr += size; 272226584Sdim return true; 273226584Sdim } 274226584Sdim case DW_FORM_block1: { 275226584Sdim uint8_t size = debug_info_data.getU8(offset_ptr); 276226584Sdim *offset_ptr += size; 277226584Sdim return true; 278226584Sdim } 279226584Sdim case DW_FORM_block2: { 280226584Sdim uint16_t size = debug_info_data.getU16(offset_ptr); 281226584Sdim *offset_ptr += size; 282226584Sdim return true; 283226584Sdim } 284226584Sdim case DW_FORM_block4: { 285226584Sdim uint32_t size = debug_info_data.getU32(offset_ptr); 286226584Sdim *offset_ptr += size; 287226584Sdim return true; 288226584Sdim } 289226584Sdim 290226584Sdim // Inlined NULL terminated C-strings 291226584Sdim case DW_FORM_string: 292226584Sdim debug_info_data.getCStr(offset_ptr); 293226584Sdim return true; 294226584Sdim 295226584Sdim // Compile unit address sized values 296226584Sdim case DW_FORM_addr: 297226584Sdim *offset_ptr += cu->getAddressByteSize(); 298226584Sdim return true; 299252723Sdim case DW_FORM_ref_addr: 300252723Sdim *offset_ptr += getRefAddrSize(cu->getAddressByteSize(), cu->getVersion()); 301252723Sdim return true; 302226584Sdim 303245431Sdim // 0 byte values - implied from the form. 304245431Sdim case DW_FORM_flag_present: 305245431Sdim return true; 306252723Sdim 307226584Sdim // 1 byte values 308226584Sdim case DW_FORM_data1: 309226584Sdim case DW_FORM_flag: 310226584Sdim case DW_FORM_ref1: 311226584Sdim *offset_ptr += 1; 312226584Sdim return true; 313226584Sdim 314226584Sdim // 2 byte values 315226584Sdim case DW_FORM_data2: 316226584Sdim case DW_FORM_ref2: 317226584Sdim *offset_ptr += 2; 318226584Sdim return true; 319226584Sdim 320226584Sdim // 4 byte values 321226584Sdim case DW_FORM_strp: 322226584Sdim case DW_FORM_data4: 323226584Sdim case DW_FORM_ref4: 324226584Sdim *offset_ptr += 4; 325226584Sdim return true; 326226584Sdim 327226584Sdim // 8 byte values 328226584Sdim case DW_FORM_data8: 329226584Sdim case DW_FORM_ref8: 330245431Sdim case DW_FORM_ref_sig8: 331226584Sdim *offset_ptr += 8; 332226584Sdim return true; 333226584Sdim 334226584Sdim // signed or unsigned LEB 128 values 335226584Sdim // case DW_FORM_APPLE_db_str: 336226584Sdim case DW_FORM_sdata: 337226584Sdim case DW_FORM_udata: 338226584Sdim case DW_FORM_ref_udata: 339252723Sdim case DW_FORM_GNU_str_index: 340252723Sdim case DW_FORM_GNU_addr_index: 341226584Sdim debug_info_data.getULEB128(offset_ptr); 342226584Sdim return true; 343226584Sdim 344226584Sdim case DW_FORM_indirect: 345226584Sdim indirect = true; 346226584Sdim form = debug_info_data.getULEB128(offset_ptr); 347226584Sdim break; 348245431Sdim 349252723Sdim // FIXME: 4 for DWARF32, 8 for DWARF64. 350245431Sdim case DW_FORM_sec_offset: 351252723Sdim *offset_ptr += 4; 352245431Sdim return true; 353252723Sdim 354226584Sdim default: 355226584Sdim return false; 356226584Sdim } 357226584Sdim } while (indirect); 358226584Sdim return true; 359226584Sdim} 360226584Sdim 361226584Sdimvoid 362263509SdimDWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const { 363252723Sdim DataExtractor debug_str_data(cu->getStringSection(), true, 0); 364252723Sdim DataExtractor debug_str_offset_data(cu->getStringOffsetSection(), true, 0); 365263509Sdim uint64_t uvalue = Value.uval; 366226584Sdim bool cu_relative_offset = false; 367226584Sdim 368226584Sdim switch (Form) { 369235633Sdim case DW_FORM_addr: OS << format("0x%016" PRIx64, uvalue); break; 370252723Sdim case DW_FORM_GNU_addr_index: { 371252723Sdim OS << format(" indexed (%8.8x) address = ", (uint32_t)uvalue); 372263509Sdim uint64_t Address; 373263509Sdim if (cu->getAddrOffsetSectionItem(uvalue, Address)) 374263509Sdim OS << format("0x%016" PRIx64, Address); 375263509Sdim else 376252723Sdim OS << "<no .debug_addr section>"; 377252723Sdim break; 378252723Sdim } 379245431Sdim case DW_FORM_flag_present: OS << "true"; break; 380226584Sdim case DW_FORM_flag: 381235633Sdim case DW_FORM_data1: OS << format("0x%02x", (uint8_t)uvalue); break; 382235633Sdim case DW_FORM_data2: OS << format("0x%04x", (uint16_t)uvalue); break; 383235633Sdim case DW_FORM_data4: OS << format("0x%08x", (uint32_t)uvalue); break; 384245431Sdim case DW_FORM_ref_sig8: 385235633Sdim case DW_FORM_data8: OS << format("0x%016" PRIx64, uvalue); break; 386226584Sdim case DW_FORM_string: 387226584Sdim OS << '"'; 388263509Sdim OS.write_escaped(Value.cstr); 389226584Sdim OS << '"'; 390226584Sdim break; 391245431Sdim case DW_FORM_exprloc: 392226584Sdim case DW_FORM_block: 393226584Sdim case DW_FORM_block1: 394226584Sdim case DW_FORM_block2: 395226584Sdim case DW_FORM_block4: 396226584Sdim if (uvalue > 0) { 397226584Sdim switch (Form) { 398245431Sdim case DW_FORM_exprloc: 399235633Sdim case DW_FORM_block: OS << format("<0x%" PRIx64 "> ", uvalue); break; 400226584Sdim case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue); break; 401226584Sdim case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break; 402226584Sdim case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break; 403226584Sdim default: break; 404226584Sdim } 405226584Sdim 406226584Sdim const uint8_t* data_ptr = Value.data; 407226584Sdim if (data_ptr) { 408226584Sdim // uvalue contains size of block 409226584Sdim const uint8_t* end_data_ptr = data_ptr + uvalue; 410226584Sdim while (data_ptr < end_data_ptr) { 411226584Sdim OS << format("%2.2x ", *data_ptr); 412226584Sdim ++data_ptr; 413226584Sdim } 414226584Sdim } 415226584Sdim else 416226584Sdim OS << "NULL"; 417226584Sdim } 418226584Sdim break; 419226584Sdim 420263509Sdim case DW_FORM_sdata: OS << Value.sval; break; 421263509Sdim case DW_FORM_udata: OS << Value.uval; break; 422226584Sdim case DW_FORM_strp: { 423226584Sdim OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue); 424263509Sdim Optional<const char *> DbgStr = getAsCString(cu); 425263509Sdim if (DbgStr.hasValue()) { 426226584Sdim OS << '"'; 427263509Sdim OS.write_escaped(DbgStr.getValue()); 428226584Sdim OS << '"'; 429226584Sdim } 430226584Sdim break; 431226584Sdim } 432252723Sdim case DW_FORM_GNU_str_index: { 433252723Sdim OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue); 434263509Sdim Optional<const char *> DbgStr = getAsCString(cu); 435263509Sdim if (DbgStr.hasValue()) { 436252723Sdim OS << '"'; 437263509Sdim OS.write_escaped(DbgStr.getValue()); 438252723Sdim OS << '"'; 439252723Sdim } 440252723Sdim break; 441252723Sdim } 442226584Sdim case DW_FORM_ref_addr: 443235633Sdim OS << format("0x%016" PRIx64, uvalue); 444226584Sdim break; 445226584Sdim case DW_FORM_ref1: 446226584Sdim cu_relative_offset = true; 447226584Sdim OS << format("cu + 0x%2.2x", (uint8_t)uvalue); 448226584Sdim break; 449226584Sdim case DW_FORM_ref2: 450226584Sdim cu_relative_offset = true; 451226584Sdim OS << format("cu + 0x%4.4x", (uint16_t)uvalue); 452226584Sdim break; 453226584Sdim case DW_FORM_ref4: 454226584Sdim cu_relative_offset = true; 455226584Sdim OS << format("cu + 0x%4.4x", (uint32_t)uvalue); 456226584Sdim break; 457226584Sdim case DW_FORM_ref8: 458226584Sdim cu_relative_offset = true; 459235633Sdim OS << format("cu + 0x%8.8" PRIx64, uvalue); 460226584Sdim break; 461226584Sdim case DW_FORM_ref_udata: 462226584Sdim cu_relative_offset = true; 463235633Sdim OS << format("cu + 0x%" PRIx64, uvalue); 464226584Sdim break; 465226584Sdim 466226584Sdim // All DW_FORM_indirect attributes should be resolved prior to calling 467226584Sdim // this function 468226584Sdim case DW_FORM_indirect: 469226584Sdim OS << "DW_FORM_indirect"; 470226584Sdim break; 471245431Sdim 472252723Sdim // Should be formatted to 64-bit for DWARF64. 473245431Sdim case DW_FORM_sec_offset: 474252723Sdim OS << format("0x%08x", (uint32_t)uvalue); 475245431Sdim break; 476252723Sdim 477226584Sdim default: 478226584Sdim OS << format("DW_FORM(0x%4.4x)", Form); 479226584Sdim break; 480226584Sdim } 481226584Sdim 482226584Sdim if (cu_relative_offset) 483235633Sdim OS << format(" => {0x%8.8" PRIx64 "}", uvalue + (cu ? cu->getOffset() : 0)); 484226584Sdim} 485226584Sdim 486263509SdimOptional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const { 487263509Sdim if (!isFormClass(FC_String)) 488263509Sdim return None; 489263509Sdim if (Form == DW_FORM_string) 490226584Sdim return Value.cstr; 491263509Sdim if (U == 0) 492263509Sdim return None; 493263509Sdim uint32_t Offset = Value.uval; 494263509Sdim if (Form == DW_FORM_GNU_str_index) { 495263509Sdim uint32_t StrOffset; 496263509Sdim if (!U->getStringOffsetSectionItem(Offset, StrOffset)) 497263509Sdim return None; 498263509Sdim Offset = StrOffset; 499226584Sdim } 500263509Sdim if (const char *Str = U->getStringExtractor().getCStr(&Offset)) { 501263509Sdim return Str; 502263509Sdim } 503263509Sdim return None; 504226584Sdim} 505226584Sdim 506263509SdimOptional<uint64_t> DWARFFormValue::getAsAddress(const DWARFUnit *U) const { 507263509Sdim if (!isFormClass(FC_Address)) 508263509Sdim return None; 509263509Sdim if (Form == DW_FORM_GNU_addr_index) { 510263509Sdim uint32_t Index = Value.uval; 511263509Sdim uint64_t Result; 512263509Sdim if (U == 0 || !U->getAddrOffsetSectionItem(Index, Result)) 513263509Sdim return None; 514263509Sdim return Result; 515226584Sdim } 516263509Sdim return Value.uval; 517226584Sdim} 518226584Sdim 519263509SdimOptional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const { 520263509Sdim if (!isFormClass(FC_Reference)) 521263509Sdim return None; 522226584Sdim switch (Form) { 523226584Sdim case DW_FORM_ref1: 524226584Sdim case DW_FORM_ref2: 525226584Sdim case DW_FORM_ref4: 526226584Sdim case DW_FORM_ref8: 527226584Sdim case DW_FORM_ref_udata: 528263509Sdim if (U == 0) 529263509Sdim return None; 530263509Sdim return Value.uval + U->getOffset(); 531263509Sdim case DW_FORM_ref_addr: 532263509Sdim return Value.uval; 533263509Sdim // FIXME: Add proper support for DW_FORM_ref_sig8 534226584Sdim default: 535263509Sdim return Value.uval; 536226584Sdim } 537226584Sdim} 538226584Sdim 539263509SdimOptional<uint64_t> DWARFFormValue::getAsSectionOffset() const { 540263509Sdim if (!isFormClass(FC_SectionOffset)) 541263509Sdim return None; 542263509Sdim return Value.uval; 543226584Sdim} 544226584Sdim 545263509SdimOptional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const { 546263509Sdim if (!isFormClass(FC_Constant) || Form == DW_FORM_sdata) 547263509Sdim return None; 548263509Sdim return Value.uval; 549226584Sdim} 550