llvm-project/lldb/unittests/Symbol/TestLineEntry.cpp
Kim-Anh Tran 3973d8b29e [lldb] Return all line entries matchign a line if no column is specified
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
2021-08-30 14:45:46 +02:00

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
*/