Previously, if no column was specified, ResolveSymbolContext would take the first match returned by FindLineEntryIndexByFileIndex, and reuse it to find subsequent exact matches. With the introduction of columns, columns are now considered when matching the line entries. This leads to a problem if one wants to get all existing line entries that match that line, since now the column is also used for the exact match. This way, all line entries are filtered out that have a different column number, but the same line number. This patch changes that by ignoring the column information of the first match if the original request of ResolveSymbolContext was also ignoring it. Reviewed By: mib Differential Revision: https://reviews.llvm.org/D108816
229 lines
7.5 KiB
C++
229 lines
7.5 KiB
C++
//===-- TestLineEntry.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 "gtest/gtest.h"
|
|
#include <iostream>
|
|
|
|
#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
|
|
#include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h"
|
|
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
|
|
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
|
|
#include "TestingSupport/SubsystemRAII.h"
|
|
#include "TestingSupport/TestUtilities.h"
|
|
|
|
#include "lldb/Core/Module.h"
|
|
#include "lldb/Host/FileSystem.h"
|
|
#include "lldb/Host/HostInfo.h"
|
|
#include "lldb/Symbol/CompileUnit.h"
|
|
#include "lldb/Symbol/SymbolContext.h"
|
|
|
|
#include "llvm/Support/FileUtilities.h"
|
|
#include "llvm/Support/Program.h"
|
|
#include "llvm/Testing/Support/Error.h"
|
|
|
|
using namespace lldb_private;
|
|
using namespace lldb;
|
|
|
|
class LineEntryTest : public testing::Test {
|
|
SubsystemRAII<FileSystem, HostInfo, ObjectFileMachO, SymbolFileDWARF,
|
|
TypeSystemClang>
|
|
subsystem;
|
|
|
|
public:
|
|
void SetUp() override;
|
|
|
|
protected:
|
|
llvm::Expected<SymbolContextList>
|
|
GetLineEntriesForLine(uint32_t line, llvm::Optional<uint16_t> column);
|
|
llvm::Optional<TestFile> m_file;
|
|
ModuleSP m_module_sp;
|
|
};
|
|
|
|
void LineEntryTest::SetUp() {
|
|
auto ExpectedFile = TestFile::fromYamlFile("inlined-functions.yaml");
|
|
ASSERT_THAT_EXPECTED(ExpectedFile, llvm::Succeeded());
|
|
m_file.emplace(std::move(*ExpectedFile));
|
|
m_module_sp = std::make_shared<Module>(m_file->moduleSpec());
|
|
}
|
|
|
|
// TODO: Handle SourceLocationSpec column information
|
|
llvm::Expected<SymbolContextList> LineEntryTest::GetLineEntriesForLine(
|
|
uint32_t line, llvm::Optional<uint16_t> column = llvm::None) {
|
|
SymbolContextList sc_comp_units;
|
|
SymbolContextList sc_line_entries;
|
|
FileSpec file_spec("inlined-functions.cpp");
|
|
m_module_sp->ResolveSymbolContextsForFileSpec(
|
|
file_spec, line, /*check_inlines=*/true, lldb::eSymbolContextCompUnit,
|
|
sc_comp_units);
|
|
if (sc_comp_units.GetSize() == 0)
|
|
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
|
"No comp unit found on the test object.");
|
|
|
|
SourceLocationSpec location_spec(file_spec, line, column,
|
|
/*check_inlines=*/true,
|
|
/*exact_match=*/true);
|
|
|
|
sc_comp_units[0].comp_unit->ResolveSymbolContext(
|
|
location_spec, eSymbolContextLineEntry, sc_line_entries);
|
|
if (sc_line_entries.GetSize() == 0)
|
|
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
|
"No line entry found on the test object.");
|
|
return sc_line_entries;
|
|
}
|
|
|
|
// This tests if we can get all line entries that match the passed line, if
|
|
// no column is specified.
|
|
TEST_F(LineEntryTest, GetAllExactLineMatchesWithoutColumn) {
|
|
auto sc_line_entries = GetLineEntriesForLine(12);
|
|
ASSERT_THAT_EXPECTED(sc_line_entries, llvm::Succeeded());
|
|
ASSERT_EQ(sc_line_entries->NumLineEntriesWithLine(12), 6u);
|
|
}
|
|
|
|
// This tests if we can get exact line and column matches.
|
|
TEST_F(LineEntryTest, GetAllExactLineColumnMatches) {
|
|
auto sc_line_entries = GetLineEntriesForLine(12, 39);
|
|
ASSERT_THAT_EXPECTED(sc_line_entries, llvm::Succeeded());
|
|
ASSERT_EQ(sc_line_entries->NumLineEntriesWithLine(12), 1u);
|
|
auto line_entry = sc_line_entries.get()[0].line_entry;
|
|
ASSERT_EQ(line_entry.column, 39);
|
|
}
|
|
|
|
TEST_F(LineEntryTest, GetSameLineContiguousAddressRangeNoInlines) {
|
|
auto sc_line_entries = GetLineEntriesForLine(18);
|
|
ASSERT_THAT_EXPECTED(sc_line_entries, llvm::Succeeded());
|
|
auto line_entry = sc_line_entries.get()[0].line_entry;
|
|
bool include_inlined_functions = false;
|
|
auto range =
|
|
line_entry.GetSameLineContiguousAddressRange(include_inlined_functions);
|
|
ASSERT_EQ(range.GetByteSize(), (uint64_t)0x24);
|
|
}
|
|
|
|
TEST_F(LineEntryTest, GetSameLineContiguousAddressRangeOneInline) {
|
|
auto sc_line_entries = GetLineEntriesForLine(18);
|
|
ASSERT_THAT_EXPECTED(sc_line_entries, llvm::Succeeded());
|
|
auto line_entry = sc_line_entries.get()[0].line_entry;
|
|
bool include_inlined_functions = true;
|
|
auto range =
|
|
line_entry.GetSameLineContiguousAddressRange(include_inlined_functions);
|
|
ASSERT_EQ(range.GetByteSize(), (uint64_t)0x49);
|
|
}
|
|
|
|
TEST_F(LineEntryTest, GetSameLineContiguousAddressRangeNestedInline) {
|
|
auto sc_line_entries = GetLineEntriesForLine(12);
|
|
ASSERT_THAT_EXPECTED(sc_line_entries, llvm::Succeeded());
|
|
auto line_entry = sc_line_entries.get()[0].line_entry;
|
|
bool include_inlined_functions = true;
|
|
auto range =
|
|
line_entry.GetSameLineContiguousAddressRange(include_inlined_functions);
|
|
ASSERT_EQ(range.GetByteSize(), (uint64_t)0x33);
|
|
}
|
|
|
|
/*
|
|
# inlined-functions.cpp
|
|
inline __attribute__((always_inline)) int sum2(int a, int b) {
|
|
int result = a + b;
|
|
return result;
|
|
}
|
|
|
|
int sum3(int a, int b, int c) {
|
|
int result = a + b + c;
|
|
return result;
|
|
}
|
|
|
|
inline __attribute__((always_inline)) int sum4(int a, int b, int c, int d) {
|
|
int result = sum2(a, b) + sum2(c, d);
|
|
result += 0;
|
|
return result;
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
sum3(3, 4, 5) + sum2(1, 2);
|
|
int sum = sum4(1, 2, 3, 4);
|
|
sum2(5, 6);
|
|
return 0;
|
|
}
|
|
|
|
// g++ -c inlined-functions.cpp -o inlined-functions.o -g -Wno-unused-value
|
|
// obj2yaml inlined-functions.o > inlined-functions.yaml
|
|
|
|
# Dump of source line per address:
|
|
# inlined-functions.cpp is src.cpp for space considerations.
|
|
0x20: src.cpp:17
|
|
0x21: src.cpp:17
|
|
0x26: src.cpp:17
|
|
0x27: src.cpp:17
|
|
0x29: src.cpp:17
|
|
0x2e: src.cpp:17
|
|
0x2f: src.cpp:17
|
|
0x31: src.cpp:17
|
|
0x36: src.cpp:18
|
|
0x37: src.cpp:18
|
|
0x39: src.cpp:18
|
|
0x3e: src.cpp:18
|
|
0x3f: src.cpp:18
|
|
0x41: src.cpp:18
|
|
0x46: src.cpp:18
|
|
0x47: src.cpp:18
|
|
0x49: src.cpp:18
|
|
0x4e: src.cpp:18
|
|
0x4f: src.cpp:18
|
|
0x51: src.cpp:18
|
|
0x56: src.cpp:18
|
|
0x57: src.cpp:18
|
|
0x59: src.cpp:18
|
|
0x5e: src.cpp:18 -> sum2@src.cpp:2
|
|
0x5f: src.cpp:18 -> sum2@src.cpp:2
|
|
0x61: src.cpp:18 -> sum2@src.cpp:2
|
|
0x66: src.cpp:18 -> sum2@src.cpp:2
|
|
0x67: src.cpp:18 -> sum2@src.cpp:2
|
|
0x69: src.cpp:18 -> sum2@src.cpp:2
|
|
0x6e: src.cpp:18 -> sum2@src.cpp:2
|
|
0x6f: src.cpp:18 -> sum2@src.cpp:2
|
|
0x71: src.cpp:18 -> sum2@src.cpp:2
|
|
0x76: src.cpp:18 -> sum2@src.cpp:2
|
|
0x77: src.cpp:18 -> sum2@src.cpp:2
|
|
0x79: src.cpp:18 -> sum2@src.cpp:2
|
|
0x7e: src.cpp:18 -> sum2@src.cpp:2
|
|
0x7f: src.cpp:19 -> sum4@src.cpp:12
|
|
0x81: src.cpp:19 -> sum4@src.cpp:12
|
|
0x86: src.cpp:19 -> sum4@src.cpp:12
|
|
0x87: src.cpp:19 -> sum4@src.cpp:12
|
|
0x89: src.cpp:19 -> sum4@src.cpp:12
|
|
0x8e: src.cpp:19 -> sum4@src.cpp:12 -> sum2@src.cpp:2
|
|
0x8f: src.cpp:19 -> sum4@src.cpp:12 -> sum2@src.cpp:2
|
|
0x91: src.cpp:19 -> sum4@src.cpp:12 -> sum2@src.cpp:2
|
|
0x96: src.cpp:19 -> sum4@src.cpp:12 -> sum2@src.cpp:3
|
|
0x97: src.cpp:19 -> sum4@src.cpp:12
|
|
0x99: src.cpp:19 -> sum4@src.cpp:12
|
|
0x9e: src.cpp:19 -> sum4@src.cpp:12
|
|
0x9f: src.cpp:19 -> sum4@src.cpp:12
|
|
0xa1: src.cpp:19 -> sum4@src.cpp:12
|
|
0xa6: src.cpp:19 -> sum4@src.cpp:12 -> sum2@src.cpp:2
|
|
0xa7: src.cpp:19 -> sum4@src.cpp:12 -> sum2@src.cpp:2
|
|
0xa9: src.cpp:19 -> sum4@src.cpp:12 -> sum2@src.cpp:2
|
|
0xae: src.cpp:19 -> sum4@src.cpp:12
|
|
0xaf: src.cpp:19 -> sum4@src.cpp:12
|
|
0xb1: src.cpp:19 -> sum4@src.cpp:12
|
|
0xb6: src.cpp:19 -> sum4@src.cpp:13
|
|
0xb7: src.cpp:19 -> sum4@src.cpp:13
|
|
0xb9: src.cpp:19 -> sum4@src.cpp:14
|
|
0xbe: src.cpp:19
|
|
0xbf: src.cpp:19
|
|
0xc1: src.cpp:19
|
|
0xc6: src.cpp:19
|
|
0xc7: src.cpp:19
|
|
0xc9: src.cpp:19
|
|
0xce: src.cpp:20 -> sum2@src.cpp:2
|
|
0xcf: src.cpp:20 -> sum2@src.cpp:2
|
|
0xd1: src.cpp:20 -> sum2@src.cpp:2
|
|
0xd6: src.cpp:21
|
|
0xd7: src.cpp:21
|
|
0xd9: src.cpp:21
|
|
0xde: src.cpp:21
|
|
*/
|