[Lldb-commits] [lldb] [lldb] Add LineTable::{upper, lower}_bound (PR #127519)

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Mon Feb 17 14:25:39 PST 2025


================
@@ -0,0 +1,285 @@
+//===-- LineTableTest.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 "Plugins/ObjectFile/ELF/ObjectFileELF.h"
+#include "TestingSupport/SubsystemRAII.h"
+#include "TestingSupport/TestUtilities.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "gtest/gtest.h"
+#include <memory>
+
+using namespace lldb;
+using namespace llvm;
+using namespace lldb_private;
+
+namespace {
+
+// A fake symbol file class to allow us to create the line table "the right
+// way". Pretty much all methods except for GetCompileUnitAtIndex and
+// GetNumCompileUnits are stubbed out.
+class FakeSymbolFile : public SymbolFile {
+public:
+  /// LLVM RTTI support.
+  /// \{
+  bool isA(const void *ClassID) const override {
+    return ClassID == &ID || SymbolFile::isA(ClassID);
+  }
+  static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+  /// \}
+
+  static void Initialize() {
+    PluginManager::RegisterPlugin("FakeSymbolFile", "", CreateInstance,
+                                  DebuggerInitialize);
+  }
+  static void Terminate() { PluginManager::UnregisterPlugin(CreateInstance); }
+
+  void InjectCompileUnit(std::unique_ptr<CompileUnit> cu_up) {
+    m_cu_sp = std::move(cu_up);
+  }
+
+private:
+  /// LLVM RTTI support.
+  static char ID;
+
+  static SymbolFile *CreateInstance(ObjectFileSP objfile_sp) {
+    return new FakeSymbolFile(std::move(objfile_sp));
+  }
+  static void DebuggerInitialize(Debugger &) {}
+
+  StringRef GetPluginName() override { return "FakeSymbolFile"; }
+  uint32_t GetAbilities() override { return UINT32_MAX; }
+  uint32_t CalculateAbilities() override { return UINT32_MAX; }
+  uint32_t GetNumCompileUnits() override { return 1; }
+  CompUnitSP GetCompileUnitAtIndex(uint32_t) override { return m_cu_sp; }
+  Symtab *GetSymtab() override { return nullptr; }
+  LanguageType ParseLanguage(CompileUnit &) override { return eLanguageTypeC; }
+  size_t ParseFunctions(CompileUnit &) override { return 0; }
+  bool ParseLineTable(CompileUnit &) override { return true; }
+  bool ParseDebugMacros(CompileUnit &) override { return true; }
+  bool ParseSupportFiles(CompileUnit &, SupportFileList &) override {
+    return true;
+  }
+  size_t ParseTypes(CompileUnit &) override { return 0; }
+  bool ParseImportedModules(const SymbolContext &,
+                            std::vector<SourceModule> &) override {
+    return false;
+  }
+  size_t ParseBlocksRecursive(Function &) override { return 0; }
+  size_t ParseVariablesForContext(const SymbolContext &) override { return 0; }
+  Type *ResolveTypeUID(user_id_t) override { return nullptr; }
+  std::optional<ArrayInfo>
+  GetDynamicArrayInfoForUID(user_id_t, const ExecutionContext *) override {
+    return std::nullopt;
+  }
+  bool CompleteType(CompilerType &) override { return true; }
+  uint32_t ResolveSymbolContext(const Address &, SymbolContextItem,
+                                SymbolContext &) override {
+    return 0;
+  }
+  void GetTypes(SymbolContextScope *, TypeClass, TypeList &) override {}
+  Expected<TypeSystemSP> GetTypeSystemForLanguage(LanguageType) override {
+    return createStringError(std::errc::not_supported, "");
+  }
+  const ObjectFile *GetObjectFile() const override {
+    return m_objfile_sp.get();
+  }
+  ObjectFile *GetObjectFile() override { return m_objfile_sp.get(); }
+  ObjectFile *GetMainObjectFile() override { return m_objfile_sp.get(); }
+  void SectionFileAddressesChanged() override {}
+  void Dump(Stream &) override {}
+  uint64_t GetDebugInfoSize(bool) override { return 0; }
+  bool GetDebugInfoIndexWasLoadedFromCache() const override { return false; }
+  void SetDebugInfoIndexWasLoadedFromCache() override {}
+  bool GetDebugInfoIndexWasSavedToCache() const override { return false; }
+  void SetDebugInfoIndexWasSavedToCache() override {}
+  bool GetDebugInfoHadFrameVariableErrors() const override { return false; }
+  void SetDebugInfoHadFrameVariableErrors() override {}
+  TypeSP MakeType(user_id_t, ConstString, std::optional<uint64_t>,
+                  SymbolContextScope *, user_id_t, Type::EncodingDataType,
+                  const Declaration &, const CompilerType &, Type::ResolveState,
+                  uint32_t) override {
+    return nullptr;
+  }
+  TypeSP CopyType(const TypeSP &) override { return nullptr; }
+
+  FakeSymbolFile(ObjectFileSP objfile_sp)
+      : m_objfile_sp(std::move(objfile_sp)) {}
+
+  ObjectFileSP m_objfile_sp;
+  CompUnitSP m_cu_sp;
+};
+
+struct FakeModuleFixture {
+  TestFile file;
+  ModuleSP module_sp;
+  SectionSP text_sp;
+  LineTable *line_table;
+};
+
+class LineTableTest : public testing::Test {
+  SubsystemRAII<ObjectFileELF, FakeSymbolFile> subsystems;
+};
+
+class LineSequenceBuilder {
+public:
+  std::vector<std::unique_ptr<LineSequence>> Build() {
+    return std::move(m_sequences);
+  }
+
+  void Entry(addr_t addr, bool terminal) {
+    LineTable::AppendLineEntryToSequence(
+        m_seq_up.get(), addr, /*line=*/1, /*column=*/0,
+        /*file_idx=*/0,
+        /*is_start_of_statement=*/false, /*is_start_of_basic_block=*/false,
+        /*is_prologue_end=*/false, /*is_epilogue_begin=*/false, terminal);
+    if (terminal) {
+      m_sequences.push_back(std::move(m_seq_up));
+      m_seq_up = LineTable::CreateLineSequenceContainer();
+    }
+  }
+
+private:
+  std::vector<std::unique_ptr<LineSequence>> m_sequences;
+  std::unique_ptr<LineSequence> m_seq_up =
+      LineTable::CreateLineSequenceContainer();
+};
+
+} // namespace
+
+char FakeSymbolFile::ID;
+
+static llvm::Expected<FakeModuleFixture>
+CreateFakeModule(std::vector<std::unique_ptr<LineSequence>> line_sequences) {
+  Expected<TestFile> file = TestFile::fromYaml(R"(
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_386
+Sections:
+  - Name:            .text
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:    0x0010
+    Address:         0x0000
+    Size:            0x1000
+)");
+  if (!file)
+    return file.takeError();
+
+  auto module_sp = std::make_shared<Module>(file->moduleSpec());
+  SectionSP text_sp =
+      module_sp->GetSectionList()->FindSectionByName(ConstString(".text"));
+  if (!text_sp)
+    return createStringError("No .text");
+
+  auto cu_up = std::make_unique<CompileUnit>(module_sp, /*user_data=*/nullptr,
+                                             /*support_file_sp=*/nullptr,
+                                             /*uid=*/0, eLanguageTypeC,
+                                             /*is_optimized=*/eLazyBoolNo);
+  LineTable *line_table = new LineTable(cu_up.get(), std::move(line_sequences));
+  cu_up->SetLineTable(line_table);
+  cast<FakeSymbolFile>(module_sp->GetSymbolFile())
+      ->InjectCompileUnit(std::move(cu_up));
+
+  return FakeModuleFixture{std::move(*file), std::move(module_sp),
+                           std::move(text_sp), line_table};
+}
+
+TEST_F(LineTableTest, LowerAndUpperBound) {
+  LineSequenceBuilder builder;
+  builder.Entry(0, false);
+  builder.Entry(10, false);
+  builder.Entry(20, true);
+  builder.Entry(20, false); // Starts right after the previous sequence.
+  builder.Entry(30, true);
+  builder.Entry(40, false); // Gap after the previous sequence.
+  builder.Entry(50, true);
----------------
JDevlieghere wrote:

```suggestion
  builder.Entry(0);
  builder.Entry(10);
  builder.Entry(20, Terminal);
  builder.Entry(20); // Starts right after the previous sequence.
  builder.Entry(30, Terminal);
  builder.Entry(40); // Gap after the previous sequence.
  builder.Entry(50, Terminal);
```

https://github.com/llvm/llvm-project/pull/127519


More information about the lldb-commits mailing list