[Lldb-commits] [lldb] 3c86789 - [lldb] Add setting to override PE/COFF ABI by module name

Martin Storsjö via lldb-commits lldb-commits at lists.llvm.org
Wed Jun 22 07:17:12 PDT 2022


Author: Alvin Wong
Date: 2022-06-22T17:16:06+03:00
New Revision: 3c867898c7be7ed2b5d119a2478a836a0c85f19b

URL: https://github.com/llvm/llvm-project/commit/3c867898c7be7ed2b5d119a2478a836a0c85f19b
DIFF: https://github.com/llvm/llvm-project/commit/3c867898c7be7ed2b5d119a2478a836a0c85f19b.diff

LOG: [lldb] Add setting to override PE/COFF ABI by module name

The setting `plugin.object-file.pe-coff.module-abi` is a string-to-enum
map that allows specifying an ABI to a module name. For example:

    ucrtbase.dll=msvc
    libstdc++-6.dll=gnu

This allows for debugging a process which mixes both modules built using
the MSVC ABI and modules built using the MinGW ABI.

Depends on D127048

Reviewed By: DavidSpickett

Differential Revision: https://reviews.llvm.org/D127234

Added: 
    

Modified: 
    lldb/include/lldb/Interpreter/OptionValueDictionary.h
    lldb/source/Interpreter/OptionValueDictionary.cpp
    lldb/source/Interpreter/Property.cpp
    lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
    lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFFProperties.td
    lldb/test/Shell/ObjectFile/PECOFF/settings-abi.yaml

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Interpreter/OptionValueDictionary.h b/lldb/include/lldb/Interpreter/OptionValueDictionary.h
index f96cbc9fe9e75..4c6bcaecd4c78 100644
--- a/lldb/include/lldb/Interpreter/OptionValueDictionary.h
+++ b/lldb/include/lldb/Interpreter/OptionValueDictionary.h
@@ -12,6 +12,7 @@
 #include <map>
 
 #include "lldb/Interpreter/OptionValue.h"
+#include "lldb/lldb-private-types.h"
 
 namespace lldb_private {
 
@@ -19,8 +20,10 @@ class OptionValueDictionary
     : public Cloneable<OptionValueDictionary, OptionValue> {
 public:
   OptionValueDictionary(uint32_t type_mask = UINT32_MAX,
+                        OptionEnumValues enum_values = OptionEnumValues(),
                         bool raw_value_dump = true)
-      : m_type_mask(type_mask), m_raw_value_dump(raw_value_dump) {}
+      : m_type_mask(type_mask), m_enum_values(enum_values),
+        m_raw_value_dump(raw_value_dump) {}
 
   ~OptionValueDictionary() override = default;
 
@@ -75,6 +78,7 @@ class OptionValueDictionary
 protected:
   typedef std::map<ConstString, lldb::OptionValueSP> collection;
   uint32_t m_type_mask;
+  OptionEnumValues m_enum_values;
   collection m_values;
   bool m_raw_value_dump;
 };

diff  --git a/lldb/source/Interpreter/OptionValueDictionary.cpp b/lldb/source/Interpreter/OptionValueDictionary.cpp
index 26fed4a987e15..6baafc9213e1a 100644
--- a/lldb/source/Interpreter/OptionValueDictionary.cpp
+++ b/lldb/source/Interpreter/OptionValueDictionary.cpp
@@ -8,11 +8,12 @@
 
 #include "lldb/Interpreter/OptionValueDictionary.h"
 
-#include "llvm/ADT/StringRef.h"
 #include "lldb/DataFormatters/FormatManager.h"
+#include "lldb/Interpreter/OptionValueEnumeration.h"
 #include "lldb/Interpreter/OptionValueString.h"
 #include "lldb/Utility/Args.h"
 #include "lldb/Utility/State.h"
+#include "llvm/ADT/StringRef.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -161,16 +162,26 @@ Status OptionValueDictionary::SetArgs(const Args &args,
         return error;
       }
 
-      lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
-          value.str().c_str(), m_type_mask, error));
-      if (value_sp) {
+      if (m_type_mask == 1u << eTypeEnum) {
+        auto enum_value =
+            std::make_shared<OptionValueEnumeration>(m_enum_values, 0);
+        error = enum_value->SetValueFromString(value);
         if (error.Fail())
           return error;
         m_value_was_set = true;
-        SetValueForKey(ConstString(key), value_sp, true);
+        SetValueForKey(ConstString(key), enum_value, true);
       } else {
-        error.SetErrorString("dictionaries that can contain multiple types "
-                             "must subclass OptionValueArray");
+        lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
+            value.str().c_str(), m_type_mask, error));
+        if (value_sp) {
+          if (error.Fail())
+            return error;
+          m_value_was_set = true;
+          SetValueForKey(ConstString(key), value_sp, true);
+        } else {
+          error.SetErrorString("dictionaries that can contain multiple types "
+                               "must subclass OptionValueArray");
+        }
       }
     }
     break;

diff  --git a/lldb/source/Interpreter/Property.cpp b/lldb/source/Interpreter/Property.cpp
index fe3a8a31394b5..681596224d31a 100644
--- a/lldb/source/Interpreter/Property.cpp
+++ b/lldb/source/Interpreter/Property.cpp
@@ -68,9 +68,10 @@ Property::Property(const PropertyDefinition &definition)
   }
   case OptionValue::eTypeDictionary:
     // "definition.default_uint_value" is always a OptionValue::Type
-    m_value_sp =
-        std::make_shared<OptionValueDictionary>(OptionValue::ConvertTypeToMask(
-            (OptionValue::Type)definition.default_uint_value));
+    m_value_sp = std::make_shared<OptionValueDictionary>(
+        OptionValue::ConvertTypeToMask(
+            (OptionValue::Type)definition.default_uint_value),
+        definition.enum_values);
     break;
 
   case OptionValue::eTypeEnum:

diff  --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
index d1e0507f1dde3..fd34ac65970ba 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -16,6 +16,7 @@
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/Section.h"
 #include "lldb/Core/StreamFile.h"
+#include "lldb/Interpreter/OptionValueDictionary.h"
 #include "lldb/Interpreter/OptionValueProperties.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Target/Process.h"
@@ -91,6 +92,11 @@ class PluginProperties : public Properties {
         m_collection_sp->GetPropertyAtIndexAsEnumeration(
             nullptr, ePropertyABI, llvm::Triple::UnknownEnvironment);
   }
+
+  OptionValueDictionary *ModuleABIMap() const {
+    return m_collection_sp->GetPropertyAtIndexAsOptionValueDictionary(
+        nullptr, ePropertyModuleABIMap);
+  }
 };
 
 static PluginProperties &GetGlobalPluginProperties() {
@@ -283,7 +289,41 @@ size_t ObjectFilePECOFF::GetModuleSpecifications(
     return llvm::Triple::MSVC;
   }();
 
-  llvm::Triple::EnvironmentType env = GetGlobalPluginProperties().ABI();
+  // Check for a module-specific override.
+  OptionValueSP module_env_option;
+  const auto *map = GetGlobalPluginProperties().ModuleABIMap();
+  if (map->GetNumValues() > 0) {
+    // Step 1: Try with the exact file name.
+    auto name = file.GetLastPathComponent();
+    module_env_option = map->GetValueForKey(name);
+    if (!module_env_option) {
+      // Step 2: Try with the file name in lowercase.
+      auto name_lower = name.GetStringRef().lower();
+      module_env_option =
+          map->GetValueForKey(ConstString(llvm::StringRef(name_lower)));
+    }
+    if (!module_env_option) {
+      // Step 3: Try with the file name with ".debug" suffix stripped.
+      auto name_stripped = name.GetStringRef();
+      if (name_stripped.consume_back_insensitive(".debug")) {
+        module_env_option = map->GetValueForKey(ConstString(name_stripped));
+        if (!module_env_option) {
+          // Step 4: Try with the file name in lowercase with ".debug" suffix
+          // stripped.
+          auto name_lower = name_stripped.lower();
+          module_env_option =
+              map->GetValueForKey(ConstString(llvm::StringRef(name_lower)));
+        }
+      }
+    }
+  }
+  llvm::Triple::EnvironmentType env;
+  if (module_env_option)
+    env =
+        (llvm::Triple::EnvironmentType)module_env_option->GetEnumerationValue();
+  else
+    env = GetGlobalPluginProperties().ABI();
+
   if (env == llvm::Triple::UnknownEnvironment)
     env = default_env;
 

diff  --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFFProperties.td b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFFProperties.td
index b2a262fd708b0..7655f6dab3843 100644
--- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFFProperties.td
+++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFFProperties.td
@@ -6,4 +6,9 @@ let Definition = "objectfilepecoff" in {
     DefaultEnumValue<"llvm::Triple::UnknownEnvironment">,
     EnumValues<"OptionEnumValues(g_abi_enums)">,
     Desc<"ABI to use when loading a PE/COFF module. This configures the C++ ABI used, which affects things like the handling of class layout. Accepted values are: `msvc` for the MSVC ABI, `gnu` for the MinGW / Itanium ABI, and `default` to follow the default target if it is a Windows triple or use the MSVC ABI by default.">;
+  def ModuleABIMap: Property<"module-abi", "Dictionary">,
+    Global,
+    ElementType<"Enum">,
+    EnumValues<"OptionEnumValues(g_abi_enums)">,
+    Desc<"A mapping of ABI override to use for specific modules. The module name is matched by its file name with extension. These versions are checked in sequence: exact, lowercase, exact with '.debug' suffix stripped, lowercase with '.debug' suffix stripped. Accepted values are: `msvc` for the MSVC ABI, `gnu` for the MinGW / Itanium ABI, and `default` to follow the default target if it is a Windows triple or use the MSVC ABI by default.">;
 }

diff  --git a/lldb/test/Shell/ObjectFile/PECOFF/settings-abi.yaml b/lldb/test/Shell/ObjectFile/PECOFF/settings-abi.yaml
index d7eb3729be708..22cb160f26fcc 100644
--- a/lldb/test/Shell/ObjectFile/PECOFF/settings-abi.yaml
+++ b/lldb/test/Shell/ObjectFile/PECOFF/settings-abi.yaml
@@ -1,4 +1,8 @@
 # RUN: yaml2obj %s -o %t
+# RUN: yaml2obj %s -o %t.debug
+# RUN: mkdir -p %t.dir
+# RUN: yaml2obj %s -o %t.dir/UPPER_CASE
+# RUN: yaml2obj %s -o %t.dir/UPPER_CASE.debug
 
 ## Default ABI is msvc:
 # RUN: %lldb -O "settings set plugin.object-file.pe-coff.abi msvc" \
@@ -10,6 +14,57 @@
 # RUN:   -f %t -o "image list --triple --basename" -o exit | \
 # RUN:   FileCheck -DABI=gnu -DFILENAME=%basename_t.tmp %s
 
+## Default ABI is msvc, module override is gnu:
+# RUN: %lldb -O "settings set plugin.object-file.pe-coff.abi msvc" \
+# RUN:   -O "settings append plugin.object-file.pe-coff.module-abi %basename_t.tmp=gnu" \
+# RUN:   -f %t -o "image list --triple --basename" -o exit | \
+# RUN:   FileCheck -DABI=gnu -DFILENAME=%basename_t.tmp %s
+
+## Default ABI is gnu, module override is msvc:
+# RUN: %lldb -O "settings set plugin.object-file.pe-coff.abi gnu" \
+# RUN:   -O "settings append plugin.object-file.pe-coff.module-abi %basename_t.tmp=msvc" \
+# RUN:   -f %t -o "image list --triple --basename" -o exit | \
+# RUN:   FileCheck -DABI=msvc -DFILENAME=%basename_t.tmp %s
+
+## Default ABI is msvc, module override is gnu (with .debug suffix):
+# RUN: %lldb -O "settings set plugin.object-file.pe-coff.abi msvc" \
+# RUN:   -O "settings append plugin.object-file.pe-coff.module-abi %basename_t.tmp=gnu" \
+# RUN:   -f %t.debug -o "image list --triple --basename" -o exit | \
+# RUN:   FileCheck -DABI=gnu -DFILENAME=%basename_t.tmp.debug %s
+
+## Default ABI is gnu, module override is msvc (with .debug suffix):
+# RUN: %lldb -O "settings set plugin.object-file.pe-coff.abi gnu" \
+# RUN:   -O "settings append plugin.object-file.pe-coff.module-abi %basename_t.tmp=msvc" \
+# RUN:   -f %t.debug -o "image list --triple --basename" -o exit | \
+# RUN:   FileCheck -DABI=msvc -DFILENAME=%basename_t.tmp.debug %s
+
+## Check that case-sensitive match is chosen before lower-case:
+# RUN: %lldb -O "settings set plugin.object-file.pe-coff.abi msvc" \
+# RUN:   -O "settings append plugin.object-file.pe-coff.module-abi upper_case=msvc" \
+# RUN:   -O "settings append plugin.object-file.pe-coff.module-abi UPPER_CASE=gnu" \
+# RUN:   -f %t.dir/UPPER_CASE -o "image list --triple --basename" -o exit | \
+# RUN:   FileCheck -DABI=gnu -DFILENAME=UPPER_CASE %s
+
+## Check that lower-case match with .debug suffix is chosen before case-sensitive match without .debug suffix:
+# RUN: %lldb -O "settings set plugin.object-file.pe-coff.abi msvc" \
+# RUN:   -O "settings append plugin.object-file.pe-coff.module-abi UPPER_CASE=msvc" \
+# RUN:   -O "settings append plugin.object-file.pe-coff.module-abi upper_case.debug=gnu" \
+# RUN:   -f %t.dir/UPPER_CASE.debug -o "image list --triple --basename" -o exit | \
+# RUN:   FileCheck -DABI=gnu -DFILENAME=UPPER_CASE.debug %s
+
+## Check that case-sensitive match without .debug suffix is chosen before lower-case match without .debug suffix:
+# RUN: %lldb -O "settings set plugin.object-file.pe-coff.abi msvc" \
+# RUN:   -O "settings append plugin.object-file.pe-coff.module-abi upper_case.debug=msvc" \
+# RUN:   -O "settings append plugin.object-file.pe-coff.module-abi UPPER_CASE.debug=gnu" \
+# RUN:   -f %t.dir/UPPER_CASE.debug -o "image list --triple --basename" -o exit | \
+# RUN:   FileCheck -DABI=gnu -DFILENAME=UPPER_CASE.debug %s
+
+## Check that lower-case match without .debug suffix works:
+# RUN: %lldb -O "settings set plugin.object-file.pe-coff.abi msvc" \
+# RUN:   -O "settings append plugin.object-file.pe-coff.module-abi upper_case.debug=gnu" \
+# RUN:   -f %t.dir/UPPER_CASE.debug -o "image list --triple --basename" -o exit | \
+# RUN:   FileCheck -DABI=gnu -DFILENAME=UPPER_CASE.debug %s
+
 # CHECK-LABEL: image list --triple --basename
 # CHECK-NEXT: x86_64-pc-windows-[[ABI]] [[FILENAME]]
 


        


More information about the lldb-commits mailing list