aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-01-17 20:45:01 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-01-17 20:45:01 +0000
commit706b4fc47bbc608932d3b491ae19a3b9cde9497b (patch)
tree4adf86a776049cbf7f69a1929c4babcbbef925eb /lldb/source/Plugins
parent7cc9cf2bf09f069cb2dd947ead05d0b54301fb71 (diff)
downloadsrc-706b4fc47bbc608932d3b491ae19a3b9cde9497b.tar.gz
src-706b4fc47bbc608932d3b491ae19a3b9cde9497b.zip
Vendor import of llvm-project master e26a78e70, the last commit beforevendor/llvm-project/llvmorg-10-init-17466-ge26a78e7085
the llvmorg-11-init tag, from which release/10.x was branched.
Notes
Notes: svn path=/vendor/llvm-project/master/; revision=356843 svn path=/vendor/llvm-project/llvmorg-10-init-17466-ge26a78e7085/; revision=356844; tag=vendor/llvm-project/llvmorg-10-init-17466-ge26a78e7085
Diffstat (limited to 'lldb/source/Plugins')
-rw-r--r--lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp2
-rw-r--r--lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp12
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp104
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h40
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp20
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h9
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp6
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h2
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp403
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h118
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp14
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h15
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp1494
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h188
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp41
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h13
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp10
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h3
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp10
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h20
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp20
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp38
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h12
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp57
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h11
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp10
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h9
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h4
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp2
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h74
-rw-r--r--lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp8
-rw-r--r--lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp23
-rw-r--r--lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp13
-rw-r--r--lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp14
-rw-r--r--lldb/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp2
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp152
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h2
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp11
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp2
-rw-r--r--lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp19
-rw-r--r--lldb/source/Plugins/Language/ObjC/Cocoa.cpp54
-rw-r--r--lldb/source/Plugins/Language/ObjC/NSArray.cpp58
-rw-r--r--lldb/source/Plugins/Language/ObjC/NSDictionary.cpp2
-rw-r--r--lldb/source/Plugins/Language/ObjC/NSError.cpp12
-rw-r--r--lldb/source/Plugins/Language/ObjC/NSException.cpp26
-rw-r--r--lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp5
-rw-r--r--lldb/source/Plugins/Language/ObjC/NSString.cpp2
-rw-r--r--lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp3
-rw-r--r--lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp203
-rw-r--r--lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h8
-rw-r--r--lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp8
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp12
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp155
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h4
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp16
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp56
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h2
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp15
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp69
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h20
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp16
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h7
-rw-r--r--lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp5
-rw-r--r--lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp2
-rw-r--r--lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp2
-rw-r--r--lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp9
-rw-r--r--lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp17
-rw-r--r--lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h6
-rw-r--r--lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp4
-rw-r--r--lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp4
-rw-r--r--lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp4
-rw-r--r--lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp24
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp333
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h3
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp2
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h7
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp138
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h7
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp108
-rw-r--r--lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h13
-rw-r--r--lldb/source/Plugins/Process/POSIX/CrashReason.cpp8
-rw-r--r--lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp11
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp6
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp6
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp6
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h7
-rw-r--r--lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h5
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp10
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h6
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp31
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h6
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp8
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h8
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp15
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp4
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp14
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp23
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h3
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp106
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h1
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td4
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp9
-rw-r--r--lldb/source/Plugins/Process/minidump/MinidumpParser.cpp73
-rw-r--r--lldb/source/Plugins/Process/minidump/MinidumpParser.h10
-rw-r--r--lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp79
-rw-r--r--lldb/source/Plugins/Process/minidump/ProcessMinidump.h3
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp59
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h48
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp157
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h61
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp110
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h44
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp88
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.h28
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp190
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h16
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h28
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h8
-rw-r--r--lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp9
-rw-r--r--lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h12
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp3082
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h69
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h4
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp14
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h8
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp33
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h4
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h6
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp42
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h10
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp167
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h38
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h2
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp107
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h4
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp204
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h49
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp2
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp491
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h39
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp33
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h28
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp7
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h20
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp2
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h10
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp25
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp42
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h12
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp2
-rw-r--r--lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp77
-rw-r--r--lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp25
-rw-r--r--lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h12
-rw-r--r--lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp2
-rw-r--r--lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h11
-rw-r--r--lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp19
157 files changed, 5513 insertions, 4959 deletions
diff --git a/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp b/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
index 6473ccf9a19a..ec7588dfb50c 100644
--- a/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
+++ b/lldb/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
@@ -2020,6 +2020,8 @@ bool ABIMacOSX_arm64::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
// registers x19 through x28 and sp are callee preserved. v8-v15 are non-
// volatile (and specifically only the lower 8 bytes of these regs), the rest
// of the fp/SIMD registers are volatile.
+//
+// v. https://github.com/ARM-software/software-standards/blob/master/abi/aapcs64/
// We treat x29 as callee preserved also, else the unwinder won't try to
// retrieve fp saves.
diff --git a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
index 28c9de2c1e96..dbdb3520087e 100644
--- a/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
+++ b/lldb/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
@@ -20,6 +20,7 @@
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/TargetRegistry.h"
@@ -949,8 +950,9 @@ DisassemblerLLVMC::MCDisasmInstance::Create(const char *triple, const char *cpu,
if (!subtarget_info_up)
return Instance();
+ llvm::MCTargetOptions MCOptions;
std::unique_ptr<llvm::MCAsmInfo> asm_info_up(
- curr_target->createMCAsmInfo(*reg_info_up, triple));
+ curr_target->createMCAsmInfo(*reg_info_up, triple, MCOptions));
if (!asm_info_up)
return Instance();
@@ -1018,7 +1020,7 @@ uint64_t DisassemblerLLVMC::MCDisasmInstance::GetMCInst(
uint64_t new_inst_size;
status = m_disasm_up->getInstruction(mc_inst, new_inst_size, data, pc,
- llvm::nulls(), llvm::nulls());
+ llvm::nulls());
if (status == llvm::MCDisassembler::Success)
return new_inst_size;
else
@@ -1032,8 +1034,8 @@ void DisassemblerLLVMC::MCDisasmInstance::PrintMCInst(
llvm::raw_string_ostream comments_stream(comments_string);
m_instr_printer_up->setCommentStream(comments_stream);
- m_instr_printer_up->printInst(&mc_inst, inst_stream, llvm::StringRef(),
- *m_subtarget_info_up);
+ m_instr_printer_up->printInst(&mc_inst, 0, llvm::StringRef(),
+ *m_subtarget_info_up, inst_stream);
m_instr_printer_up->setCommentStream(llvm::nulls());
comments_stream.flush();
@@ -1212,7 +1214,7 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
if (llvm_arch == llvm::Triple::arm) {
std::string thumb_triple(thumb_arch.GetTriple().getTriple());
m_alternate_disasm_up =
- MCDisasmInstance::Create(thumb_triple.c_str(), "", features_str.c_str(),
+ MCDisasmInstance::Create(thumb_triple.c_str(), "", features_str.c_str(),
flavor, *this);
if (!m_alternate_disasm_up)
m_disasm_up.reset();
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp
deleted file mode 100644
index f33a713cc0b2..000000000000
--- a/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-//===-- ASTDumper.cpp -------------------------------------------*- C++ -*-===//
-//
-// 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 "ASTDumper.h"
-
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangUtil.h"
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Utility/Log.h"
-
-#include "llvm/Support/raw_ostream.h"
-
-using namespace lldb_private;
-
-ASTDumper::ASTDumper(clang::Decl *decl) {
- clang::DeclContext *decl_ctx = llvm::dyn_cast<clang::DeclContext>(decl);
-
- bool has_external_lexical_storage;
- bool has_external_visible_storage;
-
- if (decl_ctx) {
- has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage();
- has_external_visible_storage = decl_ctx->hasExternalVisibleStorage();
- decl_ctx->setHasExternalLexicalStorage(false);
- decl_ctx->setHasExternalVisibleStorage(false);
- }
-
- llvm::raw_string_ostream os(m_dump);
- decl->print(os);
- os.flush();
-
- if (decl_ctx) {
- decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage);
- decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage);
- }
-}
-
-ASTDumper::ASTDumper(clang::DeclContext *decl_ctx) {
- bool has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage();
- bool has_external_visible_storage = decl_ctx->hasExternalVisibleStorage();
-
- decl_ctx->setHasExternalLexicalStorage(false);
- decl_ctx->setHasExternalVisibleStorage(false);
-
- if (clang::Decl *decl = llvm::dyn_cast<clang::Decl>(decl_ctx)) {
- llvm::raw_string_ostream os(m_dump);
- decl->print(os);
- os.flush();
- } else {
- m_dump.assign("<DeclContext is not a Decl>");
- }
-
- decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage);
- decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage);
-}
-
-ASTDumper::ASTDumper(const clang::Type *type) {
- m_dump = clang::QualType(type, 0).getAsString();
-}
-
-ASTDumper::ASTDumper(clang::QualType type) { m_dump = type.getAsString(); }
-
-ASTDumper::ASTDumper(lldb::opaque_compiler_type_t type) {
- m_dump = clang::QualType::getFromOpaquePtr(type).getAsString();
-}
-
-ASTDumper::ASTDumper(const CompilerType &compiler_type) {
- m_dump = ClangUtil::GetQualType(compiler_type).getAsString();
-}
-
-const char *ASTDumper::GetCString() { return m_dump.c_str(); }
-
-void ASTDumper::ToLog(Log *log, const char *prefix) {
- size_t len = m_dump.length() + 1;
-
- char *alloc = (char *)malloc(len);
- char *str = alloc;
-
- memcpy(str, m_dump.c_str(), len);
-
- char *end = nullptr;
-
- end = strchr(str, '\n');
-
- while (end) {
- *end = '\0';
-
- LLDB_LOGF(log, "%s%s", prefix, str);
-
- *end = '\n';
-
- str = end + 1;
- end = strchr(str, '\n');
- }
-
- LLDB_LOGF(log, "%s%s", prefix, str);
-
- free(alloc);
-}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h
deleted file mode 100644
index ddf055d9c0c3..000000000000
--- a/lldb/source/Plugins/ExpressionParser/Clang/ASTDumper.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//===-- ASTDumper.h ---------------------------------------------*- C++ -*-===//
-//
-// 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 liblldb_ASTDumper_h_
-#define liblldb_ASTDumper_h_
-
-#include "clang/AST/DeclVisitor.h"
-#include "clang/AST/TypeVisitor.h"
-
-#include "lldb/Utility/Stream.h"
-#include "llvm/ADT/DenseSet.h"
-
-namespace lldb_private {
-
-class ASTDumper {
-public:
- ASTDumper(clang::Decl *decl);
- ASTDumper(clang::DeclContext *decl_ctx);
- ASTDumper(const clang::Type *type);
- ASTDumper(clang::QualType type);
- ASTDumper(lldb::opaque_compiler_type_t type);
- ASTDumper(const CompilerType &compiler_type);
-
- const char *GetCString();
- void ToSTDERR();
- void ToLog(Log *log, const char *prefix);
- void ToStream(lldb::StreamSP &stream);
-
-private:
- std::string m_dump;
-};
-
-} // namespace lldb_private
-
-#endif
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
index 68eaad33f51c..77bb9544ea40 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
@@ -388,8 +388,7 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body,
// replace the old statement with the new one
//
- *last_stmt_ptr =
- reinterpret_cast<Stmt *>(result_initialization_stmt_result.get());
+ *last_stmt_ptr = static_cast<Stmt *>(result_initialization_stmt_result.get());
return true;
}
@@ -448,13 +447,20 @@ void ASTResultSynthesizer::RecordPersistentDecl(NamedDecl *D) {
}
void ASTResultSynthesizer::CommitPersistentDecls() {
+ auto *state =
+ m_target.GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC);
+ if (!state)
+ return;
+
+ auto *persistent_vars = llvm::cast<ClangPersistentVariables>(state);
+ ClangASTContext *scratch_ctx = ClangASTContext::GetScratch(m_target);
+
for (clang::NamedDecl *decl : m_decls) {
StringRef name = decl->getName();
ConstString name_cs(name.str().c_str());
Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl(
- m_target.GetScratchClangASTContext()->getASTContext(), m_ast_context,
- decl);
+ &scratch_ctx->getASTContext(), decl);
if (!D_scratch) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
@@ -472,10 +478,8 @@ void ASTResultSynthesizer::CommitPersistentDecls() {
}
if (NamedDecl *NamedDecl_scratch = dyn_cast<NamedDecl>(D_scratch))
- llvm::cast<ClangPersistentVariables>(
- m_target.GetPersistentExpressionStateForLanguage(
- lldb::eLanguageTypeC))
- ->RegisterPersistentDecl(name_cs, NamedDecl_scratch);
+ persistent_vars->RegisterPersistentDecl(name_cs, NamedDecl_scratch,
+ scratch_ctx);
}
}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h
index 670ba6dce72e..0b0f3b97705d 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h
@@ -135,18 +135,11 @@ private:
void RecordPersistentTypes(clang::DeclContext *FunDeclCtx);
/// Given a TypeDecl, if it declares a type whose name starts with a dollar
- /// sign, register it as a pointer type in the target's scratch
- /// AST context.
- ///
- /// \param[in] Body
- /// The body of the function.
+ /// sign, register it as a pointer type in the target's scratch AST context.
void MaybeRecordPersistentType(clang::TypeDecl *D);
/// Given a NamedDecl, register it as a pointer type in the target's scratch
/// AST context.
- ///
- /// \param[in] Body
- /// The body of the function.
void RecordPersistentDecl(clang::NamedDecl *D);
clang::ASTContext
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp
index 190eacaa2b62..a164d48ae3e0 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp
@@ -30,8 +30,8 @@ ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough,
const char *struct_name,
ClangFunctionCaller &function)
: m_ast_context(nullptr), m_passthrough(passthrough),
- m_passthrough_sema(nullptr), m_sema(nullptr), m_action(nullptr),
- m_function(function), m_struct_name(struct_name) {
+ m_passthrough_sema(nullptr), m_sema(nullptr), m_function(function),
+ m_struct_name(struct_name) {
if (!m_passthrough)
return;
@@ -170,7 +170,6 @@ void ASTStructExtractor::PrintStats() {
void ASTStructExtractor::InitializeSema(Sema &S) {
m_sema = &S;
- m_action = reinterpret_cast<Action *>(m_sema);
if (m_passthrough_sema)
m_passthrough_sema->InitializeSema(S);
@@ -178,7 +177,6 @@ void ASTStructExtractor::InitializeSema(Sema &S) {
void ASTStructExtractor::ForgetSema() {
m_sema = nullptr;
- m_action = nullptr;
if (m_passthrough_sema)
m_passthrough_sema->ForgetSema();
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h
index 7aef2e254e1f..078cf095975f 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h
@@ -121,8 +121,6 @@ private:
///for passthrough. NULL if it's an
///ASTConsumer.
clang::Sema *m_sema; ///< The Sema to use.
- clang::Action
- *m_action; ///< The Sema to use, cast to an Action so it's usable.
ClangFunctionCaller &m_function; ///< The function to populate with
///information about the argument structure.
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
index 372c2439ebf0..42927ab6cc8a 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
@@ -8,7 +8,6 @@
#include "ClangASTSource.h"
-#include "ASTDumper.h"
#include "ClangDeclVendor.h"
#include "ClangModulesDeclVendor.h"
@@ -50,114 +49,42 @@ private:
};
}
-ClangASTSource::ClangASTSource(const lldb::TargetSP &target)
+ClangASTSource::ClangASTSource(const lldb::TargetSP &target,
+ const lldb::ClangASTImporterSP &importer)
: m_import_in_progress(false), m_lookups_enabled(false), m_target(target),
m_ast_context(nullptr), m_active_lexical_decls(), m_active_lookups() {
- if (!target->GetUseModernTypeLookup()) {
- m_ast_importer_sp = m_target->GetClangASTImporter();
- }
+ m_ast_importer_sp = importer;
}
-void ClangASTSource::InstallASTContext(clang::ASTContext &ast_context,
- clang::FileManager &file_manager,
- bool is_shared_context) {
- m_ast_context = &ast_context;
- m_file_manager = &file_manager;
- if (m_target->GetUseModernTypeLookup()) {
- // Configure the ExternalASTMerger. The merger needs to be able to import
- // types from any source that we would do lookups in, which includes the
- // persistent AST context as well as the modules and Objective-C runtime
- // AST contexts.
-
- lldbassert(!m_merger_up);
- clang::ExternalASTMerger::ImporterTarget target = {ast_context,
- file_manager};
- std::vector<clang::ExternalASTMerger::ImporterSource> sources;
- for (lldb::ModuleSP module_sp : m_target->GetImages().Modules()) {
- auto type_system_or_err =
- module_sp->GetTypeSystemForLanguage(lldb::eLanguageTypeC);
- if (auto err = type_system_or_err.takeError()) {
- LLDB_LOG_ERROR(
- lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS),
- std::move(err), "Failed to get ClangASTContext");
- } else if (auto *module_ast_ctx = llvm::cast_or_null<ClangASTContext>(
- &type_system_or_err.get())) {
- lldbassert(module_ast_ctx->getASTContext());
- lldbassert(module_ast_ctx->getFileManager());
- sources.emplace_back(*module_ast_ctx->getASTContext(),
- *module_ast_ctx->getFileManager(),
- module_ast_ctx->GetOriginMap());
- }
- }
-
- do {
- lldb::ProcessSP process(m_target->GetProcessSP());
-
- if (!process)
- break;
-
- ObjCLanguageRuntime *language_runtime(ObjCLanguageRuntime::Get(*process));
-
- if (!language_runtime)
- break;
-
- if (auto *runtime_decl_vendor = llvm::dyn_cast_or_null<ClangDeclVendor>(
- language_runtime->GetDeclVendor())) {
- sources.push_back(runtime_decl_vendor->GetImporterSource());
- }
- } while (false);
-
- do {
- auto *modules_decl_vendor = m_target->GetClangModulesDeclVendor();
-
- if (!modules_decl_vendor)
- break;
-
- sources.push_back(modules_decl_vendor->GetImporterSource());
- } while (false);
-
- if (!is_shared_context) {
- // Update the scratch AST context's merger to reflect any new sources we
- // might have come across since the last time an expression was parsed.
-
- auto scratch_ast_context = static_cast<ClangASTContextForExpressions*>(
- m_target->GetScratchClangASTContext());
-
- scratch_ast_context->GetMergerUnchecked().AddSources(sources);
-
- sources.push_back({*scratch_ast_context->getASTContext(),
- *scratch_ast_context->getFileManager(),
- scratch_ast_context->GetOriginMap()});
- }
-
- m_merger_up =
- std::make_unique<clang::ExternalASTMerger>(target, sources);
- } else {
- m_ast_importer_sp->InstallMapCompleter(&ast_context, *this);
- }
+void ClangASTSource::InstallASTContext(ClangASTContext &clang_ast_context) {
+ m_ast_context = &clang_ast_context.getASTContext();
+ m_clang_ast_context = &clang_ast_context;
+ m_file_manager = &m_ast_context->getSourceManager().getFileManager();
+ m_ast_importer_sp->InstallMapCompleter(m_ast_context, *this);
}
ClangASTSource::~ClangASTSource() {
- if (m_ast_importer_sp)
- m_ast_importer_sp->ForgetDestination(m_ast_context);
+ if (!m_ast_importer_sp)
+ return;
+
+ m_ast_importer_sp->ForgetDestination(m_ast_context);
+ if (!m_target)
+ return;
// We are in the process of destruction, don't create clang ast context on
// demand by passing false to
// Target::GetScratchClangASTContext(create_on_demand).
ClangASTContext *scratch_clang_ast_context =
- m_target->GetScratchClangASTContext(false);
+ ClangASTContext::GetScratch(*m_target, false);
if (!scratch_clang_ast_context)
return;
- clang::ASTContext *scratch_ast_context =
+ clang::ASTContext &scratch_ast_context =
scratch_clang_ast_context->getASTContext();
- if (!scratch_ast_context)
- return;
-
- if (m_ast_context != scratch_ast_context && m_ast_importer_sp)
- m_ast_importer_sp->ForgetSource(scratch_ast_context, m_ast_context);
+ if (m_ast_context != &scratch_ast_context && m_ast_importer_sp)
+ m_ast_importer_sp->ForgetSource(&scratch_ast_context, m_ast_context);
}
void ClangASTSource::StartTranslationUnit(ASTConsumer *Consumer) {
@@ -279,9 +206,8 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) {
current_id, static_cast<void *>(m_ast_context),
static_cast<void *>(tag_decl), tag_decl->getName().str().c_str());
- LLDB_LOGF(log, " CTD[%u] Before:", current_id);
- ASTDumper dumper((Decl *)tag_decl);
- dumper.ToLog(log, " [CTD] ");
+ LLDB_LOG(log, " CTD[%u] Before:\n{0}", current_id,
+ ClangUtil::DumpDecl(tag_decl));
}
auto iter = m_active_lexical_decls.find(tag_decl);
@@ -291,9 +217,6 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) {
ScopedLexicalDeclEraser eraser(m_active_lexical_decls, tag_decl);
if (!m_ast_importer_sp) {
- if (HasMerger()) {
- GetMergerUnchecked().CompleteType(tag_decl);
- }
return;
}
@@ -365,7 +288,6 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) {
TypeList types;
ConstString name(tag_decl->getName().str().c_str());
- CompilerDeclContext namespace_decl;
const ModuleList &module_list = m_target->GetImages();
@@ -407,50 +329,30 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) {
}
}
- if (log) {
- LLDB_LOGF(log, " [CTD] After:");
- ASTDumper dumper((Decl *)tag_decl);
- dumper.ToLog(log, " [CTD] ");
- }
+ LLDB_LOG(log, " [CTD] After:\n{0}", ClangUtil::DumpDecl(tag_decl));
}
void ClangASTSource::CompleteType(clang::ObjCInterfaceDecl *interface_decl) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- if (log) {
- LLDB_LOGF(log,
- " [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing "
- "an ObjCInterfaceDecl named %s",
- static_cast<void *>(m_ast_context),
- interface_decl->getName().str().c_str());
- LLDB_LOGF(log, " [COID] Before:");
- ASTDumper dumper((Decl *)interface_decl);
- dumper.ToLog(log, " [COID] ");
- }
+ LLDB_LOGF(log,
+ " [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing "
+ "an ObjCInterfaceDecl named %s",
+ static_cast<void *>(m_ast_context),
+ interface_decl->getName().str().c_str());
+ LLDB_LOG(log, " [COID] Before:\n{0}",
+ ClangUtil::DumpDecl(interface_decl));
if (!m_ast_importer_sp) {
- if (HasMerger()) {
- ObjCInterfaceDecl *complete_iface_decl =
- GetCompleteObjCInterface(interface_decl);
-
- if (complete_iface_decl && (complete_iface_decl != interface_decl)) {
- m_merger_up->ForceRecordOrigin(interface_decl, {complete_iface_decl, &complete_iface_decl->getASTContext()});
- }
-
- GetMergerUnchecked().CompleteType(interface_decl);
- } else {
- lldbassert(0 && "No mechanism for completing a type!");
- }
+ lldbassert(0 && "No mechanism for completing a type!");
return;
}
- Decl *original_decl = nullptr;
- ASTContext *original_ctx = nullptr;
+ ClangASTImporter::DeclOrigin original = m_ast_importer_sp->GetDeclOrigin(interface_decl);
- if (m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl,
- &original_ctx)) {
+ if (original.Valid()) {
if (ObjCInterfaceDecl *original_iface_decl =
- dyn_cast<ObjCInterfaceDecl>(original_decl)) {
+ dyn_cast<ObjCInterfaceDecl>(original.decl)) {
ObjCInterfaceDecl *complete_iface_decl =
GetCompleteObjCInterface(original_iface_decl);
@@ -468,8 +370,7 @@ void ClangASTSource::CompleteType(clang::ObjCInterfaceDecl *interface_decl) {
if (log) {
LLDB_LOGF(log, " [COID] After:");
- ASTDumper dumper((Decl *)interface_decl);
- dumper.ToLog(log, " [COID] ");
+ LLDB_LOG(log, " [COID] {0}", ClangUtil::DumpDecl(interface_decl));
}
}
@@ -519,23 +420,9 @@ void ClangASTSource::FindExternalLexicalDecls(
llvm::function_ref<bool(Decl::Kind)> predicate,
llvm::SmallVectorImpl<Decl *> &decls) {
- if (HasMerger()) {
- if (auto *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl_context)) {
- ObjCInterfaceDecl *complete_iface_decl =
- GetCompleteObjCInterface(interface_decl);
-
- if (complete_iface_decl && (complete_iface_decl != interface_decl)) {
- m_merger_up->ForceRecordOrigin(interface_decl, {complete_iface_decl, &complete_iface_decl->getASTContext()});
- }
- }
- return GetMergerUnchecked().FindExternalLexicalDecls(decl_context,
- predicate,
- decls);
- } else if (!m_ast_importer_sp)
+ if (!m_ast_importer_sp)
return;
- ClangASTMetrics::RegisterLexicalQuery();
-
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
const Decl *context_decl = dyn_cast<Decl>(decl_context);
@@ -574,42 +461,38 @@ void ClangASTSource::FindExternalLexicalDecls(
current_id, static_cast<const void *>(m_ast_context));
}
- Decl *original_decl = nullptr;
- ASTContext *original_ctx = nullptr;
+ ClangASTImporter::DeclOrigin original = m_ast_importer_sp->GetDeclOrigin(context_decl);
- if (!m_ast_importer_sp->ResolveDeclOrigin(context_decl, &original_decl,
- &original_ctx))
+ if (!original.Valid())
return;
- if (log) {
- LLDB_LOGF(
- log, " FELD[%u] Original decl (ASTContext*)%p (Decl*)%p:", current_id,
- static_cast<void *>(original_ctx), static_cast<void *>(original_decl));
- ASTDumper(original_decl).ToLog(log, " ");
- }
+ LLDB_LOG(
+ log, " FELD[{0}] Original decl (ASTContext*){1:x} (Decl*){2:x}:\n{3}",
+ current_id, static_cast<void *>(original.ctx),
+ static_cast<void *>(original.decl), ClangUtil::DumpDecl(original.decl));
if (ObjCInterfaceDecl *original_iface_decl =
- dyn_cast<ObjCInterfaceDecl>(original_decl)) {
+ dyn_cast<ObjCInterfaceDecl>(original.decl)) {
ObjCInterfaceDecl *complete_iface_decl =
GetCompleteObjCInterface(original_iface_decl);
if (complete_iface_decl && (complete_iface_decl != original_iface_decl)) {
- original_decl = complete_iface_decl;
- original_ctx = &complete_iface_decl->getASTContext();
+ original.decl = complete_iface_decl;
+ original.ctx = &complete_iface_decl->getASTContext();
m_ast_importer_sp->SetDeclOrigin(context_decl, complete_iface_decl);
}
}
- if (TagDecl *original_tag_decl = dyn_cast<TagDecl>(original_decl)) {
- ExternalASTSource *external_source = original_ctx->getExternalSource();
+ if (TagDecl *original_tag_decl = dyn_cast<TagDecl>(original.decl)) {
+ ExternalASTSource *external_source = original.ctx->getExternalSource();
if (external_source)
external_source->CompleteType(original_tag_decl);
}
const DeclContext *original_decl_context =
- dyn_cast<DeclContext>(original_decl);
+ dyn_cast<DeclContext>(original.decl);
if (!original_decl_context)
return;
@@ -625,16 +508,16 @@ void ClangASTSource::FindExternalLexicalDecls(
// See clang::ExternalASTSource::FindExternalLexicalDecls()
if (predicate(decl->getKind())) {
if (log) {
- ASTDumper ast_dumper(decl);
+ std::string ast_dump = ClangUtil::DumpDecl(decl);
if (const NamedDecl *context_named_decl =
dyn_cast<NamedDecl>(context_decl))
LLDB_LOGF(log, " FELD[%d] Adding [to %sDecl %s] lexical %sDecl %s",
current_id, context_named_decl->getDeclKindName(),
context_named_decl->getNameAsString().c_str(),
- decl->getDeclKindName(), ast_dumper.GetCString());
+ decl->getDeclKindName(), ast_dump.c_str());
else
LLDB_LOGF(log, " FELD[%d] Adding lexical %sDecl %s", current_id,
- decl->getDeclKindName(), ast_dumper.GetCString());
+ decl->getDeclKindName(), ast_dump.c_str());
}
Decl *copied_decl = CopyDecl(decl);
@@ -647,20 +530,6 @@ void ClangASTSource::FindExternalLexicalDecls(
m_ast_importer_sp->RequireCompleteType(copied_field_type);
}
- auto decl_context_non_const = const_cast<DeclContext *>(decl_context);
-
- // The decl ended up in the wrong DeclContext. Let's fix that so
- // the decl we copied will actually be found.
- // FIXME: This is a horrible hack that shouldn't be necessary. However
- // it seems our current setup sometimes fails to copy decls to the right
- // place. See rdar://55129537.
- if (copied_decl->getDeclContext() != decl_context) {
- assert(copied_decl->getDeclContext()->containsDecl(copied_decl));
- copied_decl->getDeclContext()->removeDecl(copied_decl);
- copied_decl->setDeclContext(decl_context_non_const);
- assert(!decl_context_non_const->containsDecl(copied_decl));
- decl_context_non_const->addDeclInternal(copied_decl);
- }
} else {
SkippedDecls = true;
}
@@ -683,8 +552,6 @@ void ClangASTSource::FindExternalLexicalDecls(
void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) {
assert(m_ast_context);
- ClangASTMetrics::RegisterVisibleQuery();
-
const ConstString name(context.m_decl_name.getAsString().c_str());
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
@@ -715,25 +582,6 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) {
name.GetCString(), context.m_decl_context->getDeclKindName());
}
- if (HasMerger() && !isa<TranslationUnitDecl>(context.m_decl_context)
- /* possibly handle NamespaceDecls here? */) {
- if (auto *interface_decl =
- dyn_cast<ObjCInterfaceDecl>(context.m_decl_context)) {
- ObjCInterfaceDecl *complete_iface_decl =
- GetCompleteObjCInterface(interface_decl);
-
- if (complete_iface_decl && (complete_iface_decl != interface_decl)) {
- GetMergerUnchecked().ForceRecordOrigin(
- interface_decl,
- {complete_iface_decl, &complete_iface_decl->getASTContext()});
- }
- }
-
- GetMergerUnchecked().FindExternalVisibleDeclsByName(context.m_decl_context,
- context.m_decl_name);
- return; // otherwise we may need to fall back
- }
-
context.m_namespace_map = std::make_shared<ClangASTImporter::NamespaceMap>();
if (const NamespaceDecl *namespace_context =
@@ -758,7 +606,7 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) {
FindExternalVisibleDecls(context, i->first, i->second, current_id);
}
- } else if (isa<ObjCInterfaceDecl>(context.m_decl_context) && !HasMerger()) {
+ } else if (isa<ObjCInterfaceDecl>(context.m_decl_context)) {
FindObjCPropertyAndIvarDecls(context);
} else if (!isa<TranslationUnitDecl>(context.m_decl_context)) {
// we shouldn't be getting FindExternalVisibleDecls calls for these
@@ -788,7 +636,7 @@ void ClangASTSource::FindExternalVisibleDecls(NameSearchContext &context) {
}
clang::Sema *ClangASTSource::getSema() {
- return ClangASTContext::GetASTContext(m_ast_context)->getSema();
+ return m_clang_ast_context->getSema();
}
bool ClangASTSource::IgnoreName(const ConstString name,
@@ -821,6 +669,9 @@ void ClangASTSource::FindExternalVisibleDecls(
if (IgnoreName(name, true))
return;
+ if (!m_target)
+ return;
+
if (module_sp && namespace_decl) {
CompilerDeclContext found_namespace_decl;
@@ -837,7 +688,7 @@ void ClangASTSource::FindExternalVisibleDecls(
module_sp->GetFileSpec().GetFilename().GetCString());
}
}
- } else if (!HasMerger()) {
+ } else {
const ModuleList &target_images = m_target->GetImages();
std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex());
@@ -1049,11 +900,10 @@ public:
template <class D>
DeclFromUser<D> DeclFromParser<D>::GetOrigin(ClangASTSource &source) {
- DeclFromUser<> origin_decl;
- source.ResolveDeclOrigin(this->decl, &origin_decl.decl, nullptr);
- if (origin_decl.IsInvalid())
+ ClangASTImporter::DeclOrigin origin = source.GetDeclOrigin(this->decl);
+ if (!origin.Valid())
return DeclFromUser<D>();
- return DeclFromUser<D>(dyn_cast<D>(origin_decl.decl));
+ return DeclFromUser<D>(dyn_cast<D>(origin.decl));
}
template <class D>
@@ -1137,11 +987,8 @@ bool ClangASTSource::FindObjCMethodDeclsWithOrigin(
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- if (log) {
- ASTDumper dumper((Decl *)copied_method_decl);
- LLDB_LOGF(log, " CAS::FOMD[%d] found (%s) %s", current_id, log_info,
- dumper.GetCString());
- }
+ LLDB_LOG(log, " CAS::FOMD[{0}] found ({1}) {2}", current_id, log_info,
+ ClangUtil::DumpDecl(copied_method_decl));
context.AddNamedDecl(copied_method_decl);
}
@@ -1152,21 +999,6 @@ bool ClangASTSource::FindObjCMethodDeclsWithOrigin(
void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- if (HasMerger()) {
- if (auto *interface_decl = dyn_cast<ObjCInterfaceDecl>(context.m_decl_context)) {
- ObjCInterfaceDecl *complete_iface_decl =
- GetCompleteObjCInterface(interface_decl);
-
- if (complete_iface_decl && (complete_iface_decl != context.m_decl_context)) {
- m_merger_up->ForceRecordOrigin(interface_decl, {complete_iface_decl, &complete_iface_decl->getASTContext()});
- }
- }
-
- GetMergerUnchecked().FindExternalVisibleDeclsByName(context.m_decl_context,
- context.m_decl_name);
- return;
- }
-
static unsigned int invocation_id = 0;
unsigned int current_id = invocation_id++;
@@ -1180,17 +1012,13 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) {
return;
do {
- Decl *original_decl = nullptr;
- ASTContext *original_ctx = nullptr;
-
- m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl,
- &original_ctx);
+ ClangASTImporter::DeclOrigin original = m_ast_importer_sp->GetDeclOrigin(interface_decl);
- if (!original_decl)
+ if (!original.Valid())
break;
ObjCInterfaceDecl *original_interface_decl =
- dyn_cast<ObjCInterfaceDecl>(original_decl);
+ dyn_cast<ObjCInterfaceDecl>(original.decl);
if (FindObjCMethodDeclsWithOrigin(current_id, context,
original_interface_decl, "at origin"))
@@ -1343,11 +1171,8 @@ void ClangASTSource::FindObjCMethodDecls(NameSearchContext &context) {
if (!copied_method_decl)
continue;
- if (log) {
- ASTDumper dumper((Decl *)copied_method_decl);
- LLDB_LOGF(log, " CAS::FOMD[%d] found (in symbols) %s", current_id,
- dumper.GetCString());
- }
+ LLDB_LOG(log, " CAS::FOMD[{0}] found (in symbols)\n{1}", current_id,
+ ClangUtil::DumpDecl(copied_method_decl));
context.AddNamedDecl(copied_method_decl);
}
@@ -1476,11 +1301,8 @@ static bool FindObjCPropertyAndIvarDeclsWithOrigin(
DeclFromParser<ObjCPropertyDecl> parser_property_decl(
origin_property_decl.Import(source));
if (parser_property_decl.IsValid()) {
- if (log) {
- ASTDumper dumper((Decl *)parser_property_decl.decl);
- LLDB_LOGF(log, " CAS::FOPD[%d] found %s", current_id,
- dumper.GetCString());
- }
+ LLDB_LOG(log, " CAS::FOPD[{0}] found\n{1}", current_id,
+ ClangUtil::DumpDecl(parser_property_decl.decl));
context.AddNamedDecl(parser_property_decl.decl);
found = true;
@@ -1495,9 +1317,8 @@ static bool FindObjCPropertyAndIvarDeclsWithOrigin(
origin_ivar_decl.Import(source));
if (parser_ivar_decl.IsValid()) {
if (log) {
- ASTDumper dumper((Decl *)parser_ivar_decl.decl);
- LLDB_LOGF(log, " CAS::FOPD[%d] found %s", current_id,
- dumper.GetCString());
+ LLDB_LOG(log, " CAS::FOPD[{0}] found\n{1}", current_id,
+ ClangUtil::DumpDecl(parser_ivar_decl.decl));
}
context.AddNamedDecl(parser_ivar_decl.decl);
@@ -1736,8 +1557,6 @@ bool ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size,
FieldOffsetMap &field_offsets,
BaseOffsetMap &base_offsets,
BaseOffsetMap &virtual_base_offsets) {
- ClangASTMetrics::RegisterRecordLayout();
-
static unsigned int invocation_id = 0;
unsigned int current_id = invocation_id++;
@@ -1984,90 +1803,37 @@ NamespaceDecl *ClangASTSource::AddNamespace(
return dyn_cast<NamespaceDecl>(copied_decl);
}
-clang::QualType ClangASTSource::CopyTypeWithMerger(
- clang::ASTContext &from_context,
- clang::ExternalASTMerger &merger,
- clang::QualType type) {
- if (!merger.HasImporterForOrigin(from_context)) {
- lldbassert(0 && "Couldn't find the importer for a source context!");
- return QualType();
- }
-
- if (llvm::Expected<QualType> type_or_error =
- merger.ImporterForOrigin(from_context).Import(type)) {
- return *type_or_error;
- } else {
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
- LLDB_LOG_ERROR(log, type_or_error.takeError(), "Couldn't import type: {0}");
- return QualType();
- }
-}
-
clang::Decl *ClangASTSource::CopyDecl(Decl *src_decl) {
- clang::ASTContext &from_context = src_decl->getASTContext();
if (m_ast_importer_sp) {
- return m_ast_importer_sp->CopyDecl(m_ast_context, &from_context, src_decl);
- } else if (m_merger_up) {
- if (!m_merger_up->HasImporterForOrigin(from_context)) {
- lldbassert(0 && "Couldn't find the importer for a source context!");
- return nullptr;
- }
-
- if (llvm::Expected<Decl *> decl_or_error =
- m_merger_up->ImporterForOrigin(from_context).Import(src_decl)) {
- return *decl_or_error;
- } else {
- Log *log =
- lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
- LLDB_LOG_ERROR(log, decl_or_error.takeError(),
- "Couldn't import decl: {0}");
- return nullptr;
- }
+ return m_ast_importer_sp->CopyDecl(m_ast_context, src_decl);
} else {
lldbassert(0 && "No mechanism for copying a decl!");
return nullptr;
}
}
-bool ClangASTSource::ResolveDeclOrigin(const clang::Decl *decl,
- clang::Decl **original_decl,
- clang::ASTContext **original_ctx) {
+ClangASTImporter::DeclOrigin ClangASTSource::GetDeclOrigin(const clang::Decl *decl) {
if (m_ast_importer_sp) {
- return m_ast_importer_sp->ResolveDeclOrigin(decl, original_decl,
- original_ctx);
- } else if (m_merger_up) {
- return false; // Implement this correctly in ExternalASTMerger
+ return m_ast_importer_sp->GetDeclOrigin(decl);
} else {
// this can happen early enough that no ExternalASTSource is installed.
- return false;
+ return ClangASTImporter::DeclOrigin();
}
}
-clang::ExternalASTMerger &ClangASTSource::GetMergerUnchecked() {
- lldbassert(m_merger_up != nullptr);
- return *m_merger_up;
-}
-
CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) {
ClangASTContext *src_ast =
llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem());
if (src_ast == nullptr)
return CompilerType();
- ClangASTMetrics::RegisterLLDBImport();
-
SetImportInProgress(true);
QualType copied_qual_type;
if (m_ast_importer_sp) {
- copied_qual_type =
- m_ast_importer_sp->CopyType(m_ast_context, src_ast->getASTContext(),
- ClangUtil::GetQualType(src_type));
- } else if (m_merger_up) {
- copied_qual_type =
- CopyTypeWithMerger(*src_ast->getASTContext(), *m_merger_up,
- ClangUtil::GetQualType(src_type));
+ copied_qual_type = ClangUtil::GetQualType(
+ m_ast_importer_sp->CopyType(*m_clang_ast_context, src_type));
} else {
lldbassert(0 && "No mechanism for copying a type!");
return CompilerType();
@@ -2081,8 +1847,7 @@ CompilerType ClangASTSource::GuardedCopyType(const CompilerType &src_type) {
// seems to be generating bad types on occasion.
return CompilerType();
- return CompilerType(ClangASTContext::GetASTContext(m_ast_context),
- copied_qual_type.getAsOpaquePtr());
+ return m_clang_ast_context->GetType(copied_qual_type);
}
clang::NamedDecl *NameSearchContext::AddVarDecl(const CompilerType &type) {
@@ -2098,10 +1863,10 @@ clang::NamedDecl *NameSearchContext::AddVarDecl(const CompilerType &type) {
IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo();
- clang::ASTContext *ast = lldb_ast->getASTContext();
+ clang::ASTContext &ast = lldb_ast->getASTContext();
clang::NamedDecl *Decl = VarDecl::Create(
- *ast, const_cast<DeclContext *>(m_decl_context), SourceLocation(),
+ ast, const_cast<DeclContext *>(m_decl_context), SourceLocation(),
SourceLocation(), ii, ClangUtil::GetQualType(type), nullptr, SC_Static);
m_decls.push_back(Decl);
@@ -2127,7 +1892,7 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type,
QualType qual_type(ClangUtil::GetQualType(type));
- clang::ASTContext *ast = lldb_ast->getASTContext();
+ clang::ASTContext &ast = lldb_ast->getASTContext();
const bool isInlineSpecified = false;
const bool hasWrittenPrototype = true;
@@ -2137,7 +1902,7 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type,
if (extern_c) {
context = LinkageSpecDecl::Create(
- *ast, context, SourceLocation(), SourceLocation(),
+ ast, context, SourceLocation(), SourceLocation(),
clang::LinkageSpecDecl::LanguageIDs::lang_c, false);
}
@@ -2149,7 +1914,7 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type,
: m_decl_name;
clang::FunctionDecl *func_decl = FunctionDecl::Create(
- *ast, context, SourceLocation(), SourceLocation(), decl_name, qual_type,
+ ast, context, SourceLocation(), SourceLocation(), decl_name, qual_type,
nullptr, SC_Extern, isInlineSpecified, hasWrittenPrototype,
isConstexprSpecified ? CSK_constexpr : CSK_unspecified);
@@ -2170,7 +1935,7 @@ clang::NamedDecl *NameSearchContext::AddFunDecl(const CompilerType &type,
QualType arg_qual_type(func_proto_type->getParamType(ArgIndex));
parm_var_decls.push_back(
- ParmVarDecl::Create(*ast, const_cast<DeclContext *>(context),
+ ParmVarDecl::Create(ast, const_cast<DeclContext *>(context),
SourceLocation(), SourceLocation(), nullptr,
arg_qual_type, nullptr, SC_Static, nullptr));
}
@@ -2210,9 +1975,7 @@ clang::NamedDecl *NameSearchContext::AddGenericFunDecl() {
proto_info));
return AddFunDecl(
- CompilerType(ClangASTContext::GetASTContext(m_ast_source.m_ast_context),
- generic_function_type.getAsOpaquePtr()),
- true);
+ m_ast_source.m_clang_ast_context->GetType(generic_function_type), true);
}
clang::NamedDecl *
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
index 7a8bacf48a8f..3149b4266b2f 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
@@ -12,10 +12,9 @@
#include <set>
#include "lldb/Symbol/ClangASTImporter.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/Target.h"
-#include "clang/AST/ExternalASTMerger.h"
+#include "clang/AST/ExternalASTSource.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/SmallSet.h"
@@ -30,7 +29,7 @@ namespace lldb_private {
/// knows the name it is looking for, but nothing else. The ExternalSemaSource
/// class provides Decls (VarDecl, FunDecl, TypeDecl) to Clang for these
/// names, consulting the ClangExpressionDeclMap to do the actual lookups.
-class ClangASTSource : public ClangExternalASTSourceCommon,
+class ClangASTSource : public clang::ExternalASTSource,
public ClangASTImporter::MapCompleter {
public:
/// Constructor
@@ -39,7 +38,11 @@ public:
///
/// \param[in] target
/// A reference to the target containing debug information to use.
- ClangASTSource(const lldb::TargetSP &target);
+ ///
+ /// \param[in] importer
+ /// The ClangASTImporter to use.
+ ClangASTSource(const lldb::TargetSP &target,
+ const lldb::ClangASTImporterSP &importer);
/// Destructor
~ClangASTSource() override;
@@ -57,9 +60,7 @@ public:
}
void MaterializeVisibleDecls(const clang::DeclContext *DC) { return; }
- void InstallASTContext(clang::ASTContext &ast_context,
- clang::FileManager &file_manager,
- bool is_shared_context = false);
+ void InstallASTContext(ClangASTContext &ast_context);
//
// APIs for ExternalASTSource
@@ -89,7 +90,7 @@ public:
/// \param[in] DC
/// The DeclContext being searched.
///
- /// \param[in] isKindWeWant
+ /// \param[in] IsKindWeWant
/// A callback function that returns true given the
/// DeclKinds of desired Decls, and false otherwise.
///
@@ -155,7 +156,7 @@ public:
/// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() that
/// this object has something to say about undefined names.
///
- /// \param[in] ASTConsumer
+ /// \param[in] Consumer
/// Unused.
void StartTranslationUnit(clang::ASTConsumer *Consumer) override;
@@ -210,7 +211,7 @@ public:
///
/// Clang AST contexts like to own their AST sources, so this is a state-
/// free proxy object.
- class ClangASTSourceProxy : public ClangExternalASTSourceCommon {
+ class ClangASTSourceProxy : public clang::ExternalASTSource {
public:
ClangASTSourceProxy(ClangASTSource &original) : m_original(original) {}
@@ -249,18 +250,6 @@ public:
return m_original.StartTranslationUnit(Consumer);
}
- ClangASTMetadata *GetMetadata(const void *object) {
- return m_original.GetMetadata(object);
- }
-
- void SetMetadata(const void *object, ClangASTMetadata &metadata) {
- return m_original.SetMetadata(object, metadata);
- }
-
- bool HasMetadata(const void *object) {
- return m_original.HasMetadata(object);
- }
-
private:
ClangASTSource &m_original;
};
@@ -321,13 +310,6 @@ protected:
/// A wrapper for ClangASTContext::CopyType that sets a flag that
/// indicates that we should not respond to queries during import.
///
- /// \param[in] dest_context
- /// The target AST context, typically the parser's AST context.
- ///
- /// \param[in] source_context
- /// The source AST context, typically the AST context of whatever
- /// symbol file the type was found in.
- ///
/// \param[in] src_type
/// The source type.
///
@@ -341,7 +323,7 @@ public:
/// \param[in] name
/// The name to be considered.
///
- /// \param[in] ignore_all_dollar_nmmes
+ /// \param[in] ignore_all_dollar_names
/// True if $-names of all sorts should be ignored.
///
/// \return
@@ -358,24 +340,6 @@ public:
/// \return
/// A copy of the Decl in m_ast_context, or NULL if the copy failed.
clang::Decl *CopyDecl(clang::Decl *src_decl);
-
- /// Copies a single Type to the target of the given ExternalASTMerger.
- ///
- /// \param[in] src_context
- /// The ASTContext containing the type.
- ///
- /// \param[in] merger
- /// The merger to use. This isn't just *m_merger_up because it might be
- /// the persistent AST context's merger.
- ///
- /// \param[in] type
- /// The type to copy.
- ///
- /// \return
- /// A copy of the Type in the merger's target context.
- clang::QualType CopyTypeWithMerger(clang::ASTContext &src_context,
- clang::ExternalASTMerger &merger,
- clang::QualType type);
/// Determined the origin of a single Decl, if it can be found.
///
@@ -390,16 +354,7 @@ public:
///
/// \return
/// True if lookup succeeded; false otherwise.
- bool ResolveDeclOrigin(const clang::Decl *decl, clang::Decl **original_decl,
- clang::ASTContext **original_ctx);
-
- /// Returns m_merger_up. Only call this if the target is configured to use
- /// modern lookup,
- clang::ExternalASTMerger &GetMergerUnchecked();
-
- /// Returns true if there is a merger. This only occurs if the target is
- /// using modern lookup.
- bool HasMerger() { return (bool)m_merger_up; }
+ ClangASTImporter::DeclOrigin GetDeclOrigin(const clang::Decl *decl);
protected:
bool FindObjCMethodDeclsWithOrigin(
@@ -411,15 +366,16 @@ protected:
bool m_import_in_progress;
bool m_lookups_enabled;
- const lldb::TargetSP
- m_target; ///< The target to use in finding variables and types.
- clang::ASTContext
- *m_ast_context; ///< The AST context requests are coming in for.
- clang::FileManager
- *m_file_manager; ///< The file manager paired with the AST context.
- lldb::ClangASTImporterSP m_ast_importer_sp; ///< The target's AST importer.
- std::unique_ptr<clang::ExternalASTMerger> m_merger_up;
- ///< The ExternalASTMerger for this parse.
+ /// The target to use in finding variables and types.
+ const lldb::TargetSP m_target;
+ /// The AST context requests are coming in for.
+ clang::ASTContext *m_ast_context;
+ /// The ClangASTContext for m_ast_context.
+ ClangASTContext *m_clang_ast_context;
+ /// The file manager paired with the AST context.
+ clang::FileManager *m_file_manager;
+ /// The target's AST importer.
+ lldb::ClangASTImporterSP m_ast_importer_sp;
std::set<const clang::Decl *> m_active_lexical_decls;
std::set<const char *> m_active_lookups;
};
@@ -432,20 +388,20 @@ protected:
/// what name is being searched for and provides helper functions to construct
/// Decls given appropriate type information.
struct NameSearchContext {
- ClangASTSource &m_ast_source; ///< The AST source making the request
- llvm::SmallVectorImpl<clang::NamedDecl *>
- &m_decls; ///< The list of declarations already constructed
- ClangASTImporter::NamespaceMapSP m_namespace_map; ///< The mapping of all
- ///namespaces found for this
- ///request back to their
- ///modules
- const clang::DeclarationName &m_decl_name; ///< The name being looked for
- const clang::DeclContext
- *m_decl_context; ///< The DeclContext to put declarations into
- llvm::SmallSet<CompilerType, 5> m_function_types; ///< All the types of
- ///functions that have been
- ///reported, so we don't
- ///report conflicts
+ /// The AST source making the request.
+ ClangASTSource &m_ast_source;
+ /// The list of declarations already constructed.
+ llvm::SmallVectorImpl<clang::NamedDecl *> &m_decls;
+ /// The mapping of all namespaces found for this request back to their
+ /// modules.
+ ClangASTImporter::NamespaceMapSP m_namespace_map;
+ /// The name being looked for.
+ const clang::DeclarationName &m_decl_name;
+ /// The DeclContext to put declarations into.
+ const clang::DeclContext *m_decl_context;
+ /// All the types of functions that have been reported, so we don't
+ /// report conflicts.
+ llvm::SmallSet<CompilerType, 5> m_function_types;
struct {
bool variable : 1;
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp
index c59722b7b4f8..c87507a25855 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.cpp
@@ -15,16 +15,16 @@ using namespace lldb_private;
uint32_t ClangDeclVendor::FindDecls(ConstString name, bool append,
uint32_t max_matches,
- std::vector<CompilerDecl> &decls) {
+ std::vector<clang::NamedDecl *> &decls) {
if (!append)
decls.clear();
- std::vector<clang::NamedDecl *> named_decls;
- uint32_t ret = FindDecls(name, /*append*/ false, max_matches, named_decls);
- for (auto *named_decl : named_decls) {
- decls.push_back(CompilerDecl(
- ClangASTContext::GetASTContext(&named_decl->getASTContext()),
- named_decl));
+ std::vector<CompilerDecl> compiler_decls;
+ uint32_t ret = FindDecls(name, /*append*/ false, max_matches, compiler_decls);
+ for (CompilerDecl compiler_decl : compiler_decls) {
+ clang::Decl *d = static_cast<clang::Decl *>(compiler_decl.GetOpaqueDecl());
+ clang::NamedDecl *nd = llvm::cast<clang::NamedDecl>(d);
+ decls.push_back(nd);
}
return ret;
}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h
index 90b715f37cba..0c888de08841 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangDeclVendor.h
@@ -12,8 +12,6 @@
#include "lldb/Core/ClangForward.h"
#include "lldb/Symbol/DeclVendor.h"
-#include "clang/AST/ExternalASTMerger.h"
-
namespace lldb_private {
// A clang specialized extension to DeclVendor.
@@ -23,19 +21,10 @@ public:
virtual ~ClangDeclVendor() {}
- /// Interface for ExternalASTMerger. Returns an ImporterSource allowing type
- /// completion.
- ///
- /// \return
- /// An ImporterSource for this ClangDeclVendor.
- virtual clang::ExternalASTMerger::ImporterSource GetImporterSource() = 0;
+ using DeclVendor::FindDecls;
uint32_t FindDecls(ConstString name, bool append, uint32_t max_matches,
- std::vector<CompilerDecl> &decls) override;
-
- virtual uint32_t FindDecls(ConstString name, bool append,
- uint32_t max_matches,
- std::vector<clang::NamedDecl *> &decls) = 0;
+ std::vector<clang::NamedDecl *> &decls);
static bool classof(const DeclVendor *vendor) {
return vendor->GetKind() >= eClangDeclVendor &&
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
index f4457fc1b740..bf3023be5f60 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -8,7 +8,6 @@
#include "ClangExpressionDeclMap.h"
-#include "ASTDumper.h"
#include "ClangASTSource.h"
#include "ClangModulesDeclVendor.h"
#include "ClangPersistentVariables.h"
@@ -20,6 +19,7 @@
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Expression/Materializer.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/CompilerDecl.h"
#include "lldb/Symbol/CompilerDeclContext.h"
@@ -65,9 +65,10 @@ const char *g_lldb_local_vars_namespace_cstr = "$__lldb_local_vars";
ClangExpressionDeclMap::ClangExpressionDeclMap(
bool keep_result_in_memory,
Materializer::PersistentVariableDelegate *result_delegate,
- ExecutionContext &exe_ctx, ValueObject *ctx_obj)
- : ClangASTSource(exe_ctx.GetTargetSP()), m_found_entities(),
- m_struct_members(), m_keep_result_in_memory(keep_result_in_memory),
+ const lldb::TargetSP &target, const lldb::ClangASTImporterSP &importer,
+ ValueObject *ctx_obj)
+ : ClangASTSource(target, importer), m_found_entities(), m_struct_members(),
+ m_keep_result_in_memory(keep_result_in_memory),
m_result_delegate(result_delegate), m_ctx_obj(ctx_obj), m_parser_vars(),
m_struct_vars() {
EnableStructVars();
@@ -84,8 +85,6 @@ ClangExpressionDeclMap::~ClangExpressionDeclMap() {
bool ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx,
Materializer *materializer) {
- ClangASTMetrics::ClearLocalCounters();
-
EnableParserVars();
m_parser_vars->m_exe_ctx = exe_ctx;
@@ -110,7 +109,7 @@ bool ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx,
m_parser_vars->m_persistent_vars = llvm::cast<ClangPersistentVariables>(
target->GetPersistentExpressionStateForLanguage(eLanguageTypeC));
- if (!target->GetScratchClangASTContext())
+ if (!ClangASTContext::GetScratch(*target))
return false;
}
@@ -127,12 +126,7 @@ void ClangExpressionDeclMap::InstallCodeGenerator(
}
void ClangExpressionDeclMap::DidParse() {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
-
- if (log)
- ClangASTMetrics::DumpCounters(log);
-
- if (m_parser_vars) {
+ if (m_parser_vars && m_parser_vars->m_persistent_vars) {
for (size_t entity_index = 0, num_entities = m_found_entities.GetSize();
entity_index < num_entities; ++entity_index) {
ExpressionVariableSP var_sp(
@@ -180,55 +174,15 @@ ClangExpressionDeclMap::TargetInfo ClangExpressionDeclMap::GetTargetInfo() {
return ret;
}
-static clang::QualType ExportAllDeclaredTypes(
- clang::ExternalASTMerger &parent_merger, clang::ExternalASTMerger &merger,
- clang::ASTContext &source, clang::FileManager &source_file_manager,
- const clang::ExternalASTMerger::OriginMap &source_origin_map,
- clang::FileID file, clang::QualType root) {
- // Mark the source as temporary to make sure all declarations from the
- // AST are exported. Also add the parent_merger as the merger into the
- // source AST so that the merger can track back any declarations from
- // the persistent ASTs we used as sources.
- clang::ExternalASTMerger::ImporterSource importer_source(
- source, source_file_manager, source_origin_map, /*Temporary*/ true,
- &parent_merger);
- merger.AddSources(importer_source);
- clang::ASTImporter &exporter = merger.ImporterForOrigin(source);
- llvm::Expected<clang::QualType> ret_or_error = exporter.Import(root);
- merger.RemoveSources(importer_source);
- if (ret_or_error) {
- return *ret_or_error;
- } else {
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
- LLDB_LOG_ERROR(log, ret_or_error.takeError(), "Couldn't import type: {0}");
- return clang::QualType();
- }
-}
-
TypeFromUser ClangExpressionDeclMap::DeportType(ClangASTContext &target,
ClangASTContext &source,
TypeFromParser parser_type) {
- assert(&target == m_target->GetScratchClangASTContext());
+ assert(&target == ClangASTContext::GetScratch(*m_target));
assert((TypeSystem *)&source == parser_type.GetTypeSystem());
- assert(source.getASTContext() == m_ast_context);
+ assert(&source.getASTContext() == m_ast_context);
if (m_ast_importer_sp) {
- return TypeFromUser(m_ast_importer_sp->DeportType(
- target.getASTContext(), source.getASTContext(),
- parser_type.GetOpaqueQualType()),
- &target);
- } else if (m_merger_up) {
- clang::FileID source_file =
- source.getASTContext()->getSourceManager().getFileID(
- source.getASTContext()->getTranslationUnitDecl()->getLocation());
- auto scratch_ast_context = static_cast<ClangASTContextForExpressions *>(
- m_target->GetScratchClangASTContext());
- clang::QualType exported_type = ExportAllDeclaredTypes(
- *m_merger_up.get(), scratch_ast_context->GetMergerUnchecked(),
- *source.getASTContext(), *source.getFileManager(),
- m_merger_up->GetOrigins(), source_file,
- clang::QualType::getFromOpaquePtr(parser_type.GetOpaqueQualType()));
- return TypeFromUser(exported_type.getAsOpaquePtr(), &target);
+ return TypeFromUser(m_ast_importer_sp->DeportType(target, parser_type));
} else {
lldbassert(0 && "No mechanism for deporting a type!");
return TypeFromUser();
@@ -255,8 +209,11 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl,
if (target == nullptr)
return false;
- TypeFromUser user_type =
- DeportType(*target->GetScratchClangASTContext(), *ast, parser_type);
+ auto *clang_ast_context = ClangASTContext::GetScratch(*target);
+ if (!clang_ast_context)
+ return false;
+
+ TypeFromUser user_type = DeportType(*clang_ast_context, *ast, parser_type);
uint32_t offset = m_parser_vars->m_materializer->AddResultVariable(
user_type, is_lvalue, m_keep_result_in_memory, m_result_delegate, err);
@@ -291,7 +248,9 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl,
if (target == nullptr)
return false;
- ClangASTContext *context(target->GetScratchClangASTContext());
+ ClangASTContext *context = ClangASTContext::GetScratch(*target);
+ if (!context)
+ return false;
TypeFromUser user_type = DeportType(*context, *ast, parser_type);
@@ -303,6 +262,9 @@ bool ClangExpressionDeclMap::AddPersistentVariable(const NamedDecl *decl,
if (!m_parser_vars->m_target_info.IsValid())
return false;
+ if (!m_parser_vars->m_persistent_vars)
+ return false;
+
ClangExpressionVariable *var = llvm::cast<ClangExpressionVariable>(
m_parser_vars->m_persistent_vars
->CreatePersistentVariable(
@@ -368,7 +330,7 @@ bool ClangExpressionDeclMap::AddValueToStruct(const NamedDecl *decl,
ClangExpressionVariable *var(ClangExpressionVariable::FindVariableInList(
m_found_entities, decl, GetParserID()));
- if (!var) {
+ if (!var && m_parser_vars->m_persistent_vars) {
var = ClangExpressionVariable::FindVariableInList(
*m_parser_vars->m_persistent_vars, decl, GetParserID());
is_persistent_variable = true;
@@ -638,7 +600,7 @@ addr_t ClangExpressionDeclMap::GetSymbolAddress(ConstString name,
lldb::VariableSP ClangExpressionDeclMap::FindGlobalVariable(
Target &target, ModuleSP &module, ConstString name,
- CompilerDeclContext *namespace_decl, TypeFromUser *type) {
+ CompilerDeclContext *namespace_decl) {
VariableList vars;
if (module && namespace_decl)
@@ -646,21 +608,9 @@ lldb::VariableSP ClangExpressionDeclMap::FindGlobalVariable(
else
target.GetImages().FindGlobalVariables(name, -1, vars);
- if (vars.GetSize()) {
- if (type) {
- for (size_t i = 0; i < vars.GetSize(); ++i) {
- VariableSP var_sp = vars.GetVariableAtIndex(i);
-
- if (ClangASTContext::AreTypesSame(
- *type, var_sp->GetType()->GetFullCompilerType()))
- return var_sp;
- }
- } else {
- return vars.GetVariableAtIndex(0);
- }
- }
-
- return VariableSP();
+ if (vars.GetSize() == 0)
+ return VariableSP();
+ return vars.GetVariableAtIndex(0);
}
ClangASTContext *ClangExpressionDeclMap::GetClangASTContext() {
@@ -687,8 +637,6 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
NameSearchContext &context) {
assert(m_ast_context);
- ClangASTMetrics::RegisterVisibleQuery();
-
const ConstString name(context.m_decl_name.getAsString().c_str());
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
@@ -727,9 +675,9 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
dyn_cast<NamespaceDecl>(context.m_decl_context)) {
if (namespace_context->getName().str() ==
std::string(g_lldb_local_vars_namespace_cstr)) {
- CompilerDeclContext compiler_decl_ctx(
- GetClangASTContext(), const_cast<void *>(static_cast<const void *>(
- context.m_decl_context)));
+ CompilerDeclContext compiler_decl_ctx =
+ m_clang_ast_context->CreateDeclContext(
+ const_cast<clang::DeclContext *>(context.m_decl_context));
FindExternalVisibleDecls(context, lldb::ModuleSP(), compiler_decl_ctx,
current_id);
return;
@@ -771,743 +719,760 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
ClangASTSource::FindExternalVisibleDecls(context);
}
-void ClangExpressionDeclMap::FindExternalVisibleDecls(
- NameSearchContext &context, lldb::ModuleSP module_sp,
- CompilerDeclContext &namespace_decl, unsigned int current_id) {
- assert(m_ast_context);
+void ClangExpressionDeclMap::MaybeRegisterFunctionBody(
+ FunctionDecl *copied_function_decl) {
+ if (copied_function_decl->getBody() && m_parser_vars->m_code_gen) {
+ clang::DeclGroupRef decl_group_ref(copied_function_decl);
+ m_parser_vars->m_code_gen->HandleTopLevelDecl(decl_group_ref);
+ }
+}
- std::function<void(clang::FunctionDecl *)> MaybeRegisterFunctionBody =
- [this](clang::FunctionDecl *copied_function_decl) {
- if (copied_function_decl->getBody() && m_parser_vars->m_code_gen) {
- DeclGroupRef decl_group_ref(copied_function_decl);
- m_parser_vars->m_code_gen->HandleTopLevelDecl(decl_group_ref);
- }
- };
+clang::NamedDecl *ClangExpressionDeclMap::GetPersistentDecl(ConstString name) {
+ if (!m_parser_vars)
+ return nullptr;
+ Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
+ if (!target)
+ return nullptr;
+
+ ClangASTContext::GetScratch(*target);
+
+ if (!m_parser_vars->m_persistent_vars)
+ return nullptr;
+ return m_parser_vars->m_persistent_vars->GetPersistentDecl(name);
+}
+void ClangExpressionDeclMap::SearchPersistenDecls(NameSearchContext &context,
+ const ConstString name,
+ unsigned int current_id) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- SymbolContextList sc_list;
+ NamedDecl *persistent_decl = GetPersistentDecl(name);
- const ConstString name(context.m_decl_name.getAsString().c_str());
- if (IgnoreName(name, false))
+ if (!persistent_decl)
return;
- // Only look for functions by name out in our symbols if the function doesn't
- // start with our phony prefix of '$'
- Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
+ Decl *parser_persistent_decl = CopyDecl(persistent_decl);
+
+ if (!parser_persistent_decl)
+ return;
+
+ NamedDecl *parser_named_decl = dyn_cast<NamedDecl>(parser_persistent_decl);
+
+ if (!parser_named_decl)
+ return;
+
+ if (clang::FunctionDecl *parser_function_decl =
+ llvm::dyn_cast<clang::FunctionDecl>(parser_named_decl)) {
+ MaybeRegisterFunctionBody(parser_function_decl);
+ }
+
+ LLDB_LOGF(log, " CEDM::FEVD[%u] Found persistent decl %s", current_id,
+ name.GetCString());
+
+ context.AddNamedDecl(parser_named_decl);
+}
+
+void ClangExpressionDeclMap::LookUpLldbClass(NameSearchContext &context,
+ unsigned int current_id) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
SymbolContext sym_ctx;
if (frame != nullptr)
sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
lldb::eSymbolContextBlock);
- // Try the persistent decls, which take precedence over all else.
- if (!namespace_decl) {
- do {
- if (!target)
- break;
+ if (m_ctx_obj) {
+ Status status;
+ lldb::ValueObjectSP ctx_obj_ptr = m_ctx_obj->AddressOf(status);
+ if (!ctx_obj_ptr || status.Fail())
+ return;
- ClangASTContext *scratch_clang_ast_context =
- target->GetScratchClangASTContext();
+ AddThisType(context, TypeFromUser(m_ctx_obj->GetCompilerType()),
+ current_id);
- if (!scratch_clang_ast_context)
- break;
+ m_struct_vars->m_object_pointer_type =
+ TypeFromUser(ctx_obj_ptr->GetCompilerType());
- ASTContext *scratch_ast_context =
- scratch_clang_ast_context->getASTContext();
+ return;
+ }
- if (!scratch_ast_context)
- break;
+ // Clang is looking for the type of "this"
- NamedDecl *persistent_decl =
- m_parser_vars->m_persistent_vars->GetPersistentDecl(name);
+ if (frame == nullptr)
+ return;
- if (!persistent_decl)
- break;
+ // Find the block that defines the function represented by "sym_ctx"
+ Block *function_block = sym_ctx.GetFunctionBlock();
- Decl *parser_persistent_decl = CopyDecl(persistent_decl);
+ if (!function_block)
+ return;
- if (!parser_persistent_decl)
- break;
+ CompilerDeclContext function_decl_ctx = function_block->GetDeclContext();
- NamedDecl *parser_named_decl =
- dyn_cast<NamedDecl>(parser_persistent_decl);
+ if (!function_decl_ctx)
+ return;
- if (!parser_named_decl)
- break;
+ clang::CXXMethodDecl *method_decl =
+ ClangASTContext::DeclContextGetAsCXXMethodDecl(function_decl_ctx);
- if (clang::FunctionDecl *parser_function_decl =
- llvm::dyn_cast<clang::FunctionDecl>(parser_named_decl)) {
- MaybeRegisterFunctionBody(parser_function_decl);
- }
+ if (method_decl) {
+ clang::CXXRecordDecl *class_decl = method_decl->getParent();
- LLDB_LOGF(log, " CEDM::FEVD[%u] Found persistent decl %s", current_id,
- name.GetCString());
+ QualType class_qual_type(class_decl->getTypeForDecl(), 0);
- context.AddNamedDecl(parser_named_decl);
- } while (false);
- }
+ TypeFromUser class_user_type(class_qual_type.getAsOpaquePtr(),
+ function_decl_ctx.GetTypeSystem());
- if (name.GetCString()[0] == '$' && !namespace_decl) {
- static ConstString g_lldb_class_name("$__lldb_class");
+ LLDB_LOG(log, " CEDM::FEVD[{0}] Adding type for $__lldb_class: {1}",
+ current_id, class_qual_type.getAsString());
- if (name == g_lldb_class_name) {
- if (m_ctx_obj) {
- Status status;
- lldb::ValueObjectSP ctx_obj_ptr = m_ctx_obj->AddressOf(status);
- if (!ctx_obj_ptr || status.Fail())
- return;
+ AddThisType(context, class_user_type, current_id);
- AddThisType(context, TypeFromUser(m_ctx_obj->GetCompilerType()),
- current_id);
+ if (method_decl->isInstance()) {
+ // self is a pointer to the object
- m_struct_vars->m_object_pointer_type =
- TypeFromUser(ctx_obj_ptr->GetCompilerType());
+ QualType class_pointer_type =
+ method_decl->getASTContext().getPointerType(class_qual_type);
- return;
- }
+ TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(),
+ function_decl_ctx.GetTypeSystem());
- // Clang is looking for the type of "this"
+ m_struct_vars->m_object_pointer_type = self_user_type;
+ }
+ return;
+ }
- if (frame == nullptr)
- return;
+ // This branch will get hit if we are executing code in the context of
+ // a function that claims to have an object pointer (through
+ // DW_AT_object_pointer?) but is not formally a method of the class.
+ // In that case, just look up the "this" variable in the current scope
+ // and use its type.
+ // FIXME: This code is formally correct, but clang doesn't currently
+ // emit DW_AT_object_pointer
+ // for C++ so it hasn't actually been tested.
- // Find the block that defines the function represented by "sym_ctx"
- Block *function_block = sym_ctx.GetFunctionBlock();
+ VariableList *vars = frame->GetVariableList(false);
- if (!function_block)
- return;
+ lldb::VariableSP this_var = vars->FindVariable(ConstString("this"));
- CompilerDeclContext function_decl_ctx = function_block->GetDeclContext();
+ if (this_var && this_var->IsInScope(frame) &&
+ this_var->LocationIsValidForFrame(frame)) {
+ Type *this_type = this_var->GetType();
- if (!function_decl_ctx)
- return;
+ if (!this_type)
+ return;
- clang::CXXMethodDecl *method_decl =
- ClangASTContext::DeclContextGetAsCXXMethodDecl(function_decl_ctx);
+ TypeFromUser pointee_type =
+ this_type->GetForwardCompilerType().GetPointeeType();
- if (method_decl) {
- clang::CXXRecordDecl *class_decl = method_decl->getParent();
+ LLDB_LOG(log, " FEVD[{0}] Adding type for $__lldb_class: {1}", current_id,
+ ClangUtil::GetQualType(pointee_type).getAsString());
- QualType class_qual_type(class_decl->getTypeForDecl(), 0);
+ AddThisType(context, pointee_type, current_id);
+ TypeFromUser this_user_type(this_type->GetFullCompilerType());
+ m_struct_vars->m_object_pointer_type = this_user_type;
+ }
+}
- TypeFromUser class_user_type(
- class_qual_type.getAsOpaquePtr(),
- ClangASTContext::GetASTContext(&class_decl->getASTContext()));
+void ClangExpressionDeclMap::LookUpLldbObjCClass(NameSearchContext &context,
+ unsigned int current_id) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- if (log) {
- ASTDumper ast_dumper(class_qual_type);
- LLDB_LOGF(log, " CEDM::FEVD[%u] Adding type for $__lldb_class: %s",
- current_id, ast_dumper.GetCString());
- }
+ StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
- AddThisType(context, class_user_type, current_id);
+ if (m_ctx_obj) {
+ Status status;
+ lldb::ValueObjectSP ctx_obj_ptr = m_ctx_obj->AddressOf(status);
+ if (!ctx_obj_ptr || status.Fail())
+ return;
- if (method_decl->isInstance()) {
- // self is a pointer to the object
+ AddOneType(context, TypeFromUser(m_ctx_obj->GetCompilerType()), current_id);
- QualType class_pointer_type =
- method_decl->getASTContext().getPointerType(class_qual_type);
+ m_struct_vars->m_object_pointer_type =
+ TypeFromUser(ctx_obj_ptr->GetCompilerType());
- TypeFromUser self_user_type(
- class_pointer_type.getAsOpaquePtr(),
- ClangASTContext::GetASTContext(&method_decl->getASTContext()));
+ return;
+ }
- m_struct_vars->m_object_pointer_type = self_user_type;
- }
- } else {
- // This branch will get hit if we are executing code in the context of
- // a function that claims to have an object pointer (through
- // DW_AT_object_pointer?) but is not formally a method of the class.
- // In that case, just look up the "this" variable in the current scope
- // and use its type.
- // FIXME: This code is formally correct, but clang doesn't currently
- // emit DW_AT_object_pointer
- // for C++ so it hasn't actually been tested.
+ // Clang is looking for the type of "*self"
+
+ if (!frame)
+ return;
- VariableList *vars = frame->GetVariableList(false);
+ SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
+ lldb::eSymbolContextBlock);
- lldb::VariableSP this_var = vars->FindVariable(ConstString("this"));
+ // Find the block that defines the function represented by "sym_ctx"
+ Block *function_block = sym_ctx.GetFunctionBlock();
- if (this_var && this_var->IsInScope(frame) &&
- this_var->LocationIsValidForFrame(frame)) {
- Type *this_type = this_var->GetType();
+ if (!function_block)
+ return;
- if (!this_type)
- return;
+ CompilerDeclContext function_decl_ctx = function_block->GetDeclContext();
- TypeFromUser pointee_type =
- this_type->GetForwardCompilerType().GetPointeeType();
+ if (!function_decl_ctx)
+ return;
- if (pointee_type.IsValid()) {
- if (log) {
- ASTDumper ast_dumper(pointee_type);
- LLDB_LOGF(log, " FEVD[%u] Adding type for $__lldb_class: %s",
- current_id, ast_dumper.GetCString());
- }
+ clang::ObjCMethodDecl *method_decl =
+ ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx);
- AddThisType(context, pointee_type, current_id);
- TypeFromUser this_user_type(this_type->GetFullCompilerType());
- m_struct_vars->m_object_pointer_type = this_user_type;
- return;
- }
- }
- }
+ if (method_decl) {
+ ObjCInterfaceDecl *self_interface = method_decl->getClassInterface();
+ if (!self_interface)
return;
- }
- static ConstString g_lldb_objc_class_name("$__lldb_objc_class");
- if (name == g_lldb_objc_class_name) {
- if (m_ctx_obj) {
- Status status;
- lldb::ValueObjectSP ctx_obj_ptr = m_ctx_obj->AddressOf(status);
- if (!ctx_obj_ptr || status.Fail())
- return;
+ const clang::Type *interface_type = self_interface->getTypeForDecl();
- AddOneType(context, TypeFromUser(m_ctx_obj->GetCompilerType()),
- current_id);
+ if (!interface_type)
+ return; // This is unlikely, but we have seen crashes where this
+ // occurred
- m_struct_vars->m_object_pointer_type =
- TypeFromUser(ctx_obj_ptr->GetCompilerType());
+ TypeFromUser class_user_type(QualType(interface_type, 0).getAsOpaquePtr(),
+ function_decl_ctx.GetTypeSystem());
- return;
- }
+ LLDB_LOG(log, " FEVD[{0}] Adding type for $__lldb_objc_class: {1}",
+ current_id, ClangUtil::ToString(interface_type));
- // Clang is looking for the type of "*self"
+ AddOneType(context, class_user_type, current_id);
- if (!frame)
- return;
+ if (method_decl->isInstanceMethod()) {
+ // self is a pointer to the object
- SymbolContext sym_ctx = frame->GetSymbolContext(
- lldb::eSymbolContextFunction | lldb::eSymbolContextBlock);
+ QualType class_pointer_type =
+ method_decl->getASTContext().getObjCObjectPointerType(
+ QualType(interface_type, 0));
- // Find the block that defines the function represented by "sym_ctx"
- Block *function_block = sym_ctx.GetFunctionBlock();
+ TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(),
+ function_decl_ctx.GetTypeSystem());
- if (!function_block)
- return;
+ m_struct_vars->m_object_pointer_type = self_user_type;
+ } else {
+ // self is a Class pointer
+ QualType class_type = method_decl->getASTContext().getObjCClassType();
- CompilerDeclContext function_decl_ctx = function_block->GetDeclContext();
+ TypeFromUser self_user_type(class_type.getAsOpaquePtr(),
+ function_decl_ctx.GetTypeSystem());
- if (!function_decl_ctx)
- return;
+ m_struct_vars->m_object_pointer_type = self_user_type;
+ }
- clang::ObjCMethodDecl *method_decl =
- ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx);
+ return;
+ }
+ // This branch will get hit if we are executing code in the context of
+ // a function that claims to have an object pointer (through
+ // DW_AT_object_pointer?) but is not formally a method of the class.
+ // In that case, just look up the "self" variable in the current scope
+ // and use its type.
- if (method_decl) {
- ObjCInterfaceDecl *self_interface = method_decl->getClassInterface();
+ VariableList *vars = frame->GetVariableList(false);
- if (!self_interface)
- return;
+ lldb::VariableSP self_var = vars->FindVariable(ConstString("self"));
- const clang::Type *interface_type = self_interface->getTypeForDecl();
+ if (!self_var)
+ return;
+ if (!self_var->IsInScope(frame))
+ return;
+ if (!self_var->LocationIsValidForFrame(frame))
+ return;
- if (!interface_type)
- return; // This is unlikely, but we have seen crashes where this
- // occurred
+ Type *self_type = self_var->GetType();
- TypeFromUser class_user_type(
- QualType(interface_type, 0).getAsOpaquePtr(),
- ClangASTContext::GetASTContext(&method_decl->getASTContext()));
+ if (!self_type)
+ return;
- if (log) {
- ASTDumper ast_dumper(interface_type);
- LLDB_LOGF(log, " FEVD[%u] Adding type for $__lldb_objc_class: %s",
- current_id, ast_dumper.GetCString());
- }
+ CompilerType self_clang_type = self_type->GetFullCompilerType();
- AddOneType(context, class_user_type, current_id);
+ if (ClangASTContext::IsObjCClassType(self_clang_type)) {
+ return;
+ }
+ if (!ClangASTContext::IsObjCObjectPointerType(self_clang_type))
+ return;
+ self_clang_type = self_clang_type.GetPointeeType();
- if (method_decl->isInstanceMethod()) {
- // self is a pointer to the object
+ if (!self_clang_type)
+ return;
- QualType class_pointer_type =
- method_decl->getASTContext().getObjCObjectPointerType(
- QualType(interface_type, 0));
+ LLDB_LOG(log, " FEVD[{0}] Adding type for $__lldb_objc_class: {1}",
+ current_id, ClangUtil::ToString(self_type->GetFullCompilerType()));
- TypeFromUser self_user_type(
- class_pointer_type.getAsOpaquePtr(),
- ClangASTContext::GetASTContext(&method_decl->getASTContext()));
+ TypeFromUser class_user_type(self_clang_type);
- m_struct_vars->m_object_pointer_type = self_user_type;
- } else {
- // self is a Class pointer
- QualType class_type = method_decl->getASTContext().getObjCClassType();
+ AddOneType(context, class_user_type, current_id);
- TypeFromUser self_user_type(
- class_type.getAsOpaquePtr(),
- ClangASTContext::GetASTContext(&method_decl->getASTContext()));
+ TypeFromUser self_user_type(self_type->GetFullCompilerType());
- m_struct_vars->m_object_pointer_type = self_user_type;
- }
+ m_struct_vars->m_object_pointer_type = self_user_type;
+}
- return;
- } else {
- // This branch will get hit if we are executing code in the context of
- // a function that claims to have an object pointer (through
- // DW_AT_object_pointer?) but is not formally a method of the class.
- // In that case, just look up the "self" variable in the current scope
- // and use its type.
+void ClangExpressionDeclMap::LookupLocalVarNamespace(
+ SymbolContext &sym_ctx, NameSearchContext &name_context) {
+ if (sym_ctx.block == nullptr)
+ return;
- VariableList *vars = frame->GetVariableList(false);
+ CompilerDeclContext frame_decl_context = sym_ctx.block->GetDeclContext();
+ if (!frame_decl_context)
+ return;
- lldb::VariableSP self_var = vars->FindVariable(ConstString("self"));
+ ClangASTContext *frame_ast = llvm::dyn_cast_or_null<ClangASTContext>(
+ frame_decl_context.GetTypeSystem());
+ if (!frame_ast)
+ return;
- if (self_var && self_var->IsInScope(frame) &&
- self_var->LocationIsValidForFrame(frame)) {
- Type *self_type = self_var->GetType();
+ clang::NamespaceDecl *namespace_decl =
+ m_clang_ast_context->GetUniqueNamespaceDeclaration(
+ g_lldb_local_vars_namespace_cstr, nullptr);
+ if (!namespace_decl)
+ return;
- if (!self_type)
- return;
+ name_context.AddNamedDecl(namespace_decl);
+ clang::DeclContext *ctxt = clang::Decl::castToDeclContext(namespace_decl);
+ ctxt->setHasExternalVisibleStorage(true);
+ name_context.m_found.local_vars_nsp = true;
+}
- CompilerType self_clang_type = self_type->GetFullCompilerType();
+void ClangExpressionDeclMap::LookupInModulesDeclVendor(
+ NameSearchContext &context, ConstString name, unsigned current_id) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- if (ClangASTContext::IsObjCClassType(self_clang_type)) {
- return;
- } else if (ClangASTContext::IsObjCObjectPointerType(
- self_clang_type)) {
- self_clang_type = self_clang_type.GetPointeeType();
+ if (!m_target)
+ return;
- if (!self_clang_type)
- return;
+ auto *modules_decl_vendor = m_target->GetClangModulesDeclVendor();
+ if (!modules_decl_vendor)
+ return;
- if (log) {
- ASTDumper ast_dumper(self_type->GetFullCompilerType());
- LLDB_LOGF(log,
- " FEVD[%u] Adding type for $__lldb_objc_class: %s",
- current_id, ast_dumper.GetCString());
- }
+ bool append = false;
+ uint32_t max_matches = 1;
+ std::vector<clang::NamedDecl *> decls;
- TypeFromUser class_user_type(self_clang_type);
+ if (!modules_decl_vendor->FindDecls(name, append, max_matches, decls))
+ return;
- AddOneType(context, class_user_type, current_id);
+ assert(!decls.empty() && "FindDecls returned true but no decls?");
+ clang::NamedDecl *const decl_from_modules = decls[0];
- TypeFromUser self_user_type(self_type->GetFullCompilerType());
+ LLDB_LOG(log,
+ " CAS::FEVD[{0}] Matching decl found for "
+ "\"{1}\" in the modules",
+ current_id, name);
- m_struct_vars->m_object_pointer_type = self_user_type;
- return;
- }
- }
- }
+ clang::Decl *copied_decl = CopyDecl(decl_from_modules);
+ if (!copied_decl) {
+ LLDB_LOG(log,
+ " CAS::FEVD[{0}] - Couldn't export a "
+ "declaration from the modules",
+ current_id);
+ return;
+ }
- return;
- }
+ if (auto copied_function = dyn_cast<clang::FunctionDecl>(copied_decl)) {
+ MaybeRegisterFunctionBody(copied_function);
- if (name == ConstString(g_lldb_local_vars_namespace_cstr)) {
- CompilerDeclContext frame_decl_context =
- sym_ctx.block != nullptr ? sym_ctx.block->GetDeclContext()
- : CompilerDeclContext();
-
- if (frame_decl_context) {
- ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(
- frame_decl_context.GetTypeSystem());
-
- if (ast) {
- clang::NamespaceDecl *namespace_decl =
- ClangASTContext::GetUniqueNamespaceDeclaration(
- m_ast_context, name.GetCString(), nullptr);
- if (namespace_decl) {
- context.AddNamedDecl(namespace_decl);
- clang::DeclContext *clang_decl_ctx =
- clang::Decl::castToDeclContext(namespace_decl);
- clang_decl_ctx->setHasExternalVisibleStorage(true);
- context.m_found.local_vars_nsp = true;
- }
- }
- }
+ context.AddNamedDecl(copied_function);
- return;
- }
+ context.m_found.function_with_type_info = true;
+ context.m_found.function = true;
+ } else if (auto copied_var = dyn_cast<clang::VarDecl>(copied_decl)) {
+ context.AddNamedDecl(copied_var);
+ context.m_found.variable = true;
+ }
+}
- // any other $__lldb names should be weeded out now
- if (name.GetStringRef().startswith("$__lldb"))
- return;
+bool ClangExpressionDeclMap::LookupLocalVariable(
+ NameSearchContext &context, ConstString name, unsigned current_id,
+ SymbolContext &sym_ctx, CompilerDeclContext &namespace_decl) {
+ if (sym_ctx.block == nullptr)
+ return false;
- ExpressionVariableSP pvar_sp(
- m_parser_vars->m_persistent_vars->GetVariable(name));
+ CompilerDeclContext decl_context = sym_ctx.block->GetDeclContext();
+ if (!decl_context)
+ return false;
- if (pvar_sp) {
- AddOneVariable(context, pvar_sp, current_id);
- return;
+ // Make sure that the variables are parsed so that we have the
+ // declarations.
+ StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
+ VariableListSP vars = frame->GetInScopeVariableList(true);
+ for (size_t i = 0; i < vars->GetSize(); i++)
+ vars->GetVariableAtIndex(i)->GetDecl();
+
+ // Search for declarations matching the name. Do not include imported
+ // decls in the search if we are looking for decls in the artificial
+ // namespace $__lldb_local_vars.
+ std::vector<CompilerDecl> found_decls =
+ decl_context.FindDeclByName(name, namespace_decl.IsValid());
+
+ VariableSP var;
+ bool variable_found = false;
+ for (CompilerDecl decl : found_decls) {
+ for (size_t vi = 0, ve = vars->GetSize(); vi != ve; ++vi) {
+ VariableSP candidate_var = vars->GetVariableAtIndex(vi);
+ if (candidate_var->GetDecl() == decl) {
+ var = candidate_var;
+ break;
+ }
}
- const char *reg_name(&name.GetCString()[1]);
+ if (var && !variable_found) {
+ variable_found = true;
+ ValueObjectSP valobj = ValueObjectVariable::Create(frame, var);
+ AddOneVariable(context, var, valobj, current_id);
+ context.m_found.variable = true;
+ }
+ }
+ return variable_found;
+}
- if (m_parser_vars->m_exe_ctx.GetRegisterContext()) {
- const RegisterInfo *reg_info(
- m_parser_vars->m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName(
- reg_name));
+/// Structure to hold the info needed when comparing function
+/// declarations.
+namespace {
+struct FuncDeclInfo {
+ ConstString m_name;
+ CompilerType m_copied_type;
+ uint32_t m_decl_lvl;
+ SymbolContext m_sym_ctx;
+};
+} // namespace
+
+SymbolContextList ClangExpressionDeclMap::SearchFunctionsInSymbolContexts(
+ const SymbolContextList &sc_list,
+ const CompilerDeclContext &frame_decl_context) {
+ // First, symplify things by looping through the symbol contexts to
+ // remove unwanted functions and separate out the functions we want to
+ // compare and prune into a separate list. Cache the info needed about
+ // the function declarations in a vector for efficiency.
+ uint32_t num_indices = sc_list.GetSize();
+ SymbolContextList sc_sym_list;
+ std::vector<FuncDeclInfo> decl_infos;
+ decl_infos.reserve(num_indices);
+ clang::DeclContext *frame_decl_ctx =
+ (clang::DeclContext *)frame_decl_context.GetOpaqueDeclContext();
+ ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(
+ frame_decl_context.GetTypeSystem());
- if (reg_info) {
- LLDB_LOGF(log, " CEDM::FEVD[%u] Found register %s", current_id,
- reg_info->name);
+ for (uint32_t index = 0; index < num_indices; ++index) {
+ FuncDeclInfo fdi;
+ SymbolContext sym_ctx;
+ sc_list.GetContextAtIndex(index, sym_ctx);
- AddOneRegister(context, reg_info, current_id);
- }
+ // We don't know enough about symbols to compare them, but we should
+ // keep them in the list.
+ Function *function = sym_ctx.function;
+ if (!function) {
+ sc_sym_list.Append(sym_ctx);
+ continue;
+ }
+ // Filter out functions without declaration contexts, as well as
+ // class/instance methods, since they'll be skipped in the code that
+ // follows anyway.
+ CompilerDeclContext func_decl_context = function->GetDeclContext();
+ if (!func_decl_context ||
+ func_decl_context.IsClassMethod(nullptr, nullptr, nullptr))
+ continue;
+ // We can only prune functions for which we can copy the type.
+ CompilerType func_clang_type = function->GetType()->GetFullCompilerType();
+ CompilerType copied_func_type = GuardedCopyType(func_clang_type);
+ if (!copied_func_type) {
+ sc_sym_list.Append(sym_ctx);
+ continue;
}
- } else {
- ValueObjectSP valobj;
- VariableSP var;
-
- bool local_var_lookup =
- !namespace_decl || (namespace_decl.GetName() ==
- ConstString(g_lldb_local_vars_namespace_cstr));
- if (frame && local_var_lookup) {
- CompilerDeclContext compiler_decl_context =
- sym_ctx.block != nullptr ? sym_ctx.block->GetDeclContext()
- : CompilerDeclContext();
-
- if (compiler_decl_context) {
- // Make sure that the variables are parsed so that we have the
- // declarations.
- VariableListSP vars = frame->GetInScopeVariableList(true);
- for (size_t i = 0; i < vars->GetSize(); i++)
- vars->GetVariableAtIndex(i)->GetDecl();
-
- // Search for declarations matching the name. Do not include imported
- // decls in the search if we are looking for decls in the artificial
- // namespace $__lldb_local_vars.
- std::vector<CompilerDecl> found_decls =
- compiler_decl_context.FindDeclByName(name,
- namespace_decl.IsValid());
-
- bool variable_found = false;
- for (CompilerDecl decl : found_decls) {
- for (size_t vi = 0, ve = vars->GetSize(); vi != ve; ++vi) {
- VariableSP candidate_var = vars->GetVariableAtIndex(vi);
- if (candidate_var->GetDecl() == decl) {
- var = candidate_var;
- break;
- }
- }
- if (var && !variable_found) {
- variable_found = true;
- valobj = ValueObjectVariable::Create(frame, var);
- AddOneVariable(context, var, valobj, current_id);
- context.m_found.variable = true;
- }
- }
- if (variable_found)
- return;
- }
+ fdi.m_sym_ctx = sym_ctx;
+ fdi.m_name = function->GetName();
+ fdi.m_copied_type = copied_func_type;
+ fdi.m_decl_lvl = LLDB_INVALID_DECL_LEVEL;
+ if (fdi.m_copied_type && func_decl_context) {
+ // Call CountDeclLevels to get the number of parent scopes we have
+ // to look through before we find the function declaration. When
+ // comparing functions of the same type, the one with a lower count
+ // will be closer to us in the lookup scope and shadows the other.
+ clang::DeclContext *func_decl_ctx =
+ (clang::DeclContext *)func_decl_context.GetOpaqueDeclContext();
+ fdi.m_decl_lvl = ast->CountDeclLevels(frame_decl_ctx, func_decl_ctx,
+ &fdi.m_name, &fdi.m_copied_type);
}
- if (target) {
- var = FindGlobalVariable(*target, module_sp, name, &namespace_decl,
- nullptr);
+ decl_infos.emplace_back(fdi);
+ }
- if (var) {
- valobj = ValueObjectVariable::Create(target, var);
- AddOneVariable(context, var, valobj, current_id);
- context.m_found.variable = true;
- return;
- }
+ // Loop through the functions in our cache looking for matching types,
+ // then compare their scope levels to see which is closer.
+ std::multimap<CompilerType, const FuncDeclInfo *> matches;
+ for (const FuncDeclInfo &fdi : decl_infos) {
+ const CompilerType t = fdi.m_copied_type;
+ auto q = matches.find(t);
+ if (q != matches.end()) {
+ if (q->second->m_decl_lvl > fdi.m_decl_lvl)
+ // This function is closer; remove the old set.
+ matches.erase(t);
+ else if (q->second->m_decl_lvl < fdi.m_decl_lvl)
+ // The functions in our set are closer - skip this one.
+ continue;
}
+ matches.insert(std::make_pair(t, &fdi));
+ }
- std::vector<clang::NamedDecl *> decls_from_modules;
+ // Loop through our matches and add their symbol contexts to our list.
+ SymbolContextList sc_func_list;
+ for (const auto &q : matches)
+ sc_func_list.Append(q.second->m_sym_ctx);
- if (target) {
- if (ClangModulesDeclVendor *decl_vendor =
- target->GetClangModulesDeclVendor()) {
- decl_vendor->FindDecls(name, false, UINT32_MAX, decls_from_modules);
- }
- }
+ // Rejoin the lists with the functions in front.
+ sc_func_list.Append(sc_sym_list);
+ return sc_func_list;
+}
- const bool include_inlines = false;
- sc_list.Clear();
- if (namespace_decl && module_sp) {
- const bool include_symbols = false;
+void ClangExpressionDeclMap::LookupFunction(NameSearchContext &context,
+ lldb::ModuleSP module_sp,
+ ConstString name,
+ CompilerDeclContext &namespace_decl,
+ unsigned current_id) {
+ if (!m_parser_vars)
+ return;
- module_sp->FindFunctions(name, &namespace_decl, eFunctionNameTypeBase,
- include_symbols, include_inlines, sc_list);
- } else if (target && !namespace_decl) {
- const bool include_symbols = true;
+ Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
- // TODO Fix FindFunctions so that it doesn't return
- // instance methods for eFunctionNameTypeBase.
+ std::vector<clang::NamedDecl *> decls_from_modules;
- target->GetImages().FindFunctions(name, eFunctionNameTypeFull,
- include_symbols, include_inlines,
- sc_list);
+ if (target) {
+ if (ClangModulesDeclVendor *decl_vendor =
+ target->GetClangModulesDeclVendor()) {
+ decl_vendor->FindDecls(name, false, UINT32_MAX, decls_from_modules);
}
+ }
- // If we found more than one function, see if we can use the frame's decl
- // context to remove functions that are shadowed by other functions which
- // match in type but are nearer in scope.
- //
- // AddOneFunction will not add a function whose type has already been
- // added, so if there's another function in the list with a matching type,
- // check to see if their decl context is a parent of the current frame's or
- // was imported via a and using statement, and pick the best match
- // according to lookup rules.
- if (sc_list.GetSize() > 1) {
- // Collect some info about our frame's context.
- StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
- SymbolContext frame_sym_ctx;
- if (frame != nullptr)
- frame_sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
- lldb::eSymbolContextBlock);
- CompilerDeclContext frame_decl_context =
- frame_sym_ctx.block != nullptr ? frame_sym_ctx.block->GetDeclContext()
- : CompilerDeclContext();
-
- // We can't do this without a compiler decl context for our frame.
- if (frame_decl_context) {
- clang::DeclContext *frame_decl_ctx =
- (clang::DeclContext *)frame_decl_context.GetOpaqueDeclContext();
- ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(
- frame_decl_context.GetTypeSystem());
-
- // Structure to hold the info needed when comparing function
- // declarations.
- struct FuncDeclInfo {
- ConstString m_name;
- CompilerType m_copied_type;
- uint32_t m_decl_lvl;
- SymbolContext m_sym_ctx;
- };
-
- // First, symplify things by looping through the symbol contexts to
- // remove unwanted functions and separate out the functions we want to
- // compare and prune into a separate list. Cache the info needed about
- // the function declarations in a vector for efficiency.
- SymbolContextList sc_sym_list;
- uint32_t num_indices = sc_list.GetSize();
- std::vector<FuncDeclInfo> fdi_cache;
- fdi_cache.reserve(num_indices);
- for (uint32_t index = 0; index < num_indices; ++index) {
- FuncDeclInfo fdi;
- SymbolContext sym_ctx;
- sc_list.GetContextAtIndex(index, sym_ctx);
-
- // We don't know enough about symbols to compare them, but we should
- // keep them in the list.
- Function *function = sym_ctx.function;
- if (!function) {
- sc_sym_list.Append(sym_ctx);
- continue;
- }
- // Filter out functions without declaration contexts, as well as
- // class/instance methods, since they'll be skipped in the code that
- // follows anyway.
- CompilerDeclContext func_decl_context = function->GetDeclContext();
- if (!func_decl_context ||
- func_decl_context.IsClassMethod(nullptr, nullptr, nullptr))
- continue;
- // We can only prune functions for which we can copy the type.
- CompilerType func_clang_type =
- function->GetType()->GetFullCompilerType();
- CompilerType copied_func_type = GuardedCopyType(func_clang_type);
- if (!copied_func_type) {
- sc_sym_list.Append(sym_ctx);
- continue;
- }
+ const bool include_inlines = false;
+ SymbolContextList sc_list;
+ if (namespace_decl && module_sp) {
+ const bool include_symbols = false;
- fdi.m_sym_ctx = sym_ctx;
- fdi.m_name = function->GetName();
- fdi.m_copied_type = copied_func_type;
- fdi.m_decl_lvl = LLDB_INVALID_DECL_LEVEL;
- if (fdi.m_copied_type && func_decl_context) {
- // Call CountDeclLevels to get the number of parent scopes we have
- // to look through before we find the function declaration. When
- // comparing functions of the same type, the one with a lower count
- // will be closer to us in the lookup scope and shadows the other.
- clang::DeclContext *func_decl_ctx =
- (clang::DeclContext *)func_decl_context.GetOpaqueDeclContext();
- fdi.m_decl_lvl = ast->CountDeclLevels(
- frame_decl_ctx, func_decl_ctx, &fdi.m_name, &fdi.m_copied_type);
- }
- fdi_cache.emplace_back(fdi);
- }
+ module_sp->FindFunctions(name, &namespace_decl, eFunctionNameTypeBase,
+ include_symbols, include_inlines, sc_list);
+ } else if (target && !namespace_decl) {
+ const bool include_symbols = true;
- // Loop through the functions in our cache looking for matching types,
- // then compare their scope levels to see which is closer.
- std::multimap<CompilerType, const FuncDeclInfo *> matches;
- for (const FuncDeclInfo &fdi : fdi_cache) {
- const CompilerType t = fdi.m_copied_type;
- auto q = matches.find(t);
- if (q != matches.end()) {
- if (q->second->m_decl_lvl > fdi.m_decl_lvl)
- // This function is closer; remove the old set.
- matches.erase(t);
- else if (q->second->m_decl_lvl < fdi.m_decl_lvl)
- // The functions in our set are closer - skip this one.
- continue;
- }
- matches.insert(std::make_pair(t, &fdi));
- }
+ // TODO Fix FindFunctions so that it doesn't return
+ // instance methods for eFunctionNameTypeBase.
- // Loop through our matches and add their symbol contexts to our list.
- SymbolContextList sc_func_list;
- for (const auto &q : matches)
- sc_func_list.Append(q.second->m_sym_ctx);
+ target->GetImages().FindFunctions(
+ name, eFunctionNameTypeFull | eFunctionNameTypeBase, include_symbols,
+ include_inlines, sc_list);
+ }
- // Rejoin the lists with the functions in front.
- sc_list = sc_func_list;
- sc_list.Append(sc_sym_list);
- }
+ // If we found more than one function, see if we can use the frame's decl
+ // context to remove functions that are shadowed by other functions which
+ // match in type but are nearer in scope.
+ //
+ // AddOneFunction will not add a function whose type has already been
+ // added, so if there's another function in the list with a matching type,
+ // check to see if their decl context is a parent of the current frame's or
+ // was imported via a and using statement, and pick the best match
+ // according to lookup rules.
+ if (sc_list.GetSize() > 1) {
+ // Collect some info about our frame's context.
+ StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
+ SymbolContext frame_sym_ctx;
+ if (frame != nullptr)
+ frame_sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
+ lldb::eSymbolContextBlock);
+ CompilerDeclContext frame_decl_context =
+ frame_sym_ctx.block != nullptr ? frame_sym_ctx.block->GetDeclContext()
+ : CompilerDeclContext();
+
+ // We can't do this without a compiler decl context for our frame.
+ if (frame_decl_context) {
+ sc_list = SearchFunctionsInSymbolContexts(sc_list, frame_decl_context);
}
+ }
- if (sc_list.GetSize()) {
- Symbol *extern_symbol = nullptr;
- Symbol *non_extern_symbol = nullptr;
-
- for (uint32_t index = 0, num_indices = sc_list.GetSize();
- index < num_indices; ++index) {
- SymbolContext sym_ctx;
- sc_list.GetContextAtIndex(index, sym_ctx);
+ if (sc_list.GetSize()) {
+ Symbol *extern_symbol = nullptr;
+ Symbol *non_extern_symbol = nullptr;
- if (sym_ctx.function) {
- CompilerDeclContext decl_ctx = sym_ctx.function->GetDeclContext();
+ for (uint32_t index = 0, num_indices = sc_list.GetSize();
+ index < num_indices; ++index) {
+ SymbolContext sym_ctx;
+ sc_list.GetContextAtIndex(index, sym_ctx);
- if (!decl_ctx)
- continue;
+ if (sym_ctx.function) {
+ CompilerDeclContext decl_ctx = sym_ctx.function->GetDeclContext();
- // Filter out class/instance methods.
- if (decl_ctx.IsClassMethod(nullptr, nullptr, nullptr))
- continue;
+ if (!decl_ctx)
+ continue;
- AddOneFunction(context, sym_ctx.function, nullptr, current_id);
- context.m_found.function_with_type_info = true;
- context.m_found.function = true;
- } else if (sym_ctx.symbol) {
- if (sym_ctx.symbol->GetType() == eSymbolTypeReExported && target) {
- sym_ctx.symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target);
- if (sym_ctx.symbol == nullptr)
- continue;
- }
+ // Filter out class/instance methods.
+ if (decl_ctx.IsClassMethod(nullptr, nullptr, nullptr))
+ continue;
- if (sym_ctx.symbol->IsExternal())
- extern_symbol = sym_ctx.symbol;
- else
- non_extern_symbol = sym_ctx.symbol;
+ AddOneFunction(context, sym_ctx.function, nullptr, current_id);
+ context.m_found.function_with_type_info = true;
+ context.m_found.function = true;
+ } else if (sym_ctx.symbol) {
+ if (sym_ctx.symbol->GetType() == eSymbolTypeReExported && target) {
+ sym_ctx.symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target);
+ if (sym_ctx.symbol == nullptr)
+ continue;
}
+
+ if (sym_ctx.symbol->IsExternal())
+ extern_symbol = sym_ctx.symbol;
+ else
+ non_extern_symbol = sym_ctx.symbol;
}
+ }
- if (!context.m_found.function_with_type_info) {
- for (clang::NamedDecl *decl : decls_from_modules) {
- if (llvm::isa<clang::FunctionDecl>(decl)) {
- clang::NamedDecl *copied_decl =
- llvm::cast_or_null<FunctionDecl>(CopyDecl(decl));
- if (copied_decl) {
- context.AddNamedDecl(copied_decl);
- context.m_found.function_with_type_info = true;
- }
+ if (!context.m_found.function_with_type_info) {
+ for (clang::NamedDecl *decl : decls_from_modules) {
+ if (llvm::isa<clang::FunctionDecl>(decl)) {
+ clang::NamedDecl *copied_decl =
+ llvm::cast_or_null<FunctionDecl>(CopyDecl(decl));
+ if (copied_decl) {
+ context.AddNamedDecl(copied_decl);
+ context.m_found.function_with_type_info = true;
}
}
}
+ }
- if (!context.m_found.function_with_type_info) {
- if (extern_symbol) {
- AddOneFunction(context, nullptr, extern_symbol, current_id);
- context.m_found.function = true;
- } else if (non_extern_symbol) {
- AddOneFunction(context, nullptr, non_extern_symbol, current_id);
- context.m_found.function = true;
- }
+ if (!context.m_found.function_with_type_info) {
+ if (extern_symbol) {
+ AddOneFunction(context, nullptr, extern_symbol, current_id);
+ context.m_found.function = true;
+ } else if (non_extern_symbol) {
+ AddOneFunction(context, nullptr, non_extern_symbol, current_id);
+ context.m_found.function = true;
}
}
+ }
+}
- if (!context.m_found.function_with_type_info) {
- // Try the modules next.
+void ClangExpressionDeclMap::FindExternalVisibleDecls(
+ NameSearchContext &context, lldb::ModuleSP module_sp,
+ CompilerDeclContext &namespace_decl, unsigned int current_id) {
+ assert(m_ast_context);
- do {
- if (ClangModulesDeclVendor *modules_decl_vendor =
- m_target->GetClangModulesDeclVendor()) {
- bool append = false;
- uint32_t max_matches = 1;
- std::vector<clang::NamedDecl *> decls;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- if (!modules_decl_vendor->FindDecls(name, append, max_matches, decls))
- break;
+ const ConstString name(context.m_decl_name.getAsString().c_str());
+ if (IgnoreName(name, false))
+ return;
- clang::NamedDecl *const decl_from_modules = decls[0];
+ // Only look for functions by name out in our symbols if the function doesn't
+ // start with our phony prefix of '$'
- if (llvm::isa<clang::FunctionDecl>(decl_from_modules)) {
- if (log) {
- LLDB_LOGF(log,
- " CAS::FEVD[%u] Matching function found for "
- "\"%s\" in the modules",
- current_id, name.GetCString());
- }
+ Target *target = nullptr;
+ StackFrame *frame = nullptr;
+ SymbolContext sym_ctx;
+ if (m_parser_vars) {
+ target = m_parser_vars->m_exe_ctx.GetTargetPtr();
+ frame = m_parser_vars->m_exe_ctx.GetFramePtr();
+ }
+ if (frame != nullptr)
+ sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
+ lldb::eSymbolContextBlock);
- clang::Decl *copied_decl = CopyDecl(decl_from_modules);
- clang::FunctionDecl *copied_function_decl =
- copied_decl ? dyn_cast<clang::FunctionDecl>(copied_decl)
- : nullptr;
+ // Try the persistent decls, which take precedence over all else.
+ if (!namespace_decl)
+ SearchPersistenDecls(context, name, current_id);
- if (!copied_function_decl) {
- LLDB_LOGF(log,
- " CAS::FEVD[%u] - Couldn't export a function "
- "declaration from the modules",
- current_id);
+ if (name.GetStringRef().startswith("$") && !namespace_decl) {
+ if (name == "$__lldb_class") {
+ LookUpLldbClass(context, current_id);
+ return;
+ }
- break;
- }
+ if (name == "$__lldb_objc_class") {
+ LookUpLldbObjCClass(context, current_id);
+ return;
+ }
+ if (name == g_lldb_local_vars_namespace_cstr) {
+ LookupLocalVarNamespace(sym_ctx, context);
+ return;
+ }
+
+ // any other $__lldb names should be weeded out now
+ if (name.GetStringRef().startswith("$__lldb"))
+ return;
- MaybeRegisterFunctionBody(copied_function_decl);
+ // No ParserVars means we can't do register or variable lookup.
+ if (!m_parser_vars || !m_parser_vars->m_persistent_vars)
+ return;
- context.AddNamedDecl(copied_function_decl);
+ ExpressionVariableSP pvar_sp(
+ m_parser_vars->m_persistent_vars->GetVariable(name));
- context.m_found.function_with_type_info = true;
- context.m_found.function = true;
- } else if (llvm::isa<clang::VarDecl>(decl_from_modules)) {
- if (log) {
- LLDB_LOGF(log,
- " CAS::FEVD[%u] Matching variable found for "
- "\"%s\" in the modules",
- current_id, name.GetCString());
- }
+ if (pvar_sp) {
+ AddOneVariable(context, pvar_sp, current_id);
+ return;
+ }
- clang::Decl *copied_decl = CopyDecl(decl_from_modules);
- clang::VarDecl *copied_var_decl =
- copied_decl ? dyn_cast_or_null<clang::VarDecl>(copied_decl)
- : nullptr;
+ assert(name.GetStringRef().startswith("$"));
+ llvm::StringRef reg_name = name.GetStringRef().substr(1);
- if (!copied_var_decl) {
- LLDB_LOGF(log,
- " CAS::FEVD[%u] - Couldn't export a variable "
- "declaration from the modules",
- current_id);
+ if (m_parser_vars->m_exe_ctx.GetRegisterContext()) {
+ const RegisterInfo *reg_info(
+ m_parser_vars->m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName(
+ reg_name));
- break;
- }
+ if (reg_info) {
+ LLDB_LOGF(log, " CEDM::FEVD[%u] Found register %s", current_id,
+ reg_info->name);
- context.AddNamedDecl(copied_var_decl);
+ AddOneRegister(context, reg_info, current_id);
+ }
+ }
+ return;
+ }
- context.m_found.variable = true;
- }
- }
- } while (false);
+ bool local_var_lookup = !namespace_decl || (namespace_decl.GetName() ==
+ g_lldb_local_vars_namespace_cstr);
+ if (frame && local_var_lookup)
+ if (LookupLocalVariable(context, name, current_id, sym_ctx, namespace_decl))
+ return;
+
+ if (target) {
+ ValueObjectSP valobj;
+ VariableSP var;
+ var = FindGlobalVariable(*target, module_sp, name, &namespace_decl);
+
+ if (var) {
+ valobj = ValueObjectVariable::Create(target, var);
+ AddOneVariable(context, var, valobj, current_id);
+ context.m_found.variable = true;
+ return;
}
+ }
- if (target && !context.m_found.variable && !namespace_decl) {
- // We couldn't find a non-symbol variable for this. Now we'll hunt for a
- // generic data symbol, and -- if it is found -- treat it as a variable.
- Status error;
+ LookupFunction(context, module_sp, name, namespace_decl, current_id);
- const Symbol *data_symbol =
- m_parser_vars->m_sym_ctx.FindBestGlobalDataSymbol(name, error);
+ // Try the modules next.
+ if (!context.m_found.function_with_type_info)
+ LookupInModulesDeclVendor(context, name, current_id);
- if (!error.Success()) {
- const unsigned diag_id =
- m_ast_context->getDiagnostics().getCustomDiagID(
- clang::DiagnosticsEngine::Level::Error, "%0");
- m_ast_context->getDiagnostics().Report(diag_id) << error.AsCString();
- }
+ if (target && !context.m_found.variable && !namespace_decl) {
+ // We couldn't find a non-symbol variable for this. Now we'll hunt for a
+ // generic data symbol, and -- if it is found -- treat it as a variable.
+ Status error;
- if (data_symbol) {
- std::string warning("got name from symbols: ");
- warning.append(name.AsCString());
- const unsigned diag_id =
- m_ast_context->getDiagnostics().getCustomDiagID(
- clang::DiagnosticsEngine::Level::Warning, "%0");
- m_ast_context->getDiagnostics().Report(diag_id) << warning.c_str();
- AddOneGenericVariable(context, *data_symbol, current_id);
- context.m_found.variable = true;
- }
+ const Symbol *data_symbol =
+ m_parser_vars->m_sym_ctx.FindBestGlobalDataSymbol(name, error);
+
+ if (!error.Success()) {
+ const unsigned diag_id =
+ m_ast_context->getDiagnostics().getCustomDiagID(
+ clang::DiagnosticsEngine::Level::Error, "%0");
+ m_ast_context->getDiagnostics().Report(diag_id) << error.AsCString();
+ }
+
+ if (data_symbol) {
+ std::string warning("got name from symbols: ");
+ warning.append(name.AsCString());
+ const unsigned diag_id =
+ m_ast_context->getDiagnostics().getCustomDiagID(
+ clang::DiagnosticsEngine::Level::Warning, "%0");
+ m_ast_context->getDiagnostics().Report(diag_id) << warning.c_str();
+ AddOneGenericVariable(context, *data_symbol, current_id);
+ context.m_found.variable = true;
}
}
}
@@ -1543,15 +1508,6 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var,
return false;
}
- ASTContext *ast = clang_ast->getASTContext();
-
- if (!ast) {
- if (log)
- log->PutCString(
- "There is no AST context for the current execution context");
- return false;
- }
-
DWARFExpression &var_location_expr = var->LocationExpression();
Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
@@ -1664,14 +1620,10 @@ void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
if (is_reference)
entity->m_flags |= ClangExpressionVariable::EVTypeIsReference;
- if (log) {
- ASTDumper orig_dumper(ut.GetOpaqueQualType());
- ASTDumper ast_dumper(var_decl);
- LLDB_LOGF(log,
- " CEDM::FEVD[%u] Found variable %s, returned %s (original %s)",
- current_id, decl_name.c_str(), ast_dumper.GetCString(),
- orig_dumper.GetCString());
- }
+ LLDB_LOG(log,
+ " CEDM::FEVD[{0}] Found variable {1}, returned\n{2} (original {3})",
+ current_id, decl_name, ClangUtil::DumpDecl(var_decl),
+ ClangUtil::ToString(ut));
}
void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
@@ -1703,11 +1655,8 @@ void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
parser_vars->m_llvm_value = nullptr;
parser_vars->m_lldb_value.Clear();
- if (log) {
- ASTDumper ast_dumper(var_decl);
- LLDB_LOGF(log, " CEDM::FEVD[%u] Added pvar %s, returned %s", current_id,
- pvar_sp->GetName().GetCString(), ast_dumper.GetCString());
- }
+ LLDB_LOG(log, " CEDM::FEVD[{0}] Added pvar {1}, returned\n{2}", current_id,
+ pvar_sp->GetName(), ClangUtil::DumpDecl(var_decl));
}
void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context,
@@ -1722,17 +1671,16 @@ void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context,
if (target == nullptr)
return;
- ASTContext *scratch_ast_context =
- target->GetScratchClangASTContext()->getASTContext();
+ ClangASTContext *scratch_ast_context = ClangASTContext::GetScratch(*target);
+ if (!scratch_ast_context)
+ return;
- TypeFromUser user_type(
- ClangASTContext::GetBasicType(scratch_ast_context, eBasicTypeVoid)
- .GetPointerType()
- .GetLValueReferenceType());
- TypeFromParser parser_type(
- ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid)
- .GetPointerType()
- .GetLValueReferenceType());
+ TypeFromUser user_type(scratch_ast_context->GetBasicType(eBasicTypeVoid)
+ .GetPointerType()
+ .GetLValueReferenceType());
+ TypeFromParser parser_type(m_clang_ast_context->GetBasicType(eBasicTypeVoid)
+ .GetPointerType()
+ .GetLValueReferenceType());
NamedDecl *var_decl = context.AddVarDecl(parser_type);
std::string decl_name(context.m_decl_name.getAsString());
@@ -1761,86 +1709,8 @@ void ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context,
parser_vars->m_llvm_value = nullptr;
parser_vars->m_lldb_sym = &symbol;
- if (log) {
- ASTDumper ast_dumper(var_decl);
-
- LLDB_LOGF(log, " CEDM::FEVD[%u] Found variable %s, returned %s",
- current_id, decl_name.c_str(), ast_dumper.GetCString());
- }
-}
-
-bool ClangExpressionDeclMap::ResolveUnknownTypes() {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
-
- ClangASTContextForExpressions *scratch_ast_context =
- static_cast<ClangASTContextForExpressions *>(
- target->GetScratchClangASTContext());
-
- for (size_t index = 0, num_entities = m_found_entities.GetSize();
- index < num_entities; ++index) {
- ExpressionVariableSP entity = m_found_entities.GetVariableAtIndex(index);
-
- ClangExpressionVariable::ParserVars *parser_vars =
- llvm::cast<ClangExpressionVariable>(entity.get())
- ->GetParserVars(GetParserID());
-
- if (entity->m_flags & ClangExpressionVariable::EVUnknownType) {
- const NamedDecl *named_decl = parser_vars->m_named_decl;
- const VarDecl *var_decl = dyn_cast<VarDecl>(named_decl);
-
- if (!var_decl) {
- LLDB_LOGF(log, "Entity of unknown type does not have a VarDecl");
- return false;
- }
-
- if (log) {
- ASTDumper ast_dumper(const_cast<VarDecl *>(var_decl));
- LLDB_LOGF(log, "Variable of unknown type now has Decl %s",
- ast_dumper.GetCString());
- }
-
- QualType var_type = var_decl->getType();
- TypeFromParser parser_type(
- var_type.getAsOpaquePtr(),
- ClangASTContext::GetASTContext(&var_decl->getASTContext()));
-
- lldb::opaque_compiler_type_t copied_type = nullptr;
- if (m_ast_importer_sp) {
- copied_type = m_ast_importer_sp->CopyType(
- scratch_ast_context->getASTContext(), &var_decl->getASTContext(),
- var_type.getAsOpaquePtr());
- } else if (HasMerger()) {
- copied_type = CopyTypeWithMerger(
- var_decl->getASTContext(),
- scratch_ast_context->GetMergerUnchecked(), var_type)
- .getAsOpaquePtr();
- } else {
- lldbassert(0 && "No mechanism to copy a resolved unknown type!");
- return false;
- }
-
- if (!copied_type) {
- LLDB_LOGF(log, "ClangExpressionDeclMap::ResolveUnknownType - Couldn't "
- "import the type for a variable");
-
- return (bool)lldb::ExpressionVariableSP();
- }
-
- TypeFromUser user_type(copied_type, scratch_ast_context);
-
- // parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType,
- // user_type.GetOpaqueQualType());
- parser_vars->m_lldb_value.SetCompilerType(user_type);
- parser_vars->m_parser_type = parser_type;
-
- entity->SetCompilerType(user_type);
-
- entity->m_flags &= ~(ClangExpressionVariable::EVUnknownType);
- }
- }
-
- return true;
+ LLDB_LOG(log, " CEDM::FEVD[{0}] Found variable {1}, returned\n{2}",
+ current_id, decl_name, ClangUtil::DumpDecl(var_decl));
}
void ClangExpressionDeclMap::AddOneRegister(NameSearchContext &context,
@@ -1849,8 +1719,8 @@ void ClangExpressionDeclMap::AddOneRegister(NameSearchContext &context,
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
CompilerType clang_type =
- ClangASTContext::GetBuiltinTypeForEncodingAndBitSize(
- m_ast_context, reg_info->encoding, reg_info->byte_size * 8);
+ m_clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(
+ reg_info->encoding, reg_info->byte_size * 8);
if (!clang_type) {
LLDB_LOGF(log, " Tried to add a type for %s, but couldn't get one",
@@ -1880,12 +1750,9 @@ void ClangExpressionDeclMap::AddOneRegister(NameSearchContext &context,
parser_vars->m_lldb_value.Clear();
entity->m_flags |= ClangExpressionVariable::EVBareRegister;
- if (log) {
- ASTDumper ast_dumper(var_decl);
- LLDB_LOGF(log, " CEDM::FEVD[%d] Added register %s, returned %s",
- current_id, context.m_decl_name.getAsString().c_str(),
- ast_dumper.GetCString());
- }
+ LLDB_LOG(log, " CEDM::FEVD[{0}] Added register {1}, returned\n{2}",
+ current_id, context.m_decl_name.getAsString(),
+ ClangUtil::DumpDecl(var_decl));
}
void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
@@ -1928,17 +1795,16 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
CopyDecl(function_template));
if (copied_function_template) {
if (log) {
- ASTDumper ast_dumper((clang::Decl *)copied_function_template);
-
StreamString ss;
function->DumpSymbolContext(&ss);
- log->Printf(" CEDM::FEVD[%u] Imported decl for function template"
- " %s (description %s), returned %s",
- current_id,
- copied_function_template->getNameAsString().c_str(),
- ss.GetData(), ast_dumper.GetCString());
+ LLDB_LOG(log,
+ " CEDM::FEVD[{0}] Imported decl for function template"
+ " {1} (description {2}), returned\n{3}",
+ current_id, copied_function_template->getNameAsString(),
+ ss.GetData(),
+ ClangUtil::DumpDecl(copied_function_template));
}
context.AddNamedDecl(copied_function_template);
@@ -1948,18 +1814,15 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
llvm::dyn_cast_or_null<clang::FunctionDecl>(
CopyDecl(src_function_decl))) {
if (log) {
- ASTDumper ast_dumper((clang::Decl *)copied_function_decl);
-
StreamString ss;
function->DumpSymbolContext(&ss);
- LLDB_LOGF(log,
- " CEDM::FEVD[%u] Imported decl for function %s "
- "(description %s), returned %s",
- current_id,
- copied_function_decl->getNameAsString().c_str(),
- ss.GetData(), ast_dumper.GetCString());
+ LLDB_LOG(log,
+ " CEDM::FEVD[{0}]] Imported decl for function {1} "
+ "(description {2}), returned\n{3}",
+ current_id, copied_function_decl->getNameAsString(),
+ ss.GetData(), ClangUtil::DumpDecl(copied_function_decl));
}
context.AddNamedDecl(copied_function_decl);
@@ -2061,20 +1924,17 @@ void ClangExpressionDeclMap::AddOneFunction(NameSearchContext &context,
parser_vars->m_llvm_value = nullptr;
if (log) {
- std::string function_str =
- function_decl ? ASTDumper(function_decl).GetCString() : "nullptr";
-
StreamString ss;
fun_address.Dump(&ss,
m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(),
Address::DumpStyleResolvedDescription);
- LLDB_LOGF(
- log,
- " CEDM::FEVD[%u] Found %s function %s (description %s), returned %s",
- current_id, (function ? "specific" : "generic"), decl_name.c_str(),
- ss.GetData(), function_str.c_str());
+ LLDB_LOG(log,
+ " CEDM::FEVD[{0}] Found {1} function {2} (description {3}), "
+ "returned\n{4}",
+ current_id, (function ? "specific" : "generic"), decl_name,
+ ss.GetData(), ClangUtil::DumpDecl(function_decl));
}
}
@@ -2097,11 +1957,11 @@ void ClangExpressionDeclMap::AddThisType(NameSearchContext &context,
if (copied_clang_type.IsAggregateType() &&
copied_clang_type.GetCompleteType()) {
CompilerType void_clang_type =
- ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid);
+ m_clang_ast_context->GetBasicType(eBasicTypeVoid);
CompilerType void_ptr_clang_type = void_clang_type.GetPointerType();
- CompilerType method_type = ClangASTContext::CreateFunctionType(
- m_ast_context, void_clang_type, &void_ptr_clang_type, 1, false, 0);
+ CompilerType method_type = m_clang_ast_context->CreateFunctionType(
+ void_clang_type, &void_ptr_clang_type, 1, false, 0);
const bool is_virtual = false;
const bool is_static = false;
@@ -2110,22 +1970,16 @@ void ClangExpressionDeclMap::AddThisType(NameSearchContext &context,
const bool is_attr_used = true;
const bool is_artificial = false;
- CXXMethodDecl *method_decl =
- ClangASTContext::GetASTContext(m_ast_context)
- ->AddMethodToCXXRecordType(
- copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", nullptr,
- method_type, lldb::eAccessPublic, is_virtual, is_static,
- is_inline, is_explicit, is_attr_used, is_artificial);
-
- if (log) {
- ASTDumper method_ast_dumper((clang::Decl *)method_decl);
- ASTDumper type_ast_dumper(copied_clang_type);
+ CXXMethodDecl *method_decl = m_clang_ast_context->AddMethodToCXXRecordType(
+ copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", nullptr,
+ method_type, lldb::eAccessPublic, is_virtual, is_static, is_inline,
+ is_explicit, is_attr_used, is_artificial);
- LLDB_LOGF(log,
- " CEDM::AddThisType Added function $__lldb_expr "
- "(description %s) for this type %s",
- method_ast_dumper.GetCString(), type_ast_dumper.GetCString());
- }
+ LLDB_LOG(log,
+ " CEDM::AddThisType Added function $__lldb_expr "
+ "(description {0}) for this type\n{1}",
+ ClangUtil::ToString(copied_clang_type),
+ ClangUtil::DumpDecl(method_decl));
}
if (!copied_clang_type.IsValid())
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
index 2711e90726e7..722f5e15a2aa 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
@@ -63,12 +63,15 @@ public:
/// the result persistent variable, and instead marks the variable
/// as persisting.
///
- /// \param[in] delegate
+ /// \param[in] result_delegate
/// If non-NULL, use this delegate to report result values. This
/// allows the client ClangUserExpression to report a result.
///
- /// \param[in] exe_ctx
- /// The execution context to use when parsing.
+ /// \param[in] target
+ /// The target to use when parsing.
+ ///
+ /// \param[in] importer
+ /// The ClangASTImporter to use when parsing.
///
/// \param[in] ctx_obj
/// If not empty, then expression is evaluated in context of this object.
@@ -76,7 +79,7 @@ public:
ClangExpressionDeclMap(
bool keep_result_in_memory,
Materializer::PersistentVariableDelegate *result_delegate,
- ExecutionContext &exe_ctx,
+ const lldb::TargetSP &target, const lldb::ClangASTImporterSP &importer,
ValueObject *ctx_obj);
/// Destructor
@@ -98,13 +101,6 @@ public:
void InstallCodeGenerator(clang::ASTConsumer *code_gen);
- /// [Used by ClangExpressionParser] For each variable that had an unknown
- /// type at the beginning of parsing, determine its final type now.
- ///
- /// \return
- /// True on success; false otherwise.
- bool ResolveUnknownTypes();
-
/// Disable the state needed for parsing and IR transformation.
void DidParse();
@@ -248,17 +244,6 @@ public:
lldb::addr_t GetSymbolAddress(ConstString name,
lldb::SymbolType symbol_type);
- /// [Used by IRInterpreter] Get basic target information.
- ///
- /// \param[out] byte_order
- /// The byte order of the target.
- ///
- /// \param[out] address_byte_size
- /// The size of a pointer in bytes.
- ///
- /// \return
- /// True if the information could be determined; false
- /// otherwise.
struct TargetInfo {
lldb::ByteOrder byte_order;
size_t address_byte_size;
@@ -276,9 +261,6 @@ public:
///
/// \param[in] context
/// The NameSearchContext that can construct Decls for this name.
- ///
- /// \return
- /// True on success; false otherwise.
void FindExternalVisibleDecls(NameSearchContext &context) override;
/// Find all entities matching a given name in a given module/namespace,
@@ -296,14 +278,19 @@ public:
/// \param[in] current_id
/// The ID for the current FindExternalVisibleDecls invocation,
/// for logging purposes.
- ///
- /// \return
- /// True on success; false otherwise.
void FindExternalVisibleDecls(NameSearchContext &context,
lldb::ModuleSP module,
CompilerDeclContext &namespace_decl,
unsigned int current_id);
+protected:
+ /// Retrieves the declaration with the given name from the storage of
+ /// persistent declarations.
+ ///
+ /// \return
+ /// A persistent decl with the given name or a nullptr.
+ virtual clang::NamedDecl *GetPersistentDecl(ConstString name);
+
private:
ExpressionVariableList
m_found_entities; ///< All entities that were looked up for the parser.
@@ -329,7 +316,7 @@ private:
if (m_exe_ctx.GetTargetPtr())
return m_exe_ctx.GetTargetPtr();
else if (m_sym_ctx.target_sp)
- m_sym_ctx.target_sp.get();
+ return m_sym_ctx.target_sp.get();
return nullptr;
}
@@ -396,6 +383,130 @@ private:
/// from persistent variables.
uint64_t GetParserID() { return (uint64_t) this; }
+ /// Should be called on all copied functions.
+ void MaybeRegisterFunctionBody(clang::FunctionDecl *copied_function_decl);
+
+ /// Searches the persistent decls of the target for entities with the
+ /// given name.
+ ///
+ /// \param[in] context
+ /// The NameSearchContext that can construct Decls for this name.
+ ///
+ /// \param[in] name
+ /// The name of the entities that need to be found.
+ ///
+ /// \param[in] current_id
+ /// The ID for the current FindExternalVisibleDecls invocation,
+ /// for logging purposes.
+ void SearchPersistenDecls(NameSearchContext &context, const ConstString name,
+ unsigned int current_id);
+
+ /// Handles looking up $__lldb_class which requires special treatment.
+ ///
+ /// \param[in] context
+ /// The NameSearchContext that can construct Decls for this name.
+ ///
+ /// \param[in] current_id
+ /// The ID for the current FindExternalVisibleDecls invocation,
+ /// for logging purposes.
+ void LookUpLldbClass(NameSearchContext &context, unsigned int current_id);
+
+ /// Handles looking up $__lldb_objc_class which requires special treatment.
+ ///
+ /// \param[in] context
+ /// The NameSearchContext that can construct Decls for this name.
+ ///
+ /// \param[in] current_id
+ /// The ID for the current FindExternalVisibleDecls invocation,
+ /// for logging purposes.
+ void LookUpLldbObjCClass(NameSearchContext &context, unsigned int current_id);
+
+ /// Handles looking up the synthetic namespace that contains our local
+ /// variables for the current frame.
+ ///
+ /// \param[in] sym_ctx
+ /// The current SymbolContext of this frame.
+ ///
+ /// \param[in] name_context
+ /// The NameSearchContext that can construct Decls for this name.
+ void LookupLocalVarNamespace(SymbolContext &sym_ctx,
+ NameSearchContext &name_context);
+
+ /// Lookup entities in the ClangModulesDeclVendor.
+ /// \param[in] context
+ /// The NameSearchContext that can construct Decls for this name.
+ ///
+ /// \param[in] name
+ /// The name of the entities that need to be found.
+ ///
+ /// \param[in] current_id
+ /// The ID for the current FindExternalVisibleDecls invocation,
+ /// for logging purposes.
+ void LookupInModulesDeclVendor(NameSearchContext &context, ConstString name,
+ unsigned current_id);
+
+ /// Looks up a local variable.
+ ///
+ /// \param[in] context
+ /// The NameSearchContext that can construct Decls for this name.
+ ///
+ /// \param[in] name
+ /// The name of the entities that need to be found.
+ ///
+ /// \param[in] current_id
+ /// The ID for the current FindExternalVisibleDecls invocation,
+ /// for logging purposes.
+ ///
+ /// \param[in] sym_ctx
+ /// The current SymbolContext of this frame.
+ ///
+ /// \param[in] namespace_decl
+ /// The parent namespace if there is one.
+ ///
+ /// \return
+ /// True iff a local variable was found.
+ bool LookupLocalVariable(NameSearchContext &context, ConstString name,
+ unsigned current_id, SymbolContext &sym_ctx,
+ CompilerDeclContext &namespace_decl);
+
+ /// Searches for functions in the given SymbolContextList.
+ ///
+ /// \param[in] sc_list
+ /// The SymbolContextList to search.
+ ///
+ /// \param[in] frame_decl_context
+ /// The current DeclContext of the current frame.
+ ///
+ /// \return
+ /// A SymbolContextList with any found functions in the front and
+ /// any unknown SymbolContexts which are not functions in the back.
+ /// The SymbolContexts for the functions are ordered by how close they are
+ /// to the DeclContext for the given frame DeclContext.
+ SymbolContextList SearchFunctionsInSymbolContexts(
+ const SymbolContextList &sc_list,
+ const CompilerDeclContext &frame_decl_context);
+
+ /// Looks up a function.
+ ///
+ /// \param[in] context
+ /// The NameSearchContext that can construct Decls for this name.
+ ///
+ /// \param[in] module_sp
+ /// If non-NULL, the module to query.
+ ///
+ /// \param[in] name
+ /// The name of the function that should be find.
+ ///
+ /// \param[in] namespace_decl
+ /// If valid and module is non-NULL, the parent namespace.
+ ///
+ /// \param[in] current_id
+ /// The ID for the current FindExternalVisibleDecls invocation,
+ /// for logging purposes.
+ void LookupFunction(NameSearchContext &context, lldb::ModuleSP module_sp,
+ ConstString name, CompilerDeclContext &namespace_decl,
+ unsigned current_id);
+
/// Given a target, find a variable that matches the given name and type.
///
/// \param[in] target
@@ -410,17 +521,11 @@ private:
/// \param[in] namespace_decl
/// If non-NULL and module is non-NULL, the parent namespace.
///
- /// \param[in] type
- /// The required type for the variable. This function may be called
- /// during parsing, in which case we don't know its type; hence the
- /// default.
- ///
/// \return
/// The LLDB Variable found, or NULL if none was found.
lldb::VariableSP FindGlobalVariable(Target &target, lldb::ModuleSP &module,
ConstString name,
- CompilerDeclContext *namespace_decl,
- TypeFromUser *type = nullptr);
+ CompilerDeclContext *namespace_decl);
/// Get the value of a variable in a given execution context and return the
/// associated Types if needed.
@@ -441,9 +546,6 @@ private:
/// AST context. This is only useful when the variable is being
/// inspected on behalf of the parser, hence the default.
///
- /// \param[in] decl
- /// The Decl to be looked up.
- ///
/// \return
/// Return true if the value was successfully filled in.
bool GetVariableValue(lldb::VariableSP &var,
@@ -471,7 +573,7 @@ private:
/// \param[in] context
/// The NameSearchContext to use when constructing the Decl.
///
- /// \param[in] pvar
+ /// \param[in] pvar_sp
/// The persistent variable that needs a Decl.
///
/// \param[in] current_id
@@ -483,12 +585,6 @@ private:
/// Use the NameSearchContext to generate a Decl for the given LLDB symbol
/// (treated as a variable), and put it in the list of found entities.
- ///
- /// \param[in] context
- /// The NameSearchContext to use when constructing the Decl.
- ///
- /// \param[in] var
- /// The LLDB Variable that needs a Decl.
void AddOneGenericVariable(NameSearchContext &context, const Symbol &symbol,
unsigned int current_id);
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index 1422911d6546..8abd14942885 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -10,6 +10,7 @@
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/PrettyPrinter.h"
+#include "clang/Basic/Builtins.h"
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
@@ -582,15 +583,16 @@ ClangExpressionParser::ClangExpressionParser(
if (ClangModulesDeclVendor *decl_vendor =
target_sp->GetClangModulesDeclVendor()) {
- ClangPersistentVariables *clang_persistent_vars =
- llvm::cast<ClangPersistentVariables>(
+ if (auto *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(
target_sp->GetPersistentExpressionStateForLanguage(
- lldb::eLanguageTypeC));
- std::unique_ptr<PPCallbacks> pp_callbacks(new LLDBPreprocessorCallbacks(
- *decl_vendor, *clang_persistent_vars, m_compiler->getSourceManager()));
- m_pp_callbacks =
- static_cast<LLDBPreprocessorCallbacks *>(pp_callbacks.get());
- m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
+ lldb::eLanguageTypeC))) {
+ std::unique_ptr<PPCallbacks> pp_callbacks(
+ new LLDBPreprocessorCallbacks(*decl_vendor, *clang_persistent_vars,
+ m_compiler->getSourceManager()));
+ m_pp_callbacks =
+ static_cast<LLDBPreprocessorCallbacks *>(pp_callbacks.get());
+ m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
+ }
}
// 8. Most of this we get from the CompilerInstance, but we also want to give
@@ -696,10 +698,7 @@ class CodeComplete : public CodeCompleteConsumer {
public:
/// Constructs a CodeComplete consumer that can be attached to a Sema.
- /// \param[out] matches
- /// The list of matches that the lldb completion API expects as a result.
- /// This may already contain matches, so it's only allowed to append
- /// to this variable.
+ ///
/// \param[out] expr
/// The whole expression string that we are currently parsing. This
/// string needs to be equal to the input the user typed, and NOT the
@@ -976,7 +975,7 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager,
m_compiler->setASTConsumer(std::move(Consumer));
if (ast_context.getLangOpts().Modules) {
- m_compiler->createModuleManager();
+ m_compiler->createASTReader();
m_ast_context->setSema(&m_compiler->getSema());
}
@@ -999,7 +998,7 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager,
} else {
ast_context.setExternalSource(ast_source);
}
- decl_map->InstallASTContext(ast_context, m_compiler->getFileManager());
+ decl_map->InstallASTContext(*m_ast_context);
}
// Check that the ASTReader is properly attached to ASTContext and Sema.
@@ -1036,15 +1035,6 @@ ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager,
}
if (!num_errors) {
- if (type_system_helper->DeclMap() &&
- !type_system_helper->DeclMap()->ResolveUnknownTypes()) {
- diagnostic_manager.Printf(eDiagnosticSeverityError,
- "Couldn't infer the type of a variable");
- num_errors++;
- }
- }
-
- if (!num_errors) {
type_system_helper->CommitPersistentDecls();
}
@@ -1268,8 +1258,9 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution(
interpret_error, interpret_function_calls);
if (!can_interpret && execution_policy == eExecutionPolicyNever) {
- err.SetErrorStringWithFormat("Can't run the expression locally: %s",
- interpret_error.AsCString());
+ err.SetErrorStringWithFormat(
+ "Can't evaluate the expression without a running target due to: %s",
+ interpret_error.AsCString());
return err;
}
}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
index 79ad5728bf74..4a410cecb94a 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
@@ -42,7 +42,7 @@ public:
///
/// Initializes class variables.
///
- /// \param[in] exe_scope,
+ /// \param[in] exe_scope
/// If non-NULL, an execution context scope that can help to
/// correctly create an expression with a valid process for
/// optional tuning Objective-C runtime support. Can be NULL.
@@ -77,7 +77,7 @@ public:
/// \return
/// The number of errors encountered during parsing. 0 means
/// success.
- unsigned Parse(DiagnosticManager &diagnostic_manager) override;
+ unsigned Parse(DiagnosticManager &diagnostic_manager);
bool RewriteExpression(DiagnosticManager &diagnostic_manager) override;
@@ -99,15 +99,6 @@ public:
/// \param[in] exe_ctx
/// The execution context to write the function into.
///
- /// \param[out] evaluated_statically
- /// Set to true if the expression could be interpreted statically;
- /// untouched otherwise.
- ///
- /// \param[out] const_result
- /// If the result of the expression is constant, and the
- /// expression has no side effects, this is set to the result of the
- /// expression.
- ///
/// \param[in] execution_policy
/// Determines whether the expression must be JIT-compiled, must be
/// evaluated statically, or whether this decision may be made
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
index 21cb33402e7f..7ebb5fee1ec6 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp
@@ -315,12 +315,10 @@ bool ClangExpressionSourceCode::GetText(
}
}
- if (ClangModulesDeclVendor *decl_vendor =
- target->GetClangModulesDeclVendor()) {
- ClangPersistentVariables *persistent_vars =
- llvm::cast<ClangPersistentVariables>(
- target->GetPersistentExpressionStateForLanguage(
- lldb::eLanguageTypeC));
+ ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor();
+ auto *persistent_vars = llvm::cast<ClangPersistentVariables>(
+ target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
+ if (decl_vendor && persistent_vars) {
const ClangModulesDeclVendor::ModuleVector &hand_imported_modules =
persistent_vars->GetHandLoadedClangModules();
ClangModulesDeclVendor::ModuleVector modules_for_macros;
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
index eb7f74f20a20..0e6de28ee4df 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
@@ -74,9 +74,6 @@ public:
/// Finds a variable by NamedDecl in the list.
///
- /// \param[in] name
- /// The name of the requested variable.
- ///
/// \return
/// The variable requested, or NULL if that variable is not in the list.
static ClangExpressionVariable *
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
index 8fbfa6e47578..7f7c0a97f538 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
@@ -42,6 +42,8 @@
using namespace lldb_private;
+char ClangFunctionCaller::ID;
+
// ClangFunctionCaller constructor
ClangFunctionCaller::ClangFunctionCaller(ExecutionContextScope &exe_scope,
const CompilerType &return_type,
@@ -186,10 +188,10 @@ ClangFunctionCaller::CompileFunction(lldb::ThreadSP thread_to_use_sp,
lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
if (jit_process_sp) {
const bool generate_debug_info = true;
- m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this,
- generate_debug_info));
-
- num_errors = m_parser->Parse(diagnostic_manager);
+ auto *clang_parser = new ClangExpressionParser(jit_process_sp.get(), *this,
+ generate_debug_info);
+ num_errors = clang_parser->Parse(diagnostic_manager);
+ m_parser.reset(clang_parser);
} else {
diagnostic_manager.PutString(eDiagnosticSeverityError,
"no process - unable to inject function");
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h
index 24f6f2eb91b3..150a913152d0 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h
@@ -59,11 +59,6 @@ class ClangExpressionParser;
class ClangFunctionCaller : public FunctionCaller {
friend class ASTStructExtractor;
- /// LLVM-style RTTI support.
- static bool classof(const Expression *E) {
- return E->getKind() == eKindClangFunctionCaller;
- }
-
class ClangFunctionCallerHelper : public ClangExpressionHelper {
public:
ClangFunctionCallerHelper(ClangFunctionCaller &owner) : m_owner(owner) {}
@@ -91,18 +86,23 @@ class ClangFunctionCaller : public FunctionCaller {
///layout.
};
+ // LLVM RTTI support
+ static char ID;
+
public:
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || FunctionCaller::isA(ClassID);
+ }
+ static bool classof(const Expression *obj) { return obj->isA(&ID); }
+
/// Constructor
///
/// \param[in] exe_scope
/// An execution context scope that gets us at least a target and
/// process.
///
- /// \param[in] ast_context
- /// The AST context to evaluate argument types in.
- ///
- /// \param[in] return_qualtype
- /// An opaque Clang QualType for the function result. Should be
+ /// \param[in] return_type
+ /// A compiler type for the function result. Should be
/// defined in ast_context.
///
/// \param[in] function_address
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
index f3df589d7311..0696c669f2e2 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
@@ -80,12 +80,10 @@ public:
Stream &error_stream) override;
uint32_t FindDecls(ConstString name, bool append, uint32_t max_matches,
- std::vector<clang::NamedDecl *> &decls) override;
+ std::vector<CompilerDecl> &decls) override;
void ForEachMacro(const ModuleVector &modules,
std::function<bool(const std::string &)> handler) override;
-
- clang::ExternalASTMerger::ImporterSource GetImporterSource() override;
private:
void
ReportModuleExportsHelper(std::set<ClangModulesDeclVendor::ModuleID> &exports,
@@ -110,7 +108,6 @@ private:
typedef std::set<ModuleID> ImportedModuleSet;
ImportedModuleMap m_imported_modules;
ImportedModuleSet m_user_imported_modules;
- const clang::ExternalASTMerger::OriginMap m_origin_map;
// We assume that every ASTContext has an ClangASTContext, so we also store
// a custom ClangASTContext for our internal ASTContext.
std::unique_ptr<ClangASTContext> m_ast_context;
@@ -160,7 +157,7 @@ ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(
: m_diagnostics_engine(std::move(diagnostics_engine)),
m_compiler_invocation(std::move(compiler_invocation)),
m_compiler_instance(std::move(compiler_instance)),
- m_parser(std::move(parser)), m_origin_map() {
+ m_parser(std::move(parser)) {
// Initialize our ClangASTContext.
m_ast_context.reset(new ClangASTContext(m_compiler_instance->getASTContext()));
@@ -359,7 +356,7 @@ bool ClangModulesDeclVendorImpl::AddModulesForCompileUnit(
uint32_t
ClangModulesDeclVendorImpl::FindDecls(ConstString name, bool append,
uint32_t max_matches,
- std::vector<clang::NamedDecl *> &decls) {
+ std::vector<CompilerDecl> &decls) {
if (!m_enabled) {
return 0;
}
@@ -385,7 +382,7 @@ ClangModulesDeclVendorImpl::FindDecls(ConstString name, bool append,
if (num_matches >= max_matches)
return num_matches;
- decls.push_back(named_decl);
+ decls.push_back(CompilerDecl(m_ast_context.get(), named_decl));
++num_matches;
}
@@ -569,13 +566,6 @@ ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path,
is_inclusion_directive);
}
-clang::ExternalASTMerger::ImporterSource
-ClangModulesDeclVendorImpl::GetImporterSource() {
- return clang::ExternalASTMerger::ImporterSource(
- m_compiler_instance->getASTContext(),
- m_compiler_instance->getFileManager(), m_origin_map);
-}
-
static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer";
lldb_private::ClangModulesDeclVendor *
@@ -704,7 +694,7 @@ ClangModulesDeclVendor::Create(Target &target) {
instance->getPreprocessor().enableIncrementalProcessing();
- instance->createModuleManager();
+ instance->createASTReader();
instance->createSema(action->getTranslationUnitKind(), nullptr);
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
index 24dd705e37b1..41d62a462ab4 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
@@ -67,39 +67,35 @@ void ClangPersistentVariables::RemovePersistentVariable(
llvm::Optional<CompilerType>
ClangPersistentVariables::GetCompilerTypeFromPersistentDecl(
ConstString type_name) {
- CompilerType compiler_type;
- if (clang::TypeDecl *tdecl = llvm::dyn_cast_or_null<clang::TypeDecl>(
- GetPersistentDecl(type_name))) {
- compiler_type.SetCompilerType(
- ClangASTContext::GetASTContext(&tdecl->getASTContext()),
- reinterpret_cast<lldb::opaque_compiler_type_t>(
- const_cast<clang::Type *>(tdecl->getTypeForDecl())));
- return compiler_type;
+ PersistentDecl p = m_persistent_decls.lookup(type_name.GetCString());
+
+ if (p.m_decl == nullptr)
+ return llvm::None;
+
+ if (clang::TypeDecl *tdecl = llvm::dyn_cast<clang::TypeDecl>(p.m_decl)) {
+ opaque_compiler_type_t t = static_cast<opaque_compiler_type_t>(
+ const_cast<clang::Type *>(tdecl->getTypeForDecl()));
+ return CompilerType(p.m_context, t);
}
return llvm::None;
}
void ClangPersistentVariables::RegisterPersistentDecl(ConstString name,
- clang::NamedDecl *decl) {
- m_persistent_decls.insert(
- std::pair<const char *, clang::NamedDecl *>(name.GetCString(), decl));
+ clang::NamedDecl *decl,
+ ClangASTContext *ctx) {
+ PersistentDecl p = {decl, ctx};
+ m_persistent_decls.insert(std::make_pair(name.GetCString(), p));
if (clang::EnumDecl *enum_decl = llvm::dyn_cast<clang::EnumDecl>(decl)) {
for (clang::EnumConstantDecl *enumerator_decl : enum_decl->enumerators()) {
- m_persistent_decls.insert(std::pair<const char *, clang::NamedDecl *>(
- ConstString(enumerator_decl->getNameAsString()).GetCString(),
- enumerator_decl));
+ p = {enumerator_decl, ctx};
+ m_persistent_decls.insert(std::make_pair(
+ ConstString(enumerator_decl->getNameAsString()).GetCString(), p));
}
}
}
clang::NamedDecl *
ClangPersistentVariables::GetPersistentDecl(ConstString name) {
- PersistentDeclMap::const_iterator i =
- m_persistent_decls.find(name.GetCString());
-
- if (i == m_persistent_decls.end())
- return nullptr;
- else
- return i->second;
+ return m_persistent_decls.lookup(name.GetCString()).m_decl;
}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
index 95e6c3ac963d..434196b35fd5 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
@@ -62,7 +62,8 @@ public:
llvm::Optional<CompilerType>
GetCompilerTypeFromPersistentDecl(ConstString type_name) override;
- void RegisterPersistentDecl(ConstString name, clang::NamedDecl *decl);
+ void RegisterPersistentDecl(ConstString name, clang::NamedDecl *decl,
+ ClangASTContext *ctx);
clang::NamedDecl *GetPersistentDecl(ConstString name);
@@ -80,7 +81,14 @@ private:
// The counter used by GetNextPersistentVariableName
uint32_t m_next_persistent_variable_id = 0;
- typedef llvm::DenseMap<const char *, clang::NamedDecl *> PersistentDeclMap;
+ struct PersistentDecl {
+ /// The persistent decl.
+ clang::NamedDecl *m_decl = nullptr;
+ /// The ClangASTContext for the ASTContext of m_decl.
+ ClangASTContext *m_context = nullptr;
+ };
+
+ typedef llvm::DenseMap<const char *, PersistentDecl> PersistentDeclMap;
PersistentDeclMap
m_persistent_decls; ///< Persistent entities declared by the user.
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
index da1ca785635c..6698797617a3 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
@@ -38,10 +38,11 @@
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/ClangASTMetadata.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/VariableList.h"
@@ -62,13 +63,15 @@
using namespace lldb_private;
+char ClangUserExpression::ID;
+
ClangUserExpression::ClangUserExpression(
ExecutionContextScope &exe_scope, llvm::StringRef expr,
llvm::StringRef prefix, lldb::LanguageType language,
ResultType desired_type, const EvaluateExpressionOptions &options,
ValueObject *ctx_obj)
: LLVMUserExpression(exe_scope, expr, prefix, language, desired_type,
- options, eKindClangUserExpression),
+ options),
m_type_system_helper(*m_target_wp.lock(), options.GetExecutionPolicy() ==
eExecutionPolicyTopLevel),
m_result_delegate(exe_scope.CalculateTarget()), m_ctx_obj(ctx_obj) {
@@ -347,11 +350,12 @@ bool ClangUserExpression::SetupPersistentState(DiagnosticManager &diagnostic_man
static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target) {
if (ClangModulesDeclVendor *decl_vendor =
target->GetClangModulesDeclVendor()) {
+ auto *persistent_state = llvm::cast<ClangPersistentVariables>(
+ target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC));
+ if (!persistent_state)
+ return;
const ClangModulesDeclVendor::ModuleVector &hand_imported_modules =
- llvm::cast<ClangPersistentVariables>(
- target->GetPersistentExpressionStateForLanguage(
- lldb::eLanguageTypeC))
- ->GetHandLoadedClangModules();
+ persistent_state->GetHandLoadedClangModules();
ClangModulesDeclVendor::ModuleVector modules_for_macros;
for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) {
@@ -476,15 +480,18 @@ CppModuleConfiguration GetModuleConfig(lldb::LanguageType language,
files.AppendIfUnique(f);
// We also need to look at external modules in the case of -gmodules as they
// contain the support files for libc++ and the C library.
- sc.comp_unit->ForEachExternalModule([&files](lldb::ModuleSP module) {
- for (std::size_t i = 0; i < module->GetNumCompileUnits(); ++i) {
- const FileSpecList &support_files =
- module->GetCompileUnitAtIndex(i)->GetSupportFiles();
- for (const FileSpec &f : support_files) {
- files.AppendIfUnique(f);
- }
- }
- });
+ llvm::DenseSet<SymbolFile *> visited_symbol_files;
+ sc.comp_unit->ForEachExternalModule(
+ visited_symbol_files, [&files](Module &module) {
+ for (std::size_t i = 0; i < module.GetNumCompileUnits(); ++i) {
+ const FileSpecList &support_files =
+ module.GetCompileUnitAtIndex(i)->GetSupportFiles();
+ for (const FileSpec &f : support_files) {
+ files.AppendIfUnique(f);
+ }
+ }
+ return false;
+ });
LLDB_LOG(log, "[C++ module config] Found {0} support files to analyze",
files.GetSize());
@@ -576,7 +583,7 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); });
- if (!DeclMap()->WillParse(exe_ctx, m_materializer_up.get())) {
+ if (!DeclMap()->WillParse(exe_ctx, GetMaterializer())) {
diagnostic_manager.PutString(
eDiagnosticSeverityError,
"current process state is unsuitable for expression parsing");
@@ -676,10 +683,12 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
register_execution_unit = true;
}
- if (register_execution_unit)
- exe_ctx.GetTargetPtr()
- ->GetPersistentExpressionStateForLanguage(m_language)
- ->RegisterExecutionUnit(m_execution_unit_sp);
+ if (register_execution_unit) {
+ if (auto *persistent_state =
+ exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage(
+ m_language))
+ persistent_state->RegisterExecutionUnit(m_execution_unit_sp);
+ }
}
if (generate_debug_info) {
@@ -764,7 +773,7 @@ bool ClangUserExpression::Complete(ExecutionContext &exe_ctx,
auto on_exit = llvm::make_scope_exit([this]() { ResetDeclMap(); });
- if (!DeclMap()->WillParse(exe_ctx, m_materializer_up.get())) {
+ if (!DeclMap()->WillParse(exe_ctx, GetMaterializer())) {
diagnostic_manager.PutString(
eDiagnosticSeverityError,
"current process state is unsuitable for expression parsing");
@@ -887,9 +896,9 @@ void ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(
Materializer::PersistentVariableDelegate &delegate,
bool keep_result_in_memory,
ValueObject *ctx_obj) {
- m_expr_decl_map_up.reset(
- new ClangExpressionDeclMap(keep_result_in_memory, &delegate, exe_ctx,
- ctx_obj));
+ m_expr_decl_map_up.reset(new ClangExpressionDeclMap(
+ keep_result_in_memory, &delegate, exe_ctx.GetTargetSP(),
+ exe_ctx.GetTargetRef().GetClangASTImporter(), ctx_obj));
}
clang::ASTConsumer *
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
index d94f9cc5e066..00cbffa7fd6f 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
@@ -38,11 +38,14 @@ namespace lldb_private {
/// the objects needed to parse and interpret or JIT an expression. It uses
/// the Clang parser to produce LLVM IR from the expression.
class ClangUserExpression : public LLVMUserExpression {
+ // LLVM RTTI support
+ static char ID;
+
public:
- /// LLVM-style RTTI support.
- static bool classof(const Expression *E) {
- return E->getKind() == eKindClangUserExpression;
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || LLVMUserExpression::isA(ClassID);
}
+ static bool classof(const Expression *obj) { return obj->isA(&ID); }
enum { kDefaultTimeout = 500000u };
@@ -93,7 +96,7 @@ public:
/// \param[in] expr
/// The expression to parse.
///
- /// \param[in] expr_prefix
+ /// \param[in] prefix
/// If non-NULL, a C string containing translation-unit level
/// definitions to be included when the expression is parsed.
///
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
index 564c62c6a2c6..199e4898e118 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
@@ -31,6 +31,8 @@
using namespace lldb_private;
+char ClangUtilityFunction::ID;
+
/// Constructor
///
/// \param[in] text
@@ -40,7 +42,7 @@ using namespace lldb_private;
/// The name of the function, as used in the text.
ClangUtilityFunction::ClangUtilityFunction(ExecutionContextScope &exe_scope,
const char *text, const char *name)
- : UtilityFunction(exe_scope, text, name, eKindClangUtilityFunction) {
+ : UtilityFunction(exe_scope, text, name) {
m_function_text.assign(ClangExpressionSourceCode::g_expression_prefix);
if (text && text[0])
m_function_text.append(text);
@@ -157,7 +159,7 @@ bool ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager,
void ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap(
ExecutionContext &exe_ctx, bool keep_result_in_memory) {
- m_expr_decl_map_up.reset(
- new ClangExpressionDeclMap(keep_result_in_memory, nullptr, exe_ctx,
- nullptr));
+ m_expr_decl_map_up.reset(new ClangExpressionDeclMap(
+ keep_result_in_memory, nullptr, exe_ctx.GetTargetSP(),
+ exe_ctx.GetTargetRef().GetClangASTImporter(), nullptr));
}
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
index 70ebb2f3ad8a..9efaa0254c3e 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
@@ -33,11 +33,14 @@ namespace lldb_private {
/// simply provide a way to push a function into the target for the debugger
/// to call later on.
class ClangUtilityFunction : public UtilityFunction {
+ // LLVM RTTI support
+ static char ID;
+
public:
- /// LLVM-style RTTI support.
- static bool classof(const Expression *E) {
- return E->getKind() == eKindClangUtilityFunction;
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || UtilityFunction::isA(ClassID);
}
+ static bool classof(const Expression *obj) { return obj->isA(&ID); }
class ClangUtilityFunctionHelper : public ClangExpressionHelper {
public:
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h b/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h
index 60c0691b21c1..5b9c8007ab76 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/IRDynamicChecks.h
@@ -76,10 +76,6 @@ public:
///
/// \param[in] func_name
/// The name of the function to prepare for execution in the target.
- ///
- /// \param[in] decl_map
- /// The mapping used to look up entities in the target process. In
- /// this case, used to find objc_msgSend
IRDynamicChecks(ClangDynamicCheckerFunctions &checker_functions,
const char *func_name = "$__lldb_expr");
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
index 4e871f7d6a44..103a7ee46f35 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
@@ -355,7 +355,7 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) {
ConstantInt *new_constant_int =
ConstantInt::get(llvm::Type::getInt64Ty(m_module->getContext()),
- reinterpret_cast<uint64_t>(result_decl), false);
+ reinterpret_cast<uintptr_t>(result_decl), false);
llvm::Metadata *values[2];
values[0] = ConstantAsMetadata::get(new_result_global);
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
index 893620f7f8e0..262e8ee0c06c 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.h
@@ -71,15 +71,6 @@ public:
/// variables) should be resolved. If not, only external functions
/// are resolved.
///
- /// \param[in] execution_policy
- /// Determines whether an IR interpreter can be used to statically
- /// evaluate the expression.
- ///
- /// \param[in] const_result
- /// This variable is populated with the statically-computed result
- /// of the function, if it has no side-effects and the result can
- /// be computed statically.
- ///
/// \param[in] execution_unit
/// The holder for raw data associated with the expression.
///
@@ -105,10 +96,6 @@ public:
/// $__lldb_expr, and that function is passed to the passes one by
/// one.
///
- /// \param[in] interpreter_error
- /// An error. If the expression fails to be interpreted, this error
- /// is set to a reason why.
- ///
/// \return
/// True on success; false otherwise
bool runOnModule(llvm::Module &llvm_module) override;
@@ -142,9 +129,6 @@ private:
/// The top-level pass implementation
///
- /// \param[in] llvm_module
- /// The module currently being processed.
- ///
/// \param[in] llvm_function
/// The function currently being processed.
///
@@ -184,12 +168,12 @@ private:
/// Find the NamedDecl corresponding to a Value. This interface is exposed
/// for the IR interpreter.
///
+ /// \param[in] global_val
+ /// The global entity to search for
+ ///
/// \param[in] module
/// The module containing metadata to search
///
- /// \param[in] global
- /// The global entity to search for
- ///
/// \return
/// The corresponding variable declaration
public:
@@ -287,7 +271,7 @@ private:
/// Replace a single old-style class reference
///
- /// \param[in] selector_load
+ /// \param[in] class_load
/// The load of the statically-allocated selector.
///
/// \return
@@ -362,7 +346,7 @@ private:
/// Handle all the arguments to a function call
///
- /// \param[in] C
+ /// \param[in] call_inst
/// The call instruction.
///
/// \return
@@ -381,8 +365,8 @@ private:
/// Remove calls to __cxa_atexit, which should never be generated by
/// expressions.
///
- /// \param[in] call_inst
- /// The call instruction.
+ /// \param[in] basic_block
+ /// The basic block currently being processed.
///
/// \return
/// True if the scan was successful; false if some operation
@@ -391,7 +375,7 @@ private:
/// The top-level pass implementation
///
- /// \param[in] basic_block
+ /// \param[in] llvm_function
/// The function currently being processed.
///
/// \return
@@ -474,28 +458,9 @@ private:
///pointer (see comments in
/// ASTResultSynthesizer::SynthesizeBodyResult)
- llvm::GlobalVariable *m_reloc_placeholder; ///< A placeholder that will be
- ///replaced by a pointer to the
- ///final
- /// location of the static allocation.
-
- /// UnfoldConstant operates on a constant [Old] which has just been replaced
- /// with a value [New]. We assume that new_value has been properly placed
- /// early in the function, in front of the first instruction in the entry
- /// basic block [FirstEntryInstruction].
- ///
- /// UnfoldConstant reads through the uses of Old and replaces Old in those
- /// uses with New. Where those uses are constants, the function generates
- /// new instructions to compute the result of the new, non-constant
- /// expression and places them before FirstEntryInstruction. These
- /// instructions replace the constant uses, so UnfoldConstant calls itself
- /// recursively for those.
- ///
- /// \param[in] llvm_function
- /// The function currently being processed.
- ///
- /// \return
- /// True on success; false otherwise
+ /// A placeholder that will be replaced by a pointer to the final location of
+ /// the static allocation.
+ llvm::GlobalVariable *m_reloc_placeholder;
class FunctionValueCache {
public:
@@ -513,6 +478,20 @@ private:
FunctionValueCache m_entry_instruction_finder;
+ /// UnfoldConstant operates on a constant [Old] which has just been replaced
+ /// with a value [New]. We assume that new_value has been properly placed
+ /// early in the function, in front of the first instruction in the entry
+ /// basic block [FirstEntryInstruction].
+ ///
+ /// UnfoldConstant reads through the uses of Old and replaces Old in those
+ /// uses with New. Where those uses are constants, the function generates
+ /// new instructions to compute the result of the new, non-constant
+ /// expression and places them before FirstEntryInstruction. These
+ /// instructions replace the constant uses, so UnfoldConstant calls itself
+ /// recursively for those.
+ ///
+ /// \return
+ /// True on success; false otherwise
static bool UnfoldConstant(llvm::Constant *old_constant,
llvm::Function *llvm_function,
FunctionValueCache &value_maker,
@@ -522,9 +501,6 @@ private:
/// Commit the allocation in m_data_allocator and use its final location to
/// replace m_reloc_placeholder.
///
- /// \param[in] module
- /// The module that m_data_allocator resides in
- ///
/// \return
/// True on success; false otherwise
bool CompleteDataAllocation();
diff --git a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index 19a987b0f004..ff142e6f35ff 100644
--- a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -850,6 +850,7 @@ uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber() const {
/* On Apple iOS et al, the frame pointer register is always r7.
* Typically on other ARM systems, thumb code uses r7; arm code uses r11.
+ * Windows on ARM, which is in thumb mode, uses r11 though.
*/
uint32_t fp_regnum = 11;
@@ -857,7 +858,7 @@ uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber() const {
if (is_apple)
fp_regnum = 7;
- if (m_opcode_mode == eModeThumb)
+ if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())
fp_regnum = 7;
return fp_regnum;
@@ -879,6 +880,7 @@ uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const {
/* On Apple iOS et al, the frame pointer register is always r7.
* Typically on other ARM systems, thumb code uses r7; arm code uses r11.
+ * Windows on ARM, which is in thumb mode, uses r11 though.
*/
uint32_t fp_regnum = dwarf_r11;
@@ -886,7 +888,7 @@ uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const {
if (is_apple)
fp_regnum = dwarf_r7;
- if (m_opcode_mode == eModeThumb)
+ if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())
fp_regnum = dwarf_r7;
return fp_regnum;
@@ -1343,6 +1345,8 @@ bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode,
EmulateInstruction::Context context;
if (Rd == 13)
context.type = EmulateInstruction::eContextAdjustStackPointer;
+ else if (Rd == GetFramePointerRegisterNumber() && Rm == 13)
+ context.type = EmulateInstruction::eContextSetFramePointer;
else
context.type = EmulateInstruction::eContextRegisterPlusOffset;
RegisterInfo dwarf_reg;
diff --git a/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
index 21b6296745bd..b55eeb0eaf46 100644
--- a/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
+++ b/lldb/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
@@ -28,6 +28,7 @@
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
@@ -149,7 +150,9 @@ EmulateInstructionMIPS::EmulateInstructionMIPS(
m_insn_info.reset(target->createMCInstrInfo());
assert(m_insn_info.get());
- m_asm_info.reset(target->createMCAsmInfo(*m_reg_info, triple.getTriple()));
+ llvm::MCTargetOptions MCOptions;
+ m_asm_info.reset(
+ target->createMCAsmInfo(*m_reg_info, triple.getTriple(), MCOptions));
m_subtype_info.reset(
target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
assert(m_asm_info.get() && m_subtype_info.get());
@@ -978,13 +981,11 @@ EmulateInstructionMIPS::GetSizeOfInstruction(lldb_private::DataExtractor &data,
llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());
if (m_use_alt_disaasm)
- decode_status =
- m_alt_disasm->getInstruction(mc_insn, next_inst_size, raw_insn,
- inst_addr, llvm::nulls(), llvm::nulls());
+ decode_status = m_alt_disasm->getInstruction(
+ mc_insn, next_inst_size, raw_insn, inst_addr, llvm::nulls());
else
- decode_status =
- m_disasm->getInstruction(mc_insn, next_inst_size, raw_insn, inst_addr,
- llvm::nulls(), llvm::nulls());
+ decode_status = m_disasm->getInstruction(mc_insn, next_inst_size, raw_insn,
+ inst_addr, llvm::nulls());
if (decode_status != llvm::MCDisassembler::Success)
return false;
@@ -1067,11 +1068,11 @@ bool EmulateInstructionMIPS::EvaluateInstruction(uint32_t evaluate_options) {
llvm::MCDisassembler::DecodeStatus decode_status;
llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());
if (m_use_alt_disaasm)
- decode_status = m_alt_disasm->getInstruction(
- mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls());
+ decode_status = m_alt_disasm->getInstruction(mc_insn, insn_size, raw_insn,
+ m_addr, llvm::nulls());
else
- decode_status = m_disasm->getInstruction(
- mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls());
+ decode_status = m_disasm->getInstruction(mc_insn, insn_size, raw_insn,
+ m_addr, llvm::nulls());
if (decode_status != llvm::MCDisassembler::Success)
return false;
diff --git a/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
index 5fabbeb756cc..3baf942bc17f 100644
--- a/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
+++ b/lldb/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
@@ -28,6 +28,7 @@
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
@@ -153,7 +154,9 @@ EmulateInstructionMIPS64::EmulateInstructionMIPS64(
m_insn_info.reset(target->createMCInstrInfo());
assert(m_insn_info.get());
- m_asm_info.reset(target->createMCAsmInfo(*m_reg_info, triple.getTriple()));
+ llvm::MCTargetOptions MCOptions;
+ m_asm_info.reset(
+ target->createMCAsmInfo(*m_reg_info, triple.getTriple(), MCOptions));
m_subtype_info.reset(
target->createMCSubtargetInfo(triple.getTriple(), cpu, features));
assert(m_asm_info.get() && m_subtype_info.get());
@@ -962,8 +965,8 @@ bool EmulateInstructionMIPS64::EvaluateInstruction(uint32_t evaluate_options) {
if (m_opcode.GetData(data)) {
llvm::MCDisassembler::DecodeStatus decode_status;
llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize());
- decode_status = m_disasm->getInstruction(
- mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls());
+ decode_status = m_disasm->getInstruction(mc_insn, insn_size, raw_insn,
+ m_addr, llvm::nulls());
if (decode_status != llvm::MCDisassembler::Success)
return false;
}
@@ -1360,7 +1363,7 @@ bool EmulateInstructionMIPS64::Emulate_BXX_3ops(llvm::MCInst &insn) {
if (!success)
return false;
- if (!strcasecmp(op_name, "BEQ") || !strcasecmp(op_name, "BEQL")
+ if (!strcasecmp(op_name, "BEQ") || !strcasecmp(op_name, "BEQL")
|| !strcasecmp(op_name, "BEQ64") ) {
if (rs_val == rt_val)
target = pc + offset;
@@ -1602,7 +1605,7 @@ bool EmulateInstructionMIPS64::Emulate_BXX_2ops(llvm::MCInst &insn) {
target = pc + offset;
else
target = pc + 8;
- } else if (!strcasecmp(op_name, "BLEZL") || !strcasecmp(op_name, "BLEZ")
+ } else if (!strcasecmp(op_name, "BLEZL") || !strcasecmp(op_name, "BLEZ")
|| !strcasecmp(op_name, "BLEZ64")) {
if (rs_val <= 0)
target = pc + offset;
diff --git a/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp b/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp
index dfe61316b042..b73b6c095368 100644
--- a/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp
+++ b/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/MainThreadCheckerRuntime.cpp
@@ -153,7 +153,7 @@ bool MainThreadCheckerRuntime::NotifyBreakpointHit(
user_id_t break_loc_id) {
assert(baton && "null baton");
if (!baton)
- return false; //< false => resume execution.
+ return false; ///< false => resume execution.
MainThreadCheckerRuntime *const instance =
static_cast<MainThreadCheckerRuntime *>(baton);
@@ -241,30 +241,30 @@ MainThreadCheckerRuntime::GetBacktracesFromExtendedStopInfo(
StructuredData::ObjectSP info) {
ThreadCollectionSP threads;
threads = std::make_shared<ThreadCollection>();
-
+
ProcessSP process_sp = GetProcessSP();
-
+
if (info->GetObjectForDotSeparatedPath("instrumentation_class")
->GetStringValue() != "MainThreadChecker")
return threads;
-
+
std::vector<lldb::addr_t> PCs;
auto trace = info->GetObjectForDotSeparatedPath("trace")->GetAsArray();
trace->ForEach([&PCs](StructuredData::Object *PC) -> bool {
PCs.push_back(PC->GetAsInteger()->GetValue());
return true;
});
-
+
if (PCs.empty())
return threads;
-
+
StructuredData::ObjectSP thread_id_obj =
info->GetObjectForDotSeparatedPath("tid");
tid_t tid = thread_id_obj ? thread_id_obj->GetIntegerValue() : 0;
HistoryThread *history_thread = new HistoryThread(*process_sp, tid, PCs);
ThreadSP new_thread_sp(history_thread);
-
+
// Save this in the Process' ExtendedThreadList so a strong pointer retains
// the object
process_sp->GetExtendedThreadList().AddThread(new_thread_sp);
diff --git a/lldb/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp b/lldb/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp
index 50f1d48d03e0..137ecab224bc 100644
--- a/lldb/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp
+++ b/lldb/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp
@@ -207,7 +207,7 @@ bool UndefinedBehaviorSanitizerRuntime::NotifyBreakpointHit(
user_id_t break_loc_id) {
assert(baton && "null baton");
if (!baton)
- return false; //< false => resume execution.
+ return false; ///< false => resume execution.
UndefinedBehaviorSanitizerRuntime *const instance =
static_cast<UndefinedBehaviorSanitizerRuntime *>(baton);
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 489fa7d0ad91..4385a60f5862 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -19,6 +19,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Demangle/ItaniumDemangle.h"
+#include "lldb/Core/Mangled.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/DataFormatters/CXXFunctionPointer.h"
@@ -238,18 +239,16 @@ std::string CPlusPlusLanguage::MethodName::GetScopeQualifiedName() {
return res;
}
-bool CPlusPlusLanguage::IsCPPMangledName(const char *name) {
+bool CPlusPlusLanguage::IsCPPMangledName(llvm::StringRef name) {
// FIXME!! we should really run through all the known C++ Language plugins
// and ask each one if this is a C++ mangled name
- if (name == nullptr)
- return false;
+ Mangled::ManglingScheme scheme = Mangled::GetManglingScheme(name);
- // MSVC style mangling
- if (name[0] == '?')
- return true;
+ if (scheme == Mangled::eManglingSchemeNone)
+ return false;
- return (name[0] != '\0' && name[0] == '_' && name[1] == 'Z');
+ return true;
}
bool CPlusPlusLanguage::ExtractContextAndIdentifier(
@@ -285,46 +284,34 @@ public:
}
};
-/// Given a mangled function `Mangled`, replace all the primitive function type
-/// arguments of `Search` with type `Replace`.
-class TypeSubstitutor
- : public llvm::itanium_demangle::AbstractManglingParser<TypeSubstitutor,
+template <typename Derived>
+class ManglingSubstitutor
+ : public llvm::itanium_demangle::AbstractManglingParser<Derived,
NodeAllocator> {
- /// Input character until which we have constructed the respective output
- /// already
- const char *Written;
+ using Base =
+ llvm::itanium_demangle::AbstractManglingParser<Derived, NodeAllocator>;
- llvm::StringRef Search;
- llvm::StringRef Replace;
- llvm::SmallString<128> Result;
+public:
+ ManglingSubstitutor() : Base(nullptr, nullptr) {}
- /// Whether we have performed any substitutions.
- bool Substituted;
+ template<typename... Ts>
+ ConstString substitute(llvm::StringRef Mangled, Ts &&... Vals) {
+ this->getDerived().reset(Mangled, std::forward<Ts>(Vals)...);
+ return substituteImpl(Mangled);
+ }
- void reset(llvm::StringRef Mangled, llvm::StringRef Search,
- llvm::StringRef Replace) {
- AbstractManglingParser::reset(Mangled.begin(), Mangled.end());
+
+protected:
+ void reset(llvm::StringRef Mangled) {
+ Base::reset(Mangled.begin(), Mangled.end());
Written = Mangled.begin();
- this->Search = Search;
- this->Replace = Replace;
Result.clear();
Substituted = false;
}
- void appendUnchangedInput() {
- Result += llvm::StringRef(Written, First - Written);
- Written = First;
- }
-
-public:
- TypeSubstitutor() : AbstractManglingParser(nullptr, nullptr) {}
-
- ConstString substitute(llvm::StringRef Mangled, llvm::StringRef From,
- llvm::StringRef To) {
+ ConstString substituteImpl(llvm::StringRef Mangled) {
Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
-
- reset(Mangled, From, To);
- if (parse() == nullptr) {
+ if (this->parse() == nullptr) {
LLDB_LOG(log, "Failed to substitute mangling in {0}", Mangled);
return ConstString();
}
@@ -337,20 +324,69 @@ public:
return ConstString(Result);
}
+ void trySubstitute(llvm::StringRef From, llvm::StringRef To) {
+ if (!llvm::StringRef(currentParserPos(), this->numLeft()).startswith(From))
+ return;
+
+ // We found a match. Append unmodified input up to this point.
+ appendUnchangedInput();
+
+ // And then perform the replacement.
+ Result += To;
+ Written += From.size();
+ Substituted = true;
+ }
+
+private:
+ /// Input character until which we have constructed the respective output
+ /// already.
+ const char *Written;
+
+ llvm::SmallString<128> Result;
+
+ /// Whether we have performed any substitutions.
+ bool Substituted;
+
+ const char *currentParserPos() const { return this->First; }
+
+ void appendUnchangedInput() {
+ Result +=
+ llvm::StringRef(Written, std::distance(Written, currentParserPos()));
+ Written = currentParserPos();
+ }
+
+};
+
+/// Given a mangled function `Mangled`, replace all the primitive function type
+/// arguments of `Search` with type `Replace`.
+class TypeSubstitutor : public ManglingSubstitutor<TypeSubstitutor> {
+ llvm::StringRef Search;
+ llvm::StringRef Replace;
+
+public:
+ void reset(llvm::StringRef Mangled, llvm::StringRef Search,
+ llvm::StringRef Replace) {
+ ManglingSubstitutor::reset(Mangled);
+ this->Search = Search;
+ this->Replace = Replace;
+ }
+
llvm::itanium_demangle::Node *parseType() {
- if (llvm::StringRef(First, numLeft()).startswith(Search)) {
- // We found a match. Append unmodified input up to this point.
- appendUnchangedInput();
-
- // And then perform the replacement.
- Result += Replace;
- Written += Search.size();
- Substituted = true;
- }
- return AbstractManglingParser::parseType();
+ trySubstitute(Search, Replace);
+ return ManglingSubstitutor::parseType();
}
};
-}
+
+class CtorDtorSubstitutor : public ManglingSubstitutor<CtorDtorSubstitutor> {
+public:
+ llvm::itanium_demangle::Node *
+ parseCtorDtorName(llvm::itanium_demangle::Node *&SoFar, NameState *State) {
+ trySubstitute("C1", "C2");
+ trySubstitute("D1", "D2");
+ return ManglingSubstitutor::parseCtorDtorName(SoFar, State);
+ }
+};
+} // namespace
uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings(
const ConstString mangled_name, std::set<ConstString> &alternates) {
@@ -398,6 +434,10 @@ uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings(
TS.substitute(mangled_name.GetStringRef(), "y", "m"))
alternates.insert(ulong_fixup);
+ if (ConstString ctor_fixup =
+ CtorDtorSubstitutor().substitute(mangled_name.GetStringRef()))
+ alternates.insert(ctor_fixup);
+
return alternates.size() - start_size;
}
@@ -426,6 +466,13 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"std::__[[:alnum:]]+::char_traits<char>, "
"std::__[[:alnum:]]+::allocator<char> >$"),
stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp,
+ lldb_private::formatters::LibcxxStringSummaryProviderASCII,
+ "std::string summary provider",
+ ConstString("^std::__[[:alnum:]]+::basic_string<unsigned char, "
+ "std::__[[:alnum:]]+::char_traits<unsigned char>, "
+ "std::__[[:alnum:]]+::allocator<unsigned char> >$"),
+ stl_summary_flags, true);
AddCXXSummary(cpp_category_sp,
lldb_private::formatters::LibcxxStringSummaryProviderUTF16,
@@ -568,6 +615,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"weak_ptr synthetic children",
ConstString("^(std::__[[:alnum:]]+::)weak_ptr<.+>(( )?&)?$"),
stl_synth_flags, true);
+ AddCXXSummary(cpp_category_sp,
+ lldb_private::formatters::LibcxxFunctionSummaryProvider,
+ "libc++ std::function summary provider",
+ ConstString("^std::__[[:alnum:]]+::function<.+>$"),
+ stl_summary_flags, true);
stl_summary_flags.SetDontShowChildren(false);
stl_summary_flags.SetSkipPointers(false);
@@ -719,6 +771,10 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
ConstString("std::__cxx11::basic_string<char, std::char_traits<char>, "
"std::allocator<char> >"),
cxx11_string_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(
+ ConstString("std::__cxx11::basic_string<unsigned char, std::char_traits<unsigned char>, "
+ "std::allocator<unsigned char> >"),
+ cxx11_string_summary_sp);
// making sure we force-pick the summary for printing wstring (_M_p is a
// wchar_t*)
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
index d30e56080732..4ed45bc904ce 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
@@ -101,7 +101,7 @@ public:
static lldb_private::ConstString GetPluginNameStatic();
- static bool IsCPPMangledName(const char *name);
+ static bool IsCPPMangledName(llvm::StringRef name);
// Extract C++ context and identifier from a string using heuristic matching
// (as opposed to
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index abe89035c532..ecadaef7a87e 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -572,10 +572,13 @@ bool lldb_private::formatters::LibcxxWStringSummaryProvider(
location_sp->GetPointeeData(extractor, 0, size);
// std::wstring::size() is measured in 'characters', not bytes
- auto wchar_t_size = valobj.GetTargetSP()
- ->GetScratchClangASTContext()
- ->GetBasicType(lldb::eBasicTypeWChar)
- .GetByteSize(nullptr);
+ ClangASTContext *ast_context =
+ ClangASTContext::GetScratch(*valobj.GetTargetSP());
+ if (!ast_context)
+ return false;
+
+ auto wchar_t_size =
+ ast_context->GetBasicType(lldb::eBasicTypeWChar).GetByteSize(nullptr);
if (!wchar_t_size)
return false;
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
index 619c718a1c1b..f6d8d4d9a7eb 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
@@ -94,6 +94,8 @@ public:
MapIterator(ValueObject *entry, size_t depth = 0)
: m_entry(entry), m_max_depth(depth), m_error(false) {}
+ MapIterator &operator=(const MapIterator &) = default;
+
ValueObjectSP value() { return m_entry.GetEntry(); }
ValueObjectSP advance(size_t count) {
diff --git a/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp b/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp
index a9a1b44731f2..3e77b1646739 100644
--- a/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp
+++ b/lldb/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp
@@ -139,6 +139,22 @@ void ClangHighlighter::Highlight(const HighlightStyle &options,
FileManager file_mgr(file_opts,
FileSystem::Instance().GetVirtualFileSystem());
+ // The line might end in a backslash which would cause Clang to drop the
+ // backslash and the terminating new line. This makes sense when parsing C++,
+ // but when highlighting we care about preserving the backslash/newline. To
+ // not lose this information we remove the new line here so that Clang knows
+ // this is just a single line we are highlighting. We add back the newline
+ // after tokenizing.
+ llvm::StringRef line_ending = "";
+ // There are a few legal line endings Clang recognizes and we need to
+ // temporarily remove from the string.
+ if (line.consume_back("\r\n"))
+ line_ending = "\r\n";
+ else if (line.consume_back("\n"))
+ line_ending = "\n";
+ else if (line.consume_back("\r"))
+ line_ending = "\r";
+
unsigned line_number = previous_lines.count('\n') + 1U;
// Let's build the actual source code Clang needs and setup some utility
@@ -227,6 +243,9 @@ void ClangHighlighter::Highlight(const HighlightStyle &options,
color.Apply(result, to_print);
}
+ // Add the line ending we trimmed before tokenizing.
+ result << line_ending;
+
// If we went over the whole file but couldn't find our own file, then
// somehow our setup was wrong. When we're in release mode we just give the
// user the normal line and pretend we don't know how to highlight it. In
diff --git a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
index ddf3953bb512..8a81abbaedbe 100644
--- a/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
+++ b/lldb/source/Plugins/Language/ObjC/Cocoa.cpp
@@ -694,32 +694,44 @@ bool lldb_private::formatters::NSURLSummaryProvider(
CompilerType type(valobj.GetCompilerType());
ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset_text, type, true));
ValueObjectSP base(valobj.GetSyntheticChildAtOffset(offset_base, type, true));
- if (!text)
- return false;
- if (text->GetValueAsUnsigned(0) == 0)
+ if (!text || text->GetValueAsUnsigned(0) == 0)
return false;
+
+ StreamString base_summary;
+ if (base && base->GetValueAsUnsigned(0)) {
+ if (!NSURLSummaryProvider(*base, base_summary, options))
+ base_summary.Clear();
+ }
+ if (base_summary.Empty())
+ return NSStringSummaryProvider(*text, stream, options);
+
StreamString summary;
- if (!NSStringSummaryProvider(*text, summary, options))
+ if (!NSStringSummaryProvider(*text, summary, options) || summary.Empty())
return false;
- if (base && base->GetValueAsUnsigned(0)) {
- std::string summary_str = summary.GetString();
-
- if (!summary_str.empty())
- summary_str.pop_back();
- summary_str += " -- ";
- StreamString base_summary;
- if (NSURLSummaryProvider(*base, base_summary, options) &&
- !base_summary.Empty()) {
- llvm::StringRef base_str = base_summary.GetString();
- if (base_str.size() > 2)
- base_str = base_str.drop_front(2);
- summary_str += base_str;
+
+ const char quote_char = '"';
+ std::string prefix, suffix;
+ if (Language *language = Language::FindPlugin(options.GetLanguage())) {
+ if (!language->GetFormatterPrefixSuffix(*text, ConstString("NSString"),
+ prefix, suffix)) {
+ prefix.clear();
+ suffix.clear();
}
- summary.Clear();
- summary.PutCString(summary_str);
}
- if (!summary.Empty()) {
- stream.PutCString(summary.GetString());
+ // @"A" -> @"A
+ llvm::StringRef summary_str = summary.GetString();
+ bool back_consumed = summary_str.consume_back(quote_char + suffix);
+ assert(back_consumed);
+ UNUSED_IF_ASSERT_DISABLED(back_consumed);
+ // @"B" -> B"
+ llvm::StringRef base_summary_str = base_summary.GetString();
+ bool front_consumed = base_summary_str.consume_front(prefix + quote_char);
+ assert(front_consumed);
+ UNUSED_IF_ASSERT_DISABLED(front_consumed);
+ // @"A -- B"
+ if (!summary_str.empty() && !base_summary_str.empty()) {
+ stream.Printf("%s -- %s", summary_str.str().c_str(),
+ base_summary_str.str().c_str());
return true;
}
diff --git a/lldb/source/Plugins/Language/ObjC/NSArray.cpp b/lldb/source/Plugins/Language/ObjC/NSArray.cpp
index 7219c016dfd1..73335aff2fd7 100644
--- a/lldb/source/Plugins/Language/ObjC/NSArray.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSArray.cpp
@@ -96,31 +96,6 @@ private:
D64 *m_data_64;
};
-namespace Foundation109 {
- struct DataDescriptor_32 {
- uint32_t _used;
- uint32_t _priv1 : 2;
- uint32_t _size : 30;
- uint32_t _priv2 : 2;
- uint32_t _offset : 30;
- uint32_t _priv3;
- uint32_t _data;
- };
-
- struct DataDescriptor_64 {
- uint64_t _used;
- uint64_t _priv1 : 2;
- uint64_t _size : 62;
- uint64_t _priv2 : 2;
- uint64_t _offset : 62;
- uint32_t _priv3;
- uint64_t _data;
- };
-
- using NSArrayMSyntheticFrontEnd =
- GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>;
-}
-
namespace Foundation1010 {
struct DataDescriptor_32 {
uint32_t _used;
@@ -461,13 +436,12 @@ lldb_private::formatters::NSArrayMSyntheticFrontEndBase::NSArrayMSyntheticFrontE
: SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8),
m_id_type() {
if (valobj_sp) {
- auto *clang_ast_context = valobj_sp->GetExecutionContextRef()
- .GetTargetSP()
- ->GetScratchClangASTContext();
+ auto *clang_ast_context = ClangASTContext::GetScratch(
+ *valobj_sp->GetExecutionContextRef().GetTargetSP());
if (clang_ast_context)
m_id_type = CompilerType(
clang_ast_context,
- clang_ast_context->getASTContext()->ObjCBuiltinIdTy.getAsOpaquePtr());
+ clang_ast_context->getASTContext().ObjCBuiltinIdTy.getAsOpaquePtr());
if (valobj_sp->GetProcessSP())
m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize();
}
@@ -610,13 +584,11 @@ lldb_private::formatters::GenericNSArrayISyntheticFrontEnd<D32, D64, Inline>::
if (valobj_sp) {
CompilerType type = valobj_sp->GetCompilerType();
if (type) {
- auto *clang_ast_context = valobj_sp->GetExecutionContextRef()
- .GetTargetSP()
- ->GetScratchClangASTContext();
+ auto *clang_ast_context = ClangASTContext::GetScratch(
+ *valobj_sp->GetExecutionContextRef().GetTargetSP());
if (clang_ast_context)
- m_id_type = CompilerType(clang_ast_context,
- clang_ast_context->getASTContext()
- ->ObjCBuiltinIdTy.getAsOpaquePtr());
+ m_id_type = clang_ast_context->GetType(
+ clang_ast_context->getASTContext().ObjCBuiltinIdTy);
}
}
}
@@ -780,11 +752,15 @@ lldb_private::formatters::NSArray1SyntheticFrontEnd::GetChildAtIndex(
static const ConstString g_zero("[0]");
if (idx == 0) {
- CompilerType id_type(
- m_backend.GetTargetSP()->GetScratchClangASTContext()->GetBasicType(
- lldb::eBasicTypeObjCID));
- return m_backend.GetSyntheticChildAtOffset(
- m_backend.GetProcessSP()->GetAddressByteSize(), id_type, true, g_zero);
+ auto *clang_ast_context =
+ ClangASTContext::GetScratch(*m_backend.GetTargetSP());
+ if (clang_ast_context) {
+ CompilerType id_type(
+ clang_ast_context->GetBasicType(lldb::eBasicTypeObjCID));
+ return m_backend.GetSyntheticChildAtOffset(
+ m_backend.GetProcessSP()->GetAddressByteSize(), id_type, true,
+ g_zero);
+ }
}
return lldb::ValueObjectSP();
}
@@ -857,8 +833,6 @@ lldb_private::formatters::NSArraySyntheticFrontEndCreator(
return (new Foundation1428::NSArrayMSyntheticFrontEnd(valobj_sp));
if (runtime->GetFoundationVersion() >= 1100)
return (new Foundation1010::NSArrayMSyntheticFrontEnd(valobj_sp));
- else
- return (new Foundation109::NSArrayMSyntheticFrontEnd(valobj_sp));
} else if (class_name == g_NSCallStackArray) {
return (new CallStackArray::NSCallStackArraySyntheticFrontEnd(valobj_sp));
} else {
diff --git a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
index 10f66c4a37f8..ae00674c49f3 100644
--- a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp
@@ -65,7 +65,7 @@ NSDictionary_Additionals::GetAdditionalSynthetics() {
static CompilerType GetLLDBNSPairType(TargetSP target_sp) {
CompilerType compiler_type;
- ClangASTContext *target_ast_context = target_sp->GetScratchClangASTContext();
+ ClangASTContext *target_ast_context = ClangASTContext::GetScratch(*target_sp);
if (target_ast_context) {
ConstString g___lldb_autogen_nspair("__lldb_autogen_nspair");
diff --git a/lldb/source/Plugins/Language/ObjC/NSError.cpp b/lldb/source/Plugins/Language/ObjC/NSError.cpp
index 97df3be72c84..94a97c8ad039 100644
--- a/lldb/source/Plugins/Language/ObjC/NSError.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSError.cpp
@@ -86,10 +86,10 @@ bool lldb_private::formatters::NSError_SummaryProvider(
ValueObjectSP domain_str_sp = ValueObject::CreateValueObjectFromData(
"domain_str", isw.GetAsData(process_sp->GetByteOrder()),
- valobj.GetExecutionContextRef(), process_sp->GetTarget()
- .GetScratchClangASTContext()
- ->GetBasicType(lldb::eBasicTypeVoid)
- .GetPointerType());
+ valobj.GetExecutionContextRef(),
+ ClangASTContext::GetScratch(process_sp->GetTarget())
+ ->GetBasicType(lldb::eBasicTypeVoid)
+ .GetPointerType());
if (!domain_str_sp)
return false;
@@ -156,8 +156,8 @@ public:
m_child_sp = CreateValueObjectFromData(
"_userInfo", isw.GetAsData(process_sp->GetByteOrder()),
m_backend.GetExecutionContextRef(),
- process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(
- lldb::eBasicTypeObjCID));
+ ClangASTContext::GetScratch(process_sp->GetTarget())
+ ->GetBasicType(lldb::eBasicTypeObjCID));
return false;
}
diff --git a/lldb/source/Plugins/Language/ObjC/NSException.cpp b/lldb/source/Plugins/Language/ObjC/NSException.cpp
index 931794a12ab1..9150787361c5 100644
--- a/lldb/source/Plugins/Language/ObjC/NSException.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSException.cpp
@@ -69,10 +69,12 @@ static bool ExtractFields(ValueObject &valobj, ValueObjectSP *name_sp,
InferiorSizedWord userinfo_isw(userinfo, *process_sp);
InferiorSizedWord reserved_isw(reserved, *process_sp);
- CompilerType voidstar = process_sp->GetTarget()
- .GetScratchClangASTContext()
- ->GetBasicType(lldb::eBasicTypeVoid)
- .GetPointerType();
+ auto *clang_ast_context = ClangASTContext::GetScratch(process_sp->GetTarget());
+ if (!clang_ast_context)
+ return false;
+
+ CompilerType voidstar =
+ clang_ast_context->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
if (name_sp)
*name_sp = ValueObject::CreateValueObjectFromData(
@@ -96,21 +98,19 @@ static bool ExtractFields(ValueObject &valobj, ValueObjectSP *name_sp,
bool lldb_private::formatters::NSException_SummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
- lldb::ValueObjectSP name_sp;
lldb::ValueObjectSP reason_sp;
- if (!ExtractFields(valobj, &name_sp, &reason_sp, nullptr, nullptr))
+ if (!ExtractFields(valobj, nullptr, &reason_sp, nullptr, nullptr))
return false;
- if (!name_sp || !reason_sp)
+ if (!reason_sp) {
+ stream.Printf("No reason");
return false;
+ }
- StreamString name_str_summary;
StreamString reason_str_summary;
- if (NSStringSummaryProvider(*name_sp, name_str_summary, options) &&
- NSStringSummaryProvider(*reason_sp, reason_str_summary, options) &&
- !name_str_summary.Empty() && !reason_str_summary.Empty()) {
- stream.Printf("name: %s - reason: %s", name_str_summary.GetData(),
- reason_str_summary.GetData());
+ if (NSStringSummaryProvider(*reason_sp, reason_str_summary, options) &&
+ !reason_str_summary.Empty()) {
+ stream.Printf("%s", reason_str_summary.GetData());
return true;
} else
return false;
diff --git a/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp b/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp
index 9ee6021ae56b..587dd13870a0 100644
--- a/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSIndexPath.cpp
@@ -53,9 +53,8 @@ public:
if (!type_system)
return false;
- ClangASTContext *ast = m_backend.GetExecutionContextRef()
- .GetTargetSP()
- ->GetScratchClangASTContext();
+ ClangASTContext *ast = ClangASTContext::GetScratch(
+ *m_backend.GetExecutionContextRef().GetTargetSP());
if (!ast)
return false;
diff --git a/lldb/source/Plugins/Language/ObjC/NSString.cpp b/lldb/source/Plugins/Language/ObjC/NSString.cpp
index 55e129b098dc..ce54d657374b 100644
--- a/lldb/source/Plugins/Language/ObjC/NSString.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSString.cpp
@@ -35,7 +35,7 @@ NSString_Additionals::GetAdditionalSummaries() {
static CompilerType GetNSPathStore2Type(Target &target) {
static ConstString g_type_name("__lldb_autogen_nspathstore2");
- ClangASTContext *ast_ctx = target.GetScratchClangASTContext();
+ ClangASTContext *ast_ctx = ClangASTContext::GetScratch(target);
if (!ast_ctx)
return CompilerType();
diff --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
index c5bfb5747c13..3be548ad4144 100644
--- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
+++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
@@ -15,6 +15,7 @@
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/ConstString.h"
@@ -887,7 +888,7 @@ ObjCLanguage::GetPossibleFormattersMatches(ValueObject &valobj,
bool canBeObjCDynamic =
compiler_type.IsPossibleDynamicType(nullptr, check_cpp, check_objc);
- if (canBeObjCDynamic) {
+ if (canBeObjCDynamic && ClangUtil::IsClangType(compiler_type)) {
do {
lldb::ProcessSP process_sp = valobj.GetProcessSP();
if (!process_sp)
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
index f38014505a8b..d556aae1c458 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.cpp
@@ -21,6 +21,7 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/RegisterContext.h"
@@ -28,6 +29,7 @@
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/ThreadPlanRunToAddress.h"
#include "lldb/Target/ThreadPlanStepInRange.h"
+#include "lldb/Utility/Timer.h"
using namespace lldb;
using namespace lldb_private;
@@ -58,9 +60,53 @@ bool CPPLanguageRuntime::GetObjectDescription(
return false;
}
+bool contains_lambda_identifier(llvm::StringRef &str_ref) {
+ return str_ref.contains("$_") || str_ref.contains("'lambda'");
+}
+
+CPPLanguageRuntime::LibCppStdFunctionCallableInfo
+line_entry_helper(Target &target, const SymbolContext &sc, Symbol *symbol,
+ llvm::StringRef first_template_param_sref,
+ bool has___invoke) {
+
+ CPPLanguageRuntime::LibCppStdFunctionCallableInfo optional_info;
+
+ AddressRange range;
+ sc.GetAddressRange(eSymbolContextEverything, 0, false, range);
+
+ Address address = range.GetBaseAddress();
+
+ Address addr;
+ if (target.ResolveLoadAddress(address.GetCallableLoadAddress(&target),
+ addr)) {
+ LineEntry line_entry;
+ addr.CalculateSymbolContextLineEntry(line_entry);
+
+ if (contains_lambda_identifier(first_template_param_sref) || has___invoke) {
+ // Case 1 and 2
+ optional_info.callable_case = lldb_private::CPPLanguageRuntime::
+ LibCppStdFunctionCallableCase::Lambda;
+ } else {
+ // Case 3
+ optional_info.callable_case = lldb_private::CPPLanguageRuntime::
+ LibCppStdFunctionCallableCase::CallableObject;
+ }
+
+ optional_info.callable_symbol = *symbol;
+ optional_info.callable_line_entry = line_entry;
+ optional_info.callable_address = addr;
+ }
+
+ return optional_info;
+}
+
CPPLanguageRuntime::LibCppStdFunctionCallableInfo
CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
lldb::ValueObjectSP &valobj_sp) {
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
+ "CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo");
+
LibCppStdFunctionCallableInfo optional_info;
if (!valobj_sp)
@@ -93,7 +139,7 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
// this entry and lookup operator()() and obtain the line table entry.
// 3) a callable object via operator()(). We will obtain the name of the
// object from the first template parameter from __func's vtable. We will
- // look up the objectc operator()() and obtain the line table entry.
+ // look up the objects operator()() and obtain the line table entry.
// 4) a member function. A pointer to the function will stored after the
// we will obtain the name from this pointer.
// 5) a free function. A pointer to the function will stored after the vtable
@@ -113,6 +159,9 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
optional_info.member__f_pointer_value = member__f_pointer_value;
+ if (!member__f_pointer_value)
+ return optional_info;
+
ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef());
Process *process = exe_ctx.GetProcessPtr();
@@ -130,8 +179,14 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
if (status.Fail())
return optional_info;
+ lldb::addr_t vtable_address_first_entry =
+ process->ReadPointerFromMemory(vtable_address + address_size, status);
+
+ if (status.Fail())
+ return optional_info;
+
lldb::addr_t address_after_vtable = member__f_pointer_value + address_size;
- // As commened above we may not have a function pointer but if we do we will
+ // As commented above we may not have a function pointer but if we do we will
// need it.
lldb::addr_t possible_function_address =
process->ReadPointerFromMemory(address_after_vtable, status);
@@ -144,9 +199,15 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
if (target.GetSectionLoadList().IsEmpty())
return optional_info;
+ Address vtable_first_entry_resolved;
+
+ if (!target.GetSectionLoadList().ResolveLoadAddress(
+ vtable_address_first_entry, vtable_first_entry_resolved))
+ return optional_info;
+
Address vtable_addr_resolved;
SymbolContext sc;
- Symbol *symbol;
+ Symbol *symbol = nullptr;
if (!target.GetSectionLoadList().ResolveLoadAddress(vtable_address,
vtable_addr_resolved))
@@ -159,7 +220,7 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
if (symbol == nullptr)
return optional_info;
- llvm::StringRef vtable_name(symbol->GetName().GetCString());
+ llvm::StringRef vtable_name(symbol->GetName().GetStringRef());
bool found_expected_start_string =
vtable_name.startswith("vtable for std::__1::__function::__func<");
@@ -172,6 +233,11 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
// ... __func<main::$_0, std::__1::allocator<main::$_0> ...
// ^^^^^^^^^
//
+ // We could see names such as:
+ // main::$_0
+ // Bar::add_num2(int)::'lambda'(int)
+ // Bar
+ //
// We do this by find the first < and , and extracting in between.
//
// This covers the case of the lambda known at compile time.
@@ -193,81 +259,28 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
symbol = sc.symbol;
}
- auto get_name = [&first_template_parameter, &symbol]() {
- // Given case 1:
- //
- // main::$_0
- //
- // we want to append ::operator()()
- if (first_template_parameter.contains("$_"))
- return llvm::Regex::escape(first_template_parameter.str()) +
- R"(::operator\(\)\(.*\))";
-
- if (symbol != nullptr &&
- symbol->GetName().GetStringRef().contains("__invoke")) {
-
- llvm::StringRef symbol_name = symbol->GetName().GetStringRef();
- size_t pos2 = symbol_name.find_last_of(':');
-
- // Given case 2:
- //
- // main::$_1::__invoke(...)
- //
- // We want to slice off __invoke(...) and append operator()()
- std::string lambda_operator =
- llvm::Regex::escape(symbol_name.slice(0, pos2 + 1).str()) +
- R"(operator\(\)\(.*\))";
-
- return lambda_operator;
- }
-
- // Case 3
- return first_template_parameter.str() + R"(::operator\(\)\(.*\))";
- ;
+ // These conditions are used several times to simplify statements later on.
+ bool has___invoke =
+ (symbol ? symbol->GetName().GetStringRef().contains("__invoke") : false);
+ auto calculate_symbol_context_helper = [](auto &t,
+ SymbolContextList &sc_list) {
+ SymbolContext sc;
+ t->CalculateSymbolContext(&sc);
+ sc_list.Append(sc);
};
- std::string func_to_match = get_name();
-
- SymbolContextList scl;
-
- target.GetImages().FindSymbolsMatchingRegExAndType(
- RegularExpression{R"(^)" + func_to_match}, eSymbolTypeAny, scl);
+ // Case 2
+ if (has___invoke) {
+ SymbolContextList scl;
+ calculate_symbol_context_helper(symbol, scl);
- // Case 1,2 or 3
- if (scl.GetSize() >= 1) {
- SymbolContext sc2 = scl[0];
-
- AddressRange range;
- sc2.GetAddressRange(eSymbolContextEverything, 0, false, range);
-
- Address address = range.GetBaseAddress();
-
- Address addr;
- if (target.ResolveLoadAddress(address.GetCallableLoadAddress(&target),
- addr)) {
- LineEntry line_entry;
- addr.CalculateSymbolContextLineEntry(line_entry);
-
- if (first_template_parameter.contains("$_") ||
- (symbol != nullptr &&
- symbol->GetName().GetStringRef().contains("__invoke"))) {
- // Case 1 and 2
- optional_info.callable_case = LibCppStdFunctionCallableCase::Lambda;
- } else {
- // Case 3
- optional_info.callable_case =
- LibCppStdFunctionCallableCase::CallableObject;
- }
-
- optional_info.callable_symbol = *symbol;
- optional_info.callable_line_entry = line_entry;
- optional_info.callable_address = addr;
- return optional_info;
- }
+ return line_entry_helper(target, scl[0], symbol, first_template_parameter,
+ has___invoke);
}
// Case 4 or 5
- if (symbol && !symbol->GetName().GetStringRef().startswith("vtable for")) {
+ if (symbol && !symbol->GetName().GetStringRef().startswith("vtable for") &&
+ !contains_lambda_identifier(first_template_parameter) && !has___invoke) {
optional_info.callable_case =
LibCppStdFunctionCallableCase::FreeOrMemberFunction;
optional_info.callable_address = function_address_resolved;
@@ -276,6 +289,50 @@ CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
return optional_info;
}
+ std::string func_to_match = first_template_parameter.str();
+
+ auto it = CallableLookupCache.find(func_to_match);
+ if (it != CallableLookupCache.end())
+ return it->second;
+
+ SymbolContextList scl;
+
+ CompileUnit *vtable_cu =
+ vtable_first_entry_resolved.CalculateSymbolContextCompileUnit();
+ llvm::StringRef name_to_use = func_to_match;
+
+ // Case 3, we have a callable object instead of a lambda
+ //
+ // TODO
+ // We currently don't support this case a callable object may have multiple
+ // operator()() varying on const/non-const and number of arguments and we
+ // don't have a way to currently distinguish them so we will bail out now.
+ if (!contains_lambda_identifier(name_to_use))
+ return optional_info;
+
+ if (vtable_cu && !has___invoke) {
+ lldb::FunctionSP func_sp =
+ vtable_cu->FindFunction([name_to_use](const FunctionSP &f) {
+ auto name = f->GetName().GetStringRef();
+ if (name.startswith(name_to_use) && name.contains("operator"))
+ return true;
+
+ return false;
+ });
+
+ if (func_sp) {
+ calculate_symbol_context_helper(func_sp, scl);
+ }
+ }
+
+ // Case 1 or 3
+ if (scl.GetSize() >= 1) {
+ optional_info = line_entry_helper(target, scl[0], symbol,
+ first_template_parameter, has___invoke);
+ }
+
+ CallableLookupCache[func_to_match] = optional_info;
+
return optional_info;
}
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h
index 28526361efc4..abdd79fcd7b9 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CPPLanguageRuntime.h
@@ -10,6 +10,9 @@
#define liblldb_CPPLanguageRuntime_h_
#include <vector>
+
+#include "llvm/ADT/StringMap.h"
+
#include "lldb/Core/PluginInterface.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/lldb-private.h"
@@ -82,6 +85,11 @@ protected:
CPPLanguageRuntime(Process *process);
private:
+ using OperatorStringToCallableInfoMap =
+ llvm::StringMap<CPPLanguageRuntime::LibCppStdFunctionCallableInfo>;
+
+ OperatorStringToCallableInfoMap CallableLookupCache;
+
DISALLOW_COPY_AND_ASSIGN(CPPLanguageRuntime);
};
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index 02e62a263286..9efb021caa83 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -537,7 +537,10 @@ ValueObjectSP ItaniumABILanguageRuntime::GetExceptionObjectForThread(
return {};
ClangASTContext *clang_ast_context =
- m_process->GetTarget().GetScratchClangASTContext();
+ ClangASTContext::GetScratch(m_process->GetTarget());
+ if (!clang_ast_context)
+ return {};
+
CompilerType voidstar =
clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
@@ -559,6 +562,9 @@ ValueObjectSP ItaniumABILanguageRuntime::GetExceptionObjectForThread(
modules.FindSymbolsWithNameAndType(
ConstString("__cxa_current_exception_type"), eSymbolTypeCode, contexts);
contexts.GetContextAtIndex(0, context);
+ if (!context.symbol) {
+ return {};
+ }
Address addr = context.symbol->GetAddress();
Status error;
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
index 93aa07f89165..859b693477a9 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
@@ -111,6 +111,18 @@ bool ClassDescriptorV2::class_rw_t::Read(Process *process, lldb::addr_t addr) {
m_firstSubclass = extractor.GetAddress_unchecked(&cursor);
m_nextSiblingClass = extractor.GetAddress_unchecked(&cursor);
+ if (m_ro_ptr & 1) {
+ DataBufferHeap buffer(ptr_size, '\0');
+ process->ReadMemory(m_ro_ptr ^ 1, buffer.GetBytes(), ptr_size, error);
+ if (error.Fail())
+ return false;
+ cursor = 0;
+ DataExtractor extractor(buffer.GetBytes(), ptr_size,
+ process->GetByteOrder(),
+ process->GetAddressByteSize());
+ m_ro_ptr = extractor.GetAddress_unchecked(&cursor);
+ }
+
return true;
}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
index 1f27a4f0b3ed..73843063606c 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
@@ -8,10 +8,9 @@
#include "AppleObjCDeclVendor.h"
-#include "Plugins/ExpressionParser/Clang/ASTDumper.h"
#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
#include "lldb/Core/Module.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/ClangASTMetadata.h"
#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -19,12 +18,12 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
-
+#include "clang/AST/ExternalASTSource.h"
using namespace lldb_private;
class lldb_private::AppleObjCExternalASTSource
- : public ClangExternalASTSourceCommon {
+ : public clang::ExternalASTSource {
public:
AppleObjCExternalASTSource(AppleObjCDeclVendor &decl_vendor)
: m_decl_vendor(decl_vendor) {}
@@ -77,24 +76,18 @@ public:
Log *log(GetLogIfAllCategoriesSet(
LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
- if (log) {
- LLDB_LOGF(log,
- "AppleObjCExternalASTSource::CompleteType[%u] on "
- "(ASTContext*)%p Completing (TagDecl*)%p named %s",
- current_id, static_cast<void *>(&tag_decl->getASTContext()),
- static_cast<void *>(tag_decl),
- tag_decl->getName().str().c_str());
+ LLDB_LOGF(log,
+ "AppleObjCExternalASTSource::CompleteType[%u] on "
+ "(ASTContext*)%p Completing (TagDecl*)%p named %s",
+ current_id, static_cast<void *>(&tag_decl->getASTContext()),
+ static_cast<void *>(tag_decl), tag_decl->getName().str().c_str());
- LLDB_LOGF(log, " AOEAS::CT[%u] Before:", current_id);
- ASTDumper dumper((clang::Decl *)tag_decl);
- dumper.ToLog(log, " [CT] ");
- }
+ LLDB_LOG(log, " AOEAS::CT[{0}] Before:\n{1}", current_id,
+ ClangUtil::DumpDecl(tag_decl));
+
+ LLDB_LOG(log, " AOEAS::CT[{1}] After:{1}", current_id,
+ ClangUtil::DumpDecl(tag_decl));
- if (log) {
- LLDB_LOGF(log, " AOEAS::CT[%u] After:", current_id);
- ASTDumper dumper((clang::Decl *)tag_decl);
- dumper.ToLog(log, " [CT] ");
- }
return;
}
@@ -115,16 +108,14 @@ public:
interface_decl->getName().str().c_str());
LLDB_LOGF(log, " AOEAS::CT[%u] Before:", current_id);
- ASTDumper dumper((clang::Decl *)interface_decl);
- dumper.ToLog(log, " [CT] ");
+ LLDB_LOG(log, " [CT] {0}", ClangUtil::DumpDecl(interface_decl));
}
m_decl_vendor.FinishDecl(interface_decl);
if (log) {
LLDB_LOGF(log, " [CT] After:");
- ASTDumper dumper((clang::Decl *)interface_decl);
- dumper.ToLog(log, " [CT] ");
+ LLDB_LOG(log, " [CT] {0}", ClangUtil::DumpDecl(interface_decl));
}
return;
}
@@ -141,7 +132,7 @@ public:
void StartTranslationUnit(clang::ASTConsumer *Consumer) override {
clang::TranslationUnitDecl *translation_unit_decl =
- m_decl_vendor.m_ast_ctx.getASTContext()->getTranslationUnitDecl();
+ m_decl_vendor.m_ast_ctx.getASTContext().getTranslationUnitDecl();
translation_unit_decl->setHasExternalVisibleStorage();
translation_unit_decl->setHasExternalLexicalStorage();
}
@@ -155,14 +146,12 @@ AppleObjCDeclVendor::AppleObjCDeclVendor(ObjCLanguageRuntime &runtime)
m_ast_ctx(runtime.GetProcess()
->GetTarget()
.GetArchitecture()
- .GetTriple()
- .getTriple()
- .c_str()),
+ .GetTriple()),
m_type_realizer_sp(m_runtime.GetEncodingToType()) {
m_external_source = new AppleObjCExternalASTSource(*this);
llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> external_source_owning_ptr(
m_external_source);
- m_ast_ctx.getASTContext()->setExternalSource(external_source_owning_ptr);
+ m_ast_ctx.getASTContext().setExternalSource(external_source_owning_ptr);
}
clang::ObjCInterfaceDecl *
@@ -172,7 +161,7 @@ AppleObjCDeclVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa) {
if (iter != m_isa_to_interface.end())
return iter->second;
- clang::ASTContext *ast_ctx = m_ast_ctx.getASTContext();
+ clang::ASTContext &ast_ctx = m_ast_ctx.getASTContext();
ObjCLanguageRuntime::ClassDescriptorSP descriptor =
m_runtime.GetClassDescriptorFromISA(isa);
@@ -183,20 +172,20 @@ AppleObjCDeclVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa) {
ConstString name(descriptor->GetClassName());
clang::IdentifierInfo &identifier_info =
- ast_ctx->Idents.get(name.GetStringRef());
+ ast_ctx.Idents.get(name.GetStringRef());
clang::ObjCInterfaceDecl *new_iface_decl = clang::ObjCInterfaceDecl::Create(
- *ast_ctx, ast_ctx->getTranslationUnitDecl(), clang::SourceLocation(),
+ ast_ctx, ast_ctx.getTranslationUnitDecl(), clang::SourceLocation(),
&identifier_info, nullptr, nullptr);
ClangASTMetadata meta_data;
meta_data.SetISAPtr(isa);
- m_external_source->SetMetadata(new_iface_decl, meta_data);
+ m_ast_ctx.SetMetadata(new_iface_decl, meta_data);
new_iface_decl->setHasExternalVisibleStorage();
new_iface_decl->setHasExternalLexicalStorage();
- ast_ctx->getTranslationUnitDecl()->addDecl(new_iface_decl);
+ ast_ctx.getTranslationUnitDecl()->addDecl(new_iface_decl);
m_isa_to_interface[isa] = new_iface_decl;
@@ -320,7 +309,8 @@ public:
}
clang::ObjCMethodDecl *
- BuildMethod(clang::ObjCInterfaceDecl *interface_decl, const char *name,
+ BuildMethod(ClangASTContext &clang_ast_ctxt,
+ clang::ObjCInterfaceDecl *interface_decl, const char *name,
bool instance,
ObjCLanguageRuntime::EncodingToTypeSP type_realizer_sp) {
if (!m_is_valid || m_type_vector.size() < 3)
@@ -330,7 +320,8 @@ public:
const bool isInstance = instance;
const bool isVariadic = false;
- const bool isSynthesized = false;
+ const bool isPropertyAccessor = false;
+ const bool isSynthesizedAccessorStub = false;
const bool isImplicitlyDeclared = true;
const bool isDefined = false;
const clang::ObjCMethodDecl::ImplementationControl impControl =
@@ -368,8 +359,7 @@ public:
clang::QualType ret_type =
ClangUtil::GetQualType(type_realizer_sp->RealizeType(
- interface_decl->getASTContext(), m_type_vector[0].c_str(),
- for_expression));
+ clang_ast_ctxt, m_type_vector[0].c_str(), for_expression));
if (ret_type.isNull())
return nullptr;
@@ -377,8 +367,8 @@ public:
clang::ObjCMethodDecl *ret = clang::ObjCMethodDecl::Create(
ast_ctx, clang::SourceLocation(), clang::SourceLocation(), sel,
ret_type, nullptr, interface_decl, isInstance, isVariadic,
- isSynthesized, isImplicitlyDeclared, isDefined, impControl,
- HasRelatedResultType);
+ isPropertyAccessor, isSynthesizedAccessorStub, isImplicitlyDeclared,
+ isDefined, impControl, HasRelatedResultType);
std::vector<clang::ParmVarDecl *> parm_vars;
@@ -386,7 +376,7 @@ public:
const bool for_expression = true;
clang::QualType arg_type =
ClangUtil::GetQualType(type_realizer_sp->RealizeType(
- ast_ctx, m_type_vector[ai].c_str(), for_expression));
+ clang_ast_ctxt, m_type_vector[ai].c_str(), for_expression));
if (arg_type.isNull())
return nullptr; // well, we just wasted a bunch of time. Wish we could
@@ -421,7 +411,7 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) {
Log *log(GetLogIfAllCategoriesSet(
LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
- ClangASTMetadata *metadata = m_external_source->GetMetadata(interface_decl);
+ ClangASTMetadata *metadata = m_ast_ctx.GetMetadata(interface_decl);
ObjCLanguageRuntime::ObjCISA objc_isa = 0;
if (metadata)
objc_isa = metadata->GetISAPtr();
@@ -451,9 +441,9 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) {
return;
FinishDecl(superclass_decl);
- clang::ASTContext *context = m_ast_ctx.getASTContext();
- interface_decl->setSuperClass(context->getTrivialTypeSourceInfo(
- context->getObjCInterfaceType(superclass_decl)));
+ clang::ASTContext &context = m_ast_ctx.getASTContext();
+ interface_decl->setSuperClass(context.getTrivialTypeSourceInfo(
+ context.getObjCInterfaceType(superclass_decl)));
};
auto instance_method_func =
@@ -463,8 +453,8 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) {
ObjCRuntimeMethodType method_type(types);
- clang::ObjCMethodDecl *method_decl =
- method_type.BuildMethod(interface_decl, name, true, m_type_realizer_sp);
+ clang::ObjCMethodDecl *method_decl = method_type.BuildMethod(
+ m_ast_ctx, interface_decl, name, true, m_type_realizer_sp);
LLDB_LOGF(log, "[ AOTV::FD] Instance method [%s] [%s]", name, types);
@@ -482,7 +472,7 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) {
ObjCRuntimeMethodType method_type(types);
clang::ObjCMethodDecl *method_decl = method_type.BuildMethod(
- interface_decl, name, false, m_type_realizer_sp);
+ m_ast_ctx, interface_decl, name, false, m_type_realizer_sp);
LLDB_LOGF(log, "[ AOTV::FD] Class method [%s] [%s]", name, types);
@@ -511,8 +501,8 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) {
clang::TypeSourceInfo *const type_source_info = nullptr;
const bool is_synthesized = false;
clang::ObjCIvarDecl *ivar_decl = clang::ObjCIvarDecl::Create(
- *m_ast_ctx.getASTContext(), interface_decl, clang::SourceLocation(),
- clang::SourceLocation(), &m_ast_ctx.getASTContext()->Idents.get(name),
+ m_ast_ctx.getASTContext(), interface_decl, clang::SourceLocation(),
+ clang::SourceLocation(), &m_ast_ctx.getASTContext().Idents.get(name),
ClangUtil::GetQualType(ivar_type),
type_source_info, // TypeSourceInfo *
clang::ObjCIvarDecl::Public, nullptr, is_synthesized);
@@ -525,36 +515,29 @@ bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) {
return false;
};
- if (log) {
- ASTDumper method_dumper((clang::Decl *)interface_decl);
-
- LLDB_LOGF(log,
- "[AppleObjCDeclVendor::FinishDecl] Finishing Objective-C "
- "interface for %s",
- descriptor->GetClassName().AsCString());
- }
+ LLDB_LOG(log,
+ "[AppleObjCDeclVendor::FinishDecl] Finishing Objective-C "
+ "interface for %s",
+ descriptor->GetClassName().AsCString());
if (!descriptor->Describe(superclass_func, instance_method_func,
class_method_func, ivar_func))
return false;
if (log) {
- ASTDumper method_dumper((clang::Decl *)interface_decl);
-
LLDB_LOGF(
log,
"[AppleObjCDeclVendor::FinishDecl] Finished Objective-C interface");
- method_dumper.ToLog(log, " [AOTV::FD] ");
+ LLDB_LOG(log, " [AOTV::FD] {0}", ClangUtil::DumpDecl(interface_decl));
}
return true;
}
-uint32_t
-AppleObjCDeclVendor::FindDecls(ConstString name, bool append,
- uint32_t max_matches,
- std::vector<clang::NamedDecl *> &decls) {
+uint32_t AppleObjCDeclVendor::FindDecls(ConstString name, bool append,
+ uint32_t max_matches,
+ std::vector<CompilerDecl> &decls) {
static unsigned int invocation_id = 0;
unsigned int current_id = invocation_id++;
@@ -573,37 +556,35 @@ AppleObjCDeclVendor::FindDecls(ConstString name, bool append,
do {
// See if the type is already in our ASTContext.
- clang::ASTContext *ast_ctx = m_ast_ctx.getASTContext();
+ clang::ASTContext &ast_ctx = m_ast_ctx.getASTContext();
clang::IdentifierInfo &identifier_info =
- ast_ctx->Idents.get(name.GetStringRef());
+ ast_ctx.Idents.get(name.GetStringRef());
clang::DeclarationName decl_name =
- ast_ctx->DeclarationNames.getIdentifier(&identifier_info);
+ ast_ctx.DeclarationNames.getIdentifier(&identifier_info);
clang::DeclContext::lookup_result lookup_result =
- ast_ctx->getTranslationUnitDecl()->lookup(decl_name);
+ ast_ctx.getTranslationUnitDecl()->lookup(decl_name);
if (!lookup_result.empty()) {
if (clang::ObjCInterfaceDecl *result_iface_decl =
llvm::dyn_cast<clang::ObjCInterfaceDecl>(lookup_result[0])) {
if (log) {
clang::QualType result_iface_type =
- ast_ctx->getObjCInterfaceType(result_iface_decl);
- ASTDumper dumper(result_iface_type);
+ ast_ctx.getObjCInterfaceType(result_iface_decl);
uint64_t isa_value = LLDB_INVALID_ADDRESS;
- ClangASTMetadata *metadata =
- m_external_source->GetMetadata(result_iface_decl);
+ ClangASTMetadata *metadata = m_ast_ctx.GetMetadata(result_iface_decl);
if (metadata)
isa_value = metadata->GetISAPtr();
- LLDB_LOGF(log,
- "AOCTV::FT [%u] Found %s (isa 0x%" PRIx64
- ") in the ASTContext",
- current_id, dumper.GetCString(), isa_value);
+ LLDB_LOG(log,
+ "AOCTV::FT [%u] Found %s (isa 0x%" PRIx64
+ ") in the ASTContext",
+ current_id, result_iface_type.getAsString(), isa_value);
}
- decls.push_back(result_iface_decl);
+ decls.push_back(CompilerDecl(&m_ast_ctx, result_iface_decl));
ret++;
break;
} else {
@@ -640,24 +621,16 @@ AppleObjCDeclVendor::FindDecls(ConstString name, bool append,
}
if (log) {
- clang::QualType new_iface_type =
- ast_ctx->getObjCInterfaceType(iface_decl);
- ASTDumper dumper(new_iface_type);
- LLDB_LOGF(log, "AOCTV::FT [%u] Created %s (isa 0x%" PRIx64 ")",
- current_id, dumper.GetCString(), (uint64_t)isa);
+ clang::QualType new_iface_type = ast_ctx.getObjCInterfaceType(iface_decl);
+
+ LLDB_LOG(log, "AOCTV::FT [{0}] Created {1} (isa 0x{2:x})", current_id,
+ new_iface_type.getAsString(), (uint64_t)isa);
}
- decls.push_back(iface_decl);
+ decls.push_back(CompilerDecl(&m_ast_ctx, iface_decl));
ret++;
break;
} while (false);
return ret;
}
-
-clang::ExternalASTMerger::ImporterSource
-AppleObjCDeclVendor::GetImporterSource() {
- return clang::ExternalASTMerger::ImporterSource(*m_ast_ctx.getASTContext(),
- *m_ast_ctx.getFileManager(),
- m_ast_ctx.GetOriginMap());
-}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h
index 99ca4b748709..f49ca3540c2c 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h
@@ -28,9 +28,7 @@ public:
}
uint32_t FindDecls(ConstString name, bool append, uint32_t max_matches,
- std::vector<clang::NamedDecl *> &decls) override;
-
- clang::ExternalASTMerger::ImporterSource GetImporterSource() override;
+ std::vector<CompilerDecl> &decls) override;
friend class AppleObjCExternalASTSource;
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
index 8ca9ad7b843a..7076959bee97 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
@@ -111,7 +111,10 @@ bool AppleObjCRuntime::GetObjectDescription(Stream &strm, Value &value,
}
} else {
// If it is not a pointer, see if we can make it into a pointer.
- ClangASTContext *ast_context = target->GetScratchClangASTContext();
+ ClangASTContext *ast_context = ClangASTContext::GetScratch(*target);
+ if (!ast_context)
+ return false;
+
CompilerType opaque_type = ast_context->GetBasicType(eBasicTypeObjCID);
if (!opaque_type)
opaque_type = ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
@@ -123,7 +126,9 @@ bool AppleObjCRuntime::GetObjectDescription(Stream &strm, Value &value,
arg_value_list.PushValue(value);
// This is the return value:
- ClangASTContext *ast_context = target->GetScratchClangASTContext();
+ ClangASTContext *ast_context = ClangASTContext::GetScratch(*target);
+ if (!ast_context)
+ return false;
CompilerType return_compiler_type = ast_context->GetCStringType(true);
Value ret;
@@ -494,9 +499,12 @@ ThreadSP AppleObjCRuntime::GetBacktraceThreadFromException(
reserved_dict = reserved_dict->GetSyntheticValue();
if (!reserved_dict) return ThreadSP();
+ ClangASTContext *clang_ast_context =
+ ClangASTContext::GetScratch(*exception_sp->GetTargetSP());
+ if (!clang_ast_context)
+ return ThreadSP();
CompilerType objc_id =
- exception_sp->GetTargetSP()->GetScratchClangASTContext()->GetBasicType(
- lldb::eBasicTypeObjCID);
+ clang_ast_context->GetBasicType(lldb::eBasicTypeObjCID);
ValueObjectSP return_addresses;
auto objc_object_from_address = [&exception_sp, &objc_id](uint64_t addr,
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index 9bdbef393e39..4015f10c4966 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -1301,7 +1301,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
return DescriptorMapUpdateResult::Fail();
thread_sp->CalculateExecutionContext(exe_ctx);
- ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
+ ClangASTContext *ast = ClangASTContext::GetScratch(process->GetTarget());
if (!ast)
return DescriptorMapUpdateResult::Fail();
@@ -1563,7 +1563,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
return DescriptorMapUpdateResult::Fail();
thread_sp->CalculateExecutionContext(exe_ctx);
- ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
+ ClangASTContext *ast = ClangASTContext::GetScratch(process->GetTarget());
if (!ast)
return DescriptorMapUpdateResult::Fail();
@@ -1625,19 +1625,13 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
// Substitute in the correct class_getName / class_getNameRaw function name,
// concatenate the two parts of our expression text. The format string
// has two %s's, so provide the name twice.
- int prefix_string_size = snprintf (nullptr, 0,
+ std::string shared_class_expression;
+ llvm::raw_string_ostream(shared_class_expression) << llvm::format(
g_shared_cache_class_name_funcptr,
class_name_getter_function_name.AsCString(),
class_name_getter_function_name.AsCString());
- char *class_name_func_ptr_expr = (char*) malloc (prefix_string_size + 1);
- snprintf (class_name_func_ptr_expr, prefix_string_size + 1,
- g_shared_cache_class_name_funcptr,
- class_name_getter_function_name.AsCString(),
- class_name_getter_function_name.AsCString());
- std::string shared_class_expression = class_name_func_ptr_expr;
shared_class_expression += g_get_shared_cache_class_info_body;
- free (class_name_func_ptr_expr);
m_get_shared_cache_class_info_code.reset(
GetTargetRef().GetUtilityFunctionForLanguage(
@@ -1984,36 +1978,6 @@ void AppleObjCRuntimeV2::WarnIfNoClassesCached(
}
}
-ConstString
-AppleObjCRuntimeV2::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa) {
- if (isa == g_objc_Tagged_ISA) {
- static const ConstString g_objc_tagged_isa_name("_lldb_Tagged_ObjC_ISA");
- return g_objc_tagged_isa_name;
- }
- if (isa == g_objc_Tagged_ISA_NSAtom) {
- static const ConstString g_objc_tagged_isa_nsatom_name("NSAtom");
- return g_objc_tagged_isa_nsatom_name;
- }
- if (isa == g_objc_Tagged_ISA_NSNumber) {
- static const ConstString g_objc_tagged_isa_nsnumber_name("NSNumber");
- return g_objc_tagged_isa_nsnumber_name;
- }
- if (isa == g_objc_Tagged_ISA_NSDateTS) {
- static const ConstString g_objc_tagged_isa_nsdatets_name("NSDateTS");
- return g_objc_tagged_isa_nsdatets_name;
- }
- if (isa == g_objc_Tagged_ISA_NSManagedObject) {
- static const ConstString g_objc_tagged_isa_nsmanagedobject_name(
- "NSManagedObject");
- return g_objc_tagged_isa_nsmanagedobject_name;
- }
- if (isa == g_objc_Tagged_ISA_NSDate) {
- static const ConstString g_objc_tagged_isa_nsdate_name("NSDate");
- return g_objc_tagged_isa_nsdate_name;
- }
- return ObjCLanguageRuntime::GetActualTypeName(isa);
-}
-
DeclVendor *AppleObjCRuntimeV2::GetDeclVendor() {
if (!m_decl_vendor_up)
m_decl_vendor_up.reset(new AppleObjCDeclVendor(*this));
@@ -2678,10 +2642,12 @@ class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame {
const lldb::ABISP &abi = process_sp->GetABI();
if (!abi) return;
- CompilerType voidstar = process_sp->GetTarget()
- .GetScratchClangASTContext()
- ->GetBasicType(lldb::eBasicTypeVoid)
- .GetPointerType();
+ ClangASTContext *clang_ast_context =
+ ClangASTContext::GetScratch(process_sp->GetTarget());
+ if (!clang_ast_context)
+ return;
+ CompilerType voidstar =
+ clang_ast_context->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
ValueList args;
Value input_value;
@@ -2699,7 +2665,7 @@ class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame {
exception = ValueObjectRecognizerSynthesizedValue::Create(
*exception, eValueTypeVariableArgument);
exception = exception->GetDynamicValue(eDynamicDontRunTarget);
-
+
m_arguments = ValueObjectListSP(new ValueObjectList());
m_arguments->Append(exception);
}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
index a0fd39dc03b2..785bb3938d2c 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
@@ -69,8 +69,6 @@ public:
void UpdateISAToDescriptorMapIfNeeded() override;
- ConstString GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa) override;
-
ClassDescriptorSP GetClassDescriptor(ValueObject &in_value) override;
ClassDescriptorSP GetClassDescriptorFromISA(ObjCISA isa) override;
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
index 379ef3dca86c..36f95c063b81 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
@@ -522,7 +522,10 @@ bool AppleObjCTrampolineHandler::AppleObjCVTables::RefreshTrampolines(
const ABI *abi = process->GetABI().get();
ClangASTContext *clang_ast_context =
- process->GetTarget().GetScratchClangASTContext();
+ ClangASTContext::GetScratch(process->GetTarget());
+ if (!clang_ast_context)
+ return false;
+
ValueList argument_values;
Value input_value;
CompilerType clang_void_ptr_type =
@@ -802,7 +805,10 @@ AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread,
// Next make the runner function for our implementation utility function.
ClangASTContext *clang_ast_context =
- thread.GetProcess()->GetTarget().GetScratchClangASTContext();
+ ClangASTContext::GetScratch(thread.GetProcess()->GetTarget());
+ if (!clang_ast_context)
+ return LLDB_INVALID_ADDRESS;
+
CompilerType clang_void_ptr_type =
clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
Status error;
@@ -895,7 +901,10 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan(Thread &thread,
TargetSP target_sp(thread.CalculateTarget());
- ClangASTContext *clang_ast_context = target_sp->GetScratchClangASTContext();
+ ClangASTContext *clang_ast_context = ClangASTContext::GetScratch(*target_sp);
+ if (!clang_ast_context)
+ return ret_plan_sp;
+
ValueList argument_values;
Value void_ptr_value;
CompilerType clang_void_ptr_type =
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
index 6402e80d6f98..66f04bef6cbd 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp
@@ -26,9 +26,7 @@ AppleObjCTypeEncodingParser::AppleObjCTypeEncodingParser(
m_scratch_ast_ctx_up.reset(new ClangASTContext(runtime.GetProcess()
->GetTarget()
.GetArchitecture()
- .GetTriple()
- .str()
- .c_str()));
+ .GetTriple()));
}
std::string AppleObjCTypeEncodingParser::ReadStructName(StringLexer &type) {
@@ -63,7 +61,7 @@ AppleObjCTypeEncodingParser::StructElement::StructElement()
: name(""), type(clang::QualType()), bitfield(0) {}
AppleObjCTypeEncodingParser::StructElement
-AppleObjCTypeEncodingParser::ReadStructElement(clang::ASTContext &ast_ctx,
+AppleObjCTypeEncodingParser::ReadStructElement(ClangASTContext &ast_ctx,
StringLexer &type,
bool for_expression) {
StructElement retval;
@@ -78,19 +76,19 @@ AppleObjCTypeEncodingParser::ReadStructElement(clang::ASTContext &ast_ctx,
}
clang::QualType AppleObjCTypeEncodingParser::BuildStruct(
- clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression) {
+ ClangASTContext &ast_ctx, StringLexer &type, bool for_expression) {
return BuildAggregate(ast_ctx, type, for_expression, '{', '}',
clang::TTK_Struct);
}
clang::QualType AppleObjCTypeEncodingParser::BuildUnion(
- clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression) {
+ ClangASTContext &ast_ctx, StringLexer &type, bool for_expression) {
return BuildAggregate(ast_ctx, type, for_expression, '(', ')',
clang::TTK_Union);
}
clang::QualType AppleObjCTypeEncodingParser::BuildAggregate(
- clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression,
+ ClangASTContext &ast_ctx, StringLexer &type, bool for_expression,
char opener, char closer, uint32_t kind) {
if (!type.NextIf(opener))
return clang::QualType();
@@ -124,11 +122,8 @@ clang::QualType AppleObjCTypeEncodingParser::BuildAggregate(
if (is_templated)
return clang::QualType(); // This is where we bail out. Sorry!
- ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
- if (!lldb_ctx)
- return clang::QualType();
- CompilerType union_type(lldb_ctx->CreateRecordType(
- nullptr, lldb::eAccessPublic, name.c_str(), kind, lldb::eLanguageTypeC));
+ CompilerType union_type(ast_ctx.CreateRecordType(
+ nullptr, lldb::eAccessPublic, name, kind, lldb::eLanguageTypeC));
if (union_type) {
ClangASTContext::StartTagDeclarationDefinition(union_type);
@@ -140,9 +135,7 @@ clang::QualType AppleObjCTypeEncodingParser::BuildAggregate(
element.name = elem_name.GetString();
}
ClangASTContext::AddFieldToRecordType(
- union_type, element.name.c_str(),
- CompilerType(ClangASTContext::GetASTContext(&ast_ctx),
- element.type.getAsOpaquePtr()),
+ union_type, element.name.c_str(), ast_ctx.GetType(element.type),
lldb::eAccessPublic, element.bitfield);
++count;
}
@@ -152,20 +145,15 @@ clang::QualType AppleObjCTypeEncodingParser::BuildAggregate(
}
clang::QualType AppleObjCTypeEncodingParser::BuildArray(
- clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression) {
+ ClangASTContext &ast_ctx, StringLexer &type, bool for_expression) {
if (!type.NextIf('['))
return clang::QualType();
uint32_t size = ReadNumber(type);
clang::QualType element_type(BuildType(ast_ctx, type, for_expression));
if (!type.NextIf(']'))
return clang::QualType();
- ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
- if (!lldb_ctx)
- return clang::QualType();
- CompilerType array_type(lldb_ctx->CreateArrayType(
- CompilerType(ClangASTContext::GetASTContext(&ast_ctx),
- element_type.getAsOpaquePtr()),
- size, false));
+ CompilerType array_type(ast_ctx.CreateArrayType(
+ CompilerType(&ast_ctx, element_type.getAsOpaquePtr()), size, false));
return ClangUtil::GetQualType(array_type);
}
@@ -175,10 +163,12 @@ clang::QualType AppleObjCTypeEncodingParser::BuildArray(
// consume but ignore the type info and always return an 'id'; if anything,
// dynamic typing will resolve things for us anyway
clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType(
- clang::ASTContext &ast_ctx, StringLexer &type, bool for_expression) {
+ ClangASTContext &clang_ast_ctx, StringLexer &type, bool for_expression) {
if (!type.NextIf('@'))
return clang::QualType();
+ clang::ASTContext &ast_ctx = clang_ast_ctx.getASTContext();
+
std::string name;
if (type.NextIf('"')) {
@@ -257,23 +247,25 @@ clang::QualType AppleObjCTypeEncodingParser::BuildObjCObjectPointerType(
}
clang::QualType
-AppleObjCTypeEncodingParser::BuildType(clang::ASTContext &ast_ctx,
+AppleObjCTypeEncodingParser::BuildType(ClangASTContext &clang_ast_ctx,
StringLexer &type, bool for_expression,
uint32_t *bitfield_bit_size) {
if (!type.HasAtLeast(1))
return clang::QualType();
+ clang::ASTContext &ast_ctx = clang_ast_ctx.getASTContext();
+
switch (type.Peek()) {
default:
break;
case '{':
- return BuildStruct(ast_ctx, type, for_expression);
+ return BuildStruct(clang_ast_ctx, type, for_expression);
case '[':
- return BuildArray(ast_ctx, type, for_expression);
+ return BuildArray(clang_ast_ctx, type, for_expression);
case '(':
- return BuildUnion(ast_ctx, type, for_expression);
+ return BuildUnion(clang_ast_ctx, type, for_expression);
case '@':
- return BuildObjCObjectPointerType(ast_ctx, type, for_expression);
+ return BuildObjCObjectPointerType(clang_ast_ctx, type, for_expression);
}
switch (type.Next()) {
@@ -289,10 +281,7 @@ AppleObjCTypeEncodingParser::BuildType(clang::ASTContext &ast_ctx,
case 'l':
return ast_ctx.getIntTypeForBitwidth(32, true);
// this used to be done like this:
- // ClangASTContext *lldb_ctx = ClangASTContext::GetASTContext(&ast_ctx);
- // if (!lldb_ctx)
- // return clang::QualType();
- // return lldb_ctx->GetIntTypeFromBitSize(32, true).GetQualType();
+ // return clang_ast_ctx->GetIntTypeFromBitSize(32, true).GetQualType();
// which uses one of the constants if one is available, but we don't think
// all this work is necessary.
case 'q':
@@ -331,7 +320,8 @@ AppleObjCTypeEncodingParser::BuildType(clang::ASTContext &ast_ctx,
return clang::QualType();
}
case 'r': {
- clang::QualType target_type = BuildType(ast_ctx, type, for_expression);
+ clang::QualType target_type =
+ BuildType(clang_ast_ctx, type, for_expression);
if (target_type.isNull())
return clang::QualType();
else if (target_type == ast_ctx.UnknownAnyTy)
@@ -348,7 +338,8 @@ AppleObjCTypeEncodingParser::BuildType(clang::ASTContext &ast_ctx,
// practical cases
return ast_ctx.VoidPtrTy;
} else {
- clang::QualType target_type = BuildType(ast_ctx, type, for_expression);
+ clang::QualType target_type =
+ BuildType(clang_ast_ctx, type, for_expression);
if (target_type.isNull())
return clang::QualType();
else if (target_type == ast_ctx.UnknownAnyTy)
@@ -362,13 +353,13 @@ AppleObjCTypeEncodingParser::BuildType(clang::ASTContext &ast_ctx,
}
}
-CompilerType AppleObjCTypeEncodingParser::RealizeType(
- clang::ASTContext &ast_ctx, const char *name, bool for_expression) {
+CompilerType AppleObjCTypeEncodingParser::RealizeType(ClangASTContext &ast_ctx,
+ const char *name,
+ bool for_expression) {
if (name && name[0]) {
StringLexer lexer(name);
clang::QualType qual_type = BuildType(ast_ctx, lexer, for_expression);
- return CompilerType(ClangASTContext::GetASTContext(&ast_ctx),
- qual_type.getAsOpaquePtr());
+ return ast_ctx.GetType(qual_type);
}
return CompilerType();
}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
index 590bc4ba9eae..e43711bf4ee4 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
@@ -22,7 +22,7 @@ public:
AppleObjCTypeEncodingParser(ObjCLanguageRuntime &runtime);
~AppleObjCTypeEncodingParser() override = default;
- CompilerType RealizeType(clang::ASTContext &ast_ctx, const char *name,
+ CompilerType RealizeType(ClangASTContext &ast_ctx, const char *name,
bool for_expression) override;
private:
@@ -35,29 +35,29 @@ private:
~StructElement() = default;
};
- clang::QualType BuildType(clang::ASTContext &ast_ctx, StringLexer &type,
+ clang::QualType BuildType(ClangASTContext &clang_ast_ctx, StringLexer &type,
bool for_expression,
uint32_t *bitfield_bit_size = nullptr);
- clang::QualType BuildStruct(clang::ASTContext &ast_ctx, StringLexer &type,
+ clang::QualType BuildStruct(ClangASTContext &ast_ctx, StringLexer &type,
bool for_expression);
- clang::QualType BuildAggregate(clang::ASTContext &ast_ctx, StringLexer &type,
- bool for_expression, char opener, char closer,
- uint32_t kind);
+ clang::QualType BuildAggregate(ClangASTContext &clang_ast_ctx,
+ StringLexer &type, bool for_expression,
+ char opener, char closer, uint32_t kind);
- clang::QualType BuildUnion(clang::ASTContext &ast_ctx, StringLexer &type,
+ clang::QualType BuildUnion(ClangASTContext &ast_ctx, StringLexer &type,
bool for_expression);
- clang::QualType BuildArray(clang::ASTContext &ast_ctx, StringLexer &type,
+ clang::QualType BuildArray(ClangASTContext &ast_ctx, StringLexer &type,
bool for_expression);
std::string ReadStructName(StringLexer &type);
- StructElement ReadStructElement(clang::ASTContext &ast_ctx, StringLexer &type,
+ StructElement ReadStructElement(ClangASTContext &ast_ctx, StringLexer &type,
bool for_expression);
- clang::QualType BuildObjCObjectPointerType(clang::ASTContext &ast_ctx,
+ clang::QualType BuildObjCObjectPointerType(ClangASTContext &clang_ast_ctx,
StringLexer &type,
bool for_expression);
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp
index 87ae4c2c6c48..9eb493f83c84 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp
@@ -222,14 +222,6 @@ ObjCLanguageRuntime::GetParentClass(ObjCLanguageRuntime::ObjCISA isa) {
return 0;
}
-ConstString
-ObjCLanguageRuntime::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa) {
- ClassDescriptorSP objc_class_sp(GetNonKVOClassDescriptor(isa));
- if (objc_class_sp)
- return objc_class_sp->GetClassName();
- return ConstString();
-}
-
ObjCLanguageRuntime::ClassDescriptorSP
ObjCLanguageRuntime::GetClassDescriptorFromClassName(
ConstString class_name) {
@@ -313,14 +305,6 @@ ObjCLanguageRuntime::EncodingToType::RealizeType(const char *name,
return CompilerType();
}
-CompilerType ObjCLanguageRuntime::EncodingToType::RealizeType(
- ClangASTContext &ast_ctx, const char *name, bool for_expression) {
- clang::ASTContext *clang_ast = ast_ctx.getASTContext();
- if (!clang_ast)
- return CompilerType();
- return RealizeType(*clang_ast, name, for_expression);
-}
-
ObjCLanguageRuntime::EncodingToType::~EncodingToType() {}
ObjCLanguageRuntime::EncodingToTypeSP ObjCLanguageRuntime::GetEncodingToType() {
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h
index 39acd6e9f268..b9a4d5dae08a 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h
@@ -145,12 +145,9 @@ public:
virtual ~EncodingToType();
virtual CompilerType RealizeType(ClangASTContext &ast_ctx, const char *name,
- bool for_expression);
+ bool for_expression) = 0;
virtual CompilerType RealizeType(const char *name, bool for_expression);
- virtual CompilerType RealizeType(clang::ASTContext &ast_ctx,
- const char *name, bool for_expression) = 0;
-
protected:
std::unique_ptr<ClangASTContext> m_scratch_ast_ctx_up;
};
@@ -274,8 +271,6 @@ public:
virtual ObjCISA GetISA(ConstString name);
- virtual ConstString GetActualTypeName(ObjCISA isa);
-
virtual ObjCISA GetParentClass(ObjCISA isa);
// Finds the byte offset of the child_type ivar in parent_type. If it can't
diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
index 5200749d759f..4edb8dec6082 100644
--- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
@@ -2240,8 +2240,7 @@ void RenderScriptRuntime::FindStructTypeName(Element &elem,
// Iterate over all the global variables looking for one with a matching type
// to the Element. We make the assumption a match exists since there needs to
// be a global variable to reflect the struct type back into java host code.
- for (uint32_t i = 0; i < var_list.GetSize(); ++i) {
- const VariableSP var_sp(var_list.GetVariableAtIndex(i));
+ for (const VariableSP &var_sp : var_list) {
if (!var_sp)
continue;
@@ -3892,7 +3891,7 @@ void RSModuleDescriptor::Dump(Stream &strm) const {
int indent = strm.GetIndentLevel();
strm.Indent();
- m_module->GetFileSpec().Dump(&strm);
+ m_module->GetFileSpec().Dump(strm.AsRawOstream());
strm.Indent(m_module->GetNumCompileUnits() ? "Debug info loaded."
: "Debug info does not exist.");
strm.EOL();
diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
index a6d225d2fbd8..4ddff3ad9c4c 100644
--- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
@@ -72,7 +72,7 @@ bool isRSAllocationTyCallSite(llvm::Module &module, llvm::CallInst *call_inst) {
(void)module;
if (!call_inst->hasByValArgument())
return false;
- for (const auto &param : call_inst->operand_values())
+ for (const auto *param : call_inst->operand_values())
if (isRSAllocationPtrTy(param->getType()))
return true;
return false;
diff --git a/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp b/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp
index de17d986a860..b83b2efb492f 100644
--- a/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp
+++ b/lldb/source/Plugins/ObjectFile/Breakpad/BreakpadRecords.cpp
@@ -72,7 +72,7 @@ llvm::Triple::ArchType stringTo<llvm::Triple::ArchType>(llvm::StringRef Str) {
.Case("sparc", Triple::sparc)
.Case("sparcv9", Triple::sparcv9)
.Case("x86", Triple::x86)
- .Case("x86_64", Triple::x86_64)
+ .Cases("x86_64", "x86_64h", Triple::x86_64)
.Default(Triple::UnknownArch);
}
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 3f8502548fc2..8b62afa18cd6 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -1572,8 +1572,10 @@ static SectionType GetSectionTypeFromName(llvm::StringRef Name) {
.Case("info.dwo", eSectionTypeDWARFDebugInfoDwo)
.Cases("line", "line.dwo", eSectionTypeDWARFDebugLine)
.Cases("line_str", "line_str.dwo", eSectionTypeDWARFDebugLineStr)
- .Cases("loc", "loc.dwo", eSectionTypeDWARFDebugLoc)
- .Cases("loclists", "loclists.dwo", eSectionTypeDWARFDebugLocLists)
+ .Case("loc", eSectionTypeDWARFDebugLoc)
+ .Case("loc.dwo", eSectionTypeDWARFDebugLocDwo)
+ .Case("loclists", eSectionTypeDWARFDebugLocLists)
+ .Case("loclists.dwo", eSectionTypeDWARFDebugLocListsDwo)
.Case("macinfo", eSectionTypeDWARFDebugMacInfo)
.Cases("macro", "macro.dwo", eSectionTypeDWARFDebugMacro)
.Case("names", eSectionTypeDWARFDebugNames)
@@ -1581,6 +1583,7 @@ static SectionType GetSectionTypeFromName(llvm::StringRef Name) {
.Case("pubtypes", eSectionTypeDWARFDebugPubTypes)
.Case("ranges", eSectionTypeDWARFDebugRanges)
.Case("rnglists", eSectionTypeDWARFDebugRngLists)
+ .Case("rnglists.dwo", eSectionTypeDWARFDebugRngListsDwo)
.Case("str", eSectionTypeDWARFDebugStr)
.Case("str.dwo", eSectionTypeDWARFDebugStrDwo)
.Case("str_offsets", eSectionTypeDWARFDebugStrOffsets)
@@ -2257,6 +2260,8 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
symbol_size_valid, // Symbol size is valid
has_suffix, // Contains linker annotations?
flags); // Symbol flags.
+ if (symbol.getBinding() == STB_WEAK)
+ dc_symbol.SetIsWeak(true);
symtab->AddSymbol(dc_symbol);
}
return i;
diff --git a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
index b777a5319104..b04ac61c99a1 100644
--- a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+++ b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -6,7 +6,9 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLDB_DISABLE_PYTHON
+#include "lldb/Host/Config.h"
+
+#if LLDB_ENABLE_PYTHON
#include "OperatingSystemPython.h"
@@ -88,13 +90,12 @@ OperatingSystemPython::OperatingSystemPython(lldb_private::Process *process,
python_module_path.GetFilename().AsCString(""));
if (!os_plugin_class_name.empty()) {
const bool init_session = false;
- const bool allow_reload = true;
char python_module_path_cstr[PATH_MAX];
python_module_path.GetPath(python_module_path_cstr,
sizeof(python_module_path_cstr));
Status error;
- if (m_interpreter->LoadScriptingModule(
- python_module_path_cstr, allow_reload, init_session, error)) {
+ if (m_interpreter->LoadScriptingModule(python_module_path_cstr,
+ init_session, error)) {
// Strip the ".py" extension if there is one
size_t py_extension_pos = os_plugin_class_name.rfind(".py");
if (py_extension_pos != std::string::npos)
@@ -166,7 +167,7 @@ bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list,
Target &target = m_process->GetTarget();
std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
std::defer_lock);
- api_lock.try_lock();
+ (void)api_lock.try_lock(); // See above.
auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
LLDB_LOGF(log,
@@ -308,7 +309,7 @@ OperatingSystemPython::CreateRegisterContextForThread(Thread *thread,
Target &target = m_process->GetTarget();
std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
std::defer_lock);
- api_lock.try_lock();
+ (void)api_lock.try_lock(); // See above.
auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
@@ -395,7 +396,7 @@ lldb::ThreadSP OperatingSystemPython::CreateThread(lldb::tid_t tid,
Target &target = m_process->GetTarget();
std::unique_lock<std::recursive_mutex> api_lock(target.GetAPIMutex(),
std::defer_lock);
- api_lock.try_lock();
+ (void)api_lock.try_lock(); // See above.
auto interpreter_lock = m_interpreter->AcquireInterpreterLock();
StructuredData::DictionarySP thread_info_dict =
@@ -416,4 +417,4 @@ lldb::ThreadSP OperatingSystemPython::CreateThread(lldb::tid_t tid,
return ThreadSP();
}
-#endif // #ifndef LLDB_DISABLE_PYTHON
+#endif // #if LLDB_ENABLE_PYTHON
diff --git a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
index e76227ddb981..4a594cf29a08 100644
--- a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
+++ b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
@@ -9,7 +9,9 @@
#ifndef liblldb_OperatingSystemPython_h_
#define liblldb_OperatingSystemPython_h_
-#ifndef LLDB_DISABLE_PYTHON
+#include "lldb/Host/Config.h"
+
+#if LLDB_ENABLE_PYTHON
#include "lldb/Target/OperatingSystem.h"
#include "lldb/Utility/StructuredData.h"
@@ -80,6 +82,6 @@ protected:
lldb_private::StructuredData::ObjectSP m_python_object_sp;
};
-#endif // LLDB_DISABLE_PYTHON
+#endif
#endif // liblldb_OperatingSystemPython_h_
diff --git a/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
index 946f0ea3a5cf..261f44c230f9 100644
--- a/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
+++ b/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
@@ -10,7 +10,7 @@
#include "lldb/Host/Config.h"
#include <stdio.h>
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
#include <sys/utsname.h>
#endif
@@ -194,7 +194,7 @@ bool PlatformFreeBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
void PlatformFreeBSD::GetStatus(Stream &strm) {
Platform::GetStatus(strm);
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
// Display local kernel information only when we are running in host mode.
// Otherwise, we would end up printing non-FreeBSD information (when running
// on Mac OS for example).
diff --git a/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp b/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
index 63245d18fc5c..53f819e6a272 100644
--- a/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
+++ b/lldb/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
@@ -10,7 +10,7 @@
#include "lldb/Host/Config.h"
#include <stdio.h>
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
#include <sys/utsname.h>
#endif
@@ -168,7 +168,7 @@ bool PlatformNetBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
void PlatformNetBSD::GetStatus(Stream &strm) {
Platform::GetStatus(strm);
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
// Display local kernel information only when we are running in host mode.
// Otherwise, we would end up printing non-NetBSD information (when running
// on Mac OS for example).
diff --git a/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp b/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
index 9dfb8844c574..1b63e2da0a4f 100644
--- a/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
+++ b/lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
@@ -10,7 +10,7 @@
#include "lldb/Host/Config.h"
#include <stdio.h>
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
#include <sys/utsname.h>
#endif
@@ -173,7 +173,7 @@ bool PlatformOpenBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
void PlatformOpenBSD::GetStatus(Stream &strm) {
Platform::GetStatus(strm);
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
// Display local kernel information only when we are running in host mode.
// Otherwise, we would end up printing non-OpenBSD information (when running
// on Mac OS for example).
diff --git a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index b12e21deb459..2b64be63a623 100644
--- a/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ b/lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -223,7 +223,7 @@ static uint32_t chown_file(Platform *platform, const char *path,
command.Printf(":%d", gid);
command.Printf("%s", path);
int status;
- platform->RunShellCommand(command.GetData(), nullptr, &status, nullptr,
+ platform->RunShellCommand(command.GetData(), FileSpec(), &status, nullptr,
nullptr, std::chrono::seconds(10));
return status;
}
@@ -235,7 +235,7 @@ PlatformPOSIX::PutFile(const lldb_private::FileSpec &source,
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (IsHost()) {
- if (FileSpec::Equal(source, destination, true))
+ if (source == destination)
return Status();
// cp src dst
// chown uid:gid dst
@@ -248,7 +248,7 @@ PlatformPOSIX::PutFile(const lldb_private::FileSpec &source,
StreamString command;
command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
int status;
- RunShellCommand(command.GetData(), nullptr, &status, nullptr, nullptr,
+ RunShellCommand(command.GetData(), FileSpec(), &status, nullptr, nullptr,
std::chrono::seconds(10));
if (status != 0)
return Status("unable to perform copy");
@@ -278,7 +278,7 @@ PlatformPOSIX::PutFile(const lldb_private::FileSpec &source,
GetHostname(), dst_path.c_str());
LLDB_LOGF(log, "[PutFile] Running command: %s\n", command.GetData());
int retcode;
- Host::RunShellCommand(command.GetData(), nullptr, &retcode, nullptr,
+ Host::RunShellCommand(command.GetData(), FileSpec(), &retcode, nullptr,
nullptr, std::chrono::minutes(1));
if (retcode == 0) {
// Don't chown a local file for a remote system
@@ -307,14 +307,14 @@ lldb_private::Status PlatformPOSIX::GetFile(
if (dst_path.empty())
return Status("unable to get file path for destination");
if (IsHost()) {
- if (FileSpec::Equal(source, destination, true))
+ if (source == destination)
return Status("local scenario->source and destination are the same file "
"path: no operation performed");
// cp src dst
StreamString cp_command;
cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
int status;
- RunShellCommand(cp_command.GetData(), nullptr, &status, nullptr, nullptr,
+ RunShellCommand(cp_command.GetData(), FileSpec(), &status, nullptr, nullptr,
std::chrono::seconds(10));
if (status != 0)
return Status("unable to perform copy");
@@ -335,7 +335,7 @@ lldb_private::Status PlatformPOSIX::GetFile(
dst_path.c_str());
LLDB_LOGF(log, "[GetFile] Running command: %s\n", command.GetData());
int retcode;
- Host::RunShellCommand(command.GetData(), nullptr, &retcode, nullptr,
+ Host::RunShellCommand(command.GetData(), FileSpec(), &retcode, nullptr,
nullptr, std::chrono::minutes(1));
if (retcode == 0)
return Status();
@@ -706,7 +706,9 @@ PlatformPOSIX::MakeLoadImageUtilityFunction(ExecutionContext &exe_ctx,
FunctionCaller *do_dlopen_function = nullptr;
// Fetch the clang types we will need:
- ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
+ ClangASTContext *ast = ClangASTContext::GetScratch(process->GetTarget());
+ if (!ast)
+ return nullptr;
CompilerType clang_void_pointer_type
= ast->GetBasicType(eBasicTypeVoid).GetPointerType();
@@ -948,7 +950,11 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process,
Value return_value;
// Fetch the clang types we will need:
- ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
+ ClangASTContext *ast = ClangASTContext::GetScratch(process->GetTarget());
+ if (!ast) {
+ error.SetErrorString("dlopen error: Unable to get ClangASTContext");
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
CompilerType clang_void_pointer_type
= ast->GetBasicType(eBasicTypeVoid).GetPointerType();
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
index 8b6f9fbc33c3..4313d27e11e9 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
@@ -8,8 +8,7 @@
#include "NativeProcessNetBSD.h"
-
-
+#include "Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h"
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "lldb/Host/HostProcess.h"
#include "lldb/Host/common/NativeRegisterContext.h"
@@ -99,6 +98,17 @@ NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate,
Info.GetArchitecture(), mainloop));
+ // Enable event reporting
+ ptrace_event_t events;
+ status = PtraceWrapper(PT_GET_EVENT_MASK, pid, &events, sizeof(events));
+ if (status.Fail())
+ return status.ToError();
+ // TODO: PTRACE_FORK | PTRACE_VFORK | PTRACE_POSIX_SPAWN?
+ events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT;
+ status = PtraceWrapper(PT_SET_EVENT_MASK, pid, &events, sizeof(events));
+ if (status.Fail())
+ return status.ToError();
+
status = process_up->ReinitializeThreads();
if (status.Fail())
return status.ToError();
@@ -211,17 +221,32 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
return;
}
+ NativeThreadNetBSD* thread = nullptr;
+ if (info.psi_lwpid > 0) {
+ for (const auto &t : m_threads) {
+ if (t->GetID() == static_cast<lldb::tid_t>(info.psi_lwpid)) {
+ thread = static_cast<NativeThreadNetBSD *>(t.get());
+ break;
+ }
+ static_cast<NativeThreadNetBSD *>(t.get())->SetStoppedWithNoReason();
+ }
+ if (!thread)
+ LLDB_LOG(log,
+ "thread not found in m_threads, pid = {0}, LWP = {1}", pid,
+ info.psi_lwpid);
+ }
+
switch (info.psi_siginfo.si_code) {
case TRAP_BRKPT:
- for (const auto &thread : m_threads) {
- static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByBreakpoint();
- FixupBreakpointPCAsNeeded(static_cast<NativeThreadNetBSD &>(*thread));
+ if (thread) {
+ thread->SetStoppedByBreakpoint();
+ FixupBreakpointPCAsNeeded(*thread);
}
SetState(StateType::eStateStopped, true);
break;
case TRAP_TRACE:
- for (const auto &thread : m_threads)
- static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByTrace();
+ if (thread)
+ thread->SetStoppedByTrace();
SetState(StateType::eStateStopped, true);
break;
case TRAP_EXEC: {
@@ -238,54 +263,66 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByExec();
SetState(StateType::eStateStopped, true);
} break;
- case TRAP_DBREG: {
- // Find the thread.
- NativeThreadNetBSD* thread = nullptr;
- for (const auto &t : m_threads) {
- if (t->GetID() == info.psi_lwpid) {
- thread = static_cast<NativeThreadNetBSD *>(t.get());
+ case TRAP_LWP: {
+ ptrace_state_t pst;
+ Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst));
+ if (error.Fail()) {
+ SetState(StateType::eStateInvalid);
+ return;
+ }
+
+ switch (pst.pe_report_event) {
+ case PTRACE_LWP_CREATE: {
+ LLDB_LOG(log,
+ "monitoring new thread, pid = {0}, LWP = {1}", pid,
+ pst.pe_lwp);
+ NativeThreadNetBSD& t = AddThread(pst.pe_lwp);
+ error = t.CopyWatchpointsFrom(
+ static_cast<NativeThreadNetBSD &>(*GetCurrentThread()));
+ if (error.Fail()) {
+ LLDB_LOG(log,
+ "failed to copy watchpoints to new thread {0}: {1}",
+ pst.pe_lwp, error);
+ SetState(StateType::eStateInvalid);
+ return;
+ }
+ } break;
+ case PTRACE_LWP_EXIT:
+ LLDB_LOG(log,
+ "removing exited thread, pid = {0}, LWP = {1}", pid,
+ pst.pe_lwp);
+ RemoveThread(pst.pe_lwp);
break;
- }
}
- if (!thread) {
- LLDB_LOG(log,
- "thread not found in m_threads, pid = {0}, LWP = {1}",
- GetID(), info.psi_lwpid);
- break;
+
+ error = PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void*>(1), 0);
+ if (error.Fail()) {
+ SetState(StateType::eStateInvalid);
+ return;
}
+ } break;
+ case TRAP_DBREG: {
+ if (!thread)
+ break;
- // If a watchpoint was hit, report it
+ auto &regctx = static_cast<NativeRegisterContextNetBSD &>(
+ thread->GetRegisterContext());
uint32_t wp_index = LLDB_INVALID_INDEX32;
- Status error = thread->GetRegisterContext().GetWatchpointHitIndex(
- wp_index, (uintptr_t)info.psi_siginfo.si_addr);
+ Status error = regctx.GetWatchpointHitIndex(wp_index,
+ (uintptr_t)info.psi_siginfo.si_addr);
if (error.Fail())
LLDB_LOG(log,
"received error while checking for watchpoint hits, pid = "
- "{0}, LWP = {1}, error = {2}",
- GetID(), info.psi_lwpid, error);
+ "{0}, LWP = {1}, error = {2}", pid, info.psi_lwpid, error);
if (wp_index != LLDB_INVALID_INDEX32) {
- for (const auto &thread : m_threads)
- static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByWatchpoint(
- wp_index);
+ thread->SetStoppedByWatchpoint(wp_index);
+ regctx.ClearWatchpointHit(wp_index);
SetState(StateType::eStateStopped, true);
break;
}
- // If a breakpoint was hit, report it
- uint32_t bp_index = LLDB_INVALID_INDEX32;
- error = thread->GetRegisterContext().GetHardwareBreakHitIndex(
- bp_index, (uintptr_t)info.psi_siginfo.si_addr);
- if (error.Fail())
- LLDB_LOG(log,
- "received error while checking for hardware "
- "breakpoint hits, pid = {0}, LWP = {1}, error = {2}",
- GetID(), info.psi_lwpid, error);
- if (bp_index != LLDB_INVALID_INDEX32) {
- for (const auto &thread : m_threads)
- static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByBreakpoint();
- SetState(StateType::eStateStopped, true);
- break;
- }
+ thread->SetStoppedByTrace();
+ SetState(StateType::eStateStopped, true);
} break;
}
}
@@ -295,9 +332,14 @@ void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) {
const auto siginfo_err =
PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
- for (const auto &thread : m_threads) {
- static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(
- info.psi_siginfo.si_signo, &info.psi_siginfo);
+ for (const auto &abs_thread : m_threads) {
+ NativeThreadNetBSD &thread = static_cast<NativeThreadNetBSD &>(*abs_thread);
+ assert(info.psi_lwpid >= 0);
+ if (info.psi_lwpid == 0 ||
+ static_cast<lldb::tid_t>(info.psi_lwpid) == thread.GetID())
+ thread.SetStoppedBySignal(info.psi_siginfo.si_signo, &info.psi_siginfo);
+ else
+ thread.SetStoppedWithNoReason();
}
SetState(StateType::eStateStopped, true);
}
@@ -325,68 +367,137 @@ Status NativeProcessNetBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
return error;
}
+static llvm::Expected<ptrace_siginfo_t> ComputeSignalInfo(
+ const std::vector<std::unique_ptr<NativeThreadProtocol>> &threads,
+ const ResumeActionList &resume_actions) {
+ // We need to account for three possible scenarios:
+ // 1. no signal being sent.
+ // 2. a signal being sent to one thread.
+ // 3. a signal being sent to the whole process.
+
+ // Count signaled threads. While at it, determine which signal is being sent
+ // and ensure there's only one.
+ size_t signaled_threads = 0;
+ int signal = LLDB_INVALID_SIGNAL_NUMBER;
+ lldb::tid_t signaled_lwp;
+ for (const auto &thread : threads) {
+ assert(thread && "thread list should not contain NULL threads");
+ const ResumeAction *action =
+ resume_actions.GetActionForThread(thread->GetID(), true);
+ if (action) {
+ if (action->signal != LLDB_INVALID_SIGNAL_NUMBER) {
+ signaled_threads++;
+ if (action->signal != signal) {
+ if (signal != LLDB_INVALID_SIGNAL_NUMBER)
+ return Status("NetBSD does not support passing multiple signals "
+ "simultaneously")
+ .ToError();
+ signal = action->signal;
+ signaled_lwp = thread->GetID();
+ }
+ }
+ }
+ }
+
+ if (signaled_threads == 0) {
+ ptrace_siginfo_t siginfo;
+ siginfo.psi_siginfo.si_signo = LLDB_INVALID_SIGNAL_NUMBER;
+ return siginfo;
+ }
+
+ if (signaled_threads > 1 && signaled_threads < threads.size())
+ return Status("NetBSD does not support passing signal to 1<i<all threads")
+ .ToError();
+
+ ptrace_siginfo_t siginfo;
+ siginfo.psi_siginfo.si_signo = signal;
+ siginfo.psi_siginfo.si_code = SI_USER;
+ siginfo.psi_siginfo.si_pid = getpid();
+ siginfo.psi_siginfo.si_uid = getuid();
+ if (signaled_threads == 1)
+ siginfo.psi_lwpid = signaled_lwp;
+ else // signal for the whole process
+ siginfo.psi_lwpid = 0;
+ return siginfo;
+}
+
Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
LLDB_LOG(log, "pid {0}", GetID());
- const auto &thread = m_threads[0];
- const ResumeAction *const action =
- resume_actions.GetActionForThread(thread->GetID(), true);
+ Status ret;
- if (action == nullptr) {
- LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
- thread->GetID());
- return Status();
- }
+ Expected<ptrace_siginfo_t> siginfo =
+ ComputeSignalInfo(m_threads, resume_actions);
+ if (!siginfo)
+ return Status(siginfo.takeError());
- Status error;
- int signal =
- action->signal != LLDB_INVALID_SIGNAL_NUMBER ? action->signal : 0;
-
- switch (action->state) {
- case eStateRunning: {
- // Run the thread, possibly feeding it the signal.
- error = NativeProcessNetBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1,
- signal);
- if (!error.Success())
- return error;
- for (const auto &thread : m_threads)
- static_cast<NativeThreadNetBSD &>(*thread).SetRunning();
- SetState(eStateRunning, true);
- break;
- }
- case eStateStepping:
- // Run the thread, possibly feeding it the signal.
- error = NativeProcessNetBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1,
- signal);
- if (!error.Success())
- return error;
- for (const auto &thread : m_threads)
- static_cast<NativeThreadNetBSD &>(*thread).SetStepping();
- SetState(eStateStepping, true);
- break;
+ for (const auto &abs_thread : m_threads) {
+ assert(abs_thread && "thread list should not contain NULL threads");
+ NativeThreadNetBSD &thread = static_cast<NativeThreadNetBSD &>(*abs_thread);
- case eStateSuspended:
- case eStateStopped:
- llvm_unreachable("Unexpected state");
+ const ResumeAction *action =
+ resume_actions.GetActionForThread(thread.GetID(), true);
+ // we need to explicit issue suspend requests, so it is simpler to map it
+ // into proper action
+ ResumeAction suspend_action{thread.GetID(), eStateSuspended,
+ LLDB_INVALID_SIGNAL_NUMBER};
- default:
- return Status("NativeProcessNetBSD::%s (): unexpected state %s specified "
- "for pid %" PRIu64 ", tid %" PRIu64,
- __FUNCTION__, StateAsCString(action->state), GetID(),
- thread->GetID());
+ if (action == nullptr) {
+ LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
+ thread.GetID());
+ action = &suspend_action;
+ }
+
+ LLDB_LOG(
+ log,
+ "processing resume action state {0} signal {1} for pid {2} tid {3}",
+ action->state, action->signal, GetID(), thread.GetID());
+
+ switch (action->state) {
+ case eStateRunning:
+ ret = thread.Resume();
+ break;
+ case eStateStepping:
+ ret = thread.SingleStep();
+ break;
+ case eStateSuspended:
+ case eStateStopped:
+ if (action->signal != LLDB_INVALID_SIGNAL_NUMBER)
+ return Status("Passing signal to suspended thread unsupported");
+
+ ret = thread.Suspend();
+ break;
+
+ default:
+ return Status("NativeProcessNetBSD::%s (): unexpected state %s specified "
+ "for pid %" PRIu64 ", tid %" PRIu64,
+ __FUNCTION__, StateAsCString(action->state), GetID(),
+ thread.GetID());
+ }
+
+ if (!ret.Success())
+ return ret;
}
- return Status();
+ int signal = 0;
+ if (siginfo->psi_siginfo.si_signo != LLDB_INVALID_SIGNAL_NUMBER) {
+ ret = PtraceWrapper(PT_SET_SIGINFO, GetID(), &siginfo.get(),
+ sizeof(*siginfo));
+ if (!ret.Success())
+ return ret;
+ signal = siginfo->psi_siginfo.si_signo;
+ }
+
+ ret = PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1),
+ signal);
+ if (ret.Success())
+ SetState(eStateRunning, true);
+ return ret;
}
Status NativeProcessNetBSD::Halt() {
- Status error;
-
- if (kill(GetID(), SIGSTOP) != 0)
- error.SetErrorToErrno();
-
- return error;
+ return PtraceWrapper(PT_STOP, GetID());
}
Status NativeProcessNetBSD::Detach() {
@@ -411,6 +522,10 @@ Status NativeProcessNetBSD::Signal(int signo) {
return error;
}
+Status NativeProcessNetBSD::Interrupt() {
+ return PtraceWrapper(PT_STOP, GetID());
+}
+
Status NativeProcessNetBSD::Kill() {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
LLDB_LOG(log, "pid {0}", GetID());
@@ -650,10 +765,10 @@ bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) {
}
NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
-
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
+ assert(thread_id > 0);
assert(!HasThreadNoLock(thread_id) &&
"attempted to add a thread by id that already exists");
@@ -665,6 +780,22 @@ NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
return static_cast<NativeThreadNetBSD &>(*m_threads.back());
}
+void NativeProcessNetBSD::RemoveThread(lldb::tid_t thread_id) {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+ LLDB_LOG(log, "pid {0} removing thread with tid {1}", GetID(), thread_id);
+
+ assert(thread_id > 0);
+ assert(HasThreadNoLock(thread_id) &&
+ "attempted to remove a thread that does not exist");
+
+ for (auto it = m_threads.begin(); it != m_threads.end(); ++it) {
+ if ((*it)->GetID() == thread_id) {
+ m_threads.erase(it);
+ break;
+ }
+ }
+}
+
Status NativeProcessNetBSD::Attach() {
// Attach to the requested process.
// An attach will cause the thread to stop with a SIGSTOP.
@@ -783,15 +914,23 @@ Status NativeProcessNetBSD::ReinitializeThreads() {
m_threads.clear();
// Initialize new thread
+#ifdef PT_LWPSTATUS
+ struct ptrace_lwpstatus info = {};
+ int op = PT_LWPNEXT;
+#else
struct ptrace_lwpinfo info = {};
- Status error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info));
+ int op = PT_LWPINFO;
+#endif
+
+ Status error = PtraceWrapper(op, GetID(), &info, sizeof(info));
+
if (error.Fail()) {
return error;
}
// Reinitialize from scratch threads and register them in process
while (info.pl_lwpid != 0) {
AddThread(info.pl_lwpid);
- error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info));
+ error = PtraceWrapper(op, GetID(), &info, sizeof(info));
if (error.Fail()) {
return error;
}
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
index 4e7f0a1c13ab..6a06773f40a8 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
+++ b/lldb/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
@@ -47,6 +47,8 @@ public:
Status Signal(int signo) override;
+ Status Interrupt() override;
+
Status Kill() override;
Status GetMemoryRegionInfo(lldb::addr_t load_addr,
@@ -98,6 +100,7 @@ private:
bool HasThreadNoLock(lldb::tid_t thread_id);
NativeThreadNetBSD &AddThread(lldb::tid_t thread_id);
+ void RemoveThread(lldb::tid_t thread_id);
void MonitorCallback(lldb::pid_t pid, int signal);
void MonitorExited(lldb::pid_t pid, WaitStatus status);
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
index 3a9caaad74c8..a8afa0b20305 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.cpp
@@ -8,6 +8,8 @@
#include "NativeRegisterContextNetBSD.h"
+#include "Plugins/Process/NetBSD/NativeProcessNetBSD.h"
+
#include "lldb/Host/common/NativeProcessProtocol.h"
using namespace lldb_private;
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
index f5dd0c33b677..13e023d856d2 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
+++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h
@@ -11,12 +11,13 @@
#include "lldb/Host/common/NativeThreadProtocol.h"
-#include "Plugins/Process/NetBSD/NativeProcessNetBSD.h"
#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h"
namespace lldb_private {
namespace process_netbsd {
+class NativeProcessNetBSD;
+
class NativeRegisterContextNetBSD : public NativeRegisterContextRegisterInfo {
public:
NativeRegisterContextNetBSD(NativeThreadProtocol &native_thread,
@@ -30,6 +31,10 @@ public:
static NativeRegisterContextNetBSD *
CreateHostNativeRegisterContextNetBSD(const ArchSpec &target_arch,
NativeThreadProtocol &native_thread);
+ virtual Status
+ CopyHardwareWatchpointsFrom(NativeRegisterContextNetBSD &source) = 0;
+
+ virtual Status ClearWatchpointHit(uint32_t wp_index) = 0;
protected:
Status DoRegisterSet(int req, void *buf);
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
index 6cc2810fa235..05a35401da46 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
@@ -84,13 +84,71 @@ static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) -
k_num_gpr_registers_x86_64,
"g_gpr_regnums_x86_64 has wrong number of register infos");
+// x86 64-bit floating point registers.
+static const uint32_t g_fpu_regnums_x86_64[] = {
+ lldb_fctrl_x86_64, lldb_fstat_x86_64, lldb_ftag_x86_64,
+ lldb_fop_x86_64, lldb_fiseg_x86_64, lldb_fioff_x86_64,
+ lldb_foseg_x86_64, lldb_fooff_x86_64, lldb_mxcsr_x86_64,
+ lldb_mxcsrmask_x86_64, lldb_st0_x86_64, lldb_st1_x86_64,
+ lldb_st2_x86_64, lldb_st3_x86_64, lldb_st4_x86_64,
+ lldb_st5_x86_64, lldb_st6_x86_64, lldb_st7_x86_64,
+ lldb_mm0_x86_64, lldb_mm1_x86_64, lldb_mm2_x86_64,
+ lldb_mm3_x86_64, lldb_mm4_x86_64, lldb_mm5_x86_64,
+ lldb_mm6_x86_64, lldb_mm7_x86_64, lldb_xmm0_x86_64,
+ lldb_xmm1_x86_64, lldb_xmm2_x86_64, lldb_xmm3_x86_64,
+ lldb_xmm4_x86_64, lldb_xmm5_x86_64, lldb_xmm6_x86_64,
+ lldb_xmm7_x86_64, lldb_xmm8_x86_64, lldb_xmm9_x86_64,
+ lldb_xmm10_x86_64, lldb_xmm11_x86_64, lldb_xmm12_x86_64,
+ lldb_xmm13_x86_64, lldb_xmm14_x86_64, lldb_xmm15_x86_64,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) -
+ 1 ==
+ k_num_fpr_registers_x86_64,
+ "g_fpu_regnums_x86_64 has wrong number of register infos");
+
+// x86 64-bit registers available via XState.
+static const uint32_t g_xstate_regnums_x86_64[] = {
+ lldb_ymm0_x86_64, lldb_ymm1_x86_64, lldb_ymm2_x86_64, lldb_ymm3_x86_64,
+ lldb_ymm4_x86_64, lldb_ymm5_x86_64, lldb_ymm6_x86_64, lldb_ymm7_x86_64,
+ lldb_ymm8_x86_64, lldb_ymm9_x86_64, lldb_ymm10_x86_64, lldb_ymm11_x86_64,
+ lldb_ymm12_x86_64, lldb_ymm13_x86_64, lldb_ymm14_x86_64, lldb_ymm15_x86_64,
+ // Note: we currently do not provide them but this is needed to avoid
+ // unnamed groups in SBFrame::GetRegisterContext().
+ lldb_bnd0_x86_64, lldb_bnd1_x86_64, lldb_bnd2_x86_64,
+ lldb_bnd3_x86_64, lldb_bndcfgu_x86_64, lldb_bndstatus_x86_64,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_xstate_regnums_x86_64) / sizeof(g_xstate_regnums_x86_64[0])) -
+ 1 ==
+ k_num_avx_registers_x86_64 + k_num_mpx_registers_x86_64,
+ "g_xstate_regnums_x86_64 has wrong number of register infos");
+
+// x86 debug registers.
+static const uint32_t g_dbr_regnums_x86_64[] = {
+ lldb_dr0_x86_64, lldb_dr1_x86_64, lldb_dr2_x86_64, lldb_dr3_x86_64,
+ lldb_dr4_x86_64, lldb_dr5_x86_64, lldb_dr6_x86_64, lldb_dr7_x86_64,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_dbr_regnums_x86_64) / sizeof(g_dbr_regnums_x86_64[0])) -
+ 1 ==
+ k_num_dbr_registers_x86_64,
+ "g_dbr_regnums_x86_64 has wrong number of register infos");
+
// Number of register sets provided by this context.
-enum { k_num_extended_register_sets = 2, k_num_register_sets = 4 };
+enum { k_num_register_sets = 4 };
// Register sets for x86 64-bit.
static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = {
{"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64,
g_gpr_regnums_x86_64},
+ {"Floating Point Registers", "fpu", k_num_fpr_registers_x86_64,
+ g_fpu_regnums_x86_64},
+ {"Extended State Registers", "xstate",
+ k_num_avx_registers_x86_64 + k_num_mpx_registers_x86_64,
+ g_xstate_regnums_x86_64},
+ {"Debug Registers", "dbr", k_num_dbr_registers_x86_64,
+ g_dbr_regnums_x86_64},
};
#define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize())
@@ -667,11 +725,6 @@ Status NativeRegisterContextNetBSD_x86_64::ReadAllRegisterValues(
::memcpy(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize());
dst += GetRegisterInfoInterface().GetGPRSize();
- RegisterValue value((uint64_t)-1);
- const RegisterInfo *reg_info =
- GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_eax");
- if (reg_info == nullptr)
- reg_info = GetRegisterInfoInterface().GetDynamicRegisterInfo("orig_rax");
return error;
}
@@ -795,10 +848,10 @@ Status NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpointWithIndex(
if (!is_vacant)
return Status("Watchpoint index not vacant");
- RegisterValue reg_value;
const RegisterInfo *const reg_info_dr7 =
GetRegisterInfoAtIndex(lldb_dr7_x86_64);
- error = ReadRegister(reg_info_dr7, reg_value);
+ RegisterValue dr7_value;
+ error = ReadRegister(reg_info_dr7, dr7_value);
if (error.Fail())
return error;
@@ -816,16 +869,28 @@ Status NativeRegisterContextNetBSD_x86_64::SetHardwareWatchpointWithIndex(
uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
- uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
+ uint64_t control_bits = dr7_value.GetAsUInt64() & ~bit_mask;
control_bits |= enable_bit | rw_bits | size_bits;
const RegisterInfo *const reg_info_drN =
GetRegisterInfoAtIndex(lldb_dr0_x86_64 + wp_index);
- error = WriteRegister(reg_info_drN, RegisterValue(addr));
+ RegisterValue drN_value;
+ error = ReadRegister(reg_info_drN, drN_value);
if (error.Fail())
return error;
+ // clear dr6 if address or bits changed (i.e. we're not reenabling the same
+ // watchpoint)
+ if (drN_value.GetAsUInt64() != addr ||
+ (dr7_value.GetAsUInt64() & bit_mask) != (rw_bits | size_bits)) {
+ ClearWatchpointHit(wp_index);
+
+ error = WriteRegister(reg_info_drN, RegisterValue(addr));
+ if (error.Fail())
+ return error;
+ }
+
error = WriteRegister(reg_info_dr7, RegisterValue(control_bits));
if (error.Fail())
return error;
@@ -839,32 +904,36 @@ bool NativeRegisterContextNetBSD_x86_64::ClearHardwareWatchpoint(
if (wp_index >= NumSupportedHardwareWatchpoints())
return false;
+ // for watchpoints 0, 1, 2, or 3, respectively, clear bits 0-1, 2-3, 4-5
+ // or 6-7 of the debug control register (DR7)
+ const RegisterInfo *const reg_info_dr7 =
+ GetRegisterInfoAtIndex(lldb_dr7_x86_64);
RegisterValue reg_value;
+ Status error = ReadRegister(reg_info_dr7, reg_value);
+ if (error.Fail())
+ return false;
+ uint64_t bit_mask = 0x3 << (2 * wp_index);
+ uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
- // for watchpoints 0, 1, 2, or 3, respectively, clear bits 0, 1, 2, or 3 of
+ return WriteRegister(reg_info_dr7, RegisterValue(control_bits)).Success();
+}
+
+Status NativeRegisterContextNetBSD_x86_64::ClearWatchpointHit(uint32_t wp_index) {
+ if (wp_index >= NumSupportedHardwareWatchpoints())
+ return Status("Watchpoint index out of range");
+
+ // for watchpoints 0, 1, 2, or 3, respectively, check bits 0, 1, 2, or 3 of
// the debug status register (DR6)
const RegisterInfo *const reg_info_dr6 =
GetRegisterInfoAtIndex(lldb_dr6_x86_64);
+ RegisterValue reg_value;
Status error = ReadRegister(reg_info_dr6, reg_value);
if (error.Fail())
- return false;
+ return error;
+
uint64_t bit_mask = 1 << wp_index;
uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
- error = WriteRegister(reg_info_dr6, RegisterValue(status_bits));
- if (error.Fail())
- return false;
-
- // for watchpoints 0, 1, 2, or 3, respectively, clear bits {0-1,16-19},
- // {2-3,20-23}, {4-5,24-27}, or {6-7,28-31} of the debug control register
- // (DR7)
- const RegisterInfo *const reg_info_dr7 =
- GetRegisterInfoAtIndex(lldb_dr7_x86_64);
- error = ReadRegister(reg_info_dr7, reg_value);
- if (error.Fail())
- return false;
- bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
- uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
- return WriteRegister(reg_info_dr7, RegisterValue(control_bits)).Success();
+ return WriteRegister(reg_info_dr6, RegisterValue(status_bits));
}
Status NativeRegisterContextNetBSD_x86_64::ClearAllHardwareWatchpoints() {
@@ -930,4 +999,19 @@ uint32_t NativeRegisterContextNetBSD_x86_64::NumSupportedHardwareWatchpoints() {
return 4;
}
+Status NativeRegisterContextNetBSD_x86_64::CopyHardwareWatchpointsFrom(
+ NativeRegisterContextNetBSD &source) {
+ auto &r_source = static_cast<NativeRegisterContextNetBSD_x86_64&>(source);
+ Status res = r_source.ReadRegisterSet(DBRegSet);
+ if (!res.Fail()) {
+ // copy dbregs only if any watchpoints were set
+ if ((r_source.m_dbr_x86_64.dr[7] & 0xFF) == 0)
+ return res;
+
+ m_dbr_x86_64 = r_source.m_dbr_x86_64;
+ res = WriteRegisterSet(DBRegSet);
+ }
+ return res;
+}
+
#endif // defined(__x86_64__)
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
index 0fed16542a95..54b8a806267f 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
+++ b/lldb/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.h
@@ -58,6 +58,8 @@ public:
bool ClearHardwareWatchpoint(uint32_t wp_index) override;
+ Status ClearWatchpointHit(uint32_t wp_index) override;
+
Status ClearAllHardwareWatchpoints() override;
Status SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
@@ -71,9 +73,12 @@ public:
uint32_t NumSupportedHardwareWatchpoints() override;
+ Status
+ CopyHardwareWatchpointsFrom(NativeRegisterContextNetBSD &source) override;
+
private:
// Private member types.
- enum { GPRegSet, FPRegSet, DBRegSet, XStateRegSet };
+ enum { GPRegSet, FPRegSet, XStateRegSet, DBRegSet };
// Private member variables.
struct reg m_gpr_x86_64;
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
index e25975c93446..dd2745d9330e 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
+++ b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
@@ -16,9 +16,20 @@
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/State.h"
+#include "llvm/Support/Errno.h"
+
+// clang-format off
+#include <sys/types.h>
+#include <sys/ptrace.h>
+// clang-format on
#include <sstream>
+// clang-format off
+#include <sys/types.h>
+#include <sys/sysctl.h>
+// clang-format on
+
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_netbsd;
@@ -30,6 +41,38 @@ NativeThreadNetBSD::NativeThreadNetBSD(NativeProcessNetBSD &process,
NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(process.GetArchitecture(), *this)
), m_stop_description() {}
+Status NativeThreadNetBSD::Resume() {
+ Status ret = NativeProcessNetBSD::PtraceWrapper(PT_RESUME, m_process.GetID(),
+ nullptr, GetID());
+ if (!ret.Success())
+ return ret;
+ ret = NativeProcessNetBSD::PtraceWrapper(PT_CLEARSTEP, m_process.GetID(),
+ nullptr, GetID());
+ if (ret.Success())
+ SetRunning();
+ return ret;
+}
+
+Status NativeThreadNetBSD::SingleStep() {
+ Status ret = NativeProcessNetBSD::PtraceWrapper(PT_RESUME, m_process.GetID(),
+ nullptr, GetID());
+ if (!ret.Success())
+ return ret;
+ ret = NativeProcessNetBSD::PtraceWrapper(PT_SETSTEP, m_process.GetID(),
+ nullptr, GetID());
+ if (ret.Success())
+ SetStepping();
+ return ret;
+}
+
+Status NativeThreadNetBSD::Suspend() {
+ Status ret = NativeProcessNetBSD::PtraceWrapper(PT_SUSPEND, m_process.GetID(),
+ nullptr, GetID());
+ if (ret.Success())
+ SetStopped();
+ return ret;
+}
+
void NativeThreadNetBSD::SetStoppedBySignal(uint32_t signo,
const siginfo_t *info) {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
@@ -89,6 +132,13 @@ void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) {
m_stop_info.details.signal.signo = SIGTRAP;
}
+void NativeThreadNetBSD::SetStoppedWithNoReason() {
+ SetStopped();
+
+ m_stop_info.reason = StopReason::eStopReasonNone;
+ m_stop_info.details.signal.signo = 0;
+}
+
void NativeThreadNetBSD::SetStopped() {
const StateType new_state = StateType::eStateStopped;
m_state = new_state;
@@ -105,7 +155,49 @@ void NativeThreadNetBSD::SetStepping() {
m_stop_info.reason = StopReason::eStopReasonNone;
}
-std::string NativeThreadNetBSD::GetName() { return std::string(""); }
+std::string NativeThreadNetBSD::GetName() {
+ Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
+
+#ifdef PT_LWPSTATUS
+ struct ptrace_lwpstatus info = {};
+ info.pl_lwpid = m_tid;
+ Status error = NativeProcessNetBSD::PtraceWrapper(
+ PT_LWPSTATUS, static_cast<int>(m_process.GetID()), &info, sizeof(info));
+ if (error.Fail()) {
+ return "";
+ }
+ return info.pl_name;
+#else
+ std::vector<struct kinfo_lwp> infos;
+ int mib[5] = {CTL_KERN, KERN_LWP, static_cast<int>(m_process.GetID()),
+ sizeof(struct kinfo_lwp), 0};
+ size_t size;
+
+ if (::sysctl(mib, 5, nullptr, &size, nullptr, 0) == -1 || size == 0) {
+ LLDB_LOG(log, "sysctl() for LWP info size failed: {0}",
+ llvm::sys::StrError());
+ return "";
+ }
+
+ mib[4] = size / sizeof(size_t);
+ infos.resize(size / sizeof(struct kinfo_lwp));
+
+ if (sysctl(mib, 5, infos.data(), &size, NULL, 0) == -1 || size == 0) {
+ LLDB_LOG(log, "sysctl() for LWP info failed: {0}", llvm::sys::StrError());
+ return "";
+ }
+
+ size_t nlwps = size / sizeof(struct kinfo_lwp);
+ for (size_t i = 0; i < nlwps; i++) {
+ if (static_cast<lldb::tid_t>(infos[i].l_lid) == m_tid) {
+ return infos[i].l_name;
+ }
+ }
+
+ LLDB_LOG(log, "unable to find lwp {0} in LWP infos", m_tid);
+ return "";
+#endif
+}
lldb::StateType NativeThreadNetBSD::GetState() { return m_state; }
@@ -140,9 +232,9 @@ bool NativeThreadNetBSD::GetStopReason(ThreadStopInfo &stop_info,
llvm_unreachable("unhandled StateType!");
}
-NativeRegisterContext& NativeThreadNetBSD::GetRegisterContext() {
+NativeRegisterContextNetBSD &NativeThreadNetBSD::GetRegisterContext() {
assert(m_reg_context_up);
-return *m_reg_context_up;
+ return *m_reg_context_up;
}
Status NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size,
@@ -203,3 +295,13 @@ Status NativeThreadNetBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) {
return Status("Clearing hardware breakpoint failed.");
}
+
+Status NativeThreadNetBSD::CopyWatchpointsFrom(NativeThreadNetBSD &source) {
+ Status s = GetRegisterContext().CopyHardwareWatchpointsFrom(
+ source.GetRegisterContext());
+ if (!s.Fail()) {
+ m_watchpoint_index_map = source.m_watchpoint_index_map;
+ m_hw_break_index_map = source.m_hw_break_index_map;
+ }
+ return s;
+}
diff --git a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
index 015d8995db34..89b61ef86722 100644
--- a/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
+++ b/lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
@@ -11,6 +11,8 @@
#include "lldb/Host/common/NativeThreadProtocol.h"
+#include "Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h"
+
#include <csignal>
#include <map>
#include <string>
@@ -34,7 +36,7 @@ public:
bool GetStopReason(ThreadStopInfo &stop_info,
std::string &description) override;
- NativeRegisterContext& GetRegisterContext() override;
+ NativeRegisterContextNetBSD &GetRegisterContext() override;
Status SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags,
bool hardware) override;
@@ -48,19 +50,26 @@ public:
private:
// Interface for friend classes
+ Status Resume();
+ Status SingleStep();
+ Status Suspend();
+
void SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr);
void SetStoppedByBreakpoint();
void SetStoppedByTrace();
void SetStoppedByExec();
void SetStoppedByWatchpoint(uint32_t wp_index);
+ void SetStoppedWithNoReason();
void SetStopped();
void SetRunning();
void SetStepping();
+ Status CopyWatchpointsFrom(NativeThreadNetBSD& source);
+
// Member Variables
lldb::StateType m_state;
ThreadStopInfo m_stop_info;
- std::unique_ptr<NativeRegisterContext> m_reg_context_up;
+ std::unique_ptr<NativeRegisterContextNetBSD> m_reg_context_up;
std::string m_stop_description;
using WatchpointIndexMap = std::map<lldb::addr_t, uint32_t>;
WatchpointIndexMap m_watchpoint_index_map;
diff --git a/lldb/source/Plugins/Process/POSIX/CrashReason.cpp b/lldb/source/Plugins/Process/POSIX/CrashReason.cpp
index 9678e48436e7..b872269fdfe1 100644
--- a/lldb/source/Plugins/Process/POSIX/CrashReason.cpp
+++ b/lldb/source/Plugins/Process/POSIX/CrashReason.cpp
@@ -136,15 +136,15 @@ std::string GetCrashReasonString(CrashReason reason, const siginfo_t &info) {
#if defined(si_lower) && defined(si_upper)
if (reason == CrashReason::eBoundViolation) {
str = "signal SIGSEGV";
- AppendBounds(str, reinterpret_cast<lldb::addr_t>(info.si_lower),
- reinterpret_cast<lldb::addr_t>(info.si_upper),
- reinterpret_cast<lldb::addr_t>(info.si_addr));
+ AppendBounds(str, reinterpret_cast<uintptr_t>(info.si_lower),
+ reinterpret_cast<uintptr_t>(info.si_upper),
+ reinterpret_cast<uintptr_t>(info.si_addr));
return str;
}
#endif
return GetCrashReasonString(reason,
- reinterpret_cast<lldb::addr_t>(info.si_addr));
+ reinterpret_cast<uintptr_t>(info.si_addr));
}
std::string GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr) {
diff --git a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index 2ccbeacc4960..ee939b01d350 100644
--- a/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/lldb/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -20,7 +20,7 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
#include <sys/mman.h>
#else
// define them
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
index 4ca33c248c6f..173e66904151 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
@@ -21,12 +21,6 @@
#include <memory>
-// Support building against older versions of LLVM, this macro was added
-// recently.
-#ifndef LLVM_EXTENSION
-#define LLVM_EXTENSION
-#endif
-
#include "Utility/ARM_DWARF_Registers.h"
#include "Utility/ARM_ehframe_Registers.h"
@@ -1146,10 +1140,11 @@ bool RegisterContextDarwin_arm::ReadRegister(const RegisterInfo *reg_info,
case gpr_sp:
case gpr_lr:
case gpr_pc:
- case gpr_cpsr:
value.SetUInt32(gpr.r[reg - gpr_r0]);
break;
-
+ case gpr_cpsr:
+ value.SetUInt32(gpr.cpsr);
+ break;
case fpu_s0:
case fpu_s1:
case fpu_s2:
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
index b3ec24d8905d..fa5197cd6bf4 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
@@ -30,12 +30,6 @@
#include <sys/sysctl.h>
#endif
-// Support building against older versions of LLVM, this macro was added
-// recently.
-#ifndef LLVM_EXTENSION
-#define LLVM_EXTENSION
-#endif
-
#include "Utility/ARM64_DWARF_Registers.h"
using namespace lldb;
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
index 873713fd8373..959b04700b17 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
@@ -19,12 +19,6 @@
#include <memory>
-// Support building against older versions of LLVM, this macro was added
-// recently.
-#ifndef LLVM_EXTENSION
-#define LLVM_EXTENSION
-#endif
-
#include "RegisterContextDarwin_i386.h"
using namespace lldb;
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
index 47758ce85eb2..22088a7d6448 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
@@ -21,12 +21,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
-// Support building against older versions of LLVM, this macro was added
-// recently.
-#ifndef LLVM_EXTENSION
-#define LLVM_EXTENSION
-#endif
-
#include "RegisterContextDarwin_x86_64.h"
using namespace lldb;
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
index 4a3b3c73fd6b..af3027afa73c 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
@@ -25,15 +25,18 @@
LLVM_EXTENSION offsetof(FPR, xsave) + \
LLVM_EXTENSION offsetof(XSAVE, ymmh[0]) + (32 * reg_index))
+// Guarantees BNDR/BNDC offsets do not overlap with YMM offsets.
+#define GDB_REMOTE_OFFSET 128
+
#define BNDR_OFFSET(reg_index) \
(LLVM_EXTENSION offsetof(UserArea, fpr) + \
LLVM_EXTENSION offsetof(FPR, xsave) + \
- LLVM_EXTENSION offsetof(XSAVE, mpxr[reg_index]))
+ LLVM_EXTENSION offsetof(XSAVE, mpxr[reg_index]) + GDB_REMOTE_OFFSET)
#define BNDC_OFFSET(reg_index) \
(LLVM_EXTENSION offsetof(UserArea, fpr) + \
LLVM_EXTENSION offsetof(FPR, xsave) + \
- LLVM_EXTENSION offsetof(XSAVE, mpxc[reg_index]))
+ LLVM_EXTENSION offsetof(XSAVE, mpxc[reg_index]) + GDB_REMOTE_OFFSET)
#ifdef DECLARE_REGISTER_INFOS_X86_64_STRUCT
diff --git a/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h b/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h
index 0d2149c83573..bfdd586d9ded 100644
--- a/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h
+++ b/lldb/source/Plugins/Process/Utility/lldb-x86-register-enums.h
@@ -294,7 +294,8 @@ enum {
lldb_bndstatus_x86_64,
k_last_mpxc_x86_64 = lldb_bndstatus_x86_64,
- lldb_dr0_x86_64,
+ k_first_dbr_x86_64,
+ lldb_dr0_x86_64 = k_first_dbr_x86_64,
lldb_dr1_x86_64,
lldb_dr2_x86_64,
lldb_dr3_x86_64,
@@ -302,6 +303,7 @@ enum {
lldb_dr5_x86_64,
lldb_dr6_x86_64,
lldb_dr7_x86_64,
+ k_last_dbr_x86_64 = lldb_dr7_x86_64,
k_num_registers_x86_64,
k_num_gpr_registers_x86_64 = k_last_gpr_x86_64 - k_first_gpr_x86_64 + 1,
@@ -312,6 +314,7 @@ enum {
k_num_fpr_registers_x86_64 +
k_num_avx_registers_x86_64 +
k_num_mpx_registers_x86_64,
+ k_num_dbr_registers_x86_64 = k_last_dbr_x86_64 - k_first_dbr_x86_64 + 1,
};
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 144ae103faa4..7cea013eea7f 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -31,6 +31,7 @@
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegularExpression.h"
+#include "lldb/Utility/Reproducer.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ScopedPrinter.h"
@@ -49,7 +50,7 @@
#include <compression.h>
#endif
-#if defined(HAVE_LIBZ)
+#if LLVM_ENABLE_ZLIB
#include <zlib.h>
#endif
@@ -581,7 +582,7 @@ bool GDBRemoteCommunication::DecompressPacket() {
}
#endif
-#if defined(HAVE_LIBZ)
+#if LLVM_ENABLE_ZLIB
if (decompressed_bytes == 0 && decompressed_bufsize != ULONG_MAX &&
decompressed_buffer != nullptr &&
m_compression_type == CompressionType::ZlibDeflate) {
@@ -1243,8 +1244,9 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
void GDBRemoteCommunication::DumpHistory(Stream &strm) { m_history.Dump(strm); }
-void GDBRemoteCommunication::SetHistoryStream(llvm::raw_ostream *strm) {
- m_history.SetStream(strm);
+void GDBRemoteCommunication::SetPacketRecorder(
+ repro::PacketRecorder *recorder) {
+ m_history.SetRecorder(recorder);
}
llvm::Error
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index bb777a5c26a7..0b670018bd69 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -27,6 +27,9 @@
#include "lldb/lldb-public.h"
namespace lldb_private {
+namespace repro {
+class PacketRecorder;
+}
namespace process_gdb_remote {
enum GDBStoppointType {
@@ -133,7 +136,8 @@ public:
// fork/exec to avoid having to connect/accept
void DumpHistory(Stream &strm);
- void SetHistoryStream(llvm::raw_ostream *strm);
+
+ void SetPacketRecorder(repro::PacketRecorder *recorder);
static llvm::Error ConnectLocally(GDBRemoteCommunication &client,
GDBRemoteCommunication &server);
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index feb9f0589cee..b2f1ee527e8b 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -543,21 +543,24 @@ GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse(
//
// Takes a valid thread ID because p needs to apply to a thread.
bool GDBRemoteCommunicationClient::GetpPacketSupported(lldb::tid_t tid) {
- if (m_supports_p == eLazyBoolCalculate) {
- m_supports_p = eLazyBoolNo;
- StreamString payload;
- payload.PutCString("p0");
- StringExtractorGDBRemote response;
- if (SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload),
- response, false) ==
- PacketResult::Success &&
- response.IsNormalResponse()) {
- m_supports_p = eLazyBoolYes;
- }
- }
+ if (m_supports_p == eLazyBoolCalculate)
+ m_supports_p = GetThreadPacketSupported(tid, "p0");
return m_supports_p;
}
+LazyBool GDBRemoteCommunicationClient::GetThreadPacketSupported(
+ lldb::tid_t tid, llvm::StringRef packetStr) {
+ StreamString payload;
+ payload.PutCString(packetStr);
+ StringExtractorGDBRemote response;
+ if (SendThreadSpecificPacketAndWaitForResponse(
+ tid, std::move(payload), response, false) == PacketResult::Success &&
+ response.IsNormalResponse()) {
+ return eLazyBoolYes;
+ }
+ return eLazyBoolNo;
+}
+
StructuredData::ObjectSP GDBRemoteCommunicationClient::GetThreadsInfo() {
// Get information on all threads at one using the "jThreadsInfo" packet
StructuredData::ObjectSP object_sp;
@@ -1042,7 +1045,7 @@ void GDBRemoteCommunicationClient::MaybeEnableCompression(
}
#endif
-#if defined(HAVE_LIBZ)
+#if LLVM_ENABLE_ZLIB
if (avail_type == CompressionType::None) {
for (auto compression : supported_compressions) {
if (compression == "zlib-deflate") {
@@ -3737,7 +3740,7 @@ bool GDBRemoteCommunicationClient::ReadExtFeature(
case ('m'):
if (str.length() > 1)
output << &str[1];
- offset += size;
+ offset += str.length() - 1;
break;
// unknown chunk
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index 574cd0fd70c5..11fd40bce44f 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -89,7 +89,7 @@ public:
/// Sends a GDB remote protocol 'A' packet that delivers program
/// arguments to the remote server.
///
- /// \param[in] argv
+ /// \param[in] launch_info
/// A NULL terminated array of const C strings to use as the
/// arguments.
///
@@ -155,7 +155,7 @@ public:
/// Sets the path to use for stdin/out/err for a process
/// that will be launched with the 'A' packet.
///
- /// \param[in] path
+ /// \param[in] file_spec
/// The path to use for stdin/out/err
///
/// \return
@@ -596,6 +596,8 @@ protected:
Status GetQXferMemoryMapRegionInfo(lldb::addr_t addr,
MemoryRegionInfo &region);
+ LazyBool GetThreadPacketSupported(lldb::tid_t tid, llvm::StringRef packetStr);
+
private:
DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationClient);
};
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
index d2cc32f63f20..9e5646985f87 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
@@ -40,8 +40,8 @@ void GDBRemoteCommunicationHistory::AddPacket(char packet_char,
m_packets[idx].bytes_transmitted = bytes_transmitted;
m_packets[idx].packet_idx = m_total_packet_count;
m_packets[idx].tid = llvm::get_threadid();
- if (m_stream)
- m_packets[idx].Serialize(*m_stream);
+ if (m_recorder)
+ m_recorder->Record(m_packets[idx]);
}
void GDBRemoteCommunicationHistory::AddPacket(const std::string &src,
@@ -58,8 +58,8 @@ void GDBRemoteCommunicationHistory::AddPacket(const std::string &src,
m_packets[idx].bytes_transmitted = bytes_transmitted;
m_packets[idx].packet_idx = m_total_packet_count;
m_packets[idx].tid = llvm::get_threadid();
- if (m_stream)
- m_packets[idx].Serialize(*m_stream);
+ if (m_recorder)
+ m_recorder->Record(m_packets[idx]);
}
void GDBRemoteCommunicationHistory::Dump(Stream &strm) const {
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
index c006fbd34a4b..ee265ef86dff 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
@@ -13,11 +13,15 @@
#include <vector>
#include "lldb/Utility/GDBRemote.h"
+#include "lldb/Utility/Reproducer.h"
#include "lldb/lldb-public.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
namespace lldb_private {
+namespace repro {
+class PacketRecorder;
+}
namespace process_gdb_remote {
/// The history keeps a circular buffer of GDB remote packets. The history is
@@ -41,7 +45,7 @@ public:
void Dump(Log *log) const;
bool DidDumpToLog() const { return m_dumped_to_log; }
- void SetStream(llvm::raw_ostream *strm) { m_stream = strm; }
+ void SetRecorder(repro::PacketRecorder *recorder) { m_recorder = recorder; }
private:
uint32_t GetFirstSavedPacketIndex() const {
@@ -73,7 +77,7 @@ private:
uint32_t m_curr_idx;
uint32_t m_total_packet_count;
mutable bool m_dumped_to_log;
- llvm::raw_ostream *m_stream = nullptr;
+ repro::PacketRecorder *m_recorder = nullptr;
};
} // namespace process_gdb_remote
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp
index 2d26c550dc76..15c73e78bd44 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp
@@ -143,7 +143,14 @@ GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse(
entry.packet.data);
LLDB_LOG(log, "GDBRemoteCommunicationReplayServer actual packet: '{0}'",
packet.GetStringRef());
- assert(false && "Encountered unexpected packet during replay");
+#ifndef NDEBUG
+ // This behaves like a regular assert, but prints the expected and
+ // received packet before aborting.
+ printf("Reproducer expected packet: '%s'\n", entry.packet.data.c_str());
+ printf("Reproducer received packet: '%s'\n",
+ packet.GetStringRef().data());
+ llvm::report_fatal_error("Encountered unexpected packet during replay");
+#endif
return PacketResult::ErrorSendFailed;
}
@@ -204,9 +211,9 @@ bool GDBRemoteCommunicationReplayServer::StartAsyncThread() {
"<lldb.gdb-replay.async>",
GDBRemoteCommunicationReplayServer::AsyncThread, this);
if (!async_thread) {
- LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST),
- "failed to launch host thread: {}",
- llvm::toString(async_thread.takeError()));
+ LLDB_LOG_ERROR(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST),
+ async_thread.takeError(),
+ "failed to launch host thread: {}");
return false;
}
m_async_thread = *async_thread;
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index 37980d914dc2..4b5fc0774a6d 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -429,7 +429,7 @@ GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_qUserName(
StringExtractorGDBRemote &packet) {
-#if !defined(LLDB_DISABLE_POSIX)
+#if LLDB_ENABLE_POSIX
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
LLDB_LOGF(log, "GDBRemoteCommunicationServerCommon::%s begin", __FUNCTION__);
@@ -452,7 +452,7 @@ GDBRemoteCommunicationServerCommon::Handle_qUserName(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_qGroupName(
StringExtractorGDBRemote &packet) {
-#if !defined(LLDB_DISABLE_POSIX)
+#if LLDB_ENABLE_POSIX
// Packet format: "qGroupName:%i" where %i is the gid
packet.SetFilePos(::strlen("qGroupName:"));
uint32_t gid = packet.GetU32(UINT32_MAX);
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index ad1a39b57969..f33f0ee66304 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -669,9 +669,9 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
response.PutStringAsRawHex8(unescaped_response.GetData());
response.PutChar(';');
} else {
- LLDB_LOG(log, "failed to prepare a jstopinfo field for pid {0}:",
- m_debugged_process_up->GetID(),
- llvm::toString(threads_info.takeError()));
+ LLDB_LOG_ERROR(log, threads_info.takeError(),
+ "failed to prepare a jstopinfo field for pid {1}: {0}",
+ m_debugged_process_up->GetID());
}
}
@@ -2013,7 +2013,7 @@ GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) {
}
const uint8_t *const data =
- reinterpret_cast<const uint8_t *>(reg_value.GetBytes());
+ static_cast<const uint8_t *>(reg_value.GetBytes());
if (!data) {
LLDB_LOGF(log,
"GDBRemoteCommunicationServerLLGS::%s failed to get data "
@@ -3087,9 +3087,9 @@ GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo(
llvm::Expected<json::Value> threads_info = GetJSONThreadsInfo(
*m_debugged_process_up, threads_with_valid_stop_info_only);
if (!threads_info) {
- LLDB_LOG(log, "failed to prepare a packet for pid {0}: {1}",
- m_debugged_process_up->GetID(),
- llvm::toString(threads_info.takeError()));
+ LLDB_LOG_ERROR(log, threads_info.takeError(),
+ "failed to prepare a packet for pid {1}: {0}",
+ m_debugged_process_up->GetID());
return SendErrorResponse(52);
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index c06c9527708e..ec1a54afd727 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -31,9 +31,11 @@ using namespace lldb_private::process_gdb_remote;
// GDBRemoteRegisterContext constructor
GDBRemoteRegisterContext::GDBRemoteRegisterContext(
ThreadGDBRemote &thread, uint32_t concrete_frame_idx,
- GDBRemoteDynamicRegisterInfo &reg_info, bool read_all_at_once)
+ GDBRemoteDynamicRegisterInfo &reg_info, bool read_all_at_once,
+ bool write_all_at_once)
: RegisterContext(thread, concrete_frame_idx), m_reg_info(reg_info),
- m_reg_valid(), m_reg_data(), m_read_all_at_once(read_all_at_once) {
+ m_reg_valid(), m_reg_data(), m_read_all_at_once(read_all_at_once),
+ m_write_all_at_once(write_all_at_once) {
// Resize our vector of bools to contain one bool for every register. We will
// use these boolean values to know when a register value is valid in
// m_reg_data.
@@ -87,6 +89,9 @@ bool GDBRemoteRegisterContext::ReadRegister(const RegisterInfo *reg_info,
RegisterValue &value) {
// Read the register
if (ReadRegisterBytes(reg_info, m_reg_data)) {
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+ if (m_reg_valid[reg] == false)
+ return false;
const bool partial_data_ok = false;
Status error(value.SetValueFromData(
reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok));
@@ -203,6 +208,18 @@ bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
if (buffer_sp->GetByteSize() >= m_reg_data.GetByteSize()) {
SetAllRegisterValid(true);
return true;
+ } else if (buffer_sp->GetByteSize() > 0) {
+ const int regcount = m_reg_info.GetNumRegisters();
+ for (int i = 0; i < regcount; i++) {
+ struct RegisterInfo *reginfo = m_reg_info.GetRegisterInfoAtIndex(i);
+ if (reginfo->byte_offset + reginfo->byte_size
+ <= buffer_sp->GetByteSize()) {
+ m_reg_valid[i] = true;
+ } else {
+ m_reg_valid[i] = false;
+ }
+ }
+ return true;
} else {
Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_THREAD |
GDBR_LOG_PACKETS));
@@ -333,7 +350,7 @@ bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
{
GDBRemoteClientBase::Lock lock(gdb_comm, false);
if (lock) {
- if (m_read_all_at_once) {
+ if (m_write_all_at_once) {
// Invalidate all register values
InvalidateIfNeeded(true);
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index 25e9b716f8cb..b42c87b5991b 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -41,7 +41,7 @@ class GDBRemoteRegisterContext : public RegisterContext {
public:
GDBRemoteRegisterContext(ThreadGDBRemote &thread, uint32_t concrete_frame_idx,
GDBRemoteDynamicRegisterInfo &reg_info,
- bool read_all_at_once);
+ bool read_all_at_once, bool write_all_at_once);
~GDBRemoteRegisterContext() override;
@@ -114,6 +114,7 @@ protected:
std::vector<bool> m_reg_valid;
DataExtractor m_reg_data;
bool m_read_all_at_once;
+ bool m_write_all_at_once;
private:
// Helper function for ReadRegisterBytes().
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index f1762abc55f8..a49db5d9a934 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -10,7 +10,7 @@
#include <errno.h>
#include <stdlib.h>
-#ifndef LLDB_DISABLE_POSIX
+#if LLDB_ENABLE_POSIX
#include <netinet/in.h>
#include <sys/mman.h>
#include <sys/socket.h>
@@ -154,6 +154,11 @@ public:
nullptr, idx,
g_processgdbremote_properties[idx].default_uint_value != 0);
}
+
+ bool GetUseGPacketForReading() const {
+ const uint32_t idx = ePropertyUseGPacketForReading;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
+ }
};
typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP;
@@ -274,12 +279,9 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
"async thread did exit");
if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) {
- repro::ProcessGDBRemoteProvider &provider =
- g->GetOrCreate<repro::ProcessGDBRemoteProvider>();
- // Set the history stream to the stream owned by the provider.
- m_gdb_comm.SetHistoryStream(provider.GetHistoryStream());
- // Make sure to clear the stream again when we're finished.
- provider.SetCallback([&]() { m_gdb_comm.SetHistoryStream(nullptr); });
+ repro::GDBRemoteProvider &provider =
+ g->GetOrCreate<repro::GDBRemoteProvider>();
+ m_gdb_comm.SetPacketRecorder(provider.GetNewPacketRecorder());
}
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_ASYNC));
@@ -309,6 +311,9 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
GetGlobalPluginProperties()->GetPacketTimeout();
if (timeout_seconds > 0)
m_gdb_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds));
+
+ m_use_g_packet_for_reading =
+ GetGlobalPluginProperties()->GetUseGPacketForReading();
}
// Destructor
@@ -380,36 +385,6 @@ bool ProcessGDBRemote::ParsePythonTargetDefinition(
return false;
}
-// If the remote stub didn't give us eh_frame or DWARF register numbers for a
-// register, see if the ABI can provide them.
-// DWARF and eh_frame register numbers are defined as a part of the ABI.
-static void AugmentRegisterInfoViaABI(RegisterInfo &reg_info,
- ConstString reg_name, ABISP abi_sp) {
- if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM ||
- reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM) {
- if (abi_sp) {
- RegisterInfo abi_reg_info;
- if (abi_sp->GetRegisterInfoByName(reg_name, abi_reg_info)) {
- if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM &&
- abi_reg_info.kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) {
- reg_info.kinds[eRegisterKindEHFrame] =
- abi_reg_info.kinds[eRegisterKindEHFrame];
- }
- if (reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM &&
- abi_reg_info.kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM) {
- reg_info.kinds[eRegisterKindDWARF] =
- abi_reg_info.kinds[eRegisterKindDWARF];
- }
- if (reg_info.kinds[eRegisterKindGeneric] == LLDB_INVALID_REGNUM &&
- abi_reg_info.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) {
- reg_info.kinds[eRegisterKindGeneric] =
- abi_reg_info.kinds[eRegisterKindGeneric];
- }
- }
- }
- }
-}
-
static size_t SplitCommaSeparatedRegisterNumberString(
const llvm::StringRef &comma_separated_regiter_numbers,
std::vector<uint32_t> &regnums, int base) {
@@ -607,12 +582,12 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
reg_info.invalidate_regs = invalidate_regs.data();
}
+ reg_info.name = reg_name.AsCString();
// We have to make a temporary ABI here, and not use the GetABI because
// this code gets called in DidAttach, when the target architecture
// (and consequently the ABI we'll get from the process) may be wrong.
- ABISP abi_to_use = ABI::FindPlugin(shared_from_this(), arch_to_use);
-
- AugmentRegisterInfoViaABI(reg_info, reg_name, abi_to_use);
+ if (ABISP abi_sp = ABI::FindPlugin(shared_from_this(), arch_to_use))
+ abi_sp->AugmentRegisterInfo(reg_info);
m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);
} else {
@@ -2374,21 +2349,22 @@ void ProcessGDBRemote::RefreshStateAfterStop() {
m_thread_ids.clear();
m_thread_pcs.clear();
+
// Set the thread stop info. It might have a "threads" key whose value is a
// list of all thread IDs in the current process, so m_thread_ids might get
// set.
+ // Check to see if SetThreadStopInfo() filled in m_thread_ids?
+ if (m_thread_ids.empty()) {
+ // No, we need to fetch the thread list manually
+ UpdateThreadIDList();
+ }
+
+ // We might set some stop info's so make sure the thread list is up to
+ // date before we do that or we might overwrite what was computed here.
+ UpdateThreadListIfNeeded();
// Scope for the lock
{
- // Check to see if SetThreadStopInfo() filled in m_thread_ids?
- if (m_thread_ids.empty()) {
- // No, we need to fetch the thread list manually
- UpdateThreadIDList();
- }
- // We might set some stop info's so make sure the thread list is up to
- // date before we do that or we might overwrite what was computed here.
- UpdateThreadListIfNeeded();
-
// Lock the thread stack while we access it
std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex);
// Get the number of stop packets on the stack
@@ -3384,17 +3360,20 @@ Status ProcessGDBRemote::ConnectToReplayServer(repro::Loader *loader) {
if (!loader)
return Status("No loader provided.");
- // Construct replay history path.
- FileSpec history_file =
- loader->GetFile<repro::ProcessGDBRemoteProvider::Info>();
- if (!history_file)
- return Status("No provider for gdb-remote.");
+ static std::unique_ptr<repro::MultiLoader<repro::GDBRemoteProvider>>
+ multi_loader = repro::MultiLoader<repro::GDBRemoteProvider>::Create(
+ repro::Reproducer::Instance().GetLoader());
- // Enable replay mode.
- m_replay_mode = true;
+ if (!multi_loader)
+ return Status("No gdb remote provider found.");
+
+ llvm::Optional<std::string> history_file = multi_loader->GetNextFile();
+ if (!history_file)
+ return Status("No gdb remote packet log found.");
// Load replay history.
- if (auto error = m_gdb_replay_server.LoadReplayHistory(history_file))
+ if (auto error =
+ m_gdb_replay_server.LoadReplayHistory(FileSpec(*history_file)))
return Status("Unable to load replay history");
// Make a local connection.
@@ -3402,6 +3381,9 @@ Status ProcessGDBRemote::ConnectToReplayServer(repro::Loader *loader) {
m_gdb_replay_server))
return Status("Unable to connect to replay server");
+ // Enable replay mode.
+ m_replay_mode = true;
+
// Start server thread.
m_gdb_replay_server.StartAsyncThread();
@@ -3627,9 +3609,9 @@ bool ProcessGDBRemote::StartAsyncThread() {
llvm::Expected<HostThread> async_thread = ThreadLauncher::LaunchThread(
"<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this);
if (!async_thread) {
- LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST),
- "failed to launch host thread: {}",
- llvm::toString(async_thread.takeError()));
+ LLDB_LOG_ERROR(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST),
+ async_thread.takeError(),
+ "failed to launch host thread: {}");
return false;
}
m_async_thread = *async_thread;
@@ -4475,7 +4457,9 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
}
++cur_reg_num;
- AugmentRegisterInfoViaABI(reg_info, reg_name, abi_sp);
+ reg_info.name = reg_name.AsCString();
+ if (abi_sp)
+ abi_sp->AugmentRegisterInfo(reg_info);
dyn_reg_info.AddRegister(reg_info, reg_name, alt_name, set_name);
return true; // Keep iterating through all "reg" elements
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 0e3e3b39d9c8..9ea3940103b6 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -284,6 +284,7 @@ protected:
lldb::CommandObjectSP m_command_sp;
int64_t m_breakpoint_pc_offset;
lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach
+ bool m_use_g_packet_for_reading;
bool m_replay_mode;
bool m_allow_flash_writes;
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td
index 16e7723e3061..9cbe3d40ca2c 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteProperties.td
@@ -13,4 +13,8 @@ let Definition = "processgdbremote" in {
Global,
DefaultFalse,
Desc<"If true, the libraries-svr4 feature will be used to get a hold of the process's loaded modules.">;
+ def UseGPacketForReading: Property<"use-g-packet-for-reading", "Boolean">,
+ Global,
+ DefaultFalse,
+ Desc<"Specify if the server should use 'g' packets to read registers.">;
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 8a6a58c55450..9da481979f73 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -301,13 +301,14 @@ ThreadGDBRemote::CreateRegisterContextForFrame(StackFrame *frame) {
if (process_sp) {
ProcessGDBRemote *gdb_process =
static_cast<ProcessGDBRemote *>(process_sp.get());
- // read_all_registers_at_once will be true if 'p' packet is not
- // supported.
+ bool pSupported =
+ gdb_process->GetGDBRemote().GetpPacketSupported(GetID());
bool read_all_registers_at_once =
- !gdb_process->GetGDBRemote().GetpPacketSupported(GetID());
+ !pSupported || gdb_process->m_use_g_packet_for_reading;
+ bool write_all_registers_at_once = !pSupported;
reg_ctx_sp = std::make_shared<GDBRemoteRegisterContext>(
*this, concrete_frame_idx, gdb_process->m_register_info,
- read_all_registers_at_once);
+ read_all_registers_at_once, write_all_registers_at_once);
}
} else {
Unwind *unwinder = GetUnwinder();
diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
index 70933f91fe51..3c0e1cb49d1d 100644
--- a/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
+++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.cpp
@@ -174,6 +174,7 @@ ArchSpec MinidumpParser::GetArchitecture() {
triple.setArch(llvm::Triple::ArchType::arm);
break;
case ProcessorArchitecture::ARM64:
+ case ProcessorArchitecture::BP_ARM64:
triple.setArch(llvm::Triple::ArchType::aarch64);
break;
default:
@@ -518,58 +519,26 @@ CreateRegionsCacheFromMemory64List(MinidumpParser &parser,
return !regions.empty();
}
-MemoryRegionInfo
-MinidumpParser::FindMemoryRegion(lldb::addr_t load_addr) const {
- auto begin = m_regions.begin();
- auto end = m_regions.end();
- auto pos = std::lower_bound(begin, end, load_addr);
- if (pos != end && pos->GetRange().Contains(load_addr))
- return *pos;
-
- MemoryRegionInfo region;
- if (pos == begin)
- region.GetRange().SetRangeBase(0);
- else {
- auto prev = pos - 1;
- if (prev->GetRange().Contains(load_addr))
- return *prev;
- region.GetRange().SetRangeBase(prev->GetRange().GetRangeEnd());
- }
- if (pos == end)
- region.GetRange().SetRangeEnd(UINT64_MAX);
- else
- region.GetRange().SetRangeEnd(pos->GetRange().GetRangeBase());
- region.SetReadable(MemoryRegionInfo::eNo);
- region.SetWritable(MemoryRegionInfo::eNo);
- region.SetExecutable(MemoryRegionInfo::eNo);
- region.SetMapped(MemoryRegionInfo::eNo);
- return region;
-}
-
-MemoryRegionInfo
-MinidumpParser::GetMemoryRegionInfo(lldb::addr_t load_addr) {
- if (!m_parsed_regions)
- GetMemoryRegions();
- return FindMemoryRegion(load_addr);
-}
-
-const MemoryRegionInfos &MinidumpParser::GetMemoryRegions() {
- if (!m_parsed_regions) {
- m_parsed_regions = true;
- // We haven't cached our memory regions yet we will create the region cache
- // once. We create the region cache using the best source. We start with
- // the linux maps since they are the most complete and have names for the
- // regions. Next we try the MemoryInfoList since it has
- // read/write/execute/map data, and then fall back to the MemoryList and
- // Memory64List to just get a list of the memory that is mapped in this
- // core file
- if (!CreateRegionsCacheFromLinuxMaps(*this, m_regions))
- if (!CreateRegionsCacheFromMemoryInfoList(*this, m_regions))
- if (!CreateRegionsCacheFromMemoryList(*this, m_regions))
- CreateRegionsCacheFromMemory64List(*this, m_regions);
- llvm::sort(m_regions.begin(), m_regions.end());
- }
- return m_regions;
+std::pair<MemoryRegionInfos, bool> MinidumpParser::BuildMemoryRegions() {
+ // We create the region cache using the best source. We start with
+ // the linux maps since they are the most complete and have names for the
+ // regions. Next we try the MemoryInfoList since it has
+ // read/write/execute/map data, and then fall back to the MemoryList and
+ // Memory64List to just get a list of the memory that is mapped in this
+ // core file
+ MemoryRegionInfos result;
+ const auto &return_sorted = [&](bool is_complete) {
+ llvm::sort(result);
+ return std::make_pair(std::move(result), is_complete);
+ };
+ if (CreateRegionsCacheFromLinuxMaps(*this, result))
+ return return_sorted(true);
+ if (CreateRegionsCacheFromMemoryInfoList(*this, result))
+ return return_sorted(true);
+ if (CreateRegionsCacheFromMemoryList(*this, result))
+ return return_sorted(false);
+ CreateRegionsCacheFromMemory64List(*this, result);
+ return return_sorted(false);
}
#define ENUM_TO_CSTR(ST) \
diff --git a/lldb/source/Plugins/Process/minidump/MinidumpParser.h b/lldb/source/Plugins/Process/minidump/MinidumpParser.h
index d206fe6c9a00..4bcb2b47d45a 100644
--- a/lldb/source/Plugins/Process/minidump/MinidumpParser.h
+++ b/lldb/source/Plugins/Process/minidump/MinidumpParser.h
@@ -88,9 +88,9 @@ public:
llvm::ArrayRef<uint8_t> GetMemory(lldb::addr_t addr, size_t size);
- MemoryRegionInfo GetMemoryRegionInfo(lldb::addr_t load_addr);
-
- const MemoryRegionInfos &GetMemoryRegions();
+ /// Returns a list of memory regions and a flag indicating whether the list is
+ /// complete (includes all regions mapped into the process memory).
+ std::pair<MemoryRegionInfos, bool> BuildMemoryRegions();
static llvm::StringRef GetStreamTypeAsString(StreamType stream_type);
@@ -100,14 +100,10 @@ private:
MinidumpParser(lldb::DataBufferSP data_sp,
std::unique_ptr<llvm::object::MinidumpFile> file);
- MemoryRegionInfo FindMemoryRegion(lldb::addr_t load_addr) const;
-
private:
lldb::DataBufferSP m_data_sp;
std::unique_ptr<llvm::object::MinidumpFile> m_file;
ArchSpec m_arch;
- MemoryRegionInfos m_regions;
- bool m_parsed_regions = false;
};
} // end namespace minidump
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
index e30a3c82a887..5c090dc6e12f 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -334,15 +334,84 @@ ArchSpec ProcessMinidump::GetArchitecture() {
return ArchSpec(triple);
}
+static MemoryRegionInfo GetMemoryRegionInfo(const MemoryRegionInfos &regions,
+ lldb::addr_t load_addr) {
+ MemoryRegionInfo region;
+ auto pos = llvm::upper_bound(regions, load_addr);
+ if (pos != regions.begin() &&
+ std::prev(pos)->GetRange().Contains(load_addr)) {
+ return *std::prev(pos);
+ }
+
+ if (pos == regions.begin())
+ region.GetRange().SetRangeBase(0);
+ else
+ region.GetRange().SetRangeBase(std::prev(pos)->GetRange().GetRangeEnd());
+
+ if (pos == regions.end())
+ region.GetRange().SetRangeEnd(UINT64_MAX);
+ else
+ region.GetRange().SetRangeEnd(pos->GetRange().GetRangeBase());
+
+ region.SetReadable(MemoryRegionInfo::eNo);
+ region.SetWritable(MemoryRegionInfo::eNo);
+ region.SetExecutable(MemoryRegionInfo::eNo);
+ region.SetMapped(MemoryRegionInfo::eNo);
+ return region;
+}
+
+void ProcessMinidump::BuildMemoryRegions() {
+ if (m_memory_regions)
+ return;
+ m_memory_regions.emplace();
+ bool is_complete;
+ std::tie(*m_memory_regions, is_complete) =
+ m_minidump_parser->BuildMemoryRegions();
+
+ if (is_complete)
+ return;
+
+ MemoryRegionInfos to_add;
+ ModuleList &modules = GetTarget().GetImages();
+ SectionLoadList &load_list = GetTarget().GetSectionLoadList();
+ modules.ForEach([&](const ModuleSP &module_sp) {
+ SectionList *sections = module_sp->GetSectionList();
+ for (size_t i = 0; i < sections->GetSize(); ++i) {
+ SectionSP section_sp = sections->GetSectionAtIndex(i);
+ addr_t load_addr = load_list.GetSectionLoadAddress(section_sp);
+ if (load_addr == LLDB_INVALID_ADDRESS)
+ continue;
+ MemoryRegionInfo::RangeType section_range(load_addr,
+ section_sp->GetByteSize());
+ MemoryRegionInfo region =
+ ::GetMemoryRegionInfo(*m_memory_regions, load_addr);
+ if (region.GetMapped() != MemoryRegionInfo::eYes &&
+ region.GetRange().GetRangeBase() <= section_range.GetRangeBase() &&
+ section_range.GetRangeEnd() <= region.GetRange().GetRangeEnd()) {
+ to_add.emplace_back();
+ to_add.back().GetRange() = section_range;
+ to_add.back().SetLLDBPermissions(section_sp->GetPermissions());
+ to_add.back().SetMapped(MemoryRegionInfo::eYes);
+ to_add.back().SetName(module_sp->GetFileSpec().GetPath().c_str());
+ }
+ }
+ return true;
+ });
+ m_memory_regions->insert(m_memory_regions->end(), to_add.begin(),
+ to_add.end());
+ llvm::sort(*m_memory_regions);
+}
+
Status ProcessMinidump::GetMemoryRegionInfo(lldb::addr_t load_addr,
- MemoryRegionInfo &range_info) {
- range_info = m_minidump_parser->GetMemoryRegionInfo(load_addr);
+ MemoryRegionInfo &region) {
+ BuildMemoryRegions();
+ region = ::GetMemoryRegionInfo(*m_memory_regions, load_addr);
return Status();
}
-Status ProcessMinidump::GetMemoryRegions(
- lldb_private::MemoryRegionInfos &region_list) {
- region_list = m_minidump_parser->GetMemoryRegions();
+Status ProcessMinidump::GetMemoryRegions(MemoryRegionInfos &region_list) {
+ BuildMemoryRegions();
+ region_list = *m_memory_regions;
return Status();
}
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
index 22dc24af7c0e..750164cf8aaf 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.h
@@ -111,6 +111,9 @@ private:
const minidump::ExceptionStream *m_active_exception;
lldb::CommandObjectSP m_command_sp;
bool m_is_wow64;
+ llvm::Optional<MemoryRegionInfos> m_memory_regions;
+
+ void BuildMemoryRegions();
};
} // namespace minidump
diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp
new file mode 100644
index 000000000000..ecee8cc674f8
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp
@@ -0,0 +1,59 @@
+//===-- Lua.cpp -----------------------------------------------------------===//
+//
+// 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 "Lua.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Utility/FileSpec.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+llvm::Error Lua::Run(llvm::StringRef buffer) {
+ int error =
+ luaL_loadbuffer(m_lua_state, buffer.data(), buffer.size(), "buffer") ||
+ lua_pcall(m_lua_state, 0, 0, 0);
+ if (!error)
+ return llvm::Error::success();
+
+ llvm::Error e = llvm::make_error<llvm::StringError>(
+ llvm::formatv("{0}\n", lua_tostring(m_lua_state, -1)),
+ llvm::inconvertibleErrorCode());
+ // Pop error message from the stack.
+ lua_pop(m_lua_state, 1);
+ return e;
+}
+
+llvm::Error Lua::LoadModule(llvm::StringRef filename) {
+ FileSpec file(filename);
+ if (!FileSystem::Instance().Exists(file)) {
+ return llvm::make_error<llvm::StringError>("invalid path",
+ llvm::inconvertibleErrorCode());
+ }
+
+ ConstString module_extension = file.GetFileNameExtension();
+ if (module_extension != ".lua") {
+ return llvm::make_error<llvm::StringError>("invalid extension",
+ llvm::inconvertibleErrorCode());
+ }
+
+ int error = luaL_loadfile(m_lua_state, filename.data()) ||
+ lua_pcall(m_lua_state, 0, 1, 0);
+ if (error) {
+ llvm::Error e = llvm::make_error<llvm::StringError>(
+ llvm::formatv("{0}\n", lua_tostring(m_lua_state, -1)),
+ llvm::inconvertibleErrorCode());
+ // Pop error message from the stack.
+ lua_pop(m_lua_state, 1);
+ return e;
+ }
+
+ ConstString module_name = file.GetFileNameStrippingExtension();
+ lua_setglobal(m_lua_state, module_name.GetCString());
+ return llvm::Error::success();
+}
diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h
new file mode 100644
index 000000000000..f2984a925dfe
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.h
@@ -0,0 +1,48 @@
+//===-- ScriptInterpreterLua.h ----------------------------------*- C++ -*-===//
+//
+// 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 liblldb_Lua_h_
+#define liblldb_Lua_h_
+
+#include "lldb/lldb-types.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+
+#include "lua.hpp"
+
+#include <mutex>
+
+namespace lldb_private {
+
+extern "C" {
+int luaopen_lldb(lua_State *L);
+}
+
+class Lua {
+public:
+ Lua() : m_lua_state(luaL_newstate()) {
+ assert(m_lua_state);
+ luaL_openlibs(m_lua_state);
+ luaopen_lldb(m_lua_state);
+ }
+
+ ~Lua() {
+ assert(m_lua_state);
+ luaL_openlibs(m_lua_state);
+ }
+
+ llvm::Error Run(llvm::StringRef buffer);
+ llvm::Error LoadModule(llvm::StringRef filename);
+
+private:
+ lua_State *m_lua_state;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_Lua_h_
diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
new file mode 100644
index 000000000000..701d68d1ec08
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp
@@ -0,0 +1,157 @@
+//===-- ScriptInterpreterLua.cpp --------------------------------*- C++ -*-===//
+//
+// 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 "ScriptInterpreterLua.h"
+#include "Lua.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Utility/Stream.h"
+#include "lldb/Utility/StringList.h"
+#include "lldb/Utility/Timer.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+class IOHandlerLuaInterpreter : public IOHandlerDelegate,
+ public IOHandlerEditline {
+public:
+ IOHandlerLuaInterpreter(Debugger &debugger,
+ ScriptInterpreterLua &script_interpreter)
+ : IOHandlerEditline(debugger, IOHandler::Type::LuaInterpreter, "lua",
+ ">>> ", "..> ", true, debugger.GetUseColor(), 0,
+ *this, nullptr),
+ m_script_interpreter(script_interpreter) {
+ llvm::cantFail(m_script_interpreter.EnterSession(debugger.GetID()));
+ }
+
+ ~IOHandlerLuaInterpreter() {
+ llvm::cantFail(m_script_interpreter.LeaveSession());
+ }
+
+ void IOHandlerInputComplete(IOHandler &io_handler,
+ std::string &data) override {
+ if (llvm::Error error = m_script_interpreter.GetLua().Run(data)) {
+ *GetOutputStreamFileSP() << llvm::toString(std::move(error));
+ }
+ }
+
+private:
+ ScriptInterpreterLua &m_script_interpreter;
+};
+
+ScriptInterpreterLua::ScriptInterpreterLua(Debugger &debugger)
+ : ScriptInterpreter(debugger, eScriptLanguageLua),
+ m_lua(std::make_unique<Lua>()) {}
+
+ScriptInterpreterLua::~ScriptInterpreterLua() {}
+
+bool ScriptInterpreterLua::ExecuteOneLine(llvm::StringRef command,
+ CommandReturnObject *result,
+ const ExecuteScriptOptions &options) {
+ if (llvm::Error e = m_lua->Run(command)) {
+ result->AppendErrorWithFormatv(
+ "lua failed attempting to evaluate '{0}': {1}\n", command,
+ llvm::toString(std::move(e)));
+ return false;
+ }
+ return true;
+}
+
+void ScriptInterpreterLua::ExecuteInterpreterLoop() {
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
+
+ Debugger &debugger = m_debugger;
+
+ // At the moment, the only time the debugger does not have an input file
+ // handle is when this is called directly from lua, in which case it is
+ // both dangerous and unnecessary (not to mention confusing) to try to embed
+ // a running interpreter loop inside the already running lua interpreter
+ // loop, so we won't do it.
+
+ if (!debugger.GetInputFile().IsValid())
+ return;
+
+ IOHandlerSP io_handler_sp(new IOHandlerLuaInterpreter(debugger, *this));
+ debugger.PushIOHandler(io_handler_sp);
+}
+
+bool ScriptInterpreterLua::LoadScriptingModule(
+ const char *filename, bool init_session, lldb_private::Status &error,
+ StructuredData::ObjectSP *module_sp) {
+
+ if (llvm::Error e = m_lua->LoadModule(filename)) {
+ error.SetErrorStringWithFormatv("lua failed to import '{0}': {1}\n",
+ filename, llvm::toString(std::move(e)));
+ return false;
+ }
+ return true;
+}
+
+void ScriptInterpreterLua::Initialize() {
+ static llvm::once_flag g_once_flag;
+
+ llvm::call_once(g_once_flag, []() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(),
+ lldb::eScriptLanguageLua, CreateInstance);
+ });
+}
+
+void ScriptInterpreterLua::Terminate() {}
+
+llvm::Error ScriptInterpreterLua::EnterSession(user_id_t debugger_id) {
+ if (m_session_is_active)
+ return llvm::Error::success();
+
+ const char *fmt_str =
+ "lldb.debugger = lldb.SBDebugger.FindDebuggerWithID({0}); "
+ "lldb.target = lldb.debugger:GetSelectedTarget(); "
+ "lldb.process = lldb.target:GetProcess(); "
+ "lldb.thread = lldb.process:GetSelectedThread(); "
+ "lldb.frame = lldb.thread:GetSelectedFrame()";
+ return m_lua->Run(llvm::formatv(fmt_str, debugger_id).str());
+}
+
+llvm::Error ScriptInterpreterLua::LeaveSession() {
+ if (!m_session_is_active)
+ return llvm::Error::success();
+
+ m_session_is_active = false;
+
+ llvm::StringRef str = "lldb.debugger = nil; "
+ "lldb.target = nil; "
+ "lldb.process = nil; "
+ "lldb.thread = nil; "
+ "lldb.frame = nil";
+ return m_lua->Run(str);
+}
+
+lldb::ScriptInterpreterSP
+ScriptInterpreterLua::CreateInstance(Debugger &debugger) {
+ return std::make_shared<ScriptInterpreterLua>(debugger);
+}
+
+lldb_private::ConstString ScriptInterpreterLua::GetPluginNameStatic() {
+ static ConstString g_name("script-lua");
+ return g_name;
+}
+
+const char *ScriptInterpreterLua::GetPluginDescriptionStatic() {
+ return "Lua script interpreter";
+}
+
+lldb_private::ConstString ScriptInterpreterLua::GetPluginName() {
+ return GetPluginNameStatic();
+}
+
+uint32_t ScriptInterpreterLua::GetPluginVersion() { return 1; }
+
+Lua &ScriptInterpreterLua::GetLua() { return *m_lua; }
diff --git a/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
new file mode 100644
index 000000000000..4e922151385b
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h
@@ -0,0 +1,61 @@
+//===-- ScriptInterpreterLua.h ----------------------------------*- C++ -*-===//
+//
+// 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 liblldb_ScriptInterpreterLua_h_
+#define liblldb_ScriptInterpreterLua_h_
+
+#include "lldb/Interpreter/ScriptInterpreter.h"
+
+namespace lldb_private {
+class Lua;
+class ScriptInterpreterLua : public ScriptInterpreter {
+public:
+ ScriptInterpreterLua(Debugger &debugger);
+
+ ~ScriptInterpreterLua() override;
+
+ bool ExecuteOneLine(
+ llvm::StringRef command, CommandReturnObject *result,
+ const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
+
+ void ExecuteInterpreterLoop() override;
+
+ virtual bool
+ LoadScriptingModule(const char *filename, bool init_session,
+ lldb_private::Status &error,
+ StructuredData::ObjectSP *module_sp = nullptr) override;
+
+ // Static Functions
+ static void Initialize();
+
+ static void Terminate();
+
+ static lldb::ScriptInterpreterSP CreateInstance(Debugger &debugger);
+
+ static lldb_private::ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic();
+
+ // PluginInterface protocol
+ lldb_private::ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+
+ Lua &GetLua();
+
+ llvm::Error EnterSession(lldb::user_id_t debugger_id);
+ llvm::Error LeaveSession();
+
+private:
+ std::unique_ptr<Lua> m_lua;
+ bool m_session_is_active = false;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ScriptInterpreterLua_h_
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
index 70d93424fdec..e5a67653e334 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
@@ -6,11 +6,9 @@
//
//===----------------------------------------------------------------------===//
-#ifdef LLDB_DISABLE_PYTHON
+#include "lldb/Host/Config.h"
-// Python is disabled in this build
-
-#else
+#if LLDB_ENABLE_PYTHON
#include "PythonDataObjects.h"
#include "ScriptInterpreterPython.h"
@@ -802,29 +800,11 @@ bool PythonCallable::Check(PyObject *py_obj) {
return PyCallable_Check(py_obj);
}
-PythonCallable::ArgInfo PythonCallable::GetNumInitArguments() const {
- auto arginfo = GetInitArgInfo();
- if (!arginfo) {
- llvm::consumeError(arginfo.takeError());
- return ArgInfo{};
- }
- return arginfo.get();
-}
-
-Expected<PythonCallable::ArgInfo> PythonCallable::GetInitArgInfo() const {
- if (!IsValid())
- return nullDeref();
- auto init = As<PythonCallable>(GetAttribute("__init__"));
- if (!init)
- return init.takeError();
- return init.get().GetArgInfo();
-}
-
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
static const char get_arg_info_script[] = R"(
from inspect import signature, Parameter, ismethod
from collections import namedtuple
-ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs', 'is_bound_method'])
+ArgInfo = namedtuple('ArgInfo', ['count', 'has_varargs'])
def main(f):
count = 0
varargs = False
@@ -840,7 +820,7 @@ def main(f):
pass
else:
raise Exception(f'unknown parameter kind: {kind}')
- return ArgInfo(count, varargs, ismethod(f))
+ return ArgInfo(count, varargs)
)";
#endif
@@ -856,21 +836,27 @@ Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const {
Expected<PythonObject> pyarginfo = get_arg_info(*this);
if (!pyarginfo)
return pyarginfo.takeError();
- result.count = cantFail(As<long long>(pyarginfo.get().GetAttribute("count")));
- result.has_varargs =
+ long long count =
+ cantFail(As<long long>(pyarginfo.get().GetAttribute("count")));
+ bool has_varargs =
cantFail(As<bool>(pyarginfo.get().GetAttribute("has_varargs")));
- bool is_method =
- cantFail(As<bool>(pyarginfo.get().GetAttribute("is_bound_method")));
- result.max_positional_args =
- result.has_varargs ? ArgInfo::UNBOUNDED : result.count;
-
- // FIXME emulate old broken behavior
- if (is_method)
- result.count++;
+ result.max_positional_args = has_varargs ? ArgInfo::UNBOUNDED : count;
#else
+ PyObject *py_func_obj;
bool is_bound_method = false;
- PyObject *py_func_obj = m_py_obj;
+ bool is_class = false;
+
+ if (PyType_Check(m_py_obj) || PyClass_Check(m_py_obj)) {
+ auto init = GetAttribute("__init__");
+ if (!init)
+ return init.takeError();
+ py_func_obj = init.get().get();
+ is_class = true;
+ } else {
+ py_func_obj = m_py_obj;
+ }
+
if (PyMethod_Check(py_func_obj)) {
py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
PythonObject im_self = GetAttributeValue("im_self");
@@ -899,11 +885,11 @@ Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const {
if (!code)
return result;
- result.count = code->co_argcount;
- result.has_varargs = !!(code->co_flags & CO_VARARGS);
- result.max_positional_args = result.has_varargs
- ? ArgInfo::UNBOUNDED
- : (result.count - (int)is_bound_method);
+ auto count = code->co_argcount;
+ bool has_varargs = !!(code->co_flags & CO_VARARGS);
+ result.max_positional_args =
+ has_varargs ? ArgInfo::UNBOUNDED
+ : (count - (int)is_bound_method) - (int)is_class;
#endif
@@ -913,15 +899,6 @@ Expected<PythonCallable::ArgInfo> PythonCallable::GetArgInfo() const {
constexpr unsigned
PythonCallable::ArgInfo::UNBOUNDED; // FIXME delete after c++17
-PythonCallable::ArgInfo PythonCallable::GetNumArguments() const {
- auto arginfo = GetArgInfo();
- if (!arginfo) {
- llvm::consumeError(arginfo.takeError());
- return ArgInfo{};
- }
- return arginfo.get();
-}
-
PythonObject PythonCallable::operator()() {
return PythonObject(PyRefType::Owned, PyObject_CallObject(m_py_obj, nullptr));
}
@@ -1385,11 +1362,13 @@ llvm::Expected<FileSP> PythonFile::ConvertToFile(bool borrowed) {
if (!options)
return options.takeError();
- // LLDB and python will not share I/O buffers. We should probably
- // flush the python buffers now.
- auto r = CallMethod("flush");
- if (!r)
- return r.takeError();
+ if (options.get() & File::eOpenOptionWrite) {
+ // LLDB and python will not share I/O buffers. We should probably
+ // flush the python buffers now.
+ auto r = CallMethod("flush");
+ if (!r)
+ return r.takeError();
+ }
FileSP file_sp;
if (borrowed) {
@@ -1498,14 +1477,23 @@ Expected<PythonFile> PythonFile::FromFile(File &file, const char *mode) {
PyObject *file_obj;
#if PY_MAJOR_VERSION >= 3
file_obj = PyFile_FromFd(file.GetDescriptor(), nullptr, mode, -1, nullptr,
- "ignore", nullptr, 0);
+ "ignore", nullptr, /*closefd=*/0);
#else
- // Read through the Python source, doesn't seem to modify these strings
- char *cmode = const_cast<char *>(mode);
- // We pass ::flush instead of ::fclose here so we borrow the FILE* --
- // the lldb_private::File still owns it.
- file_obj =
- PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, ::fflush);
+ // I'd like to pass ::fflush here if the file is writable, so that
+ // when the python side destructs the file object it will be flushed.
+ // However, this would be dangerous. It can cause fflush to be called
+ // after fclose if the python program keeps a reference to the file after
+ // the original lldb_private::File has been destructed.
+ //
+ // It's all well and good to ask a python program not to use a closed file
+ // but asking a python program to make sure objects get released in a
+ // particular order is not safe.
+ //
+ // The tradeoff here is that if a python 2 program wants to make sure this
+ // file gets flushed, they'll have to do it explicitly or wait untill the
+ // original lldb File itself gets flushed.
+ file_obj = PyFile_FromFile(file.GetStream(), py2_const_cast(""),
+ py2_const_cast(mode), [](FILE *) { return 0; });
#endif
if (!file_obj)
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
index 373d3212697d..b75045b239a8 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
@@ -48,7 +48,9 @@
#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
-#ifndef LLDB_DISABLE_PYTHON
+#include "lldb/Host/Config.h"
+
+#if LLDB_ENABLE_PYTHON
// LLDB Python header must be included first
#include "lldb-python.h"
@@ -130,7 +132,7 @@ template <typename T> T Take(PyObject *obj) {
assert(!PyErr_Occurred());
T thing(PyRefType::Owned, obj);
assert(thing.IsValid());
- return std::move(thing);
+ return thing;
}
// Retain a reference you have borrowed, and turn it into
@@ -148,7 +150,7 @@ template <typename T> T Retain(PyObject *obj) {
assert(!PyErr_Occurred());
T thing(PyRefType::Borrowed, obj);
assert(thing.IsValid());
- return std::move(thing);
+ return thing;
}
// This class can be used like a utility function to convert from
@@ -189,6 +191,14 @@ inline llvm::Error keyError() {
"key not in dict");
}
+#if PY_MAJOR_VERSION < 3
+// The python 2 API declares some arguments as char* that should
+// be const char *, but it doesn't actually modify them.
+inline char *py2_const_cast(const char *s) { return const_cast<char *>(s); }
+#else
+inline const char *py2_const_cast(const char *s) { return s; }
+#endif
+
enum class PyInitialValue { Invalid, Empty };
template <typename T, typename Enable = void> struct PythonFormat;
@@ -309,16 +319,6 @@ public:
StructuredData::ObjectSP CreateStructuredObject() const;
-protected:
-
-#if PY_MAJOR_VERSION < 3
- // The python 2 API declares some arguments as char* that should
- // be const char *, but it doesn't actually modify them.
- static char *py2_const_cast(const char *s) { return const_cast<char *>(s); }
-#else
- static const char *py2_const_cast(const char *s) { return s; }
-#endif
-
public:
template <typename... T>
llvm::Expected<PythonObject> CallMethod(const char *name,
@@ -621,30 +621,12 @@ public:
* function and can accept an arbitrary number */
unsigned max_positional_args;
static constexpr unsigned UNBOUNDED = UINT_MAX; // FIXME c++17 inline
- /* the number of positional arguments, including optional ones,
- * and excluding varargs. If this is a bound method, then the
- * count will still include a +1 for self.
- *
- * FIXME. That's crazy. This should be replaced with
- * an accurate min and max for positional args.
- */
- int count;
- /* does the callable have positional varargs? */
- bool has_varargs : 1; // FIXME delete this
};
static bool Check(PyObject *py_obj);
llvm::Expected<ArgInfo> GetArgInfo() const;
- llvm::Expected<ArgInfo> GetInitArgInfo() const;
-
- ArgInfo GetNumArguments() const; // DEPRECATED
-
- // If the callable is a Py_Class, then find the number of arguments
- // of the __init__ method.
- ArgInfo GetNumInitArguments() const; // DEPRECATED
-
PythonObject operator()();
PythonObject operator()(std::initializer_list<PyObject *> args);
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
new file mode 100644
index 000000000000..5f6429f5cd0e
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp
@@ -0,0 +1,88 @@
+#include "PythonReadline.h"
+
+#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
+
+#include <stdio.h>
+
+#include <editline/readline.h>
+
+// Simple implementation of the Python readline module using libedit.
+// In the event that libedit is excluded from the build, this turns
+// back into a null implementation that blocks the module from pulling
+// in the GNU readline shared lib, which causes linkage confusion when
+// both readline and libedit's readline compatibility symbols collide.
+//
+// Currently it only installs a PyOS_ReadlineFunctionPointer, without
+// implementing any of the readline module methods. This is meant to
+// work around LLVM pr18841 to avoid seg faults in the stock Python
+// readline.so linked against GNU readline.
+//
+// Bug on the cpython side: https://bugs.python.org/issue38634
+
+PyDoc_STRVAR(moduleDocumentation,
+ "Simple readline module implementation based on libedit.");
+
+#if PY_MAJOR_VERSION >= 3
+static struct PyModuleDef readline_module = {
+ PyModuleDef_HEAD_INIT, // m_base
+ "lldb_editline", // m_name
+ moduleDocumentation, // m_doc
+ -1, // m_size
+ nullptr, // m_methods
+ nullptr, // m_reload
+ nullptr, // m_traverse
+ nullptr, // m_clear
+ nullptr, // m_free
+};
+#else
+static struct PyMethodDef moduleMethods[] = {{nullptr, nullptr, 0, nullptr}};
+#endif
+
+static char *
+#if PY_MAJOR_VERSION >= 3
+simple_readline(FILE *stdin, FILE *stdout, const char *prompt)
+#else
+simple_readline(FILE *stdin, FILE *stdout, char *prompt)
+#endif
+{
+ rl_instream = stdin;
+ rl_outstream = stdout;
+ char *line = readline(prompt);
+ if (!line) {
+#if PY_MAJOR_VERSION >= 3
+ char *ret = (char *)PyMem_RawMalloc(1);
+#else
+ char *ret = (char *)PyMem_Malloc(1);
+#endif
+ if (ret != NULL)
+ *ret = '\0';
+ return ret;
+ }
+ if (*line)
+ add_history(line);
+ int n = strlen(line);
+#if PY_MAJOR_VERSION >= 3
+ char *ret = (char *)PyMem_RawMalloc(n + 2);
+#else
+ char *ret = (char *)PyMem_Malloc(n + 2);
+#endif
+ if (ret) {
+ memcpy(ret, line, n);
+ free(line);
+ ret[n] = '\n';
+ ret[n + 1] = '\0';
+ }
+ return ret;
+}
+
+PyMODINIT_FUNC initlldb_readline(void) {
+ PyOS_ReadlineFunctionPointer = simple_readline;
+
+#if PY_MAJOR_VERSION >= 3
+ return PyModule_Create(&readline_module);
+#else
+ Py_InitModule4("readline", moduleMethods, moduleDocumentation,
+ static_cast<PyObject *>(NULL), PYTHON_API_VERSION);
+#endif
+}
+#endif
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.h b/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.h
new file mode 100644
index 000000000000..c75219eb1a4f
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.h
@@ -0,0 +1,28 @@
+//===-- PythonReadline.h ----------------------------------------*- C++ -*-===//
+//
+// 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_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONREADLINE_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONREADLINE_H
+
+#include "lldb/Host/Config.h"
+
+#if LLDB_ENABLE_LIBEDIT && defined(__linux__)
+// NOTE: Since Python may define some pre-processor definitions which affect the
+// standard headers on some systems, you must include Python.h before any
+// standard headers are included.
+#include "Python.h"
+
+// no need to hack into Python's readline module if libedit isn't used.
+//
+#define LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE 1
+
+PyMODINIT_FUNC initlldb_readline(void);
+
+#endif
+
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONREADLINE_H
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index 3eee52184142..06e0d5bfa63f 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -6,16 +6,15 @@
//
//===----------------------------------------------------------------------===//
-#ifdef LLDB_DISABLE_PYTHON
+#include "lldb/Host/Config.h"
-// Python is disabled in this build
-
-#else
+#if LLDB_ENABLE_PYTHON
// LLDB Python header must be included first
#include "lldb-python.h"
#include "PythonDataObjects.h"
+#include "PythonReadline.h"
#include "ScriptInterpreterPythonImpl.h"
#include "lldb/API/SBFrame.h"
@@ -72,10 +71,28 @@ extern "C" void init_lldb(void);
// These prototypes are the Pythonic implementations of the required callbacks.
// Although these are scripting-language specific, their definition depends on
// the public API.
-extern "C" bool LLDBSwigPythonBreakpointCallbackFunction(
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
+
+// Disable warning C4190: 'LLDBSwigPythonBreakpointCallbackFunction' has
+// C-linkage specified, but returns UDT 'llvm::Expected<bool>' which is
+// incompatible with C
+#if _MSC_VER
+#pragma warning (push)
+#pragma warning (disable : 4190)
+#endif
+
+extern "C" llvm::Expected<bool> LLDBSwigPythonBreakpointCallbackFunction(
const char *python_function_name, const char *session_dictionary_name,
const lldb::StackFrameSP &sb_frame,
- const lldb::BreakpointLocationSP &sb_bp_loc);
+ const lldb::BreakpointLocationSP &sb_bp_loc, StructuredDataImpl *args_impl);
+
+#if _MSC_VER
+#pragma warning (pop)
+#endif
+
+#pragma clang diagnostic pop
extern "C" bool LLDBSwigPythonWatchpointCallbackFunction(
const char *python_function_name, const char *session_dictionary_name,
@@ -211,6 +228,22 @@ public:
InitializePythonHome();
+#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
+ // Python's readline is incompatible with libedit being linked into lldb.
+ // Provide a patched version local to the embedded interpreter.
+ bool ReadlinePatched = false;
+ for (auto *p = PyImport_Inittab; p->name != NULL; p++) {
+ if (strcmp(p->name, "readline") == 0) {
+ p->initfunc = initlldb_readline;
+ break;
+ }
+ }
+ if (!ReadlinePatched) {
+ PyImport_AppendInittab("readline", initlldb_readline);
+ ReadlinePatched = true;
+ }
+#endif
+
// Register _lldb as a built-in module.
PyImport_AppendInittab("_lldb", LLDBSwigPyInit);
@@ -552,8 +585,10 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler,
break;
data_up->user_source.SplitIntoLines(data);
+ StructuredData::ObjectSP empty_args_sp;
if (GenerateBreakpointCommandCallbackData(data_up->user_source,
- data_up->script_source)
+ data_up->script_source,
+ false)
.Success()) {
auto baton_sp = std::make_shared<BreakpointOptions::CommandBaton>(
std::move(data_up));
@@ -779,6 +814,32 @@ PythonDictionary &ScriptInterpreterPythonImpl::GetSysModuleDictionary() {
return m_sys_module_dict;
}
+llvm::Expected<unsigned>
+ScriptInterpreterPythonImpl::GetMaxPositionalArgumentsForCallable(
+ const llvm::StringRef &callable_name) {
+ if (callable_name.empty()) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "called with empty callable name.");
+ }
+ Locker py_lock(this, Locker::AcquireLock |
+ Locker::InitSession |
+ Locker::NoSTDIN);
+ auto dict = PythonModule::MainModule()
+ .ResolveName<PythonDictionary>(m_dictionary_name);
+ auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
+ callable_name, dict);
+ if (!pfunc.IsAllocated()) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "can't find callable: %s", callable_name.str().c_str());
+ }
+ llvm::Expected<PythonCallable::ArgInfo> arg_info = pfunc.GetArgInfo();
+ if (!arg_info)
+ return arg_info.takeError();
+ return arg_info.get().max_positional_args;
+}
+
static std::string GenerateUniqueName(const char *base_name_wanted,
uint32_t &functions_counter,
const void *name_token = nullptr) {
@@ -1139,6 +1200,7 @@ bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn(
return true;
}
}
+ llvm_unreachable("Fully covered switch!");
}
Status ScriptInterpreterPythonImpl::ExecuteMultipleLines(
@@ -1186,24 +1248,56 @@ void ScriptInterpreterPythonImpl::CollectDataForBreakpointCommandCallback(
CommandReturnObject &result) {
m_active_io_handler = eIOHandlerBreakpoint;
m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(
- " ", *this, true, &bp_options_vec);
+ " ", *this, &bp_options_vec);
}
void ScriptInterpreterPythonImpl::CollectDataForWatchpointCommandCallback(
WatchpointOptions *wp_options, CommandReturnObject &result) {
m_active_io_handler = eIOHandlerWatchpoint;
m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(
- " ", *this, true, wp_options);
+ " ", *this, wp_options);
}
-void ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction(
- BreakpointOptions *bp_options, const char *function_name) {
+Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction(
+ BreakpointOptions *bp_options, const char *function_name,
+ StructuredData::ObjectSP extra_args_sp) {
+ Status error;
// For now just cons up a oneliner that calls the provided function.
std::string oneliner("return ");
oneliner += function_name;
- oneliner += "(frame, bp_loc, internal_dict)";
- m_debugger.GetScriptInterpreter()->SetBreakpointCommandCallback(
- bp_options, oneliner.c_str());
+
+ llvm::Expected<unsigned> maybe_args =
+ GetMaxPositionalArgumentsForCallable(function_name);
+ if (!maybe_args) {
+ error.SetErrorStringWithFormat(
+ "could not get num args: %s",
+ llvm::toString(maybe_args.takeError()).c_str());
+ return error;
+ }
+ size_t max_args = *maybe_args;
+
+ bool uses_extra_args = false;
+ if (max_args >= 4) {
+ uses_extra_args = true;
+ oneliner += "(frame, bp_loc, extra_args, internal_dict)";
+ } else if (max_args >= 3) {
+ if (extra_args_sp) {
+ error.SetErrorString("cannot pass extra_args to a three argument callback"
+ );
+ return error;
+ }
+ uses_extra_args = false;
+ oneliner += "(frame, bp_loc, internal_dict)";
+ } else {
+ error.SetErrorStringWithFormat("expected 3 or 4 argument "
+ "function, %s can only take %zu",
+ function_name, max_args);
+ return error;
+ }
+
+ SetBreakpointCommandCallback(bp_options, oneliner.c_str(), extra_args_sp,
+ uses_extra_args);
+ return error;
}
Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
@@ -1211,7 +1305,8 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
std::unique_ptr<BreakpointOptions::CommandData> &cmd_data_up) {
Status error;
error = GenerateBreakpointCommandCallbackData(cmd_data_up->user_source,
- cmd_data_up->script_source);
+ cmd_data_up->script_source,
+ false);
if (error.Fail()) {
return error;
}
@@ -1222,11 +1317,17 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
return error;
}
-// Set a Python one-liner as the callback for the breakpoint.
Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
BreakpointOptions *bp_options, const char *command_body_text) {
- auto data_up = std::make_unique<CommandDataPython>();
+ return SetBreakpointCommandCallback(bp_options, command_body_text, {},false);
+}
+// Set a Python one-liner as the callback for the breakpoint.
+Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
+ BreakpointOptions *bp_options, const char *command_body_text,
+ StructuredData::ObjectSP extra_args_sp,
+ bool uses_extra_args) {
+ auto data_up = std::make_unique<CommandDataPython>(extra_args_sp);
// Split the command_body_text into lines, and pass that to
// GenerateBreakpointCommandCallbackData. That will wrap the body in an
// auto-generated function, and return the function name in script_source.
@@ -1234,7 +1335,8 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
data_up->user_source.SplitIntoLines(command_body_text);
Status error = GenerateBreakpointCommandCallbackData(data_up->user_source,
- data_up->script_source);
+ data_up->script_source,
+ uses_extra_args);
if (error.Success()) {
auto baton_sp =
std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up));
@@ -1771,8 +1873,7 @@ StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_CreateThread(
StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan(
const char *class_name, StructuredDataImpl *args_data,
- std::string &error_str,
- lldb::ThreadPlanSP thread_plan_sp) {
+ std::string &error_str, lldb::ThreadPlanSP thread_plan_sp) {
if (class_name == nullptr || class_name[0] == '\0')
return StructuredData::ObjectSP();
@@ -1956,8 +2057,7 @@ ScriptInterpreterPythonImpl::LoadPluginModule(const FileSpec &file_spec,
StructuredData::ObjectSP module_sp;
- if (LoadScriptingModule(file_spec.GetPath().c_str(), true, true, error,
- &module_sp))
+ if (LoadScriptingModule(file_spec.GetPath().c_str(), true, error, &module_sp))
return module_sp;
return StructuredData::ObjectSP();
@@ -2063,7 +2163,8 @@ bool ScriptInterpreterPythonImpl::GenerateTypeSynthClass(
}
Status ScriptInterpreterPythonImpl::GenerateBreakpointCommandCallbackData(
- StringList &user_input, std::string &output) {
+ StringList &user_input, std::string &output,
+ bool has_extra_args) {
static uint32_t num_created_functions = 0;
user_input.RemoveBlankLines();
StreamString sstr;
@@ -2075,8 +2176,12 @@ Status ScriptInterpreterPythonImpl::GenerateBreakpointCommandCallbackData(
std::string auto_generated_function_name(GenerateUniqueName(
"lldb_autogen_python_bp_callback_func_", num_created_functions));
- sstr.Printf("def %s (frame, bp_loc, internal_dict):",
- auto_generated_function_name.c_str());
+ if (has_extra_args)
+ sstr.Printf("def %s (frame, bp_loc, extra_args, internal_dict):",
+ auto_generated_function_name.c_str());
+ else
+ sstr.Printf("def %s (frame, bp_loc, internal_dict):",
+ auto_generated_function_name.c_str());
error = GenerateFunction(sstr.GetData(), user_input);
if (!error.Success())
@@ -2193,10 +2298,26 @@ bool ScriptInterpreterPythonImpl::BreakpointCallbackFunction(
Locker py_lock(python_interpreter, Locker::AcquireLock |
Locker::InitSession |
Locker::NoSTDIN);
- ret_val = LLDBSwigPythonBreakpointCallbackFunction(
- python_function_name,
- python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,
- bp_loc_sp);
+ Expected<bool> maybe_ret_val =
+ LLDBSwigPythonBreakpointCallbackFunction(
+ python_function_name,
+ python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,
+ bp_loc_sp, bp_option_data->m_extra_args_up.get());
+
+ if (!maybe_ret_val) {
+
+ llvm::handleAllErrors(
+ maybe_ret_val.takeError(),
+ [&](PythonException &E) {
+ debugger.GetErrorStream() << E.ReadBacktrace();
+ },
+ [&](const llvm::ErrorInfoBase &E) {
+ debugger.GetErrorStream() << E.message();
+ });
+
+ } else {
+ ret_val = maybe_ret_val.get();
+ }
}
return ret_val;
}
@@ -2615,8 +2736,8 @@ uint64_t replace_all(std::string &str, const std::string &oldStr,
}
bool ScriptInterpreterPythonImpl::LoadScriptingModule(
- const char *pathname, bool can_reload, bool init_session,
- lldb_private::Status &error, StructuredData::ObjectSP *module_sp) {
+ const char *pathname, bool init_session, lldb_private::Status &error,
+ StructuredData::ObjectSP *module_sp) {
if (!pathname || !pathname[0]) {
error.SetErrorString("invalid pathname");
return false;
@@ -2716,11 +2837,6 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule(
bool was_imported = (was_imported_globally || was_imported_locally);
- if (was_imported && !can_reload) {
- error.SetErrorString("module already imported");
- return false;
- }
-
// now actually do the import
command_stream.Clear();
@@ -3171,4 +3287,4 @@ void ScriptInterpreterPythonImpl::AddToSysPath(AddLocation location,
//
// void ScriptInterpreterPythonImpl::Terminate() { Py_Finalize (); }
-#endif // LLDB_DISABLE_PYTHON
+#endif
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
index 33ae308041b2..e59fedbd0971 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
@@ -9,14 +9,13 @@
#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHON_H
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHON_H
-#ifdef LLDB_DISABLE_PYTHON
+#include "lldb/Host/Config.h"
-// Python is disabled in this build
-
-#else
+#if LLDB_ENABLE_PYTHON
#include "lldb/Breakpoint/BreakpointOptions.h"
#include "lldb/Core/IOHandler.h"
+#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/lldb-private.h"
@@ -34,6 +33,13 @@ public:
CommandDataPython() : BreakpointOptions::CommandData() {
interpreter = lldb::eScriptLanguagePython;
}
+ CommandDataPython(StructuredData::ObjectSP extra_args_sp) :
+ BreakpointOptions::CommandData(),
+ m_extra_args_up(new StructuredDataImpl()) {
+ interpreter = lldb::eScriptLanguagePython;
+ m_extra_args_up->SetObjectSP(extra_args_sp);
+ }
+ lldb::StructuredDataImplUP m_extra_args_up;
};
ScriptInterpreterPython(Debugger &debugger)
@@ -52,5 +58,5 @@ protected:
};
} // namespace lldb_private
-#endif // LLDB_DISABLE_PYTHON
+#endif // LLDB_ENABLE_PYTHON
#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHON_H
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
index 929567e579d8..1fa198b07e54 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
@@ -6,11 +6,9 @@
//
//===----------------------------------------------------------------------===//
-#ifdef LLDB_DISABLE_PYTHON
+#include "lldb/Host/Config.h"
-// Python is disabled in this build
-
-#else
+#if LLDB_ENABLE_PYTHON
#include "lldb-python.h"
@@ -179,8 +177,10 @@ public:
Status GenerateFunction(const char *signature,
const StringList &input) override;
- Status GenerateBreakpointCommandCallbackData(StringList &input,
- std::string &output) override;
+ Status GenerateBreakpointCommandCallbackData(
+ StringList &input,
+ std::string &output,
+ bool has_extra_args) override;
bool GenerateWatchpointCommandCallbackData(StringList &input,
std::string &output) override;
@@ -224,7 +224,7 @@ public:
std::string &output, Status &error) override;
bool
- LoadScriptingModule(const char *filename, bool can_reload, bool init_session,
+ LoadScriptingModule(const char *filename, bool init_session,
lldb_private::Status &error,
StructuredData::ObjectSP *module_sp = nullptr) override;
@@ -244,14 +244,21 @@ public:
Status SetBreakpointCommandCallback(BreakpointOptions *bp_options,
const char *callback_body) override;
- void SetBreakpointCommandCallbackFunction(BreakpointOptions *bp_options,
- const char *function_name) override;
+ Status SetBreakpointCommandCallbackFunction(
+ BreakpointOptions *bp_options,
+ const char *function_name,
+ StructuredData::ObjectSP extra_args_sp) override;
/// This one is for deserialization:
Status SetBreakpointCommandCallback(
BreakpointOptions *bp_options,
std::unique_ptr<BreakpointOptions::CommandData> &data_up) override;
+ Status SetBreakpointCommandCallback(BreakpointOptions *bp_options,
+ const char *command_body_text,
+ StructuredData::ObjectSP extra_args_sp,
+ bool uses_extra_args);
+
/// Set a one-liner as the callback for the watchpoint.
void SetWatchpointCommandCallback(WatchpointOptions *wp_options,
const char *oneliner) override;
@@ -369,6 +376,9 @@ public:
python::PythonDictionary &GetSysModuleDictionary();
+ llvm::Expected<unsigned> GetMaxPositionalArgumentsForCallable(
+ const llvm::StringRef &callable_name) override;
+
bool GetEmbeddedInterpreterModuleObjects();
bool SetStdHandle(lldb::FileSP file, const char *py_name,
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h b/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h
index 884514da9924..48f27b09b95c 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/lldb-python.h
@@ -9,12 +9,12 @@
#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H
#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H
+#include "lldb/Host/Config.h"
+
// Python.h needs to be included before any system headers in order to avoid
// redefinition of macros
-#ifdef LLDB_DISABLE_PYTHON
-// Python is disabled in this build
-#else
+#if LLDB_ENABLE_PYTHON
#include "llvm/Support/Compiler.h"
#if defined(_WIN32)
// If anyone #includes Host/PosixApi.h later, it will try to typedef pid_t. We
@@ -40,6 +40,6 @@
// Include python for non windows machines
#include <Python.h>
-#endif // LLDB_DISABLE_PYTHON
+#endif
#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H
diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
index f84cf0c5368d..b2c4d0883341 100644
--- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
+++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
@@ -25,6 +25,8 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::breakpad;
+char SymbolFileBreakpad::ID;
+
class SymbolFileBreakpad::LineIterator {
public:
// begin iterator for sections of given type
@@ -307,8 +309,9 @@ void SymbolFileBreakpad::FindTypes(
uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files,
TypeMap &types) {}
-void SymbolFileBreakpad::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
- LanguageSet languages, TypeMap &types) {}
+void SymbolFileBreakpad::FindTypes(
+ llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {}
void SymbolFileBreakpad::AddSymbols(Symtab &symtab) {
Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS);
@@ -728,7 +731,7 @@ void SymbolFileBreakpad::ParseLineTableAndSupportFiles(CompileUnit &cu,
}
if (next_addr)
finish_sequence();
- data.support_files = map.translate(cu, *m_files);
+ data.support_files = map.translate(cu.GetPrimaryFile(), *m_files);
}
void SymbolFileBreakpad::ParseUnwindData() {
diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
index a10138cdf92f..de271224a65d 100644
--- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
+++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
@@ -21,7 +21,18 @@ namespace lldb_private {
namespace breakpad {
class SymbolFileBreakpad : public SymbolFile {
+ /// LLVM RTTI support.
+ static char ID;
+
public:
+ /// LLVM RTTI support.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || SymbolFile::isA(ClassID);
+ }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
+
// Static Functions
static void Initialize();
static void Terminate();
@@ -112,6 +123,7 @@ public:
TypeMap &types) override;
void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files,
TypeMap &types) override;
llvm::Expected<TypeSystem &>
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 636e6032b877..232063a6f339 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -22,7 +22,7 @@
#include "lldb/Core/Value.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/ClangASTImporter.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/ClangASTMetadata.h"
#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
@@ -135,61 +135,111 @@ static bool IsClangModuleFwdDecl(const DWARFDIE &Die) {
return false;
}
-TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) {
- ModuleSP dwo_module_sp = die.GetContainingDWOModule();
- if (!dwo_module_sp)
+static DWARFDIE GetContainingClangModuleDIE(const DWARFDIE &die) {
+ if (die.IsValid()) {
+ DWARFDIE top_module_die;
+ // Now make sure this DIE is scoped in a DW_TAG_module tag and return true
+ // if so
+ for (DWARFDIE parent = die.GetParent(); parent.IsValid();
+ parent = parent.GetParent()) {
+ const dw_tag_t tag = parent.Tag();
+ if (tag == DW_TAG_module)
+ top_module_die = parent;
+ else if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
+ break;
+ }
+
+ return top_module_die;
+ }
+ return DWARFDIE();
+}
+
+static lldb::ModuleSP GetContainingClangModule(const DWARFDIE &die) {
+ if (die.IsValid()) {
+ DWARFDIE clang_module_die = GetContainingClangModuleDIE(die);
+
+ if (clang_module_die) {
+ const char *module_name = clang_module_die.GetName();
+ if (module_name)
+ return die.GetDWARF()->GetExternalModule(
+ lldb_private::ConstString(module_name));
+ }
+ }
+ return lldb::ModuleSP();
+}
+
+TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
+ const DWARFDIE &die,
+ Log *log) {
+ ModuleSP clang_module_sp = GetContainingClangModule(die);
+ if (!clang_module_sp)
return TypeSP();
- // If this type comes from a Clang module, look in the DWARF section
- // of the pcm file in the module cache. Clang generates DWO skeleton
- // units as breadcrumbs to find them.
+ // If this type comes from a Clang module, recursively look in the
+ // DWARF section of the .pcm file in the module cache. Clang
+ // generates DWO skeleton units as breadcrumbs to find them.
llvm::SmallVector<CompilerContext, 4> decl_context;
die.GetDeclContext(decl_context);
- TypeMap dwo_types;
+ TypeMap pcm_types;
// The type in the Clang module must have the same language as the current CU.
LanguageSet languages;
languages.Insert(die.GetCU()->GetLanguageType());
- dwo_module_sp->GetSymbolFile()->FindTypes(decl_context, languages, dwo_types);
- if (dwo_types.Empty()) {
- if (!IsClangModuleFwdDecl(die))
- return TypeSP();
-
+ llvm::DenseSet<SymbolFile *> searched_symbol_files;
+ clang_module_sp->GetSymbolFile()->FindTypes(decl_context, languages,
+ searched_symbol_files, pcm_types);
+ if (pcm_types.Empty()) {
// Since this type is defined in one of the Clang modules imported
- // by this symbol file, search all of them.
+ // by this symbol file, search all of them. Instead of calling
+ // sym_file->FindTypes(), which would return this again, go straight
+ // to the imported modules.
auto &sym_file = die.GetCU()->GetSymbolFileDWARF();
- for (const auto &name_module : sym_file.getExternalTypeModules()) {
- if (!name_module.second)
- continue;
- name_module.second->GetSymbolFile()->FindTypes(decl_context,
- languages, dwo_types);
- if (dwo_types.GetSize())
- break;
- }
+
+ // Well-formed clang modules never form cycles; guard against corrupted
+ // ones by inserting the current file.
+ searched_symbol_files.insert(&sym_file);
+ sym_file.ForEachExternalModule(
+ *sc.comp_unit, searched_symbol_files, [&](Module &module) {
+ module.GetSymbolFile()->FindTypes(decl_context, languages,
+ searched_symbol_files, pcm_types);
+ return pcm_types.GetSize();
+ });
}
- if (dwo_types.GetSize() != 1)
+ if (!pcm_types.GetSize())
return TypeSP();
// We found a real definition for this type in the Clang module, so lets use
// it and cache the fact that we found a complete type for this die.
- TypeSP dwo_type_sp = dwo_types.GetTypeAtIndex(0);
- if (!dwo_type_sp)
+ TypeSP pcm_type_sp = pcm_types.GetTypeAtIndex(0);
+ if (!pcm_type_sp)
return TypeSP();
- lldb_private::CompilerType dwo_type = dwo_type_sp->GetForwardCompilerType();
-
+ lldb_private::CompilerType pcm_type = pcm_type_sp->GetForwardCompilerType();
lldb_private::CompilerType type =
- GetClangASTImporter().CopyType(m_ast, dwo_type);
+ GetClangASTImporter().CopyType(m_ast, pcm_type);
if (!type)
return TypeSP();
+ // Under normal operation pcm_type is a shallow forward declaration
+ // that gets completed later. This is necessary to support cyclic
+ // data structures. If, however, pcm_type is already complete (for
+ // example, because it was loaded for a different target before),
+ // the definition needs to be imported right away, too.
+ // Type::ResolveClangType() effectively ignores the ResolveState
+ // inside type_sp and only looks at IsDefined(), so it never calls
+ // ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo(),
+ // which does extra work for Objective-C classes. This would result
+ // in only the forward declaration to be visible.
+ if (pcm_type.IsDefined())
+ GetClangASTImporter().RequireCompleteType(ClangUtil::GetQualType(type));
+
SymbolFileDWARF *dwarf = die.GetDWARF();
TypeSP type_sp(new Type(
- die.GetID(), dwarf, dwo_type_sp->GetName(), dwo_type_sp->GetByteSize(),
+ die.GetID(), dwarf, pcm_type_sp->GetName(), pcm_type_sp->GetByteSize(),
nullptr, LLDB_INVALID_UID, Type::eEncodingInvalid,
- &dwo_type_sp->GetDeclaration(), type, Type::eResolveStateForward));
+ &pcm_type_sp->GetDeclaration(), type, Type::ResolveState::Forward));
dwarf->GetTypeList().Insert(type_sp);
dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
@@ -205,7 +255,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) {
return type_sp;
}
-static void CompleteExternalTagDeclType(ClangASTImporter &ast_importer,
+static void CompleteExternalTagDeclType(ClangASTContext &ast,
+ ClangASTImporter &ast_importer,
clang::DeclContext *decl_ctx,
DWARFDIE die,
const char *type_name_cstr) {
@@ -214,7 +265,7 @@ static void CompleteExternalTagDeclType(ClangASTImporter &ast_importer,
return;
// If this type was not imported from an external AST, there's nothing to do.
- CompilerType type = ClangASTContext::GetTypeForDecl(tag_decl_ctx);
+ CompilerType type = ast.GetTypeForDecl(tag_decl_ctx);
if (!type || !ast_importer.CanImport(type))
return;
@@ -340,6 +391,10 @@ ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) {
is_complete_objc_class = form_value.Signed();
break;
+ case DW_AT_APPLE_objc_direct:
+ is_objc_direct_call = true;
+ break;
+
case DW_AT_APPLE_runtime_class:
class_language = (LanguageType)form_value.Signed();
break;
@@ -347,6 +402,9 @@ ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const DWARFDIE &die) {
case DW_AT_GNU_vector:
is_vector = form_value.Boolean();
break;
+ case DW_AT_export_symbols:
+ exports_symbols = form_value.Boolean();
+ break;
}
}
}
@@ -377,13 +435,12 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
dwarf->GetObjectFile()->GetModule()->LogMessage(
log,
- "SymbolFileDWARF::ParseType (die = 0x%8.8x, decl_ctx = %p (die "
- "0x%8.8x)) %s name = '%s')",
+ "DWARFASTParserClang::ParseTypeFromDWARF "
+ "(die = 0x%8.8x, decl_ctx = %p (die 0x%8.8x)) %s name = '%s')",
die.GetOffset(), static_cast<void *>(context), context_die.GetOffset(),
die.GetTagAsCString(), die.GetName());
}
-
Type *type_ptr = dwarf->GetDIEToType().lookup(die.GetDIE());
if (type_ptr == DIE_IS_BEING_PARSED)
return nullptr;
@@ -411,13 +468,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
const dw_tag_t tag = die.Tag();
- Type::ResolveState resolve_state = Type::eResolveStateUnresolved;
-
- Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
- CompilerType clang_type;
-
TypeSP type_sp;
- LanguageType cu_language = die.GetLanguage();
+
switch (tag) {
case DW_TAG_typedef:
case DW_TAG_base_type:
@@ -427,848 +479,895 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
case DW_TAG_const_type:
case DW_TAG_restrict_type:
case DW_TAG_volatile_type:
+ case DW_TAG_atomic_type:
case DW_TAG_unspecified_type: {
- if (tag == DW_TAG_typedef && attrs.type.IsValid()) {
- // Try to parse a typedef from the DWO file first as modules can
- // contain typedef'ed structures that have no names like:
- //
- // typedef struct { int a; } Foo;
- //
- // In this case we will have a structure with no name and a typedef
- // named "Foo" that points to this unnamed structure. The name in the
- // typedef is the only identifier for the struct, so always try to
- // get typedefs from DWO files if possible.
- //
- // The type_sp returned will be empty if the typedef doesn't exist in
- // a DWO file, so it is cheap to call this function just to check.
- //
- // If we don't do this we end up creating a TypeSP that says this is
- // a typedef to type 0x123 (the DW_AT_type value would be 0x123 in
- // the DW_TAG_typedef), and this is the unnamed structure type. We
- // will have a hard time tracking down an unnammed structure type in
- // the module DWO file, so we make sure we don't get into this
- // situation by always resolving typedefs from the DWO file.
- const DWARFDIE encoding_die = attrs.type.Reference();
-
- // First make sure that the die that this is typedef'ed to _is_ just
- // a declaration (DW_AT_declaration == 1), not a full definition
- // since template types can't be represented in modules since only
- // concrete instances of templates are ever emitted and modules won't
- // contain those
- if (encoding_die &&
- encoding_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) {
- type_sp = ParseTypeFromDWO(die, log);
- if (type_sp)
- return type_sp;
- }
- }
+ type_sp = ParseTypeModifier(sc, die, attrs);
+ break;
+ }
- DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n",
- die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr,
- encoding_uid.Reference());
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_class_type: {
+ type_sp = ParseStructureLikeDIE(sc, die, attrs);
+ break;
+ }
- switch (tag) {
- default:
- break;
+ case DW_TAG_enumeration_type: {
+ type_sp = ParseEnum(sc, die, attrs);
+ break;
+ }
- case DW_TAG_unspecified_type:
- if (attrs.name == "nullptr_t" || attrs.name == "decltype(nullptr)") {
- resolve_state = Type::eResolveStateFull;
- clang_type = m_ast.GetBasicType(eBasicTypeNullPtr);
- break;
- }
- // Fall through to base type below in case we can handle the type
- // there...
- LLVM_FALLTHROUGH;
-
- case DW_TAG_base_type:
- resolve_state = Type::eResolveStateFull;
- clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize(
- attrs.name.GetCString(), attrs.encoding,
- attrs.byte_size.getValueOr(0) * 8);
- break;
+ case DW_TAG_inlined_subroutine:
+ case DW_TAG_subprogram:
+ case DW_TAG_subroutine_type: {
+ type_sp = ParseSubroutine(die, attrs);
+ break;
+ }
+ case DW_TAG_array_type: {
+ type_sp = ParseArrayType(die, attrs);
+ break;
+ }
+ case DW_TAG_ptr_to_member_type: {
+ type_sp = ParsePointerToMemberType(die, attrs);
+ break;
+ }
+ default:
+ dwarf->GetObjectFile()->GetModule()->ReportError(
+ "{0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and "
+ "attach the file at the start of this error message",
+ die.GetOffset(), tag, DW_TAG_value_to_name(tag));
+ break;
+ }
- case DW_TAG_pointer_type:
- encoding_data_type = Type::eEncodingIsPointerUID;
- break;
- case DW_TAG_reference_type:
- encoding_data_type = Type::eEncodingIsLValueReferenceUID;
- break;
- case DW_TAG_rvalue_reference_type:
- encoding_data_type = Type::eEncodingIsRValueReferenceUID;
- break;
- case DW_TAG_typedef:
- encoding_data_type = Type::eEncodingIsTypedefUID;
- break;
- case DW_TAG_const_type:
- encoding_data_type = Type::eEncodingIsConstUID;
- break;
- case DW_TAG_restrict_type:
- encoding_data_type = Type::eEncodingIsRestrictUID;
- break;
- case DW_TAG_volatile_type:
- encoding_data_type = Type::eEncodingIsVolatileUID;
+ // TODO: We should consider making the switch above exhaustive to simplify
+ // control flow in ParseTypeFromDWARF. Then, we could simply replace this
+ // return statement with a call to llvm_unreachable.
+ return UpdateSymbolContextScopeForType(sc, die, type_sp);
+}
+
+lldb::TypeSP
+DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
+ const DWARFDIE &die,
+ ParsedDWARFTypeAttributes &attrs) {
+ Log *log(LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION |
+ DWARF_LOG_LOOKUPS));
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ const dw_tag_t tag = die.Tag();
+ LanguageType cu_language = die.GetLanguage();
+ Type::ResolveState resolve_state = Type::ResolveState::Unresolved;
+ Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
+ TypeSP type_sp;
+ CompilerType clang_type;
+
+ if (tag == DW_TAG_typedef && attrs.type.IsValid()) {
+ // Try to parse a typedef from the (DWARF embedded in the) Clang
+ // module file first as modules can contain typedef'ed
+ // structures that have no names like:
+ //
+ // typedef struct { int a; } Foo;
+ //
+ // In this case we will have a structure with no name and a
+ // typedef named "Foo" that points to this unnamed
+ // structure. The name in the typedef is the only identifier for
+ // the struct, so always try to get typedefs from Clang modules
+ // if possible.
+ //
+ // The type_sp returned will be empty if the typedef doesn't
+ // exist in a module file, so it is cheap to call this function
+ // just to check.
+ //
+ // If we don't do this we end up creating a TypeSP that says
+ // this is a typedef to type 0x123 (the DW_AT_type value would
+ // be 0x123 in the DW_TAG_typedef), and this is the unnamed
+ // structure type. We will have a hard time tracking down an
+ // unnammed structure type in the module debug info, so we make
+ // sure we don't get into this situation by always resolving
+ // typedefs from the module.
+ const DWARFDIE encoding_die = attrs.type.Reference();
+
+ // First make sure that the die that this is typedef'ed to _is_
+ // just a declaration (DW_AT_declaration == 1), not a full
+ // definition since template types can't be represented in
+ // modules since only concrete instances of templates are ever
+ // emitted and modules won't contain those
+ if (encoding_die &&
+ encoding_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) {
+ type_sp = ParseTypeFromClangModule(sc, die, log);
+ if (type_sp)
+ return type_sp;
+ }
+ }
+
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", die.GetID(),
+ DW_TAG_value_to_name(tag), type_name_cstr,
+ encoding_uid.Reference());
+
+ switch (tag) {
+ default:
+ break;
+
+ case DW_TAG_unspecified_type:
+ if (attrs.name == "nullptr_t" || attrs.name == "decltype(nullptr)") {
+ resolve_state = Type::ResolveState::Full;
+ clang_type = m_ast.GetBasicType(eBasicTypeNullPtr);
break;
}
+ // Fall through to base type below in case we can handle the type
+ // there...
+ LLVM_FALLTHROUGH;
- if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID ||
- encoding_data_type == Type::eEncodingIsTypedefUID)) {
- if (tag == DW_TAG_pointer_type) {
- DWARFDIE target_die = die.GetReferencedDIE(DW_AT_type);
-
- if (target_die.GetAttributeValueAsUnsigned(DW_AT_APPLE_block, 0)) {
- // Blocks have a __FuncPtr inside them which is a pointer to a
- // function of the proper type.
-
- for (DWARFDIE child_die = target_die.GetFirstChild();
- child_die.IsValid(); child_die = child_die.GetSibling()) {
- if (!strcmp(child_die.GetAttributeValueAsString(DW_AT_name, ""),
- "__FuncPtr")) {
- DWARFDIE function_pointer_type =
- child_die.GetReferencedDIE(DW_AT_type);
-
- if (function_pointer_type) {
- DWARFDIE function_type =
- function_pointer_type.GetReferencedDIE(DW_AT_type);
-
- bool function_type_is_new_pointer;
- TypeSP lldb_function_type_sp = ParseTypeFromDWARF(
- sc, function_type, &function_type_is_new_pointer);
-
- if (lldb_function_type_sp) {
- clang_type = m_ast.CreateBlockPointerType(
- lldb_function_type_sp->GetForwardCompilerType());
- encoding_data_type = Type::eEncodingIsUID;
- attrs.type.Clear();
- resolve_state = Type::eResolveStateFull;
- }
- }
+ case DW_TAG_base_type:
+ resolve_state = Type::ResolveState::Full;
+ clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize(
+ attrs.name.GetStringRef(), attrs.encoding,
+ attrs.byte_size.getValueOr(0) * 8);
+ break;
- break;
+ case DW_TAG_pointer_type:
+ encoding_data_type = Type::eEncodingIsPointerUID;
+ break;
+ case DW_TAG_reference_type:
+ encoding_data_type = Type::eEncodingIsLValueReferenceUID;
+ break;
+ case DW_TAG_rvalue_reference_type:
+ encoding_data_type = Type::eEncodingIsRValueReferenceUID;
+ break;
+ case DW_TAG_typedef:
+ encoding_data_type = Type::eEncodingIsTypedefUID;
+ break;
+ case DW_TAG_const_type:
+ encoding_data_type = Type::eEncodingIsConstUID;
+ break;
+ case DW_TAG_restrict_type:
+ encoding_data_type = Type::eEncodingIsRestrictUID;
+ break;
+ case DW_TAG_volatile_type:
+ encoding_data_type = Type::eEncodingIsVolatileUID;
+ break;
+ case DW_TAG_atomic_type:
+ encoding_data_type = Type::eEncodingIsAtomicUID;
+ break;
+ }
+
+ if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID ||
+ encoding_data_type == Type::eEncodingIsTypedefUID)) {
+ if (tag == DW_TAG_pointer_type) {
+ DWARFDIE target_die = die.GetReferencedDIE(DW_AT_type);
+
+ if (target_die.GetAttributeValueAsUnsigned(DW_AT_APPLE_block, 0)) {
+ // Blocks have a __FuncPtr inside them which is a pointer to a
+ // function of the proper type.
+
+ for (DWARFDIE child_die = target_die.GetFirstChild();
+ child_die.IsValid(); child_die = child_die.GetSibling()) {
+ if (!strcmp(child_die.GetAttributeValueAsString(DW_AT_name, ""),
+ "__FuncPtr")) {
+ DWARFDIE function_pointer_type =
+ child_die.GetReferencedDIE(DW_AT_type);
+
+ if (function_pointer_type) {
+ DWARFDIE function_type =
+ function_pointer_type.GetReferencedDIE(DW_AT_type);
+
+ bool function_type_is_new_pointer;
+ TypeSP lldb_function_type_sp = ParseTypeFromDWARF(
+ sc, function_type, &function_type_is_new_pointer);
+
+ if (lldb_function_type_sp) {
+ clang_type = m_ast.CreateBlockPointerType(
+ lldb_function_type_sp->GetForwardCompilerType());
+ encoding_data_type = Type::eEncodingIsUID;
+ attrs.type.Clear();
+ resolve_state = Type::ResolveState::Full;
+ }
}
+
+ break;
}
}
}
+ }
- if (cu_language == eLanguageTypeObjC ||
- cu_language == eLanguageTypeObjC_plus_plus) {
- if (attrs.name) {
- static ConstString g_objc_type_name_id("id");
- static ConstString g_objc_type_name_Class("Class");
- static ConstString g_objc_type_name_selector("SEL");
+ if (cu_language == eLanguageTypeObjC ||
+ cu_language == eLanguageTypeObjC_plus_plus) {
+ if (attrs.name) {
+ if (attrs.name == "id") {
+ if (log)
+ dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
+ "is Objective-C 'id' built-in type.",
+ die.GetOffset(), die.GetTagAsCString(), die.GetName());
+ clang_type = m_ast.GetBasicType(eBasicTypeObjCID);
+ encoding_data_type = Type::eEncodingIsUID;
+ attrs.type.Clear();
+ resolve_state = Type::ResolveState::Full;
+ } else if (attrs.name == "Class") {
+ if (log)
+ dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
+ "is Objective-C 'Class' built-in type.",
+ die.GetOffset(), die.GetTagAsCString(), die.GetName());
+ clang_type = m_ast.GetBasicType(eBasicTypeObjCClass);
+ encoding_data_type = Type::eEncodingIsUID;
+ attrs.type.Clear();
+ resolve_state = Type::ResolveState::Full;
+ } else if (attrs.name == "SEL") {
+ if (log)
+ dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
+ "is Objective-C 'selector' built-in type.",
+ die.GetOffset(), die.GetTagAsCString(), die.GetName());
+ clang_type = m_ast.GetBasicType(eBasicTypeObjCSel);
+ encoding_data_type = Type::eEncodingIsUID;
+ attrs.type.Clear();
+ resolve_state = Type::ResolveState::Full;
+ }
+ } else if (encoding_data_type == Type::eEncodingIsPointerUID &&
+ attrs.type.IsValid()) {
+ // Clang sometimes erroneously emits id as objc_object*. In that
+ // case we fix up the type to "id".
- if (attrs.name == g_objc_type_name_id) {
- if (log)
- dwarf->GetObjectFile()->GetModule()->LogMessage(
- log,
- "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
- "is Objective-C 'id' built-in type.",
- die.GetOffset(), die.GetTagAsCString(), die.GetName());
- clang_type = m_ast.GetBasicType(eBasicTypeObjCID);
- encoding_data_type = Type::eEncodingIsUID;
- attrs.type.Clear();
- resolve_state = Type::eResolveStateFull;
+ const DWARFDIE encoding_die = attrs.type.Reference();
- } else if (attrs.name == g_objc_type_name_Class) {
+ if (encoding_die && encoding_die.Tag() == DW_TAG_structure_type) {
+ llvm::StringRef struct_name = encoding_die.GetName();
+ if (struct_name == "objc_object") {
if (log)
dwarf->GetObjectFile()->GetModule()->LogMessage(
log,
- "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
- "is Objective-C 'Class' built-in type.",
+ "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s "
+ "'%s' is 'objc_object*', which we overrode to "
+ "'id'.",
die.GetOffset(), die.GetTagAsCString(), die.GetName());
- clang_type = m_ast.GetBasicType(eBasicTypeObjCClass);
- encoding_data_type = Type::eEncodingIsUID;
- attrs.type.Clear();
- resolve_state = Type::eResolveStateFull;
- } else if (attrs.name == g_objc_type_name_selector) {
- if (log)
- dwarf->GetObjectFile()->GetModule()->LogMessage(
- log,
- "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' "
- "is Objective-C 'selector' built-in type.",
- die.GetOffset(), die.GetTagAsCString(), die.GetName());
- clang_type = m_ast.GetBasicType(eBasicTypeObjCSel);
+ clang_type = m_ast.GetBasicType(eBasicTypeObjCID);
encoding_data_type = Type::eEncodingIsUID;
attrs.type.Clear();
- resolve_state = Type::eResolveStateFull;
- }
- } else if (encoding_data_type == Type::eEncodingIsPointerUID &&
- attrs.type.IsValid()) {
- // Clang sometimes erroneously emits id as objc_object*. In that
- // case we fix up the type to "id".
-
- const DWARFDIE encoding_die = attrs.type.Reference();
-
- if (encoding_die && encoding_die.Tag() == DW_TAG_structure_type) {
- if (const char *struct_name = encoding_die.GetName()) {
- if (!strcmp(struct_name, "objc_object")) {
- if (log)
- dwarf->GetObjectFile()->GetModule()->LogMessage(
- log,
- "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s "
- "'%s' is 'objc_object*', which we overrode to "
- "'id'.",
- die.GetOffset(), die.GetTagAsCString(), die.GetName());
- clang_type = m_ast.GetBasicType(eBasicTypeObjCID);
- encoding_data_type = Type::eEncodingIsUID;
- attrs.type.Clear();
- resolve_state = Type::eResolveStateFull;
- }
- }
+ resolve_state = Type::ResolveState::Full;
}
}
}
}
-
- type_sp = std::make_shared<Type>(
- die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr,
- dwarf->GetUID(attrs.type.Reference()), encoding_data_type, &attrs.decl,
- clang_type, resolve_state);
-
- dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
- } break;
-
- case DW_TAG_structure_type:
- case DW_TAG_union_type:
- case DW_TAG_class_type: {
- assert((!type_sp && !clang_type) &&
- "Did not expect partially computed structure-like type");
- TypeSP struct_like_type_sp = ParseStructureLikeDIE(die, attrs);
- return UpdateSymbolContextScopeForType(sc, die, struct_like_type_sp);
}
- case DW_TAG_enumeration_type: {
- if (attrs.is_forward_declaration) {
- type_sp = ParseTypeFromDWO(die, log);
- if (type_sp)
- return type_sp;
+ type_sp = std::make_shared<Type>(
+ die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr,
+ dwarf->GetUID(attrs.type.Reference()), encoding_data_type, &attrs.decl,
+ clang_type, resolve_state);
- DWARFDeclContext die_decl_ctx;
- die.GetDWARFDeclContext(die_decl_ctx);
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+ return type_sp;
+}
- type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx);
+TypeSP DWARFASTParserClang::ParseEnum(const SymbolContext &sc,
+ const DWARFDIE &die,
+ ParsedDWARFTypeAttributes &attrs) {
+ Log *log(LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION |
+ DWARF_LOG_LOOKUPS));
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ const dw_tag_t tag = die.Tag();
+ TypeSP type_sp;
- if (!type_sp) {
- SymbolFileDWARFDebugMap *debug_map_symfile =
- dwarf->GetDebugMapSymfile();
- if (debug_map_symfile) {
- // We weren't able to find a full declaration in this DWARF,
- // see if we have a declaration anywhere else...
- type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(
- die_decl_ctx);
- }
- }
+ if (attrs.is_forward_declaration) {
+ type_sp = ParseTypeFromClangModule(sc, die, log);
+ if (type_sp)
+ return type_sp;
- if (type_sp) {
- if (log) {
- dwarf->GetObjectFile()->GetModule()->LogMessage(
- log,
- "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a "
- "forward declaration, complete type is 0x%8.8" PRIx64,
- static_cast<void *>(this), die.GetOffset(),
- DW_TAG_value_to_name(tag), attrs.name.GetCString(),
- type_sp->GetID());
- }
+ DWARFDeclContext die_decl_ctx;
+ die.GetDWARFDeclContext(die_decl_ctx);
- // We found a real definition for this type elsewhere so lets use
- // it and cache the fact that we found a complete type for this
- // die
- dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
- clang::DeclContext *defn_decl_ctx =
- GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID()));
- if (defn_decl_ctx)
- LinkDeclContextToDIE(defn_decl_ctx, die);
- return type_sp;
+ type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx);
+
+ if (!type_sp) {
+ SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile();
+ if (debug_map_symfile) {
+ // We weren't able to find a full declaration in this DWARF,
+ // see if we have a declaration anywhere else...
+ type_sp = debug_map_symfile->FindDefinitionTypeForDWARFDeclContext(
+ die_decl_ctx);
}
}
- DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
- DW_TAG_value_to_name(tag), type_name_cstr);
-
- CompilerType enumerator_clang_type;
- clang_type.SetCompilerType(
- &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE()));
- if (!clang_type) {
- if (attrs.type.IsValid()) {
- Type *enumerator_type =
- dwarf->ResolveTypeUID(attrs.type.Reference(), true);
- if (enumerator_type)
- enumerator_clang_type = enumerator_type->GetFullCompilerType();
- }
- if (!enumerator_clang_type) {
- if (attrs.byte_size) {
- enumerator_clang_type =
- m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize(
- NULL, DW_ATE_signed, *attrs.byte_size * 8);
- } else {
- enumerator_clang_type = m_ast.GetBasicType(eBasicTypeInt);
- }
+ if (type_sp) {
+ if (log) {
+ dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log,
+ "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a "
+ "forward declaration, complete type is 0x%8.8" PRIx64,
+ static_cast<void *>(this), die.GetOffset(),
+ DW_TAG_value_to_name(tag), attrs.name.GetCString(),
+ type_sp->GetID());
}
- clang_type = m_ast.CreateEnumerationType(
- attrs.name.GetCString(),
- GetClangDeclContextContainingDIE(die, nullptr), attrs.decl,
- enumerator_clang_type, attrs.is_scoped_enum);
- } else {
- enumerator_clang_type =
- m_ast.GetEnumerationIntegerType(clang_type.GetOpaqueQualType());
+ // We found a real definition for this type elsewhere so lets use
+ // it and cache the fact that we found a complete type for this
+ // die
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+ clang::DeclContext *defn_decl_ctx =
+ GetCachedClangDeclContextForDIE(dwarf->GetDIE(type_sp->GetID()));
+ if (defn_decl_ctx)
+ LinkDeclContextToDIE(defn_decl_ctx, die);
+ return type_sp;
}
+ }
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
+ DW_TAG_value_to_name(tag), type_name_cstr);
- LinkDeclContextToDIE(ClangASTContext::GetDeclContextForType(clang_type),
- die);
-
- type_sp = std::make_shared<Type>(
- die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr,
- dwarf->GetUID(attrs.type.Reference()), Type::eEncodingIsUID,
- &attrs.decl, clang_type, Type::eResolveStateForward);
+ CompilerType enumerator_clang_type;
+ CompilerType clang_type;
+ clang_type.SetCompilerType(
+ &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE()));
+ if (!clang_type) {
+ if (attrs.type.IsValid()) {
+ Type *enumerator_type =
+ dwarf->ResolveTypeUID(attrs.type.Reference(), true);
+ if (enumerator_type)
+ enumerator_clang_type = enumerator_type->GetFullCompilerType();
+ }
- if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) {
- if (die.HasChildren()) {
- bool is_signed = false;
- enumerator_clang_type.IsIntegerType(is_signed);
- ParseChildEnumerators(clang_type, is_signed,
- type_sp->GetByteSize().getValueOr(0), die);
+ if (!enumerator_clang_type) {
+ if (attrs.byte_size) {
+ enumerator_clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize(
+ "", DW_ATE_signed, *attrs.byte_size * 8);
+ } else {
+ enumerator_clang_type = m_ast.GetBasicType(eBasicTypeInt);
}
- ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
- } else {
- dwarf->GetObjectFile()->GetModule()->ReportError(
- "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its "
- "definition.\nPlease file a bug and attach the file at the "
- "start of this error message",
- die.GetOffset(), attrs.name.GetCString());
}
- } break;
- case DW_TAG_inlined_subroutine:
- case DW_TAG_subprogram:
- case DW_TAG_subroutine_type: {
- bool is_variadic = false;
- bool is_static = false;
- bool has_template_params = false;
+ clang_type = m_ast.CreateEnumerationType(
+ attrs.name.GetCString(), GetClangDeclContextContainingDIE(die, nullptr),
+ attrs.decl, enumerator_clang_type, attrs.is_scoped_enum);
+ } else {
+ enumerator_clang_type =
+ m_ast.GetEnumerationIntegerType(clang_type.GetOpaqueQualType());
+ }
- unsigned type_quals = 0;
+ LinkDeclContextToDIE(ClangASTContext::GetDeclContextForType(clang_type), die);
- std::string object_pointer_name;
- if (attrs.object_pointer) {
- const char *object_pointer_name_cstr = attrs.object_pointer.GetName();
- if (object_pointer_name_cstr)
- object_pointer_name = object_pointer_name_cstr;
- }
+ type_sp = std::make_shared<Type>(
+ die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr,
+ dwarf->GetUID(attrs.type.Reference()), Type::eEncodingIsUID, &attrs.decl,
+ clang_type, Type::ResolveState::Forward);
- DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
- DW_TAG_value_to_name(tag), type_name_cstr);
+ if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) {
+ if (die.HasChildren()) {
+ bool is_signed = false;
+ enumerator_clang_type.IsIntegerType(is_signed);
+ ParseChildEnumerators(clang_type, is_signed,
+ type_sp->GetByteSize().getValueOr(0), die);
+ }
+ ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
+ } else {
+ dwarf->GetObjectFile()->GetModule()->ReportError(
+ "DWARF DIE at 0x%8.8x named \"%s\" was not able to start its "
+ "definition.\nPlease file a bug and attach the file at the "
+ "start of this error message",
+ die.GetOffset(), attrs.name.GetCString());
+ }
+ return type_sp;
+}
- CompilerType return_clang_type;
- Type *func_type = NULL;
+TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
+ ParsedDWARFTypeAttributes &attrs) {
+ Log *log(LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION |
+ DWARF_LOG_LOOKUPS));
- if (attrs.type.IsValid())
- func_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true);
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ const dw_tag_t tag = die.Tag();
- if (func_type)
- return_clang_type = func_type->GetForwardCompilerType();
- else
- return_clang_type = m_ast.GetBasicType(eBasicTypeVoid);
+ bool is_variadic = false;
+ bool is_static = false;
+ bool has_template_params = false;
- std::vector<CompilerType> function_param_types;
- std::vector<clang::ParmVarDecl *> function_param_decls;
+ unsigned type_quals = 0;
- // Parse the function children for the parameters
+ std::string object_pointer_name;
+ if (attrs.object_pointer) {
+ const char *object_pointer_name_cstr = attrs.object_pointer.GetName();
+ if (object_pointer_name_cstr)
+ object_pointer_name = object_pointer_name_cstr;
+ }
- DWARFDIE decl_ctx_die;
- clang::DeclContext *containing_decl_ctx =
- GetClangDeclContextContainingDIE(die, &decl_ctx_die);
- const clang::Decl::Kind containing_decl_kind =
- containing_decl_ctx->getDeclKind();
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
+ DW_TAG_value_to_name(tag), type_name_cstr);
- bool is_cxx_method = DeclKindIsCXXClass(containing_decl_kind);
- // Start off static. This will be set to false in
- // ParseChildParameters(...) if we find a "this" parameters as the
- // first parameter
- if (is_cxx_method) {
- is_static = true;
- }
+ CompilerType return_clang_type;
+ Type *func_type = NULL;
+
+ if (attrs.type.IsValid())
+ func_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true);
+
+ if (func_type)
+ return_clang_type = func_type->GetForwardCompilerType();
+ else
+ return_clang_type = m_ast.GetBasicType(eBasicTypeVoid);
+
+ std::vector<CompilerType> function_param_types;
+ std::vector<clang::ParmVarDecl *> function_param_decls;
+
+ // Parse the function children for the parameters
+
+ DWARFDIE decl_ctx_die;
+ clang::DeclContext *containing_decl_ctx =
+ GetClangDeclContextContainingDIE(die, &decl_ctx_die);
+ const clang::Decl::Kind containing_decl_kind =
+ containing_decl_ctx->getDeclKind();
+
+ bool is_cxx_method = DeclKindIsCXXClass(containing_decl_kind);
+ // Start off static. This will be set to false in
+ // ParseChildParameters(...) if we find a "this" parameters as the
+ // first parameter
+ if (is_cxx_method) {
+ is_static = true;
+ }
+
+ if (die.HasChildren()) {
+ bool skip_artificial = true;
+ ParseChildParameters(containing_decl_ctx, die, skip_artificial, is_static,
+ is_variadic, has_template_params,
+ function_param_types, function_param_decls,
+ type_quals);
+ }
+
+ bool ignore_containing_context = false;
+ // Check for templatized class member functions. If we had any
+ // DW_TAG_template_type_parameter or DW_TAG_template_value_parameter
+ // the DW_TAG_subprogram DIE, then we can't let this become a method in
+ // a class. Why? Because templatized functions are only emitted if one
+ // of the templatized methods is used in the current compile unit and
+ // we will end up with classes that may or may not include these member
+ // functions and this means one class won't match another class
+ // definition and it affects our ability to use a class in the clang
+ // expression parser. So for the greater good, we currently must not
+ // allow any template member functions in a class definition.
+ if (is_cxx_method && has_template_params) {
+ ignore_containing_context = true;
+ is_cxx_method = false;
+ }
+
+ // clang_type will get the function prototype clang type after this
+ // call
+ CompilerType clang_type = m_ast.CreateFunctionType(
+ return_clang_type, function_param_types.data(),
+ function_param_types.size(), is_variadic, type_quals);
- if (die.HasChildren()) {
- bool skip_artificial = true;
- ParseChildParameters(containing_decl_ctx, die, skip_artificial, is_static,
- is_variadic, has_template_params,
- function_param_types, function_param_decls,
- type_quals);
- }
-
- bool ignore_containing_context = false;
- // Check for templatized class member functions. If we had any
- // DW_TAG_template_type_parameter or DW_TAG_template_value_parameter
- // the DW_TAG_subprogram DIE, then we can't let this become a method in
- // a class. Why? Because templatized functions are only emitted if one
- // of the templatized methods is used in the current compile unit and
- // we will end up with classes that may or may not include these member
- // functions and this means one class won't match another class
- // definition and it affects our ability to use a class in the clang
- // expression parser. So for the greater good, we currently must not
- // allow any template member functions in a class definition.
- if (is_cxx_method && has_template_params) {
- ignore_containing_context = true;
- is_cxx_method = false;
- }
-
- // clang_type will get the function prototype clang type after this
- // call
- clang_type = m_ast.CreateFunctionType(
- return_clang_type, function_param_types.data(),
- function_param_types.size(), is_variadic, type_quals);
-
- if (attrs.name) {
- bool type_handled = false;
- if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) {
- ObjCLanguage::MethodName objc_method(attrs.name.GetStringRef(), true);
- if (objc_method.IsValid(true)) {
- CompilerType class_opaque_type;
- ConstString class_name(objc_method.GetClassName());
- if (class_name) {
- TypeSP complete_objc_class_type_sp(
- dwarf->FindCompleteObjCDefinitionTypeForDIE(DWARFDIE(),
- class_name, false));
-
- if (complete_objc_class_type_sp) {
- CompilerType type_clang_forward_type =
- complete_objc_class_type_sp->GetForwardCompilerType();
- if (ClangASTContext::IsObjCObjectOrInterfaceType(
- type_clang_forward_type))
- class_opaque_type = type_clang_forward_type;
- }
+ if (attrs.name) {
+ bool type_handled = false;
+ if (tag == DW_TAG_subprogram || tag == DW_TAG_inlined_subroutine) {
+ ObjCLanguage::MethodName objc_method(attrs.name.GetStringRef(), true);
+ if (objc_method.IsValid(true)) {
+ CompilerType class_opaque_type;
+ ConstString class_name(objc_method.GetClassName());
+ if (class_name) {
+ TypeSP complete_objc_class_type_sp(
+ dwarf->FindCompleteObjCDefinitionTypeForDIE(DWARFDIE(),
+ class_name, false));
+
+ if (complete_objc_class_type_sp) {
+ CompilerType type_clang_forward_type =
+ complete_objc_class_type_sp->GetForwardCompilerType();
+ if (ClangASTContext::IsObjCObjectOrInterfaceType(
+ type_clang_forward_type))
+ class_opaque_type = type_clang_forward_type;
}
+ }
- if (class_opaque_type) {
- // If accessibility isn't set to anything valid, assume public
- // for now...
- if (attrs.accessibility == eAccessNone)
- attrs.accessibility = eAccessPublic;
-
- clang::ObjCMethodDecl *objc_method_decl =
- m_ast.AddMethodToObjCObjectType(
- class_opaque_type, attrs.name.GetCString(), clang_type,
- attrs.accessibility, attrs.is_artificial, is_variadic);
- type_handled = objc_method_decl != NULL;
- if (type_handled) {
- LinkDeclContextToDIE(
- ClangASTContext::GetAsDeclContext(objc_method_decl), die);
- m_ast.SetMetadataAsUserID(objc_method_decl, die.GetID());
- } else {
- dwarf->GetObjectFile()->GetModule()->ReportError(
- "{0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), "
- "please file a bug and attach the file at the start of "
- "this error message",
- die.GetOffset(), tag, DW_TAG_value_to_name(tag));
- }
+ if (class_opaque_type) {
+ // If accessibility isn't set to anything valid, assume public
+ // for now...
+ if (attrs.accessibility == eAccessNone)
+ attrs.accessibility = eAccessPublic;
+
+ clang::ObjCMethodDecl *objc_method_decl =
+ m_ast.AddMethodToObjCObjectType(
+ class_opaque_type, attrs.name.GetCString(), clang_type,
+ attrs.accessibility, attrs.is_artificial, is_variadic,
+ attrs.is_objc_direct_call);
+ type_handled = objc_method_decl != NULL;
+ if (type_handled) {
+ LinkDeclContextToDIE(objc_method_decl, die);
+ m_ast.SetMetadataAsUserID(objc_method_decl, die.GetID());
+ } else {
+ dwarf->GetObjectFile()->GetModule()->ReportError(
+ "{0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), "
+ "please file a bug and attach the file at the start of "
+ "this error message",
+ die.GetOffset(), tag, DW_TAG_value_to_name(tag));
}
- } else if (is_cxx_method) {
- // Look at the parent of this DIE and see if is is a class or
- // struct and see if this is actually a C++ method
- Type *class_type = dwarf->ResolveType(decl_ctx_die);
- if (class_type) {
- bool alternate_defn = false;
- if (class_type->GetID() != decl_ctx_die.GetID() ||
- decl_ctx_die.GetContainingDWOModuleDIE()) {
- alternate_defn = true;
-
- // We uniqued the parent class of this function to another
- // class so we now need to associate all dies under
- // "decl_ctx_die" to DIEs in the DIE for "class_type"...
- DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID());
-
- if (class_type_die) {
- std::vector<DWARFDIE> failures;
-
- CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die,
- class_type, failures);
-
- // FIXME do something with these failures that's smarter
- // than
- // just dropping them on the ground. Unfortunately classes
- // don't like having stuff added to them after their
- // definitions are complete...
-
- type_ptr = dwarf->GetDIEToType()[die.GetDIE()];
- if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) {
- type_sp = type_ptr->shared_from_this();
- break;
- }
+ }
+ } else if (is_cxx_method) {
+ // Look at the parent of this DIE and see if is is a class or
+ // struct and see if this is actually a C++ method
+ Type *class_type = dwarf->ResolveType(decl_ctx_die);
+ if (class_type) {
+ bool alternate_defn = false;
+ if (class_type->GetID() != decl_ctx_die.GetID() ||
+ IsClangModuleFwdDecl(decl_ctx_die)) {
+ alternate_defn = true;
+
+ // We uniqued the parent class of this function to another
+ // class so we now need to associate all dies under
+ // "decl_ctx_die" to DIEs in the DIE for "class_type"...
+ DWARFDIE class_type_die = dwarf->GetDIE(class_type->GetID());
+
+ if (class_type_die) {
+ std::vector<DWARFDIE> failures;
+
+ CopyUniqueClassMethodTypes(decl_ctx_die, class_type_die,
+ class_type, failures);
+
+ // FIXME do something with these failures that's
+ // smarter than just dropping them on the ground.
+ // Unfortunately classes don't like having stuff added
+ // to them after their definitions are complete...
+
+ Type *type_ptr = dwarf->GetDIEToType()[die.GetDIE()];
+ if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) {
+ return type_ptr->shared_from_this();
}
}
+ }
- if (attrs.specification.IsValid()) {
- // We have a specification which we are going to base our
- // function prototype off of, so we need this type to be
- // completed so that the m_die_to_decl_ctx for the method in
- // the specification has a valid clang decl context.
- class_type->GetForwardCompilerType();
- // If we have a specification, then the function type should
- // have been made with the specification and not with this
- // die.
- DWARFDIE spec_die = attrs.specification.Reference();
- clang::DeclContext *spec_clang_decl_ctx =
- GetClangDeclContextForDIE(spec_die);
- if (spec_clang_decl_ctx) {
- LinkDeclContextToDIE(spec_clang_decl_ctx, die);
- } else {
- dwarf->GetObjectFile()->GetModule()->ReportWarning(
- "0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8x"
- ") has no decl\n",
- die.GetID(), spec_die.GetOffset());
- }
- type_handled = true;
- } else if (attrs.abstract_origin.IsValid()) {
- // We have a specification which we are going to base our
- // function prototype off of, so we need this type to be
- // completed so that the m_die_to_decl_ctx for the method in
- // the abstract origin has a valid clang decl context.
- class_type->GetForwardCompilerType();
-
- DWARFDIE abs_die = attrs.abstract_origin.Reference();
- clang::DeclContext *abs_clang_decl_ctx =
- GetClangDeclContextForDIE(abs_die);
- if (abs_clang_decl_ctx) {
- LinkDeclContextToDIE(abs_clang_decl_ctx, die);
- } else {
- dwarf->GetObjectFile()->GetModule()->ReportWarning(
- "0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8x"
- ") has no decl\n",
- die.GetID(), abs_die.GetOffset());
- }
- type_handled = true;
+ if (attrs.specification.IsValid()) {
+ // We have a specification which we are going to base our
+ // function prototype off of, so we need this type to be
+ // completed so that the m_die_to_decl_ctx for the method in
+ // the specification has a valid clang decl context.
+ class_type->GetForwardCompilerType();
+ // If we have a specification, then the function type should
+ // have been made with the specification and not with this
+ // die.
+ DWARFDIE spec_die = attrs.specification.Reference();
+ clang::DeclContext *spec_clang_decl_ctx =
+ GetClangDeclContextForDIE(spec_die);
+ if (spec_clang_decl_ctx) {
+ LinkDeclContextToDIE(spec_clang_decl_ctx, die);
+ } else {
+ dwarf->GetObjectFile()->GetModule()->ReportWarning(
+ "0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8x"
+ ") has no decl\n",
+ die.GetID(), spec_die.GetOffset());
+ }
+ type_handled = true;
+ } else if (attrs.abstract_origin.IsValid()) {
+ // We have a specification which we are going to base our
+ // function prototype off of, so we need this type to be
+ // completed so that the m_die_to_decl_ctx for the method in
+ // the abstract origin has a valid clang decl context.
+ class_type->GetForwardCompilerType();
+
+ DWARFDIE abs_die = attrs.abstract_origin.Reference();
+ clang::DeclContext *abs_clang_decl_ctx =
+ GetClangDeclContextForDIE(abs_die);
+ if (abs_clang_decl_ctx) {
+ LinkDeclContextToDIE(abs_clang_decl_ctx, die);
} else {
- CompilerType class_opaque_type =
- class_type->GetForwardCompilerType();
- if (ClangASTContext::IsCXXClassType(class_opaque_type)) {
- if (class_opaque_type.IsBeingDefined() || alternate_defn) {
- if (!is_static && !die.HasChildren()) {
- // We have a C++ member function with no children (this
- // pointer!) and clang will get mad if we try and make
- // a function that isn't well formed in the DWARF, so
- // we will just skip it...
- type_handled = true;
- } else {
- bool add_method = true;
- if (alternate_defn) {
- // If an alternate definition for the class exists,
- // then add the method only if an equivalent is not
- // already present.
- clang::CXXRecordDecl *record_decl =
- m_ast.GetAsCXXRecordDecl(
- class_opaque_type.GetOpaqueQualType());
- if (record_decl) {
- for (auto method_iter = record_decl->method_begin();
- method_iter != record_decl->method_end();
- method_iter++) {
- clang::CXXMethodDecl *method_decl = *method_iter;
- if (method_decl->getNameInfo().getAsString() ==
- attrs.name.GetStringRef()) {
- if (method_decl->getType() ==
- ClangUtil::GetQualType(clang_type)) {
- add_method = false;
- LinkDeclContextToDIE(
- ClangASTContext::GetAsDeclContext(
- method_decl),
- die);
- type_handled = true;
-
- break;
- }
+ dwarf->GetObjectFile()->GetModule()->ReportWarning(
+ "0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8x"
+ ") has no decl\n",
+ die.GetID(), abs_die.GetOffset());
+ }
+ type_handled = true;
+ } else {
+ CompilerType class_opaque_type =
+ class_type->GetForwardCompilerType();
+ if (ClangASTContext::IsCXXClassType(class_opaque_type)) {
+ if (class_opaque_type.IsBeingDefined() || alternate_defn) {
+ if (!is_static && !die.HasChildren()) {
+ // We have a C++ member function with no children (this
+ // pointer!) and clang will get mad if we try and make
+ // a function that isn't well formed in the DWARF, so
+ // we will just skip it...
+ type_handled = true;
+ } else {
+ bool add_method = true;
+ if (alternate_defn) {
+ // If an alternate definition for the class exists,
+ // then add the method only if an equivalent is not
+ // already present.
+ clang::CXXRecordDecl *record_decl =
+ m_ast.GetAsCXXRecordDecl(
+ class_opaque_type.GetOpaqueQualType());
+ if (record_decl) {
+ for (auto method_iter = record_decl->method_begin();
+ method_iter != record_decl->method_end();
+ method_iter++) {
+ clang::CXXMethodDecl *method_decl = *method_iter;
+ if (method_decl->getNameInfo().getAsString() ==
+ attrs.name.GetStringRef()) {
+ if (method_decl->getType() ==
+ ClangUtil::GetQualType(clang_type)) {
+ add_method = false;
+ LinkDeclContextToDIE(method_decl, die);
+ type_handled = true;
+
+ break;
}
}
}
}
+ }
- if (add_method) {
- llvm::PrettyStackTraceFormat stack_trace(
- "SymbolFileDWARF::ParseType() is adding a method "
- "%s to class %s in DIE 0x%8.8" PRIx64 " from %s",
- attrs.name.GetCString(),
- class_type->GetName().GetCString(), die.GetID(),
- dwarf->GetObjectFile()
- ->GetFileSpec()
- .GetPath()
- .c_str());
-
- const bool is_attr_used = false;
- // Neither GCC 4.2 nor clang++ currently set a valid
- // accessibility in the DWARF for C++ methods...
- // Default to public for now...
- if (attrs.accessibility == eAccessNone)
- attrs.accessibility = eAccessPublic;
-
- clang::CXXMethodDecl *cxx_method_decl =
- m_ast.AddMethodToCXXRecordType(
- class_opaque_type.GetOpaqueQualType(),
- attrs.name.GetCString(), attrs.mangled_name,
- clang_type, attrs.accessibility, attrs.is_virtual,
- is_static, attrs.is_inline, attrs.is_explicit,
- is_attr_used, attrs.is_artificial);
-
- type_handled = cxx_method_decl != NULL;
- // Artificial methods are always handled even when we
- // don't create a new declaration for them.
- type_handled |= attrs.is_artificial;
-
- if (cxx_method_decl) {
- LinkDeclContextToDIE(
- ClangASTContext::GetAsDeclContext(cxx_method_decl),
- die);
-
- ClangASTMetadata metadata;
- metadata.SetUserID(die.GetID());
-
- if (!object_pointer_name.empty()) {
- metadata.SetObjectPtrName(
- object_pointer_name.c_str());
- LLDB_LOGF(log,
- "Setting object pointer name: %s on method "
- "object %p.\n",
- object_pointer_name.c_str(),
- static_cast<void *>(cxx_method_decl));
- }
- m_ast.SetMetadata(cxx_method_decl, metadata);
- } else {
- ignore_containing_context = true;
+ if (add_method) {
+ llvm::PrettyStackTraceFormat stack_trace(
+ "SymbolFileDWARF::ParseType() is adding a method "
+ "%s to class %s in DIE 0x%8.8" PRIx64 " from %s",
+ attrs.name.GetCString(),
+ class_type->GetName().GetCString(), die.GetID(),
+ dwarf->GetObjectFile()
+ ->GetFileSpec()
+ .GetPath()
+ .c_str());
+
+ const bool is_attr_used = false;
+ // Neither GCC 4.2 nor clang++ currently set a valid
+ // accessibility in the DWARF for C++ methods...
+ // Default to public for now...
+ if (attrs.accessibility == eAccessNone)
+ attrs.accessibility = eAccessPublic;
+
+ clang::CXXMethodDecl *cxx_method_decl =
+ m_ast.AddMethodToCXXRecordType(
+ class_opaque_type.GetOpaqueQualType(),
+ attrs.name.GetCString(), attrs.mangled_name,
+ clang_type, attrs.accessibility, attrs.is_virtual,
+ is_static, attrs.is_inline, attrs.is_explicit,
+ is_attr_used, attrs.is_artificial);
+
+ type_handled = cxx_method_decl != NULL;
+ // Artificial methods are always handled even when we
+ // don't create a new declaration for them.
+ type_handled |= attrs.is_artificial;
+
+ if (cxx_method_decl) {
+ LinkDeclContextToDIE(cxx_method_decl, die);
+
+ ClangASTMetadata metadata;
+ metadata.SetUserID(die.GetID());
+
+ if (!object_pointer_name.empty()) {
+ metadata.SetObjectPtrName(
+ object_pointer_name.c_str());
+ LLDB_LOGF(log,
+ "Setting object pointer name: %s on method "
+ "object %p.\n",
+ object_pointer_name.c_str(),
+ static_cast<void *>(cxx_method_decl));
}
+ m_ast.SetMetadata(cxx_method_decl, metadata);
+ } else {
+ ignore_containing_context = true;
}
}
- } else {
- // We were asked to parse the type for a method in a
- // class, yet the class hasn't been asked to complete
- // itself through the clang::ExternalASTSource protocol,
- // so we need to just have the class complete itself and
- // do things the right way, then our
- // DIE should then have an entry in the
- // dwarf->GetDIEToType() map. First
- // we need to modify the dwarf->GetDIEToType() so it
- // doesn't think we are trying to parse this DIE
- // anymore...
- dwarf->GetDIEToType()[die.GetDIE()] = NULL;
-
- // Now we get the full type to force our class type to
- // complete itself using the clang::ExternalASTSource
- // protocol which will parse all base classes and all
- // methods (including the method for this DIE).
- class_type->GetFullCompilerType();
-
- // The type for this DIE should have been filled in the
- // function call above
- type_ptr = dwarf->GetDIEToType()[die.GetDIE()];
- if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) {
- type_sp = type_ptr->shared_from_this();
- break;
- }
-
- // FIXME This is fixing some even uglier behavior but we
- // really need to
- // uniq the methods of each class as well as the class
- // itself. <rdar://problem/11240464>
- type_handled = true;
}
+ } else {
+ // We were asked to parse the type for a method in a
+ // class, yet the class hasn't been asked to complete
+ // itself through the clang::ExternalASTSource protocol,
+ // so we need to just have the class complete itself and
+ // do things the right way, then our
+ // DIE should then have an entry in the
+ // dwarf->GetDIEToType() map. First
+ // we need to modify the dwarf->GetDIEToType() so it
+ // doesn't think we are trying to parse this DIE
+ // anymore...
+ dwarf->GetDIEToType()[die.GetDIE()] = NULL;
+
+ // Now we get the full type to force our class type to
+ // complete itself using the clang::ExternalASTSource
+ // protocol which will parse all base classes and all
+ // methods (including the method for this DIE).
+ class_type->GetFullCompilerType();
+
+ // The type for this DIE should have been filled in the
+ // function call above
+ Type *type_ptr = dwarf->GetDIEToType()[die.GetDIE()];
+ if (type_ptr && type_ptr != DIE_IS_BEING_PARSED) {
+ return type_ptr->shared_from_this();
+ }
+
+ // FIXME This is fixing some even uglier behavior but we
+ // really need to
+ // uniq the methods of each class as well as the class
+ // itself. <rdar://problem/11240464>
+ type_handled = true;
}
}
}
}
}
+ }
- if (!type_handled) {
- clang::FunctionDecl *function_decl = nullptr;
- clang::FunctionDecl *template_function_decl = nullptr;
+ if (!type_handled) {
+ clang::FunctionDecl *function_decl = nullptr;
+ clang::FunctionDecl *template_function_decl = nullptr;
- if (attrs.abstract_origin.IsValid()) {
- DWARFDIE abs_die = attrs.abstract_origin.Reference();
+ if (attrs.abstract_origin.IsValid()) {
+ DWARFDIE abs_die = attrs.abstract_origin.Reference();
- if (dwarf->ResolveType(abs_die)) {
- function_decl = llvm::dyn_cast_or_null<clang::FunctionDecl>(
- GetCachedClangDeclContextForDIE(abs_die));
+ if (dwarf->ResolveType(abs_die)) {
+ function_decl = llvm::dyn_cast_or_null<clang::FunctionDecl>(
+ GetCachedClangDeclContextForDIE(abs_die));
- if (function_decl) {
- LinkDeclContextToDIE(function_decl, die);
- }
+ if (function_decl) {
+ LinkDeclContextToDIE(function_decl, die);
}
}
+ }
- if (!function_decl) {
- // We just have a function that isn't part of a class
- function_decl = m_ast.CreateFunctionDeclaration(
+ if (!function_decl) {
+ // We just have a function that isn't part of a class
+ function_decl = m_ast.CreateFunctionDeclaration(
+ ignore_containing_context ? m_ast.GetTranslationUnitDecl()
+ : containing_decl_ctx,
+ attrs.name.GetCString(), clang_type, attrs.storage,
+ attrs.is_inline);
+
+ if (has_template_params) {
+ ClangASTContext::TemplateParameterInfos template_param_infos;
+ ParseTemplateParameterInfos(die, template_param_infos);
+ template_function_decl = m_ast.CreateFunctionDeclaration(
ignore_containing_context ? m_ast.GetTranslationUnitDecl()
: containing_decl_ctx,
attrs.name.GetCString(), clang_type, attrs.storage,
attrs.is_inline);
+ clang::FunctionTemplateDecl *func_template_decl =
+ m_ast.CreateFunctionTemplateDecl(
+ containing_decl_ctx, template_function_decl,
+ attrs.name.GetCString(), template_param_infos);
+ m_ast.CreateFunctionTemplateSpecializationInfo(
+ function_decl, func_template_decl, template_param_infos);
+ }
- if (has_template_params) {
- ClangASTContext::TemplateParameterInfos template_param_infos;
- ParseTemplateParameterInfos(die, template_param_infos);
- template_function_decl = m_ast.CreateFunctionDeclaration(
- ignore_containing_context ? m_ast.GetTranslationUnitDecl()
- : containing_decl_ctx,
- attrs.name.GetCString(), clang_type, attrs.storage,
- attrs.is_inline);
- clang::FunctionTemplateDecl *func_template_decl =
- m_ast.CreateFunctionTemplateDecl(
- containing_decl_ctx, template_function_decl,
- attrs.name.GetCString(), template_param_infos);
- m_ast.CreateFunctionTemplateSpecializationInfo(
- function_decl, func_template_decl, template_param_infos);
- }
-
- lldbassert(function_decl);
+ lldbassert(function_decl);
- if (function_decl) {
- LinkDeclContextToDIE(function_decl, die);
+ if (function_decl) {
+ LinkDeclContextToDIE(function_decl, die);
- if (!function_param_decls.empty()) {
- m_ast.SetFunctionParameters(function_decl,
+ if (!function_param_decls.empty()) {
+ m_ast.SetFunctionParameters(function_decl,
+ &function_param_decls.front(),
+ function_param_decls.size());
+ if (template_function_decl)
+ m_ast.SetFunctionParameters(template_function_decl,
&function_param_decls.front(),
function_param_decls.size());
- if (template_function_decl)
- m_ast.SetFunctionParameters(template_function_decl,
- &function_param_decls.front(),
- function_param_decls.size());
- }
+ }
- ClangASTMetadata metadata;
- metadata.SetUserID(die.GetID());
+ ClangASTMetadata metadata;
+ metadata.SetUserID(die.GetID());
- if (!object_pointer_name.empty()) {
- metadata.SetObjectPtrName(object_pointer_name.c_str());
- LLDB_LOGF(log,
- "Setting object pointer name: %s on function "
- "object %p.",
- object_pointer_name.c_str(),
- static_cast<void *>(function_decl));
- }
- m_ast.SetMetadata(function_decl, metadata);
+ if (!object_pointer_name.empty()) {
+ metadata.SetObjectPtrName(object_pointer_name.c_str());
+ LLDB_LOGF(log,
+ "Setting object pointer name: %s on function "
+ "object %p.",
+ object_pointer_name.c_str(),
+ static_cast<void *>(function_decl));
}
+ m_ast.SetMetadata(function_decl, metadata);
}
}
}
- type_sp = std::make_shared<Type>(
- die.GetID(), dwarf, attrs.name, llvm::None, nullptr, LLDB_INVALID_UID,
- Type::eEncodingIsUID, &attrs.decl, clang_type, Type::eResolveStateFull);
- assert(type_sp.get());
- } break;
+ }
+ return std::make_shared<Type>(
+ die.GetID(), dwarf, attrs.name, llvm::None, nullptr, LLDB_INVALID_UID,
+ Type::eEncodingIsUID, &attrs.decl, clang_type, Type::ResolveState::Full);
+}
- case DW_TAG_array_type: {
- DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
- DW_TAG_value_to_name(tag), type_name_cstr);
+TypeSP DWARFASTParserClang::ParseArrayType(const DWARFDIE &die,
+ ParsedDWARFTypeAttributes &attrs) {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
- DWARFDIE type_die = attrs.type.Reference();
- Type *element_type = dwarf->ResolveTypeUID(type_die, true);
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
+ DW_TAG_value_to_name(tag), type_name_cstr);
- if (element_type) {
- auto array_info = ParseChildArrayInfo(die);
- if (array_info) {
- attrs.byte_stride = array_info->byte_stride;
- attrs.bit_stride = array_info->bit_stride;
- }
- if (attrs.byte_stride == 0 && attrs.bit_stride == 0)
- attrs.byte_stride = element_type->GetByteSize().getValueOr(0);
- CompilerType array_element_type = element_type->GetForwardCompilerType();
-
- if (ClangASTContext::IsCXXClassType(array_element_type) &&
- !array_element_type.GetCompleteType()) {
- ModuleSP module_sp = die.GetModule();
- if (module_sp) {
- if (die.GetCU()->GetProducer() == eProducerClang)
- module_sp->ReportError(
- "DWARF DW_TAG_array_type DIE at 0x%8.8x has a "
- "class/union/struct element type DIE 0x%8.8x that is a "
- "forward declaration, not a complete definition.\nTry "
- "compiling the source file with -fstandalone-debug or "
- "disable -gmodules",
- die.GetOffset(), type_die.GetOffset());
- else
- module_sp->ReportError(
- "DWARF DW_TAG_array_type DIE at 0x%8.8x has a "
- "class/union/struct element type DIE 0x%8.8x that is a "
- "forward declaration, not a complete definition.\nPlease "
- "file a bug against the compiler and include the "
- "preprocessed output for %s",
- die.GetOffset(), type_die.GetOffset(),
- GetUnitName(die).c_str());
- }
+ DWARFDIE type_die = attrs.type.Reference();
+ Type *element_type = dwarf->ResolveTypeUID(type_die, true);
- // We have no choice other than to pretend that the element class
- // type is complete. If we don't do this, clang will crash when
- // trying to layout the class. Since we provide layout
- // assistance, all ivars in this class and other classes will be
- // fine, this is the best we can do short of crashing.
- if (ClangASTContext::StartTagDeclarationDefinition(
- array_element_type)) {
- ClangASTContext::CompleteTagDeclarationDefinition(array_element_type);
- } else {
- module_sp->ReportError("DWARF DIE at 0x%8.8x was not able to "
- "start its definition.\nPlease file a "
- "bug and attach the file at the start "
- "of this error message",
- type_die.GetOffset());
- }
- }
+ if (!element_type)
+ return nullptr;
- uint64_t array_element_bit_stride =
- attrs.byte_stride * 8 + attrs.bit_stride;
- if (array_info && array_info->element_orders.size() > 0) {
- uint64_t num_elements = 0;
- auto end = array_info->element_orders.rend();
- for (auto pos = array_info->element_orders.rbegin(); pos != end;
- ++pos) {
- num_elements = *pos;
- clang_type = m_ast.CreateArrayType(array_element_type, num_elements,
- attrs.is_vector);
- array_element_type = clang_type;
- array_element_bit_stride =
- num_elements ? array_element_bit_stride * num_elements
- : array_element_bit_stride;
- }
- } else {
- clang_type = m_ast.CreateArrayType(array_element_type, 0, attrs.is_vector);
- }
- ConstString empty_name;
- type_sp = std::make_shared<Type>(
- die.GetID(), dwarf, empty_name, array_element_bit_stride / 8, nullptr,
- dwarf->GetUID(type_die), Type::eEncodingIsUID, &attrs.decl,
- clang_type, Type::eResolveStateFull);
- type_sp->SetEncodingType(element_type);
- m_ast.SetMetadataAsUserID(clang_type.GetOpaqueQualType(), die.GetID());
+ llvm::Optional<SymbolFile::ArrayInfo> array_info = ParseChildArrayInfo(die);
+ if (array_info) {
+ attrs.byte_stride = array_info->byte_stride;
+ attrs.bit_stride = array_info->bit_stride;
+ }
+ if (attrs.byte_stride == 0 && attrs.bit_stride == 0)
+ attrs.byte_stride = element_type->GetByteSize().getValueOr(0);
+ CompilerType array_element_type = element_type->GetForwardCompilerType();
+
+ if (ClangASTContext::IsCXXClassType(array_element_type) &&
+ !array_element_type.GetCompleteType()) {
+ ModuleSP module_sp = die.GetModule();
+ if (module_sp) {
+ if (die.GetCU()->GetProducer() == eProducerClang)
+ module_sp->ReportError(
+ "DWARF DW_TAG_array_type DIE at 0x%8.8x has a "
+ "class/union/struct element type DIE 0x%8.8x that is a "
+ "forward declaration, not a complete definition.\nTry "
+ "compiling the source file with -fstandalone-debug or "
+ "disable -gmodules",
+ die.GetOffset(), type_die.GetOffset());
+ else
+ module_sp->ReportError(
+ "DWARF DW_TAG_array_type DIE at 0x%8.8x has a "
+ "class/union/struct element type DIE 0x%8.8x that is a "
+ "forward declaration, not a complete definition.\nPlease "
+ "file a bug against the compiler and include the "
+ "preprocessed output for %s",
+ die.GetOffset(), type_die.GetOffset(), GetUnitName(die).c_str());
+ }
+
+ // We have no choice other than to pretend that the element class
+ // type is complete. If we don't do this, clang will crash when
+ // trying to layout the class. Since we provide layout
+ // assistance, all ivars in this class and other classes will be
+ // fine, this is the best we can do short of crashing.
+ if (ClangASTContext::StartTagDeclarationDefinition(array_element_type)) {
+ ClangASTContext::CompleteTagDeclarationDefinition(array_element_type);
+ } else {
+ module_sp->ReportError("DWARF DIE at 0x%8.8x was not able to "
+ "start its definition.\nPlease file a "
+ "bug and attach the file at the start "
+ "of this error message",
+ type_die.GetOffset());
}
- } break;
+ }
- case DW_TAG_ptr_to_member_type: {
- Type *pointee_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true);
- Type *class_type =
- dwarf->ResolveTypeUID(attrs.containing_type.Reference(), true);
+ uint64_t array_element_bit_stride =
+ attrs.byte_stride * 8 + attrs.bit_stride;
+ CompilerType clang_type;
+ if (array_info && array_info->element_orders.size() > 0) {
+ uint64_t num_elements = 0;
+ auto end = array_info->element_orders.rend();
+ for (auto pos = array_info->element_orders.rbegin(); pos != end; ++pos) {
+ num_elements = *pos;
+ clang_type = m_ast.CreateArrayType(array_element_type, num_elements,
+ attrs.is_vector);
+ array_element_type = clang_type;
+ array_element_bit_stride = num_elements
+ ? array_element_bit_stride * num_elements
+ : array_element_bit_stride;
+ }
+ } else {
+ clang_type =
+ m_ast.CreateArrayType(array_element_type, 0, attrs.is_vector);
+ }
+ ConstString empty_name;
+ TypeSP type_sp = std::make_shared<Type>(
+ die.GetID(), dwarf, empty_name, array_element_bit_stride / 8, nullptr,
+ dwarf->GetUID(type_die), Type::eEncodingIsUID, &attrs.decl, clang_type,
+ Type::ResolveState::Full);
+ type_sp->SetEncodingType(element_type);
+ const clang::Type *type = ClangUtil::GetQualType(clang_type).getTypePtr();
+ m_ast.SetMetadataAsUserID(type, die.GetID());
+ return type_sp;
+}
- CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType();
- CompilerType class_clang_type = class_type->GetLayoutCompilerType();
+TypeSP DWARFASTParserClang::ParsePointerToMemberType(
+ const DWARFDIE &die, const ParsedDWARFTypeAttributes &attrs) {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ Type *pointee_type = dwarf->ResolveTypeUID(attrs.type.Reference(), true);
+ Type *class_type =
+ dwarf->ResolveTypeUID(attrs.containing_type.Reference(), true);
- clang_type = ClangASTContext::CreateMemberPointerType(class_clang_type,
- pointee_clang_type);
+ CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType();
+ CompilerType class_clang_type = class_type->GetLayoutCompilerType();
- if (llvm::Optional<uint64_t> clang_type_size =
- clang_type.GetByteSize(nullptr)) {
- type_sp = std::make_shared<Type>(
- die.GetID(), dwarf, attrs.name, *clang_type_size, nullptr,
- LLDB_INVALID_UID, Type::eEncodingIsUID, nullptr, clang_type,
- Type::eResolveStateForward);
- }
+ CompilerType clang_type = ClangASTContext::CreateMemberPointerType(
+ class_clang_type, pointee_clang_type);
- break;
- }
- default:
- dwarf->GetObjectFile()->GetModule()->ReportError(
- "{0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and "
- "attach the file at the start of this error message",
- die.GetOffset(), tag, DW_TAG_value_to_name(tag));
- break;
+ if (llvm::Optional<uint64_t> clang_type_size =
+ clang_type.GetByteSize(nullptr)) {
+ return std::make_shared<Type>(die.GetID(), dwarf, attrs.name,
+ *clang_type_size, nullptr, LLDB_INVALID_UID,
+ Type::eEncodingIsUID, nullptr, clang_type,
+ Type::ResolveState::Forward);
}
-
- // TODO: We should consider making the switch above exhaustive to simplify
- // control flow in ParseTypeFromDWARF. Then, we could simply replace this
- // return statement with a call to llvm_unreachable.
- return UpdateSymbolContextScopeForType(sc, die, type_sp);
+ return nullptr;
}
TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType(
@@ -1281,20 +1380,20 @@ TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType(
DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die);
dw_tag_t sc_parent_tag = sc_parent_die.Tag();
- SymbolContextScope *symbol_context_scope = NULL;
+ SymbolContextScope *symbol_context_scope = nullptr;
if (sc_parent_tag == DW_TAG_compile_unit ||
sc_parent_tag == DW_TAG_partial_unit) {
symbol_context_scope = sc.comp_unit;
- } else if (sc.function != NULL && sc_parent_die) {
+ } else if (sc.function != nullptr && sc_parent_die) {
symbol_context_scope =
sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
- if (symbol_context_scope == NULL)
+ if (symbol_context_scope == nullptr)
symbol_context_scope = sc.function;
} else {
symbol_context_scope = sc.module_sp.get();
}
- if (symbol_context_scope != NULL)
+ if (symbol_context_scope != nullptr)
type_sp->SetSymbolContextScope(symbol_context_scope);
// We are ready to put this type into the uniqued list up at the module
@@ -1306,7 +1405,8 @@ TypeSP DWARFASTParserClang::UpdateSymbolContextScopeForType(
}
TypeSP
-DWARFASTParserClang::ParseStructureLikeDIE(const DWARFDIE &die,
+DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc,
+ const DWARFDIE &die,
ParsedDWARFTypeAttributes &attrs) {
TypeSP type_sp;
CompilerType clang_type;
@@ -1438,9 +1538,9 @@ DWARFASTParserClang::ParseStructureLikeDIE(const DWARFDIE &die,
attrs.name.GetCString());
}
- // See if the type comes from a DWO module and if so, track down that
- // type.
- type_sp = ParseTypeFromDWO(die, log);
+ // See if the type comes from a Clang module and if so, track down
+ // that type.
+ type_sp = ParseTypeFromClangModule(sc, die, log);
if (type_sp)
return type_sp;
@@ -1495,7 +1595,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const DWARFDIE &die,
// backing the Decl is complete before adding children to it. This is
// not an issue in the non-gmodules case because the debug info will
// always contain a full definition of parent types in that case.
- CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die,
+ CompleteExternalTagDeclType(m_ast, GetClangASTImporter(), decl_ctx, die,
attrs.name.GetCString());
if (attrs.accessibility == eAccessNone && decl_ctx) {
@@ -1546,7 +1646,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const DWARFDIE &die,
clang_type_was_created = true;
clang_type = m_ast.CreateRecordType(
decl_ctx, attrs.accessibility, attrs.name.GetCString(), tag_decl_kind,
- attrs.class_language, &metadata);
+ attrs.class_language, &metadata, attrs.exports_symbols);
}
}
@@ -1557,7 +1657,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const DWARFDIE &die,
type_sp = std::make_shared<Type>(die.GetID(), dwarf, attrs.name,
attrs.byte_size, nullptr, LLDB_INVALID_UID,
Type::eEncodingIsUID, &attrs.decl,
- clang_type, Type::eResolveStateForward);
+ clang_type, Type::ResolveState::Forward);
type_sp->SetIsCompleteObjCClass(attrs.is_complete_objc_class);
@@ -1621,7 +1721,7 @@ DWARFASTParserClang::ParseStructureLikeDIE(const DWARFDIE &die,
ClangASTContext::GetAsRecordDecl(clang_type);
if (record_decl) {
- GetClangASTImporter().InsertRecordDecl(
+ GetClangASTImporter().SetRecordLayout(
record_decl, ClangASTImporter::LayoutInfo());
}
}
@@ -1810,7 +1910,7 @@ bool DWARFASTParserClang::ParseTemplateDIE(
}
}
- clang::ASTContext *ast = m_ast.getASTContext();
+ clang::ASTContext &ast = m_ast.getASTContext();
if (!clang_type)
clang_type = m_ast.GetBasicType(eBasicTypeVoid);
@@ -1830,7 +1930,7 @@ bool DWARFASTParserClang::ParseTemplateDIE(
return false;
llvm::APInt apint(*size, uval64, is_signed);
template_param_infos.args.push_back(
- clang::TemplateArgument(*ast, llvm::APSInt(apint, !is_signed),
+ clang::TemplateArgument(ast, llvm::APSInt(apint, !is_signed),
ClangUtil::GetQualType(clang_type)));
} else {
template_param_infos.args.push_back(
@@ -1880,6 +1980,182 @@ bool DWARFASTParserClang::ParseTemplateParameterInfos(
return template_param_infos.args.size() == template_param_infos.names.size();
}
+bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die,
+ lldb_private::Type *type,
+ CompilerType &clang_type) {
+ const dw_tag_t tag = die.Tag();
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+
+ ClangASTImporter::LayoutInfo layout_info;
+
+ {
+ if (die.HasChildren()) {
+ LanguageType class_language = eLanguageTypeUnknown;
+ if (ClangASTContext::IsObjCObjectOrInterfaceType(clang_type)) {
+ class_language = eLanguageTypeObjC;
+ // For objective C we don't start the definition when the class is
+ // created.
+ ClangASTContext::StartTagDeclarationDefinition(clang_type);
+ }
+
+ int tag_decl_kind = -1;
+ AccessType default_accessibility = eAccessNone;
+ if (tag == DW_TAG_structure_type) {
+ tag_decl_kind = clang::TTK_Struct;
+ default_accessibility = eAccessPublic;
+ } else if (tag == DW_TAG_union_type) {
+ tag_decl_kind = clang::TTK_Union;
+ default_accessibility = eAccessPublic;
+ } else if (tag == DW_TAG_class_type) {
+ tag_decl_kind = clang::TTK_Class;
+ default_accessibility = eAccessPrivate;
+ }
+
+ std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;
+ std::vector<int> member_accessibilities;
+ bool is_a_class = false;
+ // Parse members and base classes first
+ std::vector<DWARFDIE> member_function_dies;
+
+ DelayedPropertyList delayed_properties;
+ ParseChildMembers(die, clang_type, class_language, bases,
+ member_accessibilities, member_function_dies,
+ delayed_properties, default_accessibility, is_a_class,
+ layout_info);
+
+ // Now parse any methods if there were any...
+ for (const DWARFDIE &die : member_function_dies)
+ dwarf->ResolveType(die);
+
+ if (class_language == eLanguageTypeObjC) {
+ ConstString class_name(clang_type.GetTypeName());
+ if (class_name) {
+ DIEArray method_die_offsets;
+ dwarf->GetObjCMethodDIEOffsets(class_name, method_die_offsets);
+
+ if (!method_die_offsets.empty()) {
+ DWARFDebugInfo *debug_info = dwarf->DebugInfo();
+
+ const size_t num_matches = method_die_offsets.size();
+ for (size_t i = 0; i < num_matches; ++i) {
+ const DIERef &die_ref = method_die_offsets[i];
+ DWARFDIE method_die = debug_info->GetDIE(die_ref);
+
+ if (method_die)
+ method_die.ResolveType();
+ }
+ }
+
+ for (DelayedPropertyList::iterator pi = delayed_properties.begin(),
+ pe = delayed_properties.end();
+ pi != pe; ++pi)
+ pi->Finalize();
+ }
+ }
+
+ // If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we
+ // need to tell the clang type it is actually a class.
+ if (class_language != eLanguageTypeObjC) {
+ if (is_a_class && tag_decl_kind != clang::TTK_Class)
+ m_ast.SetTagTypeKind(ClangUtil::GetQualType(clang_type),
+ clang::TTK_Class);
+ }
+
+ // Since DW_TAG_structure_type gets used for both classes and
+ // structures, we may need to set any DW_TAG_member fields to have a
+ // "private" access if none was specified. When we parsed the child
+ // members we tracked that actual accessibility value for each
+ // DW_TAG_member in the "member_accessibilities" array. If the value
+ // for the member is zero, then it was set to the
+ // "default_accessibility" which for structs was "public". Below we
+ // correct this by setting any fields to "private" that weren't
+ // correctly set.
+ if (is_a_class && !member_accessibilities.empty()) {
+ // This is a class and all members that didn't have their access
+ // specified are private.
+ m_ast.SetDefaultAccessForRecordFields(
+ m_ast.GetAsRecordDecl(clang_type), eAccessPrivate,
+ &member_accessibilities.front(), member_accessibilities.size());
+ }
+
+ if (!bases.empty()) {
+ // Make sure all base classes refer to complete types and not forward
+ // declarations. If we don't do this, clang will crash with an
+ // assertion in the call to clang_type.TransferBaseClasses()
+ for (const auto &base_class : bases) {
+ clang::TypeSourceInfo *type_source_info =
+ base_class->getTypeSourceInfo();
+ if (type_source_info) {
+ CompilerType base_class_type =
+ m_ast.GetType(type_source_info->getType());
+ if (!base_class_type.GetCompleteType()) {
+ auto module = dwarf->GetObjectFile()->GetModule();
+ module->ReportError(":: Class '%s' has a base class '%s' which "
+ "does not have a complete definition.",
+ die.GetName(),
+ base_class_type.GetTypeName().GetCString());
+ if (die.GetCU()->GetProducer() == eProducerClang)
+ module->ReportError(":: Try compiling the source file with "
+ "-fstandalone-debug.");
+
+ // We have no choice other than to pretend that the base class
+ // is complete. If we don't do this, clang will crash when we
+ // call setBases() inside of
+ // "clang_type.TransferBaseClasses()" below. Since we
+ // provide layout assistance, all ivars in this class and other
+ // classes will be fine, this is the best we can do short of
+ // crashing.
+ if (ClangASTContext::StartTagDeclarationDefinition(
+ base_class_type)) {
+ ClangASTContext::CompleteTagDeclarationDefinition(
+ base_class_type);
+ }
+ }
+ }
+ }
+
+ m_ast.TransferBaseClasses(clang_type.GetOpaqueQualType(),
+ std::move(bases));
+ }
+ }
+ }
+
+ m_ast.AddMethodOverridesForCXXRecordType(clang_type.GetOpaqueQualType());
+ ClangASTContext::BuildIndirectFields(clang_type);
+ ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
+
+ if (!layout_info.field_offsets.empty() || !layout_info.base_offsets.empty() ||
+ !layout_info.vbase_offsets.empty()) {
+ if (type)
+ layout_info.bit_size = type->GetByteSize().getValueOr(0) * 8;
+ if (layout_info.bit_size == 0)
+ layout_info.bit_size =
+ die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;
+
+ clang::CXXRecordDecl *record_decl =
+ m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
+ if (record_decl)
+ GetClangASTImporter().SetRecordLayout(record_decl, layout_info);
+ }
+
+ return (bool)clang_type;
+}
+
+bool DWARFASTParserClang::CompleteEnumType(const DWARFDIE &die,
+ lldb_private::Type *type,
+ CompilerType &clang_type) {
+ if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) {
+ if (die.HasChildren()) {
+ bool is_signed = false;
+ clang_type.IsIntegerType(is_signed);
+ ParseChildEnumerators(clang_type, is_signed,
+ type->GetByteSize().getValueOr(0), die);
+ }
+ ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
+ }
+ return (bool)clang_type;
+}
+
bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
lldb_private::Type *type,
CompilerType &clang_type) {
@@ -1895,39 +2171,6 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
if (!die)
return false;
-#if defined LLDB_CONFIGURATION_DEBUG
- // For debugging purposes, the LLDB_DWARF_DONT_COMPLETE_TYPENAMES environment
- // variable can be set with one or more typenames separated by ';'
- // characters. This will cause this function to not complete any types whose
- // names match.
- //
- // Examples of setting this environment variable:
- //
- // LLDB_DWARF_DONT_COMPLETE_TYPENAMES=Foo
- // LLDB_DWARF_DONT_COMPLETE_TYPENAMES=Foo;Bar;Baz
- const char *dont_complete_typenames_cstr =
- getenv("LLDB_DWARF_DONT_COMPLETE_TYPENAMES");
- if (dont_complete_typenames_cstr && dont_complete_typenames_cstr[0]) {
- const char *die_name = die.GetName();
- if (die_name && die_name[0]) {
- const char *match = strstr(dont_complete_typenames_cstr, die_name);
- if (match) {
- size_t die_name_length = strlen(die_name);
- while (match) {
- const char separator_char = ';';
- const char next_char = match[die_name_length];
- if (next_char == '\0' || next_char == separator_char) {
- if (match == dont_complete_typenames_cstr ||
- match[-1] == separator_char)
- return false;
- }
- match = strstr(match + 1, die_name);
- }
- }
- }
- }
-#endif
-
const dw_tag_t tag = die.Tag();
Log *log =
@@ -1941,239 +2184,10 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
switch (tag) {
case DW_TAG_structure_type:
case DW_TAG_union_type:
- case DW_TAG_class_type: {
- ClangASTImporter::LayoutInfo layout_info;
-
- {
- if (die.HasChildren()) {
- LanguageType class_language = eLanguageTypeUnknown;
- if (ClangASTContext::IsObjCObjectOrInterfaceType(clang_type)) {
- class_language = eLanguageTypeObjC;
- // For objective C we don't start the definition when the class is
- // created.
- ClangASTContext::StartTagDeclarationDefinition(clang_type);
- }
-
- int tag_decl_kind = -1;
- AccessType default_accessibility = eAccessNone;
- if (tag == DW_TAG_structure_type) {
- tag_decl_kind = clang::TTK_Struct;
- default_accessibility = eAccessPublic;
- } else if (tag == DW_TAG_union_type) {
- tag_decl_kind = clang::TTK_Union;
- default_accessibility = eAccessPublic;
- } else if (tag == DW_TAG_class_type) {
- tag_decl_kind = clang::TTK_Class;
- default_accessibility = eAccessPrivate;
- }
-
- std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;
- std::vector<int> member_accessibilities;
- bool is_a_class = false;
- // Parse members and base classes first
- std::vector<DWARFDIE> member_function_dies;
-
- DelayedPropertyList delayed_properties;
- ParseChildMembers(die, clang_type, class_language, bases,
- member_accessibilities, member_function_dies,
- delayed_properties, default_accessibility, is_a_class,
- layout_info);
-
- // Now parse any methods if there were any...
- for (const DWARFDIE &die : member_function_dies)
- dwarf->ResolveType(die);
-
- if (class_language == eLanguageTypeObjC) {
- ConstString class_name(clang_type.GetTypeName());
- if (class_name) {
- DIEArray method_die_offsets;
- dwarf->GetObjCMethodDIEOffsets(class_name, method_die_offsets);
-
- if (!method_die_offsets.empty()) {
- DWARFDebugInfo *debug_info = dwarf->DebugInfo();
-
- const size_t num_matches = method_die_offsets.size();
- for (size_t i = 0; i < num_matches; ++i) {
- const DIERef &die_ref = method_die_offsets[i];
- DWARFDIE method_die = debug_info->GetDIE(die_ref);
-
- if (method_die)
- method_die.ResolveType();
- }
- }
-
- for (DelayedPropertyList::iterator pi = delayed_properties.begin(),
- pe = delayed_properties.end();
- pi != pe; ++pi)
- pi->Finalize();
- }
- }
-
- // If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we
- // need to tell the clang type it is actually a class.
- if (class_language != eLanguageTypeObjC) {
- if (is_a_class && tag_decl_kind != clang::TTK_Class)
- m_ast.SetTagTypeKind(ClangUtil::GetQualType(clang_type),
- clang::TTK_Class);
- }
-
- // Since DW_TAG_structure_type gets used for both classes and
- // structures, we may need to set any DW_TAG_member fields to have a
- // "private" access if none was specified. When we parsed the child
- // members we tracked that actual accessibility value for each
- // DW_TAG_member in the "member_accessibilities" array. If the value
- // for the member is zero, then it was set to the
- // "default_accessibility" which for structs was "public". Below we
- // correct this by setting any fields to "private" that weren't
- // correctly set.
- if (is_a_class && !member_accessibilities.empty()) {
- // This is a class and all members that didn't have their access
- // specified are private.
- m_ast.SetDefaultAccessForRecordFields(
- m_ast.GetAsRecordDecl(clang_type), eAccessPrivate,
- &member_accessibilities.front(), member_accessibilities.size());
- }
-
- if (!bases.empty()) {
- // Make sure all base classes refer to complete types and not forward
- // declarations. If we don't do this, clang will crash with an
- // assertion in the call to clang_type.TransferBaseClasses()
- for (const auto &base_class : bases) {
- clang::TypeSourceInfo *type_source_info =
- base_class->getTypeSourceInfo();
- if (type_source_info) {
- CompilerType base_class_type(
- &m_ast, type_source_info->getType().getAsOpaquePtr());
- if (!base_class_type.GetCompleteType()) {
- auto module = dwarf->GetObjectFile()->GetModule();
- module->ReportError(":: Class '%s' has a base class '%s' which "
- "does not have a complete definition.",
- die.GetName(),
- base_class_type.GetTypeName().GetCString());
- if (die.GetCU()->GetProducer() == eProducerClang)
- module->ReportError(":: Try compiling the source file with "
- "-fstandalone-debug.");
-
- // We have no choice other than to pretend that the base class
- // is complete. If we don't do this, clang will crash when we
- // call setBases() inside of
- // "clang_type.TransferBaseClasses()" below. Since we
- // provide layout assistance, all ivars in this class and other
- // classes will be fine, this is the best we can do short of
- // crashing.
- if (ClangASTContext::StartTagDeclarationDefinition(
- base_class_type)) {
- ClangASTContext::CompleteTagDeclarationDefinition(
- base_class_type);
- }
- }
- }
- }
-
- m_ast.TransferBaseClasses(clang_type.GetOpaqueQualType(),
- std::move(bases));
- }
- }
- }
-
- m_ast.AddMethodOverridesForCXXRecordType(clang_type.GetOpaqueQualType());
- ClangASTContext::BuildIndirectFields(clang_type);
- ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
-
- if (!layout_info.field_offsets.empty() ||
- !layout_info.base_offsets.empty() ||
- !layout_info.vbase_offsets.empty()) {
- if (type)
- layout_info.bit_size = type->GetByteSize().getValueOr(0) * 8;
- if (layout_info.bit_size == 0)
- layout_info.bit_size =
- die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;
-
- clang::CXXRecordDecl *record_decl =
- m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
- if (record_decl) {
- if (log) {
- ModuleSP module_sp = dwarf->GetObjectFile()->GetModule();
-
- if (module_sp) {
- module_sp->LogMessage(
- log,
- "ClangASTContext::CompleteTypeFromDWARF (clang_type = %p) "
- "caching layout info for record_decl = %p, bit_size = %" PRIu64
- ", alignment = %" PRIu64
- ", field_offsets[%u], base_offsets[%u], vbase_offsets[%u])",
- static_cast<void *>(clang_type.GetOpaqueQualType()),
- static_cast<void *>(record_decl), layout_info.bit_size,
- layout_info.alignment,
- static_cast<uint32_t>(layout_info.field_offsets.size()),
- static_cast<uint32_t>(layout_info.base_offsets.size()),
- static_cast<uint32_t>(layout_info.vbase_offsets.size()));
-
- uint32_t idx;
- {
- llvm::DenseMap<const clang::FieldDecl *, uint64_t>::const_iterator
- pos,
- end = layout_info.field_offsets.end();
- for (idx = 0, pos = layout_info.field_offsets.begin(); pos != end;
- ++pos, ++idx) {
- module_sp->LogMessage(
- log, "ClangASTContext::CompleteTypeFromDWARF (clang_type = "
- "%p) field[%u] = { bit_offset=%u, name='%s' }",
- static_cast<void *>(clang_type.GetOpaqueQualType()), idx,
- static_cast<uint32_t>(pos->second),
- pos->first->getNameAsString().c_str());
- }
- }
-
- {
- llvm::DenseMap<const clang::CXXRecordDecl *,
- clang::CharUnits>::const_iterator base_pos,
- base_end = layout_info.base_offsets.end();
- for (idx = 0, base_pos = layout_info.base_offsets.begin();
- base_pos != base_end; ++base_pos, ++idx) {
- module_sp->LogMessage(
- log, "ClangASTContext::CompleteTypeFromDWARF (clang_type = "
- "%p) base[%u] = { byte_offset=%u, name='%s' }",
- clang_type.GetOpaqueQualType(), idx,
- (uint32_t)base_pos->second.getQuantity(),
- base_pos->first->getNameAsString().c_str());
- }
- }
- {
- llvm::DenseMap<const clang::CXXRecordDecl *,
- clang::CharUnits>::const_iterator vbase_pos,
- vbase_end = layout_info.vbase_offsets.end();
- for (idx = 0, vbase_pos = layout_info.vbase_offsets.begin();
- vbase_pos != vbase_end; ++vbase_pos, ++idx) {
- module_sp->LogMessage(
- log, "ClangASTContext::CompleteTypeFromDWARF (clang_type = "
- "%p) vbase[%u] = { byte_offset=%u, name='%s' }",
- static_cast<void *>(clang_type.GetOpaqueQualType()), idx,
- static_cast<uint32_t>(vbase_pos->second.getQuantity()),
- vbase_pos->first->getNameAsString().c_str());
- }
- }
- }
- }
- GetClangASTImporter().InsertRecordDecl(record_decl, layout_info);
- }
- }
- }
-
- return (bool)clang_type;
-
+ case DW_TAG_class_type:
+ return CompleteRecordType(die, type, clang_type);
case DW_TAG_enumeration_type:
- if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) {
- if (die.HasChildren()) {
- bool is_signed = false;
- clang_type.IsIntegerType(is_signed);
- ParseChildEnumerators(clang_type, is_signed,
- type->GetByteSize().getValueOr(0), die);
- }
- ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
- }
- return (bool)clang_type;
-
+ return CompleteEnumType(die, type, clang_type);
default:
assert(false && "not a forward clang type decl!");
break;
@@ -2205,7 +2219,7 @@ CompilerDeclContext
DWARFASTParserClang::GetDeclContextForUIDFromDWARF(const DWARFDIE &die) {
clang::DeclContext *clang_decl_ctx = GetClangDeclContextForDIE(die);
if (clang_decl_ctx)
- return CompilerDeclContext(&m_ast, clang_decl_ctx);
+ return m_ast.CreateDeclContext(clang_decl_ctx);
return CompilerDeclContext();
}
@@ -2214,7 +2228,7 @@ DWARFASTParserClang::GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) {
clang::DeclContext *clang_decl_ctx =
GetClangDeclContextContainingDIE(die, nullptr);
if (clang_decl_ctx)
- return CompilerDeclContext(&m_ast, clang_decl_ctx);
+ return m_ast.CreateDeclContext(clang_decl_ctx);
return CompilerDeclContext();
}
@@ -2284,54 +2298,6 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
return enumerators_added;
}
-#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
-
-class DIEStack {
-public:
- void Push(const DWARFDIE &die) { m_dies.push_back(die); }
-
- void LogDIEs(Log *log) {
- StreamString log_strm;
- const size_t n = m_dies.size();
- log_strm.Printf("DIEStack[%" PRIu64 "]:\n", (uint64_t)n);
- for (size_t i = 0; i < n; i++) {
- std::string qualified_name;
- const DWARFDIE &die = m_dies[i];
- die.GetQualifiedName(qualified_name);
- log_strm.Printf("[%" PRIu64 "] 0x%8.8x: %s name='%s'\n", (uint64_t)i,
- die.GetOffset(), die.GetTagAsCString(),
- qualified_name.c_str());
- }
- log->PutCString(log_strm.GetData());
- }
- void Pop() { m_dies.pop_back(); }
-
- class ScopedPopper {
- public:
- ScopedPopper(DIEStack &die_stack)
- : m_die_stack(die_stack), m_valid(false) {}
-
- void Push(const DWARFDIE &die) {
- m_valid = true;
- m_die_stack.Push(die);
- }
-
- ~ScopedPopper() {
- if (m_valid)
- m_die_stack.Pop();
- }
-
- protected:
- DIEStack &m_die_stack;
- bool m_valid;
- };
-
-protected:
- typedef std::vector<DWARFDIE> Stack;
- Stack m_dies;
-};
-#endif
-
Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit,
const DWARFDIE &die) {
DWARFRangeList func_ranges;
@@ -2445,495 +2411,499 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit,
return nullptr;
}
-bool DWARFASTParserClang::ParseChildMembers(
- const DWARFDIE &parent_die, CompilerType &class_clang_type,
- const LanguageType class_language,
- std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,
+void DWARFASTParserClang::ParseSingleMember(
+ const DWARFDIE &die, const DWARFDIE &parent_die,
+ lldb_private::CompilerType &class_clang_type,
+ const lldb::LanguageType class_language,
std::vector<int> &member_accessibilities,
- std::vector<DWARFDIE> &member_function_dies,
- DelayedPropertyList &delayed_properties, AccessType &default_accessibility,
- bool &is_a_class, ClangASTImporter::LayoutInfo &layout_info) {
- if (!parent_die)
- return false;
-
+ lldb::AccessType &default_accessibility,
+ DelayedPropertyList &delayed_properties,
+ lldb_private::ClangASTImporter::LayoutInfo &layout_info,
+ BitfieldInfo &last_field_info) {
+ ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
+ const dw_tag_t tag = die.Tag();
// Get the parent byte size so we can verify any members will fit
const uint64_t parent_byte_size =
parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size, UINT64_MAX);
const uint64_t parent_bit_size =
parent_byte_size == UINT64_MAX ? UINT64_MAX : parent_byte_size * 8;
- uint32_t member_idx = 0;
- BitfieldInfo last_field_info;
-
- ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
- ClangASTContext *ast =
- llvm::dyn_cast_or_null<ClangASTContext>(class_clang_type.GetTypeSystem());
- if (ast == nullptr)
- return false;
-
- for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
- die = die.GetSibling()) {
- dw_tag_t tag = die.Tag();
-
- switch (tag) {
- case DW_TAG_member:
- case DW_TAG_APPLE_property: {
- DWARFAttributes attributes;
- const size_t num_attributes = die.GetAttributes(attributes);
- if (num_attributes > 0) {
- const char *name = nullptr;
- const char *prop_name = nullptr;
- const char *prop_getter_name = nullptr;
- const char *prop_setter_name = nullptr;
- uint32_t prop_attributes = 0;
-
- bool is_artificial = false;
- DWARFFormValue encoding_form;
- AccessType accessibility = eAccessNone;
- uint32_t member_byte_offset =
- (parent_die.Tag() == DW_TAG_union_type) ? 0 : UINT32_MAX;
- llvm::Optional<uint64_t> byte_size;
- int64_t bit_offset = 0;
- uint64_t data_bit_offset = UINT64_MAX;
- size_t bit_size = 0;
- bool is_external =
- false; // On DW_TAG_members, this means the member is static
- uint32_t i;
- for (i = 0; i < num_attributes && !is_artificial; ++i) {
- const dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(i, form_value)) {
- switch (attr) {
- case DW_AT_name:
- name = form_value.AsCString();
- break;
- case DW_AT_type:
- encoding_form = form_value;
- break;
- case DW_AT_bit_offset:
- bit_offset = form_value.Signed();
- break;
- case DW_AT_bit_size:
- bit_size = form_value.Unsigned();
- break;
- case DW_AT_byte_size:
- byte_size = form_value.Unsigned();
- break;
- case DW_AT_data_bit_offset:
- data_bit_offset = form_value.Unsigned();
- break;
- case DW_AT_data_member_location:
- if (form_value.BlockData()) {
- Value initialValue(0);
- Value memberOffset(0);
- const DWARFDataExtractor &debug_info_data = die.GetData();
- uint32_t block_length = form_value.Unsigned();
- uint32_t block_offset =
- form_value.BlockData() - debug_info_data.GetDataStart();
- if (DWARFExpression::Evaluate(
- nullptr, // ExecutionContext *
- nullptr, // RegisterContext *
- module_sp,
- DataExtractor(debug_info_data, block_offset,
- block_length),
- die.GetCU(), eRegisterKindDWARF, &initialValue, nullptr,
- memberOffset, nullptr)) {
- member_byte_offset =
- memberOffset.ResolveValue(nullptr).UInt();
- }
- } else {
- // With DWARF 3 and later, if the value is an integer constant,
- // this form value is the offset in bytes from the beginning of
- // the containing entity.
- member_byte_offset = form_value.Unsigned();
- }
- break;
-
- case DW_AT_accessibility:
- accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());
- break;
- case DW_AT_artificial:
- is_artificial = form_value.Boolean();
- break;
- case DW_AT_APPLE_property_name:
- prop_name = form_value.AsCString();
- break;
- case DW_AT_APPLE_property_getter:
- prop_getter_name = form_value.AsCString();
- break;
- case DW_AT_APPLE_property_setter:
- prop_setter_name = form_value.AsCString();
- break;
- case DW_AT_APPLE_property_attribute:
- prop_attributes = form_value.Unsigned();
- break;
- case DW_AT_external:
- is_external = form_value.Boolean();
- break;
-
- default:
- case DW_AT_declaration:
- case DW_AT_description:
- case DW_AT_mutable:
- case DW_AT_visibility:
- case DW_AT_sibling:
- break;
+ DWARFAttributes attributes;
+ const size_t num_attributes = die.GetAttributes(attributes);
+ if (num_attributes > 0) {
+ const char *name = nullptr;
+ const char *prop_name = nullptr;
+ const char *prop_getter_name = nullptr;
+ const char *prop_setter_name = nullptr;
+ uint32_t prop_attributes = 0;
+
+ bool is_artificial = false;
+ DWARFFormValue encoding_form;
+ AccessType accessibility = eAccessNone;
+ uint32_t member_byte_offset =
+ (parent_die.Tag() == DW_TAG_union_type) ? 0 : UINT32_MAX;
+ llvm::Optional<uint64_t> byte_size;
+ int64_t bit_offset = 0;
+ uint64_t data_bit_offset = UINT64_MAX;
+ size_t bit_size = 0;
+ bool is_external =
+ false; // On DW_TAG_members, this means the member is static
+ uint32_t i;
+ for (i = 0; i < num_attributes && !is_artificial; ++i) {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value)) {
+ switch (attr) {
+ case DW_AT_name:
+ name = form_value.AsCString();
+ break;
+ case DW_AT_type:
+ encoding_form = form_value;
+ break;
+ case DW_AT_bit_offset:
+ bit_offset = form_value.Signed();
+ break;
+ case DW_AT_bit_size:
+ bit_size = form_value.Unsigned();
+ break;
+ case DW_AT_byte_size:
+ byte_size = form_value.Unsigned();
+ break;
+ case DW_AT_data_bit_offset:
+ data_bit_offset = form_value.Unsigned();
+ break;
+ case DW_AT_data_member_location:
+ if (form_value.BlockData()) {
+ Value initialValue(0);
+ Value memberOffset(0);
+ const DWARFDataExtractor &debug_info_data = die.GetData();
+ uint32_t block_length = form_value.Unsigned();
+ uint32_t block_offset =
+ form_value.BlockData() - debug_info_data.GetDataStart();
+ if (DWARFExpression::Evaluate(
+ nullptr, // ExecutionContext *
+ nullptr, // RegisterContext *
+ module_sp,
+ DataExtractor(debug_info_data, block_offset, block_length),
+ die.GetCU(), eRegisterKindDWARF, &initialValue, nullptr,
+ memberOffset, nullptr)) {
+ member_byte_offset = memberOffset.ResolveValue(nullptr).UInt();
}
+ } else {
+ // With DWARF 3 and later, if the value is an integer constant,
+ // this form value is the offset in bytes from the beginning of
+ // the containing entity.
+ member_byte_offset = form_value.Unsigned();
}
- }
-
- if (prop_name) {
- ConstString fixed_getter;
- ConstString fixed_setter;
-
- // Check if the property getter/setter were provided as full names.
- // We want basenames, so we extract them.
-
- if (prop_getter_name && prop_getter_name[0] == '-') {
- ObjCLanguage::MethodName prop_getter_method(prop_getter_name, true);
- prop_getter_name = prop_getter_method.GetSelector().GetCString();
- }
+ break;
- if (prop_setter_name && prop_setter_name[0] == '-') {
- ObjCLanguage::MethodName prop_setter_method(prop_setter_name, true);
- prop_setter_name = prop_setter_method.GetSelector().GetCString();
- }
+ case DW_AT_accessibility:
+ accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());
+ break;
+ case DW_AT_artificial:
+ is_artificial = form_value.Boolean();
+ break;
+ case DW_AT_APPLE_property_name:
+ prop_name = form_value.AsCString();
+ break;
+ case DW_AT_APPLE_property_getter:
+ prop_getter_name = form_value.AsCString();
+ break;
+ case DW_AT_APPLE_property_setter:
+ prop_setter_name = form_value.AsCString();
+ break;
+ case DW_AT_APPLE_property_attribute:
+ prop_attributes = form_value.Unsigned();
+ break;
+ case DW_AT_external:
+ is_external = form_value.Boolean();
+ break;
- // If the names haven't been provided, they need to be filled in.
+ default:
+ case DW_AT_declaration:
+ case DW_AT_description:
+ case DW_AT_mutable:
+ case DW_AT_visibility:
+ case DW_AT_sibling:
+ break;
+ }
+ }
+ }
- if (!prop_getter_name) {
- prop_getter_name = prop_name;
- }
- if (!prop_setter_name && prop_name[0] &&
- !(prop_attributes & DW_APPLE_PROPERTY_readonly)) {
- StreamString ss;
+ if (prop_name) {
+ ConstString fixed_setter;
- ss.Printf("set%c%s:", toupper(prop_name[0]), &prop_name[1]);
+ // Check if the property getter/setter were provided as full names.
+ // We want basenames, so we extract them.
- fixed_setter.SetString(ss.GetString());
- prop_setter_name = fixed_setter.GetCString();
- }
- }
+ if (prop_getter_name && prop_getter_name[0] == '-') {
+ ObjCLanguage::MethodName prop_getter_method(prop_getter_name, true);
+ prop_getter_name = prop_getter_method.GetSelector().GetCString();
+ }
- // Clang has a DWARF generation bug where sometimes it represents
- // fields that are references with bad byte size and bit size/offset
- // information such as:
- //
- // DW_AT_byte_size( 0x00 )
- // DW_AT_bit_size( 0x40 )
- // DW_AT_bit_offset( 0xffffffffffffffc0 )
- //
- // So check the bit offset to make sure it is sane, and if the values
- // are not sane, remove them. If we don't do this then we will end up
- // with a crash if we try to use this type in an expression when clang
- // becomes unhappy with its recycled debug info.
-
- if (byte_size.getValueOr(0) == 0 && bit_offset < 0) {
- bit_size = 0;
- bit_offset = 0;
- }
+ if (prop_setter_name && prop_setter_name[0] == '-') {
+ ObjCLanguage::MethodName prop_setter_method(prop_setter_name, true);
+ prop_setter_name = prop_setter_method.GetSelector().GetCString();
+ }
- // FIXME: Make Clang ignore Objective-C accessibility for expressions
- if (class_language == eLanguageTypeObjC ||
- class_language == eLanguageTypeObjC_plus_plus)
- accessibility = eAccessNone;
-
- // Handle static members
- if (is_external && member_byte_offset == UINT32_MAX) {
- Type *var_type = die.ResolveTypeUID(encoding_form.Reference());
-
- if (var_type) {
- if (accessibility == eAccessNone)
- accessibility = eAccessPublic;
- ClangASTContext::AddVariableToRecordType(
- class_clang_type, name, var_type->GetLayoutCompilerType(),
- accessibility);
- }
- break;
- }
+ // If the names haven't been provided, they need to be filled in.
- if (!is_artificial) {
- Type *member_type = die.ResolveTypeUID(encoding_form.Reference());
-
- clang::FieldDecl *field_decl = nullptr;
- if (tag == DW_TAG_member) {
- if (member_type) {
- if (accessibility == eAccessNone)
- accessibility = default_accessibility;
- member_accessibilities.push_back(accessibility);
-
- uint64_t field_bit_offset =
- (member_byte_offset == UINT32_MAX ? 0
- : (member_byte_offset * 8));
- if (bit_size > 0) {
-
- BitfieldInfo this_field_info;
- this_field_info.bit_offset = field_bit_offset;
- this_field_info.bit_size = bit_size;
-
- /////////////////////////////////////////////////////////////
- // How to locate a field given the DWARF debug information
- //
- // AT_byte_size indicates the size of the word in which the bit
- // offset must be interpreted.
- //
- // AT_data_member_location indicates the byte offset of the
- // word from the base address of the structure.
- //
- // AT_bit_offset indicates how many bits into the word
- // (according to the host endianness) the low-order bit of the
- // field starts. AT_bit_offset can be negative.
- //
- // AT_bit_size indicates the size of the field in bits.
- /////////////////////////////////////////////////////////////
-
- if (data_bit_offset != UINT64_MAX) {
- this_field_info.bit_offset = data_bit_offset;
- } else {
- if (!byte_size)
- byte_size = member_type->GetByteSize();
-
- ObjectFile *objfile = die.GetDWARF()->GetObjectFile();
- if (objfile->GetByteOrder() == eByteOrderLittle) {
- this_field_info.bit_offset += byte_size.getValueOr(0) * 8;
- this_field_info.bit_offset -= (bit_offset + bit_size);
- } else {
- this_field_info.bit_offset += bit_offset;
- }
- }
+ if (!prop_getter_name) {
+ prop_getter_name = prop_name;
+ }
+ if (!prop_setter_name && prop_name[0] &&
+ !(prop_attributes & DW_APPLE_PROPERTY_readonly)) {
+ StreamString ss;
- if ((this_field_info.bit_offset >= parent_bit_size) ||
- !last_field_info.NextBitfieldOffsetIsValid(
- this_field_info.bit_offset)) {
- ObjectFile *objfile = die.GetDWARF()->GetObjectFile();
- objfile->GetModule()->ReportWarning(
- "0x%8.8" PRIx64 ": %s bitfield named \"%s\" has invalid "
- "bit offset (0x%8.8" PRIx64
- ") member will be ignored. Please file a bug against the "
- "compiler and include the preprocessed output for %s\n",
- die.GetID(), DW_TAG_value_to_name(tag), name,
- this_field_info.bit_offset,
- GetUnitName(parent_die).c_str());
- this_field_info.Clear();
- continue;
- }
+ ss.Printf("set%c%s:", toupper(prop_name[0]), &prop_name[1]);
- // Update the field bit offset we will report for layout
- field_bit_offset = this_field_info.bit_offset;
-
- // If the member to be emitted did not start on a character
- // boundary and there is empty space between the last field and
- // this one, then we need to emit an anonymous member filling
- // up the space up to its start. There are three cases here:
- //
- // 1 If the previous member ended on a character boundary, then
- // we can emit an
- // anonymous member starting at the most recent character
- // boundary.
- //
- // 2 If the previous member did not end on a character boundary
- // and the distance
- // from the end of the previous member to the current member
- // is less than a
- // word width, then we can emit an anonymous member starting
- // right after the
- // previous member and right before this member.
- //
- // 3 If the previous member did not end on a character boundary
- // and the distance
- // from the end of the previous member to the current member
- // is greater than
- // or equal a word width, then we act as in Case 1.
-
- const uint64_t character_width = 8;
- const uint64_t word_width = 32;
-
- // Objective-C has invalid DW_AT_bit_offset values in older
- // versions of clang, so we have to be careful and only insert
- // unnamed bitfields if we have a new enough clang.
- bool detect_unnamed_bitfields = true;
-
- if (class_language == eLanguageTypeObjC ||
- class_language == eLanguageTypeObjC_plus_plus)
- detect_unnamed_bitfields =
- die.GetCU()->Supports_unnamed_objc_bitfields();
-
- if (detect_unnamed_bitfields) {
- BitfieldInfo anon_field_info;
-
- if ((this_field_info.bit_offset % character_width) !=
- 0) // not char aligned
- {
- uint64_t last_field_end = 0;
-
- if (last_field_info.IsValid())
- last_field_end =
- last_field_info.bit_offset + last_field_info.bit_size;
-
- if (this_field_info.bit_offset != last_field_end) {
- if (((last_field_end % character_width) == 0) || // case 1
- (this_field_info.bit_offset - last_field_end >=
- word_width)) // case 3
- {
- anon_field_info.bit_size =
- this_field_info.bit_offset % character_width;
- anon_field_info.bit_offset =
- this_field_info.bit_offset -
- anon_field_info.bit_size;
- } else // case 2
- {
- anon_field_info.bit_size =
- this_field_info.bit_offset - last_field_end;
- anon_field_info.bit_offset = last_field_end;
- }
- }
- }
+ fixed_setter.SetString(ss.GetString());
+ prop_setter_name = fixed_setter.GetCString();
+ }
+ }
- if (anon_field_info.IsValid()) {
- clang::FieldDecl *unnamed_bitfield_decl =
- ClangASTContext::AddFieldToRecordType(
- class_clang_type, llvm::StringRef(),
- m_ast.GetBuiltinTypeForEncodingAndBitSize(
- eEncodingSint, word_width),
- accessibility, anon_field_info.bit_size);
+ // Clang has a DWARF generation bug where sometimes it represents
+ // fields that are references with bad byte size and bit size/offset
+ // information such as:
+ //
+ // DW_AT_byte_size( 0x00 )
+ // DW_AT_bit_size( 0x40 )
+ // DW_AT_bit_offset( 0xffffffffffffffc0 )
+ //
+ // So check the bit offset to make sure it is sane, and if the values
+ // are not sane, remove them. If we don't do this then we will end up
+ // with a crash if we try to use this type in an expression when clang
+ // becomes unhappy with its recycled debug info.
+
+ if (byte_size.getValueOr(0) == 0 && bit_offset < 0) {
+ bit_size = 0;
+ bit_offset = 0;
+ }
+
+ // FIXME: Make Clang ignore Objective-C accessibility for expressions
+ if (class_language == eLanguageTypeObjC ||
+ class_language == eLanguageTypeObjC_plus_plus)
+ accessibility = eAccessNone;
+
+ // Handle static members
+ if (is_external && member_byte_offset == UINT32_MAX) {
+ Type *var_type = die.ResolveTypeUID(encoding_form.Reference());
+
+ if (var_type) {
+ if (accessibility == eAccessNone)
+ accessibility = eAccessPublic;
+ ClangASTContext::AddVariableToRecordType(
+ class_clang_type, name, var_type->GetLayoutCompilerType(),
+ accessibility);
+ }
+ return;
+ }
+
+ if (!is_artificial) {
+ Type *member_type = die.ResolveTypeUID(encoding_form.Reference());
+
+ clang::FieldDecl *field_decl = nullptr;
+ if (tag == DW_TAG_member) {
+ if (member_type) {
+ if (accessibility == eAccessNone)
+ accessibility = default_accessibility;
+ member_accessibilities.push_back(accessibility);
+
+ uint64_t field_bit_offset =
+ (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8));
+ if (bit_size > 0) {
+
+ BitfieldInfo this_field_info;
+ this_field_info.bit_offset = field_bit_offset;
+ this_field_info.bit_size = bit_size;
+
+ /////////////////////////////////////////////////////////////
+ // How to locate a field given the DWARF debug information
+ //
+ // AT_byte_size indicates the size of the word in which the bit
+ // offset must be interpreted.
+ //
+ // AT_data_member_location indicates the byte offset of the
+ // word from the base address of the structure.
+ //
+ // AT_bit_offset indicates how many bits into the word
+ // (according to the host endianness) the low-order bit of the
+ // field starts. AT_bit_offset can be negative.
+ //
+ // AT_bit_size indicates the size of the field in bits.
+ /////////////////////////////////////////////////////////////
+
+ if (data_bit_offset != UINT64_MAX) {
+ this_field_info.bit_offset = data_bit_offset;
+ } else {
+ if (!byte_size)
+ byte_size = member_type->GetByteSize();
- layout_info.field_offsets.insert(std::make_pair(
- unnamed_bitfield_decl, anon_field_info.bit_offset));
- }
- }
- last_field_info = this_field_info;
+ ObjectFile *objfile = die.GetDWARF()->GetObjectFile();
+ if (objfile->GetByteOrder() == eByteOrderLittle) {
+ this_field_info.bit_offset += byte_size.getValueOr(0) * 8;
+ this_field_info.bit_offset -= (bit_offset + bit_size);
} else {
- last_field_info.Clear();
+ this_field_info.bit_offset += bit_offset;
}
+ }
- CompilerType member_clang_type =
- member_type->GetLayoutCompilerType();
- if (!member_clang_type.IsCompleteType())
- member_clang_type.GetCompleteType();
+ if ((this_field_info.bit_offset >= parent_bit_size) ||
+ !last_field_info.NextBitfieldOffsetIsValid(
+ this_field_info.bit_offset)) {
+ ObjectFile *objfile = die.GetDWARF()->GetObjectFile();
+ objfile->GetModule()->ReportWarning(
+ "0x%8.8" PRIx64 ": %s bitfield named \"%s\" has invalid "
+ "bit offset (0x%8.8" PRIx64
+ ") member will be ignored. Please file a bug against the "
+ "compiler and include the preprocessed output for %s\n",
+ die.GetID(), DW_TAG_value_to_name(tag), name,
+ this_field_info.bit_offset, GetUnitName(parent_die).c_str());
+ this_field_info.Clear();
+ return;
+ }
+ // Update the field bit offset we will report for layout
+ field_bit_offset = this_field_info.bit_offset;
+
+ // If the member to be emitted did not start on a character
+ // boundary and there is empty space between the last field and
+ // this one, then we need to emit an anonymous member filling
+ // up the space up to its start. There are three cases here:
+ //
+ // 1 If the previous member ended on a character boundary, then
+ // we can emit an
+ // anonymous member starting at the most recent character
+ // boundary.
+ //
+ // 2 If the previous member did not end on a character boundary
+ // and the distance
+ // from the end of the previous member to the current member
+ // is less than a
+ // word width, then we can emit an anonymous member starting
+ // right after the
+ // previous member and right before this member.
+ //
+ // 3 If the previous member did not end on a character boundary
+ // and the distance
+ // from the end of the previous member to the current member
+ // is greater than
+ // or equal a word width, then we act as in Case 1.
+
+ const uint64_t character_width = 8;
+ const uint64_t word_width = 32;
+
+ // Objective-C has invalid DW_AT_bit_offset values in older
+ // versions of clang, so we have to be careful and only insert
+ // unnamed bitfields if we have a new enough clang.
+ bool detect_unnamed_bitfields = true;
+
+ if (class_language == eLanguageTypeObjC ||
+ class_language == eLanguageTypeObjC_plus_plus)
+ detect_unnamed_bitfields =
+ die.GetCU()->Supports_unnamed_objc_bitfields();
+
+ if (detect_unnamed_bitfields) {
+ BitfieldInfo anon_field_info;
+
+ if ((this_field_info.bit_offset % character_width) !=
+ 0) // not char aligned
{
- // Older versions of clang emit array[0] and array[1] in the
- // same way (<rdar://problem/12566646>). If the current field
- // is at the end of the structure, then there is definitely no
- // room for extra elements and we override the type to
- // array[0].
-
- CompilerType member_array_element_type;
- uint64_t member_array_size;
- bool member_array_is_incomplete;
-
- if (member_clang_type.IsArrayType(
- &member_array_element_type, &member_array_size,
- &member_array_is_incomplete) &&
- !member_array_is_incomplete) {
- uint64_t parent_byte_size =
- parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size,
- UINT64_MAX);
-
- if (member_byte_offset >= parent_byte_size) {
- if (member_array_size != 1 &&
- (member_array_size != 0 ||
- member_byte_offset > parent_byte_size)) {
- module_sp->ReportError(
- "0x%8.8" PRIx64
- ": DW_TAG_member '%s' refers to type 0x%8.8x"
- " which extends beyond the bounds of 0x%8.8" PRIx64,
- die.GetID(), name,
- encoding_form.Reference().GetOffset(),
- parent_die.GetID());
- }
+ uint64_t last_field_end = 0;
+
+ if (last_field_info.IsValid())
+ last_field_end =
+ last_field_info.bit_offset + last_field_info.bit_size;
- member_clang_type = m_ast.CreateArrayType(
- member_array_element_type, 0, false);
+ if (this_field_info.bit_offset != last_field_end) {
+ if (((last_field_end % character_width) == 0) || // case 1
+ (this_field_info.bit_offset - last_field_end >=
+ word_width)) // case 3
+ {
+ anon_field_info.bit_size =
+ this_field_info.bit_offset % character_width;
+ anon_field_info.bit_offset =
+ this_field_info.bit_offset - anon_field_info.bit_size;
+ } else // case 2
+ {
+ anon_field_info.bit_size =
+ this_field_info.bit_offset - last_field_end;
+ anon_field_info.bit_offset = last_field_end;
}
}
}
- if (ClangASTContext::IsCXXClassType(member_clang_type) &&
- !member_clang_type.GetCompleteType()) {
- if (die.GetCU()->GetProducer() == eProducerClang)
- module_sp->ReportError(
- "DWARF DIE at 0x%8.8x (class %s) has a member variable "
- "0x%8.8x (%s) whose type is a forward declaration, not a "
- "complete definition.\nTry compiling the source file "
- "with -fstandalone-debug",
- parent_die.GetOffset(), parent_die.GetName(),
- die.GetOffset(), name);
- else
- module_sp->ReportError(
- "DWARF DIE at 0x%8.8x (class %s) has a member variable "
- "0x%8.8x (%s) whose type is a forward declaration, not a "
- "complete definition.\nPlease file a bug against the "
- "compiler and include the preprocessed output for %s",
- parent_die.GetOffset(), parent_die.GetName(),
- die.GetOffset(), name, GetUnitName(parent_die).c_str());
- // We have no choice other than to pretend that the member
- // class is complete. If we don't do this, clang will crash
- // when trying to layout the class. Since we provide layout
- // assistance, all ivars in this class and other classes will
- // be fine, this is the best we can do short of crashing.
- if (ClangASTContext::StartTagDeclarationDefinition(
- member_clang_type)) {
- ClangASTContext::CompleteTagDeclarationDefinition(
- member_clang_type);
- } else {
- module_sp->ReportError(
- "DWARF DIE at 0x%8.8x (class %s) has a member variable "
- "0x%8.8x (%s) whose type claims to be a C++ class but we "
- "were not able to start its definition.\nPlease file a "
- "bug and attach the file at the start of this error "
- "message",
- parent_die.GetOffset(), parent_die.GetName(),
- die.GetOffset(), name);
- }
+ if (anon_field_info.IsValid()) {
+ clang::FieldDecl *unnamed_bitfield_decl =
+ ClangASTContext::AddFieldToRecordType(
+ class_clang_type, llvm::StringRef(),
+ m_ast.GetBuiltinTypeForEncodingAndBitSize(eEncodingSint,
+ word_width),
+ accessibility, anon_field_info.bit_size);
+
+ layout_info.field_offsets.insert(std::make_pair(
+ unnamed_bitfield_decl, anon_field_info.bit_offset));
}
+ }
+ last_field_info = this_field_info;
+ } else {
+ last_field_info.Clear();
+ }
- field_decl = ClangASTContext::AddFieldToRecordType(
- class_clang_type, name, member_clang_type, accessibility,
- bit_size);
+ CompilerType member_clang_type = member_type->GetLayoutCompilerType();
+ if (!member_clang_type.IsCompleteType())
+ member_clang_type.GetCompleteType();
+
+ {
+ // Older versions of clang emit array[0] and array[1] in the
+ // same way (<rdar://problem/12566646>). If the current field
+ // is at the end of the structure, then there is definitely no
+ // room for extra elements and we override the type to
+ // array[0].
+
+ CompilerType member_array_element_type;
+ uint64_t member_array_size;
+ bool member_array_is_incomplete;
+
+ if (member_clang_type.IsArrayType(&member_array_element_type,
+ &member_array_size,
+ &member_array_is_incomplete) &&
+ !member_array_is_incomplete) {
+ uint64_t parent_byte_size =
+ parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size,
+ UINT64_MAX);
+
+ if (member_byte_offset >= parent_byte_size) {
+ if (member_array_size != 1 &&
+ (member_array_size != 0 ||
+ member_byte_offset > parent_byte_size)) {
+ module_sp->ReportError(
+ "0x%8.8" PRIx64
+ ": DW_TAG_member '%s' refers to type 0x%8.8x"
+ " which extends beyond the bounds of 0x%8.8" PRIx64,
+ die.GetID(), name, encoding_form.Reference().GetOffset(),
+ parent_die.GetID());
+ }
- m_ast.SetMetadataAsUserID(field_decl, die.GetID());
+ member_clang_type =
+ m_ast.CreateArrayType(member_array_element_type, 0, false);
+ }
+ }
+ }
- layout_info.field_offsets.insert(
- std::make_pair(field_decl, field_bit_offset));
+ if (ClangASTContext::IsCXXClassType(member_clang_type) &&
+ !member_clang_type.GetCompleteType()) {
+ if (die.GetCU()->GetProducer() == eProducerClang)
+ module_sp->ReportError(
+ "DWARF DIE at 0x%8.8x (class %s) has a member variable "
+ "0x%8.8x (%s) whose type is a forward declaration, not a "
+ "complete definition.\nTry compiling the source file "
+ "with -fstandalone-debug",
+ parent_die.GetOffset(), parent_die.GetName(), die.GetOffset(),
+ name);
+ else
+ module_sp->ReportError(
+ "DWARF DIE at 0x%8.8x (class %s) has a member variable "
+ "0x%8.8x (%s) whose type is a forward declaration, not a "
+ "complete definition.\nPlease file a bug against the "
+ "compiler and include the preprocessed output for %s",
+ parent_die.GetOffset(), parent_die.GetName(), die.GetOffset(),
+ name, GetUnitName(parent_die).c_str());
+ // We have no choice other than to pretend that the member
+ // class is complete. If we don't do this, clang will crash
+ // when trying to layout the class. Since we provide layout
+ // assistance, all ivars in this class and other classes will
+ // be fine, this is the best we can do short of crashing.
+ if (ClangASTContext::StartTagDeclarationDefinition(
+ member_clang_type)) {
+ ClangASTContext::CompleteTagDeclarationDefinition(
+ member_clang_type);
} else {
- if (name)
- module_sp->ReportError(
- "0x%8.8" PRIx64
- ": DW_TAG_member '%s' refers to type 0x%8.8x"
- " which was unable to be parsed",
- die.GetID(), name, encoding_form.Reference().GetOffset());
- else
- module_sp->ReportError(
- "0x%8.8" PRIx64 ": DW_TAG_member refers to type 0x%8.8x"
- " which was unable to be parsed",
- die.GetID(), encoding_form.Reference().GetOffset());
+ module_sp->ReportError(
+ "DWARF DIE at 0x%8.8x (class %s) has a member variable "
+ "0x%8.8x (%s) whose type claims to be a C++ class but we "
+ "were not able to start its definition.\nPlease file a "
+ "bug and attach the file at the start of this error "
+ "message",
+ parent_die.GetOffset(), parent_die.GetName(), die.GetOffset(),
+ name);
}
}
- if (prop_name != nullptr && member_type) {
- clang::ObjCIvarDecl *ivar_decl = nullptr;
+ field_decl = ClangASTContext::AddFieldToRecordType(
+ class_clang_type, name, member_clang_type, accessibility,
+ bit_size);
- if (field_decl) {
- ivar_decl = clang::dyn_cast<clang::ObjCIvarDecl>(field_decl);
- assert(ivar_decl != nullptr);
- }
+ m_ast.SetMetadataAsUserID(field_decl, die.GetID());
- ClangASTMetadata metadata;
- metadata.SetUserID(die.GetID());
- delayed_properties.push_back(DelayedAddObjCClassProperty(
- class_clang_type, prop_name,
- member_type->GetLayoutCompilerType(), ivar_decl,
- prop_setter_name, prop_getter_name, prop_attributes,
- &metadata));
+ layout_info.field_offsets.insert(
+ std::make_pair(field_decl, field_bit_offset));
+ } else {
+ if (name)
+ module_sp->ReportError(
+ "0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8x"
+ " which was unable to be parsed",
+ die.GetID(), name, encoding_form.Reference().GetOffset());
+ else
+ module_sp->ReportError(
+ "0x%8.8" PRIx64 ": DW_TAG_member refers to type 0x%8.8x"
+ " which was unable to be parsed",
+ die.GetID(), encoding_form.Reference().GetOffset());
+ }
+ }
- if (ivar_decl)
- m_ast.SetMetadataAsUserID(ivar_decl, die.GetID());
- }
+ if (prop_name != nullptr && member_type) {
+ clang::ObjCIvarDecl *ivar_decl = nullptr;
+
+ if (field_decl) {
+ ivar_decl = clang::dyn_cast<clang::ObjCIvarDecl>(field_decl);
+ assert(ivar_decl != nullptr);
}
+
+ ClangASTMetadata metadata;
+ metadata.SetUserID(die.GetID());
+ delayed_properties.push_back(DelayedAddObjCClassProperty(
+ class_clang_type, prop_name, member_type->GetLayoutCompilerType(),
+ ivar_decl, prop_setter_name, prop_getter_name, prop_attributes,
+ &metadata));
+
+ if (ivar_decl)
+ m_ast.SetMetadataAsUserID(ivar_decl, die.GetID());
}
- ++member_idx;
- } break;
+ }
+ }
+}
+
+bool DWARFASTParserClang::ParseChildMembers(
+ const DWARFDIE &parent_die, CompilerType &class_clang_type,
+ const LanguageType class_language,
+ std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,
+ std::vector<int> &member_accessibilities,
+ std::vector<DWARFDIE> &member_function_dies,
+ DelayedPropertyList &delayed_properties, AccessType &default_accessibility,
+ bool &is_a_class, ClangASTImporter::LayoutInfo &layout_info) {
+ if (!parent_die)
+ return false;
+
+ BitfieldInfo last_field_info;
+
+ ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
+ ClangASTContext *ast =
+ llvm::dyn_cast_or_null<ClangASTContext>(class_clang_type.GetTypeSystem());
+ if (ast == nullptr)
+ return false;
+
+ for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
+ die = die.GetSibling()) {
+ dw_tag_t tag = die.Tag();
+
+ switch (tag) {
+ case DW_TAG_member:
+ case DW_TAG_APPLE_property:
+ ParseSingleMember(die, parent_die, class_clang_type, class_language,
+ member_accessibilities, default_accessibility,
+ delayed_properties, layout_info, last_field_info);
+ break;
case DW_TAG_subprogram:
// Let the type parsing code handle this one for us.
@@ -3552,18 +3522,20 @@ DWARFASTParserClang::ResolveNamespaceDIE(const DWARFDIE &die) {
SymbolFileDWARF *dwarf = die.GetDWARF();
if (namespace_name) {
dwarf->GetObjectFile()->GetModule()->LogMessage(
- log, "ASTContext => %p: 0x%8.8" PRIx64
- ": DW_TAG_namespace with DW_AT_name(\"%s\") => "
- "clang::NamespaceDecl *%p (original = %p)",
- static_cast<void *>(m_ast.getASTContext()), die.GetID(),
+ log,
+ "ASTContext => %p: 0x%8.8" PRIx64
+ ": DW_TAG_namespace with DW_AT_name(\"%s\") => "
+ "clang::NamespaceDecl *%p (original = %p)",
+ static_cast<void *>(&m_ast.getASTContext()), die.GetID(),
namespace_name, static_cast<void *>(namespace_decl),
static_cast<void *>(namespace_decl->getOriginalNamespace()));
} else {
dwarf->GetObjectFile()->GetModule()->LogMessage(
- log, "ASTContext => %p: 0x%8.8" PRIx64
- ": DW_TAG_namespace (anonymous) => clang::NamespaceDecl *%p "
- "(original = %p)",
- static_cast<void *>(m_ast.getASTContext()), die.GetID(),
+ log,
+ "ASTContext => %p: 0x%8.8" PRIx64
+ ": DW_TAG_namespace (anonymous) => clang::NamespaceDecl *%p "
+ "(original = %p)",
+ static_cast<void *>(&m_ast.getASTContext()), die.GetID(),
static_cast<void *>(namespace_decl),
static_cast<void *>(namespace_decl->getOriginalNamespace()));
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
index 106f9254a449..4ad757247c3e 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -128,7 +128,8 @@ protected:
const DWARFDIE &parent_die);
/// Parse a structure, class, or union type DIE.
- lldb::TypeSP ParseStructureLikeDIE(const DWARFDIE &die,
+ lldb::TypeSP ParseStructureLikeDIE(const lldb_private::SymbolContext &sc,
+ const DWARFDIE &die,
ParsedDWARFTypeAttributes &attrs);
lldb_private::Type *GetTypeForDIE(const DWARFDIE &die);
@@ -159,11 +160,73 @@ protected:
UpdateSymbolContextScopeForType(const lldb_private::SymbolContext &sc,
const DWARFDIE &die, lldb::TypeSP type_sp);
- lldb::TypeSP ParseTypeFromDWO(const DWARFDIE &die, lldb_private::Log *log);
+ /// Follow Clang Module Skeleton CU references to find a type definition.
+ lldb::TypeSP ParseTypeFromClangModule(const lldb_private::SymbolContext &sc,
+ const DWARFDIE &die,
+ lldb_private::Log *log);
// Return true if this type is a declaration to a type in an external
// module.
lldb::ModuleSP GetModuleForType(const DWARFDIE &die);
+
+private:
+ struct BitfieldInfo {
+ uint64_t bit_size;
+ uint64_t bit_offset;
+
+ BitfieldInfo()
+ : bit_size(LLDB_INVALID_ADDRESS), bit_offset(LLDB_INVALID_ADDRESS) {}
+
+ void Clear() {
+ bit_size = LLDB_INVALID_ADDRESS;
+ bit_offset = LLDB_INVALID_ADDRESS;
+ }
+
+ bool IsValid() const {
+ return (bit_size != LLDB_INVALID_ADDRESS) &&
+ (bit_offset != LLDB_INVALID_ADDRESS);
+ }
+
+ bool NextBitfieldOffsetIsValid(const uint64_t next_bit_offset) const {
+ if (IsValid()) {
+ // This bitfield info is valid, so any subsequent bitfields must not
+ // overlap and must be at a higher bit offset than any previous bitfield
+ // + size.
+ return (bit_size + bit_offset) <= next_bit_offset;
+ } else {
+ // If the this BitfieldInfo is not valid, then any offset isOK
+ return true;
+ }
+ }
+ };
+
+ void
+ ParseSingleMember(const DWARFDIE &die, const DWARFDIE &parent_die,
+ lldb_private::CompilerType &class_clang_type,
+ const lldb::LanguageType class_language,
+ std::vector<int> &member_accessibilities,
+ lldb::AccessType &default_accessibility,
+ DelayedPropertyList &delayed_properties,
+ lldb_private::ClangASTImporter::LayoutInfo &layout_info,
+ BitfieldInfo &last_field_info);
+
+ bool CompleteRecordType(const DWARFDIE &die, lldb_private::Type *type,
+ lldb_private::CompilerType &clang_type);
+ bool CompleteEnumType(const DWARFDIE &die, lldb_private::Type *type,
+ lldb_private::CompilerType &clang_type);
+
+ lldb::TypeSP ParseTypeModifier(const lldb_private::SymbolContext &sc,
+ const DWARFDIE &die,
+ ParsedDWARFTypeAttributes &attrs);
+ lldb::TypeSP ParseEnum(const lldb_private::SymbolContext &sc,
+ const DWARFDIE &die, ParsedDWARFTypeAttributes &attrs);
+ lldb::TypeSP ParseSubroutine(const DWARFDIE &die,
+ ParsedDWARFTypeAttributes &attrs);
+ // FIXME: attrs should be passed as a const reference.
+ lldb::TypeSP ParseArrayType(const DWARFDIE &die,
+ ParsedDWARFTypeAttributes &attrs);
+ lldb::TypeSP ParsePointerToMemberType(const DWARFDIE &die,
+ const ParsedDWARFTypeAttributes &attrs);
};
/// Parsed form of all attributes that are relevant for type reconstruction.
@@ -181,6 +244,8 @@ struct ParsedDWARFTypeAttributes {
bool is_scoped_enum = false;
bool is_vector = false;
bool is_virtual = false;
+ bool is_objc_direct_call = false;
+ bool exports_symbols = false;
clang::StorageClass storage = clang::SC_None;
const char *mangled_name = nullptr;
lldb_private::ConstString name;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
index 75647dbb082f..454637ef981c 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
@@ -24,8 +24,8 @@ private:
DWARFCompileUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
const DWARFUnitHeader &header,
const DWARFAbbreviationDeclarationSet &abbrevs,
- DIERef::Section section)
- : DWARFUnit(dwarf, uid, header, abbrevs, section) {}
+ DIERef::Section section, bool is_dwo)
+ : DWARFUnit(dwarf, uid, header, abbrevs, section, is_dwo) {}
DISALLOW_COPY_AND_ASSIGN(DWARFCompileUnit);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp
index eb307ce1cce1..5052b825fea6 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.cpp
@@ -70,6 +70,17 @@ const DWARFDataExtractor &DWARFContext::getOrLoadLineStrData() {
m_data_debug_line_str);
}
+const DWARFDataExtractor &DWARFContext::getOrLoadLocData() {
+ return LoadOrGetSection(eSectionTypeDWARFDebugLoc,
+ eSectionTypeDWARFDebugLocDwo, m_data_debug_loc);
+}
+
+const DWARFDataExtractor &DWARFContext::getOrLoadLocListsData() {
+ return LoadOrGetSection(eSectionTypeDWARFDebugLocLists,
+ eSectionTypeDWARFDebugLocListsDwo,
+ m_data_debug_loclists);
+}
+
const DWARFDataExtractor &DWARFContext::getOrLoadMacroData() {
return LoadOrGetSection(eSectionTypeDWARFDebugMacro, llvm::None,
m_data_debug_macro);
@@ -81,7 +92,8 @@ const DWARFDataExtractor &DWARFContext::getOrLoadRangesData() {
}
const DWARFDataExtractor &DWARFContext::getOrLoadRngListsData() {
- return LoadOrGetSection(eSectionTypeDWARFDebugRngLists, llvm::None,
+ return LoadOrGetSection(eSectionTypeDWARFDebugRngLists,
+ eSectionTypeDWARFDebugRngListsDwo,
m_data_debug_rnglists);
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h
index add042384039..8691001b1b76 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFContext.h
@@ -34,6 +34,8 @@ private:
SectionData m_data_debug_info;
SectionData m_data_debug_line;
SectionData m_data_debug_line_str;
+ SectionData m_data_debug_loc;
+ SectionData m_data_debug_loclists;
SectionData m_data_debug_macro;
SectionData m_data_debug_ranges;
SectionData m_data_debug_rnglists;
@@ -41,8 +43,6 @@ private:
SectionData m_data_debug_str_offsets;
SectionData m_data_debug_types;
- bool isDwo() { return m_dwo_section_list != nullptr; }
-
const DWARFDataExtractor &
LoadOrGetSection(lldb::SectionType main_section_type,
llvm::Optional<lldb::SectionType> dwo_section_type,
@@ -60,6 +60,8 @@ public:
const DWARFDataExtractor &getOrLoadDebugInfoData();
const DWARFDataExtractor &getOrLoadLineData();
const DWARFDataExtractor &getOrLoadLineStrData();
+ const DWARFDataExtractor &getOrLoadLocData();
+ const DWARFDataExtractor &getOrLoadLocListsData();
const DWARFDataExtractor &getOrLoadMacroData();
const DWARFDataExtractor &getOrLoadRangesData();
const DWARFDataExtractor &getOrLoadRngListsData();
@@ -67,6 +69,8 @@ public:
const DWARFDataExtractor &getOrLoadStrOffsetsData();
const DWARFDataExtractor &getOrLoadDebugTypesData();
+ bool isDwo() { return m_dwo_section_list != nullptr; }
+
llvm::DWARFContext &GetAsLLVM();
};
} // namespace lldb_private
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
index 5ee0687995a1..c5411a17f274 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -406,39 +406,6 @@ bool DWARFDIE::IsMethod() const {
return false;
}
-DWARFDIE
-DWARFDIE::GetContainingDWOModuleDIE() const {
- if (IsValid()) {
- DWARFDIE top_module_die;
- // Now make sure this DIE is scoped in a DW_TAG_module tag and return true
- // if so
- for (DWARFDIE parent = GetParent(); parent.IsValid();
- parent = parent.GetParent()) {
- const dw_tag_t tag = parent.Tag();
- if (tag == DW_TAG_module)
- top_module_die = parent;
- else if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
- break;
- }
-
- return top_module_die;
- }
- return DWARFDIE();
-}
-
-lldb::ModuleSP DWARFDIE::GetContainingDWOModule() const {
- if (IsValid()) {
- DWARFDIE dwo_module_die = GetContainingDWOModuleDIE();
-
- if (dwo_module_die) {
- const char *module_name = dwo_module_die.GetName();
- if (module_name)
- return GetDWARF()->GetDWOModule(lldb_private::ConstString(module_name));
- }
- }
- return lldb::ModuleSP();
-}
-
bool DWARFDIE::GetDIENamesAndRanges(
const char *&name, const char *&mangled, DWARFRangeList &ranges,
int &decl_file, int &decl_line, int &decl_column, int &call_file,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
index a779c589611a..87d52eee9dd9 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
@@ -22,10 +22,6 @@ public:
bool IsMethod() const;
// Accessors
- lldb::ModuleSP GetContainingDWOModule() const;
-
- DWARFDIE
- GetContainingDWOModuleDIE() const;
// Accessing information about a DIE
const char *GetMangledName() const;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
index d1b066ffe80c..056cf33a202f 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
@@ -16,7 +16,6 @@
#include "DWARFTypeUnit.h"
#include "DWARFUnit.h"
#include "SymbolFileDWARF.h"
-#include "lldb/Core/STLUtils.h"
#include "lldb/lldb-private.h"
#include "llvm/Support/Error.h"
@@ -24,11 +23,6 @@ namespace lldb_private {
class DWARFContext;
}
-typedef std::multimap<const char *, dw_offset_t, CStringCompareFunctionObject>
- CStringToDIEMap;
-typedef CStringToDIEMap::iterator CStringToDIEMapIter;
-typedef CStringToDIEMap::const_iterator CStringToDIEMapConstIter;
-
class DWARFDebugInfo {
public:
typedef dw_offset_t (*Callback)(SymbolFileDWARF *dwarf2Data,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
index 8c0fbeb4b717..320500fe608d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -156,6 +156,7 @@ bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data,
// signed or unsigned LEB 128 values
case DW_FORM_addrx:
+ case DW_FORM_loclistx:
case DW_FORM_rnglistx:
case DW_FORM_sdata:
case DW_FORM_udata:
@@ -200,7 +201,7 @@ bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data,
return false;
}
-static DWARFRangeList GetRangesOrReportError(const DWARFUnit &unit,
+static DWARFRangeList GetRangesOrReportError(DWARFUnit &unit,
const DWARFDebugInfoEntry &die,
const DWARFFormValue &value) {
llvm::Expected<DWARFRangeList> expected_ranges =
@@ -223,7 +224,7 @@ static DWARFRangeList GetRangesOrReportError(const DWARFUnit &unit,
// Gets the valid address ranges for a given DIE by looking for a
// DW_AT_low_pc/DW_AT_high_pc pair, DW_AT_entry_pc, or DW_AT_ranges attributes.
bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
- const DWARFUnit *cu, const char *&name, const char *&mangled,
+ DWARFUnit *cu, const char *&name, const char *&mangled,
DWARFRangeList &ranges, int &decl_file, int &decl_line, int &decl_column,
int &call_file, int &call_line, int &call_column,
DWARFExpression *frame_base) const {
@@ -343,15 +344,15 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
*frame_base = DWARFExpression(
module, DataExtractor(data, block_offset, block_length), cu);
} else {
- DataExtractor data = dwarf.DebugLocData();
+ DataExtractor data = cu->GetLocationData();
const dw_offset_t offset = form_value.Unsigned();
if (data.ValidOffset(offset)) {
data = DataExtractor(data, offset, data.GetByteSize() - offset);
*frame_base = DWARFExpression(module, data, cu);
if (lo_pc != LLDB_INVALID_ADDRESS) {
assert(lo_pc >= cu->GetBaseAddress());
- frame_base->SetLocationListSlide(lo_pc -
- cu->GetBaseAddress());
+ frame_base->SetLocationListAddresses(cu->GetBaseAddress(),
+ lo_pc);
} else {
set_frame_base_loclist_addr = true;
}
@@ -379,7 +380,7 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
if (set_frame_base_loclist_addr) {
dw_addr_t lowest_range_pc = ranges.GetMinRangeBase(0);
assert(lowest_range_pc >= cu->GetBaseAddress());
- frame_base->SetLocationListSlide(lowest_range_pc - cu->GetBaseAddress());
+ frame_base->SetLocationListAddresses(cu->GetBaseAddress(), lowest_range_pc);
}
if (ranges.IsEmpty() || name == nullptr || mangled == nullptr) {
@@ -477,8 +478,6 @@ void DWARFDebugInfoEntry::DumpAttribute(
s.PutCString("( ");
- SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF();
-
// Check to see if we have any special attribute formatters
switch (attr) {
case DW_AT_stmt_list:
@@ -508,7 +507,7 @@ void DWARFDebugInfoEntry::DumpAttribute(
// We have a location list offset as the value that is the offset into
// the .debug_loc section that describes the value over it's lifetime
uint64_t debug_loc_offset = form_value.Unsigned();
- DWARFExpression::PrintDWARFLocationList(s, cu, dwarf.DebugLocData(),
+ DWARFExpression::PrintDWARFLocationList(s, cu, cu->GetLocationData(),
debug_loc_offset);
}
} break;
@@ -646,25 +645,7 @@ dw_offset_t DWARFDebugInfoEntry::GetAttributeValue(
}
}
}
-
- // If we're a unit DIE, also check the attributes of the dwo unit (if any).
- if (GetParent())
- return 0;
- SymbolFileDWARFDwo *dwo_symbol_file = cu->GetDwoSymbolFile();
- if (!dwo_symbol_file)
- return 0;
-
- DWARFCompileUnit *dwo_cu = dwo_symbol_file->GetCompileUnit();
- if (!dwo_cu)
- return 0;
-
- DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly();
- if (!dwo_cu_die.IsValid())
- return 0;
-
- return dwo_cu_die.GetDIE()->GetAttributeValue(
- dwo_cu, attr, form_value, end_attr_offset_ptr,
- check_specification_or_abstract_origin);
+ return 0;
}
// GetAttributeValueAsString
@@ -766,7 +747,7 @@ bool DWARFDebugInfoEntry::GetAttributeAddressRange(
}
size_t DWARFDebugInfoEntry::GetAttributeAddressRanges(
- const DWARFUnit *cu, DWARFRangeList &ranges, bool check_hi_lo_pc,
+ DWARFUnit *cu, DWARFRangeList &ranges, bool check_hi_lo_pc,
bool check_specification_or_abstract_origin) const {
ranges.Clear();
@@ -1012,8 +993,7 @@ DWARFDebugInfoEntry::GetQualifiedName(DWARFUnit *cu,
return storage.c_str();
}
-bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address,
- const DWARFUnit *cu,
+bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, DWARFUnit *cu,
DWARFDebugInfoEntry **function_die,
DWARFDebugInfoEntry **block_die) {
bool found_address = false;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
index 25c885608d85..f35af6e7d498 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
@@ -23,6 +23,10 @@ class DWARFDeclContext;
#define DIE_SIBLING_IDX_BITSIZE 31
+/// DWARFDebugInfoEntry objects assume that they are living in one big
+/// vector and do pointer arithmetic on their this pointers. Don't
+/// pass them by value. Due to the way they are constructed in a
+/// std::vector, we cannot delete the copy constructor.
class DWARFDebugInfoEntry {
public:
typedef std::vector<DWARFDebugInfoEntry> collection;
@@ -46,7 +50,7 @@ public:
bool Extract(const lldb_private::DWARFDataExtractor &data,
const DWARFUnit *cu, lldb::offset_t *offset_ptr);
- bool LookupAddress(const dw_addr_t address, const DWARFUnit *cu,
+ bool LookupAddress(const dw_addr_t address, DWARFUnit *cu,
DWARFDebugInfoEntry **function_die,
DWARFDebugInfoEntry **block_die);
@@ -87,7 +91,7 @@ public:
bool check_specification_or_abstract_origin = false) const;
size_t GetAttributeAddressRanges(
- const DWARFUnit *cu, DWARFRangeList &ranges, bool check_hi_lo_pc,
+ DWARFUnit *cu, DWARFRangeList &ranges, bool check_hi_lo_pc,
bool check_specification_or_abstract_origin = false) const;
const char *GetName(const DWARFUnit *cu) const;
@@ -112,7 +116,7 @@ public:
dw_attr_t attr, DWARFFormValue &form_value);
bool GetDIENamesAndRanges(
- const DWARFUnit *cu, const char *&name, const char *&mangled,
+ DWARFUnit *cu, const char *&name, const char *&mangled,
DWARFRangeList &rangeList, int &decl_file, int &decl_line,
int &decl_column, int &call_file, int &call_line, int &call_column,
lldb_private::DWARFExpression *frame_base = nullptr) const;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
index 0b08fa09f906..6c074002cb20 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
@@ -95,13 +95,15 @@ void DWARFDebugRanges::Dump(Stream &s,
} else if (begin == LLDB_INVALID_ADDRESS) {
// A base address selection entry
base_addr = end;
- s.Address(base_addr, sizeof(dw_addr_t), " Base address = ");
+ DumpAddress(s.AsRawOstream(), base_addr, sizeof(dw_addr_t),
+ " Base address = ");
} else {
// Convert from offset to an address
dw_addr_t begin_addr = begin + base_addr;
dw_addr_t end_addr = end + base_addr;
- s.AddressRange(begin_addr, end_addr, sizeof(dw_addr_t), nullptr);
+ DumpAddressRange(s.AsRawOstream(), begin_addr, end_addr,
+ sizeof(dw_addr_t), nullptr);
}
}
}
@@ -122,164 +124,3 @@ bool DWARFDebugRanges::FindRanges(const DWARFUnit *cu,
}
return false;
}
-
-bool DWARFDebugRngLists::ExtractRangeList(
- const DWARFDataExtractor &data, uint8_t addrSize,
- lldb::offset_t *offset_ptr, std::vector<RngListEntry> &rangeList) {
- rangeList.clear();
-
- bool error = false;
- while (!error) {
- switch (data.GetU8(offset_ptr)) {
- case DW_RLE_end_of_list:
- return true;
-
- case DW_RLE_start_length: {
- dw_addr_t begin = data.GetMaxU64(offset_ptr, addrSize);
- dw_addr_t len = data.GetULEB128(offset_ptr);
- rangeList.push_back({DW_RLE_start_length, begin, len});
- break;
- }
-
- case DW_RLE_start_end: {
- dw_addr_t begin = data.GetMaxU64(offset_ptr, addrSize);
- dw_addr_t end = data.GetMaxU64(offset_ptr, addrSize);
- rangeList.push_back({DW_RLE_start_end, begin, end});
- break;
- }
-
- case DW_RLE_base_address: {
- dw_addr_t base = data.GetMaxU64(offset_ptr, addrSize);
- rangeList.push_back({DW_RLE_base_address, base, 0});
- break;
- }
-
- case DW_RLE_offset_pair: {
- dw_addr_t begin = data.GetULEB128(offset_ptr);
- dw_addr_t end = data.GetULEB128(offset_ptr);
- rangeList.push_back({DW_RLE_offset_pair, begin, end});
- break;
- }
-
- case DW_RLE_base_addressx: {
- dw_addr_t base = data.GetULEB128(offset_ptr);
- rangeList.push_back({DW_RLE_base_addressx, base, 0});
- break;
- }
-
- case DW_RLE_startx_endx: {
- dw_addr_t start = data.GetULEB128(offset_ptr);
- dw_addr_t end = data.GetULEB128(offset_ptr);
- rangeList.push_back({DW_RLE_startx_endx, start, end});
- break;
- }
-
- case DW_RLE_startx_length: {
- dw_addr_t start = data.GetULEB128(offset_ptr);
- dw_addr_t length = data.GetULEB128(offset_ptr);
- rangeList.push_back({DW_RLE_startx_length, start, length});
- break;
- }
-
- default:
- lldbassert(0 && "unknown range list entry encoding");
- error = true;
- }
- }
-
- return false;
-}
-
-static uint64_t ReadAddressFromDebugAddrSection(const DWARFUnit *cu,
- uint32_t index) {
- uint32_t index_size = cu->GetAddressByteSize();
- dw_offset_t addr_base = cu->GetAddrBase();
- lldb::offset_t offset = addr_base + index * index_size;
- return cu->GetSymbolFileDWARF()
- .GetDWARFContext()
- .getOrLoadAddrData()
- .GetMaxU64(&offset, index_size);
-}
-
-bool DWARFDebugRngLists::FindRanges(const DWARFUnit *cu,
- dw_offset_t debug_ranges_offset,
- DWARFRangeList &range_list) const {
- range_list.Clear();
- dw_addr_t debug_ranges_address = cu->GetRangesBase() + debug_ranges_offset;
- auto pos = m_range_map.find(debug_ranges_address);
- if (pos != m_range_map.end()) {
- dw_addr_t BaseAddr = cu->GetBaseAddress();
- for (const RngListEntry &E : pos->second) {
- switch (E.encoding) {
- case DW_RLE_start_length:
- range_list.Append(DWARFRangeList::Entry(E.value0, E.value1));
- break;
- case DW_RLE_base_address:
- BaseAddr = E.value0;
- break;
- case DW_RLE_start_end:
- range_list.Append(DWARFRangeList::Entry(E.value0, E.value1 - E.value0));
- break;
- case DW_RLE_offset_pair:
- range_list.Append(
- DWARFRangeList::Entry(BaseAddr + E.value0, E.value1 - E.value0));
- break;
- case DW_RLE_base_addressx: {
- BaseAddr = ReadAddressFromDebugAddrSection(cu, E.value0);
- break;
- }
- case DW_RLE_startx_endx: {
- dw_addr_t start = ReadAddressFromDebugAddrSection(cu, E.value0);
- dw_addr_t end = ReadAddressFromDebugAddrSection(cu, E.value1);
- range_list.Append(DWARFRangeList::Entry(start, end - start));
- break;
- }
- case DW_RLE_startx_length: {
- dw_addr_t start = ReadAddressFromDebugAddrSection(cu, E.value0);
- range_list.Append(DWARFRangeList::Entry(start, E.value1));
- break;
- }
- default:
- llvm_unreachable("unexpected encoding");
- }
- }
- return true;
- }
- return false;
-}
-
-void DWARFDebugRngLists::Extract(DWARFContext &context) {
- const DWARFDataExtractor &data = context.getOrLoadRngListsData();
- lldb::offset_t offset = 0;
-
- uint64_t length = data.GetU32(&offset);
- // FIXME: Handle DWARF64.
- lldb::offset_t end = offset + length;
-
- // Check version.
- if (data.GetU16(&offset) < 5)
- return;
-
- uint8_t addrSize = data.GetU8(&offset);
-
- // We do not support non-zero segment selector size.
- if (data.GetU8(&offset) != 0) {
- lldbassert(0 && "not implemented");
- return;
- }
-
- uint32_t offsetsAmount = data.GetU32(&offset);
- for (uint32_t i = 0; i < offsetsAmount; ++i)
- Offsets.push_back(data.GetMaxU64(&offset, 4));
-
- lldb::offset_t listOffset = offset;
- std::vector<RngListEntry> rangeList;
- while (offset < end && ExtractRangeList(data, addrSize, &offset, rangeList)) {
- m_range_map[listOffset] = rangeList;
- listOffset = offset;
- }
-}
-
-uint64_t DWARFDebugRngLists::GetOffset(size_t Index) const {
- return Offsets[Index];
-}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
index c398259056b3..1888a7760f27 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
@@ -17,22 +17,13 @@ namespace lldb_private {
class DWARFContext;
}
-class DWARFDebugRangesBase {
-public:
- virtual ~DWARFDebugRangesBase(){};
-
- virtual void Extract(lldb_private::DWARFContext &context) = 0;
- virtual bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset,
- DWARFRangeList &range_list) const = 0;
-};
-
-class DWARFDebugRanges final : public DWARFDebugRangesBase {
+class DWARFDebugRanges {
public:
DWARFDebugRanges();
- void Extract(lldb_private::DWARFContext &context) override;
+ void Extract(lldb_private::DWARFContext &context);
bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset,
- DWARFRangeList &range_list) const override;
+ DWARFRangeList &range_list) const;
static void Dump(lldb_private::Stream &s,
const lldb_private::DWARFDataExtractor &debug_ranges_data,
@@ -48,27 +39,4 @@ protected:
range_map m_range_map;
};
-// DWARF v5 .debug_rnglists section.
-class DWARFDebugRngLists final : public DWARFDebugRangesBase {
- struct RngListEntry {
- uint8_t encoding;
- uint64_t value0;
- uint64_t value1;
- };
-
-public:
- void Extract(lldb_private::DWARFContext &context) override;
- bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset,
- DWARFRangeList &range_list) const override;
- uint64_t GetOffset(size_t Index) const;
-
-protected:
- bool ExtractRangeList(const lldb_private::DWARFDataExtractor &data,
- uint8_t addrSize, lldb::offset_t *offset_ptr,
- std::vector<RngListEntry> &list);
-
- std::vector<uint64_t> Offsets;
- std::map<dw_offset_t, std::vector<RngListEntry>> m_range_map;
-};
-
#endif // SymbolFileDWARF_DWARFDebugRanges_h_
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
index 6501ac27f27d..348b33464a54 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
@@ -63,7 +63,7 @@ public:
const char *GetQualifiedName() const;
- // Same as GetQaulifiedName, but the life time of the returned string will
+ // Same as GetQualifiedName, but the life time of the returned string will
// be that of the LLDB session.
lldb_private::ConstString GetQualifiedNameAsConstString() const {
return lldb_private::ConstString(GetQualifiedName());
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
index 046ae67446af..f660cc32b3f8 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -107,6 +107,7 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
m_value.value.uval = data.GetU64(offset_ptr);
break;
case DW_FORM_addrx:
+ case DW_FORM_loclistx:
case DW_FORM_rnglistx:
case DW_FORM_strx:
case DW_FORM_udata:
@@ -305,6 +306,7 @@ bool DWARFFormValue::SkipValue(dw_form_t form,
// signed or unsigned LEB 128 values
case DW_FORM_addrx:
+ case DW_FORM_loclistx:
case DW_FORM_rnglistx:
case DW_FORM_sdata:
case DW_FORM_udata:
@@ -333,7 +335,7 @@ void DWARFFormValue::Dump(Stream &s) const {
switch (m_form) {
case DW_FORM_addr:
- s.Address(uvalue, sizeof(uint64_t));
+ DumpAddress(s.AsRawOstream(), uvalue, sizeof(uint64_t));
break;
case DW_FORM_flag:
case DW_FORM_data1:
@@ -409,10 +411,11 @@ void DWARFFormValue::Dump(Stream &s) const {
assert(m_unit); // Unit must be valid for DW_FORM_ref_addr objects or we
// will get this wrong
if (m_unit->GetVersion() <= 2)
- s.Address(uvalue, sizeof(uint64_t) * 2);
+ DumpAddress(s.AsRawOstream(), uvalue, sizeof(uint64_t) * 2);
else
- s.Address(uvalue, 4 * 2); // 4 for DWARF32, 8 for DWARF64, but we don't
- // support DWARF64 yet
+ DumpAddress(s.AsRawOstream(), uvalue,
+ 4 * 2); // 4 for DWARF32, 8 for DWARF64, but we don't
+ // support DWARF64 yet
break;
}
case DW_FORM_ref1:
@@ -599,105 +602,11 @@ bool DWARFFormValue::IsDataForm(const dw_form_t form) {
return false;
}
-int DWARFFormValue::Compare(const DWARFFormValue &a_value,
- const DWARFFormValue &b_value) {
- dw_form_t a_form = a_value.Form();
- dw_form_t b_form = b_value.Form();
- if (a_form < b_form)
- return -1;
- if (a_form > b_form)
- return 1;
- switch (a_form) {
- case DW_FORM_addr:
- case DW_FORM_addrx:
- case DW_FORM_flag:
- case DW_FORM_data1:
- case DW_FORM_data2:
- case DW_FORM_data4:
- case DW_FORM_data8:
- case DW_FORM_udata:
- case DW_FORM_ref_addr:
- case DW_FORM_sec_offset:
- case DW_FORM_flag_present:
- case DW_FORM_ref_sig8:
- case DW_FORM_GNU_addr_index: {
- uint64_t a = a_value.Unsigned();
- uint64_t b = b_value.Unsigned();
- if (a < b)
- return -1;
- if (a > b)
- return 1;
- return 0;
- }
-
- case DW_FORM_sdata: {
- int64_t a = a_value.Signed();
- int64_t b = b_value.Signed();
- if (a < b)
- return -1;
- if (a > b)
- return 1;
- return 0;
- }
-
- case DW_FORM_string:
- case DW_FORM_strp:
- case DW_FORM_GNU_str_index: {
- const char *a_string = a_value.AsCString();
- const char *b_string = b_value.AsCString();
- if (a_string == b_string)
- return 0;
- else if (a_string && b_string)
- return strcmp(a_string, b_string);
- else if (a_string == nullptr)
- return -1; // A string is NULL, and B is valid
- else
- return 1; // A string valid, and B is NULL
- }
-
- case DW_FORM_block:
- case DW_FORM_block1:
- case DW_FORM_block2:
- case DW_FORM_block4:
- case DW_FORM_exprloc: {
- uint64_t a_len = a_value.Unsigned();
- uint64_t b_len = b_value.Unsigned();
- if (a_len < b_len)
- return -1;
- if (a_len > b_len)
- return 1;
- // The block lengths are the same
- return memcmp(a_value.BlockData(), b_value.BlockData(), a_value.Unsigned());
- } break;
-
- case DW_FORM_ref1:
- case DW_FORM_ref2:
- case DW_FORM_ref4:
- case DW_FORM_ref8:
- case DW_FORM_ref_udata: {
- uint64_t a = a_value.m_value.value.uval;
- uint64_t b = b_value.m_value.value.uval;
- if (a < b)
- return -1;
- if (a > b)
- return 1;
- return 0;
- }
-
- case DW_FORM_indirect:
- llvm_unreachable(
- "This shouldn't happen after the form has been extracted...");
-
- default:
- llvm_unreachable("Unhandled DW_FORM");
- }
- return -1;
-}
-
bool DWARFFormValue::FormIsSupported(dw_form_t form) {
switch (form) {
case DW_FORM_addr:
case DW_FORM_addrx:
+ case DW_FORM_loclistx:
case DW_FORM_rnglistx:
case DW_FORM_block2:
case DW_FORM_block4:
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h
index 6ff73ecd8efa..8967509c081a 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h
@@ -28,8 +28,8 @@ private:
DWARFTypeUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
const DWARFUnitHeader &header,
const DWARFAbbreviationDeclarationSet &abbrevs,
- DIERef::Section section)
- : DWARFUnit(dwarf, uid, header, abbrevs, section) {}
+ DIERef::Section section, bool is_dwo)
+ : DWARFUnit(dwarf, uid, header, abbrevs, section, is_dwo) {}
friend class DWARFUnit;
};
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 9964cf4b893c..22e3e40dac93 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -32,9 +32,9 @@ extern int g_verbose;
DWARFUnit::DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
const DWARFUnitHeader &header,
const DWARFAbbreviationDeclarationSet &abbrevs,
- DIERef::Section section)
+ DIERef::Section section, bool is_dwo)
: UserID(uid), m_dwarf(dwarf), m_header(header), m_abbrevs(&abbrevs),
- m_cancel_scopes(false), m_section(section) {}
+ m_cancel_scopes(false), m_section(section), m_is_dwo(is_dwo) {}
DWARFUnit::~DWARFUnit() = default;
@@ -287,15 +287,27 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
DWARFAttributes attributes;
size_t num_attributes = cu_die.GetAttributes(this, attributes);
+
+ // Extract DW_AT_addr_base first, as other attributes may need it.
+ for (size_t i = 0; i < num_attributes; ++i) {
+ if (attributes.AttributeAtIndex(i) != DW_AT_addr_base)
+ continue;
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value)) {
+ addr_base = form_value.Unsigned();
+ SetAddrBase(*addr_base);
+ break;
+ }
+ }
+
for (size_t i = 0; i < num_attributes; ++i) {
dw_attr_t attr = attributes.AttributeAtIndex(i);
DWARFFormValue form_value;
if (!attributes.ExtractFormValueAtIndex(i, form_value))
continue;
switch (attr) {
- case DW_AT_addr_base:
- addr_base = form_value.Unsigned();
- SetAddrBase(*addr_base);
+ case DW_AT_loclists_base:
+ SetLoclistsBase(form_value.Unsigned());
break;
case DW_AT_rnglists_base:
ranges_base = form_value.Unsigned();
@@ -324,6 +336,9 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
}
}
+ if (m_is_dwo)
+ return;
+
std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file =
m_dwarf.GetDwoSymbolFileForCompileUnit(*this, cu_die);
if (!dwo_symbol_file)
@@ -358,10 +373,18 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
else if (gnu_addr_base)
dwo_cu->SetAddrBase(*gnu_addr_base);
- if (ranges_base)
- dwo_cu->SetRangesBase(*ranges_base);
- else if (gnu_ranges_base)
+ if (GetVersion() <= 4 && gnu_ranges_base)
dwo_cu->SetRangesBase(*gnu_ranges_base);
+ else if (m_dwo_symbol_file->GetDWARFContext()
+ .getOrLoadRngListsData()
+ .GetByteSize() > 0)
+ dwo_cu->SetRangesBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
+
+ if (GetVersion() >= 5 && m_dwo_symbol_file->GetDWARFContext()
+ .getOrLoadLocListsData()
+ .GetByteSize() > 0)
+ dwo_cu->SetLoclistsBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32));
+ dwo_cu->SetBaseAddress(GetBaseAddress());
for (size_t i = 0; i < m_dwo_symbol_file->DebugInfo()->GetNumUnits(); ++i) {
DWARFUnit *unit = m_dwo_symbol_file->DebugInfo()->GetUnitAtIndex(i);
@@ -380,24 +403,6 @@ DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) {
return DWARFDIE();
}
-size_t DWARFUnit::AppendDIEsWithTag(const dw_tag_t tag,
- std::vector<DWARFDIE> &dies,
- uint32_t depth) const {
- size_t old_size = dies.size();
- {
- llvm::sys::ScopedReader lock(m_die_array_mutex);
- DWARFDebugInfoEntry::const_iterator pos;
- DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
- for (pos = m_die_array.begin(); pos != end; ++pos) {
- if (pos->Tag() == tag)
- dies.emplace_back(this, &(*pos));
- }
- }
-
- // Return the number of DIEs added to the collection
- return dies.size() - old_size;
-}
-
size_t DWARFUnit::GetDebugInfoSize() const {
return GetLengthByteSize() + GetLength() - GetHeaderByteSize();
}
@@ -417,8 +422,79 @@ dw_offset_t DWARFUnit::GetLineTableOffset() {
void DWARFUnit::SetAddrBase(dw_addr_t addr_base) { m_addr_base = addr_base; }
+// Parse the rangelist table header, including the optional array of offsets
+// following it (DWARF v5 and later).
+template <typename ListTableType>
+static llvm::Expected<ListTableType>
+ParseListTableHeader(const llvm::DWARFDataExtractor &data, uint64_t offset,
+ DwarfFormat format) {
+ // We are expected to be called with Offset 0 or pointing just past the table
+ // header. Correct Offset in the latter case so that it points to the start
+ // of the header.
+ if (offset > 0) {
+ uint64_t HeaderSize = llvm::DWARFListTableHeader::getHeaderSize(format);
+ if (offset < HeaderSize)
+ return llvm::createStringError(errc::invalid_argument,
+ "did not detect a valid"
+ " list table with base = 0x%" PRIx64 "\n",
+ offset);
+ offset -= HeaderSize;
+ }
+ ListTableType Table;
+ if (llvm::Error E = Table.extractHeaderAndOffsets(data, &offset))
+ return std::move(E);
+ return Table;
+}
+
+void DWARFUnit::SetLoclistsBase(dw_addr_t loclists_base) {
+ m_loclists_base = loclists_base;
+
+ uint64_t header_size = llvm::DWARFListTableHeader::getHeaderSize(DWARF32);
+ if (loclists_base < header_size)
+ return;
+
+ m_loclist_table_header.emplace(".debug_loclists", "locations");
+ uint64_t offset = loclists_base - header_size;
+ if (llvm::Error E = m_loclist_table_header->extract(
+ m_dwarf.GetDWARFContext().getOrLoadLocListsData().GetAsLLVM(),
+ &offset)) {
+ GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
+ "Failed to extract location list table at offset 0x%" PRIx64 ": %s",
+ loclists_base, toString(std::move(E)).c_str());
+ }
+}
+
+std::unique_ptr<llvm::DWARFLocationTable>
+DWARFUnit::GetLocationTable(const DataExtractor &data) const {
+ llvm::DWARFDataExtractor llvm_data(
+ toStringRef(data.GetData()),
+ data.GetByteOrder() == lldb::eByteOrderLittle, data.GetAddressByteSize());
+
+ if (m_is_dwo || GetVersion() >= 5)
+ return std::make_unique<llvm::DWARFDebugLoclists>(llvm_data, GetVersion());
+ return std::make_unique<llvm::DWARFDebugLoc>(llvm_data);
+}
+
+const DWARFDataExtractor &DWARFUnit::GetLocationData() const {
+ DWARFContext &Ctx = GetSymbolFileDWARF().GetDWARFContext();
+ return GetVersion() >= 5 ? Ctx.getOrLoadLocListsData()
+ : Ctx.getOrLoadLocData();
+}
+
void DWARFUnit::SetRangesBase(dw_addr_t ranges_base) {
m_ranges_base = ranges_base;
+
+ if (GetVersion() < 5)
+ return;
+
+ if (auto table_or_error = ParseListTableHeader<llvm::DWARFDebugRnglistTable>(
+ m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(),
+ ranges_base, DWARF32))
+ m_rnglist_table = std::move(table_or_error.get());
+ else
+ GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
+ "Failed to extract range list table at offset 0x%" PRIx64 ": %s",
+ ranges_base, toString(table_or_error.takeError()).c_str());
}
void DWARFUnit::SetStrOffsetsBase(dw_offset_t str_offsets_base) {
@@ -646,6 +722,8 @@ FileSpec DWARFUnit::GetFile(size_t file_idx) {
// Remove the host part if present.
static llvm::StringRef
removeHostnameFromPathname(llvm::StringRef path_from_dwarf) {
+ if (!path_from_dwarf.contains(':'))
+ return path_from_dwarf;
llvm::StringRef host, path;
std::tie(host, path) = path_from_dwarf.split(':');
@@ -715,7 +793,8 @@ void DWARFUnit::ComputeAbsolutePath() {
m_file_spec->MakeAbsolute(GetCompilationDirectory());
}
-SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const {
+SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() {
+ ExtractUnitDIEIfNeeded();
return m_dwo_symbol_file.get();
}
@@ -816,11 +895,12 @@ DWARFUnit::extract(SymbolFileDWARF &dwarf, user_id_t uid,
return llvm::make_error<llvm::object::GenericBinaryError>(
"No abbrev exists at the specified offset.");
+ bool is_dwo = dwarf.GetDWARFContext().isDwo();
if (expected_header->IsTypeUnit())
- return DWARFUnitSP(
- new DWARFTypeUnit(dwarf, uid, *expected_header, *abbrevs, section));
- return DWARFUnitSP(
- new DWARFCompileUnit(dwarf, uid, *expected_header, *abbrevs, section));
+ return DWARFUnitSP(new DWARFTypeUnit(dwarf, uid, *expected_header, *abbrevs,
+ section, is_dwo));
+ return DWARFUnitSP(new DWARFCompileUnit(dwarf, uid, *expected_header,
+ *abbrevs, section, is_dwo));
}
const lldb_private::DWARFDataExtractor &DWARFUnit::GetData() const {
@@ -845,30 +925,56 @@ uint32_t DWARFUnit::GetHeaderByteSize() const {
}
llvm::Expected<DWARFRangeList>
-DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) const {
- const DWARFDebugRangesBase *debug_ranges;
- llvm::StringRef section;
+DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) {
if (GetVersion() <= 4) {
- debug_ranges = m_dwarf.GetDebugRanges();
- section = "debug_ranges";
- } else {
- debug_ranges = m_dwarf.GetDebugRngLists();
- section = "debug_rnglists";
+ const DWARFDebugRanges *debug_ranges = m_dwarf.GetDebugRanges();
+ if (!debug_ranges)
+ return llvm::make_error<llvm::object::GenericBinaryError>(
+ "No debug_ranges section");
+ DWARFRangeList ranges;
+ debug_ranges->FindRanges(this, offset, ranges);
+ return ranges;
}
- if (!debug_ranges)
- return llvm::make_error<llvm::object::GenericBinaryError>("No " + section +
- " section");
+
+ if (!m_rnglist_table)
+ return llvm::createStringError(errc::invalid_argument,
+ "missing or invalid range list table");
+
+ auto range_list_or_error = m_rnglist_table->findList(
+ m_dwarf.GetDWARFContext().getOrLoadRngListsData().GetAsLLVM(), offset);
+ if (!range_list_or_error)
+ return range_list_or_error.takeError();
+
+ llvm::Expected<llvm::DWARFAddressRangesVector> llvm_ranges =
+ range_list_or_error->getAbsoluteRanges(
+ llvm::object::SectionedAddress{GetBaseAddress()},
+ [&](uint32_t index) {
+ uint32_t index_size = GetAddressByteSize();
+ dw_offset_t addr_base = GetAddrBase();
+ lldb::offset_t offset = addr_base + index * index_size;
+ return llvm::object::SectionedAddress{
+ m_dwarf.GetDWARFContext().getOrLoadAddrData().GetMaxU64(
+ &offset, index_size)};
+ });
+ if (!llvm_ranges)
+ return llvm_ranges.takeError();
DWARFRangeList ranges;
- debug_ranges->FindRanges(this, offset, ranges);
+ for (const llvm::DWARFAddressRange &llvm_range : *llvm_ranges) {
+ ranges.Append(DWARFRangeList::Entry(llvm_range.LowPC,
+ llvm_range.HighPC - llvm_range.LowPC));
+ }
return ranges;
}
llvm::Expected<DWARFRangeList>
-DWARFUnit::FindRnglistFromIndex(uint32_t index) const {
- const DWARFDebugRngLists *debug_rnglists = m_dwarf.GetDebugRngLists();
- if (!debug_rnglists)
- return llvm::make_error<llvm::object::GenericBinaryError>(
- "No debug_rnglists section");
- return FindRnglistFromOffset(debug_rnglists->GetOffset(index));
+DWARFUnit::FindRnglistFromIndex(uint32_t index) {
+ if (llvm::Optional<uint64_t> offset = GetRnglistOffset(index))
+ return FindRnglistFromOffset(*offset);
+ if (m_rnglist_table)
+ return llvm::createStringError(errc::invalid_argument,
+ "invalid range list table index %d", index);
+
+ return llvm::createStringError(errc::invalid_argument,
+ "missing or invalid range list table");
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
index 87e0de283de4..217f9bb89ace 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -95,8 +95,6 @@ public:
ScopedExtractDIEs ExtractDIEsScoped();
DWARFDIE LookupAddress(const dw_addr_t address);
- size_t AppendDIEsWithTag(const dw_tag_t tag, std::vector<DWARFDIE> &dies,
- uint32_t depth = UINT32_MAX) const;
bool Verify(lldb_private::Stream *s) const;
virtual void Dump(lldb_private::Stream *s) const = 0;
/// Get the data that contains the DIE information for this unit.
@@ -147,6 +145,7 @@ public:
dw_addr_t GetRangesBase() const { return m_ranges_base; }
dw_addr_t GetStrOffsetsBase() const { return m_str_offsets_base; }
void SetAddrBase(dw_addr_t addr_base);
+ void SetLoclistsBase(dw_addr_t loclists_base);
void SetRangesBase(dw_addr_t ranges_base);
void SetStrOffsetsBase(dw_offset_t str_offsets_base);
virtual void BuildAddressRangeTable(DWARFDebugAranges *debug_aranges) = 0;
@@ -202,7 +201,7 @@ public:
lldb_private::FileSpec GetFile(size_t file_idx);
lldb_private::FileSpec::Style GetPathStyle();
- SymbolFileDWARFDwo *GetDwoSymbolFile() const;
+ SymbolFileDWARFDwo *GetDwoSymbolFile();
die_iterator_range dies() {
ExtractDIEsIfNeeded();
@@ -216,18 +215,46 @@ public:
/// Return a list of address ranges resulting from a (possibly encoded)
/// range list starting at a given offset in the appropriate ranges section.
- llvm::Expected<DWARFRangeList> FindRnglistFromOffset(dw_offset_t offset) const;
+ llvm::Expected<DWARFRangeList> FindRnglistFromOffset(dw_offset_t offset);
/// Return a list of address ranges retrieved from an encoded range
/// list whose offset is found via a table lookup given an index (DWARF v5
/// and later).
- llvm::Expected<DWARFRangeList> FindRnglistFromIndex(uint32_t index) const;
+ llvm::Expected<DWARFRangeList> FindRnglistFromIndex(uint32_t index);
+
+ /// Return a rangelist's offset based on an index. The index designates
+ /// an entry in the rangelist table's offset array and is supplied by
+ /// DW_FORM_rnglistx.
+ llvm::Optional<uint64_t> GetRnglistOffset(uint32_t Index) const {
+ if (!m_rnglist_table)
+ return llvm::None;
+ if (llvm::Optional<uint64_t> off = m_rnglist_table->getOffsetEntry(Index))
+ return *off + m_ranges_base;
+ return llvm::None;
+ }
+
+ llvm::Optional<uint64_t> GetLoclistOffset(uint32_t Index) {
+ if (!m_loclist_table_header)
+ return llvm::None;
+
+ llvm::Optional<uint64_t> Offset = m_loclist_table_header->getOffsetEntry(Index);
+ if (!Offset)
+ return llvm::None;
+ return *Offset + m_loclists_base;
+ }
+
+ /// Return the location table for parsing the given location list data. The
+ /// format is chosen according to the unit type. Never returns null.
+ std::unique_ptr<llvm::DWARFLocationTable>
+ GetLocationTable(const lldb_private::DataExtractor &data) const;
+
+ const lldb_private::DWARFDataExtractor &GetLocationData() const;
protected:
DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
const DWARFUnitHeader &header,
const DWARFAbbreviationDeclarationSet &abbrevs,
- DIERef::Section section);
+ DIERef::Section section, bool is_dwo);
llvm::Error ExtractHeader(SymbolFileDWARF &dwarf,
const lldb_private::DWARFDataExtractor &data,
@@ -281,14 +308,20 @@ protected:
lldb_private::LazyBool m_is_optimized = lldb_private::eLazyBoolCalculate;
llvm::Optional<lldb_private::FileSpec> m_comp_dir;
llvm::Optional<lldb_private::FileSpec> m_file_spec;
- dw_addr_t m_addr_base = 0; // Value of DW_AT_addr_base
- dw_addr_t m_ranges_base = 0; // Value of DW_AT_ranges_base
+ dw_addr_t m_addr_base = 0; ///< Value of DW_AT_addr_base.
+ dw_addr_t m_loclists_base = 0; ///< Value of DW_AT_loclists_base.
+ dw_addr_t m_ranges_base = 0; ///< Value of DW_AT_rnglists_base.
/// Value of DW_AT_stmt_list.
dw_offset_t m_line_table_offset = DW_INVALID_OFFSET;
dw_offset_t m_str_offsets_base = 0; // Value of DW_AT_str_offsets_base.
+
+ llvm::Optional<llvm::DWARFDebugRnglistTable> m_rnglist_table;
+ llvm::Optional<llvm::DWARFListTableHeader> m_loclist_table_header;
+
const DIERef::Section m_section;
+ bool m_is_dwo;
private:
void ParseProducerInfo();
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
index aff8b5d8c15f..1e5927bd14f0 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -401,8 +401,6 @@ void ManualDWARFIndex::GetFunctions(ConstString name, SymbolFileDWARF &dwarf,
if (name_type_mask & eFunctionNameTypeFull) {
DIEArray offsets;
- m_set.function_basenames.Find(name, offsets);
- m_set.function_methods.Find(name, offsets);
m_set.function_fullnames.Find(name, offsets);
for (const DIERef &die_ref: offsets) {
DWARFDIE die = dwarf.GetDIE(die_ref);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index c982d59c2830..d45a8b56efe4 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -94,6 +94,8 @@
using namespace lldb;
using namespace lldb_private;
+char SymbolFileDWARF::ID;
+
// static inline bool
// child_requires_parent_class_union_or_struct_to_be_completed (dw_tag_t tag)
//{
@@ -179,36 +181,46 @@ ParseLLVMLineTable(lldb_private::DWARFContext &context,
return *line_table;
}
-static FileSpecList ParseSupportFilesFromPrologue(
- const lldb::ModuleSP &module,
- const llvm::DWARFDebugLine::Prologue &prologue, FileSpec::Style style,
- llvm::StringRef compile_dir = {}, FileSpec first_file = {}) {
+static llvm::Optional<std::string>
+GetFileByIndex(const llvm::DWARFDebugLine::Prologue &prologue, size_t idx,
+ llvm::StringRef compile_dir, FileSpec::Style style) {
+ // Try to get an absolute path first.
+ std::string abs_path;
+ auto absolute = llvm::DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath;
+ if (prologue.getFileNameByIndex(idx, compile_dir, absolute, abs_path, style))
+ return std::move(abs_path);
+
+ // Otherwise ask for a relative path.
+ std::string rel_path;
+ auto relative = llvm::DILineInfoSpecifier::FileLineInfoKind::Default;
+ if (!prologue.getFileNameByIndex(idx, compile_dir, relative, rel_path, style))
+ return {};
+ return std::move(rel_path);
+}
+
+static FileSpecList
+ParseSupportFilesFromPrologue(const lldb::ModuleSP &module,
+ const llvm::DWARFDebugLine::Prologue &prologue,
+ FileSpec::Style style,
+ llvm::StringRef compile_dir = {}) {
FileSpecList support_files;
- support_files.Append(first_file);
+ size_t first_file = 0;
+ if (prologue.getVersion() <= 4) {
+ // File index 0 is not valid before DWARF v5. Add a dummy entry to ensure
+ // support file list indices match those we get from the debug info and line
+ // tables.
+ support_files.Append(FileSpec());
+ first_file = 1;
+ }
const size_t number_of_files = prologue.FileNames.size();
- for (size_t idx = 1; idx <= number_of_files; ++idx) {
- std::string original_file;
- if (!prologue.getFileNameByIndex(
- idx, compile_dir,
- llvm::DILineInfoSpecifier::FileLineInfoKind::Default, original_file,
- style)) {
- // Always add an entry so the indexes remain correct.
- support_files.EmplaceBack();
- continue;
- }
-
+ for (size_t idx = first_file; idx <= number_of_files; ++idx) {
std::string remapped_file;
- if (!prologue.getFileNameByIndex(
- idx, compile_dir,
- llvm::DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
- remapped_file, style)) {
- // Always add an entry so the indexes remain correct.
- support_files.EmplaceBack(original_file, style);
- continue;
- }
+ if (auto file_path = GetFileByIndex(prologue, idx, compile_dir, style))
+ if (!module->RemapSourceFile(llvm::StringRef(*file_path), remapped_file))
+ remapped_file = std::move(*file_path);
- module->RemapSourceFile(llvm::StringRef(original_file), remapped_file);
+ // Unconditionally add an entry, so the indices match up.
support_files.EmplaceBack(remapped_file, style);
}
@@ -585,22 +597,6 @@ void SymbolFileDWARF::LoadSectionData(lldb::SectionType sect_type,
m_objfile_sp->ReadSectionData(section_sp.get(), data);
}
-const DWARFDataExtractor &SymbolFileDWARF::DebugLocData() {
- const DWARFDataExtractor &debugLocData = get_debug_loc_data();
- if (debugLocData.GetByteSize() > 0)
- return debugLocData;
- return get_debug_loclists_data();
-}
-
-const DWARFDataExtractor &SymbolFileDWARF::get_debug_loc_data() {
- return GetCachedSectionData(eSectionTypeDWARFDebugLoc, m_data_debug_loc);
-}
-
-const DWARFDataExtractor &SymbolFileDWARF::get_debug_loclists_data() {
- return GetCachedSectionData(eSectionTypeDWARFDebugLocLists,
- m_data_debug_loclists);
-}
-
DWARFDebugAbbrev *SymbolFileDWARF::DebugAbbrev() {
if (m_abbr)
return m_abbr.get();
@@ -672,21 +668,6 @@ DWARFDebugRanges *SymbolFileDWARF::GetDebugRanges() {
return m_ranges.get();
}
-DWARFDebugRngLists *SymbolFileDWARF::GetDebugRngLists() {
- if (!m_rnglists) {
- static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
- Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION,
- static_cast<void *>(this));
-
- if (m_context.getOrLoadRngListsData().GetByteSize() > 0)
- m_rnglists.reset(new DWARFDebugRngLists());
-
- if (m_rnglists)
- m_rnglists->Extract(m_context);
- }
- return m_rnglists.get();
-}
-
lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
CompUnitSP cu_sp;
CompileUnit *comp_unit = (CompileUnit *)dwarf_cu.GetUserData();
@@ -703,7 +684,8 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
} else {
ModuleSP module_sp(m_objfile_sp->GetModule());
if (module_sp) {
- const DWARFDIE cu_die = dwarf_cu.DIE();
+ const DWARFBaseDIE cu_die =
+ dwarf_cu.GetNonSkeletonUnit().GetUnitDIEOnly();
if (cu_die) {
FileSpec cu_file_spec(cu_die.GetName(), dwarf_cu.GetPathStyle());
if (cu_file_spec) {
@@ -721,7 +703,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
LanguageType cu_language = DWARFUnit::LanguageTypeFromDWARF(
cu_die.GetAttributeValueAsUnsigned(DW_AT_language, 0));
- bool is_optimized = dwarf_cu.GetIsOptimized();
+ bool is_optimized = dwarf_cu.GetNonSkeletonUnit().GetIsOptimized();
BuildCuTranslationTable();
cu_sp = std::make_shared<CompileUnit>(
module_sp, &dwarf_cu, cu_file_spec,
@@ -828,15 +810,20 @@ lldb::LanguageType SymbolFileDWARF::ParseLanguage(CompileUnit &comp_unit) {
}
size_t SymbolFileDWARF::ParseFunctions(CompileUnit &comp_unit) {
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "SymbolFileDWARF::ParseFunctions");
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
if (!dwarf_cu)
return 0;
size_t functions_added = 0;
- std::vector<DWARFDIE> function_dies;
- dwarf_cu->AppendDIEsWithTag(DW_TAG_subprogram, function_dies);
- for (const DWARFDIE &die : function_dies) {
+ dwarf_cu = &dwarf_cu->GetNonSkeletonUnit();
+ for (DWARFDebugInfoEntry &entry : dwarf_cu->dies()) {
+ if (entry.Tag() != DW_TAG_subprogram)
+ continue;
+
+ DWARFDIE die(dwarf_cu, &entry);
if (comp_unit.FindFunctionByUID(die.GetID()))
continue;
if (ParseFunction(comp_unit, die))
@@ -846,16 +833,32 @@ size_t SymbolFileDWARF::ParseFunctions(CompileUnit &comp_unit) {
return functions_added;
}
-void SymbolFileDWARF::ForEachExternalModule(
- CompileUnit &comp_unit, llvm::function_ref<void(ModuleSP)> f) {
- UpdateExternalModuleListIfNeeded();
+bool SymbolFileDWARF::ForEachExternalModule(
+ CompileUnit &comp_unit,
+ llvm::DenseSet<lldb_private::SymbolFile *> &visited_symbol_files,
+ llvm::function_ref<bool(Module &)> lambda) {
+ // Only visit each symbol file once.
+ if (!visited_symbol_files.insert(this).second)
+ return false;
+ UpdateExternalModuleListIfNeeded();
for (auto &p : m_external_type_modules) {
ModuleSP module = p.second;
- f(module);
- for (std::size_t i = 0; i < module->GetNumCompileUnits(); ++i)
- module->GetCompileUnitAtIndex(i)->ForEachExternalModule(f);
+ if (!module)
+ continue;
+
+ // Invoke the action and potentially early-exit.
+ if (lambda(*module))
+ return true;
+
+ for (std::size_t i = 0; i < module->GetNumCompileUnits(); ++i) {
+ auto cu = module->GetCompileUnitAtIndex(i);
+ bool early_exit = cu->ForEachExternalModule(visited_symbol_files, lambda);
+ if (early_exit)
+ return true;
+ }
}
+ return false;
}
bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit,
@@ -961,7 +964,7 @@ bool SymbolFileDWARF::ParseImportedModules(
DW_AT_LLVM_include_path, nullptr))
module.search_path = ConstString(include_path);
if (const char *sysroot = module_die.GetAttributeValueAsString(
- DW_AT_LLVM_isysroot, nullptr))
+ DW_AT_LLVM_sysroot, nullptr))
module.sysroot = ConstString(sysroot);
imported_modules.push_back(module);
}
@@ -1023,7 +1026,7 @@ bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) {
comp_unit.SetSupportFiles(ParseSupportFilesFromPrologue(
comp_unit.GetModule(), line_table->Prologue, dwarf_cu->GetPathStyle(),
- dwarf_cu->GetCompilationDirectory().GetCString(), FileSpec(comp_unit)));
+ dwarf_cu->GetCompilationDirectory().GetCString()));
return true;
}
@@ -1507,7 +1510,7 @@ bool SymbolFileDWARF::GetFunction(const DWARFDIE &die, SymbolContext &sc) {
return false;
}
-lldb::ModuleSP SymbolFileDWARF::GetDWOModule(ConstString name) {
+lldb::ModuleSP SymbolFileDWARF::GetExternalModule(ConstString name) {
UpdateExternalModuleListIfNeeded();
const auto &pos = m_external_type_modules.find(name);
if (pos != m_external_type_modules.end())
@@ -1532,12 +1535,48 @@ SymbolFileDWARF::GetDIE(const DIERef &die_ref) {
return DWARFDIE();
}
+/// Return the DW_AT_(GNU_)dwo_name.
+static const char *GetDWOName(DWARFCompileUnit &dwarf_cu,
+ const DWARFDebugInfoEntry &cu_die) {
+ const char *dwo_name =
+ cu_die.GetAttributeValueAsString(&dwarf_cu, DW_AT_GNU_dwo_name, nullptr);
+ if (!dwo_name)
+ dwo_name =
+ cu_die.GetAttributeValueAsString(&dwarf_cu, DW_AT_dwo_name, nullptr);
+ return dwo_name;
+}
+
+/// Return the DW_AT_(GNU_)dwo_id.
+/// FIXME: Technically 0 is a valid hash.
+static uint64_t GetDWOId(DWARFCompileUnit &dwarf_cu,
+ const DWARFDebugInfoEntry &cu_die) {
+ uint64_t dwo_id =
+ cu_die.GetAttributeValueAsUnsigned(&dwarf_cu, DW_AT_GNU_dwo_id, 0);
+ if (!dwo_id)
+ dwo_id = cu_die.GetAttributeValueAsUnsigned(&dwarf_cu, DW_AT_dwo_id, 0);
+ return dwo_id;
+}
+
+llvm::Optional<uint64_t> SymbolFileDWARF::GetDWOId() {
+ if (GetNumCompileUnits() == 1) {
+ if (auto comp_unit = GetCompileUnitAtIndex(0))
+ if (DWARFCompileUnit *cu = llvm::dyn_cast_or_null<DWARFCompileUnit>(
+ GetDWARFCompileUnit(comp_unit.get())))
+ if (DWARFDebugInfoEntry *cu_die = cu->DIE().GetDIE())
+ if (uint64_t dwo_id = ::GetDWOId(*cu, *cu_die))
+ return dwo_id;
+ }
+ return {};
+}
+
std::unique_ptr<SymbolFileDWARFDwo>
SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
DWARFUnit &unit, const DWARFDebugInfoEntry &cu_die) {
- // If we are using a dSYM file, we never want the standard DWO files since
- // the -gmodules support uses the same DWO machanism to specify full debug
- // info files for modules.
+ // If this is a Darwin-style debug map (non-.dSYM) symbol file,
+ // never attempt to load ELF-style DWO files since the -gmodules
+ // support uses the same DWO machanism to specify full debug info
+ // files for modules. This is handled in
+ // UpdateExternalModuleListIfNeeded().
if (GetDebugMapSymfile())
return nullptr;
@@ -1546,15 +1585,13 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
if (!dwarf_cu)
return nullptr;
- const char *dwo_name =
- cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_GNU_dwo_name, nullptr);
+ const char *dwo_name = GetDWOName(*dwarf_cu, cu_die);
if (!dwo_name)
return nullptr;
SymbolFileDWARFDwp *dwp_symfile = GetDwpSymbolFile();
if (dwp_symfile) {
- uint64_t dwo_id =
- cu_die.GetAttributeValueAsUnsigned(dwarf_cu, DW_AT_GNU_dwo_id, 0);
+ uint64_t dwo_id = ::GetDWOId(*dwarf_cu, cu_die);
std::unique_ptr<SymbolFileDWARFDwo> dwo_symfile =
dwp_symfile->GetSymbolFileForDwoId(*dwarf_cu, dwo_id);
if (dwo_symfile)
@@ -1594,76 +1631,101 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() {
if (m_fetched_external_modules)
return;
m_fetched_external_modules = true;
-
DWARFDebugInfo *debug_info = DebugInfo();
+ // Follow DWO skeleton unit breadcrumbs.
const uint32_t num_compile_units = GetNumCompileUnits();
for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) {
- DWARFUnit *dwarf_cu = debug_info->GetUnitAtIndex(cu_idx);
+ auto *dwarf_cu =
+ llvm::dyn_cast<DWARFCompileUnit>(debug_info->GetUnitAtIndex(cu_idx));
+ if (!dwarf_cu)
+ continue;
const DWARFBaseDIE die = dwarf_cu->GetUnitDIEOnly();
- if (die && !die.HasChildren()) {
- const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr);
-
- if (name) {
- ConstString const_name(name);
- if (m_external_type_modules.find(const_name) ==
- m_external_type_modules.end()) {
- ModuleSP module_sp;
- const char *dwo_path =
- die.GetAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr);
- if (dwo_path) {
- ModuleSpec dwo_module_spec;
- dwo_module_spec.GetFileSpec().SetFile(dwo_path,
- FileSpec::Style::native);
- if (dwo_module_spec.GetFileSpec().IsRelative()) {
- const char *comp_dir =
- die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr);
- if (comp_dir) {
- dwo_module_spec.GetFileSpec().SetFile(comp_dir,
- FileSpec::Style::native);
- FileSystem::Instance().Resolve(dwo_module_spec.GetFileSpec());
- dwo_module_spec.GetFileSpec().AppendPathComponent(dwo_path);
- }
- }
- dwo_module_spec.GetArchitecture() =
- m_objfile_sp->GetModule()->GetArchitecture();
-
- // When LLDB loads "external" modules it looks at the presence of
- // DW_AT_GNU_dwo_name. However, when the already created module
- // (corresponding to .dwo itself) is being processed, it will see
- // the presence of DW_AT_GNU_dwo_name (which contains the name of
- // dwo file) and will try to call ModuleList::GetSharedModule
- // again. In some cases (i.e. for empty files) Clang 4.0 generates
- // a *.dwo file which has DW_AT_GNU_dwo_name, but no
- // DW_AT_comp_dir. In this case the method
- // ModuleList::GetSharedModule will fail and the warning will be
- // printed. However, as one can notice in this case we don't
- // actually need to try to load the already loaded module
- // (corresponding to .dwo) so we simply skip it.
- if (m_objfile_sp->GetFileSpec().GetFileNameExtension() == ".dwo" &&
- llvm::StringRef(m_objfile_sp->GetFileSpec().GetPath())
- .endswith(dwo_module_spec.GetFileSpec().GetPath())) {
- continue;
- }
+ if (!die || die.HasChildren() || !die.GetDIE())
+ continue;
- Status error = ModuleList::GetSharedModule(
- dwo_module_spec, module_sp, nullptr, nullptr, nullptr);
- if (!module_sp) {
- GetObjectFile()->GetModule()->ReportWarning(
- "0x%8.8x: unable to locate module needed for external types: "
- "%s\nerror: %s\nDebugging will be degraded due to missing "
- "types. Rebuilding your project will regenerate the needed "
- "module files.",
- die.GetOffset(),
- dwo_module_spec.GetFileSpec().GetPath().c_str(),
- error.AsCString("unknown error"));
- }
- }
- m_external_type_modules[const_name] = module_sp;
- }
+ const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr);
+ if (!name)
+ continue;
+
+ ConstString const_name(name);
+ ModuleSP &module_sp = m_external_type_modules[const_name];
+ if (module_sp)
+ continue;
+
+ const char *dwo_path = GetDWOName(*dwarf_cu, *die.GetDIE());
+ if (!dwo_path)
+ continue;
+
+ ModuleSpec dwo_module_spec;
+ dwo_module_spec.GetFileSpec().SetFile(dwo_path, FileSpec::Style::native);
+ if (dwo_module_spec.GetFileSpec().IsRelative()) {
+ const char *comp_dir =
+ die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr);
+ if (comp_dir) {
+ dwo_module_spec.GetFileSpec().SetFile(comp_dir,
+ FileSpec::Style::native);
+ FileSystem::Instance().Resolve(dwo_module_spec.GetFileSpec());
+ dwo_module_spec.GetFileSpec().AppendPathComponent(dwo_path);
}
}
+ dwo_module_spec.GetArchitecture() =
+ m_objfile_sp->GetModule()->GetArchitecture();
+
+ // When LLDB loads "external" modules it looks at the presence of
+ // DW_AT_dwo_name. However, when the already created module
+ // (corresponding to .dwo itself) is being processed, it will see
+ // the presence of DW_AT_dwo_name (which contains the name of dwo
+ // file) and will try to call ModuleList::GetSharedModule
+ // again. In some cases (i.e., for empty files) Clang 4.0
+ // generates a *.dwo file which has DW_AT_dwo_name, but no
+ // DW_AT_comp_dir. In this case the method
+ // ModuleList::GetSharedModule will fail and the warning will be
+ // printed. However, as one can notice in this case we don't
+ // actually need to try to load the already loaded module
+ // (corresponding to .dwo) so we simply skip it.
+ if (m_objfile_sp->GetFileSpec().GetFileNameExtension() == ".dwo" &&
+ llvm::StringRef(m_objfile_sp->GetFileSpec().GetPath())
+ .endswith(dwo_module_spec.GetFileSpec().GetPath())) {
+ continue;
+ }
+
+ Status error = ModuleList::GetSharedModule(dwo_module_spec, module_sp,
+ nullptr, nullptr, nullptr);
+ if (!module_sp) {
+ GetObjectFile()->GetModule()->ReportWarning(
+ "0x%8.8x: unable to locate module needed for external types: "
+ "%s\nerror: %s\nDebugging will be degraded due to missing "
+ "types. Rebuilding the project will regenerate the needed "
+ "module files.",
+ die.GetOffset(), dwo_module_spec.GetFileSpec().GetPath().c_str(),
+ error.AsCString("unknown error"));
+ continue;
+ }
+
+ // Verify the DWO hash.
+ // FIXME: Technically "0" is a valid hash.
+ uint64_t dwo_id = ::GetDWOId(*dwarf_cu, *die.GetDIE());
+ if (!dwo_id)
+ continue;
+
+ auto *dwo_symfile =
+ llvm::dyn_cast_or_null<SymbolFileDWARF>(module_sp->GetSymbolFile());
+ if (!dwo_symfile)
+ continue;
+ llvm::Optional<uint64_t> dwo_dwo_id = dwo_symfile->GetDWOId();
+ if (!dwo_dwo_id)
+ continue;
+
+ if (dwo_id != dwo_dwo_id) {
+ GetObjectFile()->GetModule()->ReportWarning(
+ "0x%8.8x: Module %s is out-of-date (hash mismatch). Type information "
+ "from this module may be incomplete or inconsistent with the rest of "
+ "the program. Rebuilding the project will regenerate the needed "
+ "module files.",
+ die.GetOffset(), dwo_module_spec.GetFileSpec().GetPath().c_str());
+ }
}
}
@@ -1867,9 +1929,8 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
if (!dc_cu)
continue;
- const bool full_match = (bool)file_spec.GetDirectory();
bool file_spec_matches_cu_file_spec =
- FileSpec::Equal(file_spec, *dc_cu, full_match);
+ FileSpec::Match(file_spec, dc_cu->GetPrimaryFile());
if (check_inlines || file_spec_matches_cu_file_spec) {
SymbolContext sc(m_objfile_sp->GetModule());
sc.comp_unit = dc_cu;
@@ -2208,9 +2269,12 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die,
addr = sc.function->GetAddressRange().GetBaseAddress();
}
- if (addr.IsValid()) {
- sc_list.Append(sc);
- return true;
+
+ if (auto section_sp = addr.GetSection()) {
+ if (section_sp->GetPermissions() & ePermissionsExecutable) {
+ sc_list.Append(sc);
+ return true;
+ }
}
}
@@ -2364,12 +2428,10 @@ void SymbolFileDWARF::FindTypes(
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
- // Make sure we haven't already searched this SymbolFile before...
- if (searched_symbol_files.count(this))
+ // Make sure we haven't already searched this SymbolFile before.
+ if (!searched_symbol_files.insert(this).second)
return;
- searched_symbol_files.insert(this);
-
DWARFDebugInfo *info = DebugInfo();
if (!info)
return;
@@ -2451,8 +2513,13 @@ void SymbolFileDWARF::FindTypes(
}
}
-void SymbolFileDWARF::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
- LanguageSet languages, TypeMap &types) {
+void SymbolFileDWARF::FindTypes(
+ llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {
+ // Make sure we haven't already searched this SymbolFile before.
+ if (!searched_symbol_files.insert(this).second)
+ return;
+
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
if (pattern.empty())
return;
@@ -2482,11 +2549,22 @@ void SymbolFileDWARF::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
if (!contextMatches(die_context, pattern))
continue;
- if (Type *matching_type = ResolveType(die, true, true))
+ if (Type *matching_type = ResolveType(die, true, true)) {
// We found a type pointer, now find the shared pointer form our type
// list.
types.InsertUnique(matching_type->shared_from_this());
+ }
}
+
+ // Next search through the reachable Clang modules. This only applies for
+ // DWARF objects compiled with -gmodules that haven't been processed by
+ // dsymutil.
+ UpdateExternalModuleListIfNeeded();
+
+ for (const auto &pair : m_external_type_modules)
+ if (ModuleSP external_module_sp = pair.second)
+ external_module_sp->FindTypes(pattern, languages, searched_symbol_files,
+ types);
}
CompilerDeclContext
@@ -3268,15 +3346,17 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
module, DataExtractor(data, block_offset, block_length),
die.GetCU());
} else {
- DataExtractor data = DebugLocData();
- const dw_offset_t offset = form_value.Unsigned();
+ DataExtractor data = die.GetCU()->GetLocationData();
+ dw_offset_t offset = form_value.Unsigned();
+ if (form_value.Form() == DW_FORM_loclistx)
+ offset = die.GetCU()->GetLoclistOffset(offset).getValueOr(-1);
if (data.ValidOffset(offset)) {
data = DataExtractor(data, offset, data.GetByteSize() - offset);
location = DWARFExpression(module, data, die.GetCU());
assert(func_low_pc != LLDB_INVALID_ADDRESS);
- location.SetLocationListSlide(
- func_low_pc -
- attributes.CompileUnitAtIndex(i)->GetBaseAddress());
+ location.SetLocationListAddresses(
+ attributes.CompileUnitAtIndex(i)->GetBaseAddress(),
+ func_low_pc);
}
}
} break;
@@ -3685,8 +3765,8 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) {
if (child.Tag() != DW_TAG_call_site_parameter)
continue;
- llvm::Optional<DWARFExpression> LocationInCallee = {};
- llvm::Optional<DWARFExpression> LocationInCaller = {};
+ llvm::Optional<DWARFExpression> LocationInCallee;
+ llvm::Optional<DWARFExpression> LocationInCaller;
DWARFAttributes attributes;
const size_t num_attributes = child.GetAttributes(attributes);
@@ -3725,7 +3805,7 @@ CollectCallSiteParameters(ModuleSP module, DWARFDIE call_site_die) {
}
/// Collect call graph edges present in a function DIE.
-static std::vector<lldb_private::CallEdge>
+static std::vector<std::unique_ptr<lldb_private::CallEdge>>
CollectCallEdges(ModuleSP module, DWARFDIE function_die) {
// Check if the function has a supported call site-related attribute.
// TODO: In the future it may be worthwhile to support call_all_source_calls.
@@ -3743,32 +3823,87 @@ CollectCallEdges(ModuleSP module, DWARFDIE function_die) {
// to be DWARF5-compliant. This may need to be done lazily to be performant.
// For now, assume that all entries are nested directly under the subprogram
// (this is the kind of DWARF LLVM produces) and parse them eagerly.
- std::vector<CallEdge> call_edges;
+ std::vector<std::unique_ptr<CallEdge>> call_edges;
for (DWARFDIE child = function_die.GetFirstChild(); child.IsValid();
child = child.GetSibling()) {
if (child.Tag() != DW_TAG_call_site)
continue;
- // Extract DW_AT_call_origin (the call target's DIE).
- DWARFDIE call_origin = child.GetReferencedDIE(DW_AT_call_origin);
- if (!call_origin.IsValid()) {
- LLDB_LOG(log, "CollectCallEdges: Invalid call origin in {0}",
- function_die.GetPubname());
+ llvm::Optional<DWARFDIE> call_origin;
+ llvm::Optional<DWARFExpression> call_target;
+ addr_t return_pc = LLDB_INVALID_ADDRESS;
+
+ DWARFAttributes attributes;
+ const size_t num_attributes = child.GetAttributes(attributes);
+ for (size_t i = 0; i < num_attributes; ++i) {
+ DWARFFormValue form_value;
+ if (!attributes.ExtractFormValueAtIndex(i, form_value)) {
+ LLDB_LOG(log, "CollectCallEdges: Could not extract TAG_call_site form");
+ break;
+ }
+
+ dw_attr_t attr = attributes.AttributeAtIndex(i);
+
+ // Extract DW_AT_call_origin (the call target's DIE).
+ if (attr == DW_AT_call_origin) {
+ call_origin = form_value.Reference();
+ if (!call_origin->IsValid()) {
+ LLDB_LOG(log, "CollectCallEdges: Invalid call origin in {0}",
+ function_die.GetPubname());
+ break;
+ }
+ }
+
+ // Extract DW_AT_call_return_pc (the PC the call returns to) if it's
+ // available. It should only ever be unavailable for tail call edges, in
+ // which case use LLDB_INVALID_ADDRESS.
+ if (attr == DW_AT_call_return_pc)
+ return_pc = form_value.Address();
+
+ // Extract DW_AT_call_target (the location of the address of the indirect
+ // call).
+ if (attr == DW_AT_call_target) {
+ if (!DWARFFormValue::IsBlockForm(form_value.Form())) {
+ LLDB_LOG(log,
+ "CollectCallEdges: AT_call_target does not have block form");
+ break;
+ }
+
+ auto data = child.GetData();
+ uint32_t block_offset = form_value.BlockData() - data.GetDataStart();
+ uint32_t block_length = form_value.Unsigned();
+ call_target = DWARFExpression(
+ module, DataExtractor(data, block_offset, block_length),
+ child.GetCU());
+ }
+ }
+ if (!call_origin && !call_target) {
+ LLDB_LOG(log, "CollectCallEdges: call site without any call target");
continue;
}
- // Extract DW_AT_call_return_pc (the PC the call returns to) if it's
- // available. It should only ever be unavailable for tail call edges, in
- // which case use LLDB_INVALID_ADDRESS.
- addr_t return_pc = child.GetAttributeValueAsAddress(DW_AT_call_return_pc,
- LLDB_INVALID_ADDRESS);
-
// Extract call site parameters.
CallSiteParameterArray parameters =
CollectCallSiteParameters(module, child);
- LLDB_LOG(log, "CollectCallEdges: Found call origin: {0} (retn-PC: {1:x})",
- call_origin.GetPubname(), return_pc);
+ std::unique_ptr<CallEdge> edge;
+ if (call_origin) {
+ LLDB_LOG(log, "CollectCallEdges: Found call origin: {0} (retn-PC: {1:x})",
+ call_origin->GetPubname(), return_pc);
+ edge = std::make_unique<DirectCallEdge>(call_origin->GetMangledName(),
+ return_pc, std::move(parameters));
+ } else {
+ if (log) {
+ StreamString call_target_desc;
+ call_target->GetDescription(&call_target_desc, eDescriptionLevelBrief,
+ LLDB_INVALID_ADDRESS, nullptr);
+ LLDB_LOG(log, "CollectCallEdges: Found indirect call target: {0}",
+ call_target_desc.GetString());
+ }
+ edge = std::make_unique<IndirectCallEdge>(*call_target, return_pc,
+ std::move(parameters));
+ }
+
if (log && parameters.size()) {
for (const CallSiteParameter &param : parameters) {
StreamString callee_loc_desc, caller_loc_desc;
@@ -3783,13 +3918,12 @@ CollectCallEdges(ModuleSP module, DWARFDIE function_die) {
}
}
- call_edges.emplace_back(call_origin.GetMangledName(), return_pc,
- std::move(parameters));
+ call_edges.push_back(std::move(edge));
}
return call_edges;
}
-std::vector<lldb_private::CallEdge>
+std::vector<std::unique_ptr<lldb_private::CallEdge>>
SymbolFileDWARF::ParseCallEdgesInFunction(UserID func_id) {
DWARFDIE func_die = GetDIE(func_id.GetID());
if (func_die.IsValid())
@@ -3829,13 +3963,6 @@ SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() {
return m_debug_map_symfile;
}
-DWARFExpression::LocationListFormat
-SymbolFileDWARF::GetLocationListFormat() const {
- if (m_data_debug_loclists.m_data.GetByteSize() > 0)
- return DWARFExpression::LocLists;
- return DWARFExpression::RegularLocationList;
-}
-
SymbolFileDWARFDwp *SymbolFileDWARF::GetDwpSymbolFile() {
llvm::call_once(m_dwp_symfile_once_flag, [this]() {
ModuleSpec module_spec;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 04cb11d426be..23e26732453f 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -21,7 +21,6 @@
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/Core/dwarf.h"
-#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Symbol/DebugMacros.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolFile.h"
@@ -47,7 +46,6 @@ class DWARFDebugInfo;
class DWARFDebugInfoEntry;
class DWARFDebugLine;
class DWARFDebugRanges;
-class DWARFDebugRngLists;
class DWARFDeclContext;
class DWARFFormValue;
class DWARFTypeUnit;
@@ -59,7 +57,18 @@ class SymbolFileDWARFDwp;
class SymbolFileDWARF : public lldb_private::SymbolFile,
public lldb_private::UserID {
+ /// LLVM RTTI support.
+ static char ID;
+
public:
+ /// LLVM RTTI support.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || SymbolFile::isA(ClassID);
+ }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
+
friend class SymbolFileDWARFDebugMap;
friend class SymbolFileDWARFDwo;
friend class DebugMapModule;
@@ -105,9 +114,9 @@ public:
bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override;
- void
- ForEachExternalModule(lldb_private::CompileUnit &comp_unit,
- llvm::function_ref<void(lldb::ModuleSP)> f) override;
+ bool ForEachExternalModule(
+ lldb_private::CompileUnit &, llvm::DenseSet<lldb_private::SymbolFile *> &,
+ llvm::function_ref<bool(lldb_private::Module &)>) override;
bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit,
lldb_private::FileSpecList &support_files) override;
@@ -190,6 +199,7 @@ public:
void FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern,
lldb_private::LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files,
lldb_private::TypeMap &types) override;
void GetTypes(lldb_private::SymbolContextScope *sc_scope,
@@ -212,9 +222,6 @@ public:
uint32_t GetPluginVersion() override;
- const lldb_private::DWARFDataExtractor &get_debug_loc_data();
- const lldb_private::DWARFDataExtractor &get_debug_loclists_data();
-
DWARFDebugAbbrev *DebugAbbrev();
const DWARFDebugAbbrev *DebugAbbrev() const;
@@ -224,9 +231,6 @@ public:
const DWARFDebugInfo *DebugInfo() const;
DWARFDebugRanges *GetDebugRanges();
- DWARFDebugRngLists *GetDebugRngLists();
-
- const lldb_private::DWARFDataExtractor &DebugLocData();
static bool SupportedVersion(uint16_t version);
@@ -250,10 +254,7 @@ public:
virtual lldb::CompUnitSP ParseCompileUnit(DWARFCompileUnit &dwarf_cu);
- virtual lldb_private::DWARFExpression::LocationListFormat
- GetLocationListFormat() const;
-
- lldb::ModuleSP GetDWOModule(lldb_private::ConstString name);
+ lldb::ModuleSP GetExternalModule(lldb_private::ConstString name);
typedef std::map<lldb_private::ConstString, lldb::ModuleSP>
ExternalTypeModuleMap;
@@ -277,7 +278,7 @@ public:
lldb::user_id_t GetUID(DIERef ref);
- virtual std::unique_ptr<SymbolFileDWARFDwo>
+ std::unique_ptr<SymbolFileDWARFDwo>
GetDwoSymbolFileForCompileUnit(DWARFUnit &dwarf_cu,
const DWARFDebugInfoEntry &cu_die);
@@ -288,11 +289,14 @@ public:
virtual llvm::Optional<uint32_t> GetDwoNum() { return llvm::None; }
+ /// If this is a DWARF object with a single CU, return its DW_AT_dwo_id.
+ llvm::Optional<uint64_t> GetDWOId();
+
static bool
DIEInDeclContext(const lldb_private::CompilerDeclContext *parent_decl_ctx,
const DWARFDIE &die);
- std::vector<lldb_private::CallEdge>
+ std::vector<std::unique_ptr<lldb_private::CallEdge>>
ParseCallEdgesInFunction(UserID func_id) override;
void Dump(lldb_private::Stream &s) override;
@@ -484,7 +488,6 @@ protected:
typedef llvm::StringMap<DIERefSet> NameToOffsetMap;
NameToOffsetMap m_function_scope_qualified_name_map;
std::unique_ptr<DWARFDebugRanges> m_ranges;
- std::unique_ptr<DWARFDebugRngLists> m_rnglists;
UniqueDWARFASTTypeMap m_unique_ast_type_map;
DIEToTypePtr m_die_to_type;
DIEToVariableSP m_die_to_variable_sp;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index a50d4e460bae..cce666a222d0 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -39,6 +39,8 @@
using namespace lldb;
using namespace lldb_private;
+char SymbolFileDWARFDebugMap::ID;
+
// Subclass lldb_private::Module so we can intercept the
// "Module::GetObjectFile()" (so we can fixup the object file sections) and
// also for "Module::GetSymbolFile()" (so we can fixup the symbol file id.
@@ -602,7 +604,7 @@ SymbolFileDWARFDebugMap::CompileUnitInfo *
SymbolFileDWARFDebugMap::GetCompUnitInfo(const CompileUnit &comp_unit) {
const uint32_t cu_count = GetNumCompileUnits();
for (uint32_t i = 0; i < cu_count; ++i) {
- if (comp_unit == m_compile_unit_infos[i].compile_unit_sp.get())
+ if (&comp_unit == m_compile_unit_infos[i].compile_unit_sp.get())
return &m_compile_unit_infos[i];
}
return nullptr;
@@ -652,12 +654,15 @@ bool SymbolFileDWARFDebugMap::ParseDebugMacros(CompileUnit &comp_unit) {
return false;
}
-void SymbolFileDWARFDebugMap::ForEachExternalModule(
- CompileUnit &comp_unit, llvm::function_ref<void(ModuleSP)> f) {
+bool SymbolFileDWARFDebugMap::ForEachExternalModule(
+ CompileUnit &comp_unit,
+ llvm::DenseSet<lldb_private::SymbolFile *> &visited_symbol_files,
+ llvm::function_ref<bool(Module &)> f) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
if (oso_dwarf)
- oso_dwarf->ForEachExternalModule(comp_unit, f);
+ return oso_dwarf->ForEachExternalModule(comp_unit, visited_symbol_files, f);
+ return false;
}
bool SymbolFileDWARFDebugMap::ParseSupportFiles(CompileUnit &comp_unit,
@@ -807,12 +812,8 @@ uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext(
if (!resolve) {
FileSpec so_file_spec;
- if (GetFileSpecForSO(i, so_file_spec)) {
- // Match the full path if the incoming file_spec has a directory (not
- // just a basename)
- const bool full_match = (bool)file_spec.GetDirectory();
- resolve = FileSpec::Equal(file_spec, so_file_spec, full_match);
- }
+ if (GetFileSpecForSO(i, so_file_spec))
+ resolve = FileSpec::Match(file_spec, so_file_spec);
}
if (resolve) {
SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(i);
@@ -1071,7 +1072,7 @@ void SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope,
}
}
-std::vector<lldb_private::CallEdge>
+std::vector<std::unique_ptr<lldb_private::CallEdge>>
SymbolFileDWARFDebugMap::ParseCallEdgesInFunction(UserID func_id) {
uint32_t oso_idx = GetOSOIndexFromUserID(func_id.GetID());
SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
@@ -1183,6 +1184,16 @@ void SymbolFileDWARFDebugMap::FindTypes(
});
}
+void SymbolFileDWARFDebugMap::FindTypes(
+ llvm::ArrayRef<CompilerContext> context, LanguageSet languages,
+ llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
+ TypeMap &types) {
+ ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
+ oso_dwarf->FindTypes(context, languages, searched_symbol_files, types);
+ return false;
+ });
+}
+
//
// uint32_t
// SymbolFileDWARFDebugMap::FindTypes (const SymbolContext& sc, const
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
index 7adee1b356ce..035a902498be 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -23,7 +23,18 @@ class DWARFDebugAranges;
class DWARFDeclContext;
class SymbolFileDWARFDebugMap : public lldb_private::SymbolFile {
+ /// LLVM RTTI support.
+ static char ID;
+
public:
+ /// LLVM RTTI support.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || SymbolFile::isA(ClassID);
+ }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
+
// Static Functions
static void Initialize();
@@ -53,9 +64,9 @@ public:
bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override;
- void
- ForEachExternalModule(lldb_private::CompileUnit &comp_unit,
- llvm::function_ref<void(lldb::ModuleSP)> f) override;
+ bool ForEachExternalModule(
+ lldb_private::CompileUnit &, llvm::DenseSet<lldb_private::SymbolFile *> &,
+ llvm::function_ref<bool(lldb_private::Module &)>) override;
bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit,
lldb_private::FileSpecList &support_files) override;
@@ -114,13 +125,18 @@ public:
uint32_t max_matches,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
lldb_private::TypeMap &types) override;
+ void
+ FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> context,
+ lldb_private::LanguageSet languages,
+ llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
+ lldb_private::TypeMap &types) override;
lldb_private::CompilerDeclContext FindNamespace(
lldb_private::ConstString name,
const lldb_private::CompilerDeclContext *parent_decl_ctx) override;
void GetTypes(lldb_private::SymbolContextScope *sc_scope,
lldb::TypeClass type_mask,
lldb_private::TypeList &type_list) override;
- std::vector<lldb_private::CallEdge>
+ std::vector<std::unique_ptr<lldb_private::CallEdge>>
ParseCallEdgesInFunction(lldb_private::UserID func_id) override;
void DumpClangAST(lldb_private::Stream &s) override;
@@ -348,8 +364,8 @@ protected:
/// \param[in] oso_symfile
/// The DWARF symbol file that produced the \a line_table
///
- /// \param[in] addr
- /// A section offset address from a .o file
+ /// \param[in] line_table
+ /// A pointer to the line table.
///
/// \return
/// Returns a valid line table full of linked addresses, or NULL
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
index b0f7e813d4f8..f75f06f31e2d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
@@ -21,6 +21,8 @@
using namespace lldb;
using namespace lldb_private;
+char SymbolFileDWARFDwo::ID;
+
SymbolFileDWARFDwo::SymbolFileDWARFDwo(ObjectFileSP objfile,
DWARFCompileUnit &dwarf_cu)
: SymbolFileDWARF(objfile, objfile->GetSectionList(
@@ -135,11 +137,6 @@ SymbolFileDWARF &SymbolFileDWARFDwo::GetBaseSymbolFile() {
return m_base_dwarf_cu.GetSymbolFileDWARF();
}
-DWARFExpression::LocationListFormat
-SymbolFileDWARFDwo::GetLocationListFormat() const {
- return DWARFExpression::SplitDwarfLocationList;
-}
-
llvm::Expected<TypeSystem &>
SymbolFileDWARFDwo::GetTypeSystemForLanguage(LanguageType language) {
return GetBaseSymbolFile().GetTypeSystemForLanguage(language);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
index ad290cdcf65e..0855dba044e4 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
@@ -12,7 +12,18 @@
#include "SymbolFileDWARF.h"
class SymbolFileDWARFDwo : public SymbolFileDWARF {
+ /// LLVM RTTI support.
+ static char ID;
+
public:
+ /// LLVM RTTI support.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || SymbolFileDWARF::isA(ClassID);
+ }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
+
SymbolFileDWARFDwo(lldb::ObjectFileSP objfile, DWARFCompileUnit &dwarf_cu);
~SymbolFileDWARFDwo() override = default;
@@ -24,9 +35,6 @@ public:
DWARFUnit *
GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) override;
- lldb_private::DWARFExpression::LocationListFormat
- GetLocationListFormat() const override;
-
size_t GetObjCMethodDIEOffsets(lldb_private::ConstString class_name,
DIEArray &method_die_offsets) override;
@@ -36,12 +44,6 @@ public:
DWARFDIE
GetDIE(const DIERef &die_ref) override;
- std::unique_ptr<SymbolFileDWARFDwo>
- GetDwoSymbolFileForCompileUnit(DWARFUnit &dwarf_cu,
- const DWARFDebugInfoEntry &cu_die) override {
- return nullptr;
- }
-
DWARFCompileUnit *GetBaseCompileUnit() override { return &m_base_dwarf_cu; }
llvm::Optional<uint32_t> GetDwoNum() override { return GetID() >> 32; }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp
index efea192b17ce..4288dcb5c9bd 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.cpp
@@ -19,6 +19,8 @@
using namespace lldb;
using namespace lldb_private;
+char SymbolFileDWARFDwoDwp::ID;
+
SymbolFileDWARFDwoDwp::SymbolFileDWARFDwoDwp(SymbolFileDWARFDwp *dwp_symfile,
ObjectFileSP objfile,
DWARFCompileUnit &dwarf_cu,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h
index 2105e1a8f6cb..a55795ba5950 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h
@@ -13,7 +13,17 @@
#include "SymbolFileDWARFDwp.h"
class SymbolFileDWARFDwoDwp : public SymbolFileDWARFDwo {
+ /// LLVM RTTI support.
+ static char ID;
+
public:
+ /// LLVM RTTI support.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || SymbolFileDWARFDwo::isA(ClassID);
+ }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
SymbolFileDWARFDwoDwp(SymbolFileDWARFDwp *dwp_symfile,
lldb::ObjectFileSP objfile, DWARFCompileUnit &dwarf_cu,
uint64_t dwo_id);
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
index 986b0b785d87..4588c80aa1b1 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -17,7 +17,7 @@
#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/ClangASTMetadata.h"
#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/LLDBAssert.h"
@@ -655,7 +655,7 @@ bool PdbAstBuilder::CompleteTagDecl(clang::TagDecl &tag) {
lldbassert(IsTagRecord(type_id, m_index.tpi()));
- clang::QualType tag_qt = m_clang.getASTContext()->getTypeDeclType(&tag);
+ clang::QualType tag_qt = m_clang.getASTContext().getTypeDeclType(&tag);
ClangASTContext::SetHasExternalStorage(tag_qt.getAsOpaquePtr(), false);
TypeIndex tag_ti = type_id.index;
@@ -700,7 +700,7 @@ clang::QualType PdbAstBuilder::CreateSimpleType(TypeIndex ti) {
if (ti.getSimpleMode() != SimpleTypeMode::Direct) {
clang::QualType direct_type = GetOrCreateType(ti.makeDirect());
- return m_clang.getASTContext()->getPointerType(direct_type);
+ return m_clang.getASTContext().getPointerType(direct_type);
}
if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated)
@@ -725,19 +725,17 @@ clang::QualType PdbAstBuilder::CreatePointerType(const PointerRecord &pointer) {
MemberPointerInfo mpi = pointer.getMemberInfo();
clang::QualType class_type = GetOrCreateType(mpi.ContainingType);
- return m_clang.getASTContext()->getMemberPointerType(
+ return m_clang.getASTContext().getMemberPointerType(
pointee_type, class_type.getTypePtr());
}
clang::QualType pointer_type;
if (pointer.getMode() == PointerMode::LValueReference)
- pointer_type =
- m_clang.getASTContext()->getLValueReferenceType(pointee_type);
+ pointer_type = m_clang.getASTContext().getLValueReferenceType(pointee_type);
else if (pointer.getMode() == PointerMode::RValueReference)
- pointer_type =
- m_clang.getASTContext()->getRValueReferenceType(pointee_type);
+ pointer_type = m_clang.getASTContext().getRValueReferenceType(pointee_type);
else
- pointer_type = m_clang.getASTContext()->getPointerType(pointee_type);
+ pointer_type = m_clang.getASTContext().getPointerType(pointee_type);
if ((pointer.getOptions() & PointerOptions::Const) != PointerOptions::None)
pointer_type.addConst();
@@ -778,9 +776,8 @@ clang::QualType PdbAstBuilder::CreateRecordType(PdbTypeSymId id,
metadata.SetUserID(toOpaqueUid(id));
metadata.SetIsDynamicCXXType(false);
- CompilerType ct =
- m_clang.CreateRecordType(context, access, uname.c_str(), ttk,
- lldb::eLanguageTypeC_plus_plus, &metadata);
+ CompilerType ct = m_clang.CreateRecordType(
+ context, access, uname, ttk, lldb::eLanguageTypeC_plus_plus, &metadata);
lldbassert(ct.IsValid());
@@ -1081,7 +1078,7 @@ void PdbAstBuilder::CreateFunctionParameters(PdbCompilandSymId func_id,
PdbCompilandSymId param_uid(func_id.modi, record_offset);
clang::QualType qt = GetOrCreateType(param_type);
- CompilerType param_type_ct(&m_clang, qt.getAsOpaquePtr());
+ CompilerType param_type_ct = m_clang.GetType(qt);
clang::ParmVarDecl *param = m_clang.CreateParameterDeclaration(
&function_decl, param_name.str().c_str(), param_type_ct,
clang::SC_None, true);
@@ -1346,7 +1343,7 @@ CompilerType PdbAstBuilder::ToCompilerType(clang::QualType qt) {
CompilerDeclContext
PdbAstBuilder::ToCompilerDeclContext(clang::DeclContext &context) {
- return {&m_clang, &context};
+ return m_clang.CreateDeclContext(&context);
}
clang::Decl * PdbAstBuilder::FromCompilerDecl(CompilerDecl decl) {
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 33b8da3b543b..370c339fb74b 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -20,7 +20,6 @@
#include "lldb/Core/StreamBuffer.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/LineTable.h"
@@ -67,6 +66,8 @@ using namespace npdb;
using namespace llvm::codeview;
using namespace llvm::pdb;
+char SymbolFileNativePDB::ID;
+
static lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
switch (lang) {
case PDB_Lang::Cpp:
@@ -460,7 +461,7 @@ lldb::TypeSP SymbolFileNativePDB::CreateModifierType(PdbTypeSymId type_id,
return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(name),
modified_type->GetByteSize(), nullptr,
LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
- ct, Type::eResolveStateFull);
+ ct, Type::ResolveState::Full);
}
lldb::TypeSP
@@ -480,7 +481,7 @@ SymbolFileNativePDB::CreatePointerType(PdbTypeSymId type_id,
return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(),
pr.getSize(), nullptr, LLDB_INVALID_UID,
Type::eEncodingIsUID, decl, ct,
- Type::eResolveStateFull);
+ Type::ResolveState::Full);
}
lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
@@ -490,7 +491,7 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
Declaration decl;
return std::make_shared<Type>(
uid, this, ConstString("std::nullptr_t"), 0, nullptr, LLDB_INVALID_UID,
- Type::eEncodingIsUID, decl, ct, Type::eResolveStateFull);
+ Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);
}
if (ti.getSimpleMode() != SimpleTypeMode::Direct) {
@@ -511,7 +512,7 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
Declaration decl;
return std::make_shared<Type>(
uid, this, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID,
- Type::eEncodingIsUID, decl, ct, Type::eResolveStateFull);
+ Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full);
}
if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated)
@@ -523,7 +524,7 @@ lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
Declaration decl;
return std::make_shared<Type>(uid, this, ConstString(type_name), size,
nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID,
- decl, ct, Type::eResolveStateFull);
+ decl, ct, Type::ResolveState::Full);
}
static std::string GetUnqualifiedTypeName(const TagRecord &record) {
@@ -557,7 +558,7 @@ SymbolFileNativePDB::CreateClassStructUnion(PdbTypeSymId type_id,
return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(uname),
size, nullptr, LLDB_INVALID_UID,
Type::eEncodingIsUID, decl, ct,
- Type::eResolveStateForward);
+ Type::ResolveState::Forward);
}
lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
@@ -584,7 +585,7 @@ lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
toOpaqueUid(type_id), this, ConstString(uname),
underlying_type->GetByteSize(), nullptr, LLDB_INVALID_UID,
lldb_private::Type::eEncodingIsUID, decl, ct,
- lldb_private::Type::eResolveStateForward);
+ lldb_private::Type::ResolveState::Forward);
}
TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id,
@@ -596,7 +597,7 @@ TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id,
TypeSP array_sp = std::make_shared<lldb_private::Type>(
toOpaqueUid(type_id), this, ConstString(), ar.Size, nullptr,
LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct,
- lldb_private::Type::eResolveStateFull);
+ lldb_private::Type::ResolveState::Full);
array_sp->SetEncodingType(element_type.get());
return array_sp;
}
@@ -609,7 +610,7 @@ TypeSP SymbolFileNativePDB::CreateFunctionType(PdbTypeSymId type_id,
return std::make_shared<lldb_private::Type>(
toOpaqueUid(type_id), this, ConstString(), 0, nullptr, LLDB_INVALID_UID,
lldb_private::Type::eEncodingIsUID, decl, ct,
- lldb_private::Type::eResolveStateFull);
+ lldb_private::Type::ResolveState::Full);
}
TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id,
@@ -619,7 +620,7 @@ TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id,
return std::make_shared<lldb_private::Type>(
toOpaqueUid(type_id), this, ConstString(), 0, nullptr, LLDB_INVALID_UID,
lldb_private::Type::eEncodingIsUID, decl, ct,
- lldb_private::Type::eResolveStateFull);
+ lldb_private::Type::ResolveState::Full);
}
TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) {
@@ -1108,9 +1109,7 @@ bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) {
// LLDB wants the index of the file in the list of support files.
auto fn_iter = llvm::find(cci->m_file_list, *efn);
lldbassert(fn_iter != cci->m_file_list.end());
- // LLDB support file indices are 1-based.
- uint32_t file_index =
- 1 + std::distance(cci->m_file_list.begin(), fn_iter);
+ uint32_t file_index = std::distance(cci->m_file_list.begin(), fn_iter);
std::unique_ptr<LineSequence> sequence(
line_table->CreateLineSequenceContainer());
@@ -1153,14 +1152,6 @@ bool SymbolFileNativePDB::ParseSupportFiles(CompileUnit &comp_unit,
FileSpec spec(f, style);
support_files.Append(spec);
}
-
- llvm::SmallString<64> main_source_file =
- m_index->compilands().GetMainSourceFile(*cci);
- FileSpec::Style style = main_source_file.startswith("/")
- ? FileSpec::Style::posix
- : FileSpec::Style::windows;
- FileSpec spec(main_source_file, style);
- support_files.Insert(0, spec);
return true;
}
@@ -1259,8 +1250,9 @@ void SymbolFileNativePDB::FindTypes(
FindTypesByName(name.GetStringRef(), max_matches, types);
}
-void SymbolFileNativePDB::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
- LanguageSet languages, TypeMap &types) {}
+void SymbolFileNativePDB::FindTypes(
+ llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {}
void SymbolFileNativePDB::FindTypesByName(llvm::StringRef name,
uint32_t max_matches,
@@ -1386,7 +1378,7 @@ TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) {
toOpaqueUid(id), this, ConstString(udt.Name), target_type->GetByteSize(),
nullptr, target_type->GetID(), lldb_private::Type::eEncodingIsTypedefUID,
decl, target_type->GetForwardCompilerType(),
- lldb_private::Type::eResolveStateForward);
+ lldb_private::Type::ResolveState::Forward);
}
TypeSP SymbolFileNativePDB::GetOrCreateTypedef(PdbGlobalSymId id) {
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
index ca7de0e7d1ed..a37de0f58ef3 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -41,7 +41,18 @@ class PdbAstBuilder;
class SymbolFileNativePDB : public SymbolFile {
friend class UdtRecordCompleter;
+ /// LLVM RTTI support.
+ static char ID;
+
public:
+ /// LLVM RTTI support.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || SymbolFile::isA(ClassID);
+ }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
+
// Static Functions
static void Initialize();
@@ -131,6 +142,7 @@ public:
TypeMap &types) override;
void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files,
TypeMap &types) override;
llvm::Expected<TypeSystem &>
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
index 3c494dc83986..7221144407c1 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
@@ -231,6 +231,6 @@ void UdtRecordCompleter::complete() {
ClangASTContext::CompleteTagDeclarationDefinition(m_derived_ct);
if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) {
- m_ast_builder.importer().InsertRecordDecl(record_decl, m_layout);
+ m_ast_builder.importer().SetRecordLayout(record_decl, m_layout);
}
}
diff --git a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
index 47c4ad088494..6b2dbd9e1e5a 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
+++ b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
@@ -16,7 +16,7 @@
#include "lldb/Core/Module.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/ClangASTMetadata.h"
#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Symbol/Declaration.h"
#include "lldb/Symbol/SymbolFile.h"
@@ -103,9 +103,7 @@ static CompilerType
GetBuiltinTypeForPDBEncodingAndBitSize(ClangASTContext &clang_ast,
const PDBSymbolTypeBuiltin &pdb_type,
Encoding encoding, uint32_t width) {
- auto *ast = clang_ast.getASTContext();
- if (!ast)
- return CompilerType();
+ clang::ASTContext &ast = clang_ast.getASTContext();
switch (pdb_type.getBuiltinType()) {
default:
@@ -119,32 +117,25 @@ GetBuiltinTypeForPDBEncodingAndBitSize(ClangASTContext &clang_ast,
case PDB_BuiltinType::Bool:
return clang_ast.GetBasicType(eBasicTypeBool);
case PDB_BuiltinType::Long:
- if (width == ast->getTypeSize(ast->LongTy))
- return CompilerType(ClangASTContext::GetASTContext(ast),
- ast->LongTy.getAsOpaquePtr());
- if (width == ast->getTypeSize(ast->LongLongTy))
- return CompilerType(ClangASTContext::GetASTContext(ast),
- ast->LongLongTy.getAsOpaquePtr());
+ if (width == ast.getTypeSize(ast.LongTy))
+ return CompilerType(&clang_ast, ast.LongTy.getAsOpaquePtr());
+ if (width == ast.getTypeSize(ast.LongLongTy))
+ return CompilerType(&clang_ast, ast.LongLongTy.getAsOpaquePtr());
break;
case PDB_BuiltinType::ULong:
- if (width == ast->getTypeSize(ast->UnsignedLongTy))
- return CompilerType(ClangASTContext::GetASTContext(ast),
- ast->UnsignedLongTy.getAsOpaquePtr());
- if (width == ast->getTypeSize(ast->UnsignedLongLongTy))
- return CompilerType(ClangASTContext::GetASTContext(ast),
- ast->UnsignedLongLongTy.getAsOpaquePtr());
+ if (width == ast.getTypeSize(ast.UnsignedLongTy))
+ return CompilerType(&clang_ast, ast.UnsignedLongTy.getAsOpaquePtr());
+ if (width == ast.getTypeSize(ast.UnsignedLongLongTy))
+ return CompilerType(&clang_ast, ast.UnsignedLongLongTy.getAsOpaquePtr());
break;
case PDB_BuiltinType::WCharT:
- if (width == ast->getTypeSize(ast->WCharTy))
- return CompilerType(ClangASTContext::GetASTContext(ast),
- ast->WCharTy.getAsOpaquePtr());
+ if (width == ast.getTypeSize(ast.WCharTy))
+ return CompilerType(&clang_ast, ast.WCharTy.getAsOpaquePtr());
break;
case PDB_BuiltinType::Char16:
- return CompilerType(ClangASTContext::GetASTContext(ast),
- ast->Char16Ty.getAsOpaquePtr());
+ return CompilerType(&clang_ast, ast.Char16Ty.getAsOpaquePtr());
case PDB_BuiltinType::Char32:
- return CompilerType(ClangASTContext::GetASTContext(ast),
- ast->Char32Ty.getAsOpaquePtr());
+ return CompilerType(&clang_ast, ast.Char32Ty.getAsOpaquePtr());
case PDB_BuiltinType::Float:
// Note: types `long double` and `double` have same bit size in MSVC and
// there is no information in the PDB to distinguish them. So when falling
@@ -405,7 +396,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
// This may occur with const or volatile types. There are separate type
// symbols in PDB for types with const or volatile modifiers, but we need
// to create only one declaration for them all.
- Type::ResolveStateTag type_resolve_state_tag;
+ Type::ResolveState type_resolve_state;
CompilerType clang_type = m_ast.GetTypeForIdentifier<clang::CXXRecordDecl>(
ConstString(name), decl_context);
if (!clang_type.IsValid()) {
@@ -417,9 +408,9 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
metadata.SetUserID(type.getSymIndexId());
metadata.SetIsDynamicCXXType(false);
- clang_type = m_ast.CreateRecordType(
- decl_context, access, name.c_str(), tag_type_kind,
- lldb::eLanguageTypeC_plus_plus, &metadata);
+ clang_type =
+ m_ast.CreateRecordType(decl_context, access, name, tag_type_kind,
+ lldb::eLanguageTypeC_plus_plus, &metadata);
assert(clang_type.IsValid());
auto record_decl =
@@ -428,7 +419,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
m_uid_to_decl[type.getSymIndexId()] = record_decl;
auto inheritance_attr = clang::MSInheritanceAttr::CreateImplicit(
- *m_ast.getASTContext(), GetMSInheritance(*udt));
+ m_ast.getASTContext(), GetMSInheritance(*udt));
record_decl->addAttr(inheritance_attr);
ClangASTContext::StartTagDeclarationDefinition(clang_type);
@@ -442,7 +433,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
ClangASTContext::SetHasExternalStorage(clang_type.GetOpaqueQualType(),
false);
- type_resolve_state_tag = Type::eResolveStateFull;
+ type_resolve_state = Type::ResolveState::Full;
} else {
// Add the type to the forward declarations. It will help us to avoid
// an endless recursion in CompleteTypeFromUdt function.
@@ -451,10 +442,10 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
ClangASTContext::SetHasExternalStorage(clang_type.GetOpaqueQualType(),
true);
- type_resolve_state_tag = Type::eResolveStateForward;
+ type_resolve_state = Type::ResolveState::Forward;
}
} else
- type_resolve_state_tag = Type::eResolveStateForward;
+ type_resolve_state = Type::ResolveState::Forward;
if (udt->isConstType())
clang_type = clang_type.AddConstModifier();
@@ -467,7 +458,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name),
udt->getLength(), nullptr, LLDB_INVALID_UID,
lldb_private::Type::eEncodingIsUID, decl, clang_type,
- type_resolve_state_tag);
+ type_resolve_state);
} break;
case PDB_SymType::Enum: {
auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(&type);
@@ -535,7 +526,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
return std::make_shared<lldb_private::Type>(
type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), bytes,
nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
- ast_enum, lldb_private::Type::eResolveStateFull);
+ ast_enum, lldb_private::Type::ResolveState::Full);
} break;
case PDB_SymType::Typedef: {
auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type);
@@ -558,7 +549,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
CompilerType target_ast_type = target_type->GetFullCompilerType();
ast_typedef = m_ast.CreateTypedefType(
- target_ast_type, name.c_str(), CompilerDeclContext(&m_ast, decl_ctx));
+ target_ast_type, name.c_str(), m_ast.CreateDeclContext(decl_ctx));
if (!ast_typedef)
return nullptr;
@@ -581,7 +572,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
type_def->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name),
size, nullptr, target_type->GetID(),
lldb_private::Type::eEncodingIsTypedefUID, decl, ast_typedef,
- lldb_private::Type::eResolveStateFull);
+ lldb_private::Type::ResolveState::Full);
} break;
case PDB_SymType::Function:
case PDB_SymType::FunctionSig: {
@@ -649,7 +640,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name),
llvm::None, nullptr, LLDB_INVALID_UID,
lldb_private::Type::eEncodingIsUID, decl, func_sig_ast_type,
- lldb_private::Type::eResolveStateFull);
+ lldb_private::Type::ResolveState::Full);
} break;
case PDB_SymType::ArrayType: {
auto array_type = llvm::dyn_cast<PDBSymbolTypeArray>(&type);
@@ -683,7 +674,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
TypeSP type_sp = std::make_shared<lldb_private::Type>(
array_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(),
bytes, nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID,
- decl, array_ast_type, lldb_private::Type::eResolveStateFull);
+ decl, array_ast_type, lldb_private::Type::ResolveState::Full);
type_sp->SetEncodingType(element_type);
return type_sp;
} break;
@@ -712,7 +703,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
return std::make_shared<lldb_private::Type>(
builtin_type->getSymIndexId(), m_ast.GetSymbolFile(), type_name, bytes,
nullptr, LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl,
- builtin_ast_type, lldb_private::Type::eResolveStateFull);
+ builtin_ast_type, lldb_private::Type::ResolveState::Full);
} break;
case PDB_SymType::PointerType: {
auto *pointer_type = llvm::dyn_cast<PDBSymbolTypePointer>(&type);
@@ -739,7 +730,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
pointer_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(),
pointer_type->getLength(), nullptr, LLDB_INVALID_UID,
lldb_private::Type::eEncodingIsUID, decl, pointer_ast_type,
- lldb_private::Type::eResolveStateForward);
+ lldb_private::Type::ResolveState::Forward);
}
CompilerType pointer_ast_type;
@@ -764,7 +755,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
pointer_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(),
pointer_type->getLength(), nullptr, LLDB_INVALID_UID,
lldb_private::Type::eEncodingIsUID, decl, pointer_ast_type,
- lldb_private::Type::eResolveStateFull);
+ lldb_private::Type::ResolveState::Full);
} break;
default:
break;
@@ -900,7 +891,7 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) {
// Check if the current context already contains the symbol with the name.
clang::Decl *decl =
- GetDeclFromContextByName(*m_ast.getASTContext(), *decl_context, name);
+ GetDeclFromContextByName(m_ast.getASTContext(), *decl_context, name);
if (!decl) {
auto type = symbol_file->ResolveTypeUID(data->getTypeId());
if (!type)
@@ -1160,7 +1151,7 @@ bool PDBASTParser::AddEnumValue(CompilerType enum_type,
}
CompilerType underlying_type =
m_ast.GetEnumerationIntegerType(enum_type.GetOpaqueQualType());
- uint32_t byte_size = m_ast.getASTContext()->getTypeSize(
+ uint32_t byte_size = m_ast.getASTContext().getTypeSize(
ClangUtil::GetQualType(underlying_type));
auto enum_constant_decl = m_ast.AddEnumerationValueToEnumerationType(
enum_type, decl, name.c_str(), raw_value, byte_size * 8);
@@ -1207,7 +1198,7 @@ bool PDBASTParser::CompleteTypeFromUDT(
if (!record_decl)
return static_cast<bool>(compiler_type);
- GetClangASTImporter().InsertRecordDecl(record_decl, layout_info);
+ GetClangASTImporter().SetRecordLayout(record_decl, layout_info);
return static_cast<bool>(compiler_type);
}
diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
index 854e735b5f83..917ab68af418 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -58,6 +58,8 @@ using namespace lldb;
using namespace lldb_private;
using namespace llvm::pdb;
+char SymbolFilePDB::ID;
+
namespace {
lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
switch (lang) {
@@ -369,10 +371,6 @@ bool SymbolFilePDB::ParseSupportFiles(
support_files.AppendIfUnique(spec);
}
- // LLDB uses the DWARF-like file numeration (one based),
- // the zeroth file is the compile unit itself
- support_files.Insert(0, comp_unit);
-
return true;
}
@@ -668,7 +666,7 @@ SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid) {
if (!decl_context)
return GetDeclContextContainingUID(uid);
- return CompilerDeclContext(clang_ast_ctx, decl_context);
+ return clang_ast_ctx->CreateDeclContext(decl_context);
}
lldb_private::CompilerDeclContext
@@ -697,7 +695,7 @@ SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
auto decl_context = pdb->GetDeclContextContainingSymbol(*symbol);
assert(decl_context);
- return CompilerDeclContext(clang_ast_ctx, decl_context);
+ return clang_ast_ctx->CreateDeclContext(decl_context);
}
void SymbolFilePDB::ParseDeclsForContext(
@@ -1562,9 +1560,10 @@ void SymbolFilePDB::FindTypesByName(
}
}
-void SymbolFilePDB::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
- LanguageSet languages,
- lldb_private::TypeMap &types) {}
+void SymbolFilePDB::FindTypes(
+ llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files,
+ lldb_private::TypeMap &types) {}
void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol,
uint32_t type_mask,
@@ -1704,8 +1703,7 @@ lldb_private::CompilerDeclContext SymbolFilePDB::FindNamespace(
if (!namespace_decl)
return CompilerDeclContext();
- return CompilerDeclContext(clang_type_system,
- static_cast<clang::DeclContext *>(namespace_decl));
+ return clang_type_system->CreateDeclContext(namespace_decl);
}
lldb_private::ConstString SymbolFilePDB::GetPluginName() {
@@ -1777,7 +1775,6 @@ bool SymbolFilePDB::ParseCompileUnitLineTable(CompileUnit &comp_unit,
auto line_table = std::make_unique<LineTable>(&comp_unit);
// Find contributions to `compiland` from all source and header files.
- std::string path = comp_unit.GetPath();
auto files = m_session_up->getSourceFilesForCompiland(*compiland_up);
if (!files)
return false;
@@ -1879,9 +1876,7 @@ void SymbolFilePDB::BuildSupportFileIdToSupportFileIndexMap(
if (!source_files)
return;
- // LLDB uses the DWARF-like file numeration (one based)
- int index = 1;
-
+ int index = 0;
while (auto file = source_files->getNext()) {
uint32_t source_id = file->getUniqueId();
index_map[source_id] = index++;
diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
index df717bbbbdb0..7a4eee48771a 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
+++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
@@ -22,7 +22,18 @@
class PDBASTParser;
class SymbolFilePDB : public lldb_private::SymbolFile {
+ /// LLVM RTTI support.
+ static char ID;
+
public:
+ /// LLVM RTTI support.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || SymbolFile::isA(ClassID);
+ }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
+
// Static Functions
static void Initialize();
@@ -134,6 +145,7 @@ public:
void FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern,
lldb_private::LanguageSet languages,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files,
lldb_private::TypeMap &types) override;
void FindTypesByRegex(const lldb_private::RegularExpression &regex,
diff --git a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
index 62da76581c3e..305efea1afab 100644
--- a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
+++ b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
@@ -25,6 +25,8 @@
using namespace lldb;
using namespace lldb_private;
+char SymbolFileSymtab::ID;
+
void SymbolFileSymtab::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
GetPluginDescriptionStatic(), CreateInstance);
diff --git a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
index 2ac4660f0125..1fff8188433e 100644
--- a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
+++ b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
@@ -16,7 +16,18 @@
#include "lldb/Symbol/Symtab.h"
class SymbolFileSymtab : public lldb_private::SymbolFile {
+ /// LLVM RTTI support.
+ static char ID;
+
public:
+ /// LLVM RTTI support.
+ /// \{
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || SymbolFile::isA(ClassID);
+ }
+ static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+ /// \}
+
// Constructors and Destructors
SymbolFileSymtab(lldb::ObjectFileSP objfile_sp);
diff --git a/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
index e61e5763fabb..d4d7a8937c12 100644
--- a/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
+++ b/lldb/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
@@ -119,14 +119,17 @@ SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp,
SectionList *objfile_section_list = dsym_objfile_sp->GetSectionList();
static const SectionType g_sections[] = {
- eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr,
- eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugCuIndex,
- eSectionTypeDWARFDebugFrame, eSectionTypeDWARFDebugInfo,
- eSectionTypeDWARFDebugLine, eSectionTypeDWARFDebugLoc,
- eSectionTypeDWARFDebugMacInfo, eSectionTypeDWARFDebugPubNames,
- eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges,
- eSectionTypeDWARFDebugStr, eSectionTypeDWARFDebugStrOffsets,
- eSectionTypeELFSymbolTable, eSectionTypeDWARFGNUDebugAltLink,
+ eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr,
+ eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugCuIndex,
+ eSectionTypeDWARFDebugFrame, eSectionTypeDWARFDebugInfo,
+ eSectionTypeDWARFDebugLine, eSectionTypeDWARFDebugLineStr,
+ eSectionTypeDWARFDebugLoc, eSectionTypeDWARFDebugLocLists,
+ eSectionTypeDWARFDebugMacInfo, eSectionTypeDWARFDebugMacro,
+ eSectionTypeDWARFDebugNames, eSectionTypeDWARFDebugPubNames,
+ eSectionTypeDWARFDebugPubTypes, eSectionTypeDWARFDebugRanges,
+ eSectionTypeDWARFDebugRngLists, eSectionTypeDWARFDebugStr,
+ eSectionTypeDWARFDebugStrOffsets, eSectionTypeDWARFDebugTypes,
+ eSectionTypeELFSymbolTable, eSectionTypeDWARFGNUDebugAltLink,
};
for (SectionType section_type : g_sections) {
if (SectionSP section_sp =