diff --git a/lldb/bindings/interface/SBTarget.i b/lldb/bindings/interface/SBTarget.i --- a/lldb/bindings/interface/SBTarget.i +++ b/lldb/bindings/interface/SBTarget.i @@ -966,6 +966,8 @@ lldb::SBStructuredData GetStatistics(); + lldb::SBStructuredData GetSourceMap(); + bool operator == (const lldb::SBTarget &rhs) const; diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h --- a/lldb/include/lldb/API/SBTarget.h +++ b/lldb/include/lldb/API/SBTarget.h @@ -85,6 +85,12 @@ /// A SBStructuredData with the statistics collected. lldb::SBStructuredData GetStatistics(); + /// Returns a dump of the source map settings. + /// + /// \return + /// A SBStructuredData with the source map entries collected. + lldb::SBStructuredData GetSourceMap(); + /// Return the platform object associated with the target. /// /// After return, the platform object should be checked for @@ -321,7 +327,7 @@ uint32_t GetAddressByteSize(); const char *GetTriple(); - + const char *GetABIName(); /// Architecture data byte width accessor diff --git a/lldb/include/lldb/Target/PathMappingList.h b/lldb/include/lldb/Target/PathMappingList.h --- a/lldb/include/lldb/Target/PathMappingList.h +++ b/lldb/include/lldb/Target/PathMappingList.h @@ -13,6 +13,7 @@ #include #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Status.h" +#include "llvm/Support/JSON.h" namespace lldb_private { @@ -41,6 +42,8 @@ // By default, dump all pairs. void Dump(Stream *s, int pair_index = -1); + llvm::json::Value ToJSON(); + bool IsEmpty() const { return m_pairs.empty(); } size_t GetSize() const { return m_pairs.size(); } diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -211,6 +211,21 @@ return data; } +SBStructuredData SBTarget::GetSourceMap() { + LLDB_INSTRUMENT_VA(this); + + SBStructuredData data; + TargetSP target_sp(GetSP()); + if (!target_sp) + return data; + + std::string json_str = + llvm::formatv("{0:2}", + target_sp->GetSourcePathMap().ToJSON()).str(); + data.m_impl_up->SetObjectSP(StructuredData::ParseJSON(json_str)); + return data; +} + void SBTarget::SetCollectingStats(bool v) { LLDB_INSTRUMENT_VA(this, v); @@ -1590,7 +1605,7 @@ const char *SBTarget::GetABIName() { LLDB_INSTRUMENT_VA(this); - + TargetSP target_sp(GetSP()); if (target_sp) { std::string abi_name(target_sp->GetABIName().str()); diff --git a/lldb/source/Target/PathMappingList.cpp b/lldb/source/Target/PathMappingList.cpp --- a/lldb/source/Target/PathMappingList.cpp +++ b/lldb/source/Target/PathMappingList.cpp @@ -131,6 +131,17 @@ } } +llvm::json::Value PathMappingList::ToJSON() { + llvm::json::Array entries; + for (const auto &pair : m_pairs) { + llvm::json::Object entry; + entry.try_emplace("first", pair.first.GetStringRef().str()); + entry.try_emplace("second", pair.second.GetStringRef().str()); + entries.emplace_back(std::move(entry)); + } + return std::move(entries); +} + void PathMappingList::Clear(bool notify) { if (!m_pairs.empty()) ++m_mod_id; diff --git a/lldb/test/API/functionalities/source-map/TestTargetSourceMap.py b/lldb/test/API/functionalities/source-map/TestTargetSourceMap.py --- a/lldb/test/API/functionalities/source-map/TestTargetSourceMap.py +++ b/lldb/test/API/functionalities/source-map/TestTargetSourceMap.py @@ -1,11 +1,49 @@ import lldb from lldbsuite.test.lldbtest import * from lldbsuite.test.decorators import * +import json import os class TestTargetSourceMap(TestBase): + @no_debug_info_test + def test_source_map_target_api(self): + """ + Test that ensures SBTarget::GetSourceMap() API can correctly fetch + source mapping entries. + """ + # Set the target soure map to map "./" to the current test directory + src_dir = self.getSourceDir() + src_path = os.path.join(src_dir, "main.c") + yaml_path = os.path.join(src_dir, "a.yaml") + yaml_base, ext = os.path.splitext(yaml_path) + obj_path = self.getBuildArtifact("main.o") + self.yaml2obj(yaml_path, obj_path) + + # Create a target with the object file we just created from YAML + target = self.dbg.CreateTarget(obj_path) + + initial_source_map = target.GetSourceMap() + self.assertEquals(initial_source_map.GetSize(), 0, + "Initial source map should be empty") + + src_dir = self.getSourceDir() + self.runCmd('settings append target.source-map . "%s"' % src_dir) + + source_map = target.GetSourceMap() + self.assertEquals(source_map.GetSize(), 1, + "source map should be have one appended entry") + + stream = lldb.SBStream() + source_map.GetAsJSON(stream) + serialized_source_map = json.loads(stream.GetData()) + self.assertEquals(serialized_source_map[0]["first"], ".", + "source map entry 'first' does not match") + self.assertEquals(serialized_source_map[0]["second"], src_dir, + "source map entry 'second' does not match") + + @no_debug_info_test def test_source_map(self): """Test target.source-map' functionality."""