diff options
| author | Pavel Labath <pavel@labath.sk> | 2019-11-08 15:24:11 +0100 |
|---|---|---|
| committer | Pavel Labath <pavel@labath.sk> | 2019-11-20 13:25:18 +0100 |
| commit | 089c0f581492cd6e2a3d2927be3fbf60ea2d7e62 (patch) | |
| tree | c99b6523359271ad380b5b039af76805b7dab1dc /llvm/unittests/DebugInfo/DWARF | |
| parent | 979592a6f735a7111ba2c3a19e5ef3e8d336e01a (diff) | |
| download | bcm5719-llvm-089c0f581492cd6e2a3d2927be3fbf60ea2d7e62.tar.gz bcm5719-llvm-089c0f581492cd6e2a3d2927be3fbf60ea2d7e62.zip | |
[DWARF] Add an api to get "interpreted" location lists
Summary:
This patch adds DWARFDie::getLocations, which returns the location
expressions for a given attribute (typically DW_AT_location). It handles
both "inline" locations and references to the external location list
sections (currently only of the DW_FORM_sec_offset type). It is
implemented on top of DWARFUnit::findLoclistFromOffset, which is also
added in this patch. I tried to make their signatures similar to the
equivalent range list functionality.
The actual location list interpretation logic is in
DWARFLocationTable::visitAbsoluteLocationList. This part is not
equivalent to the range list code, but this deviation is motivated by a
desire to reuse the same location list parsing code within lldb.
The functionality is tested via a c++ unit test of the DWARFDie API.
Reviewers: dblaikie, JDevlieghere, SouraVX
Subscribers: mgorny, hiraditya, cmtice, probinson, llvm-commits, aprantl
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D70394
Diffstat (limited to 'llvm/unittests/DebugInfo/DWARF')
| -rw-r--r-- | llvm/unittests/DebugInfo/DWARF/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp | 117 |
2 files changed, 118 insertions, 0 deletions
diff --git a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt index 2181e0543d0..4fb79b2a96e 100644 --- a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt +++ b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt @@ -13,6 +13,7 @@ add_llvm_unittest(DebugInfoDWARFTests DwarfUtils.cpp DWARFDebugInfoTest.cpp DWARFDebugLineTest.cpp + DWARFDieTest.cpp DWARFFormValueTest.cpp DWARFLocationExpressionTest.cpp ) diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp new file mode 100644 index 00000000000..05e8e05b927 --- /dev/null +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp @@ -0,0 +1,117 @@ +//===- llvm/unittest/DebugInfo/DWARFDieTest.cpp ---------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/ObjectYAML/DWARFEmitter.h" +#include "llvm/Testing/Support/Error.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::dwarf; +using object::SectionedAddress; + +namespace { + +TEST(DWARFLocationTable, getLocations) { + const char *yamldata = R"( + debug_abbrev: + - Code: 0x00000001 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_location + Form: DW_FORM_sec_offset + - Attribute: DW_AT_data_member_location + Form: DW_FORM_exprloc + - Attribute: DW_AT_vtable_elem_location + Form: DW_FORM_sec_offset + - Attribute: DW_AT_call_data_location + Form: DW_FORM_sec_offset + debug_info: + - Length: + TotalLength: 0 + Version: 5 + UnitType: DW_UT_compile + AbbrOffset: 0 + AddrSize: 4 + Entries: + - AbbrCode: 0x00000001 + Values: + - Value: 12 + - Value: 0x0000000000000001 + BlockData: [ 0x47 ] + - Value: 20 + - Value: 25 + )"; + Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections = + DWARFYAML::EmitDebugSections(StringRef(yamldata), + /*IsLittleEndian=*/true); + ASSERT_THAT_EXPECTED(Sections, Succeeded()); + std::vector<uint8_t> Loclists{ + // Header + 0, 0, 0, 0, // Length + 5, 0, // Version + 4, // Address size + 0, // Segment selector size + 0, 0, 0, 0, // Offset entry count + // First location list. + DW_LLE_start_length, // First entry + 1, 0, 0, 0, // Start offset + 2, // Length + 0, // Expression length + DW_LLE_end_of_list, + // Second location list. + DW_LLE_startx_length, // First entry + 1, // Start index + 2, // Length + 0, // Expression length + DW_LLE_end_of_list, + // Third location list. + DW_LLE_start_length, // First entry + 1, 0, 0, 0, // Start offset + 2, // Length + 0, // Expression length + // end_of_list intentionally missing + }; + Loclists[0] = Loclists.size() - 4; + Sections->try_emplace( + "debug_loclists", + MemoryBuffer::getMemBuffer(toStringRef(Loclists), "debug_loclists", + /*RequiresNullTerminator=*/false)); + std::unique_ptr<DWARFContext> Ctx = DWARFContext::create(*Sections, 8); + DWARFCompileUnit *CU = Ctx->getCompileUnitForOffset(0); + ASSERT_NE(nullptr, CU); + DWARFDie Die = CU->getUnitDIE(); + ASSERT_TRUE(Die.isValid()); + + EXPECT_THAT_EXPECTED(Die.getLocations(DW_AT_location), + HasValue(testing::ElementsAre(DWARFLocationExpression{ + DWARFAddressRange{1, 3}, {}}))); + + EXPECT_THAT_EXPECTED( + Die.getLocations(DW_AT_data_member_location), + HasValue(testing::ElementsAre(DWARFLocationExpression{None, {0x47}}))); + + EXPECT_THAT_EXPECTED( + Die.getLocations(DW_AT_vtable_elem_location), + Failed<ErrorInfoBase>(testing::Property( + &ErrorInfoBase::message, + "Unable to resolve indirect address 1 for: DW_LLE_startx_length"))); + + EXPECT_THAT_EXPECTED(Die.getLocations(DW_AT_call_data_location), + Failed<ErrorInfoBase>(testing::Property( + &ErrorInfoBase::message, "unexpected end of data"))); + + EXPECT_THAT_EXPECTED( + Die.getLocations(DW_AT_call_data_value), + Failed<ErrorInfoBase>(testing::Property(&ErrorInfoBase::message, + "No DW_AT_call_data_value"))); +} + +} // end anonymous namespace |

