diff --git a/lldb/source/Plugins/Process/minidump/CMakeLists.txt b/lldb/source/Plugins/Process/minidump/CMakeLists.txt --- a/lldb/source/Plugins/Process/minidump/CMakeLists.txt +++ b/lldb/source/Plugins/Process/minidump/CMakeLists.txt @@ -1,3 +1,11 @@ +lldb_tablegen(ProcessMinidumpProperties.inc -gen-lldb-property-defs + SOURCE ProcessMinidumpProperties.td + TARGET LLDBPluginProcessMinidumpPropertiesGen) + +lldb_tablegen(ProcessMinidumpPropertiesEnum.inc -gen-lldb-property-enum-defs + SOURCE ProcessMinidumpProperties.td + TARGET LLDBPluginProcessMinidumpPropertiesEnumGen) + add_lldb_library(lldbPluginProcessMinidump PLUGIN MinidumpTypes.cpp MinidumpParser.cpp @@ -19,3 +27,7 @@ Object Support ) + +add_dependencies(lldbPluginProcessMinidump + LLDBPluginProcessMinidumpPropertiesGen + LLDBPluginProcessMinidumpPropertiesEnumGen) diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h --- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h +++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h @@ -35,6 +35,8 @@ static void Initialize(); + static void DebuggerInitialize(Debugger &debugger); + static void Terminate(); static llvm::StringRef GetPluginNameStatic() { return "minidump"; } diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp --- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp +++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp @@ -21,6 +21,7 @@ #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionGroupBoolean.h" +#include "lldb/Interpreter/OptionValueProperties.h" #include "lldb/Target/JITLoaderList.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/SectionLoadList.h" @@ -46,6 +47,55 @@ namespace { +static constexpr OptionEnumValueElement g_abi_enums[] = { + { + llvm::Triple::UnknownEnvironment, + "default", + "Use default target (if it is Windows) or MSVC", + }, + { + llvm::Triple::MSVC, + "msvc", + "MSVC ABI", + }, + { + llvm::Triple::GNU, + "gnu", + "MinGW / Itanium ABI", + }, +}; + +#define LLDB_PROPERTIES_processminidump +#include "ProcessMinidumpProperties.inc" + +enum { +#define LLDB_PROPERTIES_processminidump +#include "ProcessMinidumpPropertiesEnum.inc" +}; + +class PluginProperties : public Properties { +public: + static ConstString GetSettingName() { + return ConstString(ProcessMinidump::GetPluginNameStatic()); + } + + PluginProperties() { + m_collection_sp = std::make_shared(GetSettingName()); + m_collection_sp->Initialize(g_processminidump_properties); + } + + llvm::Triple::EnvironmentType ABI() const { + return (llvm::Triple::EnvironmentType) + m_collection_sp->GetPropertyAtIndexAsEnumeration( + nullptr, ePropertyABI, llvm::Triple::UnknownEnvironment); + } +}; + +static PluginProperties &GetGlobalPluginProperties() { + static PluginProperties g_settings; + return g_settings; +} + /// A minimal ObjectFile implementation providing a dummy object file for the /// cases when the real module binary is not available. This allows the module /// to show up in "image list" and symbols to be added to it. @@ -249,12 +299,23 @@ static llvm::once_flag g_once_flag; llvm::call_once(g_once_flag, []() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), - ProcessMinidump::CreateInstance); + PluginManager::RegisterPlugin( + GetPluginNameStatic(), GetPluginDescriptionStatic(), + ProcessMinidump::CreateInstance, DebuggerInitialize); }); } +void ProcessMinidump::DebuggerInitialize(Debugger &debugger) { + if (!PluginManager::GetSettingForProcessPlugin( + debugger, PluginProperties::GetSettingName())) { + const bool is_global_setting = true; + PluginManager::CreateSettingForProcessPlugin( + debugger, GetGlobalPluginProperties().GetValueProperties(), + ConstString("Properties for the minidump process plug-in."), + is_global_setting); + } +} + void ProcessMinidump::Terminate() { PluginManager::UnregisterPlugin(ProcessMinidump::CreateInstance); } @@ -388,14 +449,24 @@ } ArchSpec ProcessMinidump::GetArchitecture() { + // "settings set plugin.process.minidump.abi" overrides the env in minidump. + ArchSpec arch = m_minidump_parser->GetArchitecture(); + llvm::Triple::EnvironmentType env = GetGlobalPluginProperties().ABI(); + if (env == llvm::Triple::UnknownEnvironment) + env = arch.GetTriple().getEnvironment() != llvm::Triple::UnknownEnvironment + ? arch.GetTriple().getEnvironment() + : llvm::Triple::MSVC; + if (!m_is_wow64) { - return m_minidump_parser->GetArchitecture(); + arch.GetTriple().setEnvironment(env); + return arch; } llvm::Triple triple; triple.setVendor(llvm::Triple::VendorType::UnknownVendor); triple.setArch(llvm::Triple::ArchType::x86); triple.setOS(llvm::Triple::OSType::Win32); + triple.setEnvironment(env); return ArchSpec(triple); } diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidumpProperties.td b/lldb/source/Plugins/Process/minidump/ProcessMinidumpProperties.td new file mode 100644 --- /dev/null +++ b/lldb/source/Plugins/Process/minidump/ProcessMinidumpProperties.td @@ -0,0 +1,9 @@ +include "../../../../include/lldb/Core/PropertiesBase.td" + +let Definition = "processminidump" in { + def ABI: Property<"abi", "Enum">, + Global, + DefaultEnumValue<"llvm::Triple::UnknownEnvironment">, + EnumValues<"OptionEnumValues(g_abi_enums)">, + Desc<"ABI to use when loading a Windows minidump. 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.">; +} diff --git a/lldb/test/Shell/Minidump/Windows/find-module.test b/lldb/test/Shell/Minidump/Windows/find-module.test --- a/lldb/test/Shell/Minidump/Windows/find-module.test +++ b/lldb/test/Shell/Minidump/Windows/find-module.test @@ -4,7 +4,21 @@ RUN: yaml2obj %S/Inputs/find-module.exe.yaml -o %T/find-module.exe RUN: yaml2obj %S/Inputs/find-module.dmp.yaml -o %T/find-module.dmp RUN: %lldb -O "settings set target.exec-search-paths %T" \ -RUN: -c %T/find-module.dmp -o "image dump objfile" -o exit | FileCheck %s +RUN: -c %T/find-module.dmp -o "image dump objfile" -o "target list" -o exit \ +RUN: | FileCheck -DABI=msvc -DFILENAME=%basename_t.tmp %s + +RUN: %lldb -O "settings set plugin.process.minidump.abi msvc" \ +RUN: -O "settings set target.exec-search-paths %T" \ +RUN: -c %T/find-module.dmp -o "image dump objfile" -o "target list" -o exit \ +RUN: | FileCheck -DABI=msvc -DFILENAME=%basename_t.tmp %s + +RUN: %lldb -O "settings set plugin.process.minidump.abi gnu" \ +RUN: -O "settings set target.exec-search-paths %T" \ +RUN: -c %T/find-module.dmp -o "image dump objfile" -o "target list" -o exit \ +RUN: | FileCheck -DABI=gnu -DFILENAME=%basename_t.tmp %s CHECK-LABEL: image dump objfile CHECK: ObjectFilePECOFF, file = '{{.*}}find-module.exe', arch = i386 + +CHECK-LABEL: target list +CHECK: arch=i386-pc-windows-[[ABI]] diff --git a/llvm/utils/gn/secondary/lldb/source/Plugins/Process/minidump/BUILD.gn b/llvm/utils/gn/secondary/lldb/source/Plugins/Process/minidump/BUILD.gn --- a/llvm/utils/gn/secondary/lldb/source/Plugins/Process/minidump/BUILD.gn +++ b/llvm/utils/gn/secondary/lldb/source/Plugins/Process/minidump/BUILD.gn @@ -1,7 +1,20 @@ +import("//lldb/utils/TableGen/lldb_tablegen.gni") + +lldb_tablegen("ProcessMinidumpProperties") { + args = [ "-gen-lldb-property-defs" ] +} + +lldb_tablegen("ProcessMinidumpPropertiesEnum") { + args = [ "-gen-lldb-property-enum-defs" ] + td_file = "ProcessMinidumpProperties.td" +} + static_library("minidump") { output_name = "lldbPluginProcessMinidump" configs += [ "//llvm/utils/gn/build:lldb_code" ] deps = [ + ":ProcessMinidumpProperties", + ":ProcessMinidumpPropertiesEnum", "//lldb/source/Core", "//lldb/source/Plugins/Process/Utility", "//lldb/source/Plugins/Process/elf-core",