799 lines · cpp
1//===- DWARFFormValue.cpp -------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"10#include "llvm/ADT/ArrayRef.h"11#include "llvm/ADT/StringRef.h"12#include "llvm/BinaryFormat/Dwarf.h"13#include "llvm/DebugInfo/DWARF/DWARFContext.h"14#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"15#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"16#include "llvm/DebugInfo/DWARF/DWARFObject.h"17#include "llvm/DebugInfo/DWARF/DWARFSection.h"18#include "llvm/DebugInfo/DWARF/DWARFUnit.h"19#include "llvm/Support/ErrorHandling.h"20#include "llvm/Support/Format.h"21#include "llvm/Support/WithColor.h"22#include "llvm/Support/raw_ostream.h"23#include <cinttypes>24#include <cstdint>25#include <limits>26#include <optional>27 28using namespace llvm;29using namespace dwarf;30 31static const DWARFFormValue::FormClass DWARF5FormClasses[] = {32 DWARFFormValue::FC_Unknown, // 0x033 DWARFFormValue::FC_Address, // 0x01 DW_FORM_addr34 DWARFFormValue::FC_Unknown, // 0x02 unused35 DWARFFormValue::FC_Block, // 0x03 DW_FORM_block236 DWARFFormValue::FC_Block, // 0x04 DW_FORM_block437 DWARFFormValue::FC_Constant, // 0x05 DW_FORM_data238 // --- These can be FC_SectionOffset in DWARF3 and below:39 DWARFFormValue::FC_Constant, // 0x06 DW_FORM_data440 DWARFFormValue::FC_Constant, // 0x07 DW_FORM_data841 // ---42 DWARFFormValue::FC_String, // 0x08 DW_FORM_string43 DWARFFormValue::FC_Block, // 0x09 DW_FORM_block44 DWARFFormValue::FC_Block, // 0x0a DW_FORM_block145 DWARFFormValue::FC_Constant, // 0x0b DW_FORM_data146 DWARFFormValue::FC_Flag, // 0x0c DW_FORM_flag47 DWARFFormValue::FC_Constant, // 0x0d DW_FORM_sdata48 DWARFFormValue::FC_String, // 0x0e DW_FORM_strp49 DWARFFormValue::FC_Constant, // 0x0f DW_FORM_udata50 DWARFFormValue::FC_Reference, // 0x10 DW_FORM_ref_addr51 DWARFFormValue::FC_Reference, // 0x11 DW_FORM_ref152 DWARFFormValue::FC_Reference, // 0x12 DW_FORM_ref253 DWARFFormValue::FC_Reference, // 0x13 DW_FORM_ref454 DWARFFormValue::FC_Reference, // 0x14 DW_FORM_ref855 DWARFFormValue::FC_Reference, // 0x15 DW_FORM_ref_udata56 DWARFFormValue::FC_Indirect, // 0x16 DW_FORM_indirect57 DWARFFormValue::FC_SectionOffset, // 0x17 DW_FORM_sec_offset58 DWARFFormValue::FC_Exprloc, // 0x18 DW_FORM_exprloc59 DWARFFormValue::FC_Flag, // 0x19 DW_FORM_flag_present60 DWARFFormValue::FC_String, // 0x1a DW_FORM_strx61 DWARFFormValue::FC_Address, // 0x1b DW_FORM_addrx62 DWARFFormValue::FC_Reference, // 0x1c DW_FORM_ref_sup463 DWARFFormValue::FC_String, // 0x1d DW_FORM_strp_sup64 DWARFFormValue::FC_Constant, // 0x1e DW_FORM_data1665 DWARFFormValue::FC_String, // 0x1f DW_FORM_line_strp66 DWARFFormValue::FC_Reference, // 0x20 DW_FORM_ref_sig867 DWARFFormValue::FC_Constant, // 0x21 DW_FORM_implicit_const68 DWARFFormValue::FC_SectionOffset, // 0x22 DW_FORM_loclistx69 DWARFFormValue::FC_SectionOffset, // 0x23 DW_FORM_rnglistx70 DWARFFormValue::FC_Reference, // 0x24 DW_FORM_ref_sup871 DWARFFormValue::FC_String, // 0x25 DW_FORM_strx172 DWARFFormValue::FC_String, // 0x26 DW_FORM_strx273 DWARFFormValue::FC_String, // 0x27 DW_FORM_strx374 DWARFFormValue::FC_String, // 0x28 DW_FORM_strx475 DWARFFormValue::FC_Address, // 0x29 DW_FORM_addrx176 DWARFFormValue::FC_Address, // 0x2a DW_FORM_addrx277 DWARFFormValue::FC_Address, // 0x2b DW_FORM_addrx378 DWARFFormValue::FC_Address, // 0x2c DW_FORM_addrx479 DWARFFormValue::FC_Address, // 0x2001 DW_FORM_addrx_offset80};81 82DWARFFormValue DWARFFormValue::createFromSValue(dwarf::Form F, int64_t V) {83 return DWARFFormValue(F, ValueType(V));84}85 86DWARFFormValue DWARFFormValue::createFromUValue(dwarf::Form F, uint64_t V) {87 return DWARFFormValue(F, ValueType(V));88}89 90DWARFFormValue DWARFFormValue::createFromPValue(dwarf::Form F, const char *V) {91 return DWARFFormValue(F, ValueType(V));92}93 94DWARFFormValue DWARFFormValue::createFromBlockValue(dwarf::Form F,95 ArrayRef<uint8_t> D) {96 ValueType V;97 V.uval = D.size();98 V.data = D.data();99 return DWARFFormValue(F, V);100}101 102DWARFFormValue DWARFFormValue::createFromUnit(dwarf::Form F, const DWARFUnit *U,103 uint64_t *OffsetPtr) {104 DWARFFormValue FormValue(F);105 FormValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr,106 U->getFormParams(), U);107 return FormValue;108}109 110bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData,111 uint64_t *OffsetPtr,112 const dwarf::FormParams Params) {113 bool Indirect = false;114 do {115 switch (Form) {116 // Blocks of inlined data that have a length field and the data bytes117 // inlined in the .debug_info.118 case DW_FORM_exprloc:119 case DW_FORM_block: {120 uint64_t size = DebugInfoData.getULEB128(OffsetPtr);121 *OffsetPtr += size;122 return true;123 }124 case DW_FORM_block1: {125 uint8_t size = DebugInfoData.getU8(OffsetPtr);126 *OffsetPtr += size;127 return true;128 }129 case DW_FORM_block2: {130 uint16_t size = DebugInfoData.getU16(OffsetPtr);131 *OffsetPtr += size;132 return true;133 }134 case DW_FORM_block4: {135 uint32_t size = DebugInfoData.getU32(OffsetPtr);136 *OffsetPtr += size;137 return true;138 }139 140 // Inlined NULL terminated C-strings.141 case DW_FORM_string:142 DebugInfoData.getCStr(OffsetPtr);143 return true;144 145 case DW_FORM_addr:146 case DW_FORM_ref_addr:147 case DW_FORM_flag_present:148 case DW_FORM_data1:149 case DW_FORM_data2:150 case DW_FORM_data4:151 case DW_FORM_data8:152 case DW_FORM_data16:153 case DW_FORM_flag:154 case DW_FORM_ref1:155 case DW_FORM_ref2:156 case DW_FORM_ref4:157 case DW_FORM_ref8:158 case DW_FORM_ref_sig8:159 case DW_FORM_ref_sup4:160 case DW_FORM_ref_sup8:161 case DW_FORM_strx1:162 case DW_FORM_strx2:163 case DW_FORM_strx3:164 case DW_FORM_strx4:165 case DW_FORM_addrx1:166 case DW_FORM_addrx2:167 case DW_FORM_addrx3:168 case DW_FORM_addrx4:169 case DW_FORM_sec_offset:170 case DW_FORM_strp:171 case DW_FORM_strp_sup:172 case DW_FORM_line_strp:173 case DW_FORM_GNU_ref_alt:174 case DW_FORM_GNU_strp_alt:175 case DW_FORM_implicit_const:176 if (std::optional<uint8_t> FixedSize =177 dwarf::getFixedFormByteSize(Form, Params)) {178 *OffsetPtr += *FixedSize;179 return true;180 }181 return false;182 183 // signed or unsigned LEB 128 values.184 case DW_FORM_sdata:185 DebugInfoData.getSLEB128(OffsetPtr);186 return true;187 188 case DW_FORM_udata:189 case DW_FORM_ref_udata:190 case DW_FORM_strx:191 case DW_FORM_addrx:192 case DW_FORM_loclistx:193 case DW_FORM_rnglistx:194 case DW_FORM_GNU_addr_index:195 case DW_FORM_GNU_str_index:196 DebugInfoData.getULEB128(OffsetPtr);197 return true;198 199 case DW_FORM_LLVM_addrx_offset:200 DebugInfoData.getULEB128(OffsetPtr);201 *OffsetPtr += 4;202 return true;203 204 case DW_FORM_indirect:205 Indirect = true;206 Form = static_cast<dwarf::Form>(DebugInfoData.getULEB128(OffsetPtr));207 break;208 209 default:210 return false;211 }212 } while (Indirect);213 return true;214}215 216bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {217 return doesFormBelongToClass(Form, FC, U ? U->getVersion() : 3);218}219 220bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data,221 uint64_t *OffsetPtr, dwarf::FormParams FP,222 const DWARFContext *Ctx,223 const DWARFUnit *CU) {224 if (!Ctx && CU)225 Ctx = &CU->getContext();226 C = Ctx;227 U = CU;228 Format = FP.Format;229 bool Indirect = false;230 bool IsBlock = false;231 Value.data = nullptr;232 // Read the value for the form into value and follow and DW_FORM_indirect233 // instances we run into234 Error Err = Error::success();235 do {236 Indirect = false;237 switch (Form) {238 case DW_FORM_addr:239 case DW_FORM_ref_addr: {240 uint16_t Size =241 (Form == DW_FORM_addr) ? FP.AddrSize : FP.getRefAddrByteSize();242 Value.uval =243 Data.getRelocatedValue(Size, OffsetPtr, &Value.SectionIndex, &Err);244 break;245 }246 case DW_FORM_exprloc:247 case DW_FORM_block:248 Value.uval = Data.getULEB128(OffsetPtr, &Err);249 IsBlock = true;250 break;251 case DW_FORM_block1:252 Value.uval = Data.getU8(OffsetPtr, &Err);253 IsBlock = true;254 break;255 case DW_FORM_block2:256 Value.uval = Data.getU16(OffsetPtr, &Err);257 IsBlock = true;258 break;259 case DW_FORM_block4:260 Value.uval = Data.getU32(OffsetPtr, &Err);261 IsBlock = true;262 break;263 case DW_FORM_data1:264 case DW_FORM_ref1:265 case DW_FORM_flag:266 case DW_FORM_strx1:267 case DW_FORM_addrx1:268 Value.uval = Data.getU8(OffsetPtr, &Err);269 break;270 case DW_FORM_data2:271 case DW_FORM_ref2:272 case DW_FORM_strx2:273 case DW_FORM_addrx2:274 Value.uval = Data.getU16(OffsetPtr, &Err);275 break;276 case DW_FORM_strx3:277 case DW_FORM_addrx3:278 Value.uval = Data.getU24(OffsetPtr, &Err);279 break;280 case DW_FORM_data4:281 case DW_FORM_ref4:282 case DW_FORM_ref_sup4:283 case DW_FORM_strx4:284 case DW_FORM_addrx4:285 Value.uval = Data.getRelocatedValue(4, OffsetPtr, nullptr, &Err);286 break;287 case DW_FORM_data8:288 case DW_FORM_ref8:289 case DW_FORM_ref_sup8:290 Value.uval = Data.getRelocatedValue(8, OffsetPtr, nullptr, &Err);291 break;292 case DW_FORM_data16:293 // Treat this like a 16-byte block.294 Value.uval = 16;295 IsBlock = true;296 break;297 case DW_FORM_sdata:298 Value.sval = Data.getSLEB128(OffsetPtr, &Err);299 break;300 case DW_FORM_udata:301 case DW_FORM_ref_udata:302 case DW_FORM_rnglistx:303 case DW_FORM_loclistx:304 case DW_FORM_GNU_addr_index:305 case DW_FORM_GNU_str_index:306 case DW_FORM_addrx:307 case DW_FORM_strx:308 Value.uval = Data.getULEB128(OffsetPtr, &Err);309 break;310 case DW_FORM_LLVM_addrx_offset:311 Value.uval = Data.getULEB128(OffsetPtr, &Err) << 32;312 Value.uval |= Data.getU32(OffsetPtr, &Err);313 break;314 case DW_FORM_string:315 Value.cstr = Data.getCStr(OffsetPtr, &Err);316 break;317 case DW_FORM_indirect:318 Form = static_cast<dwarf::Form>(Data.getULEB128(OffsetPtr, &Err));319 Indirect = true;320 break;321 case DW_FORM_strp:322 case DW_FORM_sec_offset:323 case DW_FORM_GNU_ref_alt:324 case DW_FORM_GNU_strp_alt:325 case DW_FORM_line_strp:326 case DW_FORM_strp_sup: {327 Value.uval = Data.getRelocatedValue(FP.getDwarfOffsetByteSize(),328 OffsetPtr, nullptr, &Err);329 break;330 }331 case DW_FORM_flag_present:332 Value.uval = 1;333 break;334 case DW_FORM_ref_sig8:335 Value.uval = Data.getU64(OffsetPtr, &Err);336 break;337 case DW_FORM_implicit_const:338 // Value has been already set by DWARFFormValue::createFromSValue.339 break;340 default:341 // DWARFFormValue::skipValue() will have caught this and caused all342 // DWARF DIEs to fail to be parsed, so this code is not be reachable.343 llvm_unreachable("unsupported form");344 }345 } while (Indirect && !Err);346 347 if (IsBlock)348 Value.data = Data.getBytes(OffsetPtr, Value.uval, &Err).bytes_begin();349 350 return !errorToBool(std::move(Err));351}352 353void DWARFFormValue::dumpAddress(raw_ostream &OS, uint8_t AddressSize,354 uint64_t Address) {355 uint8_t HexDigits = AddressSize * 2;356 OS << format("0x%*.*" PRIx64, HexDigits, HexDigits, Address);357}358 359void DWARFFormValue::dumpSectionedAddress(raw_ostream &OS,360 DIDumpOptions DumpOpts,361 object::SectionedAddress SA) const {362 dumpAddress(OS, U->getAddressByteSize(), SA.Address);363 dumpAddressSection(U->getContext().getDWARFObj(), OS, DumpOpts,364 SA.SectionIndex);365}366 367void DWARFFormValue::dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS,368 DIDumpOptions DumpOpts,369 uint64_t SectionIndex) {370 if (!DumpOpts.Verbose || SectionIndex == -1ULL)371 return;372 ArrayRef<SectionName> SectionNames = Obj.getSectionNames();373 const auto &SecRef = SectionNames[SectionIndex];374 375 OS << " \"" << SecRef.Name << '\"';376 377 // Print section index if name is not unique.378 if (!SecRef.IsNameUnique)379 OS << format(" [%" PRIu64 "]", SectionIndex);380}381 382void DWARFFormValue::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const {383 uint64_t UValue = Value.uval;384 bool CURelativeOffset = false;385 raw_ostream &AddrOS = DumpOpts.ShowAddresses386 ? WithColor(OS, HighlightColor::Address).get()387 : nulls();388 int OffsetDumpWidth = 2 * dwarf::getDwarfOffsetByteSize(Format);389 switch (Form) {390 case DW_FORM_addr:391 dumpSectionedAddress(AddrOS, DumpOpts, {Value.uval, Value.SectionIndex});392 break;393 case DW_FORM_addrx:394 case DW_FORM_addrx1:395 case DW_FORM_addrx2:396 case DW_FORM_addrx3:397 case DW_FORM_addrx4:398 case DW_FORM_GNU_addr_index:399 case DW_FORM_LLVM_addrx_offset: {400 if (U == nullptr) {401 OS << "<invalid dwarf unit>";402 break;403 }404 std::optional<object::SectionedAddress> A = getAsSectionedAddress();405 if (!A || DumpOpts.Verbose) {406 if (Form == DW_FORM_LLVM_addrx_offset) {407 uint32_t Index = UValue >> 32;408 uint32_t Offset = UValue & 0xffffffff;409 AddrOS << format("indexed (%8.8x) + 0x%x address = ", Index, Offset);410 } else411 AddrOS << format("indexed (%8.8x) address = ", (uint32_t)UValue);412 }413 if (A)414 dumpSectionedAddress(AddrOS, DumpOpts, *A);415 else416 OS << "<unresolved>";417 break;418 }419 case DW_FORM_flag_present:420 OS << "true";421 break;422 case DW_FORM_flag:423 case DW_FORM_data1:424 OS << format("0x%02x", (uint8_t)UValue);425 break;426 case DW_FORM_data2:427 OS << format("0x%04x", (uint16_t)UValue);428 break;429 case DW_FORM_data4:430 OS << format("0x%08x", (uint32_t)UValue);431 break;432 case DW_FORM_ref_sig8:433 AddrOS << format("0x%016" PRIx64, UValue);434 break;435 case DW_FORM_data8:436 OS << format("0x%016" PRIx64, UValue);437 break;438 case DW_FORM_data16:439 OS << format_bytes(ArrayRef<uint8_t>(Value.data, 16), std::nullopt, 16, 16);440 break;441 case DW_FORM_string:442 OS << '"';443 OS.write_escaped(Value.cstr);444 OS << '"';445 break;446 case DW_FORM_exprloc:447 case DW_FORM_block:448 case DW_FORM_block1:449 case DW_FORM_block2:450 case DW_FORM_block4:451 if (UValue > 0) {452 switch (Form) {453 case DW_FORM_exprloc:454 case DW_FORM_block:455 AddrOS << format("<0x%" PRIx64 "> ", UValue);456 break;457 case DW_FORM_block1:458 AddrOS << format("<0x%2.2x> ", (uint8_t)UValue);459 break;460 case DW_FORM_block2:461 AddrOS << format("<0x%4.4x> ", (uint16_t)UValue);462 break;463 case DW_FORM_block4:464 AddrOS << format("<0x%8.8x> ", (uint32_t)UValue);465 break;466 default:467 break;468 }469 470 const uint8_t *DataPtr = Value.data;471 if (DataPtr) {472 // UValue contains size of block473 const uint8_t *EndDataPtr = DataPtr + UValue;474 while (DataPtr < EndDataPtr) {475 AddrOS << format("%2.2x ", *DataPtr);476 ++DataPtr;477 }478 } else479 OS << "NULL";480 }481 break;482 483 case DW_FORM_sdata:484 case DW_FORM_implicit_const:485 OS << Value.sval;486 break;487 case DW_FORM_udata:488 OS << Value.uval;489 break;490 case DW_FORM_strp:491 if (DumpOpts.Verbose)492 OS << format(" .debug_str[0x%0*" PRIx64 "] = ", OffsetDumpWidth, UValue);493 dumpString(OS);494 break;495 case DW_FORM_line_strp:496 if (DumpOpts.Verbose)497 OS << format(" .debug_line_str[0x%0*" PRIx64 "] = ", OffsetDumpWidth,498 UValue);499 dumpString(OS);500 break;501 case DW_FORM_strx:502 case DW_FORM_strx1:503 case DW_FORM_strx2:504 case DW_FORM_strx3:505 case DW_FORM_strx4:506 case DW_FORM_GNU_str_index:507 if (DumpOpts.Verbose)508 OS << format("indexed (%8.8x) string = ", (uint32_t)UValue);509 dumpString(OS);510 break;511 case DW_FORM_GNU_strp_alt:512 if (DumpOpts.Verbose)513 OS << format("alt indirect string, offset: 0x%" PRIx64 "", UValue);514 dumpString(OS);515 break;516 case DW_FORM_ref_addr:517 AddrOS << format("0x%016" PRIx64, UValue);518 break;519 case DW_FORM_ref1:520 CURelativeOffset = true;521 if (DumpOpts.Verbose)522 AddrOS << format("cu + 0x%2.2x", (uint8_t)UValue);523 break;524 case DW_FORM_ref2:525 CURelativeOffset = true;526 if (DumpOpts.Verbose)527 AddrOS << format("cu + 0x%4.4x", (uint16_t)UValue);528 break;529 case DW_FORM_ref4:530 CURelativeOffset = true;531 if (DumpOpts.Verbose)532 AddrOS << format("cu + 0x%4.4x", (uint32_t)UValue);533 break;534 case DW_FORM_ref8:535 CURelativeOffset = true;536 if (DumpOpts.Verbose)537 AddrOS << format("cu + 0x%8.8" PRIx64, UValue);538 break;539 case DW_FORM_ref_udata:540 CURelativeOffset = true;541 if (DumpOpts.Verbose)542 AddrOS << format("cu + 0x%" PRIx64, UValue);543 break;544 case DW_FORM_GNU_ref_alt:545 AddrOS << format("<alt 0x%" PRIx64 ">", UValue);546 break;547 548 // All DW_FORM_indirect attributes should be resolved prior to calling549 // this function550 case DW_FORM_indirect:551 OS << "DW_FORM_indirect";552 break;553 554 case DW_FORM_rnglistx:555 OS << format("indexed (0x%x) rangelist = ", (uint32_t)UValue);556 break;557 558 case DW_FORM_loclistx:559 OS << format("indexed (0x%x) loclist = ", (uint32_t)UValue);560 break;561 562 case DW_FORM_sec_offset:563 AddrOS << format("0x%0*" PRIx64, OffsetDumpWidth, UValue);564 break;565 566 default:567 OS << format("DW_FORM(0x%4.4x)", Form);568 break;569 }570 571 if (CURelativeOffset) {572 if (DumpOpts.Verbose)573 OS << " => {";574 if (DumpOpts.ShowAddresses)575 WithColor(OS, HighlightColor::Address).get()576 << format("0x%8.8" PRIx64, UValue + (U ? U->getOffset() : 0));577 if (DumpOpts.Verbose)578 OS << "}";579 }580}581 582void DWARFFormValue::dumpString(raw_ostream &OS) const {583 if (auto DbgStr = dwarf::toString(*this)) {584 auto COS = WithColor(OS, HighlightColor::String);585 COS.get() << '"';586 COS.get().write_escaped(*DbgStr);587 COS.get() << '"';588 }589}590 591Expected<const char *> DWARFFormValue::getAsCString() const {592 if (!isFormClass(FC_String))593 return make_error<StringError>("Invalid form for string attribute",594 inconvertibleErrorCode());595 if (Form == DW_FORM_string)596 return Value.cstr;597 // FIXME: Add support for DW_FORM_GNU_strp_alt598 if (Form == DW_FORM_GNU_strp_alt || C == nullptr)599 return make_error<StringError>("Unsupported form for string attribute",600 inconvertibleErrorCode());601 uint64_t Offset = Value.uval;602 std::optional<uint32_t> Index;603 if (Form == DW_FORM_GNU_str_index || Form == DW_FORM_strx ||604 Form == DW_FORM_strx1 || Form == DW_FORM_strx2 || Form == DW_FORM_strx3 ||605 Form == DW_FORM_strx4) {606 if (!U)607 return make_error<StringError>("API limitation - string extraction not "608 "available without a DWARFUnit",609 inconvertibleErrorCode());610 Expected<uint64_t> StrOffset = U->getStringOffsetSectionItem(Offset);611 Index = Offset;612 if (!StrOffset)613 return StrOffset.takeError();614 Offset = *StrOffset;615 }616 // Prefer the Unit's string extractor, because for .dwo it will point to617 // .debug_str.dwo, while the Context's extractor always uses .debug_str.618 bool IsDebugLineString = Form == DW_FORM_line_strp;619 DataExtractor StrData =620 IsDebugLineString ? C->getLineStringExtractor()621 : U ? U->getStringExtractor() : C->getStringExtractor();622 if (const char *Str = StrData.getCStr(&Offset))623 return Str;624 std::string Msg = FormEncodingString(Form).str();625 if (Index)626 Msg += (" uses index " + Twine(*Index) + ", but the referenced string").str();627 Msg += (" offset " + Twine(Offset) + " is beyond " +628 (IsDebugLineString ? ".debug_line_str" : ".debug_str") + " bounds")629 .str();630 return make_error<StringError>(Msg,631 inconvertibleErrorCode());632}633 634std::optional<uint64_t> DWARFFormValue::getAsAddress() const {635 if (auto SA = getAsSectionedAddress())636 return SA->Address;637 return std::nullopt;638}639 640std::optional<object::SectionedAddress> DWARFFormValue::getAsSectionedAddress(641 const ValueType &Value, const dwarf::Form Form, const DWARFUnit *U) {642 if (!doesFormBelongToClass(Form, FC_Address, U ? U->getVersion() : 3))643 return std::nullopt;644 bool AddrOffset = Form == dwarf::DW_FORM_LLVM_addrx_offset;645 if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx ||646 Form == DW_FORM_addrx1 || Form == DW_FORM_addrx2 ||647 Form == DW_FORM_addrx3 || Form == DW_FORM_addrx4 || AddrOffset) {648 649 uint32_t Index = AddrOffset ? (Value.uval >> 32) : Value.uval;650 if (!U)651 return std::nullopt;652 std::optional<object::SectionedAddress> SA =653 U->getAddrOffsetSectionItem(Index);654 if (!SA)655 return std::nullopt;656 if (AddrOffset)657 SA->Address += (Value.uval & 0xffffffff);658 return SA;659 }660 return {{Value.uval, Value.SectionIndex}};661}662 663std::optional<object::SectionedAddress>664DWARFFormValue::getAsSectionedAddress() const {665 return getAsSectionedAddress(Value, Form, U);666}667 668std::optional<uint64_t> DWARFFormValue::getAsRelativeReference() const {669 switch (Form) {670 case DW_FORM_ref1:671 case DW_FORM_ref2:672 case DW_FORM_ref4:673 case DW_FORM_ref8:674 case DW_FORM_ref_udata:675 if (!U)676 return std::nullopt;677 return Value.uval;678 default:679 return std::nullopt;680 }681}682 683std::optional<uint64_t> DWARFFormValue::getAsDebugInfoReference() const {684 if (Form == DW_FORM_ref_addr)685 return Value.uval;686 return std::nullopt;687}688 689std::optional<uint64_t> DWARFFormValue::getAsSignatureReference() const {690 if (Form == DW_FORM_ref_sig8)691 return Value.uval;692 return std::nullopt;693}694 695std::optional<uint64_t> DWARFFormValue::getAsSupplementaryReference() const {696 switch (Form) {697 case DW_FORM_GNU_ref_alt:698 case DW_FORM_ref_sup4:699 case DW_FORM_ref_sup8:700 return Value.uval;701 default:702 return std::nullopt;703 }704}705 706std::optional<uint64_t> DWARFFormValue::getAsSectionOffset() const {707 if (!isFormClass(FC_SectionOffset))708 return std::nullopt;709 return Value.uval;710}711 712std::optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {713 if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) ||714 Form == DW_FORM_sdata)715 return std::nullopt;716 return Value.uval;717}718 719std::optional<int64_t> DWARFFormValue::getAsSignedConstant() const {720 if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) ||721 (Form == DW_FORM_udata &&722 uint64_t(std::numeric_limits<int64_t>::max()) < Value.uval))723 return std::nullopt;724 switch (Form) {725 case DW_FORM_data4:726 return int32_t(Value.uval);727 case DW_FORM_data2:728 return int16_t(Value.uval);729 case DW_FORM_data1:730 return int8_t(Value.uval);731 case DW_FORM_sdata:732 case DW_FORM_data8:733 default:734 return Value.sval;735 }736}737 738std::optional<ArrayRef<uint8_t>> DWARFFormValue::getAsBlock() const {739 if (!isFormClass(FC_Block) && !isFormClass(FC_Exprloc) &&740 Form != DW_FORM_data16)741 return std::nullopt;742 return ArrayRef(Value.data, Value.uval);743}744 745std::optional<uint64_t> DWARFFormValue::getAsCStringOffset() const {746 if (!isFormClass(FC_String) && Form == DW_FORM_string)747 return std::nullopt;748 return Value.uval;749}750 751std::optional<uint64_t> DWARFFormValue::getAsReferenceUVal() const {752 if (!isFormClass(FC_Reference))753 return std::nullopt;754 return Value.uval;755}756 757std::optional<std::string>758DWARFFormValue::getAsFile(DILineInfoSpecifier::FileLineInfoKind Kind) const {759 if (U == nullptr || !isFormClass(FC_Constant))760 return std::nullopt;761 DWARFUnit *DLU = const_cast<DWARFUnit *>(U)->getLinkedUnit();762 if (auto *LT = DLU->getContext().getLineTableForUnit(DLU)) {763 std::string FileName;764 if (LT->getFileNameByIndex(Value.uval, DLU->getCompilationDir(), Kind,765 FileName))766 return FileName;767 }768 return std::nullopt;769}770 771bool llvm::dwarf::doesFormBelongToClass(dwarf::Form Form, DWARFFormValue::FormClass FC,772 uint16_t DwarfVersion) {773 // First, check DWARF5 form classes.774 if (Form < std::size(DWARF5FormClasses) && DWARF5FormClasses[Form] == FC)775 return true;776 // Check more forms from extensions and proposals.777 switch (Form) {778 case DW_FORM_GNU_ref_alt:779 return (FC == DWARFFormValue::FC_Reference);780 case DW_FORM_GNU_addr_index:781 return (FC == DWARFFormValue::FC_Address);782 case DW_FORM_GNU_str_index:783 case DW_FORM_GNU_strp_alt:784 return (FC == DWARFFormValue::FC_String);785 case DW_FORM_LLVM_addrx_offset:786 return (FC == DWARFFormValue::FC_Address);787 case DW_FORM_strp:788 case DW_FORM_line_strp:789 return (FC == DWARFFormValue::FC_SectionOffset);790 case DW_FORM_data4:791 case DW_FORM_data8:792 // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section793 // offset.794 return (FC == DWARFFormValue::FC_SectionOffset) && (DwarfVersion <= 3);795 default:796 return false;797 }798}799