Author: Alexandre Perez
Date: 2024-07-31T10:57:40-07:00
New Revision: 0a01e8ff530ab15277aa9fad5361297d7b55e247

URL: 
https://github.com/llvm/llvm-project/commit/0a01e8ff530ab15277aa9fad5361297d7b55e247
DIFF: 
https://github.com/llvm/llvm-project/commit/0a01e8ff530ab15277aa9fad5361297d7b55e247.diff

LOG: [lldb] Allow mapping object file paths (#101361)

This introduces a `target.object-map` which allows us to remap module
locations, much in the same way as source mapping works today. This is
useful, for instance, when debugging coredumps, so we can replace some
of the locations where LLDB attempts to load shared libraries and
executables from, without having to setup an entire sysroot.

Added: 
    

Modified: 
    lldb/include/lldb/Target/Target.h
    lldb/source/Target/Target.cpp
    lldb/source/Target/TargetProperties.td
    lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Target/Target.h 
b/lldb/include/lldb/Target/Target.h
index 5d5ae1bfcd3bd..119dff4d49819 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -141,6 +141,8 @@ class TargetProperties : public Properties {
 
   PathMappingList &GetSourcePathMap() const;
 
+  PathMappingList &GetObjectPathMap() const;
+
   bool GetAutoSourceMapRelative() const;
 
   FileSpecList GetExecutableSearchPaths();

diff  --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index ec0da8a1378a8..129683c43f0c1 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -2155,12 +2155,21 @@ bool Target::ReadPointerFromMemory(const Address &addr, 
Status &error,
   return false;
 }
 
-ModuleSP Target::GetOrCreateModule(const ModuleSpec &module_spec, bool notify,
-                                   Status *error_ptr) {
+ModuleSP Target::GetOrCreateModule(const ModuleSpec &orig_module_spec,
+                                   bool notify, Status *error_ptr) {
   ModuleSP module_sp;
 
   Status error;
 
+  // Apply any remappings specified in target.object-map:
+  ModuleSpec module_spec(orig_module_spec);
+  PathMappingList &obj_mapping = GetObjectPathMap();
+  if (std::optional<FileSpec> remapped_obj_file =
+          obj_mapping.RemapPath(orig_module_spec.GetFileSpec().GetPath(),
+                                true /* only_if_exists */)) {
+    module_spec.GetFileSpec().SetPath(remapped_obj_file->GetPath());
+  }
+
   // First see if we already have this module in our module list.  If we do,
   // then we're done, we don't need to consult the shared modules list.  But
   // only do this if we are passed a UUID.
@@ -4459,6 +4468,14 @@ PathMappingList &TargetProperties::GetSourcePathMap() 
const {
   return option_value->GetCurrentValue();
 }
 
+PathMappingList &TargetProperties::GetObjectPathMap() const {
+  const uint32_t idx = ePropertyObjectMap;
+  OptionValuePathMappings *option_value =
+      m_collection_sp->GetPropertyAtIndexAsOptionValuePathMappings(idx);
+  assert(option_value);
+  return option_value->GetCurrentValue();
+}
+
 bool TargetProperties::GetAutoSourceMapRelative() const {
   const uint32_t idx = ePropertyAutoSourceMapRelative;
   return GetPropertyAtIndexAs<bool>(

diff  --git a/lldb/source/Target/TargetProperties.td 
b/lldb/source/Target/TargetProperties.td
index 7f79218e0a6a4..4404a45492254 100644
--- a/lldb/source/Target/TargetProperties.td
+++ b/lldb/source/Target/TargetProperties.td
@@ -46,6 +46,9 @@ let Definition = "target" in {
   def SourceMap: Property<"source-map", "PathMap">,
     DefaultStringValue<"">,
     Desc<"Source path remappings apply substitutions to the paths of source 
files, typically needed to debug from a 
diff erent host than the one that built the target.  The source-map property 
consists of an array of pairs, the first element is a path prefix, and the 
second is its replacement.  The syntax is `prefix1 replacement1 prefix2 
replacement2...`.  The pairs are checked in order, the first prefix that 
matches is used, and that prefix is substituted with the replacement.  A common 
pattern is to use source-map in conjunction with the clang -fdebug-prefix-map 
flag.  In the build, use `-fdebug-prefix-map=/path/to/build_dir=.` to rewrite 
the host specific build directory to `.`.  Then for debugging, use `settings 
set target.source-map . /path/to/local_dir` to convert `.` to a valid local 
path.">;
+  def ObjectMap: Property<"object-map", "PathMap">,
+    DefaultStringValue<"">,
+    Desc<"Object path remappings apply substitutions to the paths of object 
files, typically needed to debug from a 
diff erent host than the one that built the target.  The object-map property 
consists of an array of pairs, the first element is a path prefix, and the 
second is its replacement.  The syntax is `prefix1 replacement1 prefix2 
replacement2...`.  The pairs are checked in order, the first prefix that 
matches is used, and that prefix is substituted with the replacement.">;
   def AutoSourceMapRelative: Property<"auto-source-map-relative", "Boolean">,
     DefaultTrue,
     Desc<"Automatically deduce source path mappings based on source file 
breakpoint resolution. It only deduces source mapping if source file breakpoint 
request is using full path and if the debug info contains relative paths.">;

diff  --git 
a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py 
b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
index 0afac26367de0..0b9d17bc9f45e 100644
--- a/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
+++ b/lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
@@ -249,6 +249,32 @@ def test_i386_sysroot(self):
 
         self.dbg.DeleteTarget(target)
 
+    def test_object_map(self):
+        """Test that lldb can find the exe for an i386 linux core file using 
the object map."""
+
+        # Copy linux-i386.out to lldb_i386_object_map/a.out
+        tmp_object_map_root = os.path.join(self.getBuildDir(), 
"lldb_i386_object_map")
+        executable = os.path.join(tmp_object_map_root, "a.out")
+        lldbutil.mkdir_p(os.path.dirname(executable))
+        shutil.copyfile("linux-i386.out", executable)
+
+        # Replace the original module path at /home/labath/test and load the 
core
+        self.runCmd(
+            "settings set target.object-map /home/labath/test {}".format(
+                tmp_object_map_root
+            )
+        )
+
+        target = self.dbg.CreateTarget(None)
+        process = target.LoadCore("linux-i386.core")
+
+        # Check that we did load the mapped executable
+        exe_module_spec = process.GetTarget().GetModuleAtIndex(0).GetFileSpec()
+        
self.assertTrue(exe_module_spec.fullpath.startswith(tmp_object_map_root))
+
+        self.check_all(process, self._i386_pid, self._i386_regions, "a.out")
+        self.dbg.DeleteTarget(target)
+
     @skipIfLLVMTargetMissing("X86")
     @skipIfWindows
     def test_x86_64_sysroot(self):


        
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to