Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ add_lldb_library(lldbPluginCPPRuntime
)

add_subdirectory(ItaniumABI)
#add_subdirectory(MicrosoftABI)
add_subdirectory(MicrosoftABI)
Original file line number Diff line number Diff line change
Expand Up @@ -491,3 +491,10 @@ bool CPPLanguageRuntime::IsSymbolARuntimeThunk(const Symbol &symbol) {
return mangled_name.starts_with("_ZTh") || mangled_name.starts_with("_ZTv") ||
mangled_name.starts_with("_ZTc");
}

bool CPPLanguageRuntime::ShouldUseMicrosoftABI(Process *process) {
return process->GetTarget()
.GetArchitecture()
.GetTriple()
.isWindowsMSVCEnvironment();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this distinguish whether the target process to be debugged is mingw or msvc style? Does this in the end just determine the style based on which flavour LLDB itself was built as?

Note that one process may include multiple DLLs that use both ABIs. (In particular, most mingw executables link in a bunch of MS DLLs that internally use their C++ ABI - even though we perhaps don't have debug info for them normally.)

And one may want to use a MSVC built LLDB for debugging mingw executables, or vice versa.

See 25c8a06 and 3c86789 for existing options that allow controlling which C++ ABI to use for interpreting things; these options allow controlling this on the level of each individual DLL. Can't the information from those preexisting options be used here, instead of inventing a new and less flexible approach?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, this inherits the style LLDB was built as. The language runtime being tied to a process and language is too coarse for allowing mixed ABIs in different DLLs.

An alternative could be to handle both ABIs in the Itanium plugin (but rename it). So for dynamic types, it could check the module or determine the ABI based on the mangled symbol name. For exception breakpoints, all function names would need to be registered. Would that be a better idea?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. I'm too unfamiliar with the LLDB aspects involved here to be able to have any clue about what you're suggesting (and how much extra complexity it would add) unfortunately... Also, can you give a quick high level explanation of which ABI aspects were covered by the existing switches added in 25c8a06, compared with what aspects of debugging this newly added code covers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, then the changes in 25c8a06 mostly affected how the clang AST is created for modules.

By adding a language runtime that supports the MS ABI, I'm trying to add the capability to downcast references to a base class when using virtual inheritance and to break when C++ exceptions are thrown.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see - thanks for the explanation! So whichever way we deal with this, the old option for switching mode for the Clang AST should keep working to the extent it did before. Also CC @alvinhochun.

If it is possible to handle this in a more granular way (tied either to the same options as above) then that's certainly very much appreciated, but I guess it's not a blocker. I'd leave that judgement up to you, if you feel it'd be doable or if it'd be too much mess for a potentially uncommon case.

Btw, I occasionally try to get the LLDB tests running in mingw mode as well. I haven't got that finished up to a state where all tests pass, I'm currently at around 16 tests failing and 1 unexpectedly passing, but haven't had much time to devote to it lately.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do want to keep LLDB's ability to debug mixed DLLs from different ABIs simultaneously. Having separate plugins for each ABI won't work here (I think?), because they'd be tied to the same language.

Currently, ItaniumABILanguageRuntime inherits from CPPLanguageRuntime. What about moving the methods from the Itanium ABI to the C++ language runtime plugin? GetDynamicTypeAndAddress and GetVTableInfo would then check for the value's module and branch based on that (to account for 25c8a06). @JDevlieghere do you have any thoughts on this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what you're suggesting is the most pragmatic solution. The alternative is detangling the two and everywhere where we obtain a language runtime today, you would have to specify a language and an ABI and the ABI would be tied (and potentially shared) across modules. I think that's probably a lot of work for little benefit, so I'm fine with going with the more pragmatic approach.

}
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ class CPPLanguageRuntime : public LanguageRuntime {

bool IsSymbolARuntimeThunk(const Symbol &symbol) override;

static bool ShouldUseMicrosoftABI(Process *process);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than returning a bool, can we have an enum for the C++ runtime ABIs and have this return either Itanium or Microsoft?


protected:
// Classes that inherit from CPPLanguageRuntime can see and modify these
CPPLanguageRuntime(Process *process);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -397,9 +397,9 @@ TypeAndOrName ItaniumABILanguageRuntime::FixUpDynamicType(
LanguageRuntime *
ItaniumABILanguageRuntime::CreateInstance(Process *process,
lldb::LanguageType language) {
// FIXME: We have to check the process and make sure we actually know that
// this process supports
// the Itanium ABI.
if (ShouldUseMicrosoftABI(process))
return nullptr;

if (language == eLanguageTypeC_plus_plus ||
language == eLanguageTypeC_plus_plus_03 ||
language == eLanguageTypeC_plus_plus_11 ||
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
add_lldb_library(lldbPluginCXXMicrosoftABI PLUGIN
MicrosoftABILanguageRuntime.cpp

LINK_LIBS
lldbPluginCPPRuntime
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//===----------------------------------------------------------------------===//
//
// 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 "MicrosoftABILanguageRuntime.h"

#include "lldb/Core/PluginManager.h"
#include "lldb/Target/Process.h"

using namespace lldb;
using namespace lldb_private;

LLDB_PLUGIN_DEFINE_ADV(MicrosoftABILanguageRuntime, CXXMicrosoftABI)

char MicrosoftABILanguageRuntime::ID = 0;

void MicrosoftABILanguageRuntime::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
"Microsoft ABI for the C++ language",
CreateInstance);
}

void MicrosoftABILanguageRuntime::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}

LanguageRuntime *
MicrosoftABILanguageRuntime::CreateInstance(Process *process,
lldb::LanguageType language) {
if (!ShouldUseMicrosoftABI(process))
return nullptr;

if (!(language == eLanguageTypeC_plus_plus ||
language == eLanguageTypeC_plus_plus_03 ||
language == eLanguageTypeC_plus_plus_11 ||
language == eLanguageTypeC_plus_plus_14))
return nullptr;

return new MicrosoftABILanguageRuntime(process);
}

llvm::Expected<LanguageRuntime::VTableInfo>
MicrosoftABILanguageRuntime::GetVTableInfo(ValueObject &in_value,
bool check_type) {
return llvm::createStringError("Not implemented");
}

bool MicrosoftABILanguageRuntime::GetDynamicTypeAndAddress(
ValueObject &in_value, lldb::DynamicValueType use_dynamic,
TypeAndOrName &class_type_or_name, Address &address,
Value::ValueType &value_type, llvm::ArrayRef<uint8_t> &local_buffer) {
return false;
}

TypeAndOrName MicrosoftABILanguageRuntime::FixUpDynamicType(
const TypeAndOrName &type_and_or_name, ValueObject &static_value) {
return type_and_or_name;
}

bool MicrosoftABILanguageRuntime::CouldHaveDynamicValue(ValueObject &in_value) {
return false;
}

lldb::BreakpointResolverSP MicrosoftABILanguageRuntime::CreateExceptionResolver(
const lldb::BreakpointSP &bkpt, bool catch_bp, bool throw_bp) {
return nullptr;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_CPLUSPLUS_MICROSOFTABI_MICROSOFTABILANGUAGERUNTIME_H
#define LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_CPLUSPLUS_MICROSOFTABI_MICROSOFTABILANGUAGERUNTIME_H

#include "lldb/Core/Value.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Target/LanguageRuntime.h"

#include "Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h"

namespace lldb_private {

class MicrosoftABILanguageRuntime : public CPPLanguageRuntime {
public:
static void Initialize();

static void Terminate();

static lldb_private::LanguageRuntime *
CreateInstance(Process *process, lldb::LanguageType language);

static llvm::StringRef GetPluginNameStatic() { return "microsoft-abi"; }

static char ID;

bool isA(const void *ClassID) const override {
return ClassID == &ID || CPPLanguageRuntime::isA(ClassID);
}

static bool classof(const LanguageRuntime *runtime) {
return runtime->isA(&ID);
}

llvm::Expected<LanguageRuntime::VTableInfo>
GetVTableInfo(ValueObject &in_value, bool check_type) override;

bool GetDynamicTypeAndAddress(ValueObject &in_value,
lldb::DynamicValueType use_dynamic,
TypeAndOrName &class_type_or_name,
Address &address, Value::ValueType &value_type,
llvm::ArrayRef<uint8_t> &local_buffer) override;

TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name,
ValueObject &static_value) override;

bool CouldHaveDynamicValue(ValueObject &in_value) override;

llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }

lldb::BreakpointResolverSP
CreateExceptionResolver(const lldb::BreakpointSP &bkpt, bool catch_bp,
bool throw_bp) override;

private:
MicrosoftABILanguageRuntime(Process *process) : CPPLanguageRuntime(process) {}
};

} // namespace lldb_private

#endif
Loading