aboutsummaryrefslogtreecommitdiff
path: root/source/Plugins
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-12-30 11:55:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-12-30 11:55:28 +0000
commite81d9d49145e432d917eea3a70d2ae74dcad1d89 (patch)
tree9ed5e1a91f242e2cb5911577356e487a55c01b78 /source/Plugins
parent85d8ef8f1f0e0e063a8571944302be2d2026f823 (diff)
downloadsrc-e81d9d49145e432d917eea3a70d2ae74dcad1d89.tar.gz
src-e81d9d49145e432d917eea3a70d2ae74dcad1d89.zip
Vendor import of stripped lldb trunk r256633:
Notes
Notes: svn path=/vendor/lldb/dist/; revision=292932
Diffstat (limited to 'source/Plugins')
-rw-r--r--source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp317
-rw-r--r--source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h81
-rw-r--r--source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp170
-rw-r--r--source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h72
-rw-r--r--source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp397
-rw-r--r--source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h84
-rw-r--r--source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp262
-rw-r--r--source/Plugins/ABI/SysV-arm/ABISysV_arm.h16
-rw-r--r--source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp31
-rw-r--r--source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h17
-rw-r--r--source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp38
-rw-r--r--source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h117
-rw-r--r--source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp495
-rw-r--r--source/Plugins/ABI/SysV-i386/ABISysV_i386.h37
-rw-r--r--source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp327
-rw-r--r--source/Plugins/ABI/SysV-mips/ABISysV_mips.h96
-rw-r--r--source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp542
-rw-r--r--source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h88
-rw-r--r--source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp347
-rw-r--r--source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h98
-rw-r--r--source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp348
-rw-r--r--source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h98
-rw-r--r--source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp475
-rw-r--r--source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h88
-rw-r--r--source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp236
-rw-r--r--source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h57
-rw-r--r--source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp37
-rw-r--r--source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h66
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp42
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp63
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h76
-rw-r--r--source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h42
-rw-r--r--source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp42
-rw-r--r--source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h25
-rw-r--r--source/Plugins/ExpressionParser/Clang/ASTDumper.cpp134
-rw-r--r--source/Plugins/ExpressionParser/Clang/ASTDumper.h42
-rw-r--r--source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp514
-rw-r--r--source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h185
-rw-r--r--source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp221
-rw-r--r--source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h158
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp2101
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangASTSource.h526
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp2351
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h714
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h79
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp657
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h136
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp76
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h265
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp221
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h173
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp731
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h128
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp84
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h106
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp673
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangUserExpression.h218
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp189
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h137
-rw-r--r--source/Plugins/ExpressionParser/Clang/IRForTarget.cpp2820
-rw-r--r--source/Plugins/ExpressionParser/Clang/IRForTarget.h745
-rw-r--r--source/Plugins/ExpressionParser/Go/GoAST.h3225
-rw-r--r--source/Plugins/ExpressionParser/Go/GoLexer.cpp402
-rw-r--r--source/Plugins/ExpressionParser/Go/GoLexer.h201
-rw-r--r--source/Plugins/ExpressionParser/Go/GoParser.cpp1035
-rw-r--r--source/Plugins/ExpressionParser/Go/GoParser.h165
-rw-r--r--source/Plugins/ExpressionParser/Go/GoUserExpression.cpp756
-rw-r--r--source/Plugins/ExpressionParser/Go/GoUserExpression.h98
-rw-r--r--source/Plugins/ExpressionParser/Go/gen_go_ast.py356
-rw-r--r--source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp406
-rw-r--r--source/Plugins/Instruction/ARM/EmulateInstructionARM.h48
-rw-r--r--source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp304
-rw-r--r--source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h93
-rw-r--r--source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp1823
-rw-r--r--source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h132
-rw-r--r--source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp1119
-rw-r--r--source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h114
-rw-r--r--source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp74
-rw-r--r--source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h48
-rw-r--r--source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp77
-rw-r--r--source/Plugins/JITLoader/GDB/JITLoaderGDB.h36
-rw-r--r--source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp792
-rw-r--r--source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h186
-rw-r--r--source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp204
-rw-r--r--source/Plugins/Language/CPlusPlus/CxxStringTypes.h41
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxx.cpp653
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxx.h141
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp147
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxList.cpp414
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxMap.cpp478
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp172
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxVector.cpp159
-rw-r--r--source/Plugins/Language/CPlusPlus/LibStdcpp.cpp373
-rw-r--r--source/Plugins/Language/CPlusPlus/LibStdcpp.h33
-rw-r--r--source/Plugins/Language/Go/GoFormatterFunctions.cpp173
-rw-r--r--source/Plugins/Language/Go/GoFormatterFunctions.h43
-rw-r--r--source/Plugins/Language/Go/GoLanguage.cpp146
-rw-r--r--source/Plugins/Language/Go/GoLanguage.h66
-rw-r--r--source/Plugins/Language/ObjC/CF.cpp334
-rw-r--r--source/Plugins/Language/ObjC/CF.h34
-rw-r--r--source/Plugins/Language/ObjC/Cocoa.cpp967
-rw-r--r--source/Plugins/Language/ObjC/Cocoa.h97
-rw-r--r--source/Plugins/Language/ObjC/CoreMedia.cpp89
-rw-r--r--source/Plugins/Language/ObjC/CoreMedia.h26
-rw-r--r--source/Plugins/Language/ObjC/NSArray.cpp792
-rw-r--r--source/Plugins/Language/ObjC/NSDictionary.cpp749
-rw-r--r--source/Plugins/Language/ObjC/NSDictionary.h48
-rw-r--r--source/Plugins/Language/ObjC/NSError.cpp218
-rw-r--r--source/Plugins/Language/ObjC/NSException.cpp219
-rw-r--r--source/Plugins/Language/ObjC/NSIndexPath.cpp349
-rw-r--r--source/Plugins/Language/ObjC/NSSet.cpp758
-rw-r--r--source/Plugins/Language/ObjC/NSSet.h40
-rw-r--r--source/Plugins/Language/ObjC/NSString.cpp405
-rw-r--r--source/Plugins/Language/ObjC/NSString.h42
-rw-r--r--source/Plugins/Language/ObjC/ObjCLanguage.cpp877
-rw-r--r--source/Plugins/Language/ObjC/ObjCLanguage.h210
-rw-r--r--source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp68
-rw-r--r--source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h63
-rw-r--r--source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp49
-rw-r--r--source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h83
-rw-r--r--source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp238
-rw-r--r--source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h93
-rw-r--r--source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp3171
-rw-r--r--source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h229
-rw-r--r--source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp108
-rw-r--r--source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h34
-rw-r--r--source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp10
-rw-r--r--source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h65
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp508
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.h19
-rw-r--r--source/Plugins/ObjectFile/JIT/ObjectFileJIT.h114
-rw-r--r--source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp559
-rw-r--r--source/Plugins/OperatingSystem/Go/OperatingSystemGo.h87
-rw-r--r--source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp5
-rw-r--r--source/Plugins/OperatingSystem/Python/OperatingSystemPython.h60
-rw-r--r--source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h13
-rw-r--r--source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp685
-rw-r--r--source/Plugins/Platform/NetBSD/PlatformNetBSD.h177
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.cpp185
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.h60
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp125
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h33
-rw-r--r--source/Plugins/Process/FreeBSD/FreeBSDThread.cpp623
-rw-r--r--source/Plugins/Process/FreeBSD/FreeBSDThread.h109
-rw-r--r--source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp2
-rw-r--r--source/Plugins/Process/FreeBSD/POSIXStopInfo.h8
-rw-r--r--source/Plugins/Process/FreeBSD/POSIXThread.cpp661
-rw-r--r--source/Plugins/Process/FreeBSD/POSIXThread.h132
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp829
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessFreeBSD.h197
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.cpp6
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.h4
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp939
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessPOSIX.h205
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h (renamed from source/Plugins/Process/Utility/RegisterContextPOSIX.h)0
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp4
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h1
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp6
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h1
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp4
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h1
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp4
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h1
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp35
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h2
-rw-r--r--source/Plugins/Process/POSIX/CrashReason.cpp5
-rw-r--r--source/Plugins/Process/Utility/DynamicRegisterInfo.cpp18
-rw-r--r--source/Plugins/Process/Utility/FreeBSDSignals.cpp132
-rw-r--r--source/Plugins/Process/Utility/HistoryThread.h47
-rw-r--r--source/Plugins/Process/Utility/HistoryUnwind.h20
-rw-r--r--source/Plugins/Process/Utility/InferiorCallPOSIX.cpp15
-rw-r--r--source/Plugins/Process/Utility/LinuxSignals.cpp134
-rw-r--r--source/Plugins/Process/Utility/MipsLinuxSignals.cpp134
-rw-r--r--source/Plugins/Process/Utility/NetBSDSignals.cpp34
-rw-r--r--source/Plugins/Process/Utility/NetBSDSignals.h31
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp184
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_arm.h76
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp114
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h64
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp228
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_i386.h55
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp406
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h52
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDummy.cpp4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDummy.h56
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp1
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h1
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h18
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextHistory.cpp4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextHistory.h55
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.cpp93
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.h58
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp1
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_arm.h1
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_arm64.h1
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp14
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_i386.h8
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp17
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_mips.h5
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp16
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_mips64.h2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp11
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h7
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h57
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMemory.h61
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp48
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h30
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h27
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h27
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h29
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h29
-rw-r--r--source/Plugins/Process/Utility/RegisterContextThreadMemory.h104
-rw-r--r--source/Plugins/Process/Utility/RegisterContext_mips.h663
-rw-r--r--source/Plugins/Process/Utility/RegisterContext_powerpc.h321
-rw-r--r--source/Plugins/Process/Utility/RegisterContext_x86.h411
-rw-r--r--source/Plugins/Process/Utility/RegisterInfoInterface.h22
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_arm.h334
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_arm64.h156
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_i386.h73
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_mips.h233
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_mips64.h319
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_powerpc.h14
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_x86_64.h94
-rw-r--r--source/Plugins/Process/Utility/StopInfoMachException.cpp4
-rw-r--r--source/Plugins/Process/Utility/StopInfoMachException.h16
-rw-r--r--source/Plugins/Process/Utility/ThreadMemory.h92
-rw-r--r--source/Plugins/Process/Utility/UnwindLLDB.cpp86
-rw-r--r--source/Plugins/Process/Utility/UnwindLLDB.h37
-rw-r--r--source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h28
-rw-r--r--source/Plugins/Process/Utility/lldb-arm-register-enums.h50
-rw-r--r--source/Plugins/Process/elf-core/ProcessElfCore.cpp77
-rw-r--r--source/Plugins/Process/elf-core/ProcessElfCore.h32
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp1
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h40
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp1
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h40
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp1
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h40
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp1
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h42
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp1
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h40
-rw-r--r--source/Plugins/Process/elf-core/ThreadElfCore.cpp5
-rw-r--r--source/Plugins/Process/elf-core/ThreadElfCore.h41
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp232
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h77
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp287
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h76
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h8
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp105
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h17
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp600
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h41
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp305
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h52
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp290
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h22
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp1080
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.h138
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp8
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.h32
-rw-r--r--source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp93
-rw-r--r--source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h66
-rw-r--r--source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp1069
-rw-r--r--source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h498
-rw-r--r--source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp201
-rw-r--r--source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h70
-rw-r--r--source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp3172
-rw-r--r--source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h607
-rw-r--r--source/Plugins/ScriptInterpreter/Python/lldb-python.h31
-rw-r--r--source/Plugins/SymbolFile/DWARF/DIERef.cpp56
-rw-r--r--source/Plugins/SymbolFile/DWARF/DIERef.h42
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParser.h65
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp4034
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h213
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp828
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h84
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp90
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFAttribute.h60
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp459
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h124
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp543
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDIE.h281
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp18
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h12
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h5
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp230
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h35
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp953
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h138
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp95
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h9
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp128
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h68
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp60
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp54
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h16
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h7
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp114
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFFormValue.h40
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp172
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h24
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp94
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFLocationList.h34
-rw-r--r--source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp747
-rw-r--r--source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h950
-rw-r--r--source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h34
-rw-r--r--source/Plugins/SymbolFile/DWARF/NameToDIE.cpp34
-rw-r--r--source/Plugins/SymbolFile/DWARF/NameToDIE.h33
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp5934
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h807
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp212
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h45
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp131
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h70
-rw-r--r--source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp49
-rw-r--r--source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h35
-rw-r--r--source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp83
-rw-r--r--source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h129
-rw-r--r--source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp8
-rw-r--r--source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h31
-rw-r--r--source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp56
-rw-r--r--source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h100
-rw-r--r--source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h51
329 files changed, 66037 insertions, 19036 deletions
diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
index 700d223fbc6d..3b9b0f346072 100644
--- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
+++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
@@ -17,7 +17,6 @@
#include "lldb/Core/Scalar.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -28,7 +27,7 @@
#include "llvm/ADT/Triple.h"
#include "Utility/ARM_DWARF_Registers.h"
-#include "Utility/ARM_GCC_Registers.h"
+#include "Utility/ARM_ehframe_Registers.h"
#include "Plugins/Process/Utility/ARMDefines.h"
#include <vector>
@@ -38,90 +37,90 @@ using namespace lldb_private;
static RegisterInfo g_register_infos[] =
{
- // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
+ // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS
// ========== ======= == === ============= ============ ======================= =================== =========================== ======================= ====================== ========== ===============
- { "r0", "arg1", 4, 0, eEncodingUint , eFormatHex, { gcc_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, gdb_arm_r0, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r1", "arg2", 4, 0, eEncodingUint , eFormatHex, { gcc_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, gdb_arm_r1, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r2", "arg3", 4, 0, eEncodingUint , eFormatHex, { gcc_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, gdb_arm_r2, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r3", "arg4", 4, 0, eEncodingUint , eFormatHex, { gcc_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, gdb_arm_r3, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r4", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, gdb_arm_r4, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r5", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, gdb_arm_r5, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r6", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, gdb_arm_r6, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r7", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, gdb_arm_r7, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r8", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, gdb_arm_r8, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r9", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, gdb_arm_r9, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r10", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, gdb_arm_r10, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r11", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM, gdb_arm_r11, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r12", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, gdb_arm_r12, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "sp", "r13", 4, 0, eEncodingUint , eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, gdb_arm_sp, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "lr", "r14", 4, 0, eEncodingUint , eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_arm_lr, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "pc", "r15", 4, 0, eEncodingUint , eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_arm_pc, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, gdb_arm_cpsr, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, gdb_arm_s0, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, gdb_arm_s1, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, gdb_arm_s2, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, gdb_arm_s3, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, gdb_arm_s4, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, gdb_arm_s5, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, gdb_arm_s6, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, gdb_arm_s7, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, gdb_arm_s8, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, gdb_arm_s9, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, gdb_arm_s10, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, gdb_arm_s11, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, gdb_arm_s12, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, gdb_arm_s13, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, gdb_arm_s14, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, gdb_arm_s15, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, gdb_arm_s16, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, gdb_arm_s17, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, gdb_arm_s18, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, gdb_arm_s19, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, gdb_arm_s20, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, gdb_arm_s21, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, gdb_arm_s22, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, gdb_arm_s23, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, gdb_arm_s24, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, gdb_arm_s25, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, gdb_arm_s26, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, gdb_arm_s27, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, gdb_arm_s28, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, gdb_arm_s29, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, gdb_arm_s30, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, gdb_arm_s31, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fpscr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, gdb_arm_fpscr, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, gdb_arm_d0, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, gdb_arm_d1, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, gdb_arm_d2, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, gdb_arm_d3, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, gdb_arm_d4, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, gdb_arm_d5, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, gdb_arm_d6, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, gdb_arm_d7, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, gdb_arm_d8, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, gdb_arm_d9, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, gdb_arm_d10, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, gdb_arm_d11, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, gdb_arm_d12, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, gdb_arm_d13, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, gdb_arm_d14, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, gdb_arm_d15, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, gdb_arm_d16, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, gdb_arm_d17, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, gdb_arm_d18, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, gdb_arm_d19, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, gdb_arm_d20, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, gdb_arm_d21, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, gdb_arm_d22, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, gdb_arm_d23, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, gdb_arm_d24, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, gdb_arm_d25, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, gdb_arm_d26, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, gdb_arm_d27, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, gdb_arm_d28, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, gdb_arm_d29, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, gdb_arm_d30, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, gdb_arm_d31, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r0", "arg1", 4, 0, eEncodingUint , eFormatHex, { ehframe_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r1", "arg2", 4, 0, eEncodingUint , eFormatHex, { ehframe_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r2", "arg3", 4, 0, eEncodingUint , eFormatHex, { ehframe_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r3", "arg4", 4, 0, eEncodingUint , eFormatHex, { ehframe_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r4", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r5", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r6", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r7", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r8", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r9", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r10", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r11", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r12", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "sp", "r13", 4, 0, eEncodingUint , eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "lr", "r14", 4, 0, eEncodingUint , eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "pc", "r15", 4, 0, eEncodingUint , eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fpscr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
{ "r8_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r8_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
{ "r9_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r9_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
{ "r10_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r10_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
@@ -239,8 +238,8 @@ ABIMacOSX_arm::PrepareTrivialCall (Thread &thread,
size_t num_stack_regs = ae - ai;
sp -= (num_stack_regs * 4);
- // Keep the stack 8 byte aligned, not that we need to
- sp &= ~(8ull-1ull);
+ // Keep the stack 16 byte aligned
+ sp &= ~(16ull-1ull);
// just using arg1 to get the right size
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
@@ -333,18 +332,18 @@ ABIMacOSX_arm::GetArgumentValues (Thread &thread,
if (!value)
return false;
- ClangASTType clang_type = value->GetClangType();
- if (clang_type)
+ CompilerType compiler_type = value->GetCompilerType();
+ if (compiler_type)
{
bool is_signed = false;
size_t bit_width = 0;
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
- bit_width = clang_type.GetBitSize(&thread);
+ bit_width = compiler_type.GetBitSize(&thread);
}
- else if (clang_type.IsPointerOrReferenceType ())
+ else if (compiler_type.IsPointerOrReferenceType ())
{
- bit_width = clang_type.GetBitSize(&thread);
+ bit_width = compiler_type.GetBitSize(&thread);
}
else
{
@@ -414,22 +413,37 @@ ABIMacOSX_arm::GetArgumentValues (Thread &thread,
return true;
}
+bool
+ABIMacOSX_arm::IsArmv7kProcess (Thread *thread) const
+{
+ bool is_armv7k = false;
+ if (thread)
+ {
+ ProcessSP process_sp (thread->GetProcess());
+ if (process_sp)
+ {
+ const ArchSpec &arch (process_sp->GetTarget().GetArchitecture());
+ const ArchSpec::Core system_core = arch.GetCore();
+ if (system_core == ArchSpec::eCore_arm_armv7k)
+ {
+ is_armv7k = true;
+ }
+ }
+ }
+ return is_armv7k;
+}
+
ValueObjectSP
ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread,
- lldb_private::ClangASTType &clang_type) const
+ lldb_private::CompilerType &compiler_type) const
{
Value value;
ValueObjectSP return_valobj_sp;
- if (!clang_type)
- return return_valobj_sp;
-
- clang::ASTContext *ast_context = clang_type.GetASTContext();
- if (!ast_context)
+ if (!compiler_type)
return return_valobj_sp;
- //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType());
- value.SetClangType (clang_type);
+ value.SetCompilerType (compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
@@ -441,14 +455,68 @@ ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread,
// when reading data
const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfoByName("r0", 0);
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
- size_t bit_width = clang_type.GetBitSize(&thread);
+ size_t bit_width = compiler_type.GetBitSize(&thread);
switch (bit_width)
{
default:
return return_valobj_sp;
+ case 128:
+ if (IsArmv7kProcess (&thread))
+ {
+ // "A composite type not larger than 16 bytes is returned in r0-r3. The format is
+ // as if the result had been stored in memory at a word-aligned address and then
+ // loaded into r0-r3 with an ldm instruction"
+ {
+ const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfoByName("r1", 0);
+ const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
+ const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
+ if (r1_reg_info && r2_reg_info && r3_reg_info)
+ {
+ const size_t byte_size = compiler_type.GetByteSize(&thread);
+ ProcessSP process_sp (thread.GetProcess());
+ if (byte_size <= r0_reg_info->byte_size + r1_reg_info->byte_size + r2_reg_info->byte_size + r3_reg_info->byte_size
+ && process_sp)
+ {
+ std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
+ const ByteOrder byte_order = process_sp->GetByteOrder();
+ RegisterValue r0_reg_value;
+ RegisterValue r1_reg_value;
+ RegisterValue r2_reg_value;
+ RegisterValue r3_reg_value;
+ if (reg_ctx->ReadRegister(r0_reg_info, r0_reg_value)
+ && reg_ctx->ReadRegister(r1_reg_info, r1_reg_value)
+ && reg_ctx->ReadRegister(r2_reg_info, r2_reg_value)
+ && reg_ctx->ReadRegister(r3_reg_info, r3_reg_value))
+ {
+ Error error;
+ if (r0_reg_value.GetAsMemoryData (r0_reg_info, heap_data_ap->GetBytes()+0, 4, byte_order, error)
+ && r1_reg_value.GetAsMemoryData (r1_reg_info, heap_data_ap->GetBytes()+4, 4, byte_order, error)
+ && r2_reg_value.GetAsMemoryData (r2_reg_info, heap_data_ap->GetBytes()+8, 4, byte_order, error)
+ && r3_reg_value.GetAsMemoryData (r3_reg_info, heap_data_ap->GetBytes()+12, 4, byte_order, error))
+ {
+ DataExtractor data (DataBufferSP (heap_data_ap.release()),
+ byte_order,
+ process_sp->GetAddressByteSize());
+
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ compiler_type,
+ ConstString(""),
+ data);
+ return return_valobj_sp;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ return return_valobj_sp;
+ }
+ break;
case 64:
{
const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfoByName("r1", 0);
@@ -481,7 +549,7 @@ ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread,
break;
}
}
- else if (clang_type.IsPointerType ())
+ else if (compiler_type.IsPointerType ())
{
uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
value.GetScalar() = ptr;
@@ -510,8 +578,8 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
return error;
}
- ClangASTType clang_type = new_value_sp->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = new_value_sp->GetCompilerType();
+ if (!compiler_type)
{
error.SetErrorString ("Null clang type for return value.");
return error;
@@ -526,7 +594,7 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
RegisterContext *reg_ctx = thread->GetRegisterContext().get();
bool set_it_simple = false;
- if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())
{
DataExtractor data;
Error data_error;
@@ -561,12 +629,45 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
}
}
}
+ else if (num_bytes <= 16 && IsArmv7kProcess (frame_sp->GetThread().get()))
+ {
+ // "A composite type not larger than 16 bytes is returned in r0-r3. The format is
+ // as if the result had been stored in memory at a word-aligned address and then
+ // loaded into r0-r3 with an ldm instruction"
+
+ const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("r0", 0);
+ const RegisterInfo *r1_info = reg_ctx->GetRegisterInfoByName("r1", 0);
+ const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
+ const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
+ lldb::offset_t offset = 0;
+ uint32_t bytes_written = 4;
+ uint32_t raw_value = data.GetMaxU64(&offset, 4);
+ if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value) && bytes_written <= num_bytes)
+ {
+ bytes_written += 4;
+ raw_value = data.GetMaxU64(&offset, 4);
+ if (bytes_written <= num_bytes && reg_ctx->WriteRegisterFromUnsigned (r1_info, raw_value))
+ {
+ bytes_written += 4;
+ raw_value = data.GetMaxU64(&offset, 4);
+ if (bytes_written <= num_bytes && reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value))
+ {
+ bytes_written += 4;
+ raw_value = data.GetMaxU64(&offset, 4);
+ if (bytes_written <= num_bytes && reg_ctx->WriteRegisterFromUnsigned (r3_info, raw_value))
+ {
+ set_it_simple = true;
+ }
+ }
+ }
+ }
+ }
else
{
error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
}
}
- else if (clang_type.IsFloatingPointType (count, is_complex))
+ else if (compiler_type.IsFloatingPointType (count, is_complex))
{
if (is_complex)
error.SetErrorString ("We don't support returning complex values at present");
diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
index eee43943d73a..a4e9dead7794 100644
--- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
+++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
@@ -20,42 +20,36 @@
class ABIMacOSX_arm : public lldb_private::ABI
{
public:
- ~ABIMacOSX_arm() { }
+ ~ABIMacOSX_arm() override = default;
- virtual size_t
- GetRedZoneSize () const;
+ size_t
+ GetRedZoneSize() const override;
- virtual bool
- PrepareTrivialCall (lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t func_addr,
- lldb::addr_t returnAddress,
- llvm::ArrayRef<lldb::addr_t> args) const;
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t func_addr,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const override;
- virtual bool
- GetArgumentValues (lldb_private::Thread &thread,
- lldb_private::ValueList &values) const;
+ bool
+ GetArgumentValues(lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
- virtual lldb_private::Error
- SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
- virtual lldb::ValueObjectSP
- GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const;
-
-public:
- virtual bool
- CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+ bool
+ RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
- virtual bool
- CallFrameAddressIsValid (lldb::addr_t cfa)
+ bool
+ CallFrameAddressIsValid(lldb::addr_t cfa) override
{
// Make sure the stack call frame addresses are are 4 byte aligned
if (cfa & (4ull - 1ull))
@@ -65,8 +59,8 @@ public:
return true;
}
- virtual bool
- CodeAddressIsValid (lldb::addr_t pc)
+ bool
+ CodeAddressIsValid(lldb::addr_t pc) override
{
// Just make sure the address is a valid 32 bit address. Bit zero
// might be set due to Thumb function calls, so don't enforce 2 byte
@@ -74,20 +68,24 @@ public:
return pc <= UINT32_MAX;
}
- virtual lldb::addr_t
- FixCodeAddress (lldb::addr_t pc)
+ lldb::addr_t
+ FixCodeAddress(lldb::addr_t pc) override
{
// ARM uses bit zero to signify a code address is thumb, so we must
// strip bit zero in any code addresses.
return pc & ~(lldb::addr_t)1;
}
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoArray (uint32_t &count);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray(uint32_t &count) override;
+
+ bool
+ IsArmv7kProcess (lldb_private::Thread *thread) const;
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -103,13 +101,18 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
protected:
+ lldb::ValueObjectSP
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const override;
+
private:
ABIMacOSX_arm() :
lldb_private::ABI()
@@ -118,4 +121,4 @@ private:
}
};
-#endif // liblldb_ABIMacOSX_arm_h_
+#endif // liblldb_ABIMacOSX_arm_h_
diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
index 04b96180deb3..0e6f9d663ae8 100644
--- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
+++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
@@ -19,7 +19,6 @@
#include "lldb/Core/Value.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -37,12 +36,11 @@ using namespace lldb;
using namespace lldb_private;
static const char *pluginDesc = "Mac OS X ABI for arm64 targets";
-static const char *pluginShort = "abi.macosx-arm64";
static RegisterInfo g_register_infos[] =
{
- // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE
+ // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE
// ========== ======= == === ============= =================== =================== ====================== =========================== ======================= ======================
{ "x0", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
{ "x1", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
@@ -77,7 +75,7 @@ static RegisterInfo g_register_infos[] =
{ "lr", "x30", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x30, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
{ "sp", "x31", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x31, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
{ "pc", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
{ "v0", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
{ "v1", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
@@ -115,71 +113,71 @@ static RegisterInfo g_register_infos[] =
{ "fpsr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
{ "fpcr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
-
- { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
- { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }
+ { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+
+ { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
+ { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }
};
static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
@@ -322,7 +320,7 @@ ABIMacOSX_arm64::GetArgumentValues (Thread &thread, ValueList &values) const
if (!value)
return false;
- ClangASTType value_type = value->GetClangType();
+ CompilerType value_type = value->GetCompilerType();
if (value_type)
{
bool is_signed = false;
@@ -424,7 +422,7 @@ ABIMacOSX_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueO
return error;
}
- ClangASTType return_value_type = new_value_sp->GetClangType();
+ CompilerType return_value_type = new_value_sp->GetCompilerType();
if (!return_value_type)
{
error.SetErrorString ("Null clang type for return value.");
@@ -709,7 +707,7 @@ ABIMacOSX_arm64::RegisterIsVolatile (const RegisterInfo *reg_info)
static bool
LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,
RegisterContext *reg_ctx,
- const ClangASTType &value_type,
+ const CompilerType &value_type,
bool is_return_value, // false => parameter, true => return value
uint32_t &NGRN, // NGRN (see ABI documentation)
uint32_t &NSRN, // NSRN (see ABI documentation)
@@ -724,18 +722,16 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,
const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();
Error error;
- ClangASTType base_type;
+ CompilerType base_type;
const uint32_t homogeneous_count = value_type.IsHomogeneousAggregate (&base_type);
if (homogeneous_count > 0 && homogeneous_count <= 8)
{
- printf ("ClangASTContext::IsHomogeneousAggregate() => %u\n", homogeneous_count);
// Make sure we have enough registers
if (NSRN < 8 && (8-NSRN) >= homogeneous_count)
{
if (!base_type)
return false;
const size_t base_byte_size = base_type.GetByteSize(nullptr);
- printf ("ClangASTContext::IsHomogeneousAggregate() => base_byte_size = %" PRIu64 "\n", (uint64_t) base_byte_size);
uint32_t data_offset = 0;
for (uint32_t i=0; i<homogeneous_count; ++i)
@@ -861,7 +857,7 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,
}
ValueObjectSP
-ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
Value value;
@@ -870,16 +866,16 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_
if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)
return return_valobj_sp;
- //value.SetContext (Value::eContextTypeClangType, return_clang_type);
- value.SetClangType(return_clang_type);
+ //value.SetContext (Value::eContextTypeClangType, return_compiler_type);
+ value.SetCompilerType(return_compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return return_valobj_sp;
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
- const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL);
+ const uint32_t type_flags = return_compiler_type.GetTypeInfo (NULL);
if (type_flags & eTypeIsScalar ||
type_flags & eTypeIsPointer)
{
@@ -926,7 +922,7 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_
exe_ctx.GetProcessRef().GetAddressByteSize());
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
return return_valobj_sp;
@@ -1043,7 +1039,7 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_
byte_order,
exe_ctx.GetProcessRef().GetAddressByteSize());
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
}
@@ -1060,10 +1056,10 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_
uint32_t NGRN = 0; // Search ABI docs for NGRN
uint32_t NSRN = 0; // Search ABI docs for NSRN
const bool is_return_value = true;
- if (LoadValueFromConsecutiveGPRRegisters (exe_ctx, reg_ctx, return_clang_type, is_return_value, NGRN, NSRN, data))
+ if (LoadValueFromConsecutiveGPRRegisters (exe_ctx, reg_ctx, return_compiler_type, is_return_value, NGRN, NSRN, data))
{
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
}
@@ -1095,12 +1091,6 @@ ABIMacOSX_arm64::GetPluginNameStatic()
return g_plugin_name;
}
-const char *
-ABIMacOSX_arm64::GetShortPluginName()
-{
- return pluginShort;
-}
-
uint32_t
ABIMacOSX_arm64::GetPluginVersion()
{
diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h
index 6cce6a6f1174..1bc94f61c2f1 100644
--- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h
+++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h
@@ -22,30 +22,30 @@ class ABIMacOSX_arm64 :
public lldb_private::ABI
{
public:
- ~ABIMacOSX_arm64() { }
+ ~ABIMacOSX_arm64() override = default;
- virtual size_t
- GetRedZoneSize () const;
+ size_t
+ GetRedZoneSize() const override;
- virtual bool
- PrepareTrivialCall (lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t functionAddress,
- lldb::addr_t returnAddress,
- llvm::ArrayRef<lldb::addr_t> args) const;
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const override;
- virtual bool
- GetArgumentValues (lldb_private::Thread &thread,
- lldb_private::ValueList &values) const;
+ bool
+ GetArgumentValues(lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
- virtual bool
- CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+ bool
+ RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
// The arm64 ABI requires that stack frames be 16 byte aligned.
// When there is a trap handler on the stack, e.g. _sigtramp in userland
@@ -57,9 +57,8 @@ public:
// Whitelisting the trap handlers for user space would be easy (_sigtramp) but
// in other environments there can be a large number of different functions
// involved in async traps.
-
- virtual bool
- CallFrameAddressIsValid (lldb::addr_t cfa)
+ bool
+ CallFrameAddressIsValid(lldb::addr_t cfa) override
{
// Make sure the stack call frame addresses are are 8 byte aligned
if (cfa & (8ull - 1ull))
@@ -69,8 +68,8 @@ public:
return true;
}
- virtual bool
- CodeAddressIsValid (lldb::addr_t pc)
+ bool
+ CodeAddressIsValid(lldb::addr_t pc) override
{
if (pc & (4ull - 1ull))
return false; // Not 4 byte aligned
@@ -79,12 +78,13 @@ public:
return true;
}
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoArray (uint32_t &count);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray(uint32_t &count) override;
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -97,28 +97,26 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
+
static lldb_private::ConstString
GetPluginNameStatic();
- virtual lldb_private::ConstString
- GetPluginName()
+ lldb_private::ConstString
+ GetPluginName() override
{
return GetPluginNameStatic();
}
- virtual const char *
- GetShortPluginName();
-
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
- virtual lldb_private::Error
- SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
protected:
- virtual lldb::ValueObjectSP
+ lldb::ValueObjectSP
GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const;
+ lldb_private::CompilerType &ast_type) const override;
private:
ABIMacOSX_arm64() :
@@ -128,4 +126,4 @@ private:
}
};
-#endif // liblldb_ABI_h_
+#endif // liblldb_ABIMacOSX_arm64_h_
diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
index 4204d18769b8..75e5fb1558e6 100644
--- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
+++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
@@ -16,13 +16,13 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include <vector>
@@ -32,16 +32,16 @@ using namespace lldb_private;
enum
{
- gcc_eax = 0,
- gcc_ecx,
- gcc_edx,
- gcc_ebx,
- gcc_ebp,
- gcc_esp,
- gcc_esi,
- gcc_edi,
- gcc_eip,
- gcc_eflags
+ ehframe_eax = 0,
+ ehframe_ecx,
+ ehframe_edx,
+ ehframe_ebx,
+ ehframe_ebp, // Different from DWARF the regnums - eh_frame esp/ebp had their regnums switched on i386 darwin
+ ehframe_esp, // Different from DWARF the regnums - eh_frame esp/ebp had their regnums switched on i386 darwin
+ ehframe_esi,
+ ehframe_edi,
+ ehframe_eip,
+ ehframe_eflags
};
enum
@@ -82,121 +82,60 @@ enum
dwarf_ymm7 = dwarf_xmm7
};
-enum
-{
- gdb_eax = 0,
- gdb_ecx = 1,
- gdb_edx = 2,
- gdb_ebx = 3,
- gdb_esp = 4,
- gdb_ebp = 5,
- gdb_esi = 6,
- gdb_edi = 7,
- gdb_eip = 8,
- gdb_eflags = 9,
- gdb_cs = 10,
- gdb_ss = 11,
- gdb_ds = 12,
- gdb_es = 13,
- gdb_fs = 14,
- gdb_gs = 15,
- gdb_stmm0 = 16,
- gdb_stmm1 = 17,
- gdb_stmm2 = 18,
- gdb_stmm3 = 19,
- gdb_stmm4 = 20,
- gdb_stmm5 = 21,
- gdb_stmm6 = 22,
- gdb_stmm7 = 23,
- gdb_fctrl = 24, gdb_fcw = gdb_fctrl,
- gdb_fstat = 25, gdb_fsw = gdb_fstat,
- gdb_ftag = 26, gdb_ftw = gdb_ftag,
- gdb_fiseg = 27, gdb_fpu_cs = gdb_fiseg,
- gdb_fioff = 28, gdb_ip = gdb_fioff,
- gdb_foseg = 29, gdb_fpu_ds = gdb_foseg,
- gdb_fooff = 30, gdb_dp = gdb_fooff,
- gdb_fop = 31,
- gdb_xmm0 = 32,
- gdb_xmm1 = 33,
- gdb_xmm2 = 34,
- gdb_xmm3 = 35,
- gdb_xmm4 = 36,
- gdb_xmm5 = 37,
- gdb_xmm6 = 38,
- gdb_xmm7 = 39,
- gdb_mxcsr = 40,
- gdb_mm0 = 41,
- gdb_mm1 = 42,
- gdb_mm2 = 43,
- gdb_mm3 = 44,
- gdb_mm4 = 45,
- gdb_mm5 = 46,
- gdb_mm6 = 47,
- gdb_mm7 = 48,
- gdb_ymm0 = gdb_xmm0,
- gdb_ymm1 = gdb_xmm1,
- gdb_ymm2 = gdb_xmm2,
- gdb_ymm3 = gdb_xmm3,
- gdb_ymm4 = gdb_xmm4,
- gdb_ymm5 = gdb_xmm5,
- gdb_ymm6 = gdb_xmm6,
- gdb_ymm7 = gdb_xmm7
-};
-
static RegisterInfo g_register_infos[] =
{
- // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
+ // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS
// ====== ======= == === ============= ============ ===================== ===================== ============================ ==================== ====================== ========== ===============
- { "eax", NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_eax , dwarf_eax , LLDB_INVALID_REGNUM , gdb_eax , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ebx" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , gdb_ebx , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ecx" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_ecx , dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , gdb_ecx , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "edx" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_edx , dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , gdb_edx , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "esi" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_esi , dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , gdb_esi , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "edi" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_edi , dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , gdb_edi , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { gcc_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , gdb_ebp , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { gcc_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , gdb_esp , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { gcc_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , gdb_eip , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "eflags", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "cs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_cs , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ss" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ss , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ds" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ds , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "es" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_es , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fs , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "gs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gs , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm0" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm0 , LLDB_INVALID_REGNUM , gdb_stmm0 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm1" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm1 , LLDB_INVALID_REGNUM , gdb_stmm1 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm2" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm2 , LLDB_INVALID_REGNUM , gdb_stmm2 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm3" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm3 , LLDB_INVALID_REGNUM , gdb_stmm3 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm4" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm4 , LLDB_INVALID_REGNUM , gdb_stmm4 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm5" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm5 , LLDB_INVALID_REGNUM , gdb_stmm5 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm6" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm6 , LLDB_INVALID_REGNUM , gdb_stmm6 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm7" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm7 , LLDB_INVALID_REGNUM , gdb_stmm7 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fctrl" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fctrl , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fstat" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fstat , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ftag" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ftag , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fiseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fiseg , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fioff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fioff , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "foseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_foseg , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fooff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fooff , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fop" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fop , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm0" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm0 , LLDB_INVALID_REGNUM , gdb_xmm0 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm1" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm1 , LLDB_INVALID_REGNUM , gdb_xmm1 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm2" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm2 , LLDB_INVALID_REGNUM , gdb_xmm2 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm3" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm3 , LLDB_INVALID_REGNUM , gdb_xmm3 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm4" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm4 , LLDB_INVALID_REGNUM , gdb_xmm4 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm5" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm5 , LLDB_INVALID_REGNUM , gdb_xmm5 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm6" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm6 , LLDB_INVALID_REGNUM , gdb_xmm6 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm7" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm7 , LLDB_INVALID_REGNUM , gdb_xmm7 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "mxcsr" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_mxcsr , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm0" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm0 , LLDB_INVALID_REGNUM , gdb_ymm0 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm1" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm1 , LLDB_INVALID_REGNUM , gdb_ymm1 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm2" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm2 , LLDB_INVALID_REGNUM , gdb_ymm2 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm3" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm3 , LLDB_INVALID_REGNUM , gdb_ymm3 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm4" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm4 , LLDB_INVALID_REGNUM , gdb_ymm4 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm5" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm5 , LLDB_INVALID_REGNUM , gdb_ymm5 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm6" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm6 , LLDB_INVALID_REGNUM , gdb_ymm6 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm7" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7 , LLDB_INVALID_REGNUM , gdb_ymm7 , LLDB_INVALID_REGNUM }, NULL, NULL}
+ { "eax", NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_eax , dwarf_eax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ebx" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ecx" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_ecx , dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "edx" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_edx , dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "esi" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_esi , dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "edi" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_edi , dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { ehframe_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { ehframe_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { ehframe_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "eflags", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "cs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ss" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ds" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "es" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "gs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm0" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm1" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm2" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm3" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm4" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm5" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm6" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm7" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fctrl" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fstat" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ftag" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fiseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fioff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "foseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fooff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fop" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm0" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm1" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm2" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm3" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm4" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm5" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm6" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm7" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "mxcsr" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm0" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm1" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm2" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm3" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm4" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm5" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm6" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm7" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}
};
static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
@@ -237,7 +176,7 @@ ABIMacOSX_i386::CreateInstance (const ArchSpec &arch)
{
static ABISP g_abi_sp;
if ((arch.GetTriple().getArch() == llvm::Triple::x86) &&
- (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS()))
+ (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS() || arch.GetTriple().isWatchOS()))
{
if (!g_abi_sp)
g_abi_sp.reset (new ABIMacOSX_i386);
@@ -316,184 +255,6 @@ ABIMacOSX_i386::PrepareTrivialCall (Thread &thread,
return true;
}
-bool
-ABIMacOSX_i386::PrepareNormalCall (Thread &thread,
- addr_t sp,
- addr_t func_addr,
- addr_t return_addr,
- ValueList &args) const
-{
- ExecutionContext exe_ctx (thread.shared_from_this());
- RegisterContext *reg_ctx = thread.GetRegisterContext().get();
- if (!reg_ctx)
- return false;
-
- Process *process = exe_ctx.GetProcessPtr();
- Error error;
- uint32_t fp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
- uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
- uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
-
- // Do the argument layout
-
- std::vector <uint32_t> argLayout; // 4-byte chunks, as discussed in the ABI Function Call Guide
-
- size_t numArgs = args.GetSize();
- size_t index;
-
- for (index = 0; index < numArgs; ++index)
- {
- Value *val = args.GetValueAtIndex(index);
-
- if (!val)
- return false;
-
- switch (val->GetValueType())
- {
- case Value::eValueTypeScalar:
- {
- Scalar &scalar = val->GetScalar();
- switch (scalar.GetType())
- {
- case Scalar::e_void:
- return false;
- case Scalar::e_sint:
- case Scalar::e_uint:
- case Scalar::e_slong:
- case Scalar::e_ulong:
- case Scalar::e_slonglong:
- case Scalar::e_ulonglong:
- {
- uint64_t data = scalar.ULongLong();
-
- switch (scalar.GetByteSize())
- {
- default:
- return false;
- case 1:
- argLayout.push_back((uint32_t)(data & 0xffull));
- break;
- case 2:
- argLayout.push_back((uint32_t)(data & 0xffffull));
- break;
- case 4:
- argLayout.push_back((uint32_t)(data & 0xffffffffull));
- break;
- case 8:
- argLayout.push_back((uint32_t)(data & 0xffffffffull));
- argLayout.push_back((uint32_t)(data >> 32));
- break;
- }
- }
- break;
- case Scalar::e_float:
- {
- float data = scalar.Float();
- uint32_t dataRaw = *((uint32_t*)(&data));
- argLayout.push_back(dataRaw);
- }
- break;
- case Scalar::e_double:
- {
- double data = scalar.Double();
- uint32_t *dataRaw = ((uint32_t*)(&data));
- argLayout.push_back(dataRaw[0]);
- argLayout.push_back(dataRaw[1]);
- }
- break;
- case Scalar::e_long_double:
- {
- long double data = scalar.Double();
- uint32_t *dataRaw = ((uint32_t*)(&data));
- while ((argLayout.size() * 4) & 0xf)
- argLayout.push_back(0);
- argLayout.push_back(dataRaw[0]);
- argLayout.push_back(dataRaw[1]);
- argLayout.push_back(dataRaw[2]);
- argLayout.push_back(dataRaw[3]);
- }
- break;
- }
- }
- break;
- case Value::eValueTypeHostAddress:
- {
- ClangASTType clang_type (val->GetClangType());
- if (clang_type)
- {
- uint32_t cstr_length = 0;
- if (clang_type.IsCStringType (cstr_length))
- {
- const char *cstr = (const char*)val->GetScalar().ULongLong();
- cstr_length = strlen(cstr);
-
- // Push the string onto the stack immediately.
-
- sp -= (cstr_length + 1);
-
- if (process->WriteMemory(sp, cstr, cstr_length + 1, error) != (cstr_length + 1))
- return false;
-
- // Put the address of the string into the argument array.
-
- argLayout.push_back((uint32_t)(sp & 0xffffffff));
- }
- else
- {
- return false;
- }
- }
- break;
- }
- break;
- case Value::eValueTypeFileAddress:
- case Value::eValueTypeLoadAddress:
- default:
- return false;
- }
- }
-
- // Make room for the arguments on the stack
-
- sp -= 4 * argLayout.size();
-
- // Align the SP
-
- sp &= ~(16ull-1ull); // 16-byte alignment
-
- // Write the arguments on the stack
-
- size_t numChunks = argLayout.size();
-
- for (index = 0; index < numChunks; ++index)
- if (process->WriteMemory(sp + (index * 4), &argLayout[index], sizeof(uint32_t), error) != sizeof(uint32_t))
- return false;
-
- // The return address is pushed onto the stack.
-
- sp -= 4;
- uint32_t returnAddressU32 = return_addr;
- if (process->WriteMemory (sp, &returnAddressU32, sizeof(returnAddressU32), error) != sizeof(returnAddressU32))
- return false;
-
- // %esp is set to the actual stack value.
-
- if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp))
- return false;
-
- // %ebp is set to a fake value, in our case 0x0x00000000
-
- if (!reg_ctx->WriteRegisterFromUnsigned(fp_reg_num, 0x00000000))
- return false;
-
- // %eip is set to the address of the called function.
-
- if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr))
- return false;
-
- return true;
-}
-
static bool
ReadIntegerArgument (Scalar &scalar,
unsigned int bit_width,
@@ -545,23 +306,23 @@ ABIMacOSX_i386::GetArgumentValues (Thread &thread,
// We currently only support extracting values with Clang QualTypes.
// Do we care about others?
- ClangASTType clang_type (value->GetClangType());
- if (clang_type)
+ CompilerType compiler_type (value->GetCompilerType());
+ if (compiler_type)
{
bool is_signed;
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
is_signed,
thread.GetProcess().get(),
current_stack_argument);
}
- else if (clang_type.IsPointerType())
+ else if (compiler_type.IsPointerType())
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
false,
thread.GetProcess().get(),
current_stack_argument);
@@ -582,8 +343,8 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
return error;
}
- ClangASTType clang_type = new_value_sp->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = new_value_sp->GetCompilerType();
+ if (!compiler_type)
{
error.SetErrorString ("Null clang type for return value.");
return error;
@@ -598,7 +359,7 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
RegisterContext *reg_ctx = thread->GetRegisterContext().get();
bool set_it_simple = false;
- if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())
{
DataExtractor data;
Error data_error;
@@ -638,7 +399,7 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
}
}
- else if (clang_type.IsFloatingPointType (count, is_complex))
+ else if (compiler_type.IsFloatingPointType (count, is_complex))
{
if (is_complex)
error.SetErrorString ("We don't support returning complex values at present");
@@ -654,16 +415,16 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
ValueObjectSP
ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,
- ClangASTType &clang_type) const
+ CompilerType &compiler_type) const
{
Value value;
ValueObjectSP return_valobj_sp;
- if (!clang_type)
+ if (!compiler_type)
return return_valobj_sp;
- //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType());
- value.SetClangType (clang_type);
+ //value.SetContext (Value::eContextTypeClangType, compiler_type.GetOpaqueQualType());
+ value.SetCompilerType (compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
@@ -671,9 +432,9 @@ ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,
bool is_signed;
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
- size_t bit_width = clang_type.GetBitSize(&thread);
+ size_t bit_width = compiler_type.GetBitSize(&thread);
unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
@@ -713,7 +474,7 @@ ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,
break;
}
}
- else if (clang_type.IsPointerType ())
+ else if (compiler_type.IsPointerType ())
{
unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
index d81b7a7e684b..6a82fce35bf7 100644
--- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
+++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
@@ -22,48 +22,33 @@ class ABIMacOSX_i386 :
public lldb_private::ABI
{
public:
-
- ~ABIMacOSX_i386() { }
-
- virtual size_t
- GetRedZoneSize () const;
+ ~ABIMacOSX_i386() override = default;
- virtual bool
- PrepareTrivialCall (lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t func_addr,
- lldb::addr_t return_addr,
- llvm::ArrayRef<lldb::addr_t> args) const;
+ size_t
+ GetRedZoneSize() const override;
- virtual bool
- PrepareNormalCall (lldb_private::Thread &thread,
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
lldb::addr_t sp,
lldb::addr_t func_addr,
lldb::addr_t return_addr,
- lldb_private::ValueList &args) const;
+ llvm::ArrayRef<lldb::addr_t> args) const override;
- virtual bool
- GetArgumentValues (lldb_private::Thread &thread,
- lldb_private::ValueList &values) const;
+ bool
+ GetArgumentValues(lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
- virtual lldb_private::Error
- SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
- virtual lldb::ValueObjectSP
- GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const;
-
-public:
-
- virtual bool
- CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+ bool
+ RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
// The Darwin i386 ABI requires that stack frames be 16 byte aligned.
// When there is a trap handler on the stack, e.g. _sigtramp in userland
@@ -78,8 +63,8 @@ public:
//
// If we were to enforce 16-byte alignment, we also need to relax to 4-byte
// alignment for non-darwin i386 targets.
- virtual bool
- CallFrameAddressIsValid (lldb::addr_t cfa)
+ bool
+ CallFrameAddressIsValid(lldb::addr_t cfa) override
{
// Make sure the stack call frame addresses are are 4 byte aligned
if (cfa & (4ull - 1ull))
@@ -89,19 +74,20 @@ public:
return true;
}
- virtual bool
- CodeAddressIsValid (lldb::addr_t pc)
+ bool
+ CodeAddressIsValid(lldb::addr_t pc) override
{
// Just make sure the address is a valid 32 bit address.
return pc <= UINT32_MAX;
}
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoArray (uint32_t &count);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray(uint32_t &count) override;
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -114,22 +100,30 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
+
static lldb_private::ConstString
GetPluginNameStatic ();
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
protected:
+ lldb::ValueObjectSP
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const override;
+
bool
RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
private:
- ABIMacOSX_i386() : lldb_private::ABI() { } // Call CreateInstance instead.
+ ABIMacOSX_i386() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
};
-
-#endif // liblldb_ABI_h_
+#endif // liblldb_ABIMacOSX_i386_h_
diff --git a/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
index 50a9863d83e7..ef625dece265 100644
--- a/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
+++ b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
@@ -17,7 +17,6 @@
#include "lldb/Core/Scalar.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -28,7 +27,7 @@
#include "llvm/ADT/Triple.h"
#include "Utility/ARM_DWARF_Registers.h"
-#include "Utility/ARM_GCC_Registers.h"
+#include "Utility/ARM_ehframe_Registers.h"
#include "Plugins/Process/Utility/ARMDefines.h"
#include <vector>
@@ -38,90 +37,90 @@ using namespace lldb_private;
static RegisterInfo g_register_infos[] =
{
- // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
+ // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS
// ========== ======= == === ============= ============ ======================= =================== =========================== ======================= ====================== ========== ===============
- { "r0", "arg1", 4, 0, eEncodingUint , eFormatHex, { gcc_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, gdb_arm_r0, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r1", "arg2", 4, 0, eEncodingUint , eFormatHex, { gcc_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, gdb_arm_r1, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r2", "arg3", 4, 0, eEncodingUint , eFormatHex, { gcc_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, gdb_arm_r2, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r3", "arg4", 4, 0, eEncodingUint , eFormatHex, { gcc_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, gdb_arm_r3, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r4", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, gdb_arm_r4, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r5", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, gdb_arm_r5, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r6", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, gdb_arm_r6, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r7", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, gdb_arm_r7, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r8", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, gdb_arm_r8, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r9", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, gdb_arm_r9, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r10", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, gdb_arm_r10, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r11", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM, gdb_arm_r11, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r12", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, gdb_arm_r12, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "sp", "r13", 4, 0, eEncodingUint , eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, gdb_arm_sp, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "lr", "r14", 4, 0, eEncodingUint , eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_arm_lr, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "pc", "r15", 4, 0, eEncodingUint , eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_arm_pc, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, gdb_arm_cpsr, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, gdb_arm_s0, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, gdb_arm_s1, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, gdb_arm_s2, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, gdb_arm_s3, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, gdb_arm_s4, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, gdb_arm_s5, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, gdb_arm_s6, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, gdb_arm_s7, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, gdb_arm_s8, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, gdb_arm_s9, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, gdb_arm_s10, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, gdb_arm_s11, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, gdb_arm_s12, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, gdb_arm_s13, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, gdb_arm_s14, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, gdb_arm_s15, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, gdb_arm_s16, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, gdb_arm_s17, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, gdb_arm_s18, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, gdb_arm_s19, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, gdb_arm_s20, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, gdb_arm_s21, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, gdb_arm_s22, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, gdb_arm_s23, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, gdb_arm_s24, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, gdb_arm_s25, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, gdb_arm_s26, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, gdb_arm_s27, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, gdb_arm_s28, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, gdb_arm_s29, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, gdb_arm_s30, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, gdb_arm_s31, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fpscr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, gdb_arm_fpscr, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, gdb_arm_d0, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, gdb_arm_d1, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, gdb_arm_d2, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, gdb_arm_d3, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, gdb_arm_d4, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, gdb_arm_d5, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, gdb_arm_d6, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, gdb_arm_d7, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, gdb_arm_d8, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, gdb_arm_d9, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, gdb_arm_d10, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, gdb_arm_d11, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, gdb_arm_d12, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, gdb_arm_d13, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, gdb_arm_d14, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, gdb_arm_d15, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, gdb_arm_d16, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, gdb_arm_d17, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, gdb_arm_d18, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, gdb_arm_d19, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, gdb_arm_d20, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, gdb_arm_d21, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, gdb_arm_d22, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, gdb_arm_d23, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, gdb_arm_d24, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, gdb_arm_d25, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, gdb_arm_d26, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, gdb_arm_d27, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, gdb_arm_d28, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, gdb_arm_d29, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, gdb_arm_d30, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, gdb_arm_d31, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r0", "arg1", 4, 0, eEncodingUint , eFormatHex, { ehframe_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r1", "arg2", 4, 0, eEncodingUint , eFormatHex, { ehframe_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r2", "arg3", 4, 0, eEncodingUint , eFormatHex, { ehframe_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r3", "arg4", 4, 0, eEncodingUint , eFormatHex, { ehframe_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r4", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r5", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r6", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r7", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r8", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r9", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r10", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r11", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r12", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "sp", "r13", 4, 0, eEncodingUint , eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "lr", "r14", 4, 0, eEncodingUint , eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "pc", "r15", 4, 0, eEncodingUint , eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fpscr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
{ "r8_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r8_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
{ "r9_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r9_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
{ "r10_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r10_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
@@ -333,18 +332,18 @@ ABISysV_arm::GetArgumentValues (Thread &thread,
if (!value)
return false;
- ClangASTType clang_type = value->GetClangType();
- if (clang_type)
+ CompilerType compiler_type = value->GetCompilerType();
+ if (compiler_type)
{
bool is_signed = false;
size_t bit_width = 0;
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
- bit_width = clang_type.GetBitSize(&thread);
+ bit_width = compiler_type.GetBitSize(&thread);
}
- else if (clang_type.IsPointerOrReferenceType ())
+ else if (compiler_type.IsPointerOrReferenceType ())
{
- bit_width = clang_type.GetBitSize(&thread);
+ bit_width = compiler_type.GetBitSize(&thread);
}
else
{
@@ -398,22 +397,35 @@ ABISysV_arm::GetArgumentValues (Thread &thread,
return true;
}
+static bool
+GetReturnValuePassedInMemory(Thread &thread, RegisterContext* reg_ctx, size_t byte_size, Value& value)
+{
+ Error error;
+ DataBufferHeap buffer(byte_size, 0);
+
+ const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
+ uint32_t address = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
+ thread.GetProcess()->ReadMemory(address, buffer.GetBytes(), buffer.GetByteSize(), error);
+
+ if (error.Fail())
+ return false;
+
+ value.SetBytes(buffer.GetBytes(), buffer.GetByteSize());
+ return true;
+}
+
ValueObjectSP
ABISysV_arm::GetReturnValueObjectImpl (Thread &thread,
- lldb_private::ClangASTType &clang_type) const
+ lldb_private::CompilerType &compiler_type) const
{
Value value;
ValueObjectSP return_valobj_sp;
- if (!clang_type)
+ if (!compiler_type)
return return_valobj_sp;
- clang::ASTContext *ast_context = clang_type.GetASTContext();
- if (!ast_context)
- return return_valobj_sp;
-
- //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType());
- value.SetClangType (clang_type);
+ //value.SetContext (Value::eContextTypeClangType, compiler_type.GetOpaqueQualType());
+ value.SetCompilerType (compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
@@ -427,9 +439,9 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread,
// when reading data
const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
- size_t bit_width = clang_type.GetBitSize(&thread);
+ size_t bit_width = compiler_type.GetBitSize(&thread);
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
switch (bit_width)
{
@@ -467,12 +479,33 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread,
break;
}
}
- else if (clang_type.IsPointerType ())
+ else if (compiler_type.IsPointerType ())
{
uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
value.GetScalar() = ptr;
}
- else if (clang_type.IsFloatingPointType(float_count, is_complex))
+ else if (compiler_type.IsVectorType(nullptr, nullptr))
+ {
+ size_t byte_size = compiler_type.GetByteSize(&thread);
+ if (byte_size <= 16)
+ {
+ DataBufferHeap buffer(16, 0);
+ uint32_t* buffer_ptr = (uint32_t*)buffer.GetBytes();
+
+ for (uint32_t i = 0; 4*i < byte_size; ++i)
+ {
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
+ buffer_ptr[i] = reg_ctx->ReadRegisterAsUnsigned(reg_info, 0) & UINT32_MAX;
+ }
+ value.SetBytes(buffer.GetBytes(), byte_size);
+ }
+ else
+ {
+ if (!GetReturnValuePassedInMemory(thread, reg_ctx, byte_size, value))
+ return return_valobj_sp;
+ }
+ }
+ else if (compiler_type.IsFloatingPointType(float_count, is_complex))
{
if (float_count == 1 && !is_complex)
{
@@ -506,9 +539,9 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread,
return return_valobj_sp;
}
}
- else if (clang_type.IsAggregateType())
+ else if (compiler_type.IsAggregateType())
{
- size_t byte_size = clang_type.GetByteSize(&thread);
+ size_t byte_size = compiler_type.GetByteSize(&thread);
if (byte_size <= 4)
{
RegisterValue r0_reg_value;
@@ -517,16 +550,7 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread,
}
else
{
- RegisterValue r0_reg_value;
- uint32_t address = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
-
- Error error;
- DataBufferHeap buffer(byte_size, 0);
- thread.GetProcess()->ReadMemory(address, buffer.GetBytes(), buffer.GetByteSize(), error);
-
- if (error.Success())
- value.SetBytes(buffer.GetBytes(), buffer.GetByteSize());
- else
+ if (!GetReturnValuePassedInMemory(thread, reg_ctx, byte_size, value))
return return_valobj_sp;
}
}
@@ -554,8 +578,8 @@ ABISysV_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec
return error;
}
- ClangASTType clang_type = new_value_sp->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = new_value_sp->GetCompilerType();
+ if (!compiler_type)
{
error.SetErrorString ("Null clang type for return value.");
return error;
@@ -570,7 +594,7 @@ ABISysV_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec
RegisterContext *reg_ctx = thread->GetRegisterContext().get();
bool set_it_simple = false;
- if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())
{
DataExtractor data;
Error data_error;
@@ -610,7 +634,7 @@ ABISysV_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec
error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
}
}
- else if (clang_type.IsFloatingPointType (count, is_complex))
+ else if (compiler_type.IsFloatingPointType (count, is_complex))
{
if (is_complex)
error.SetErrorString ("We don't support returning complex values at present");
diff --git a/source/Plugins/ABI/SysV-arm/ABISysV_arm.h b/source/Plugins/ABI/SysV-arm/ABISysV_arm.h
index 69becd6ec0c2..e3b280296a64 100644
--- a/source/Plugins/ABI/SysV-arm/ABISysV_arm.h
+++ b/source/Plugins/ABI/SysV-arm/ABISysV_arm.h
@@ -20,7 +20,7 @@
class ABISysV_arm : public lldb_private::ABI
{
public:
- ~ABISysV_arm() { }
+ ~ABISysV_arm() override = default;
size_t
GetRedZoneSize () const override;
@@ -39,12 +39,6 @@ public:
lldb_private::Error
SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
- lldb::ValueObjectSP
- GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const override;
-
-public:
bool
CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan) override;
@@ -88,6 +82,7 @@ public:
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -103,6 +98,7 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
+
lldb_private::ConstString
GetPluginName() override;
@@ -110,6 +106,10 @@ public:
GetPluginVersion() override;
protected:
+ lldb::ValueObjectSP
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const override;
+
private:
ABISysV_arm() :
lldb_private::ABI()
@@ -118,4 +118,4 @@ private:
}
};
-#endif // liblldb_ABISysV_arm_h_
+#endif // liblldb_ABISysV_arm_h_
diff --git a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp
index ed058ff19d99..bc6df235cb1e 100644
--- a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp
+++ b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp
@@ -18,7 +18,6 @@
#include "lldb/Core/Scalar.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -37,7 +36,7 @@ using namespace lldb_private;
static RegisterInfo g_register_infos[] =
{
- // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE
+ // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE
// ========== ======= == === ============= =================== =================== ====================== =========================== ======================= ======================
{ "x0", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
{ "x1", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL },
@@ -313,7 +312,7 @@ ABISysV_arm64::GetArgumentValues (Thread &thread, ValueList &values) const
if (!value)
return false;
- ClangASTType value_type = value->GetClangType();
+ CompilerType value_type = value->GetCompilerType();
if (value_type)
{
bool is_signed = false;
@@ -397,7 +396,7 @@ ABISysV_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
return error;
}
- ClangASTType return_value_type = new_value_sp->GetClangType();
+ CompilerType return_value_type = new_value_sp->GetCompilerType();
if (!return_value_type)
{
error.SetErrorString ("Null clang type for return value.");
@@ -686,7 +685,7 @@ ABISysV_arm64::RegisterIsVolatile (const RegisterInfo *reg_info)
static bool
LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,
RegisterContext *reg_ctx,
- const ClangASTType &value_type,
+ const CompilerType &value_type,
bool is_return_value, // false => parameter, true => return value
uint32_t &NGRN, // NGRN (see ABI documentation)
uint32_t &NSRN, // NSRN (see ABI documentation)
@@ -701,18 +700,16 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,
const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();
Error error;
- ClangASTType base_type;
+ CompilerType base_type;
const uint32_t homogeneous_count = value_type.IsHomogeneousAggregate (&base_type);
if (homogeneous_count > 0 && homogeneous_count <= 8)
{
- printf ("ClangASTContext::IsHomogeneousAggregate() => %u\n", homogeneous_count);
// Make sure we have enough registers
if (NSRN < 8 && (8-NSRN) >= homogeneous_count)
{
if (!base_type)
return false;
const size_t base_byte_size = base_type.GetByteSize(nullptr);
- printf ("ClangASTContext::IsHomogeneousAggregate() => base_byte_size = %" PRIu64 "\n", (uint64_t) base_byte_size);
uint32_t data_offset = 0;
for (uint32_t i=0; i<homogeneous_count; ++i)
@@ -831,7 +828,7 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx,
}
ValueObjectSP
-ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
Value value;
@@ -840,16 +837,16 @@ ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)
return return_valobj_sp;
- //value.SetContext (Value::eContextTypeClangType, return_clang_type);
- value.SetClangType(return_clang_type);
+ //value.SetContext (Value::eContextTypeClangType, return_compiler_type);
+ value.SetCompilerType(return_compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return return_valobj_sp;
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
- const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL);
+ const uint32_t type_flags = return_compiler_type.GetTypeInfo (NULL);
if (type_flags & eTypeIsScalar ||
type_flags & eTypeIsPointer)
{
@@ -898,7 +895,7 @@ ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
exe_ctx.GetProcessRef().GetAddressByteSize());
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
return return_valobj_sp;
@@ -1015,7 +1012,7 @@ ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
byte_order,
exe_ctx.GetProcessRef().GetAddressByteSize());
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
}
@@ -1032,10 +1029,10 @@ ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
uint32_t NGRN = 0; // Search ABI docs for NGRN
uint32_t NSRN = 0; // Search ABI docs for NSRN
const bool is_return_value = true;
- if (LoadValueFromConsecutiveGPRRegisters (exe_ctx, reg_ctx, return_clang_type, is_return_value, NGRN, NSRN, data))
+ if (LoadValueFromConsecutiveGPRRegisters (exe_ctx, reg_ctx, return_compiler_type, is_return_value, NGRN, NSRN, data))
{
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
}
diff --git a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h
index 08c8682d8fa4..e36f87e744f4 100644
--- a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h
+++ b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h
@@ -20,7 +20,7 @@
class ABISysV_arm64 : public lldb_private::ABI
{
public:
- ~ABISysV_arm64() { }
+ ~ABISysV_arm64() override = default;
size_t
GetRedZoneSize () const override;
@@ -39,12 +39,6 @@ public:
lldb_private::Error
SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
- lldb::ValueObjectSP
- GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const override;
-
-public:
bool
CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan) override;
@@ -64,7 +58,6 @@ public:
// Whitelisting the trap handlers for user space would be easy (_sigtramp) but
// in other environments there can be a large number of different functions
// involved in async traps.
-
bool
CallFrameAddressIsValid (lldb::addr_t cfa) override
{
@@ -92,6 +85,7 @@ public:
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -107,6 +101,7 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
+
lldb_private::ConstString
GetPluginName() override;
@@ -114,6 +109,10 @@ public:
GetPluginVersion() override;
protected:
+ lldb::ValueObjectSP
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const override;
+
private:
ABISysV_arm64() :
lldb_private::ABI()
@@ -122,4 +121,4 @@ private:
}
};
-#endif // liblldb_ABISysV_arm64_h_
+#endif // liblldb_ABISysV_arm64_h_
diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
index 69129df1f16b..e0299b6f0b94 100644
--- a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
+++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
@@ -20,7 +20,6 @@
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/ValueObjectMemory.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
@@ -30,7 +29,7 @@
#include "llvm/ADT/Triple.h"
-#include "llvm/IR/Type.h"
+#include "llvm/IR/DerivedTypes.h"
using namespace lldb;
using namespace lldb_private;
@@ -227,7 +226,7 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,
// . handle 64bit values and their register / stack requirements
*/
-#define HEX_ABI_DEBUG 1
+#define HEX_ABI_DEBUG 0
bool
ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,
lldb::addr_t sp ,
@@ -243,6 +242,23 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,
// grab the process so we have access to the memory for spilling
lldb::ProcessSP proc = thread.GetProcess( );
+ // get the register context for modifying all of the registers
+ RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+ if (!reg_ctx)
+ return false;
+
+ uint32_t pc_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ if (pc_reg == LLDB_INVALID_REGNUM)
+ return false;
+
+ uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
+ if (ra_reg == LLDB_INVALID_REGNUM)
+ return false;
+
+ uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+ if (sp_reg == LLDB_INVALID_REGNUM)
+ return false;
+
// push host data onto target
for ( size_t i = 0; i < args.size( ); i++ )
{
@@ -277,11 +293,6 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,
// check if this is a variable argument function
bool isVArg = prototype.isFunctionVarArg();
- // get the register context for modifying all of the registers
- RegisterContext *reg_ctx = thread.GetRegisterContext().get();
- if (!reg_ctx)
- return false;
-
// number of arguments passed by register
int nRegArgs = nVArgRegParams;
if (! isVArg )
@@ -324,10 +335,9 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread,
}
// update registers with current function call state
- reg_ctx->WriteRegisterFromUnsigned ( 41, pc );
- reg_ctx->WriteRegisterFromUnsigned ( 31, ra );
- reg_ctx->WriteRegisterFromUnsigned ( 29, sp );
-// reg_ctx->WriteRegisterFromUnsigned ( FP ??? );
+ reg_ctx->WriteRegisterFromUnsigned(pc_reg, pc);
+ reg_ctx->WriteRegisterFromUnsigned(ra_reg, ra);
+ reg_ctx->WriteRegisterFromUnsigned(sp_reg, sp);
#if HEX_ABI_DEBUG
// quick and dirty stack dumper for debugging
@@ -359,14 +369,14 @@ ABISysV_hexagon::SetReturnValueObject ( lldb::StackFrameSP &frame_sp, lldb::Valu
}
ValueObjectSP
-ABISysV_hexagon::GetReturnValueObjectSimple ( Thread &thread, ClangASTType &return_clang_type ) const
+ABISysV_hexagon::GetReturnValueObjectSimple ( Thread &thread, CompilerType &return_compiler_type ) const
{
ValueObjectSP return_valobj_sp;
return return_valobj_sp;
}
ValueObjectSP
-ABISysV_hexagon::GetReturnValueObjectImpl ( Thread &thread, ClangASTType &return_clang_type ) const
+ABISysV_hexagon::GetReturnValueObjectImpl ( Thread &thread, CompilerType &return_compiler_type ) const
{
ValueObjectSP return_valobj_sp;
return return_valobj_sp;
diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h
index 1550a38c4f3b..337e3fdcf7b5 100644
--- a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h
+++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h
@@ -21,63 +21,54 @@ class ABISysV_hexagon :
public lldb_private::ABI
{
public:
+ ~ABISysV_hexagon() override = default;
- ~ABISysV_hexagon( void )
- {
- }
-
- virtual size_t
- GetRedZoneSize ( void ) const;
+ size_t
+ GetRedZoneSize() const override;
- virtual bool
- PrepareTrivialCall ( lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t functionAddress,
- lldb::addr_t returnAddress,
- llvm::ArrayRef<lldb::addr_t> args ) const;
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const override;
// special thread plan for GDB style non-jit function calls
- virtual bool
- PrepareTrivialCall ( lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t functionAddress,
- lldb::addr_t returnAddress,
- llvm::Type &prototype,
- llvm::ArrayRef<ABI::CallArgument> args ) const;
-
- virtual bool
- GetArgumentValues ( lldb_private::Thread &thread,
- lldb_private::ValueList &values ) const;
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::Type &prototype,
+ llvm::ArrayRef<ABI::CallArgument> args) const override;
+
+ bool
+ GetArgumentValues(lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
- virtual lldb_private::Error
- SetReturnValueObject ( lldb::StackFrameSP &frame_sp,
- lldb::ValueObjectSP &new_value );
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp,
+ lldb::ValueObjectSP &new_value) override;
-protected:
lldb::ValueObjectSP
- GetReturnValueObjectSimple ( lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type ) const;
-
-public:
- virtual lldb::ValueObjectSP
- GetReturnValueObjectImpl ( lldb_private::Thread &thread,
- lldb_private::ClangASTType &type ) const;
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &type) const override;
// specialized to work with llvm IR types
- virtual lldb::ValueObjectSP
- GetReturnValueObjectImpl ( lldb_private::Thread &thread, llvm::Type &type ) const;
+ lldb::ValueObjectSP
+ GetReturnValueObjectImpl(lldb_private::Thread &thread, llvm::Type &type) const override;
- virtual bool
- CreateFunctionEntryUnwindPlan ( lldb_private::UnwindPlan &unwind_plan );
+ bool
+ CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- CreateDefaultUnwindPlan ( lldb_private::UnwindPlan &unwind_plan );
+ bool
+ CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- RegisterIsVolatile ( const lldb_private::RegisterInfo *reg_info );
+ bool
+ RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
- virtual bool
- CallFrameAddressIsValid ( lldb::addr_t cfa )
+ bool
+ CallFrameAddressIsValid(lldb::addr_t cfa) override
{
// Make sure the stack call frame addresses are 8 byte aligned
if (cfa & 0x07)
@@ -87,50 +78,60 @@ public:
return true;
}
- virtual bool
- CodeAddressIsValid ( lldb::addr_t pc )
+ bool
+ CodeAddressIsValid(lldb::addr_t pc) override
{
// We have a 64 bit address space, so anything is valid as opcodes
// aren't fixed width...
return true;
}
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoArray ( uint32_t &count );
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray(uint32_t &count) override;
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
- Initialize ( void );
+ Initialize();
static void
- Terminate ( void );
+ Terminate();
static lldb::ABISP
CreateInstance ( const lldb_private::ArchSpec &arch );
static lldb_private::ConstString
- GetPluginNameStatic ( void );
+ GetPluginNameStatic();
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName ( void );
- virtual uint32_t
- GetPluginVersion ( void );
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
protected:
void
- CreateRegisterMapIfNeeded ( void );
+ CreateRegisterMapIfNeeded();
+
+ lldb::ValueObjectSP
+ GetReturnValueObjectSimple(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const;
bool
RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
private:
- ABISysV_hexagon ( void ) : lldb_private::ABI() { } // Call CreateInstance instead.
+ ABISysV_hexagon() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
};
-#endif // liblldb_ABISysV_hexagon_h_
+#endif // liblldb_ABISysV_hexagon_h_
diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
index 26da9aeb370d..0a3779a2ce94 100644
--- a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
+++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
@@ -19,7 +19,6 @@
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/ValueObjectMemory.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
@@ -59,171 +58,109 @@ using namespace lldb_private;
// Comment: Table 2.14 is followed till 'mm' entries.
// After that, all entries are ignored here.
-enum gcc_dwarf_regnums
+enum dwarf_regnums
{
- gcc_dwarf_eax = 0,
- gcc_dwarf_ecx,
- gcc_dwarf_edx,
- gcc_dwarf_ebx,
- gcc_dwarf_esp,
- gcc_dwarf_ebp,
- gcc_dwarf_esi,
- gcc_dwarf_edi,
- gcc_dwarf_eip,
- gcc_dwarf_eflags,
-
- gcc_dwarf_st0 = 11,
- gcc_dwarf_st1,
- gcc_dwarf_st2,
- gcc_dwarf_st3,
- gcc_dwarf_st4,
- gcc_dwarf_st5,
- gcc_dwarf_st6,
- gcc_dwarf_st7,
-
- gcc_dwarf_xmm0 = 21,
- gcc_dwarf_xmm1,
- gcc_dwarf_xmm2,
- gcc_dwarf_xmm3,
- gcc_dwarf_xmm4,
- gcc_dwarf_xmm5,
- gcc_dwarf_xmm6,
- gcc_dwarf_xmm7,
- gcc_dwarf_ymm0 = gcc_dwarf_xmm0,
- gcc_dwarf_ymm1 = gcc_dwarf_xmm1,
- gcc_dwarf_ymm2 = gcc_dwarf_xmm2,
- gcc_dwarf_ymm3 = gcc_dwarf_xmm3,
- gcc_dwarf_ymm4 = gcc_dwarf_xmm4,
- gcc_dwarf_ymm5 = gcc_dwarf_xmm5,
- gcc_dwarf_ymm6 = gcc_dwarf_xmm6,
- gcc_dwarf_ymm7 = gcc_dwarf_xmm7,
-
- gcc_dwarf_mm0 = 29,
- gcc_dwarf_mm1,
- gcc_dwarf_mm2,
- gcc_dwarf_mm3,
- gcc_dwarf_mm4,
- gcc_dwarf_mm5,
- gcc_dwarf_mm6,
- gcc_dwarf_mm7
-};
-
-
-enum gdb_regnums
-{
- gdb_eax = 0,
- gdb_ecx = 1,
- gdb_edx = 2,
- gdb_ebx = 3,
- gdb_esp = 4,
- gdb_ebp = 5,
- gdb_esi = 6,
- gdb_edi = 7,
- gdb_eip = 8,
- gdb_eflags = 9,
- gdb_cs = 10,
- gdb_ss = 11,
- gdb_ds = 12,
- gdb_es = 13,
- gdb_fs = 14,
- gdb_gs = 15,
- gdb_st0 = 16,
- gdb_st1 = 17,
- gdb_st2 = 18,
- gdb_st3 = 19,
- gdb_st4 = 20,
- gdb_st5 = 21,
- gdb_st6 = 22,
- gdb_st7 = 23,
- gdb_fctrl = 24, gdb_fcw = gdb_fctrl,
- gdb_fstat = 25, gdb_fsw = gdb_fstat,
- gdb_ftag = 26, gdb_ftw = gdb_ftag,
- gdb_fiseg = 27, gdb_fpu_cs = gdb_fiseg,
- gdb_fioff = 28, gdb_ip = gdb_fioff,
- gdb_foseg = 29, gdb_fpu_ds = gdb_foseg,
- gdb_fooff = 30, gdb_dp = gdb_fooff,
- gdb_fop = 31,
- gdb_xmm0 = 32,
- gdb_xmm1 = 33,
- gdb_xmm2 = 34,
- gdb_xmm3 = 35,
- gdb_xmm4 = 36,
- gdb_xmm5 = 37,
- gdb_xmm6 = 38,
- gdb_xmm7 = 39,
- gdb_mxcsr = 40,
- gdb_mm0 = 41,
- gdb_mm1 = 42,
- gdb_mm2 = 43,
- gdb_mm3 = 44,
- gdb_mm4 = 45,
- gdb_mm5 = 46,
- gdb_mm6 = 47,
- gdb_mm7 = 48,
- gdb_ymm0 = gdb_xmm0,
- gdb_ymm1 = gdb_xmm1,
- gdb_ymm2 = gdb_xmm2,
- gdb_ymm3 = gdb_xmm3,
- gdb_ymm4 = gdb_xmm4,
- gdb_ymm5 = gdb_xmm5,
- gdb_ymm6 = gdb_xmm6,
- gdb_ymm7 = gdb_xmm7
+ dwarf_eax = 0,
+ dwarf_ecx,
+ dwarf_edx,
+ dwarf_ebx,
+ dwarf_esp,
+ dwarf_ebp,
+ dwarf_esi,
+ dwarf_edi,
+ dwarf_eip,
+ dwarf_eflags,
+
+ dwarf_st0 = 11,
+ dwarf_st1,
+ dwarf_st2,
+ dwarf_st3,
+ dwarf_st4,
+ dwarf_st5,
+ dwarf_st6,
+ dwarf_st7,
+
+ dwarf_xmm0 = 21,
+ dwarf_xmm1,
+ dwarf_xmm2,
+ dwarf_xmm3,
+ dwarf_xmm4,
+ dwarf_xmm5,
+ dwarf_xmm6,
+ dwarf_xmm7,
+ dwarf_ymm0 = dwarf_xmm0,
+ dwarf_ymm1 = dwarf_xmm1,
+ dwarf_ymm2 = dwarf_xmm2,
+ dwarf_ymm3 = dwarf_xmm3,
+ dwarf_ymm4 = dwarf_xmm4,
+ dwarf_ymm5 = dwarf_xmm5,
+ dwarf_ymm6 = dwarf_xmm6,
+ dwarf_ymm7 = dwarf_xmm7,
+
+ dwarf_mm0 = 29,
+ dwarf_mm1,
+ dwarf_mm2,
+ dwarf_mm3,
+ dwarf_mm4,
+ dwarf_mm5,
+ dwarf_mm6,
+ dwarf_mm7
};
static RegisterInfo g_register_infos[] =
{
- // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
+ // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS
// ====== ======= == === ============= ============ ===================== ===================== ============================ ==================== ====================== ========== ===============
- { "eax", nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_eax , gcc_dwarf_eax , LLDB_INVALID_REGNUM , gdb_eax , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ebx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_ebx , gcc_dwarf_ebx , LLDB_INVALID_REGNUM , gdb_ebx , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ecx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_ecx , gcc_dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , gdb_ecx , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "edx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_edx , gcc_dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , gdb_edx , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "esi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_esi , gcc_dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , gdb_esi , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "edi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_edi , gcc_dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , gdb_edi , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_ebp , gcc_dwarf_ebp , LLDB_REGNUM_GENERIC_FP , gdb_ebp , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_esp , gcc_dwarf_esp , LLDB_REGNUM_GENERIC_SP , gdb_esp , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_eip , gcc_dwarf_eip , LLDB_REGNUM_GENERIC_PC , gdb_eip , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "eflags", nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "cs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_cs , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ss" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ss , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ds" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ds , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "es" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_es , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "fs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fs , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "gs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gs , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "st0" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st0 , LLDB_INVALID_REGNUM , gdb_st0 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "st1" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st1 , LLDB_INVALID_REGNUM , gdb_st1 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "st2" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st2 , LLDB_INVALID_REGNUM , gdb_st2 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "st3" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st3 , LLDB_INVALID_REGNUM , gdb_st3 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "st4" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st4 , LLDB_INVALID_REGNUM , gdb_st4 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "st5" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st5 , LLDB_INVALID_REGNUM , gdb_st5 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "st6" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st6 , LLDB_INVALID_REGNUM , gdb_st6 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "st7" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st7 , LLDB_INVALID_REGNUM , gdb_st7 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "fctrl" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fctrl , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "fstat" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fstat , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ftag" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ftag , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "fiseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fiseg , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "fioff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fioff , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "foseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_foseg , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "fooff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fooff , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "fop" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fop , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "xmm0" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm0 , LLDB_INVALID_REGNUM , gdb_xmm0 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "xmm1" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm1 , LLDB_INVALID_REGNUM , gdb_xmm1 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "xmm2" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm2 , LLDB_INVALID_REGNUM , gdb_xmm2 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "xmm3" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm3 , LLDB_INVALID_REGNUM , gdb_xmm3 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "xmm4" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm4 , LLDB_INVALID_REGNUM , gdb_xmm4 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "xmm5" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm5 , LLDB_INVALID_REGNUM , gdb_xmm5 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "xmm6" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm6 , LLDB_INVALID_REGNUM , gdb_xmm6 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "xmm7" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm7 , LLDB_INVALID_REGNUM , gdb_xmm7 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "mxcsr" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_mxcsr , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ymm0" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm0 , LLDB_INVALID_REGNUM , gdb_ymm0 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ymm1" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm1 , LLDB_INVALID_REGNUM , gdb_ymm1 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ymm2" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm2 , LLDB_INVALID_REGNUM , gdb_ymm2 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ymm3" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm3 , LLDB_INVALID_REGNUM , gdb_ymm3 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ymm4" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm4 , LLDB_INVALID_REGNUM , gdb_ymm4 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ymm5" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm5 , LLDB_INVALID_REGNUM , gdb_ymm5 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ymm6" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm6 , LLDB_INVALID_REGNUM , gdb_ymm6 , LLDB_INVALID_REGNUM }, nullptr, nullptr},
- { "ymm7" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm7 , LLDB_INVALID_REGNUM , gdb_ymm7 , LLDB_INVALID_REGNUM }, nullptr, nullptr}
+ { "eax", nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_eax , dwarf_eax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ebx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ecx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_ecx , dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "edx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_edx , dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "esi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_esi , dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "edi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_edi , dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { dwarf_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { dwarf_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { dwarf_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "eflags", nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "cs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ss" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ds" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "es" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "gs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st0" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st1" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st2" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st3" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st4" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st5" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st6" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "st7" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fctrl" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fstat" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ftag" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fiseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fioff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "foseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fooff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "fop" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm0" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm1" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm2" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm3" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm4" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm5" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm6" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "xmm7" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "mxcsr" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm0" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm1" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm2" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm3" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm4" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm5" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm6" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr},
+ { "ymm7" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}
};
static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
@@ -387,22 +324,22 @@ ABISysV_i386::GetArgumentValues (Thread &thread,
return false;
// Currently: Support for extracting values with Clang QualTypes only.
- ClangASTType clang_type (value->GetClangType());
- if (clang_type)
+ CompilerType compiler_type (value->GetCompilerType());
+ if (compiler_type)
{
bool is_signed;
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
is_signed,
thread.GetProcess().get(),
current_stack_argument);
}
- else if (clang_type.IsPointerType())
+ else if (compiler_type.IsPointerType())
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
false,
thread.GetProcess().get(),
current_stack_argument);
@@ -418,29 +355,170 @@ Error
ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
{
Error error;
- //ToDo: Yet to be implemented
- error.SetErrorString("ABISysV_i386::SetReturnValueObject(): Not implemented yet");
+ if (!new_value_sp)
+ {
+ error.SetErrorString("Empty value object for return value.");
+ return error;
+ }
+
+ CompilerType compiler_type = new_value_sp->GetCompilerType();
+ if (!compiler_type)
+ {
+ error.SetErrorString ("Null clang type for return value.");
+ return error;
+ }
+
+ const uint32_t type_flags = compiler_type.GetTypeInfo ();
+ Thread *thread = frame_sp->GetThread().get();
+ RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+ DataExtractor data;
+ Error data_error;
+ size_t num_bytes = new_value_sp->GetData(data, data_error);
+ bool register_write_successful = true;
+
+ if (data_error.Fail())
+ {
+ error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
+ return error;
+ }
+
+ // Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
+ // The terminology 'Fundamental Data Types' used here is adopted from
+ // Table 2.1 of the reference document (specified on top of this file)
+
+ if (type_flags & eTypeIsPointer) // 'Pointer'
+ {
+ if(num_bytes != sizeof(uint32_t))
+ {
+ error.SetErrorString("Pointer to be returned is not 4 bytes wide");
+ return error;
+ }
+ lldb::offset_t offset = 0;
+ const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
+ register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value);
+ }
+ else if ((type_flags & eTypeIsScalar) || (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
+ {
+ lldb::offset_t offset = 0;
+ const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
+
+ if (type_flags & eTypeIsInteger) // 'Integral' except enum
+ {
+ switch (num_bytes)
+ {
+ default:
+ break;
+ case 16:
+ // For clang::BuiltinType::UInt128 & Int128
+ // ToDo: Need to decide how to handle it
+ break;
+ case 8:
+ {
+ uint32_t raw_value_low = data.GetMaxU32(&offset, 4);
+ const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0);
+ uint32_t raw_value_high = data.GetMaxU32(&offset, num_bytes - offset);
+ register_write_successful = (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value_low) &&
+ reg_ctx->WriteRegisterFromUnsigned (edx_info, raw_value_high));
+ break;
+ }
+ case 4:
+ case 2:
+ case 1:
+ {
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
+ register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value);
+ break;
+ }
+ }
+ }
+ else if (type_flags & eTypeIsEnumeration) // handles enum
+ {
+ uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
+ register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value);
+ }
+ else if (type_flags & eTypeIsFloat) // 'Floating Point'
+ {
+ RegisterValue st0_value, fstat_value, ftag_value;
+ const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
+ const RegisterInfo *fstat_info = reg_ctx->GetRegisterInfoByName("fstat", 0);
+ const RegisterInfo *ftag_info = reg_ctx->GetRegisterInfoByName("ftag", 0);
+
+ /* According to Page 3-12 of document
+ System V Application Binary Interface, Intel386 Architecture Processor Supplement, Fourth Edition
+ To return Floating Point values, all st% registers except st0 should be empty after exiting from
+ a function. This requires setting fstat and ftag registers to specific values.
+ fstat: The TOP field of fstat should be set to a value [0,7]. ABI doesn't specify the specific
+ value of TOP in case of function return. Hence, we set the TOP field to 7 by our choice. */
+ uint32_t value_fstat_u32 = 0x00003800;
+
+ /* ftag: Implication of setting TOP to 7 and indicating all st% registers empty except st0 is to set
+ 7th bit of 4th byte of FXSAVE area to 1 and all other bits of this byte to 0. This is in accordance
+ with the document Intel 64 and IA-32 Architectures Software Developer's Manual, January 2015 */
+ uint32_t value_ftag_u32 = 0x00000080;
+
+ if (num_bytes <= 12) // handles float, double, long double, __float80
+ {
+ long double value_long_dbl = 0.0;
+ if (num_bytes == 4)
+ value_long_dbl = data.GetFloat(&offset);
+ else if (num_bytes == 8)
+ value_long_dbl = data.GetDouble(&offset);
+ else if (num_bytes == 12)
+ value_long_dbl = data.GetLongDouble(&offset);
+ else
+ {
+ error.SetErrorString ("Invalid number of bytes for this return type");
+ return error;
+ }
+ st0_value.SetLongDouble(value_long_dbl);
+ fstat_value.SetUInt32(value_fstat_u32);
+ ftag_value.SetUInt32(value_ftag_u32);
+ register_write_successful = reg_ctx->WriteRegister(st0_info, st0_value) &&
+ reg_ctx->WriteRegister(fstat_info, fstat_value) &&
+ reg_ctx->WriteRegister(ftag_info, ftag_value);
+ }
+ else if(num_bytes == 16) // handles __float128
+ {
+ error.SetErrorString ("Implementation is missing for this clang type.");
+ }
+ }
+ else
+ {
+ // Neither 'Integral' nor 'Floating Point'. If flow reaches here
+ // then check type_flags. This type_flags is not a valid type.
+ error.SetErrorString ("Invalid clang type");
+ }
+ }
+ else
+ {
+ /* 'Complex Floating Point', 'Packed', 'Decimal Floating Point' and 'Aggregate' data types
+ are yet to be implemented */
+ error.SetErrorString ("Currently only Integral and Floating Point clang types are supported.");
+ }
+ if(!register_write_successful)
+ error.SetErrorString ("Register writing failed");
return error;
}
ValueObjectSP
ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,
- ClangASTType &return_clang_type) const
+ CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
Value value;
- if (!return_clang_type)
+ if (!return_compiler_type)
return return_valobj_sp;
- value.SetClangType (return_clang_type);
+ value.SetCompilerType (return_compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return return_valobj_sp;
- const uint32_t type_flags = return_clang_type.GetTypeInfo ();
+ const uint32_t type_flags = return_compiler_type.GetTypeInfo ();
unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
@@ -463,7 +541,7 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,
else if ((type_flags & eTypeIsScalar) || (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
{
value.SetValueType(Value::eValueTypeScalar);
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
bool success = false;
if (type_flags & eTypeIsInteger) // 'Integral' except enum
@@ -579,7 +657,7 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,
return_valobj_sp = ValueObjectMemory::Create (&thread,
"",
Address (storage_addr, nullptr),
- return_clang_type);
+ return_compiler_type);
}
}
@@ -597,16 +675,12 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,
else if (type_flags & eTypeIsVector) // 'Packed'
{
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
if (byte_size > 0)
{
- const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("ymm0", 0);
+ const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
if (vec_reg == nullptr)
- {
- vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
- if (vec_reg == nullptr)
- vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
- }
+ vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
if (vec_reg)
{
@@ -631,13 +705,52 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,
byte_order,
process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
}
}
}
}
+ else if (byte_size <= vec_reg->byte_size*2)
+ {
+ const RegisterInfo *vec_reg2 = reg_ctx->GetRegisterInfoByName("xmm1", 0);
+ if (vec_reg2)
+ {
+ ProcessSP process_sp (thread.GetProcess());
+ if (process_sp)
+ {
+ std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
+ const ByteOrder byte_order = process_sp->GetByteOrder();
+ RegisterValue reg_value;
+ RegisterValue reg_value2;
+ if (reg_ctx->ReadRegister(vec_reg, reg_value) && reg_ctx->ReadRegister(vec_reg2, reg_value2))
+ {
+
+ Error error;
+ if (reg_value.GetAsMemoryData (vec_reg,
+ heap_data_ap->GetBytes(),
+ vec_reg->byte_size,
+ byte_order,
+ error) &&
+ reg_value2.GetAsMemoryData (vec_reg2,
+ heap_data_ap->GetBytes() + vec_reg->byte_size,
+ heap_data_ap->GetByteSize() - vec_reg->byte_size,
+ byte_order,
+ error))
+ {
+ DataExtractor data (DataBufferSP (heap_data_ap.release()),
+ byte_order,
+ process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_compiler_type,
+ ConstString(""),
+ data);
+ }
+ }
+ }
+ }
+ }
}
}
}
@@ -651,15 +764,15 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,
ValueObjectSP
-ABISysV_i386::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+ABISysV_i386::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
- if (!return_clang_type)
+ if (!return_compiler_type)
return return_valobj_sp;
ExecutionContext exe_ctx (thread.shared_from_this());
- return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type);
+ return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
if (return_valobj_sp)
return return_valobj_sp;
@@ -667,14 +780,14 @@ ABISysV_i386::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cla
if (!reg_ctx_sp)
return return_valobj_sp;
- if (return_clang_type.IsAggregateType())
+ if (return_compiler_type.IsAggregateType())
{
unsigned eax_id = reg_ctx_sp->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
lldb::addr_t storage_addr = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
return_valobj_sp = ValueObjectMemory::Create (&thread,
"",
Address (storage_addr, nullptr),
- return_clang_type);
+ return_compiler_type);
}
return return_valobj_sp;
@@ -690,8 +803,8 @@ ABISysV_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
unwind_plan.Clear();
unwind_plan.SetRegisterKind (eRegisterKindDWARF);
- uint32_t sp_reg_num = gcc_dwarf_esp;
- uint32_t pc_reg_num = gcc_dwarf_eip;
+ uint32_t sp_reg_num = dwarf_esp;
+ uint32_t pc_reg_num = dwarf_eip;
UnwindPlan::RowSP row(new UnwindPlan::Row);
row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4);
@@ -714,9 +827,9 @@ ABISysV_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
unwind_plan.Clear();
unwind_plan.SetRegisterKind (eRegisterKindDWARF);
- uint32_t fp_reg_num = gcc_dwarf_ebp;
- uint32_t sp_reg_num = gcc_dwarf_esp;
- uint32_t pc_reg_num = gcc_dwarf_eip;
+ uint32_t fp_reg_num = dwarf_ebp;
+ uint32_t sp_reg_num = dwarf_esp;
+ uint32_t pc_reg_num = dwarf_eip;
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 4;
diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.h b/source/Plugins/ABI/SysV-i386/ABISysV_i386.h
index 9612f900d2ce..2d0f097c328e 100644
--- a/source/Plugins/ABI/SysV-i386/ABISysV_i386.h
+++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.h
@@ -21,10 +21,7 @@ class ABISysV_i386 :
public lldb_private::ABI
{
public:
-
- ~ABISysV_i386()
- {
- }
+ ~ABISysV_i386() override = default;
size_t
GetRedZoneSize () const override
@@ -46,18 +43,9 @@ public:
lldb_private::Error
SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
- lldb::ValueObjectSP
- GetReturnValueObjectSimple (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const;
-
- bool
- RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
-
-public:
lldb::ValueObjectSP
GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &type) const override;
+ lldb_private::CompilerType &type) const override;
bool
CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan) override;
@@ -104,9 +92,11 @@ public:
const lldb_private::RegisterInfo *
GetRegisterInfoArray (uint32_t &count) override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -119,6 +109,7 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
+
static lldb_private::ConstString
GetPluginNameStatic();
@@ -126,13 +117,25 @@ public:
GetPluginName() override;
uint32_t
- GetPluginVersion() override
+ GetPluginVersion() override
{
return 1;
}
+protected:
+ lldb::ValueObjectSP
+ GetReturnValueObjectSimple(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const;
+
+ bool
+ RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info);
+
private:
- ABISysV_i386() : lldb_private::ABI() { } // Call CreateInstance instead.
+ ABISysV_i386() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
};
-#endif // liblldb_ABI_h
+#endif // liblldb_ABISysV_i386_h_
diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp
index e1fc13a691af..3c7e9495d6ce 100644
--- a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp
+++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp
@@ -20,7 +20,6 @@
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/ValueObjectMemory.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
@@ -34,133 +33,91 @@
using namespace lldb;
using namespace lldb_private;
-enum gcc_dwarf_regnums
+enum dwarf_regnums
{
- gcc_dwarf_r0 = 0,
- gcc_dwarf_r1,
- gcc_dwarf_r2,
- gcc_dwarf_r3,
- gcc_dwarf_r4,
- gcc_dwarf_r5,
- gcc_dwarf_r6,
- gcc_dwarf_r7,
- gcc_dwarf_r8,
- gcc_dwarf_r9,
- gcc_dwarf_r10,
- gcc_dwarf_r11,
- gcc_dwarf_r12,
- gcc_dwarf_r13,
- gcc_dwarf_r14,
- gcc_dwarf_r15,
- gcc_dwarf_r16,
- gcc_dwarf_r17,
- gcc_dwarf_r18,
- gcc_dwarf_r19,
- gcc_dwarf_r20,
- gcc_dwarf_r21,
- gcc_dwarf_r22,
- gcc_dwarf_r23,
- gcc_dwarf_r24,
- gcc_dwarf_r25,
- gcc_dwarf_r26,
- gcc_dwarf_r27,
- gcc_dwarf_r28,
- gcc_dwarf_r29,
- gcc_dwarf_r30,
- gcc_dwarf_r31,
- gcc_dwarf_sr,
- gcc_dwarf_lo,
- gcc_dwarf_hi,
- gcc_dwarf_bad,
- gcc_dwarf_cause,
- gcc_dwarf_pc
-};
-
-enum gdb_regnums
-{
- gdb_r0 = 0,
- gdb_r1,
- gdb_r2,
- gdb_r3,
- gdb_r4,
- gdb_r5,
- gdb_r6,
- gdb_r7,
- gdb_r8,
- gdb_r9,
- gdb_r10,
- gdb_r11,
- gdb_r12,
- gdb_r13,
- gdb_r14,
- gdb_r15,
- gdb_r16,
- gdb_r17,
- gdb_r18,
- gdb_r19,
- gdb_r20,
- gdb_r21,
- gdb_r22,
- gdb_r23,
- gdb_r24,
- gdb_r25,
- gdb_r26,
- gdb_r27,
- gdb_r28,
- gdb_r29,
- gdb_r30,
- gdb_r31,
- gdb_sr,
- gdb_lo,
- gdb_hi,
- gdb_bad,
- gdb_cause,
- gdb_pc
+ dwarf_r0 = 0,
+ dwarf_r1,
+ dwarf_r2,
+ dwarf_r3,
+ dwarf_r4,
+ dwarf_r5,
+ dwarf_r6,
+ dwarf_r7,
+ dwarf_r8,
+ dwarf_r9,
+ dwarf_r10,
+ dwarf_r11,
+ dwarf_r12,
+ dwarf_r13,
+ dwarf_r14,
+ dwarf_r15,
+ dwarf_r16,
+ dwarf_r17,
+ dwarf_r18,
+ dwarf_r19,
+ dwarf_r20,
+ dwarf_r21,
+ dwarf_r22,
+ dwarf_r23,
+ dwarf_r24,
+ dwarf_r25,
+ dwarf_r26,
+ dwarf_r27,
+ dwarf_r28,
+ dwarf_r29,
+ dwarf_r30,
+ dwarf_r31,
+ dwarf_sr,
+ dwarf_lo,
+ dwarf_hi,
+ dwarf_bad,
+ dwarf_cause,
+ dwarf_pc
};
static const RegisterInfo
g_register_infos[] =
{
- // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
- // ======== ====== == === ============= =================== ============ ===================== ==================== ================= ====================== ========== ===============
- { "r0" , "zero", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r1" , "AT", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r1, gcc_dwarf_r1, LLDB_INVALID_REGNUM, gdb_r1, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r2" , "v0", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r3" , "v1", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r3, gcc_dwarf_r3, LLDB_INVALID_REGNUM, gdb_r3, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r4" , "arg1", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, gdb_r4, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r5" , "arg2", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, gdb_r5, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r6" , "arg3", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, gdb_r6, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r7" , "arg4", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, gdb_r7, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r8" , "arg5", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r8, gcc_dwarf_r8, LLDB_INVALID_REGNUM, gdb_r8, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r9" , "arg6", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r9, gcc_dwarf_r9, LLDB_INVALID_REGNUM, gdb_r9, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r10" , "arg7", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r10, gcc_dwarf_r10, LLDB_INVALID_REGNUM, gdb_r10, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r11" , "arg8", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r11, gcc_dwarf_r11, LLDB_INVALID_REGNUM, gdb_r11, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r12" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r13" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r14" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r15" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r16" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r17" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r18" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r19" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r20" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r21" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r22" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r23" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r24" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r25" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r26" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r27" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r28" , "gp", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r29" , "sp", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r29, gcc_dwarf_r29, LLDB_REGNUM_GENERIC_SP, gdb_r29, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r30" , "fp", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r30, gcc_dwarf_r30, LLDB_REGNUM_GENERIC_FP, gdb_r30, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r31" , "ra", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r31, gcc_dwarf_r31, LLDB_REGNUM_GENERIC_RA, gdb_r31, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "sr" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_sr, gcc_dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, gdb_sr, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "lo" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_lo, gcc_dwarf_lo, LLDB_INVALID_REGNUM, gdb_lo, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "hi" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_hi, gcc_dwarf_hi, LLDB_INVALID_REGNUM, gdb_hi, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "bad" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_bad, gcc_dwarf_bad, LLDB_INVALID_REGNUM, gdb_bad, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "cause" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cause, gcc_dwarf_cause, LLDB_INVALID_REGNUM, gdb_cause, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "pc" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_pc, LLDB_INVALID_REGNUM }, NULL, NULL},
+ // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGINS LLDB NATIVE VALUE REGS INVALIDATE REGS
+ // ======== ====== == === ============= =========== ============ ============== ============ ================= =================== ========== =================
+ { "r0" , "zero", 4, 0, eEncodingUint, eFormatHex, { dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r1" , "AT", 4, 0, eEncodingUint, eFormatHex, { dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r2" , "v0", 4, 0, eEncodingUint, eFormatHex, { dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r3" , "v1", 4, 0, eEncodingUint, eFormatHex, { dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r4" , "arg1", 4, 0, eEncodingUint, eFormatHex, { dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r5" , "arg2", 4, 0, eEncodingUint, eFormatHex, { dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r6" , "arg3", 4, 0, eEncodingUint, eFormatHex, { dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r7" , "arg4", 4, 0, eEncodingUint, eFormatHex, { dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r8" , "arg5", 4, 0, eEncodingUint, eFormatHex, { dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r9" , "arg6", 4, 0, eEncodingUint, eFormatHex, { dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r10" , "arg7", 4, 0, eEncodingUint, eFormatHex, { dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r11" , "arg8", 4, 0, eEncodingUint, eFormatHex, { dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r12" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r13" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r14" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r15" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r16" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r17" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r18" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r19" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r20" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r21" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r22" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r23" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r24" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r25" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r26" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r27" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r28" , "gp", 4, 0, eEncodingUint, eFormatHex, { dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r29" , "sp", 4, 0, eEncodingUint, eFormatHex, { dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r30" , "fp", 4, 0, eEncodingUint, eFormatHex, { dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r31" , "ra", 4, 0, eEncodingUint, eFormatHex, { dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "sr" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "lo" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "hi" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "bad" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "cause" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "pc" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
};
static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
@@ -284,6 +241,7 @@ ABISysV_mips::PrepareTrivialCall (Thread &thread,
const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
const RegisterInfo *ra_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
+ const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);
if (log)
log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
@@ -305,7 +263,14 @@ ABISysV_mips::PrepareTrivialCall (Thread &thread,
// Set pc to the address of the called function.
if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr))
return false;
-
+
+ if (log)
+ log->Printf("Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
+
+ // All callers of position independent functions must place the address of the called function in t9 (r25)
+ if (!reg_ctx->WriteRegisterFromUnsigned (r25_info, func_addr))
+ return false;
+
return true;
}
@@ -325,8 +290,8 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje
return error;
}
- ClangASTType clang_type = new_value_sp->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = new_value_sp->GetCompilerType();
+ if (!compiler_type)
{
error.SetErrorString ("Null clang type for return value.");
return error;
@@ -341,7 +306,7 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje
RegisterContext *reg_ctx = thread->GetRegisterContext().get();
bool set_it_simple = false;
- if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())
{
DataExtractor data;
Error data_error;
@@ -382,7 +347,7 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje
error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
}
}
- else if (clang_type.IsFloatingPointType (count, is_complex))
+ else if (compiler_type.IsFloatingPointType (count, is_complex))
{
if (is_complex)
error.SetErrorString ("We don't support returning complex values at present");
@@ -398,40 +363,41 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje
ValueObjectSP
-ABISysV_mips::GetReturnValueObjectSimple (Thread &thread, ClangASTType &return_clang_type) const
+ABISysV_mips::GetReturnValueObjectSimple (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
return return_valobj_sp;
}
ValueObjectSP
-ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
Value value;
- if (!return_clang_type)
+ if (!return_compiler_type)
return return_valobj_sp;
ExecutionContext exe_ctx (thread.shared_from_this());
if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)
return return_valobj_sp;
- value.SetClangType(return_clang_type);
+ value.SetCompilerType(return_compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return return_valobj_sp;
- bool is_signed;
+ bool is_signed = false;
+ bool is_complex = false;
+ uint32_t count = 0;
// In MIPS register "r2" (v0) holds the integer function return values
const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
+ size_t bit_width = return_compiler_type.GetBitSize(&thread);
- if (return_clang_type.IsIntegerType (is_signed))
+ if (return_compiler_type.IsIntegerType (is_signed))
{
- size_t bit_width = return_clang_type.GetBitSize(&thread);
-
switch (bit_width)
{
default:
@@ -468,11 +434,57 @@ ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cla
break;
}
}
- else if (return_clang_type.IsPointerType ())
+ else if (return_compiler_type.IsPointerType ())
{
uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
value.GetScalar() = ptr;
}
+ else if (return_compiler_type.IsAggregateType ())
+ {
+ // Structure/Vector is always passed in memory and pointer to that memory is passed in r2.
+ uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0);
+ // We have got the address. Create a memory object out of it
+ return_valobj_sp = ValueObjectMemory::Create (&thread,
+ "",
+ Address (mem_address, NULL),
+ return_compiler_type);
+ return return_valobj_sp;
+ }
+ else if (return_compiler_type.IsFloatingPointType (count, is_complex))
+ {
+ const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
+ const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
+
+ if (count == 1 && !is_complex)
+ {
+ switch (bit_width)
+ {
+ default:
+ return return_valobj_sp;
+ case 64:
+ {
+ static_assert(sizeof(double) == sizeof(uint64_t), "");
+ uint64_t raw_value;
+ raw_value = reg_ctx->ReadRegisterAsUnsigned(f0_info, 0) & UINT32_MAX;
+ raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(f1_info, 0) & UINT32_MAX)) << 32;
+ value.GetScalar() = *reinterpret_cast<double*>(&raw_value);
+ break;
+ }
+ case 32:
+ {
+ static_assert(sizeof(float) == sizeof(uint32_t), "");
+ uint32_t raw_value = reg_ctx->ReadRegisterAsUnsigned(f0_info, 0) & UINT32_MAX;
+ value.GetScalar() = *reinterpret_cast<float*>(&raw_value);
+ break;
+ }
+ }
+ }
+ else
+ {
+ // not handled yet
+ return return_valobj_sp;
+ }
+ }
else
{
// not handled yet
@@ -496,17 +508,17 @@ ABISysV_mips::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
// Our Call Frame Address is the stack pointer value
- row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0);
+ row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
// The previous PC is in the RA
- row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true);
+ row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
unwind_plan.AppendRow (row);
// All other registers are the same.
unwind_plan.SetSourceName ("mips at-func-entry default");
unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
- unwind_plan.SetReturnAddressRegister(gcc_dwarf_r31);
+ unwind_plan.SetReturnAddressRegister(dwarf_r31);
return true;
}
@@ -518,9 +530,9 @@ ABISysV_mips::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
- row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0);
+ row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
- row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true);
+ row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
unwind_plan.AppendRow (row);
unwind_plan.SetSourceName ("mips default unwind plan");
@@ -542,13 +554,36 @@ ABISysV_mips::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
{
// Preserved registers are :
// r16-r23, r28, r29, r30, r31
+ const char *name = reg_info->name;
- int reg = ((reg_info->byte_offset) / 4);
-
- bool save = (reg >= 16) && (reg <= 23);
- save |= (reg >= 28) && (reg <= 31);
+ if (name[0] == 'r')
+ {
+ switch (name[1])
+ {
+ case '1':
+ if (name[2] == '6' || name[2] == '7' || name[2] == '8' || name[2] == '9') // r16-r19
+ return name[3] == '\0';
+ break;
+ case '2':
+ if (name[2] == '0' || name[2] == '1' || name[2] == '2' || name[2] == '3' // r20-r23
+ || name[2] == '8' || name[2] == '9') // r28 and r29
+ return name[3] == '\0';
+ break;
+ case '3':
+ if (name[2] == '0' || name[2] == '1') // r30 and r31
+ return name[3] == '\0';
+ break;
+ }
- return save;
+ if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0') // gp (r28)
+ return true;
+ if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp (r29)
+ return true;
+ if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp (r30)
+ return true;
+ if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0') // ra (r31)
+ return true;
+ }
}
return false;
}
diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.h b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h
index ad47ac222932..709c3bfe3adf 100644
--- a/source/Plugins/ABI/SysV-mips/ABISysV_mips.h
+++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h
@@ -21,49 +21,40 @@ class ABISysV_mips :
public lldb_private::ABI
{
public:
+ ~ABISysV_mips() override = default;
- ~ABISysV_mips()
- {
- }
-
- virtual size_t
- GetRedZoneSize () const;
+ size_t
+ GetRedZoneSize() const override;
- virtual bool
- PrepareTrivialCall (lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t functionAddress,
- lldb::addr_t returnAddress,
- llvm::ArrayRef<lldb::addr_t> args) const;
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const override;
- virtual bool
- GetArgumentValues (lldb_private::Thread &thread,
- lldb_private::ValueList &values) const;
+ bool
+ GetArgumentValues(lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
- virtual lldb_private::Error
- SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
lldb::ValueObjectSP
- GetReturnValueObjectSimple (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const;
-
-public:
- virtual lldb::ValueObjectSP
- GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &type) const;
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &type) const override;
- virtual bool
- CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+ bool
+ RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
- virtual bool
- CallFrameAddressIsValid (lldb::addr_t cfa)
+ bool
+ CallFrameAddressIsValid(lldb::addr_t cfa) override
{
// Make sure the stack call frame addresses are 8 byte aligned
if (cfa & (8ull - 1ull))
@@ -73,21 +64,21 @@ public:
return true;
}
- virtual bool
- CodeAddressIsValid (lldb::addr_t pc)//must- check
+ bool
+ CodeAddressIsValid(lldb::addr_t pc) override
{
- if (pc & (4ull - 1ull))
- return false; // Not 4 byte aligned
-
- // Anything else if fair game..
- return true;
+ // Just make sure the address is a valid 32 bit address. Bit zero
+ // might be set due to MicroMIPS function calls, so don't enforce alignment.
+ return (pc <= UINT32_MAX);
}
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoArray (uint32_t &count);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray(uint32_t &count) override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -103,21 +94,30 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
- virtual uint32_t
- GetPluginVersion();
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
protected:
void
CreateRegisterMapIfNeeded ();
+ lldb::ValueObjectSP
+ GetReturnValueObjectSimple(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const;
+
bool
RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
private:
- ABISysV_mips() : lldb_private::ABI() { } // Call CreateInstance instead.
+ ABISysV_mips() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
};
-#endif // liblldb_ABI_h_
+#endif // liblldb_ABISysV_mips_h_
diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
index c790fa7e7bdd..bc62c9fe82ee 100644
--- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
+++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
@@ -20,7 +20,6 @@
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/ValueObjectMemory.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
@@ -34,133 +33,91 @@
using namespace lldb;
using namespace lldb_private;
-enum gcc_dwarf_regnums
+enum dwarf_regnums
{
- gcc_dwarf_r0 = 0,
- gcc_dwarf_r1,
- gcc_dwarf_r2,
- gcc_dwarf_r3,
- gcc_dwarf_r4,
- gcc_dwarf_r5,
- gcc_dwarf_r6,
- gcc_dwarf_r7,
- gcc_dwarf_r8,
- gcc_dwarf_r9,
- gcc_dwarf_r10,
- gcc_dwarf_r11,
- gcc_dwarf_r12,
- gcc_dwarf_r13,
- gcc_dwarf_r14,
- gcc_dwarf_r15,
- gcc_dwarf_r16,
- gcc_dwarf_r17,
- gcc_dwarf_r18,
- gcc_dwarf_r19,
- gcc_dwarf_r20,
- gcc_dwarf_r21,
- gcc_dwarf_r22,
- gcc_dwarf_r23,
- gcc_dwarf_r24,
- gcc_dwarf_r25,
- gcc_dwarf_r26,
- gcc_dwarf_r27,
- gcc_dwarf_r28,
- gcc_dwarf_r29,
- gcc_dwarf_r30,
- gcc_dwarf_r31,
- gcc_dwarf_sr,
- gcc_dwarf_lo,
- gcc_dwarf_hi,
- gcc_dwarf_bad,
- gcc_dwarf_cause,
- gcc_dwarf_pc
-};
-
-enum gdb_regnums
-{
- gdb_r0 = 0,
- gdb_r1,
- gdb_r2,
- gdb_r3,
- gdb_r4,
- gdb_r5,
- gdb_r6,
- gdb_r7,
- gdb_r8,
- gdb_r9,
- gdb_r10,
- gdb_r11,
- gdb_r12,
- gdb_r13,
- gdb_r14,
- gdb_r15,
- gdb_r16,
- gdb_r17,
- gdb_r18,
- gdb_r19,
- gdb_r20,
- gdb_r21,
- gdb_r22,
- gdb_r23,
- gdb_r24,
- gdb_r25,
- gdb_r26,
- gdb_r27,
- gdb_r28,
- gdb_r29,
- gdb_r30,
- gdb_r31,
- gdb_sr,
- gdb_lo,
- gdb_hi,
- gdb_bad,
- gdb_cause,
- gdb_pc
+ dwarf_r0 = 0,
+ dwarf_r1,
+ dwarf_r2,
+ dwarf_r3,
+ dwarf_r4,
+ dwarf_r5,
+ dwarf_r6,
+ dwarf_r7,
+ dwarf_r8,
+ dwarf_r9,
+ dwarf_r10,
+ dwarf_r11,
+ dwarf_r12,
+ dwarf_r13,
+ dwarf_r14,
+ dwarf_r15,
+ dwarf_r16,
+ dwarf_r17,
+ dwarf_r18,
+ dwarf_r19,
+ dwarf_r20,
+ dwarf_r21,
+ dwarf_r22,
+ dwarf_r23,
+ dwarf_r24,
+ dwarf_r25,
+ dwarf_r26,
+ dwarf_r27,
+ dwarf_r28,
+ dwarf_r29,
+ dwarf_r30,
+ dwarf_r31,
+ dwarf_sr,
+ dwarf_lo,
+ dwarf_hi,
+ dwarf_bad,
+ dwarf_cause,
+ dwarf_pc
};
static const RegisterInfo
g_register_infos_mips64[] =
{
- // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
- // ======== ====== == === ============= =================== ============ ===================== ==================== ================= ====================== ========== ===============
- { "r0" , "zero", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r1" , "AT", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r1, gcc_dwarf_r1, LLDB_INVALID_REGNUM, gdb_r1, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r2" , "v0", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r3" , "v1", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r3, gcc_dwarf_r3, LLDB_INVALID_REGNUM, gdb_r3, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r4" , "arg1", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, gdb_r4, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r5" , "arg2", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, gdb_r5, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r6" , "arg3", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, gdb_r6, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r7" , "arg4", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, gdb_r7, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r8" , "arg5", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r8, gcc_dwarf_r8, LLDB_REGNUM_GENERIC_ARG5, gdb_r8, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r9" , "arg6", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r9, gcc_dwarf_r9, LLDB_REGNUM_GENERIC_ARG6, gdb_r9, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r10" , "arg7", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r10, gcc_dwarf_r10, LLDB_REGNUM_GENERIC_ARG7, gdb_r10, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r11" , "arg8", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r11, gcc_dwarf_r11, LLDB_REGNUM_GENERIC_ARG8, gdb_r11, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r12" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r13" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r14" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r15" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r16" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r17" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r18" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r19" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r20" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r21" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r22" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r23" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r24" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r25" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r26" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r27" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r28" , "gp", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r29" , "sp", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r29, gcc_dwarf_r29, LLDB_REGNUM_GENERIC_SP, gdb_r29, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r30" , "fp", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r30, gcc_dwarf_r30, LLDB_REGNUM_GENERIC_FP, gdb_r30, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r31" , "ra", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r31, gcc_dwarf_r31, LLDB_REGNUM_GENERIC_RA, gdb_r31, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "sr" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_sr, gcc_dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, gdb_sr, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "lo" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_lo, gcc_dwarf_lo, LLDB_INVALID_REGNUM, gdb_lo, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "hi" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_hi, gcc_dwarf_hi, LLDB_INVALID_REGNUM, gdb_hi, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "bad" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_bad, gcc_dwarf_bad, LLDB_INVALID_REGNUM, gdb_bad, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "cause" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cause, gcc_dwarf_cause, LLDB_INVALID_REGNUM, gdb_cause, LLDB_INVALID_REGNUM }, NULL, NULL},
- { "pc" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_pc, LLDB_INVALID_REGNUM }, NULL, NULL},
+ // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS
+ // ======== ====== == === ============= ========== ============= ================= ==================== ================= ==================== ========== ===============
+ { "r0" , "zero", 8, 0, eEncodingUint, eFormatHex, { dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r1" , "AT", 8, 0, eEncodingUint, eFormatHex, { dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r2" , "v0", 8, 0, eEncodingUint, eFormatHex, { dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r3" , "v1", 8, 0, eEncodingUint, eFormatHex, { dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r4" , "arg1", 8, 0, eEncodingUint, eFormatHex, { dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r5" , "arg2", 8, 0, eEncodingUint, eFormatHex, { dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r6" , "arg3", 8, 0, eEncodingUint, eFormatHex, { dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r7" , "arg4", 8, 0, eEncodingUint, eFormatHex, { dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r8" , "arg5", 8, 0, eEncodingUint, eFormatHex, { dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r9" , "arg6", 8, 0, eEncodingUint, eFormatHex, { dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r10" , "arg7", 8, 0, eEncodingUint, eFormatHex, { dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r11" , "arg8", 8, 0, eEncodingUint, eFormatHex, { dwarf_r11, dwarf_r11, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r12" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r13" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r14" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r15" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r16" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r17" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r18" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r19" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r20" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r21" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r22" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r23" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r24" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r25" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r26" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r27" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r28" , "gp", 8, 0, eEncodingUint, eFormatHex, { dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r29" , "sp", 8, 0, eEncodingUint, eFormatHex, { dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r30" , "fp", 8, 0, eEncodingUint, eFormatHex, { dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r31" , "ra", 8, 0, eEncodingUint, eFormatHex, { dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "sr" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "lo" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "hi" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "bad" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "cause" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "pc" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
};
static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos_mips64);
@@ -290,8 +247,8 @@ ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
return error;
}
- ClangASTType clang_type = new_value_sp->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = new_value_sp->GetCompilerType();
+ if (!compiler_type)
{
error.SetErrorString ("Null clang type for return value.");
return error;
@@ -313,7 +270,7 @@ ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
return error;
}
- const uint32_t type_flags = clang_type.GetTypeInfo (NULL);
+ const uint32_t type_flags = compiler_type.GetTypeInfo (NULL);
if (type_flags & eTypeIsScalar ||
type_flags & eTypeIsPointer)
@@ -368,42 +325,50 @@ ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
ValueObjectSP
-ABISysV_mips64::GetReturnValueObjectSimple (Thread &thread, ClangASTType &return_clang_type) const
+ABISysV_mips64::GetReturnValueObjectSimple (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
return return_valobj_sp;
}
ValueObjectSP
-ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
Value value;
-
+ Error error;
+
ExecutionContext exe_ctx (thread.shared_from_this());
if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)
return return_valobj_sp;
- value.SetClangType(return_clang_type);
+ value.SetCompilerType(return_compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return return_valobj_sp;
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
- const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL);
+ Target *target = exe_ctx.GetTargetPtr();
+ ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder();
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
+ const uint32_t type_flags = return_compiler_type.GetTypeInfo (NULL);
+
+ const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
+ const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
- if (type_flags & eTypeIsScalar)
+ if (type_flags & eTypeIsScalar ||
+ type_flags & eTypeIsPointer)
{
value.SetValueType(Value::eValueTypeScalar);
bool success = false;
- if (type_flags & eTypeIsInteger)
+ if (type_flags & eTypeIsInteger ||
+ type_flags & eTypeIsPointer)
{
// Extract the register context so we can read arguments from registers
// In MIPS register "r2" (v0) holds the integer function return values
- uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0);
+ uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0);
const bool is_signed = (type_flags & eTypeIsSigned) != 0;
switch (byte_size)
@@ -444,25 +409,302 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
break;
}
}
+ else if (type_flags & eTypeIsFloat)
+ {
+ if (type_flags & eTypeIsComplex)
+ {
+ // Don't handle complex yet.
+ }
+ else
+ {
+ if (byte_size <= sizeof(long double))
+ {
+ const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
+ const RegisterInfo *f2_info = reg_ctx->GetRegisterInfoByName("f2", 0);
+ RegisterValue f0_value, f2_value;
+ DataExtractor f0_data, f2_data;
+
+ reg_ctx->ReadRegister (f0_info, f0_value);
+ reg_ctx->ReadRegister (f2_info, f2_value);
+
+ f0_value.GetData(f0_data);
+ f2_value.GetData(f2_data);
+
+ lldb::offset_t offset = 0;
+ if (byte_size == sizeof(float))
+ {
+ value.GetScalar() = (float) f0_data.GetFloat(&offset);
+ success = true;
+ }
+ else if (byte_size == sizeof(double))
+ {
+ value.GetScalar() = (double) f0_data.GetDouble(&offset);
+ success = true;
+ }
+ else if (byte_size == sizeof(long double))
+ {
+ DataExtractor *copy_from_extractor = NULL;
+ DataBufferSP data_sp (new DataBufferHeap(16, 0));
+ DataExtractor return_ext (data_sp,
+ target_byte_order,
+ target->GetArchitecture().GetAddressByteSize());
+
+ if (target_byte_order == eByteOrderLittle)
+ {
+ f0_data.Append(f2_data);
+ copy_from_extractor = &f0_data;
+ }
+ else
+ {
+ f2_data.Append(f0_data);
+ copy_from_extractor = &f2_data;
+ }
+
+ copy_from_extractor->CopyByteOrderedData (0,
+ byte_size,
+ data_sp->GetBytes(),
+ byte_size,
+ target_byte_order);
+
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_compiler_type,
+ ConstString(""),
+ return_ext);
+ return return_valobj_sp;
+
+ }
+ }
+ }
+ }
if (success)
return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
value,
ConstString(""));
}
- else if (type_flags & eTypeIsPointer)
+ else if (type_flags & eTypeIsStructUnion ||
+ type_flags & eTypeIsClass ||
+ type_flags & eTypeIsVector)
{
- value.SetValueType(Value::eValueTypeScalar);
- uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0);
- value.GetScalar() = (uint64_t)(raw_value);
+ // Any structure of up to 16 bytes in size is returned in the registers.
+ if (byte_size <= 16)
+ {
+ DataBufferSP data_sp (new DataBufferHeap(16, 0));
+ DataExtractor return_ext (data_sp,
+ target_byte_order,
+ target->GetArchitecture().GetAddressByteSize());
+
+ RegisterValue r2_value, r3_value, f0_value, f1_value, f2_value;
+
+ uint32_t integer_bytes = 0; // Tracks how much bytes of r2 and r3 registers we've consumed so far
+ bool use_fp_regs = 0; // True if return values are in FP return registers.
+ bool found_non_fp_field = 0; // True if we found any non floating point field in structure.
+ bool use_r2 = 0; // True if return values are in r2 register.
+ bool use_r3 = 0; // True if return values are in r3 register.
+ bool sucess = 0; // True if the result is copied into our data buffer
+ std::string name;
+ bool is_complex;
+ uint32_t count;
+ const uint32_t num_children = return_compiler_type.GetNumFields ();
+
+ // A structure consisting of one or two FP values (and nothing else) will be
+ // returned in the two FP return-value registers i.e fp0 and fp2.
+ if (num_children <= 2)
+ {
+ uint64_t field_bit_offset = 0;
- return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
- value,
- ConstString(""));
- }
- else if (type_flags & eTypeIsVector)
- {
- // TODO: Handle vector types
+ // Check if this structure contains only floating point fields
+ for (uint32_t idx = 0; idx < num_children; idx++)
+ {
+ CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
+
+ if (field_compiler_type.IsFloatingPointType (count, is_complex))
+ use_fp_regs = 1;
+ else
+ found_non_fp_field = 1;
+ }
+
+ if (use_fp_regs && !found_non_fp_field)
+ {
+ // We have one or two FP-only values in this structure. Get it from f0/f2 registers.
+ DataExtractor f0_data, f1_data, f2_data;
+ const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
+ const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
+ const RegisterInfo *f2_info = reg_ctx->GetRegisterInfoByName("f2", 0);
+
+ reg_ctx->ReadRegister (f0_info, f0_value);
+ reg_ctx->ReadRegister (f2_info, f2_value);
+
+ f0_value.GetData(f0_data);
+ f2_value.GetData(f2_data);
+
+ for (uint32_t idx = 0; idx < num_children; idx++)
+ {
+ CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
+ const size_t field_byte_width = field_compiler_type.GetByteSize(nullptr);
+
+ DataExtractor *copy_from_extractor = NULL;
+
+ if (idx == 0)
+ {
+ if (field_byte_width == 16) // This case is for long double type.
+ {
+ // If structure contains long double type, then it is returned in fp0/fp1 registers.
+ reg_ctx->ReadRegister (f1_info, f1_value);
+ f1_value.GetData(f1_data);
+
+ if (target_byte_order == eByteOrderLittle)
+ {
+ f0_data.Append(f1_data);
+ copy_from_extractor = &f0_data;
+ }
+ else
+ {
+ f1_data.Append(f0_data);
+ copy_from_extractor = &f1_data;
+ }
+ }
+ else
+ copy_from_extractor = &f0_data; // This is in f0, copy from register to our result structure
+ }
+ else
+ copy_from_extractor = &f2_data; // This is in f2, copy from register to our result structure
+
+ // Sanity check to avoid crash
+ if (!copy_from_extractor || field_byte_width > copy_from_extractor->GetByteSize())
+ return return_valobj_sp;
+
+ // copy the register contents into our data buffer
+ copy_from_extractor->CopyByteOrderedData (0,
+ field_byte_width,
+ data_sp->GetBytes() + (field_bit_offset/8),
+ field_byte_width,
+ target_byte_order);
+ }
+
+ // The result is in our data buffer. Create a variable object out of it
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_compiler_type,
+ ConstString(""),
+ return_ext);
+
+ return return_valobj_sp;
+ }
+ }
+
+ // If we reach here, it means this structure either contains more than two fields or
+ // it contains at least one non floating point type.
+ // In that case, all fields are returned in GP return registers.
+ for (uint32_t idx = 0; idx < num_children; idx++)
+ {
+ uint64_t field_bit_offset = 0;
+ bool is_signed;
+ uint32_t padding;
+
+ CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
+ const size_t field_byte_width = field_compiler_type.GetByteSize(nullptr);
+
+ // if we don't know the size of the field (e.g. invalid type), just bail out
+ if (field_byte_width == 0)
+ break;
+
+ uint32_t field_byte_offset = field_bit_offset/8;
+
+ if (field_compiler_type.IsIntegerType (is_signed)
+ || field_compiler_type.IsPointerType ()
+ || field_compiler_type.IsFloatingPointType (count, is_complex))
+ {
+ padding = field_byte_offset - integer_bytes;
+
+ if (integer_bytes < 8)
+ {
+ // We have not yet consumed r2 completely.
+ if (integer_bytes + field_byte_width + padding <= 8)
+ {
+ // This field fits in r2, copy its value from r2 to our result structure
+ integer_bytes = integer_bytes + field_byte_width + padding; // Increase the consumed bytes.
+ use_r2 = 1;
+ }
+ else
+ {
+ // There isn't enough space left in r2 for this field, so this will be in r3.
+ integer_bytes = integer_bytes + field_byte_width + padding; // Increase the consumed bytes.
+ use_r3 = 1;
+ }
+ }
+ // We already have consumed at-least 8 bytes that means r2 is done, and this field will be in r3.
+ // Check if this field can fit in r3.
+ else if (integer_bytes + field_byte_width + padding <= 16)
+ {
+ integer_bytes = integer_bytes + field_byte_width + padding;
+ use_r3 = 1;
+ }
+ else
+ {
+ // There isn't any space left for this field, this should not happen as we have already checked
+ // the overall size is not greater than 16 bytes. For now, return a NULL return value object.
+ return return_valobj_sp;
+ }
+ }
+ }
+ // Vector types upto 16 bytes are returned in GP return registers
+ if (type_flags & eTypeIsVector)
+ {
+ if (byte_size <= 8)
+ use_r2 = 1;
+ else
+ {
+ use_r2 = 1;
+ use_r3 = 1;
+ }
+ }
+
+ if (use_r2)
+ {
+ reg_ctx->ReadRegister (r2_info, r2_value);
+
+ const size_t bytes_copied = r2_value.GetAsMemoryData (r2_info,
+ data_sp->GetBytes(),
+ r2_info->byte_size,
+ target_byte_order,
+ error);
+ if (bytes_copied != r2_info->byte_size)
+ return return_valobj_sp;
+ sucess = 1;
+ }
+ if (use_r3)
+ {
+ reg_ctx->ReadRegister (r3_info, r3_value);
+ const size_t bytes_copied = r3_value.GetAsMemoryData (r3_info,
+ data_sp->GetBytes() + r2_info->byte_size,
+ r3_info->byte_size,
+ target_byte_order,
+ error);
+
+ if (bytes_copied != r3_info->byte_size)
+ return return_valobj_sp;
+ sucess = 1;
+ }
+ if (sucess)
+ {
+ // The result is in our data buffer. Create a variable object out of it
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_compiler_type,
+ ConstString(""),
+ return_ext);
+ }
+ return return_valobj_sp;
+ }
+
+ // Any structure/vector greater than 16 bytes in size is returned in memory.
+ // The pointer to that memory is returned in r2.
+ uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0);
+
+ // We have got the address. Create a memory object out of it
+ return_valobj_sp = ValueObjectMemory::Create (&thread,
+ "",
+ Address (mem_address, NULL),
+ return_compiler_type);
}
return return_valobj_sp;
}
@@ -476,17 +718,17 @@ ABISysV_mips64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
// Our Call Frame Address is the stack pointer value
- row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0);
+ row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
// The previous PC is in the RA
- row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true);
+ row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
unwind_plan.AppendRow (row);
// All other registers are the same.
unwind_plan.SetSourceName ("mips64 at-func-entry default");
unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
- unwind_plan.SetReturnAddressRegister(gcc_dwarf_r31);
+ unwind_plan.SetReturnAddressRegister(dwarf_r31);
return true;
}
@@ -498,9 +740,9 @@ ABISysV_mips64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
UnwindPlan::RowSP row(new UnwindPlan::Row);
- row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0);
+ row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
- row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true);
+ row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
unwind_plan.AppendRow (row);
unwind_plan.SetSourceName ("mips64 default unwind plan");
diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h
index c37e717e0938..3290331e05a0 100644
--- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h
+++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h
@@ -21,46 +21,37 @@ class ABISysV_mips64 :
public lldb_private::ABI
{
public:
+ ~ABISysV_mips64() override = default;
- ~ABISysV_mips64()
- {
- }
-
- virtual size_t
- GetRedZoneSize () const;
+ size_t
+ GetRedZoneSize() const override;
- virtual bool
- PrepareTrivialCall (lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t functionAddress,
- lldb::addr_t returnAddress,
- llvm::ArrayRef<lldb::addr_t> args) const;
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const override;
- virtual bool
- GetArgumentValues (lldb_private::Thread &thread,
- lldb_private::ValueList &values) const;
+ bool
+ GetArgumentValues(lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
- virtual lldb_private::Error
- SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
lldb::ValueObjectSP
- GetReturnValueObjectSimple (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const;
-
-public:
- virtual lldb::ValueObjectSP
- GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &type) const;
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &type) const override;
- virtual bool
- CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+ bool
+ RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
// The SysV mips ABI requires that stack frames be 16 byte aligned.
// When there is a trap handler on the stack, e.g. _sigtramp in userland
@@ -72,8 +63,8 @@ public:
// Whitelisting the trap handlers for user space would be easy (_sigtramp) but
// in other environments there can be a large number of different functions
// involved in async traps.
- virtual bool
- CallFrameAddressIsValid (lldb::addr_t cfa)
+ bool
+ CallFrameAddressIsValid(lldb::addr_t cfa) override
{
// Make sure the stack call frame addresses are 8 byte aligned
if (cfa & (8ull - 1ull))
@@ -83,8 +74,8 @@ public:
return true;
}
- virtual bool
- CodeAddressIsValid (lldb::addr_t pc)
+ bool
+ CodeAddressIsValid(lldb::addr_t pc) override
{
if (pc & (4ull - 1ull))
return false; // Not 4 byte aligned
@@ -93,11 +84,13 @@ public:
return true;
}
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoArray (uint32_t &count);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray(uint32_t &count) override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -113,21 +106,30 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
- virtual uint32_t
- GetPluginVersion();
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
protected:
void
CreateRegisterMapIfNeeded ();
+ lldb::ValueObjectSP
+ GetReturnValueObjectSimple(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const;
+
bool
RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
private:
- ABISysV_mips64() : lldb_private::ABI() { } // Call CreateInstance instead.
+ ABISysV_mips64() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
};
-#endif // liblldb_ABI_h_
+#endif // liblldb_ABISysV_mips64_h_
diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
index 08416dc25b08..f0da18637ba8 100644
--- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
+++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
@@ -20,7 +20,6 @@
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/ValueObjectMemory.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
@@ -34,123 +33,81 @@
using namespace lldb;
using namespace lldb_private;
-enum gcc_dwarf_regnums
+enum dwarf_regnums
{
- gcc_dwarf_r0 = 0,
- gcc_dwarf_r1,
- gcc_dwarf_r2,
- gcc_dwarf_r3,
- gcc_dwarf_r4,
- gcc_dwarf_r5,
- gcc_dwarf_r6,
- gcc_dwarf_r7,
- gcc_dwarf_r8,
- gcc_dwarf_r9,
- gcc_dwarf_r10,
- gcc_dwarf_r11,
- gcc_dwarf_r12,
- gcc_dwarf_r13,
- gcc_dwarf_r14,
- gcc_dwarf_r15,
- gcc_dwarf_r16,
- gcc_dwarf_r17,
- gcc_dwarf_r18,
- gcc_dwarf_r19,
- gcc_dwarf_r20,
- gcc_dwarf_r21,
- gcc_dwarf_r22,
- gcc_dwarf_r23,
- gcc_dwarf_r24,
- gcc_dwarf_r25,
- gcc_dwarf_r26,
- gcc_dwarf_r27,
- gcc_dwarf_r28,
- gcc_dwarf_r29,
- gcc_dwarf_r30,
- gcc_dwarf_r31,
- gcc_dwarf_f0,
- gcc_dwarf_f1,
- gcc_dwarf_f2,
- gcc_dwarf_f3,
- gcc_dwarf_f4,
- gcc_dwarf_f5,
- gcc_dwarf_f6,
- gcc_dwarf_f7,
- gcc_dwarf_f8,
- gcc_dwarf_f9,
- gcc_dwarf_f10,
- gcc_dwarf_f11,
- gcc_dwarf_f12,
- gcc_dwarf_f13,
- gcc_dwarf_f14,
- gcc_dwarf_f15,
- gcc_dwarf_f16,
- gcc_dwarf_f17,
- gcc_dwarf_f18,
- gcc_dwarf_f19,
- gcc_dwarf_f20,
- gcc_dwarf_f21,
- gcc_dwarf_f22,
- gcc_dwarf_f23,
- gcc_dwarf_f24,
- gcc_dwarf_f25,
- gcc_dwarf_f26,
- gcc_dwarf_f27,
- gcc_dwarf_f28,
- gcc_dwarf_f29,
- gcc_dwarf_f30,
- gcc_dwarf_f31,
- gcc_dwarf_cr,
- gcc_dwarf_fpscr,
- gcc_dwarf_xer = 101,
- gcc_dwarf_lr = 108,
- gcc_dwarf_ctr,
- gcc_dwarf_pc,
- gcc_dwarf_cfa,
+ dwarf_r0 = 0,
+ dwarf_r1,
+ dwarf_r2,
+ dwarf_r3,
+ dwarf_r4,
+ dwarf_r5,
+ dwarf_r6,
+ dwarf_r7,
+ dwarf_r8,
+ dwarf_r9,
+ dwarf_r10,
+ dwarf_r11,
+ dwarf_r12,
+ dwarf_r13,
+ dwarf_r14,
+ dwarf_r15,
+ dwarf_r16,
+ dwarf_r17,
+ dwarf_r18,
+ dwarf_r19,
+ dwarf_r20,
+ dwarf_r21,
+ dwarf_r22,
+ dwarf_r23,
+ dwarf_r24,
+ dwarf_r25,
+ dwarf_r26,
+ dwarf_r27,
+ dwarf_r28,
+ dwarf_r29,
+ dwarf_r30,
+ dwarf_r31,
+ dwarf_f0,
+ dwarf_f1,
+ dwarf_f2,
+ dwarf_f3,
+ dwarf_f4,
+ dwarf_f5,
+ dwarf_f6,
+ dwarf_f7,
+ dwarf_f8,
+ dwarf_f9,
+ dwarf_f10,
+ dwarf_f11,
+ dwarf_f12,
+ dwarf_f13,
+ dwarf_f14,
+ dwarf_f15,
+ dwarf_f16,
+ dwarf_f17,
+ dwarf_f18,
+ dwarf_f19,
+ dwarf_f20,
+ dwarf_f21,
+ dwarf_f22,
+ dwarf_f23,
+ dwarf_f24,
+ dwarf_f25,
+ dwarf_f26,
+ dwarf_f27,
+ dwarf_f28,
+ dwarf_f29,
+ dwarf_f30,
+ dwarf_f31,
+ dwarf_cr,
+ dwarf_fpscr,
+ dwarf_xer = 101,
+ dwarf_lr = 108,
+ dwarf_ctr,
+ dwarf_pc,
+ dwarf_cfa,
};
-enum gdb_regnums
-{
- gdb_r0 = 0,
- gdb_r1,
- gdb_r2,
- gdb_r3,
- gdb_r4,
- gdb_r5,
- gdb_r6,
- gdb_r7,
- gdb_r8,
- gdb_r9,
- gdb_r10,
- gdb_r11,
- gdb_r12,
- gdb_r13,
- gdb_r14,
- gdb_r15,
- gdb_r16,
- gdb_r17,
- gdb_r18,
- gdb_r19,
- gdb_r20,
- gdb_r21,
- gdb_r22,
- gdb_r23,
- gdb_r24,
- gdb_r25,
- gdb_r26,
- gdb_r27,
- gdb_r28,
- gdb_r29,
- gdb_r30,
- gdb_r31,
- gdb_lr,
- gdb_cr,
- gdb_xer,
- gdb_ctr,
- gdb_pc,
-};
-
-
// Note that the size and offset will be updated by platform-specific classes.
#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
{ #reg, alt, 8, 0, eEncodingUint, \
@@ -158,45 +115,45 @@ enum gdb_regnums
static const RegisterInfo
g_register_infos[] =
{
- // General purpose registers. GCC, DWARF, Generic, GDB
- DEFINE_GPR(r0, NULL, gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0),
- DEFINE_GPR(r1, "sp", gcc_dwarf_r1, gcc_dwarf_r1, LLDB_REGNUM_GENERIC_SP, gdb_r1),
- DEFINE_GPR(r2, NULL, gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2),
- DEFINE_GPR(r3, "arg1",gcc_dwarf_r3, gcc_dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, gdb_r3),
- DEFINE_GPR(r4, "arg2",gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,gdb_r4),
- DEFINE_GPR(r5, "arg3",gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, gdb_r5),
- DEFINE_GPR(r6, "arg4",gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, gdb_r6),
- DEFINE_GPR(r7, "arg5",gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, gdb_r7),
- DEFINE_GPR(r8, "arg6",gcc_dwarf_r8, gcc_dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, gdb_r8),
- DEFINE_GPR(r9, "arg7",gcc_dwarf_r9, gcc_dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, gdb_r9),
- DEFINE_GPR(r10, "arg8",gcc_dwarf_r10, gcc_dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, gdb_r10),
- DEFINE_GPR(r11, NULL, gcc_dwarf_r11, gcc_dwarf_r11, LLDB_INVALID_REGNUM, gdb_r11),
- DEFINE_GPR(r12, NULL, gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12),
- DEFINE_GPR(r13, NULL, gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13),
- DEFINE_GPR(r14, NULL, gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14),
- DEFINE_GPR(r15, NULL, gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15),
- DEFINE_GPR(r16, NULL, gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16),
- DEFINE_GPR(r17, NULL, gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17),
- DEFINE_GPR(r18, NULL, gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18),
- DEFINE_GPR(r19, NULL, gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19),
- DEFINE_GPR(r20, NULL, gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20),
- DEFINE_GPR(r21, NULL, gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21),
- DEFINE_GPR(r22, NULL, gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22),
- DEFINE_GPR(r23, NULL, gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23),
- DEFINE_GPR(r24, NULL, gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24),
- DEFINE_GPR(r25, NULL, gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25),
- DEFINE_GPR(r26, NULL, gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26),
- DEFINE_GPR(r27, NULL, gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27),
- DEFINE_GPR(r28, NULL, gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28),
- DEFINE_GPR(r29, NULL, gcc_dwarf_r29, gcc_dwarf_r29, LLDB_INVALID_REGNUM, gdb_r29),
- DEFINE_GPR(r30, NULL, gcc_dwarf_r30, gcc_dwarf_r30, LLDB_INVALID_REGNUM, gdb_r30),
- DEFINE_GPR(r31, NULL, gcc_dwarf_r31, gcc_dwarf_r31, LLDB_INVALID_REGNUM, gdb_r31),
- DEFINE_GPR(lr, "lr", gcc_dwarf_lr, gcc_dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_lr),
- DEFINE_GPR(cr, "cr", gcc_dwarf_cr, gcc_dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
- DEFINE_GPR(xer, "xer", gcc_dwarf_xer, gcc_dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(ctr, "ctr", gcc_dwarf_ctr, gcc_dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(pc, "pc", gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
- { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cfa, gcc_dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL},
+ // General purpose registers. eh_frame, DWARF, Generic, Process Plugin
+ DEFINE_GPR(r0, NULL, dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r1, "sp", dwarf_r1, dwarf_r1, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r2, NULL, dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r3, "arg1",dwarf_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r4, "arg2",dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r5, "arg3",dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r6, "arg4",dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r7, "arg5",dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r8, "arg6",dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r9, "arg7",dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r10, "arg8",dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r11, NULL, dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r12, NULL, dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r13, NULL, dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r14, NULL, dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r15, NULL, dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r16, NULL, dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r17, NULL, dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r18, NULL, dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r19, NULL, dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r20, NULL, dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r21, NULL, dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r22, NULL, dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r23, NULL, dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r24, NULL, dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r25, NULL, dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r26, NULL, dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r27, NULL, dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r28, NULL, dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r29, NULL, dwarf_r29, dwarf_r29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r30, NULL, dwarf_r30, dwarf_r30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r31, NULL, dwarf_r31, dwarf_r31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(lr, "lr", dwarf_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(cr, "cr", dwarf_cr, dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(xer, "xer", dwarf_xer, dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ctr, "ctr", dwarf_ctr, dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(pc, "pc", dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_cfa, dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL},
};
static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
@@ -436,25 +393,25 @@ ABISysV_ppc::GetArgumentValues (Thread &thread,
// We currently only support extracting values with Clang QualTypes.
// Do we care about others?
- ClangASTType clang_type = value->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = value->GetCompilerType();
+ if (!compiler_type)
return false;
bool is_signed;
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
is_signed,
thread,
argument_register_ids,
current_argument_register,
current_stack_argument);
}
- else if (clang_type.IsPointerType ())
+ else if (compiler_type.IsPointerType ())
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
false,
thread,
argument_register_ids,
@@ -476,8 +433,8 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec
return error;
}
- ClangASTType clang_type = new_value_sp->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = new_value_sp->GetCompilerType();
+ if (!compiler_type)
{
error.SetErrorString ("Null clang type for return value.");
return error;
@@ -492,7 +449,7 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec
RegisterContext *reg_ctx = thread->GetRegisterContext().get();
bool set_it_simple = false;
- if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())
{
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
@@ -518,13 +475,13 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec
}
}
- else if (clang_type.IsFloatingPointType (count, is_complex))
+ else if (compiler_type.IsFloatingPointType (count, is_complex))
{
if (is_complex)
error.SetErrorString ("We don't support returning complex values at present");
else
{
- size_t bit_width = clang_type.GetBitSize(frame_sp.get());
+ size_t bit_width = compiler_type.GetBitSize(frame_sp.get());
if (bit_width <= 64)
{
DataExtractor data;
@@ -563,22 +520,22 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec
ValueObjectSP
ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,
- ClangASTType &return_clang_type) const
+ CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
Value value;
- if (!return_clang_type)
+ if (!return_compiler_type)
return return_valobj_sp;
//value.SetContext (Value::eContextTypeClangType, return_value_type);
- value.SetClangType (return_clang_type);
+ value.SetCompilerType (return_compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return return_valobj_sp;
- const uint32_t type_flags = return_clang_type.GetTypeInfo ();
+ const uint32_t type_flags = return_compiler_type.GetTypeInfo ();
if (type_flags & eTypeIsScalar)
{
value.SetValueType(Value::eValueTypeScalar);
@@ -588,7 +545,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,
{
// Extract the register context so we can read arguments from registers
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0);
const bool is_signed = (type_flags & eTypeIsSigned) != 0;
switch (byte_size)
@@ -637,7 +594,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,
}
else
{
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
if (byte_size <= sizeof(long double))
{
const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
@@ -681,7 +638,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,
}
else if (type_flags & eTypeIsVector)
{
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
if (byte_size > 0)
{
@@ -709,7 +666,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,
byte_order,
process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
}
@@ -724,15 +681,15 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread,
}
ValueObjectSP
-ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
- if (!return_clang_type)
+ if (!return_compiler_type)
return return_valobj_sp;
ExecutionContext exe_ctx (thread.shared_from_this());
- return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type);
+ return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
if (return_valobj_sp)
return return_valobj_sp;
@@ -740,8 +697,8 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
if (!reg_ctx_sp)
return return_valobj_sp;
- const size_t bit_width = return_clang_type.GetBitSize(&thread);
- if (return_clang_type.IsAggregateType())
+ const size_t bit_width = return_compiler_type.GetBitSize(&thread);
+ if (return_compiler_type.IsAggregateType())
{
Target *target = exe_ctx.GetTargetPtr();
bool is_memory = true;
@@ -768,7 +725,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
uint32_t fp_bytes = 0; // Tracks how much of the xmm registers we've consumed so far
uint32_t integer_bytes = 0; // Tracks how much of the r3/rds registers we've consumed so far
- const uint32_t num_children = return_clang_type.GetNumFields ();
+ const uint32_t num_children = return_compiler_type.GetNumFields ();
// Since we are in the small struct regime, assume we are not in memory.
is_memory = false;
@@ -781,8 +738,8 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
bool is_complex;
uint32_t count;
- ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
- const size_t field_bit_width = field_clang_type.GetBitSize(&thread);
+ CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
+ const size_t field_bit_width = field_compiler_type.GetBitSize(&thread);
// If there are any unaligned fields, this is stored in memory.
if (field_bit_offset % field_bit_width != 0)
@@ -798,7 +755,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
DataExtractor *copy_from_extractor = NULL;
uint32_t copy_from_offset = 0;
- if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ())
+ if (field_compiler_type.IsIntegerType (is_signed) || field_compiler_type.IsPointerType ())
{
if (integer_bytes < 8)
{
@@ -831,7 +788,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
return return_valobj_sp;
}
}
- else if (field_clang_type.IsFloatingPointType (count, is_complex))
+ else if (field_compiler_type.IsFloatingPointType (count, is_complex))
{
// Structs with long doubles are always passed in memory.
if (field_bit_width == 128)
@@ -858,12 +815,12 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
else
{
uint64_t next_field_bit_offset = 0;
- ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1,
+ CompilerType next_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx + 1,
name,
&next_field_bit_offset,
NULL,
NULL);
- if (next_field_clang_type.IsIntegerType (is_signed))
+ if (next_field_compiler_type.IsIntegerType (is_signed))
in_gpr = true;
else
{
@@ -882,12 +839,12 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
else
{
uint64_t prev_field_bit_offset = 0;
- ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1,
+ CompilerType prev_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx - 1,
name,
&prev_field_bit_offset,
NULL,
NULL);
- if (prev_field_clang_type.IsIntegerType (is_signed))
+ if (prev_field_compiler_type.IsIntegerType (is_signed))
in_gpr = true;
else
{
@@ -946,7 +903,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
{
// The result is in our data buffer. Let's make a variable object out of it:
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
return_ext);
}
@@ -965,7 +922,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan
return_valobj_sp = ValueObjectMemory::Create (&thread,
"",
Address (storage_addr, NULL),
- return_clang_type);
+ return_compiler_type);
}
}
@@ -978,9 +935,9 @@ ABISysV_ppc::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
unwind_plan.Clear();
unwind_plan.SetRegisterKind (eRegisterKindDWARF);
- uint32_t lr_reg_num = gcc_dwarf_lr;
- uint32_t sp_reg_num = gcc_dwarf_r1;
- uint32_t pc_reg_num = gcc_dwarf_pc;
+ uint32_t lr_reg_num = dwarf_lr;
+ uint32_t sp_reg_num = dwarf_r1;
+ uint32_t pc_reg_num = dwarf_pc;
UnwindPlan::RowSP row(new UnwindPlan::Row);
@@ -1005,8 +962,8 @@ ABISysV_ppc::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
unwind_plan.Clear();
unwind_plan.SetRegisterKind (eRegisterKindDWARF);
- uint32_t sp_reg_num = gcc_dwarf_r1;
- uint32_t pc_reg_num = gcc_dwarf_lr;
+ uint32_t sp_reg_num = dwarf_r1;
+ uint32_t pc_reg_num = dwarf_lr;
UnwindPlan::RowSP row(new UnwindPlan::Row);
@@ -1020,7 +977,7 @@ ABISysV_ppc::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
unwind_plan.SetSourceName ("ppc default unwind plan");
unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
- unwind_plan.SetReturnAddressRegister(gcc_dwarf_lr);
+ unwind_plan.SetReturnAddressRegister(dwarf_lr);
return true;
}
diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h
index a7aad300e297..99ee755631c2 100644
--- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h
+++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h
@@ -21,52 +21,37 @@ class ABISysV_ppc :
public lldb_private::ABI
{
public:
+ ~ABISysV_ppc() override = default;
- ~ABISysV_ppc()
- {
- }
+ size_t
+ GetRedZoneSize() const override;
- virtual size_t
- GetRedZoneSize () const;
-
- virtual bool
- PrepareTrivialCall (lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t functionAddress,
- lldb::addr_t returnAddress,
- llvm::ArrayRef<lldb::addr_t> args) const;
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const override;
- virtual bool
- GetArgumentValues (lldb_private::Thread &thread,
- lldb_private::ValueList &values) const;
+ bool
+ GetArgumentValues(lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
- virtual lldb_private::Error
- SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
lldb::ValueObjectSP
- GetReturnValueObjectSimple (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const;
-
-public:
- virtual lldb::ValueObjectSP
- GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &type) const;
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &type) const override;
- virtual bool
- CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
-
- virtual bool
- StackUsesFrames ()
- {
- return true;
- }
+ bool
+ RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
// The SysV ppc ABI requires that stack frames be 16 byte aligned.
// When there is a trap handler on the stack, e.g. _sigtramp in userland
@@ -78,8 +63,8 @@ public:
// Whitelisting the trap handlers for user space would be easy (_sigtramp) but
// in other environments there can be a large number of different functions
// involved in async traps.
- virtual bool
- CallFrameAddressIsValid (lldb::addr_t cfa)
+ bool
+ CallFrameAddressIsValid(lldb::addr_t cfa) override
{
// Make sure the stack call frame addresses are 8 byte aligned
if (cfa & (8ull - 1ull))
@@ -89,25 +74,21 @@ public:
return true;
}
- virtual bool
- CodeAddressIsValid (lldb::addr_t pc)
+ bool
+ CodeAddressIsValid(lldb::addr_t pc) override
{
// We have a 64 bit address space, so anything is valid as opcodes
// aren't fixed width...
return true;
}
- virtual bool
- FunctionCallsChangeCFA ()
- {
- return true;
- }
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray(uint32_t &count) override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoArray (uint32_t &count);
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -123,21 +104,30 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
- virtual uint32_t
- GetPluginVersion();
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
protected:
void
CreateRegisterMapIfNeeded ();
+ lldb::ValueObjectSP
+ GetReturnValueObjectSimple(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const;
+
bool
RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
private:
- ABISysV_ppc() : lldb_private::ABI() { } // Call CreateInstance instead.
+ ABISysV_ppc() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
};
-#endif // liblldb_ABI_h_
+#endif // liblldb_ABISysV_ppc_h_
diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
index eb0d7c00070f..96c54ce97eec 100644
--- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
+++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
@@ -20,7 +20,6 @@
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/ValueObjectMemory.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
@@ -34,120 +33,79 @@
using namespace lldb;
using namespace lldb_private;
-enum gcc_dwarf_regnums
+enum dwarf_regnums
{
- gcc_dwarf_r0 = 0,
- gcc_dwarf_r1,
- gcc_dwarf_r2,
- gcc_dwarf_r3,
- gcc_dwarf_r4,
- gcc_dwarf_r5,
- gcc_dwarf_r6,
- gcc_dwarf_r7,
- gcc_dwarf_r8,
- gcc_dwarf_r9,
- gcc_dwarf_r10,
- gcc_dwarf_r11,
- gcc_dwarf_r12,
- gcc_dwarf_r13,
- gcc_dwarf_r14,
- gcc_dwarf_r15,
- gcc_dwarf_r16,
- gcc_dwarf_r17,
- gcc_dwarf_r18,
- gcc_dwarf_r19,
- gcc_dwarf_r20,
- gcc_dwarf_r21,
- gcc_dwarf_r22,
- gcc_dwarf_r23,
- gcc_dwarf_r24,
- gcc_dwarf_r25,
- gcc_dwarf_r26,
- gcc_dwarf_r27,
- gcc_dwarf_r28,
- gcc_dwarf_r29,
- gcc_dwarf_r30,
- gcc_dwarf_r31,
- gcc_dwarf_f0,
- gcc_dwarf_f1,
- gcc_dwarf_f2,
- gcc_dwarf_f3,
- gcc_dwarf_f4,
- gcc_dwarf_f5,
- gcc_dwarf_f6,
- gcc_dwarf_f7,
- gcc_dwarf_f8,
- gcc_dwarf_f9,
- gcc_dwarf_f10,
- gcc_dwarf_f11,
- gcc_dwarf_f12,
- gcc_dwarf_f13,
- gcc_dwarf_f14,
- gcc_dwarf_f15,
- gcc_dwarf_f16,
- gcc_dwarf_f17,
- gcc_dwarf_f18,
- gcc_dwarf_f19,
- gcc_dwarf_f20,
- gcc_dwarf_f21,
- gcc_dwarf_f22,
- gcc_dwarf_f23,
- gcc_dwarf_f24,
- gcc_dwarf_f25,
- gcc_dwarf_f26,
- gcc_dwarf_f27,
- gcc_dwarf_f28,
- gcc_dwarf_f29,
- gcc_dwarf_f30,
- gcc_dwarf_f31,
- gcc_dwarf_cr,
- gcc_dwarf_fpscr,
- gcc_dwarf_xer = 101,
- gcc_dwarf_lr = 108,
- gcc_dwarf_ctr,
- gcc_dwarf_pc,
- gcc_dwarf_cfa,
-};
-
-enum gdb_regnums
-{
- gdb_r0 = 0,
- gdb_r1,
- gdb_r2,
- gdb_r3,
- gdb_r4,
- gdb_r5,
- gdb_r6,
- gdb_r7,
- gdb_r8,
- gdb_r9,
- gdb_r10,
- gdb_r11,
- gdb_r12,
- gdb_r13,
- gdb_r14,
- gdb_r15,
- gdb_r16,
- gdb_r17,
- gdb_r18,
- gdb_r19,
- gdb_r20,
- gdb_r21,
- gdb_r22,
- gdb_r23,
- gdb_r24,
- gdb_r25,
- gdb_r26,
- gdb_r27,
- gdb_r28,
- gdb_r29,
- gdb_r30,
- gdb_r31,
- gdb_lr,
- gdb_cr,
- gdb_xer,
- gdb_ctr,
- gdb_pc,
+ dwarf_r0 = 0,
+ dwarf_r1,
+ dwarf_r2,
+ dwarf_r3,
+ dwarf_r4,
+ dwarf_r5,
+ dwarf_r6,
+ dwarf_r7,
+ dwarf_r8,
+ dwarf_r9,
+ dwarf_r10,
+ dwarf_r11,
+ dwarf_r12,
+ dwarf_r13,
+ dwarf_r14,
+ dwarf_r15,
+ dwarf_r16,
+ dwarf_r17,
+ dwarf_r18,
+ dwarf_r19,
+ dwarf_r20,
+ dwarf_r21,
+ dwarf_r22,
+ dwarf_r23,
+ dwarf_r24,
+ dwarf_r25,
+ dwarf_r26,
+ dwarf_r27,
+ dwarf_r28,
+ dwarf_r29,
+ dwarf_r30,
+ dwarf_r31,
+ dwarf_f0,
+ dwarf_f1,
+ dwarf_f2,
+ dwarf_f3,
+ dwarf_f4,
+ dwarf_f5,
+ dwarf_f6,
+ dwarf_f7,
+ dwarf_f8,
+ dwarf_f9,
+ dwarf_f10,
+ dwarf_f11,
+ dwarf_f12,
+ dwarf_f13,
+ dwarf_f14,
+ dwarf_f15,
+ dwarf_f16,
+ dwarf_f17,
+ dwarf_f18,
+ dwarf_f19,
+ dwarf_f20,
+ dwarf_f21,
+ dwarf_f22,
+ dwarf_f23,
+ dwarf_f24,
+ dwarf_f25,
+ dwarf_f26,
+ dwarf_f27,
+ dwarf_f28,
+ dwarf_f29,
+ dwarf_f30,
+ dwarf_f31,
+ dwarf_cr,
+ dwarf_fpscr,
+ dwarf_xer = 101,
+ dwarf_lr = 108,
+ dwarf_ctr,
+ dwarf_pc,
+ dwarf_cfa,
};
@@ -158,45 +116,45 @@ enum gdb_regnums
static const RegisterInfo
g_register_infos[] =
{
- // General purpose registers. GCC, DWARF, Generic, GDB
- DEFINE_GPR(r0, NULL, gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0),
- DEFINE_GPR(r1, "sp", gcc_dwarf_r1, gcc_dwarf_r1, LLDB_REGNUM_GENERIC_SP, gdb_r1),
- DEFINE_GPR(r2, NULL, gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2),
- DEFINE_GPR(r3, "arg1",gcc_dwarf_r3, gcc_dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, gdb_r3),
- DEFINE_GPR(r4, "arg2",gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,gdb_r4),
- DEFINE_GPR(r5, "arg3",gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, gdb_r5),
- DEFINE_GPR(r6, "arg4",gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, gdb_r6),
- DEFINE_GPR(r7, "arg5",gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, gdb_r7),
- DEFINE_GPR(r8, "arg6",gcc_dwarf_r8, gcc_dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, gdb_r8),
- DEFINE_GPR(r9, "arg7",gcc_dwarf_r9, gcc_dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, gdb_r9),
- DEFINE_GPR(r10, "arg8",gcc_dwarf_r10, gcc_dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, gdb_r10),
- DEFINE_GPR(r11, NULL, gcc_dwarf_r11, gcc_dwarf_r11, LLDB_INVALID_REGNUM, gdb_r11),
- DEFINE_GPR(r12, NULL, gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12),
- DEFINE_GPR(r13, NULL, gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13),
- DEFINE_GPR(r14, NULL, gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14),
- DEFINE_GPR(r15, NULL, gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15),
- DEFINE_GPR(r16, NULL, gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16),
- DEFINE_GPR(r17, NULL, gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17),
- DEFINE_GPR(r18, NULL, gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18),
- DEFINE_GPR(r19, NULL, gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19),
- DEFINE_GPR(r20, NULL, gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20),
- DEFINE_GPR(r21, NULL, gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21),
- DEFINE_GPR(r22, NULL, gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22),
- DEFINE_GPR(r23, NULL, gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23),
- DEFINE_GPR(r24, NULL, gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24),
- DEFINE_GPR(r25, NULL, gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25),
- DEFINE_GPR(r26, NULL, gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26),
- DEFINE_GPR(r27, NULL, gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27),
- DEFINE_GPR(r28, NULL, gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28),
- DEFINE_GPR(r29, NULL, gcc_dwarf_r29, gcc_dwarf_r29, LLDB_INVALID_REGNUM, gdb_r29),
- DEFINE_GPR(r30, NULL, gcc_dwarf_r30, gcc_dwarf_r30, LLDB_INVALID_REGNUM, gdb_r30),
- DEFINE_GPR(r31, NULL, gcc_dwarf_r31, gcc_dwarf_r31, LLDB_INVALID_REGNUM, gdb_r31),
- DEFINE_GPR(lr, "lr", gcc_dwarf_lr, gcc_dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_lr),
- DEFINE_GPR(cr, "cr", gcc_dwarf_cr, gcc_dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
- DEFINE_GPR(xer, "xer", gcc_dwarf_xer, gcc_dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(ctr, "ctr", gcc_dwarf_ctr, gcc_dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(pc, "pc", gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
- { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cfa, gcc_dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL},
+ // General purpose registers. eh_frame, DWARF, Generic, Process Plugin
+ DEFINE_GPR(r0, NULL, dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r1, "sp", dwarf_r1, dwarf_r1, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r2, NULL, dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r3, "arg1",dwarf_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r4, "arg2",dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r5, "arg3",dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r6, "arg4",dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r7, "arg5",dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r8, "arg6",dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r9, "arg7",dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r10, "arg8",dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r11, NULL, dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r12, NULL, dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r13, NULL, dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r14, NULL, dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r15, NULL, dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r16, NULL, dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r17, NULL, dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r18, NULL, dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r19, NULL, dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r20, NULL, dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r21, NULL, dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r22, NULL, dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r23, NULL, dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r24, NULL, dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r25, NULL, dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r26, NULL, dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r27, NULL, dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r28, NULL, dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r29, NULL, dwarf_r29, dwarf_r29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r30, NULL, dwarf_r30, dwarf_r30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r31, NULL, dwarf_r31, dwarf_r31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(lr, "lr", dwarf_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(cr, "cr", dwarf_cr, dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(xer, "xer", dwarf_xer, dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ctr, "ctr", dwarf_ctr, dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(pc, "pc", dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_cfa, dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL},
};
static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
@@ -436,25 +394,25 @@ ABISysV_ppc64::GetArgumentValues (Thread &thread,
// We currently only support extracting values with Clang QualTypes.
// Do we care about others?
- ClangASTType clang_type = value->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = value->GetCompilerType();
+ if (!compiler_type)
return false;
bool is_signed;
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
is_signed,
thread,
argument_register_ids,
current_argument_register,
current_stack_argument);
}
- else if (clang_type.IsPointerType ())
+ else if (compiler_type.IsPointerType ())
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
false,
thread,
argument_register_ids,
@@ -476,8 +434,8 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
return error;
}
- ClangASTType clang_type = new_value_sp->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = new_value_sp->GetCompilerType();
+ if (!compiler_type)
{
error.SetErrorString ("Null clang type for return value.");
return error;
@@ -492,7 +450,7 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
RegisterContext *reg_ctx = thread->GetRegisterContext().get();
bool set_it_simple = false;
- if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())
{
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
@@ -518,13 +476,13 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
}
}
- else if (clang_type.IsFloatingPointType (count, is_complex))
+ else if (compiler_type.IsFloatingPointType (count, is_complex))
{
if (is_complex)
error.SetErrorString ("We don't support returning complex values at present");
else
{
- size_t bit_width = clang_type.GetBitSize(frame_sp.get());
+ size_t bit_width = compiler_type.GetBitSize(frame_sp.get());
if (bit_width <= 64)
{
DataExtractor data;
@@ -563,22 +521,22 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj
ValueObjectSP
ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread,
- ClangASTType &return_clang_type) const
+ CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
Value value;
- if (!return_clang_type)
+ if (!return_compiler_type)
return return_valobj_sp;
//value.SetContext (Value::eContextTypeClangType, return_value_type);
- value.SetClangType (return_clang_type);
+ value.SetCompilerType (return_compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return return_valobj_sp;
- const uint32_t type_flags = return_clang_type.GetTypeInfo ();
+ const uint32_t type_flags = return_compiler_type.GetTypeInfo ();
if (type_flags & eTypeIsScalar)
{
value.SetValueType(Value::eValueTypeScalar);
@@ -588,7 +546,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread,
{
// Extract the register context so we can read arguments from registers
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0);
const bool is_signed = (type_flags & eTypeIsSigned) != 0;
switch (byte_size)
@@ -637,7 +595,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread,
}
else
{
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
if (byte_size <= sizeof(long double))
{
const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
@@ -681,7 +639,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread,
}
else if (type_flags & eTypeIsVector)
{
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
if (byte_size > 0)
{
@@ -709,7 +667,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread,
byte_order,
process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
}
@@ -724,15 +682,15 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread,
}
ValueObjectSP
-ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
- if (!return_clang_type)
+ if (!return_compiler_type)
return return_valobj_sp;
ExecutionContext exe_ctx (thread.shared_from_this());
- return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type);
+ return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
if (return_valobj_sp)
return return_valobj_sp;
@@ -740,8 +698,8 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
if (!reg_ctx_sp)
return return_valobj_sp;
- const size_t bit_width = return_clang_type.GetBitSize(&thread);
- if (return_clang_type.IsAggregateType())
+ const size_t bit_width = return_compiler_type.GetBitSize(&thread);
+ if (return_compiler_type.IsAggregateType())
{
Target *target = exe_ctx.GetTargetPtr();
bool is_memory = true;
@@ -768,7 +726,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
uint32_t fp_bytes = 0; // Tracks how much of the xmm registers we've consumed so far
uint32_t integer_bytes = 0; // Tracks how much of the r3/rds registers we've consumed so far
- const uint32_t num_children = return_clang_type.GetNumFields ();
+ const uint32_t num_children = return_compiler_type.GetNumFields ();
// Since we are in the small struct regime, assume we are not in memory.
is_memory = false;
@@ -781,8 +739,8 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
bool is_complex;
uint32_t count;
- ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
- const size_t field_bit_width = field_clang_type.GetBitSize(&thread);
+ CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
+ const size_t field_bit_width = field_compiler_type.GetBitSize(&thread);
// If there are any unaligned fields, this is stored in memory.
if (field_bit_offset % field_bit_width != 0)
@@ -798,7 +756,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
DataExtractor *copy_from_extractor = NULL;
uint32_t copy_from_offset = 0;
- if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ())
+ if (field_compiler_type.IsIntegerType (is_signed) || field_compiler_type.IsPointerType ())
{
if (integer_bytes < 8)
{
@@ -831,7 +789,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
return return_valobj_sp;
}
}
- else if (field_clang_type.IsFloatingPointType (count, is_complex))
+ else if (field_compiler_type.IsFloatingPointType (count, is_complex))
{
// Structs with long doubles are always passed in memory.
if (field_bit_width == 128)
@@ -858,12 +816,12 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
else
{
uint64_t next_field_bit_offset = 0;
- ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1,
+ CompilerType next_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx + 1,
name,
&next_field_bit_offset,
NULL,
NULL);
- if (next_field_clang_type.IsIntegerType (is_signed))
+ if (next_field_compiler_type.IsIntegerType (is_signed))
in_gpr = true;
else
{
@@ -882,12 +840,12 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
else
{
uint64_t prev_field_bit_offset = 0;
- ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1,
+ CompilerType prev_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx - 1,
name,
&prev_field_bit_offset,
NULL,
NULL);
- if (prev_field_clang_type.IsIntegerType (is_signed))
+ if (prev_field_compiler_type.IsIntegerType (is_signed))
in_gpr = true;
else
{
@@ -946,7 +904,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
{
// The result is in our data buffer. Let's make a variable object out of it:
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
return_ext);
}
@@ -965,7 +923,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl
return_valobj_sp = ValueObjectMemory::Create (&thread,
"",
Address (storage_addr, NULL),
- return_clang_type);
+ return_compiler_type);
}
}
@@ -978,9 +936,9 @@ ABISysV_ppc64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
unwind_plan.Clear();
unwind_plan.SetRegisterKind (eRegisterKindDWARF);
- uint32_t lr_reg_num = gcc_dwarf_lr;
- uint32_t sp_reg_num = gcc_dwarf_r1;
- uint32_t pc_reg_num = gcc_dwarf_pc;
+ uint32_t lr_reg_num = dwarf_lr;
+ uint32_t sp_reg_num = dwarf_r1;
+ uint32_t pc_reg_num = dwarf_pc;
UnwindPlan::RowSP row(new UnwindPlan::Row);
@@ -1005,8 +963,8 @@ ABISysV_ppc64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
unwind_plan.Clear();
unwind_plan.SetRegisterKind (eRegisterKindDWARF);
- uint32_t sp_reg_num = gcc_dwarf_r1;
- uint32_t pc_reg_num = gcc_dwarf_lr;
+ uint32_t sp_reg_num = dwarf_r1;
+ uint32_t pc_reg_num = dwarf_lr;
UnwindPlan::RowSP row(new UnwindPlan::Row);
@@ -1015,13 +973,13 @@ ABISysV_ppc64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 2, true);
row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
- row->SetRegisterLocationToAtCFAPlusOffset(gcc_dwarf_cr, ptr_size, true);
+ row->SetRegisterLocationToAtCFAPlusOffset(dwarf_cr, ptr_size, true);
unwind_plan.AppendRow (row);
unwind_plan.SetSourceName ("ppc64 default unwind plan");
unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
- unwind_plan.SetReturnAddressRegister(gcc_dwarf_lr);
+ unwind_plan.SetReturnAddressRegister(dwarf_lr);
return true;
}
diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
index d77cb9f1efe3..b87f7938d544 100644
--- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
+++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
@@ -21,52 +21,37 @@ class ABISysV_ppc64 :
public lldb_private::ABI
{
public:
+ ~ABISysV_ppc64() override = default;
- ~ABISysV_ppc64()
- {
- }
+ size_t
+ GetRedZoneSize() const override;
- virtual size_t
- GetRedZoneSize () const;
-
- virtual bool
- PrepareTrivialCall (lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t functionAddress,
- lldb::addr_t returnAddress,
- llvm::ArrayRef<lldb::addr_t> args) const;
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const override;
- virtual bool
- GetArgumentValues (lldb_private::Thread &thread,
- lldb_private::ValueList &values) const;
+ bool
+ GetArgumentValues(lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
- virtual lldb_private::Error
- SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
lldb::ValueObjectSP
- GetReturnValueObjectSimple (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const;
-
-public:
- virtual lldb::ValueObjectSP
- GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &type) const;
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &type) const override;
- virtual bool
- CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
-
- virtual bool
- StackUsesFrames ()
- {
- return true;
- }
+ bool
+ RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
// The SysV ppc64 ABI requires that stack frames be 16 byte aligned.
// When there is a trap handler on the stack, e.g. _sigtramp in userland
@@ -78,8 +63,8 @@ public:
// Whitelisting the trap handlers for user space would be easy (_sigtramp) but
// in other environments there can be a large number of different functions
// involved in async traps.
- virtual bool
- CallFrameAddressIsValid (lldb::addr_t cfa)
+ bool
+ CallFrameAddressIsValid(lldb::addr_t cfa) override
{
// Make sure the stack call frame addresses are 8 byte aligned
if (cfa & (8ull - 1ull))
@@ -89,25 +74,21 @@ public:
return true;
}
- virtual bool
- CodeAddressIsValid (lldb::addr_t pc)
+ bool
+ CodeAddressIsValid(lldb::addr_t pc) override
{
// We have a 64 bit address space, so anything is valid as opcodes
// aren't fixed width...
return true;
}
- virtual bool
- FunctionCallsChangeCFA ()
- {
- return true;
- }
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray(uint32_t &count) override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoArray (uint32_t &count);
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -123,21 +104,30 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
- virtual uint32_t
- GetPluginVersion();
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
protected:
void
CreateRegisterMapIfNeeded ();
+ lldb::ValueObjectSP
+ GetReturnValueObjectSimple(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const;
+
bool
RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
private:
- ABISysV_ppc64() : lldb_private::ABI() { } // Call CreateInstance instead.
+ ABISysV_ppc64() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
};
-#endif // liblldb_ABI_h_
+#endif // liblldb_ABISysV_ppc64_h_
diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
index 1d63628466c2..11e383d269c3 100644
--- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
+++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
@@ -20,7 +20,6 @@
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/ValueObjectMemory.h"
-#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
@@ -34,222 +33,144 @@
using namespace lldb;
using namespace lldb_private;
-enum gcc_dwarf_regnums
+enum dwarf_regnums
{
- gcc_dwarf_rax = 0,
- gcc_dwarf_rdx,
- gcc_dwarf_rcx,
- gcc_dwarf_rbx,
- gcc_dwarf_rsi,
- gcc_dwarf_rdi,
- gcc_dwarf_rbp,
- gcc_dwarf_rsp,
- gcc_dwarf_r8,
- gcc_dwarf_r9,
- gcc_dwarf_r10,
- gcc_dwarf_r11,
- gcc_dwarf_r12,
- gcc_dwarf_r13,
- gcc_dwarf_r14,
- gcc_dwarf_r15,
- gcc_dwarf_rip,
- gcc_dwarf_xmm0,
- gcc_dwarf_xmm1,
- gcc_dwarf_xmm2,
- gcc_dwarf_xmm3,
- gcc_dwarf_xmm4,
- gcc_dwarf_xmm5,
- gcc_dwarf_xmm6,
- gcc_dwarf_xmm7,
- gcc_dwarf_xmm8,
- gcc_dwarf_xmm9,
- gcc_dwarf_xmm10,
- gcc_dwarf_xmm11,
- gcc_dwarf_xmm12,
- gcc_dwarf_xmm13,
- gcc_dwarf_xmm14,
- gcc_dwarf_xmm15,
- gcc_dwarf_stmm0,
- gcc_dwarf_stmm1,
- gcc_dwarf_stmm2,
- gcc_dwarf_stmm3,
- gcc_dwarf_stmm4,
- gcc_dwarf_stmm5,
- gcc_dwarf_stmm6,
- gcc_dwarf_stmm7,
- gcc_dwarf_ymm0,
- gcc_dwarf_ymm1,
- gcc_dwarf_ymm2,
- gcc_dwarf_ymm3,
- gcc_dwarf_ymm4,
- gcc_dwarf_ymm5,
- gcc_dwarf_ymm6,
- gcc_dwarf_ymm7,
- gcc_dwarf_ymm8,
- gcc_dwarf_ymm9,
- gcc_dwarf_ymm10,
- gcc_dwarf_ymm11,
- gcc_dwarf_ymm12,
- gcc_dwarf_ymm13,
- gcc_dwarf_ymm14,
- gcc_dwarf_ymm15
+ dwarf_rax = 0,
+ dwarf_rdx,
+ dwarf_rcx,
+ dwarf_rbx,
+ dwarf_rsi,
+ dwarf_rdi,
+ dwarf_rbp,
+ dwarf_rsp,
+ dwarf_r8,
+ dwarf_r9,
+ dwarf_r10,
+ dwarf_r11,
+ dwarf_r12,
+ dwarf_r13,
+ dwarf_r14,
+ dwarf_r15,
+ dwarf_rip,
+ dwarf_xmm0,
+ dwarf_xmm1,
+ dwarf_xmm2,
+ dwarf_xmm3,
+ dwarf_xmm4,
+ dwarf_xmm5,
+ dwarf_xmm6,
+ dwarf_xmm7,
+ dwarf_xmm8,
+ dwarf_xmm9,
+ dwarf_xmm10,
+ dwarf_xmm11,
+ dwarf_xmm12,
+ dwarf_xmm13,
+ dwarf_xmm14,
+ dwarf_xmm15,
+ dwarf_stmm0,
+ dwarf_stmm1,
+ dwarf_stmm2,
+ dwarf_stmm3,
+ dwarf_stmm4,
+ dwarf_stmm5,
+ dwarf_stmm6,
+ dwarf_stmm7,
+ dwarf_ymm0,
+ dwarf_ymm1,
+ dwarf_ymm2,
+ dwarf_ymm3,
+ dwarf_ymm4,
+ dwarf_ymm5,
+ dwarf_ymm6,
+ dwarf_ymm7,
+ dwarf_ymm8,
+ dwarf_ymm9,
+ dwarf_ymm10,
+ dwarf_ymm11,
+ dwarf_ymm12,
+ dwarf_ymm13,
+ dwarf_ymm14,
+ dwarf_ymm15
};
-enum gdb_regnums
-{
- gdb_rax = 0,
- gdb_rbx = 1,
- gdb_rcx = 2,
- gdb_rdx = 3,
- gdb_rsi = 4,
- gdb_rdi = 5,
- gdb_rbp = 6,
- gdb_rsp = 7,
- gdb_r8 = 8,
- gdb_r9 = 9,
- gdb_r10 = 10,
- gdb_r11 = 11,
- gdb_r12 = 12,
- gdb_r13 = 13,
- gdb_r14 = 14,
- gdb_r15 = 15,
- gdb_rip = 16,
- gdb_rflags = 17,
- gdb_cs = 18,
- gdb_ss = 19,
- gdb_ds = 20,
- gdb_es = 21,
- gdb_fs = 22,
- gdb_gs = 23,
- gdb_stmm0 = 24,
- gdb_stmm1 = 25,
- gdb_stmm2 = 26,
- gdb_stmm3 = 27,
- gdb_stmm4 = 28,
- gdb_stmm5 = 29,
- gdb_stmm6 = 30,
- gdb_stmm7 = 31,
- gdb_fctrl = 32, gdb_fcw = gdb_fctrl,
- gdb_fstat = 33, gdb_fsw = gdb_fstat,
- gdb_ftag = 34, gdb_ftw = gdb_ftag,
- gdb_fiseg = 35, gdb_fpu_cs = gdb_fiseg,
- gdb_fioff = 36, gdb_ip = gdb_fioff,
- gdb_foseg = 37, gdb_fpu_ds = gdb_foseg,
- gdb_fooff = 38, gdb_dp = gdb_fooff,
- gdb_fop = 39,
- gdb_xmm0 = 40,
- gdb_xmm1 = 41,
- gdb_xmm2 = 42,
- gdb_xmm3 = 43,
- gdb_xmm4 = 44,
- gdb_xmm5 = 45,
- gdb_xmm6 = 46,
- gdb_xmm7 = 47,
- gdb_xmm8 = 48,
- gdb_xmm9 = 49,
- gdb_xmm10 = 50,
- gdb_xmm11 = 51,
- gdb_xmm12 = 52,
- gdb_xmm13 = 53,
- gdb_xmm14 = 54,
- gdb_xmm15 = 55,
- gdb_mxcsr = 56,
- gdb_ymm0 = 57,
- gdb_ymm1 = 58,
- gdb_ymm2 = 59,
- gdb_ymm3 = 60,
- gdb_ymm4 = 61,
- gdb_ymm5 = 62,
- gdb_ymm6 = 63,
- gdb_ymm7 = 64,
- gdb_ymm8 = 65,
- gdb_ymm9 = 66,
- gdb_ymm10 = 67,
- gdb_ymm11 = 68,
- gdb_ymm12 = 69,
- gdb_ymm13 = 70,
- gdb_ymm14 = 71,
- gdb_ymm15 = 72
-};
-
-
static RegisterInfo g_register_infos[] =
{
- // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
+ // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS
// ======== ======= == === ============= =================== ======================= ===================== =========================== ===================== ====================== ========== ===============
- { "rax" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rax , gcc_dwarf_rax , LLDB_INVALID_REGNUM , gdb_rax , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "rbx" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rbx , gcc_dwarf_rbx , LLDB_INVALID_REGNUM , gdb_rbx , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "rcx" , "arg4", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rcx , gcc_dwarf_rcx , LLDB_REGNUM_GENERIC_ARG4 , gdb_rcx , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "rdx" , "arg3", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rdx , gcc_dwarf_rdx , LLDB_REGNUM_GENERIC_ARG3 , gdb_rdx , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "rsi" , "arg2", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rsi , gcc_dwarf_rsi , LLDB_REGNUM_GENERIC_ARG2 , gdb_rsi , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "rdi" , "arg1", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rdi , gcc_dwarf_rdi , LLDB_REGNUM_GENERIC_ARG1 , gdb_rdi , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "rbp" , "fp", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rbp , gcc_dwarf_rbp , LLDB_REGNUM_GENERIC_FP , gdb_rbp , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "rsp" , "sp", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rsp , gcc_dwarf_rsp , LLDB_REGNUM_GENERIC_SP , gdb_rsp , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r8" , "arg5", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r8 , gcc_dwarf_r8 , LLDB_REGNUM_GENERIC_ARG5 , gdb_r8 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r9" , "arg6", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r9 , gcc_dwarf_r9 , LLDB_REGNUM_GENERIC_ARG6 , gdb_r9 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r10" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r10 , gcc_dwarf_r10 , LLDB_INVALID_REGNUM , gdb_r10 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r11" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r11 , gcc_dwarf_r11 , LLDB_INVALID_REGNUM , gdb_r11 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r12" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r12 , gcc_dwarf_r12 , LLDB_INVALID_REGNUM , gdb_r12 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r13" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r13 , gcc_dwarf_r13 , LLDB_INVALID_REGNUM , gdb_r13 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r14" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r14 , gcc_dwarf_r14 , LLDB_INVALID_REGNUM , gdb_r14 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "r15" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r15 , gcc_dwarf_r15 , LLDB_INVALID_REGNUM , gdb_r15 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "rip" , "pc", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rip , gcc_dwarf_rip , LLDB_REGNUM_GENERIC_PC , gdb_rip , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "rflags", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_rflags , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "cs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_cs , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ss" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ss , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ds" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ds , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "es" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_es , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fs , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "gs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gs , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm0" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm0 , gcc_dwarf_stmm0 , LLDB_INVALID_REGNUM , gdb_stmm0 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm1" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm1 , gcc_dwarf_stmm1 , LLDB_INVALID_REGNUM , gdb_stmm1 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm2" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm2 , gcc_dwarf_stmm2 , LLDB_INVALID_REGNUM , gdb_stmm2 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm3" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm3 , gcc_dwarf_stmm3 , LLDB_INVALID_REGNUM , gdb_stmm3 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm4" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm4 , gcc_dwarf_stmm4 , LLDB_INVALID_REGNUM , gdb_stmm4 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm5" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm5 , gcc_dwarf_stmm5 , LLDB_INVALID_REGNUM , gdb_stmm5 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm6" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm6 , gcc_dwarf_stmm6 , LLDB_INVALID_REGNUM , gdb_stmm6 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "stmm7" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm7 , gcc_dwarf_stmm7 , LLDB_INVALID_REGNUM , gdb_stmm7 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fctrl" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fctrl , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fstat" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fstat , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ftag" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ftag , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fiseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fiseg , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fioff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fioff , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "foseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_foseg , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fooff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fooff , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "fop" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fop , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm0" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm0 , gcc_dwarf_xmm0 , LLDB_INVALID_REGNUM , gdb_xmm0 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm1" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm1 , gcc_dwarf_xmm1 , LLDB_INVALID_REGNUM , gdb_xmm1 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm2" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm2 , gcc_dwarf_xmm2 , LLDB_INVALID_REGNUM , gdb_xmm2 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm3" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm3 , gcc_dwarf_xmm3 , LLDB_INVALID_REGNUM , gdb_xmm3 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm4" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm4 , gcc_dwarf_xmm4 , LLDB_INVALID_REGNUM , gdb_xmm4 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm5" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm5 , gcc_dwarf_xmm5 , LLDB_INVALID_REGNUM , gdb_xmm5 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm6" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm6 , gcc_dwarf_xmm6 , LLDB_INVALID_REGNUM , gdb_xmm6 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm7" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm7 , gcc_dwarf_xmm7 , LLDB_INVALID_REGNUM , gdb_xmm7 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm8" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm8 , gcc_dwarf_xmm8 , LLDB_INVALID_REGNUM , gdb_xmm8 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm9" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm9 , gcc_dwarf_xmm9 , LLDB_INVALID_REGNUM , gdb_xmm9 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm10" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm10 , gcc_dwarf_xmm10 , LLDB_INVALID_REGNUM , gdb_xmm10 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm11" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm11 , gcc_dwarf_xmm11 , LLDB_INVALID_REGNUM , gdb_xmm11 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm12" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm12 , gcc_dwarf_xmm12 , LLDB_INVALID_REGNUM , gdb_xmm12 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm13" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm13 , gcc_dwarf_xmm13 , LLDB_INVALID_REGNUM , gdb_xmm13 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm14" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm14 , gcc_dwarf_xmm14 , LLDB_INVALID_REGNUM , gdb_xmm14 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "xmm15" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm15 , gcc_dwarf_xmm15 , LLDB_INVALID_REGNUM , gdb_xmm15 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "mxcsr" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_mxcsr , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm0" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm0 , gcc_dwarf_ymm0 , LLDB_INVALID_REGNUM , gdb_ymm0 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm1" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm1 , gcc_dwarf_ymm1 , LLDB_INVALID_REGNUM , gdb_ymm1 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm2" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm2 , gcc_dwarf_ymm2 , LLDB_INVALID_REGNUM , gdb_ymm2 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm3" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm3 , gcc_dwarf_ymm3 , LLDB_INVALID_REGNUM , gdb_ymm3 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm4" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm4 , gcc_dwarf_ymm4 , LLDB_INVALID_REGNUM , gdb_ymm4 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm5" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm5 , gcc_dwarf_ymm5 , LLDB_INVALID_REGNUM , gdb_ymm5 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm6" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm6 , gcc_dwarf_ymm6 , LLDB_INVALID_REGNUM , gdb_ymm6 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm7" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm7 , gcc_dwarf_ymm7 , LLDB_INVALID_REGNUM , gdb_ymm7 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm8" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm8 , gcc_dwarf_ymm8 , LLDB_INVALID_REGNUM , gdb_ymm8 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm9" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm9 , gcc_dwarf_ymm9 , LLDB_INVALID_REGNUM , gdb_ymm9 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm10" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm10 , gcc_dwarf_ymm10 , LLDB_INVALID_REGNUM , gdb_ymm10 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm11" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm11 , gcc_dwarf_ymm11 , LLDB_INVALID_REGNUM , gdb_ymm11 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm12" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm12 , gcc_dwarf_ymm12 , LLDB_INVALID_REGNUM , gdb_ymm12 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm13" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm13 , gcc_dwarf_ymm13 , LLDB_INVALID_REGNUM , gdb_ymm13 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm14" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm14 , gcc_dwarf_ymm14 , LLDB_INVALID_REGNUM , gdb_ymm14 , LLDB_INVALID_REGNUM }, NULL, NULL},
- { "ymm15" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm15 , gcc_dwarf_ymm15 , LLDB_INVALID_REGNUM , gdb_ymm15 , LLDB_INVALID_REGNUM }, NULL, NULL}
+ { "rax" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_rax , dwarf_rax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "rbx" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_rbx , dwarf_rbx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "rcx" , "arg4", 8, 0, eEncodingUint , eFormatHex , { dwarf_rcx , dwarf_rcx , LLDB_REGNUM_GENERIC_ARG4 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "rdx" , "arg3", 8, 0, eEncodingUint , eFormatHex , { dwarf_rdx , dwarf_rdx , LLDB_REGNUM_GENERIC_ARG3 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "rsi" , "arg2", 8, 0, eEncodingUint , eFormatHex , { dwarf_rsi , dwarf_rsi , LLDB_REGNUM_GENERIC_ARG2 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "rdi" , "arg1", 8, 0, eEncodingUint , eFormatHex , { dwarf_rdi , dwarf_rdi , LLDB_REGNUM_GENERIC_ARG1 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "rbp" , "fp", 8, 0, eEncodingUint , eFormatHex , { dwarf_rbp , dwarf_rbp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "rsp" , "sp", 8, 0, eEncodingUint , eFormatHex , { dwarf_rsp , dwarf_rsp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r8" , "arg5", 8, 0, eEncodingUint , eFormatHex , { dwarf_r8 , dwarf_r8 , LLDB_REGNUM_GENERIC_ARG5 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r9" , "arg6", 8, 0, eEncodingUint , eFormatHex , { dwarf_r9 , dwarf_r9 , LLDB_REGNUM_GENERIC_ARG6 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r10" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r10 , dwarf_r10 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r11" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r11 , dwarf_r11 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r12" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r12 , dwarf_r12 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r13" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r13 , dwarf_r13 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r14" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r14 , dwarf_r14 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "r15" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r15 , dwarf_r15 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "rip" , "pc", 8, 0, eEncodingUint , eFormatHex , { dwarf_rip , dwarf_rip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "rflags", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "cs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ss" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ds" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "es" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "gs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm0" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm0 , dwarf_stmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm1" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm1 , dwarf_stmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm2" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm2 , dwarf_stmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm3" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm3 , dwarf_stmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm4" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm4 , dwarf_stmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm5" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm5 , dwarf_stmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm6" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm6 , dwarf_stmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "stmm7" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm7 , dwarf_stmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fctrl" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fstat" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ftag" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fiseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fioff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "foseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fooff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "fop" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm0" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm0 , dwarf_xmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm1" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm1 , dwarf_xmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm2" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm2 , dwarf_xmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm3" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm3 , dwarf_xmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm4" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm4 , dwarf_xmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm5" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm5 , dwarf_xmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm6" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm6 , dwarf_xmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm7" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm7 , dwarf_xmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm8" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm8 , dwarf_xmm8 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm9" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm9 , dwarf_xmm9 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm10" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm10 , dwarf_xmm10 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm11" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm11 , dwarf_xmm11 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm12" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm12 , dwarf_xmm12 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm13" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm13 , dwarf_xmm13 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm14" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm14 , dwarf_xmm14 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "xmm15" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm15 , dwarf_xmm15 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "mxcsr" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm0" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm0 , dwarf_ymm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm1" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm1 , dwarf_ymm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm2" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm2 , dwarf_ymm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm3" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm3 , dwarf_ymm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm4" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm4 , dwarf_ymm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm5" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm5 , dwarf_ymm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm6" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm6 , dwarf_ymm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm7" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm7 , dwarf_ymm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm8" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm8 , dwarf_ymm8 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm9" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm9 , dwarf_ymm9 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm10" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm10 , dwarf_ymm10 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm11" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm11 , dwarf_ymm11 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm12" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm12 , dwarf_ymm12 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm13" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm13 , dwarf_ymm13 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm14" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm14 , dwarf_ymm14 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL},
+ { "ymm15" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm15 , dwarf_ymm15 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}
};
static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
@@ -502,25 +423,25 @@ ABISysV_x86_64::GetArgumentValues (Thread &thread,
// We currently only support extracting values with Clang QualTypes.
// Do we care about others?
- ClangASTType clang_type = value->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = value->GetCompilerType();
+ if (!compiler_type)
return false;
bool is_signed;
- if (clang_type.IsIntegerType (is_signed))
+ if (compiler_type.IsIntegerType (is_signed))
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
is_signed,
thread,
argument_register_ids,
current_argument_register,
current_stack_argument);
}
- else if (clang_type.IsPointerType ())
+ else if (compiler_type.IsPointerType ())
{
ReadIntegerArgument(value->GetScalar(),
- clang_type.GetBitSize(&thread),
+ compiler_type.GetBitSize(&thread),
false,
thread,
argument_register_ids,
@@ -542,8 +463,8 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
return error;
}
- ClangASTType clang_type = new_value_sp->GetClangType();
- if (!clang_type)
+ CompilerType compiler_type = new_value_sp->GetCompilerType();
+ if (!compiler_type)
{
error.SetErrorString ("Null clang type for return value.");
return error;
@@ -558,7 +479,7 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
RegisterContext *reg_ctx = thread->GetRegisterContext().get();
bool set_it_simple = false;
- if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+ if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType())
{
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("rax", 0);
@@ -584,13 +505,13 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
}
}
- else if (clang_type.IsFloatingPointType (count, is_complex))
+ else if (compiler_type.IsFloatingPointType (count, is_complex))
{
if (is_complex)
error.SetErrorString ("We don't support returning complex values at present");
else
{
- size_t bit_width = clang_type.GetBitSize(frame_sp.get());
+ size_t bit_width = compiler_type.GetBitSize(frame_sp.get());
if (bit_width <= 64)
{
const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0);
@@ -633,22 +554,22 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb
ValueObjectSP
ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
- ClangASTType &return_clang_type) const
+ CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
Value value;
- if (!return_clang_type)
+ if (!return_compiler_type)
return return_valobj_sp;
//value.SetContext (Value::eContextTypeClangType, return_value_type);
- value.SetClangType (return_clang_type);
+ value.SetCompilerType (return_compiler_type);
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return return_valobj_sp;
- const uint32_t type_flags = return_clang_type.GetTypeInfo ();
+ const uint32_t type_flags = return_compiler_type.GetTypeInfo ();
if (type_flags & eTypeIsScalar)
{
value.SetValueType(Value::eValueTypeScalar);
@@ -658,7 +579,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
{
// Extract the register context so we can read arguments from registers
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("rax", 0), 0);
const bool is_signed = (type_flags & eTypeIsSigned) != 0;
switch (byte_size)
@@ -707,7 +628,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
}
else
{
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
if (byte_size <= sizeof(long double))
{
const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0);
@@ -755,18 +676,13 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
}
else if (type_flags & eTypeIsVector)
{
- const size_t byte_size = return_clang_type.GetByteSize(nullptr);
+ const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
if (byte_size > 0)
{
+ const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
+ if (altivec_reg == nullptr)
+ altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
- const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("ymm0", 0);
- if (altivec_reg == NULL)
- {
- altivec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
- if (altivec_reg == NULL)
- altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
- }
-
if (altivec_reg)
{
if (byte_size <= altivec_reg->byte_size)
@@ -790,13 +706,52 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
byte_order,
process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
data);
}
}
}
}
+ else if (byte_size <= altivec_reg->byte_size*2)
+ {
+ const RegisterInfo *altivec_reg2 = reg_ctx->GetRegisterInfoByName("xmm1", 0);
+ if (altivec_reg2)
+ {
+ ProcessSP process_sp (thread.GetProcess());
+ if (process_sp)
+ {
+ std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
+ const ByteOrder byte_order = process_sp->GetByteOrder();
+ RegisterValue reg_value;
+ RegisterValue reg_value2;
+ if (reg_ctx->ReadRegister(altivec_reg, reg_value) && reg_ctx->ReadRegister(altivec_reg2, reg_value2))
+ {
+
+ Error error;
+ if (reg_value.GetAsMemoryData (altivec_reg,
+ heap_data_ap->GetBytes(),
+ altivec_reg->byte_size,
+ byte_order,
+ error) &&
+ reg_value2.GetAsMemoryData (altivec_reg2,
+ heap_data_ap->GetBytes() + altivec_reg->byte_size,
+ heap_data_ap->GetByteSize() - altivec_reg->byte_size,
+ byte_order,
+ error))
+ {
+ DataExtractor data (DataBufferSP (heap_data_ap.release()),
+ byte_order,
+ process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
+ return_valobj_sp = ValueObjectConstResult::Create (&thread,
+ return_compiler_type,
+ ConstString(""),
+ data);
+ }
+ }
+ }
+ }
+ }
}
}
}
@@ -805,15 +760,15 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
}
ValueObjectSP
-ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const
{
ValueObjectSP return_valobj_sp;
- if (!return_clang_type)
+ if (!return_compiler_type)
return return_valobj_sp;
ExecutionContext exe_ctx (thread.shared_from_this());
- return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type);
+ return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
if (return_valobj_sp)
return return_valobj_sp;
@@ -821,8 +776,8 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
if (!reg_ctx_sp)
return return_valobj_sp;
- const size_t bit_width = return_clang_type.GetBitSize(&thread);
- if (return_clang_type.IsAggregateType())
+ const size_t bit_width = return_compiler_type.GetBitSize(&thread);
+ if (return_compiler_type.IsAggregateType())
{
Target *target = exe_ctx.GetTargetPtr();
bool is_memory = true;
@@ -855,7 +810,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
uint32_t fp_bytes = 0; // Tracks how much of the xmm registers we've consumed so far
uint32_t integer_bytes = 0; // Tracks how much of the rax/rds registers we've consumed so far
- const uint32_t num_children = return_clang_type.GetNumFields ();
+ const uint32_t num_children = return_compiler_type.GetNumFields ();
// Since we are in the small struct regime, assume we are not in memory.
is_memory = false;
@@ -868,8 +823,8 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
bool is_complex;
uint32_t count;
- ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
- const size_t field_bit_width = field_clang_type.GetBitSize(&thread);
+ CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
+ const size_t field_bit_width = field_compiler_type.GetBitSize(&thread);
// if we don't know the size of the field (e.g. invalid type), just bail out
if (field_bit_width == 0)
@@ -889,7 +844,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
DataExtractor *copy_from_extractor = NULL;
uint32_t copy_from_offset = 0;
- if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ())
+ if (field_compiler_type.IsIntegerType (is_signed) || field_compiler_type.IsPointerType ())
{
if (integer_bytes < 8)
{
@@ -922,7 +877,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
return return_valobj_sp;
}
}
- else if (field_clang_type.IsFloatingPointType (count, is_complex))
+ else if (field_compiler_type.IsFloatingPointType (count, is_complex))
{
// Structs with long doubles are always passed in memory.
if (field_bit_width == 128)
@@ -955,12 +910,12 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
else
{
uint64_t next_field_bit_offset = 0;
- ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1,
+ CompilerType next_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx + 1,
name,
&next_field_bit_offset,
NULL,
NULL);
- if (next_field_clang_type.IsIntegerType (is_signed))
+ if (next_field_compiler_type.IsIntegerType (is_signed))
in_gpr = true;
else
{
@@ -979,12 +934,12 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
else
{
uint64_t prev_field_bit_offset = 0;
- ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1,
+ CompilerType prev_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx - 1,
name,
&prev_field_bit_offset,
NULL,
NULL);
- if (prev_field_clang_type.IsIntegerType (is_signed))
+ if (prev_field_compiler_type.IsIntegerType (is_signed))
in_gpr = true;
else
{
@@ -1048,7 +1003,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
{
// The result is in our data buffer. Let's make a variable object out of it:
return_valobj_sp = ValueObjectConstResult::Create (&thread,
- return_clang_type,
+ return_compiler_type,
ConstString(""),
return_ext);
}
@@ -1067,7 +1022,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c
return_valobj_sp = ValueObjectMemory::Create (&thread,
"",
Address (storage_addr, NULL),
- return_clang_type);
+ return_compiler_type);
}
}
@@ -1084,8 +1039,8 @@ ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
unwind_plan.Clear();
unwind_plan.SetRegisterKind (eRegisterKindDWARF);
- uint32_t sp_reg_num = gcc_dwarf_rsp;
- uint32_t pc_reg_num = gcc_dwarf_rip;
+ uint32_t sp_reg_num = dwarf_rsp;
+ uint32_t pc_reg_num = dwarf_rip;
UnwindPlan::RowSP row(new UnwindPlan::Row);
row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 8);
@@ -1108,14 +1063,14 @@ ABISysV_x86_64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
unwind_plan.Clear();
unwind_plan.SetRegisterKind (eRegisterKindDWARF);
- uint32_t fp_reg_num = gcc_dwarf_rbp;
- uint32_t sp_reg_num = gcc_dwarf_rsp;
- uint32_t pc_reg_num = gcc_dwarf_rip;
+ uint32_t fp_reg_num = dwarf_rbp;
+ uint32_t sp_reg_num = dwarf_rsp;
+ uint32_t pc_reg_num = dwarf_rip;
UnwindPlan::RowSP row(new UnwindPlan::Row);
const int32_t ptr_size = 8;
- row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_rbp, 2 * ptr_size);
+ row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_rbp, 2 * ptr_size);
row->SetOffset (0);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
index 6fefcc2a9c74..07b57abaf57c 100644
--- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
+++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
@@ -21,46 +21,37 @@ class ABISysV_x86_64 :
public lldb_private::ABI
{
public:
+ ~ABISysV_x86_64() override = default;
- ~ABISysV_x86_64()
- {
- }
-
- virtual size_t
- GetRedZoneSize () const;
+ size_t
+ GetRedZoneSize() const override;
- virtual bool
- PrepareTrivialCall (lldb_private::Thread &thread,
- lldb::addr_t sp,
- lldb::addr_t functionAddress,
- lldb::addr_t returnAddress,
- llvm::ArrayRef<lldb::addr_t> args) const;
+ bool
+ PrepareTrivialCall(lldb_private::Thread &thread,
+ lldb::addr_t sp,
+ lldb::addr_t functionAddress,
+ lldb::addr_t returnAddress,
+ llvm::ArrayRef<lldb::addr_t> args) const override;
- virtual bool
- GetArgumentValues (lldb_private::Thread &thread,
- lldb_private::ValueList &values) const;
+ bool
+ GetArgumentValues(lldb_private::Thread &thread,
+ lldb_private::ValueList &values) const override;
- virtual lldb_private::Error
- SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+ lldb_private::Error
+ SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
-protected:
lldb::ValueObjectSP
- GetReturnValueObjectSimple (lldb_private::Thread &thread,
- lldb_private::ClangASTType &ast_type) const;
-
-public:
- virtual lldb::ValueObjectSP
- GetReturnValueObjectImpl (lldb_private::Thread &thread,
- lldb_private::ClangASTType &type) const;
+ GetReturnValueObjectImpl(lldb_private::Thread &thread,
+ lldb_private::CompilerType &type) const override;
- virtual bool
- CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
- virtual bool
- RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+ bool
+ RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
// The SysV x86_64 ABI requires that stack frames be 16 byte aligned.
// When there is a trap handler on the stack, e.g. _sigtramp in userland
@@ -72,8 +63,8 @@ public:
// Whitelisting the trap handlers for user space would be easy (_sigtramp) but
// in other environments there can be a large number of different functions
// involved in async traps.
- virtual bool
- CallFrameAddressIsValid (lldb::addr_t cfa)
+ bool
+ CallFrameAddressIsValid(lldb::addr_t cfa) override
{
// Make sure the stack call frame addresses are 8 byte aligned
if (cfa & (8ull - 1ull))
@@ -83,19 +74,21 @@ public:
return true;
}
- virtual bool
- CodeAddressIsValid (lldb::addr_t pc)
+ bool
+ CodeAddressIsValid(lldb::addr_t pc) override
{
// We have a 64 bit address space, so anything is valid as opcodes
// aren't fixed width...
return true;
}
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoArray (uint32_t &count);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoArray(uint32_t &count) override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
+
static void
Initialize();
@@ -111,21 +104,30 @@ public:
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
- virtual uint32_t
- GetPluginVersion();
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
protected:
void
CreateRegisterMapIfNeeded ();
+ lldb::ValueObjectSP
+ GetReturnValueObjectSimple(lldb_private::Thread &thread,
+ lldb_private::CompilerType &ast_type) const;
+
bool
RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
private:
- ABISysV_x86_64() : lldb_private::ABI() { } // Call CreateInstance instead.
+ ABISysV_x86_64() :
+ lldb_private::ABI()
+ {
+ // Call CreateInstance instead.
+ }
};
-#endif // liblldb_ABI_h_
+#endif // liblldb_ABISysV_x86_64_h_
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
index d20219f6d1eb..6d124b689341 100644
--- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
@@ -7,8 +7,9 @@
//
//===----------------------------------------------------------------------===//
-#include "DisassemblerLLVMC.h"
-
+// C Includes
+// C++ Includes
+// Project includes
#include "llvm-c/Disassembler.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
@@ -25,6 +26,8 @@
#include "llvm/Support/TargetSelect.h"
#include "llvm/ADT/SmallString.h"
+// Other libraries and framework includes
+#include "DisassemblerLLVMC.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/DataExtractor.h"
@@ -52,18 +55,16 @@ public:
Instruction (address, addr_class),
m_disasm_sp (disasm.shared_from_this()),
m_does_branch (eLazyBoolCalculate),
+ m_has_delay_slot (eLazyBoolCalculate),
m_is_valid (false),
m_using_file_addr (false)
{
}
- virtual
- ~InstructionLLVMC ()
- {
- }
+ ~InstructionLLVMC() override = default;
- virtual bool
- DoesBranch ()
+ bool
+ DoesBranch() override
{
if (m_does_branch == eLazyBoolCalculate)
{
@@ -99,6 +100,43 @@ public:
return m_does_branch == eLazyBoolYes;
}
+ bool
+ HasDelaySlot() override
+ {
+ if (m_has_delay_slot == eLazyBoolCalculate)
+ {
+ GetDisassemblerLLVMC().Lock(this, NULL);
+ DataExtractor data;
+ if (m_opcode.GetData(data))
+ {
+ bool is_alternate_isa;
+ lldb::addr_t pc = m_address.GetFileAddress();
+
+ DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
+ const uint8_t *opcode_data = data.GetDataStart();
+ const size_t opcode_data_len = data.GetByteSize();
+ llvm::MCInst inst;
+ const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data,
+ opcode_data_len,
+ pc,
+ inst);
+ // if we didn't understand the instruction, say it doesn't have a delay slot...
+ if (inst_size == 0)
+ m_has_delay_slot = eLazyBoolNo;
+ else
+ {
+ const bool has_delay_slot = mc_disasm_ptr->HasDelaySlot(inst);
+ if (has_delay_slot)
+ m_has_delay_slot = eLazyBoolYes;
+ else
+ m_has_delay_slot = eLazyBoolNo;
+ }
+ }
+ GetDisassemblerLLVMC().Unlock();
+ }
+ return m_has_delay_slot == eLazyBoolYes;
+ }
+
DisassemblerLLVMC::LLVMCDisassembler *
GetDisasmToUse (bool &is_alternate_isa)
{
@@ -117,10 +155,10 @@ public:
return llvm_disasm.m_disasm_ap.get();
}
- virtual size_t
- Decode (const lldb_private::Disassembler &disassembler,
- const lldb_private::DataExtractor &data,
- lldb::offset_t data_offset)
+ size_t
+ Decode(const lldb_private::Disassembler &disassembler,
+ const lldb_private::DataExtractor &data,
+ lldb::offset_t data_offset) override
{
// All we have to do is read the opcode which can be easy for some
// architectures
@@ -234,15 +272,16 @@ public:
}
}
- virtual void
- CalculateMnemonicOperandsAndComment (const lldb_private::ExecutionContext *exe_ctx)
+ void
+ CalculateMnemonicOperandsAndComment(const lldb_private::ExecutionContext *exe_ctx) override
{
DataExtractor data;
const AddressClass address_class = GetAddressClass ();
if (m_opcode.GetData(data))
{
- char out_string[512];
+ std::string out_string;
+ std::string comment_string;
DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC();
@@ -293,7 +332,12 @@ public:
if (inst_size > 0)
{
mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style);
- mc_disasm_ptr->PrintMCInst(inst, out_string, sizeof(out_string));
+ mc_disasm_ptr->PrintMCInst(inst, out_string, comment_string);
+
+ if (!comment_string.empty())
+ {
+ AppendComment(comment_string);
+ }
}
llvm_disasm.Unlock();
@@ -375,10 +419,10 @@ public:
RegularExpression::Match matches(3);
- if (s_regex.Execute(out_string, &matches))
+ if (s_regex.Execute(out_string.c_str(), &matches))
{
- matches.GetMatchAtIndex(out_string, 1, m_opcode_name);
- matches.GetMatchAtIndex(out_string, 2, m_mnemonics);
+ matches.GetMatchAtIndex(out_string.c_str(), 1, m_opcode_name);
+ matches.GetMatchAtIndex(out_string.c_str(), 2, m_mnemonics);
}
}
}
@@ -409,12 +453,11 @@ protected:
DisassemblerSP m_disasm_sp; // for ownership
LazyBool m_does_branch;
+ LazyBool m_has_delay_slot;
bool m_is_valid;
bool m_using_file_addr;
};
-
-
DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, const char *cpu, const char *features_str, unsigned flavor, DisassemblerLLVMC &owner):
m_is_valid(true)
{
@@ -482,9 +525,7 @@ DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, con
m_is_valid = false;
}
-DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler()
-{
-}
+DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler() = default;
uint64_t
DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (const uint8_t *opcode_data,
@@ -508,22 +549,25 @@ DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (const uint8_t *opcode_data,
return 0;
}
-uint64_t
+void
DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst (llvm::MCInst &mc_inst,
- char *dst,
- size_t dst_len)
+ std::string &inst_string,
+ std::string &comments_string)
{
- llvm::StringRef unused_annotations;
- llvm::SmallString<64> inst_string;
- llvm::raw_svector_ostream inst_stream(inst_string);
- m_instr_printer_ap->printInst (&mc_inst, inst_stream, unused_annotations,
- *m_subtarget_info_ap);
- inst_stream.flush();
- const size_t output_size = std::min(dst_len - 1, inst_string.size());
- std::memcpy(dst, inst_string.data(), output_size);
- dst[output_size] = '\0';
-
- return output_size;
+ llvm::raw_string_ostream inst_stream(inst_string);
+ llvm::raw_string_ostream comments_stream(comments_string);
+
+ m_instr_printer_ap->setCommentStream(comments_stream);
+ m_instr_printer_ap->printInst (&mc_inst, inst_stream, llvm::StringRef(), *m_subtarget_info_ap);
+ m_instr_printer_ap->setCommentStream(llvm::nulls());
+ comments_stream.flush();
+
+ static std::string g_newlines("\r\n");
+
+ for (size_t newline_pos = 0; (newline_pos = comments_string.find_first_of(g_newlines, newline_pos)) != comments_string.npos; /**/)
+ {
+ comments_string.replace(comments_string.begin() + newline_pos, comments_string.begin() + newline_pos + 1, 1, ' ');
+ }
}
void
@@ -544,35 +588,9 @@ DisassemblerLLVMC::LLVMCDisassembler::CanBranch (llvm::MCInst &mc_inst)
}
bool
-DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor)
+DisassemblerLLVMC::LLVMCDisassembler::HasDelaySlot (llvm::MCInst &mc_inst)
{
- llvm::Triple triple = arch.GetTriple();
- if (flavor == NULL || strcmp (flavor, "default") == 0)
- return true;
-
- if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64)
- {
- if (strcmp (flavor, "intel") == 0 || strcmp (flavor, "att") == 0)
- return true;
- else
- return false;
- }
- else
- return false;
-}
-
-
-Disassembler *
-DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor)
-{
- if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch)
- {
- std::unique_ptr<DisassemblerLLVMC> disasm_ap (new DisassemblerLLVMC(arch, flavor));
-
- if (disasm_ap.get() && disasm_ap->IsValid())
- return disasm_ap.release();
- }
- return NULL;
+ return m_instr_info_ap->get(mc_inst.getOpcode()).hasDelaySlot();
}
DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_string) :
@@ -586,13 +604,12 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
m_flavor.assign("default");
}
- const char *triple = arch.GetTriple().getTriple().c_str();
unsigned flavor = ~0U;
+ llvm::Triple triple = arch.GetTriple();
// So far the only supported flavor is "intel" on x86. The base class will set this
// correctly coming in.
- if (arch.GetTriple().getArch() == llvm::Triple::x86
- || arch.GetTriple().getArch() == llvm::Triple::x86_64)
+ if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64)
{
if (m_flavor == "intel")
{
@@ -605,7 +622,7 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
}
ArchSpec thumb_arch(arch);
- if (arch.GetTriple().getArch() == llvm::Triple::arm)
+ if (triple.getArch() == llvm::Triple::arm)
{
std::string thumb_arch_name (thumb_arch.GetTriple().getArchName().str());
// Replace "arm" with "thumb" so we get all thumb variants correct
@@ -621,18 +638,29 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name.c_str()));
}
+ // If no sub architecture specified then use the most recent arm architecture so the
+ // disassembler will return all instruction. Without it we will see a lot of unknow opcode
+ // in case the code uses instructions which are not available in the oldest arm version
+ // (used when no sub architecture is specified)
+ if (triple.getArch() == llvm::Triple::arm && triple.getSubArch() == llvm::Triple::NoSubArch)
+ triple.setArchName("armv8.1a");
+
+ const char *triple_str = triple.getTriple().c_str();
+
+ // v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization
+ //
// Cortex-M3 devices (e.g. armv7m) can only execute thumb (T2) instructions,
// so hardcode the primary disassembler to thumb mode. Same for Cortex-M4 (armv7em).
//
// Handle the Cortex-M0 (armv6m) the same; the ISA is a subset of the T and T32
// instructions defined in ARMv7-A.
- if (arch.GetTriple().getArch() == llvm::Triple::arm
+ if ((triple.getArch() == llvm::Triple::arm || triple.getArch() == llvm::Triple::thumb)
&& (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m
|| arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em
|| arch.GetCore() == ArchSpec::Core::eCore_arm_armv6m))
{
- triple = thumb_arch.GetTriple().getTriple().c_str();
+ triple_str = thumb_arch.GetTriple().getTriple().c_str();
}
const char *cpu = "";
@@ -674,8 +702,8 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
}
std::string features_str = "";
- if (arch.GetTriple().getArch() == llvm::Triple::mips || arch.GetTriple().getArch() == llvm::Triple::mipsel
- || arch.GetTriple().getArch() == llvm::Triple::mips64 || arch.GetTriple().getArch() == llvm::Triple::mips64el)
+ if (triple.getArch() == llvm::Triple::mips || triple.getArch() == llvm::Triple::mipsel
+ || triple.getArch() == llvm::Triple::mips64 || triple.getArch() == llvm::Triple::mips64el)
{
uint32_t arch_flags = arch.GetFlags ();
if (arch_flags & ArchSpec::eMIPSAse_msa)
@@ -684,13 +712,9 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
features_str += "+dsp,";
if (arch_flags & ArchSpec::eMIPSAse_dspr2)
features_str += "+dspr2,";
- if (arch_flags & ArchSpec::eMIPSAse_mips16)
- features_str += "+mips16,";
- if (arch_flags & ArchSpec::eMIPSAse_micromips)
- features_str += "+micromips,";
}
- m_disasm_ap.reset (new LLVMCDisassembler(triple, cpu, features_str.c_str(), flavor, *this));
+ m_disasm_ap.reset (new LLVMCDisassembler(triple_str, cpu, features_str.c_str(), flavor, *this));
if (!m_disasm_ap->IsValid())
{
// We use m_disasm_ap.get() to tell whether we are valid or not, so if this isn't good for some reason,
@@ -698,8 +722,10 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
m_disasm_ap.reset();
}
+ llvm::Triple::ArchType llvm_arch = triple.getArch();
+
// For arm CPUs that can execute arm or thumb instructions, also create a thumb instruction disassembler.
- if (arch.GetTriple().getArch() == llvm::Triple::arm)
+ if (llvm_arch == llvm::Triple::arm)
{
std::string thumb_triple(thumb_arch.GetTriple().getTriple());
m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), "", "", flavor, *this));
@@ -709,10 +735,40 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s
m_alternate_disasm_ap.reset();
}
}
+ else if (llvm_arch == llvm::Triple::mips
+ || llvm_arch == llvm::Triple::mipsel
+ || llvm_arch == llvm::Triple::mips64
+ || llvm_arch == llvm::Triple::mips64el)
+ {
+ /* Create alternate disassembler for MIPS16 and microMIPS */
+ uint32_t arch_flags = arch.GetFlags ();
+ if (arch_flags & ArchSpec::eMIPSAse_mips16)
+ features_str += "+mips16,";
+ else if (arch_flags & ArchSpec::eMIPSAse_micromips)
+ features_str += "+micromips,";
+
+ m_alternate_disasm_ap.reset(new LLVMCDisassembler (triple_str, cpu, features_str.c_str(), flavor, *this));
+ if (!m_alternate_disasm_ap->IsValid())
+ {
+ m_disasm_ap.reset();
+ m_alternate_disasm_ap.reset();
+ }
+ }
}
-DisassemblerLLVMC::~DisassemblerLLVMC()
+DisassemblerLLVMC::~DisassemblerLLVMC() = default;
+
+Disassembler *
+DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor)
{
+ if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch)
+ {
+ std::unique_ptr<DisassemblerLLVMC> disasm_ap (new DisassemblerLLVMC(arch, flavor));
+
+ if (disasm_ap.get() && disasm_ap->IsValid())
+ return disasm_ap.release();
+ }
+ return NULL;
}
size_t
@@ -817,6 +873,24 @@ const char *DisassemblerLLVMC::SymbolLookupCallback (void *disassembler,
name);
}
+bool
+DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor)
+{
+ llvm::Triple triple = arch.GetTriple();
+ if (flavor == NULL || strcmp (flavor, "default") == 0)
+ return true;
+
+ if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64)
+ {
+ if (strcmp (flavor, "intel") == 0 || strcmp (flavor, "att") == 0)
+ return true;
+ else
+ return false;
+ }
+ else
+ return false;
+}
+
int DisassemblerLLVMC::OpInfo (uint64_t PC,
uint64_t Offset,
uint64_t Size,
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
index 56cec03994ef..6359146d81d8 100644
--- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
@@ -10,10 +10,20 @@
#ifndef liblldb_DisassemblerLLVMC_h_
#define liblldb_DisassemblerLLVMC_h_
+// C Includes
+// C++ Includes
+#include <memory>
#include <string>
+// Other libraries and framework includes
#include "llvm-c/Disassembler.h"
+// Project includes
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Host/Mutex.h"
+
// Opaque references to C++ Objects in LLVM's MC.
namespace llvm
{
@@ -25,12 +35,7 @@ namespace llvm
class MCInstPrinter;
class MCAsmInfo;
class MCSubtargetInfo;
-}
-
-#include "lldb/Core/Address.h"
-#include "lldb/Core/Disassembler.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Host/Mutex.h"
+} // namespace llvm
class InstructionLLVMC;
@@ -46,9 +51,10 @@ class DisassemblerLLVMC : public lldb_private::Disassembler
~LLVMCDisassembler();
uint64_t GetMCInst (const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, llvm::MCInst &mc_inst);
- uint64_t PrintMCInst (llvm::MCInst &mc_inst, char *output_buffer, size_t out_buffer_len);
+ void PrintMCInst (llvm::MCInst &mc_inst, std::string &inst_string, std::string &comments_string);
void SetStyle (bool use_hex_immed, HexImmediateStyle hex_style);
bool CanBranch (llvm::MCInst &mc_inst);
+ bool HasDelaySlot (llvm::MCInst &mc_inst);
bool IsValid()
{
return m_is_valid;
@@ -66,6 +72,10 @@ class DisassemblerLLVMC : public lldb_private::Disassembler
};
public:
+ DisassemblerLLVMC(const lldb_private::ArchSpec &arch, const char *flavor /* = NULL */);
+
+ ~DisassemblerLLVMC() override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
@@ -81,33 +91,28 @@ public:
static lldb_private::Disassembler *
CreateInstance(const lldb_private::ArchSpec &arch, const char *flavor);
- DisassemblerLLVMC(const lldb_private::ArchSpec &arch, const char *flavor /* = NULL */);
-
- virtual
- ~DisassemblerLLVMC();
-
- virtual size_t
- DecodeInstructions (const lldb_private::Address &base_addr,
- const lldb_private::DataExtractor& data,
- lldb::offset_t data_offset,
- size_t num_instructions,
- bool append,
- bool data_from_file);
+ size_t
+ DecodeInstructions(const lldb_private::Address &base_addr,
+ const lldb_private::DataExtractor& data,
+ lldb::offset_t data_offset,
+ size_t num_instructions,
+ bool append,
+ bool data_from_file) override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
protected:
friend class InstructionLLVMC;
- virtual bool
- FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor);
+ bool
+ FlavorValidForArchSpec(const lldb_private::ArchSpec &arch, const char *flavor) override;
bool
IsValid()
@@ -163,4 +168,4 @@ protected:
std::unique_ptr<LLVMCDisassembler> m_alternate_disasm_ap;
};
-#endif // liblldb_DisassemblerLLVM_h_
+#endif // liblldb_DisassemblerLLVM_h_
diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
index 2308129b8cab..28493170ac36 100644
--- a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
+++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
@@ -104,11 +104,6 @@ DynamicLoaderHexagonDYLD::GetPluginDescriptionStatic()
"loads/unloads in Hexagon processes.";
}
-void
-DynamicLoaderHexagonDYLD::GetPluginCommandHelp(const char *command, Stream *strm)
-{
-}
-
uint32_t
DynamicLoaderHexagonDYLD::GetPluginVersion()
{
@@ -177,7 +172,7 @@ DynamicLoaderHexagonDYLD::DidAttach()
// Map the loaded sections of this executable
if ( load_offset != LLDB_INVALID_ADDRESS )
- UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset);
+ UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true);
// AD: confirm this?
// Load into LLDB all of the currently loaded executables in the stub
@@ -248,18 +243,6 @@ DynamicLoaderHexagonDYLD::GetTargetExecutable()
return executable;
}
-Error
-DynamicLoaderHexagonDYLD::ExecutePluginCommand(Args &command, Stream *strm)
-{
- return Error();
-}
-
-Log *
-DynamicLoaderHexagonDYLD::EnablePluginLogging(Stream *strm, Args &command)
-{
- return NULL;
-}
-
//AD: Needs to be updated?
Error
DynamicLoaderHexagonDYLD::CanLoadImage()
@@ -268,7 +251,10 @@ DynamicLoaderHexagonDYLD::CanLoadImage()
}
void
-DynamicLoaderHexagonDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr)
+DynamicLoaderHexagonDYLD::UpdateLoadedSections(ModuleSP module,
+ addr_t link_map_addr,
+ addr_t base_addr,
+ bool base_addr_is_offset)
{
Target &target = m_process->GetTarget();
const SectionList *sections = GetSectionListFromModule(module);
@@ -442,7 +428,7 @@ DynamicLoaderHexagonDYLD::RefreshModules()
for (I = m_rendezvous.loaded_begin(); I != E; ++I)
{
FileSpec file(I->path.c_str(), true);
- ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr);
+ ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr, true);
if (module_sp.get())
{
loaded_modules.AppendIfNeeded( module_sp );
@@ -571,7 +557,7 @@ DynamicLoaderHexagonDYLD::LoadAllCurrentModules()
{
const char *module_path = I->path.c_str();
FileSpec file(module_path, false);
- ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr);
+ ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr, true);
if (module_sp.get())
{
module_list.Append(module_sp);
@@ -591,7 +577,10 @@ DynamicLoaderHexagonDYLD::LoadAllCurrentModules()
/// Helper for the entry breakpoint callback. Resolves the load addresses
/// of all dependent modules.
ModuleSP
-DynamicLoaderHexagonDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, addr_t base_addr)
+DynamicLoaderHexagonDYLD::LoadModuleAtAddress(const FileSpec &file,
+ addr_t link_map_addr,
+ addr_t base_addr,
+ bool base_addr_is_offset)
{
Target &target = m_process->GetTarget();
ModuleList &modules = target.GetImages();
@@ -602,12 +591,12 @@ DynamicLoaderHexagonDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t link_
// check if module is currently loaded
if ((module_sp = modules.FindFirstModule (module_spec)))
{
- UpdateLoadedSections(module_sp, link_map_addr, base_addr);
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr, true);
}
// try to load this module from disk
else if ((module_sp = target.GetSharedModule(module_spec)))
{
- UpdateLoadedSections(module_sp, link_map_addr, base_addr);
+ UpdateLoadedSections(module_sp, link_map_addr, base_addr, true);
}
return module_sp;
diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h
index aafa385c0fca..e10d4ee64209 100644
--- a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h
+++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h
@@ -7,12 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_DynamicLoaderHexagon_H_
-#define liblldb_DynamicLoaderHexagon_H_
+#ifndef liblldb_DynamicLoaderHexagonDYLD_h_
+#define liblldb_DynamicLoaderHexagonDYLD_h_
// C Includes
// C++ Includes
// Other libraries and framework includes
+// Project includes
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Target/DynamicLoader.h"
@@ -21,6 +22,9 @@
class DynamicLoaderHexagonDYLD : public lldb_private::DynamicLoader
{
public:
+ DynamicLoaderHexagonDYLD(lldb_private::Process *process);
+
+ ~DynamicLoaderHexagonDYLD() override;
static void
Initialize();
@@ -37,48 +41,34 @@ public:
static lldb_private::DynamicLoader *
CreateInstance(lldb_private::Process *process, bool force);
- DynamicLoaderHexagonDYLD(lldb_private::Process *process);
-
- virtual
- ~DynamicLoaderHexagonDYLD();
-
//------------------------------------------------------------------
// DynamicLoader protocol
//------------------------------------------------------------------
- virtual void
- DidAttach();
+ void
+ DidAttach() override;
- virtual void
- DidLaunch();
+ void
+ DidLaunch() override;
- virtual lldb::ThreadPlanSP
+ lldb::ThreadPlanSP
GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
- bool stop_others);
+ bool stop_others) override;
- virtual lldb_private::Error
- CanLoadImage();
+ lldb_private::Error
+ CanLoadImage() override;
- virtual lldb::addr_t
- GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread);
+ lldb::addr_t
+ GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread) override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
-
- virtual void
- GetPluginCommandHelp(const char *command, lldb_private::Stream *strm);
-
- virtual lldb_private::Error
- ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm);
-
- virtual lldb_private::Log *
- EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command);
+ uint32_t
+ GetPluginVersion() override;
protected:
/// Runtime linker rendezvous structure.
@@ -124,18 +114,22 @@ protected:
void
UpdateLoadedSections(lldb::ModuleSP module,
lldb::addr_t link_map_addr,
- lldb::addr_t base_addr);
+ lldb::addr_t base_addr,
+ bool base_addr_is_offset) override;
/// Removes the loaded sections from the target in @p module.
///
/// @param module The module to traverse.
void
- UnloadSections(const lldb::ModuleSP module);
+ UnloadSections(const lldb::ModuleSP module) override;
/// Locates or creates a module given by @p file and updates/loads the
/// resulting module at the virtual base address @p base_addr.
lldb::ModuleSP
- LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t link_map_addr, lldb::addr_t base_addr);
+ LoadModuleAtAddress(const lldb_private::FileSpec &file,
+ lldb::addr_t link_map_addr,
+ lldb::addr_t base_addr,
+ bool base_addr_is_offset) override;
/// Callback routine invoked when we hit the breakpoint on process entry.
///
@@ -173,10 +167,10 @@ protected:
FindRendezvousBreakpointAddress( );
private:
- DISALLOW_COPY_AND_ASSIGN(DynamicLoaderHexagonDYLD);
-
const lldb_private::SectionList *
GetSectionListFromModule(const lldb::ModuleSP module) const;
+
+ DISALLOW_COPY_AND_ASSIGN(DynamicLoaderHexagonDYLD);
};
-#endif // liblldb_DynamicLoaderHexagonDYLD_H_
+#endif // liblldb_DynamicLoaderHexagonDYLD_h_
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
index 8b1dd283394b..09e874a011df 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
@@ -17,6 +17,7 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -290,19 +291,13 @@ DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry)
// FreeBSD and on Android it is the full path to the executable.
auto triple = m_process->GetTarget().GetArchitecture().GetTriple();
- auto os_type = triple.getOS();
- auto env_type = triple.getEnvironment();
-
- switch (os_type) {
+ switch (triple.getOS()) {
case llvm::Triple::FreeBSD:
return entry.file_spec == m_exe_file_spec;
case llvm::Triple::Linux:
- switch (env_type) {
- case llvm::Triple::Android:
- return entry.file_spec == m_exe_file_spec;
- default:
- return !entry.file_spec;
- }
+ if (triple.isAndroid())
+ return entry.file_spec == m_exe_file_spec;
+ return !entry.file_spec;
default:
return false;
}
@@ -372,6 +367,25 @@ DYLDRendezvous::ReadStringFromMemory(addr_t addr)
return str;
}
+// Returns true if the load bias reported by the linker is incorrect for the given entry. This
+// function is used to handle cases where we want to work around a bug in the system linker.
+static bool
+isLoadBiasIncorrect(Target& target, const std::string& file_path)
+{
+ // On Android L (API 21, 22) the load address of the "/system/bin/linker" isn't filled in
+ // correctly.
+ uint32_t os_major = 0, os_minor = 0, os_update = 0;
+ if (target.GetArchitecture().GetTriple().isAndroid() &&
+ target.GetPlatform()->GetOSVersion(os_major, os_minor, os_update) &&
+ (os_major == 21 || os_major == 22) &&
+ (file_path == "/system/bin/linker" || file_path == "/system/bin/linker64"))
+ {
+ return true;
+ }
+
+ return false;
+}
+
bool
DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
{
@@ -413,11 +427,9 @@ DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
std::string file_path = ReadStringFromMemory(entry.path_addr);
entry.file_spec.SetFile(file_path, false);
- // On Android L (5.0, 5.1) the load address of the "/system/bin/linker" isn't filled in
- // correctly. To get the correct load address we fetch the load address of the file from the
- // proc file system.
- if (arch.GetTriple().getEnvironment() == llvm::Triple::Android && entry.base_addr == 0 &&
- (file_path == "/system/bin/linker" || file_path == "/system/bin/linker64"))
+ // If the load bias reported by the linker is incorrect then fetch the load address of the file
+ // from the proc file system.
+ if (isLoadBiasIncorrect(m_process->GetTarget(), file_path))
{
lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
bool is_loaded = false;
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 8724fc039cb9..6ba7b470d743 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -62,11 +62,6 @@ DynamicLoaderPOSIXDYLD::GetPluginDescriptionStatic()
"loads/unloads in POSIX processes.";
}
-void
-DynamicLoaderPOSIXDYLD::GetPluginCommandHelp(const char *command, Stream *strm)
-{
-}
-
uint32_t
DynamicLoaderPOSIXDYLD::GetPluginVersion()
{
@@ -96,7 +91,8 @@ DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process)
m_load_offset(LLDB_INVALID_ADDRESS),
m_entry_point(LLDB_INVALID_ADDRESS),
m_auxv(),
- m_dyld_bid(LLDB_INVALID_BREAK_ID)
+ m_dyld_bid(LLDB_INVALID_BREAK_ID),
+ m_vdso_base(LLDB_INVALID_ADDRESS)
{
}
@@ -131,6 +127,8 @@ DynamicLoaderPOSIXDYLD::DidAttach()
if (log)
log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " executable '%s', load_offset 0x%" PRIx64, __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, executable_sp ? executable_sp->GetFileSpec().GetPath().c_str () : "<null executable>", load_offset);
+ EvalVdsoStatus();
+
// if we dont have a load address we cant re-base
bool rebase_exec = (load_offset == LLDB_INVALID_ADDRESS) ? false : true;
@@ -165,7 +163,7 @@ DynamicLoaderPOSIXDYLD::DidAttach()
m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID,
executable_sp->GetFileSpec().GetPath().c_str ());
- UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset);
+ UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset, true);
// When attaching to a target, there are two possible states:
// (1) We already crossed the entry point and therefore the rendezvous
@@ -218,12 +216,13 @@ DynamicLoaderPOSIXDYLD::DidLaunch()
executable = GetTargetExecutable();
load_offset = ComputeLoadOffset();
+ EvalVdsoStatus();
if (executable.get() && load_offset != LLDB_INVALID_ADDRESS)
{
ModuleList module_list;
module_list.Append(executable);
- UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset);
+ UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true);
if (log)
log->Printf ("DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()", __FUNCTION__);
@@ -234,29 +233,19 @@ DynamicLoaderPOSIXDYLD::DidLaunch()
}
Error
-DynamicLoaderPOSIXDYLD::ExecutePluginCommand(Args &command, Stream *strm)
-{
- return Error();
-}
-
-Log *
-DynamicLoaderPOSIXDYLD::EnablePluginLogging(Stream *strm, Args &command)
-{
- return NULL;
-}
-
-Error
DynamicLoaderPOSIXDYLD::CanLoadImage()
{
return Error();
}
void
-DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr)
+DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module,
+ addr_t link_map_addr,
+ addr_t base_addr,
+ bool base_addr_is_offset)
{
m_loaded_modules[module] = link_map_addr;
-
- UpdateLoadedSectionsCommon(module, base_addr);
+ UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
}
void
@@ -414,7 +403,7 @@ DynamicLoaderPOSIXDYLD::RefreshModules()
E = m_rendezvous.loaded_end();
for (I = m_rendezvous.loaded_begin(); I != E; ++I)
{
- ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr);
+ ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true);
if (module_sp.get())
{
loaded_modules.AppendIfNeeded(module_sp);
@@ -432,8 +421,7 @@ DynamicLoaderPOSIXDYLD::RefreshModules()
for (I = m_rendezvous.unloaded_begin(); I != E; ++I)
{
ModuleSpec module_spec{I->file_spec};
- ModuleSP module_sp =
- loaded_modules.FindFirstModule (module_spec);
+ ModuleSP module_sp = loaded_modules.FindFirstModule (module_spec);
if (module_sp.get())
{
@@ -519,11 +507,18 @@ DynamicLoaderPOSIXDYLD::LoadAllCurrentModules()
// that ourselves here.
ModuleSP executable = GetTargetExecutable();
m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress();
-
-
+ if (m_vdso_base != LLDB_INVALID_ADDRESS)
+ {
+ FileSpec file_spec("[vdso]", false);
+ ModuleSP module_sp = LoadModuleAtAddress(file_spec, LLDB_INVALID_ADDRESS, m_vdso_base, false);
+ if (module_sp.get())
+ {
+ module_list.Append(module_sp);
+ }
+ }
for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
{
- ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr);
+ ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true);
if (module_sp.get())
{
module_list.Append(module_sp);
@@ -568,6 +563,16 @@ DynamicLoaderPOSIXDYLD::ComputeLoadOffset()
return m_load_offset;
}
+void
+DynamicLoaderPOSIXDYLD::EvalVdsoStatus()
+{
+ AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_SYSINFO_EHDR);
+
+ if (I != m_auxv->end())
+ m_vdso_base = I->value;
+
+}
+
addr_t
DynamicLoaderPOSIXDYLD::GetEntryPoint()
{
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
index 68d3059cb4be..cb97bbf43ba9 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
@@ -1,4 +1,4 @@
-//===-- DynamicLoaderPOSIX.h ------------------------------------*- C++ -*-===//
+//===-- DynamicLoaderPOSIXDYLD.h --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,12 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_DynamicLoaderPOSIX_H_
-#define liblldb_DynamicLoaderPOSIX_H_
+#ifndef liblldb_DynamicLoaderPOSIXDYLD_h_
+#define liblldb_DynamicLoaderPOSIXDYLD_h_
// C Includes
// C++ Includes
// Other libraries and framework includes
+// Project includes
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Target/DynamicLoader.h"
@@ -23,6 +24,9 @@ class AuxVector;
class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader
{
public:
+ DynamicLoaderPOSIXDYLD(lldb_private::Process *process);
+
+ ~DynamicLoaderPOSIXDYLD() override;
static void
Initialize();
@@ -39,48 +43,34 @@ public:
static lldb_private::DynamicLoader *
CreateInstance(lldb_private::Process *process, bool force);
- DynamicLoaderPOSIXDYLD(lldb_private::Process *process);
-
- virtual
- ~DynamicLoaderPOSIXDYLD();
-
//------------------------------------------------------------------
// DynamicLoader protocol
//------------------------------------------------------------------
- virtual void
- DidAttach();
+ void
+ DidAttach() override;
- virtual void
- DidLaunch();
+ void
+ DidLaunch() override;
- virtual lldb::ThreadPlanSP
+ lldb::ThreadPlanSP
GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
- bool stop_others);
+ bool stop_others) override;
- virtual lldb_private::Error
- CanLoadImage();
+ lldb_private::Error
+ CanLoadImage() override;
- virtual lldb::addr_t
- GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread);
+ lldb::addr_t
+ GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread) override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
-
- virtual uint32_t
- GetPluginVersion();
-
- virtual void
- GetPluginCommandHelp(const char *command, lldb_private::Stream *strm);
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual lldb_private::Error
- ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm);
-
- virtual lldb_private::Log *
- EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command);
+ uint32_t
+ GetPluginVersion() override;
protected:
/// Runtime linker rendezvous structure.
@@ -98,12 +88,16 @@ protected:
/// Rendezvous breakpoint.
lldb::break_id_t m_dyld_bid;
+ /// Contains AT_SYSINFO_EHDR, which means a vDSO has been
+ /// mapped to the address space
+ lldb::addr_t m_vdso_base;
+
/// Loaded module list. (link map for each module)
std::map<lldb::ModuleWP, lldb::addr_t, std::owner_less<lldb::ModuleWP>> m_loaded_modules;
/// Enables a breakpoint on a function called by the runtime
/// linker each time a module is loaded or unloaded.
- void
+ virtual void
SetRendezvousBreakpoint();
/// Callback routine which updates the current list of loaded modules based
@@ -126,16 +120,17 @@ protected:
/// @param link_map_addr The virtual address of the link map for the @p module.
///
/// @param base_addr The virtual base address @p module is loaded at.
- virtual void
+ void
UpdateLoadedSections(lldb::ModuleSP module,
lldb::addr_t link_map_addr,
- lldb::addr_t base_addr);
+ lldb::addr_t base_addr,
+ bool base_addr_is_offset) override;
/// Removes the loaded sections from the target in @p module.
///
/// @param module The module to traverse.
- virtual void
- UnloadSections(const lldb::ModuleSP module);
+ void
+ UnloadSections(const lldb::ModuleSP module) override;
/// Resolves the entry point for the current inferior process and sets a
/// breakpoint at that address.
@@ -155,7 +150,7 @@ protected:
/// Helper for the entry breakpoint callback. Resolves the load addresses
/// of all dependent modules.
- void
+ virtual void
LoadAllCurrentModules();
/// Computes a value for m_load_offset returning the computed address on
@@ -168,6 +163,11 @@ protected:
lldb::addr_t
GetEntryPoint();
+ /// Evaluate if Aux vectors contain vDSO information
+ /// in case they do, read and assign the address to m_vdso_base
+ void
+ EvalVdsoStatus();
+
/// Loads Module from inferior process.
void
ResolveExecutableModule(lldb::ModuleSP &module_sp);
@@ -176,4 +176,4 @@ private:
DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD);
};
-#endif // liblldb_DynamicLoaderPOSIXDYLD_H_
+#endif // liblldb_DynamicLoaderPOSIXDYLD_h_
diff --git a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h
index ea33164cf823..a7fdf4d22165 100644
--- a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h
+++ b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h
@@ -12,12 +12,8 @@
// C Includes
// C++ Includes
-#include <map>
-#include <vector>
-#include <string>
-
// Other libraries and framework includes
-
+// Project includes
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Core/UUID.h"
@@ -27,6 +23,10 @@
class DynamicLoaderStatic : public lldb_private::DynamicLoader
{
public:
+ DynamicLoaderStatic(lldb_private::Process *process);
+
+ ~DynamicLoaderStatic() override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
@@ -45,37 +45,33 @@ public:
static lldb_private::DynamicLoader *
CreateInstance (lldb_private::Process *process, bool force);
- DynamicLoaderStatic (lldb_private::Process *process);
-
- virtual
- ~DynamicLoaderStatic ();
//------------------------------------------------------------------
/// Called after attaching a process.
///
/// Allow DynamicLoader plug-ins to execute some code after
/// attaching to a process.
//------------------------------------------------------------------
- virtual void
- DidAttach ();
+ void
+ DidAttach() override;
- virtual void
- DidLaunch ();
+ void
+ DidLaunch() override;
- virtual lldb::ThreadPlanSP
- GetStepThroughTrampolinePlan (lldb_private::Thread &thread,
- bool stop_others);
+ lldb::ThreadPlanSP
+ GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
+ bool stop_others) override;
- virtual lldb_private::Error
- CanLoadImage ();
+ lldb_private::Error
+ CanLoadImage() override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
private:
void
@@ -84,4 +80,4 @@ private:
DISALLOW_COPY_AND_ASSIGN (DynamicLoaderStatic);
};
-#endif // liblldb_DynamicLoaderStatic_h_
+#endif // liblldb_DynamicLoaderStatic_h_
diff --git a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
index 56b56ab3a194..dd391b4ca4d2 100644
--- a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
+++ b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
@@ -21,40 +21,39 @@ using namespace lldb_private;
DynamicLoaderWindowsDYLD::DynamicLoaderWindowsDYLD(Process *process)
: DynamicLoader(process)
{
-
}
DynamicLoaderWindowsDYLD::~DynamicLoaderWindowsDYLD()
{
-
}
-void DynamicLoaderWindowsDYLD::Initialize()
+void
+DynamicLoaderWindowsDYLD::Initialize()
{
- PluginManager::RegisterPlugin(GetPluginNameStatic(),
- GetPluginDescriptionStatic(),
- CreateInstance);
+ PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance);
}
-void DynamicLoaderWindowsDYLD::Terminate()
+void
+DynamicLoaderWindowsDYLD::Terminate()
{
-
}
-ConstString DynamicLoaderWindowsDYLD::GetPluginNameStatic()
+ConstString
+DynamicLoaderWindowsDYLD::GetPluginNameStatic()
{
static ConstString g_plugin_name("windows-dyld");
return g_plugin_name;
}
-const char *DynamicLoaderWindowsDYLD::GetPluginDescriptionStatic()
+const char *
+DynamicLoaderWindowsDYLD::GetPluginDescriptionStatic()
{
return "Dynamic loader plug-in that watches for shared library "
"loads/unloads in Windows processes.";
}
-
-DynamicLoader *DynamicLoaderWindowsDYLD::CreateInstance(Process *process, bool force)
+DynamicLoader *
+DynamicLoaderWindowsDYLD::CreateInstance(Process *process, bool force)
{
bool should_create = force;
if (!should_create)
@@ -65,32 +64,35 @@ DynamicLoader *DynamicLoaderWindowsDYLD::CreateInstance(Process *process, bool f
}
if (should_create)
- return new DynamicLoaderWindowsDYLD (process);
+ return new DynamicLoaderWindowsDYLD(process);
return nullptr;
}
-void DynamicLoaderWindowsDYLD::DidAttach()
+void
+DynamicLoaderWindowsDYLD::DidAttach()
{
-
}
-void DynamicLoaderWindowsDYLD::DidLaunch()
+void
+DynamicLoaderWindowsDYLD::DidLaunch()
{
-
}
-Error DynamicLoaderWindowsDYLD::CanLoadImage()
+Error
+DynamicLoaderWindowsDYLD::CanLoadImage()
{
return Error();
}
-ConstString DynamicLoaderWindowsDYLD::GetPluginName()
+ConstString
+DynamicLoaderWindowsDYLD::GetPluginName()
{
return GetPluginNameStatic();
}
-uint32_t DynamicLoaderWindowsDYLD::GetPluginVersion()
+uint32_t
+DynamicLoaderWindowsDYLD::GetPluginVersion()
{
return 1;
}
diff --git a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h
index d12b999f4627..8c479819c535 100644
--- a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h
+++ b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h
@@ -1,4 +1,4 @@
-//===-- DynamicLoaderWindowsDYLDh ----------------------------------*- C++ -*-===//
+//===-- DynamicLoaderWindowsDYLD.h ------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,9 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_H_
-#define liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_H_
+#ifndef liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_h_
+#define liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-forward.h"
#include "lldb/Target/DynamicLoader.h"
@@ -18,9 +22,10 @@ namespace lldb_private
class DynamicLoaderWindowsDYLD : public DynamicLoader
{
- public:
+public:
DynamicLoaderWindowsDYLD(Process *process);
- virtual ~DynamicLoaderWindowsDYLD();
+
+ ~DynamicLoaderWindowsDYLD() override;
static void Initialize();
static void Terminate();
@@ -29,15 +34,15 @@ class DynamicLoaderWindowsDYLD : public DynamicLoader
static DynamicLoader *CreateInstance(Process *process, bool force);
- void DidAttach () override;
- void DidLaunch () override;
- Error CanLoadImage () override;
+ void DidAttach() override;
+ void DidLaunch() override;
+ Error CanLoadImage() override;
lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread, bool stop) override;
ConstString GetPluginName() override;
uint32_t GetPluginVersion() override;
};
-}
+} // namespace lldb_private
-#endif
+#endif // liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_h_
diff --git a/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp b/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp
new file mode 100644
index 000000000000..976310610f51
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp
@@ -0,0 +1,134 @@
+//===-- ASTDumper.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ASTDumper.h"
+
+#include "lldb/Core/Log.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/CompilerType.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 = ClangASTContext::GetQualType(compiler_type).getAsString();
+}
+
+
+const char *
+ASTDumper::GetCString()
+{
+ return m_dump.c_str();
+}
+
+void ASTDumper::ToSTDERR()
+{
+ fprintf(stderr, "%s\n", 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 = NULL;
+
+ end = strchr(str, '\n');
+
+ while (end)
+ {
+ *end = '\0';
+
+ log->Printf("%s%s", prefix, str);
+
+ *end = '\n';
+
+ str = end + 1;
+ end = strchr(str, '\n');
+ }
+
+ log->Printf("%s%s", prefix, str);
+
+ free(alloc);
+}
+
+void ASTDumper::ToStream(lldb::StreamSP &stream)
+{
+ stream->PutCString(m_dump.c_str());
+}
diff --git a/source/Plugins/ExpressionParser/Clang/ASTDumper.h b/source/Plugins/ExpressionParser/Clang/ASTDumper.h
new file mode 100644
index 000000000000..c8dc6847d6c2
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ASTDumper.h
@@ -0,0 +1,42 @@
+//===-- ASTDumper.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ASTDumper_h_
+#define liblldb_ASTDumper_h_
+
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/TypeVisitor.h"
+
+#include "lldb/Core/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/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
new file mode 100644
index 000000000000..02505bde240c
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
@@ -0,0 +1,514 @@
+//===-- ASTResultSynthesizer.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ASTResultSynthesizer.h"
+
+#include "ClangPersistentVariables.h"
+
+#include "stdlib.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Sema/SemaDiagnostic.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ClangASTImporter.h"
+#include "lldb/Target/Target.h"
+
+using namespace llvm;
+using namespace clang;
+using namespace lldb_private;
+
+ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough,
+ Target &target) :
+ m_ast_context (NULL),
+ m_passthrough (passthrough),
+ m_passthrough_sema (NULL),
+ m_target (target),
+ m_sema (NULL)
+{
+ if (!m_passthrough)
+ return;
+
+ m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
+}
+
+ASTResultSynthesizer::~ASTResultSynthesizer()
+{
+}
+
+void
+ASTResultSynthesizer::Initialize(ASTContext &Context)
+{
+ m_ast_context = &Context;
+
+ if (m_passthrough)
+ m_passthrough->Initialize(Context);
+}
+
+void
+ASTResultSynthesizer::TransformTopLevelDecl(Decl* D)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (NamedDecl *named_decl = dyn_cast<NamedDecl>(D))
+ {
+ if (log && log->GetVerbose())
+ {
+ if (named_decl->getIdentifier())
+ log->Printf("TransformTopLevelDecl(%s)", named_decl->getIdentifier()->getNameStart());
+ else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D))
+ log->Printf("TransformTopLevelDecl(%s)", method_decl->getSelector().getAsString().c_str());
+ else
+ log->Printf("TransformTopLevelDecl(<complex>)");
+ }
+
+ }
+
+ if (LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D))
+ {
+ RecordDecl::decl_iterator decl_iterator;
+
+ for (decl_iterator = linkage_spec_decl->decls_begin();
+ decl_iterator != linkage_spec_decl->decls_end();
+ ++decl_iterator)
+ {
+ TransformTopLevelDecl(*decl_iterator);
+ }
+ }
+ else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D))
+ {
+ if (m_ast_context &&
+ !method_decl->getSelector().getAsString().compare("$__lldb_expr:"))
+ {
+ RecordPersistentTypes(method_decl);
+ SynthesizeObjCMethodResult(method_decl);
+ }
+ }
+ else if (FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D))
+ {
+ if (m_ast_context &&
+ !function_decl->getNameInfo().getAsString().compare("$__lldb_expr"))
+ {
+ RecordPersistentTypes(function_decl);
+ SynthesizeFunctionResult(function_decl);
+ }
+ }
+}
+
+bool
+ASTResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D)
+{
+ DeclGroupRef::iterator decl_iterator;
+
+ for (decl_iterator = D.begin();
+ decl_iterator != D.end();
+ ++decl_iterator)
+ {
+ Decl *decl = *decl_iterator;
+
+ TransformTopLevelDecl(decl);
+ }
+
+ if (m_passthrough)
+ return m_passthrough->HandleTopLevelDecl(D);
+ return true;
+}
+
+bool
+ASTResultSynthesizer::SynthesizeFunctionResult (FunctionDecl *FunDecl)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (!m_sema)
+ return false;
+
+ FunctionDecl *function_decl = FunDecl;
+
+ if (!function_decl)
+ return false;
+
+ if (log && log->GetVerbose())
+ {
+ std::string s;
+ raw_string_ostream os(s);
+
+ function_decl->print(os);
+
+ os.flush();
+
+ log->Printf ("Untransformed function AST:\n%s", s.c_str());
+ }
+
+ Stmt *function_body = function_decl->getBody();
+ CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body);
+
+ bool ret = SynthesizeBodyResult (compound_stmt,
+ function_decl);
+
+ if (log && log->GetVerbose())
+ {
+ std::string s;
+ raw_string_ostream os(s);
+
+ function_decl->print(os);
+
+ os.flush();
+
+ log->Printf ("Transformed function AST:\n%s", s.c_str());
+ }
+
+ return ret;
+}
+
+bool
+ASTResultSynthesizer::SynthesizeObjCMethodResult (ObjCMethodDecl *MethodDecl)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (!m_sema)
+ return false;
+
+ if (!MethodDecl)
+ return false;
+
+ if (log && log->GetVerbose())
+ {
+ std::string s;
+ raw_string_ostream os(s);
+
+ MethodDecl->print(os);
+
+ os.flush();
+
+ log->Printf ("Untransformed method AST:\n%s", s.c_str());
+ }
+
+ Stmt *method_body = MethodDecl->getBody();
+
+ if (!method_body)
+ return false;
+
+ CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(method_body);
+
+ bool ret = SynthesizeBodyResult (compound_stmt,
+ MethodDecl);
+
+ if (log && log->GetVerbose())
+ {
+ std::string s;
+ raw_string_ostream os(s);
+
+ MethodDecl->print(os);
+
+ os.flush();
+
+ log->Printf("Transformed method AST:\n%s", s.c_str());
+ }
+
+ return ret;
+}
+
+bool
+ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body,
+ DeclContext *DC)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ ASTContext &Ctx(*m_ast_context);
+
+ if (!Body)
+ return false;
+
+ if (Body->body_empty())
+ return false;
+
+ Stmt **last_stmt_ptr = Body->body_end() - 1;
+ Stmt *last_stmt = *last_stmt_ptr;
+
+ while (dyn_cast<NullStmt>(last_stmt))
+ {
+ if (last_stmt_ptr != Body->body_begin())
+ {
+ last_stmt_ptr--;
+ last_stmt = *last_stmt_ptr;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ Expr *last_expr = dyn_cast<Expr>(last_stmt);
+
+ if (!last_expr)
+ // No auxiliary variable necessary; expression returns void
+ return true;
+
+ // In C++11, last_expr can be a LValueToRvalue implicit cast. Strip that off if that's the
+ // case.
+
+ do {
+ ImplicitCastExpr *implicit_cast = dyn_cast<ImplicitCastExpr>(last_expr);
+
+ if (!implicit_cast)
+ break;
+
+ if (implicit_cast->getCastKind() != CK_LValueToRValue)
+ break;
+
+ last_expr = implicit_cast->getSubExpr();
+ } while (0);
+
+ // is_lvalue is used to record whether the expression returns an assignable Lvalue or an
+ // Rvalue. This is relevant because they are handled differently.
+ //
+ // For Lvalues
+ //
+ // - In AST result synthesis (here!) the expression E is transformed into an initialization
+ // T *$__lldb_expr_result_ptr = &E.
+ //
+ // - In structure allocation, a pointer-sized slot is allocated in the struct that is to be
+ // passed into the expression.
+ //
+ // - In IR transformations, reads and writes to $__lldb_expr_result_ptr are redirected at
+ // an entry in the struct ($__lldb_arg) passed into the expression. (Other persistent
+ // variables are treated similarly, having been materialized as references, but in those
+ // cases the value of the reference itself is never modified.)
+ //
+ // - During materialization, $0 (the result persistent variable) is ignored.
+ //
+ // - During dematerialization, $0 is marked up as a load address with value equal to the
+ // contents of the structure entry.
+ //
+ // For Rvalues
+ //
+ // - In AST result synthesis the expression E is transformed into an initialization
+ // static T $__lldb_expr_result = E.
+ //
+ // - In structure allocation, a pointer-sized slot is allocated in the struct that is to be
+ // passed into the expression.
+ //
+ // - In IR transformations, an instruction is inserted at the beginning of the function to
+ // dereference the pointer resident in the slot. Reads and writes to $__lldb_expr_result
+ // are redirected at that dereferenced version. Guard variables for the static variable
+ // are excised.
+ //
+ // - During materialization, $0 (the result persistent variable) is populated with the location
+ // of a newly-allocated area of memory.
+ //
+ // - During dematerialization, $0 is ignored.
+
+ bool is_lvalue =
+ (last_expr->getValueKind() == VK_LValue || last_expr->getValueKind() == VK_XValue) &&
+ (last_expr->getObjectKind() == OK_Ordinary);
+
+ QualType expr_qual_type = last_expr->getType();
+ const clang::Type *expr_type = expr_qual_type.getTypePtr();
+
+ if (!expr_type)
+ return false;
+
+ if (expr_type->isVoidType())
+ return true;
+
+ if (log)
+ {
+ std::string s = expr_qual_type.getAsString();
+
+ log->Printf("Last statement is an %s with type: %s", (is_lvalue ? "lvalue" : "rvalue"), s.c_str());
+ }
+
+ clang::VarDecl *result_decl = NULL;
+
+ if (is_lvalue)
+ {
+ IdentifierInfo *result_ptr_id;
+
+ if (expr_type->isFunctionType())
+ result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result"); // functions actually should be treated like function pointers
+ else
+ result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result_ptr");
+
+ m_sema->RequireCompleteType(SourceLocation(), expr_qual_type, clang::diag::err_incomplete_type);
+
+ QualType ptr_qual_type;
+
+ if (expr_qual_type->getAs<ObjCObjectType>() != NULL)
+ ptr_qual_type = Ctx.getObjCObjectPointerType(expr_qual_type);
+ else
+ ptr_qual_type = Ctx.getPointerType(expr_qual_type);
+
+ result_decl = VarDecl::Create(Ctx,
+ DC,
+ SourceLocation(),
+ SourceLocation(),
+ result_ptr_id,
+ ptr_qual_type,
+ NULL,
+ SC_Static);
+
+ if (!result_decl)
+ return false;
+
+ ExprResult address_of_expr = m_sema->CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, last_expr);
+
+ m_sema->AddInitializerToDecl(result_decl, address_of_expr.get(), true, false);
+ }
+ else
+ {
+ IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result");
+
+ result_decl = VarDecl::Create(Ctx,
+ DC,
+ SourceLocation(),
+ SourceLocation(),
+ &result_id,
+ expr_qual_type,
+ NULL,
+ SC_Static);
+
+ if (!result_decl)
+ return false;
+
+ m_sema->AddInitializerToDecl(result_decl, last_expr, true, false);
+ }
+
+ DC->addDecl(result_decl);
+
+ ///////////////////////////////
+ // call AddInitializerToDecl
+ //
+
+ //m_sema->AddInitializerToDecl(result_decl, last_expr);
+
+ /////////////////////////////////
+ // call ConvertDeclToDeclGroup
+ //
+
+ Sema::DeclGroupPtrTy result_decl_group_ptr;
+
+ result_decl_group_ptr = m_sema->ConvertDeclToDeclGroup(result_decl);
+
+ ////////////////////////
+ // call ActOnDeclStmt
+ //
+
+ StmtResult result_initialization_stmt_result(m_sema->ActOnDeclStmt(result_decl_group_ptr,
+ SourceLocation(),
+ SourceLocation()));
+
+ ////////////////////////////////////////////////
+ // replace the old statement with the new one
+ //
+
+ *last_stmt_ptr = reinterpret_cast<Stmt*>(result_initialization_stmt_result.get());
+
+ return true;
+}
+
+void
+ASTResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx)
+{
+ if (m_passthrough)
+ m_passthrough->HandleTranslationUnit(Ctx);
+}
+
+void
+ASTResultSynthesizer::RecordPersistentTypes(DeclContext *FunDeclCtx)
+{
+ typedef DeclContext::specific_decl_iterator<TypeDecl> TypeDeclIterator;
+
+ for (TypeDeclIterator i = TypeDeclIterator(FunDeclCtx->decls_begin()),
+ e = TypeDeclIterator(FunDeclCtx->decls_end());
+ i != e;
+ ++i)
+ {
+ MaybeRecordPersistentType(*i);
+ }
+}
+
+void
+ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl *D)
+{
+ if (!D->getIdentifier())
+ return;
+
+ StringRef name = D->getName();
+
+ if (name.size() == 0 || name[0] != '$')
+ return;
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ ConstString name_cs(name.str().c_str());
+
+ if (log)
+ log->Printf ("Recording persistent type %s\n", name_cs.GetCString());
+
+ Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl(m_target.GetScratchClangASTContext()->getASTContext(),
+ m_ast_context,
+ D);
+
+ if (TypeDecl *TypeDecl_scratch = dyn_cast<TypeDecl>(D_scratch))
+ llvm::cast<ClangPersistentVariables>(m_target.GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))->RegisterPersistentType(name_cs, TypeDecl_scratch);
+}
+
+void
+ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D)
+{
+ if (m_passthrough)
+ m_passthrough->HandleTagDeclDefinition(D);
+}
+
+void
+ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D)
+{
+ if (m_passthrough)
+ m_passthrough->CompleteTentativeDefinition(D);
+}
+
+void
+ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD)
+{
+ if (m_passthrough)
+ m_passthrough->HandleVTable(RD);
+}
+
+void
+ASTResultSynthesizer::PrintStats()
+{
+ if (m_passthrough)
+ m_passthrough->PrintStats();
+}
+
+void
+ASTResultSynthesizer::InitializeSema(Sema &S)
+{
+ m_sema = &S;
+
+ if (m_passthrough_sema)
+ m_passthrough_sema->InitializeSema(S);
+}
+
+void
+ASTResultSynthesizer::ForgetSema()
+{
+ m_sema = NULL;
+
+ if (m_passthrough_sema)
+ m_passthrough_sema->ForgetSema();
+}
diff --git a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h
new file mode 100644
index 000000000000..9f7bbe05b082
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h
@@ -0,0 +1,185 @@
+//===-- ASTResultSynthesizer.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ASTResultSynthesizer_h_
+#define liblldb_ASTResultSynthesizer_h_
+
+#include "clang/Sema/SemaConsumer.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Target/Target.h"
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+/// @class ASTResultSynthesizer ASTResultSynthesizer.h "lldb/Expression/ASTResultSynthesizer.h"
+/// @brief Adds a result variable declaration to the ASTs for an expression.
+///
+/// Users expect the expression "i + 3" to return a result, even if a result
+/// variable wasn't specifically declared. To fulfil this requirement, LLDB adds
+/// a result variable to the expression, transforming it to
+/// "int $__lldb_expr_result = i + 3." The IR transformers ensure that the
+/// resulting variable is mapped to the right piece of memory.
+/// ASTResultSynthesizer's job is to add the variable and its initialization to
+/// the ASTs for the expression, and it does so by acting as a SemaConsumer for
+/// Clang.
+//----------------------------------------------------------------------
+class ASTResultSynthesizer : public clang::SemaConsumer
+{
+public:
+ //----------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// @param[in] passthrough
+ /// Since the ASTs must typically go through to the Clang code generator
+ /// in order to produce LLVM IR, this SemaConsumer must allow them to
+ /// pass to the next step in the chain after processing. Passthrough is
+ /// the next ASTConsumer, or NULL if none is required.
+ ///
+ /// @param[in] target
+ /// The target, which contains the persistent variable store and the
+ /// AST importer.
+ //----------------------------------------------------------------------
+ ASTResultSynthesizer(clang::ASTConsumer *passthrough,
+ Target &target);
+
+ //----------------------------------------------------------------------
+ /// Destructor
+ //----------------------------------------------------------------------
+ ~ASTResultSynthesizer() override;
+
+ //----------------------------------------------------------------------
+ /// Link this consumer with a particular AST context
+ ///
+ /// @param[in] Context
+ /// This AST context will be used for types and identifiers, and also
+ /// forwarded to the passthrough consumer, if one exists.
+ //----------------------------------------------------------------------
+ void Initialize(clang::ASTContext &Context) override;
+
+ //----------------------------------------------------------------------
+ /// Examine a list of Decls to find the function $__lldb_expr and
+ /// transform its code
+ ///
+ /// @param[in] D
+ /// The list of Decls to search. These may contain LinkageSpecDecls,
+ /// which need to be searched recursively. That job falls to
+ /// TransformTopLevelDecl.
+ //----------------------------------------------------------------------
+ bool HandleTopLevelDecl(clang::DeclGroupRef D) override;
+
+ //----------------------------------------------------------------------
+ /// Passthrough stub
+ //----------------------------------------------------------------------
+ void HandleTranslationUnit(clang::ASTContext &Ctx) override;
+
+ //----------------------------------------------------------------------
+ /// Passthrough stub
+ //----------------------------------------------------------------------
+ void HandleTagDeclDefinition(clang::TagDecl *D) override;
+
+ //----------------------------------------------------------------------
+ /// Passthrough stub
+ //----------------------------------------------------------------------
+ void CompleteTentativeDefinition(clang::VarDecl *D) override;
+
+ //----------------------------------------------------------------------
+ /// Passthrough stub
+ //----------------------------------------------------------------------
+ void HandleVTable(clang::CXXRecordDecl *RD) override;
+
+ //----------------------------------------------------------------------
+ /// Passthrough stub
+ //----------------------------------------------------------------------
+ void PrintStats() override;
+
+ //----------------------------------------------------------------------
+ /// Set the Sema object to use when performing transforms, and pass it on
+ ///
+ /// @param[in] S
+ /// The Sema to use. Because Sema isn't externally visible, this class
+ /// casts it to an Action for actual use.
+ //----------------------------------------------------------------------
+ void InitializeSema(clang::Sema &S) override;
+
+ //----------------------------------------------------------------------
+ /// Reset the Sema to NULL now that transformations are done
+ //----------------------------------------------------------------------
+ void ForgetSema() override;
+
+private:
+ //----------------------------------------------------------------------
+ /// Hunt the given Decl for FunctionDecls named $__lldb_expr, recursing
+ /// as necessary through LinkageSpecDecls, and calling SynthesizeResult on
+ /// anything that was found
+ ///
+ /// @param[in] D
+ /// The Decl to hunt.
+ //----------------------------------------------------------------------
+ void TransformTopLevelDecl(clang::Decl *D);
+
+ //----------------------------------------------------------------------
+ /// Process an Objective-C method and produce the result variable and
+ /// initialization
+ ///
+ /// @param[in] MethodDecl
+ /// The method to process.
+ //----------------------------------------------------------------------
+ bool SynthesizeObjCMethodResult(clang::ObjCMethodDecl *MethodDecl);
+
+ //----------------------------------------------------------------------
+ /// Process a function and produce the result variable and initialization
+ ///
+ /// @param[in] FunDecl
+ /// The function to process.
+ //----------------------------------------------------------------------
+ bool SynthesizeFunctionResult(clang::FunctionDecl *FunDecl);
+
+ //----------------------------------------------------------------------
+ /// Process a function body and produce the result variable and
+ /// initialization
+ ///
+ /// @param[in] Body
+ /// The body of the function.
+ ///
+ /// @param[in] DC
+ /// The DeclContext of the function, into which the result variable
+ /// is inserted.
+ //----------------------------------------------------------------------
+ bool SynthesizeBodyResult(clang::CompoundStmt *Body,
+ clang::DeclContext *DC);
+
+ //----------------------------------------------------------------------
+ /// Given a DeclContext for a function or method, find all types
+ /// declared in the context and record any persistent types found.
+ ///
+ /// @param[in] FunDeclCtx
+ /// The context for the function to process.
+ //----------------------------------------------------------------------
+ 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.
+ //----------------------------------------------------------------------
+ void MaybeRecordPersistentType(clang::TypeDecl *D);
+
+ clang::ASTContext *m_ast_context; ///< The AST context to use for identifiers and types.
+ clang::ASTConsumer *m_passthrough; ///< The ASTConsumer down the chain, for passthrough. NULL if it's a SemaConsumer.
+ clang::SemaConsumer *m_passthrough_sema; ///< The SemaConsumer down the chain, for passthrough. NULL if it's an ASTConsumer.
+ Target &m_target; ///< The target, which contains the persistent variable store and the
+ clang::Sema *m_sema; ///< The Sema to use.
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ASTResultSynthesizer_h_
diff --git a/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp
new file mode 100644
index 000000000000..38a2b6b33a8a
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp
@@ -0,0 +1,221 @@
+//===-- ASTStructExtractor.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ASTStructExtractor.h"
+
+#include "stdlib.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Sema/Sema.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
+#include "lldb/Core/Log.h"
+
+using namespace llvm;
+using namespace clang;
+using namespace lldb_private;
+
+ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough,
+ const char *struct_name,
+ ClangFunctionCaller &function) :
+ m_ast_context (NULL),
+ m_passthrough (passthrough),
+ m_passthrough_sema (NULL),
+ m_sema (NULL),
+ m_action (NULL),
+ m_function (function),
+ m_struct_name (struct_name)
+{
+ if (!m_passthrough)
+ return;
+
+ m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
+}
+
+ASTStructExtractor::~ASTStructExtractor()
+{
+}
+
+void
+ASTStructExtractor::Initialize(ASTContext &Context)
+{
+ m_ast_context = &Context;
+
+ if (m_passthrough)
+ m_passthrough->Initialize(Context);
+}
+
+void
+ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F)
+{
+ if (!F->hasBody())
+ return;
+
+ Stmt *body_stmt = F->getBody();
+ CompoundStmt *body_compound_stmt = dyn_cast<CompoundStmt>(body_stmt);
+
+ if (!body_compound_stmt)
+ return; // do we have to handle this?
+
+ RecordDecl *struct_decl = NULL;
+
+ StringRef desired_name(m_struct_name.c_str());
+
+ for (CompoundStmt::const_body_iterator bi = body_compound_stmt->body_begin(), be = body_compound_stmt->body_end();
+ bi != be;
+ ++bi)
+ {
+ Stmt *curr_stmt = *bi;
+ DeclStmt *curr_decl_stmt = dyn_cast<DeclStmt>(curr_stmt);
+ if (!curr_decl_stmt)
+ continue;
+ DeclGroupRef decl_group = curr_decl_stmt->getDeclGroup();
+ for (Decl *candidate_decl : decl_group)
+ {
+ RecordDecl *candidate_record_decl = dyn_cast<RecordDecl>(candidate_decl);
+ if (!candidate_record_decl)
+ continue;
+ if (candidate_record_decl->getName() == desired_name)
+ {
+ struct_decl = candidate_record_decl;
+ break;
+ }
+ }
+ if (struct_decl)
+ break;
+ }
+
+ if (!struct_decl)
+ return;
+
+ const ASTRecordLayout* struct_layout(&m_ast_context->getASTRecordLayout (struct_decl));
+
+ if (!struct_layout)
+ return;
+
+ m_function.m_struct_size = struct_layout->getSize().getQuantity(); // TODO Store m_struct_size as CharUnits
+ m_function.m_return_offset = struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8;
+ m_function.m_return_size = struct_layout->getDataSize().getQuantity() - m_function.m_return_offset;
+
+ for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount();
+ field_index < num_fields;
+ ++field_index)
+ {
+ m_function.m_member_offsets.push_back(struct_layout->getFieldOffset(field_index) / 8);
+ }
+
+ m_function.m_struct_valid = true;
+}
+
+void
+ASTStructExtractor::ExtractFromTopLevelDecl(Decl* D)
+{
+ LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D);
+
+ if (linkage_spec_decl)
+ {
+ RecordDecl::decl_iterator decl_iterator;
+
+ for (decl_iterator = linkage_spec_decl->decls_begin();
+ decl_iterator != linkage_spec_decl->decls_end();
+ ++decl_iterator)
+ {
+ ExtractFromTopLevelDecl(*decl_iterator);
+ }
+ }
+
+ FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D);
+
+ if (m_ast_context &&
+ function_decl &&
+ !m_function.m_wrapper_function_name.compare(function_decl->getNameAsString().c_str()))
+ {
+ ExtractFromFunctionDecl(function_decl);
+ }
+}
+
+bool
+ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D)
+{
+ DeclGroupRef::iterator decl_iterator;
+
+ for (decl_iterator = D.begin();
+ decl_iterator != D.end();
+ ++decl_iterator)
+ {
+ Decl *decl = *decl_iterator;
+
+ ExtractFromTopLevelDecl(decl);
+ }
+
+ if (m_passthrough)
+ return m_passthrough->HandleTopLevelDecl(D);
+ return true;
+}
+
+void
+ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx)
+{
+ if (m_passthrough)
+ m_passthrough->HandleTranslationUnit(Ctx);
+}
+
+void
+ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D)
+{
+ if (m_passthrough)
+ m_passthrough->HandleTagDeclDefinition(D);
+}
+
+void
+ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D)
+{
+ if (m_passthrough)
+ m_passthrough->CompleteTentativeDefinition(D);
+}
+
+void
+ASTStructExtractor::HandleVTable(CXXRecordDecl *RD)
+{
+ if (m_passthrough)
+ m_passthrough->HandleVTable(RD);
+}
+
+void
+ASTStructExtractor::PrintStats()
+{
+ if (m_passthrough)
+ m_passthrough->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);
+}
+
+void
+ASTStructExtractor::ForgetSema()
+{
+ m_sema = NULL;
+ m_action = NULL;
+
+ if (m_passthrough_sema)
+ m_passthrough_sema->ForgetSema();
+}
diff --git a/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h
new file mode 100644
index 000000000000..2152cff911ff
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h
@@ -0,0 +1,158 @@
+//===-- ASTStructExtractor.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ASTStructExtractor_h_
+#define liblldb_ASTStructExtractor_h_
+
+#include "ClangExpressionVariable.h"
+#include "ClangFunctionCaller.h"
+
+#include "clang/Sema/SemaConsumer.h"
+#include "lldb/Core/ClangForward.h"
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+/// @class ASTStructExtractor ASTStructExtractor.h "lldb/Expression/ASTStructExtractor.h"
+/// @brief Extracts and describes the argument structure for a wrapped function.
+///
+/// This pass integrates with ClangFunctionCaller, which calls functions with custom
+/// sets of arguments. To avoid having to implement the full calling convention
+/// for the target's architecture, ClangFunctionCaller writes a simple wrapper
+/// function that takes a pointer to an argument structure that contains room
+/// for the address of the function to be called, the values of all its
+/// arguments, and room for the function's return value.
+///
+/// The definition of this struct is itself in the body of the wrapper function,
+/// so Clang does the structure layout itself. ASTStructExtractor reads through
+/// the AST for the wrapper function and finds the struct.
+//----------------------------------------------------------------------
+class ASTStructExtractor : public clang::SemaConsumer
+{
+public:
+ //----------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// @param[in] passthrough
+ /// Since the ASTs must typically go through to the Clang code generator
+ /// in order to produce LLVM IR, this SemaConsumer must allow them to
+ /// pass to the next step in the chain after processing. Passthrough is
+ /// the next ASTConsumer, or NULL if none is required.
+ ///
+ /// @param[in] struct_name
+ /// The name of the structure to extract from the wrapper function.
+ ///
+ /// @param[in] function
+ /// The caller object whose members should be populated with information
+ /// about the argument struct. ClangFunctionCaller friends ASTStructExtractor
+ /// for this purpose.
+ //----------------------------------------------------------------------
+ ASTStructExtractor(clang::ASTConsumer *passthrough,
+ const char *struct_name,
+ ClangFunctionCaller &function);
+
+ //----------------------------------------------------------------------
+ /// Destructor
+ //----------------------------------------------------------------------
+ ~ASTStructExtractor() override;
+
+ //----------------------------------------------------------------------
+ /// Link this consumer with a particular AST context
+ ///
+ /// @param[in] Context
+ /// This AST context will be used for types and identifiers, and also
+ /// forwarded to the passthrough consumer, if one exists.
+ //----------------------------------------------------------------------
+ void Initialize(clang::ASTContext &Context) override;
+
+ //----------------------------------------------------------------------
+ /// Examine a list of Decls to find the function $__lldb_expr and
+ /// transform its code
+ ///
+ /// @param[in] D
+ /// The list of Decls to search. These may contain LinkageSpecDecls,
+ /// which need to be searched recursively. That job falls to
+ /// TransformTopLevelDecl.
+ //----------------------------------------------------------------------
+ bool HandleTopLevelDecl(clang::DeclGroupRef D) override;
+
+ //----------------------------------------------------------------------
+ /// Passthrough stub
+ //----------------------------------------------------------------------
+ void HandleTranslationUnit(clang::ASTContext &Ctx) override;
+
+ //----------------------------------------------------------------------
+ /// Passthrough stub
+ //----------------------------------------------------------------------
+ void HandleTagDeclDefinition(clang::TagDecl *D) override;
+
+ //----------------------------------------------------------------------
+ /// Passthrough stub
+ //----------------------------------------------------------------------
+ void CompleteTentativeDefinition(clang::VarDecl *D) override;
+
+ //----------------------------------------------------------------------
+ /// Passthrough stub
+ //----------------------------------------------------------------------
+ void HandleVTable(clang::CXXRecordDecl *RD) override;
+
+ //----------------------------------------------------------------------
+ /// Passthrough stub
+ //----------------------------------------------------------------------
+ void PrintStats() override;
+
+ //----------------------------------------------------------------------
+ /// Set the Sema object to use when performing transforms, and pass it on
+ ///
+ /// @param[in] S
+ /// The Sema to use. Because Sema isn't externally visible, this class
+ /// casts it to an Action for actual use.
+ //----------------------------------------------------------------------
+ void InitializeSema(clang::Sema &S) override;
+
+ //----------------------------------------------------------------------
+ /// Reset the Sema to NULL now that transformations are done
+ //----------------------------------------------------------------------
+ void ForgetSema() override;
+
+private:
+ //----------------------------------------------------------------------
+ /// Hunt the given FunctionDecl for the argument struct and place
+ /// information about it into m_function
+ ///
+ /// @param[in] F
+ /// The FunctionDecl to hunt.
+ //----------------------------------------------------------------------
+ void
+ ExtractFromFunctionDecl(clang::FunctionDecl* F);
+
+ //----------------------------------------------------------------------
+ /// Hunt the given Decl for FunctionDecls named the same as the wrapper
+ /// function name, recursing as necessary through LinkageSpecDecls, and
+ /// calling ExtractFromFunctionDecl on anything that was found
+ ///
+ /// @param[in] D
+ /// The Decl to hunt.
+ //----------------------------------------------------------------------
+ void
+ ExtractFromTopLevelDecl(clang::Decl* D);
+
+ clang::ASTContext *m_ast_context; ///< The AST context to use for identifiers and types.
+ clang::ASTConsumer *m_passthrough; ///< The ASTConsumer down the chain, for passthrough. NULL if it's a SemaConsumer.
+ clang::SemaConsumer *m_passthrough_sema; ///< The SemaConsumer down the chain, 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.
+ std::string m_struct_name; ///< The name of the structure to extract.
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ASTStructExtractor_h_
diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
new file mode 100644
index 000000000000..d2ea4390560a
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
@@ -0,0 +1,2101 @@
+//===-- ClangASTSource.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangASTSource.h"
+
+#include "ASTDumper.h"
+#include "ClangModulesDeclVendor.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecordLayout.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/CompilerDeclContext.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/TaggedASTType.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Target.h"
+
+#include <vector>
+
+using namespace clang;
+using namespace lldb_private;
+
+//------------------------------------------------------------------
+// Scoped class that will remove an active lexical decl from the set
+// when it goes out of scope.
+//------------------------------------------------------------------
+namespace {
+ class ScopedLexicalDeclEraser
+ {
+ public:
+ ScopedLexicalDeclEraser(std::set<const clang::Decl *> &decls,
+ const clang::Decl *decl)
+ : m_active_lexical_decls(decls), m_decl(decl)
+ {
+ }
+
+ ~ScopedLexicalDeclEraser()
+ {
+ m_active_lexical_decls.erase(m_decl);
+ }
+
+ private:
+ std::set<const clang::Decl *> &m_active_lexical_decls;
+ const clang::Decl *m_decl;
+ };
+}
+
+ClangASTSource::~ClangASTSource()
+{
+ m_ast_importer_sp->ForgetDestination(m_ast_context);
+
+ // 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);
+
+ if (!scratch_clang_ast_context)
+ return;
+
+ 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->ForgetSource(scratch_ast_context, m_ast_context);
+}
+
+void
+ClangASTSource::StartTranslationUnit(ASTConsumer *Consumer)
+{
+ if (!m_ast_context)
+ return;
+
+ m_ast_context->getTranslationUnitDecl()->setHasExternalVisibleStorage();
+ m_ast_context->getTranslationUnitDecl()->setHasExternalLexicalStorage();
+}
+
+// The core lookup interface.
+bool
+ClangASTSource::FindExternalVisibleDeclsByName
+(
+ const DeclContext *decl_ctx,
+ DeclarationName clang_decl_name
+)
+{
+ if (!m_ast_context)
+ {
+ SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
+ return false;
+ }
+
+ if (GetImportInProgress())
+ {
+ SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
+ return false;
+ }
+
+ std::string decl_name (clang_decl_name.getAsString());
+
+// if (m_decl_map.DoingASTImport ())
+// return DeclContext::lookup_result();
+//
+ switch (clang_decl_name.getNameKind()) {
+ // Normal identifiers.
+ case DeclarationName::Identifier:
+ {
+ clang::IdentifierInfo *identifier_info = clang_decl_name.getAsIdentifierInfo();
+
+ if (!identifier_info ||
+ identifier_info->getBuiltinID() != 0)
+ {
+ SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
+ return false;
+ }
+ }
+ break;
+
+ // Operator names.
+ case DeclarationName::CXXOperatorName:
+ case DeclarationName::CXXLiteralOperatorName:
+ break;
+
+ // Using directives found in this context.
+ // Tell Sema we didn't find any or we'll end up getting asked a *lot*.
+ case DeclarationName::CXXUsingDirective:
+ SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
+ return false;
+
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ {
+ llvm::SmallVector<NamedDecl*, 1> method_decls;
+
+ NameSearchContext method_search_context (*this, method_decls, clang_decl_name, decl_ctx);
+
+ FindObjCMethodDecls(method_search_context);
+
+ SetExternalVisibleDeclsForName (decl_ctx, clang_decl_name, method_decls);
+ return (method_decls.size() > 0);
+ }
+ // These aren't possible in the global context.
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
+ return false;
+ }
+
+
+ if (!GetLookupsEnabled())
+ {
+ // Wait until we see a '$' at the start of a name before we start doing
+ // any lookups so we can avoid lookup up all of the builtin types.
+ if (!decl_name.empty() && decl_name[0] == '$')
+ {
+ SetLookupsEnabled (true);
+ }
+ else
+ {
+ SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
+ return false;
+ }
+ }
+
+ ConstString const_decl_name(decl_name.c_str());
+
+ const char *uniqued_const_decl_name = const_decl_name.GetCString();
+ if (m_active_lookups.find (uniqued_const_decl_name) != m_active_lookups.end())
+ {
+ // We are currently looking up this name...
+ SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name);
+ return false;
+ }
+ m_active_lookups.insert(uniqued_const_decl_name);
+// static uint32_t g_depth = 0;
+// ++g_depth;
+// printf("[%5u] FindExternalVisibleDeclsByName() \"%s\"\n", g_depth, uniqued_const_decl_name);
+ llvm::SmallVector<NamedDecl*, 4> name_decls;
+ NameSearchContext name_search_context(*this, name_decls, clang_decl_name, decl_ctx);
+ FindExternalVisibleDecls(name_search_context);
+ SetExternalVisibleDeclsForName (decl_ctx, clang_decl_name, name_decls);
+// --g_depth;
+ m_active_lookups.erase (uniqued_const_decl_name);
+ return (name_decls.size() != 0);
+}
+
+void
+ClangASTSource::CompleteType (TagDecl *tag_decl)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ static unsigned int invocation_id = 0;
+ unsigned int current_id = invocation_id++;
+
+ if (log)
+ {
+ log->Printf(" CompleteTagDecl[%u] on (ASTContext*)%p Completing (TagDecl*)%p named %s",
+ current_id, static_cast<void*>(m_ast_context),
+ static_cast<void*>(tag_decl),
+ tag_decl->getName().str().c_str());
+
+ log->Printf(" CTD[%u] Before:", current_id);
+ ASTDumper dumper((Decl*)tag_decl);
+ dumper.ToLog(log, " [CTD] ");
+ }
+
+ auto iter = m_active_lexical_decls.find(tag_decl);
+ if (iter != m_active_lexical_decls.end())
+ return;
+ m_active_lexical_decls.insert(tag_decl);
+ ScopedLexicalDeclEraser eraser(m_active_lexical_decls, tag_decl);
+
+ if (!m_ast_importer_sp->CompleteTagDecl (tag_decl))
+ {
+ // We couldn't complete the type. Maybe there's a definition
+ // somewhere else that can be completed.
+
+ if (log)
+ log->Printf(" CTD[%u] Type could not be completed in the module in which it was first found.", current_id);
+
+ bool found = false;
+
+ DeclContext *decl_ctx = tag_decl->getDeclContext();
+
+ if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(decl_ctx))
+ {
+ ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context);
+
+ if (log && log->GetVerbose())
+ log->Printf(" CTD[%u] Inspecting namespace map %p (%d entries)",
+ current_id, static_cast<void*>(namespace_map.get()),
+ static_cast<int>(namespace_map->size()));
+
+ if (!namespace_map)
+ return;
+
+ for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end();
+ i != e && !found;
+ ++i)
+ {
+ if (log)
+ log->Printf(" CTD[%u] Searching namespace %s in module %s",
+ current_id,
+ i->second.GetName().AsCString(),
+ i->first->GetFileSpec().GetFilename().GetCString());
+
+ TypeList types;
+
+ SymbolContext null_sc;
+ ConstString name(tag_decl->getName().str().c_str());
+
+ i->first->FindTypesInNamespace(null_sc, name, &i->second, UINT32_MAX, types);
+
+ for (uint32_t ti = 0, te = types.GetSize();
+ ti != te && !found;
+ ++ti)
+ {
+ lldb::TypeSP type = types.GetTypeAtIndex(ti);
+
+ if (!type)
+ continue;
+
+ CompilerType clang_type (type->GetFullCompilerType ());
+
+ if (!clang_type)
+ continue;
+
+ const TagType *tag_type = ClangASTContext::GetQualType(clang_type)->getAs<TagType>();
+
+ if (!tag_type)
+ continue;
+
+ TagDecl *candidate_tag_decl = const_cast<TagDecl*>(tag_type->getDecl());
+
+ if (m_ast_importer_sp->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl))
+ found = true;
+ }
+ }
+ }
+ else
+ {
+ TypeList types;
+
+ SymbolContext null_sc;
+ ConstString name(tag_decl->getName().str().c_str());
+ CompilerDeclContext namespace_decl;
+
+ const ModuleList &module_list = m_target->GetImages();
+
+ bool exact_match = false;
+ module_list.FindTypes (null_sc, name, exact_match, UINT32_MAX, types);
+
+ for (uint32_t ti = 0, te = types.GetSize();
+ ti != te && !found;
+ ++ti)
+ {
+ lldb::TypeSP type = types.GetTypeAtIndex(ti);
+
+ if (!type)
+ continue;
+
+ CompilerType clang_type (type->GetFullCompilerType ());
+
+ if (!clang_type)
+ continue;
+
+ const TagType *tag_type = ClangASTContext::GetQualType(clang_type)->getAs<TagType>();
+
+ if (!tag_type)
+ continue;
+
+ TagDecl *candidate_tag_decl = const_cast<TagDecl*>(tag_type->getDecl());
+
+ // We have found a type by basename and we need to make sure the decl contexts
+ // are the same before we can try to complete this type with another
+ if (!ClangASTContext::DeclsAreEquivalent (tag_decl, candidate_tag_decl))
+ continue;
+
+ if (m_ast_importer_sp->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl))
+ found = true;
+ }
+ }
+ }
+
+ if (log)
+ {
+ log->Printf(" [CTD] After:");
+ ASTDumper dumper((Decl*)tag_decl);
+ dumper.ToLog(log, " [CTD] ");
+ }
+}
+
+void
+ClangASTSource::CompleteType (clang::ObjCInterfaceDecl *interface_decl)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ {
+ log->Printf(" [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing an ObjCInterfaceDecl named %s",
+ static_cast<void*>(m_ast_context),
+ interface_decl->getName().str().c_str());
+ log->Printf(" [COID] Before:");
+ ASTDumper dumper((Decl*)interface_decl);
+ dumper.ToLog(log, " [COID] ");
+ }
+
+ Decl *original_decl = NULL;
+ ASTContext *original_ctx = NULL;
+
+ if (m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx))
+ {
+ if (ObjCInterfaceDecl *original_iface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl))
+ {
+ ObjCInterfaceDecl *complete_iface_decl = GetCompleteObjCInterface(original_iface_decl);
+
+ if (complete_iface_decl && (complete_iface_decl != original_iface_decl))
+ {
+ m_ast_importer_sp->SetDeclOrigin(interface_decl, original_iface_decl);
+ }
+ }
+ }
+
+ m_ast_importer_sp->CompleteObjCInterfaceDecl (interface_decl);
+
+ if (interface_decl->getSuperClass() &&
+ interface_decl->getSuperClass() != interface_decl)
+ CompleteType(interface_decl->getSuperClass());
+
+ if (log)
+ {
+ log->Printf(" [COID] After:");
+ ASTDumper dumper((Decl*)interface_decl);
+ dumper.ToLog(log, " [COID] ");
+ }
+}
+
+clang::ObjCInterfaceDecl *
+ClangASTSource::GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_decl)
+{
+ lldb::ProcessSP process(m_target->GetProcessSP());
+
+ if (!process)
+ return NULL;
+
+ ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime());
+
+ if (!language_runtime)
+ return NULL;
+
+ ConstString class_name(interface_decl->getNameAsString().c_str());
+
+ lldb::TypeSP complete_type_sp(language_runtime->LookupInCompleteClassCache(class_name));
+
+ if (!complete_type_sp)
+ return NULL;
+
+ TypeFromUser complete_type = TypeFromUser(complete_type_sp->GetFullCompilerType ());
+ lldb::opaque_compiler_type_t complete_opaque_type = complete_type.GetOpaqueQualType();
+
+ if (!complete_opaque_type)
+ return NULL;
+
+ const clang::Type *complete_clang_type = QualType::getFromOpaquePtr(complete_opaque_type).getTypePtr();
+ const ObjCInterfaceType *complete_interface_type = dyn_cast<ObjCInterfaceType>(complete_clang_type);
+
+ if (!complete_interface_type)
+ return NULL;
+
+ ObjCInterfaceDecl *complete_iface_decl(complete_interface_type->getDecl());
+
+ return complete_iface_decl;
+}
+
+void
+ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context,
+ llvm::function_ref<bool(Decl::Kind)> predicate,
+ llvm::SmallVectorImpl<Decl*> &decls)
+{
+ ClangASTMetrics::RegisterLexicalQuery();
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ const Decl *context_decl = dyn_cast<Decl>(decl_context);
+
+ if (!context_decl)
+ return;
+
+ auto iter = m_active_lexical_decls.find(context_decl);
+ if (iter != m_active_lexical_decls.end())
+ return;
+ m_active_lexical_decls.insert(context_decl);
+ ScopedLexicalDeclEraser eraser(m_active_lexical_decls, context_decl);
+
+ static unsigned int invocation_id = 0;
+ unsigned int current_id = invocation_id++;
+
+ if (log)
+ {
+ if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl))
+ log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in '%s' (%sDecl*)%p",
+ current_id, static_cast<void*>(m_ast_context),
+ context_named_decl->getNameAsString().c_str(),
+ context_decl->getDeclKindName(),
+ static_cast<const void*>(context_decl));
+ else if(context_decl)
+ log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in (%sDecl*)%p",
+ current_id, static_cast<void*>(m_ast_context),
+ context_decl->getDeclKindName(),
+ static_cast<const void*>(context_decl));
+ else
+ log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in a NULL context",
+ current_id, static_cast<const void*>(m_ast_context));
+ }
+
+ Decl *original_decl = NULL;
+ ASTContext *original_ctx = NULL;
+
+ if (!m_ast_importer_sp->ResolveDeclOrigin(context_decl, &original_decl, &original_ctx))
+ return;
+
+ if (log)
+ {
+ log->Printf(" 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, " ");
+ }
+
+ if (ObjCInterfaceDecl *original_iface_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();
+
+ m_ast_importer_sp->SetDeclOrigin(context_decl, original_iface_decl);
+ }
+ }
+
+ 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);
+
+ if (!original_decl_context)
+ return;
+
+ for (TagDecl::decl_iterator iter = original_decl_context->decls_begin();
+ iter != original_decl_context->decls_end();
+ ++iter)
+ {
+ Decl *decl = *iter;
+
+ if (predicate(decl->getKind()))
+ {
+ if (log)
+ {
+ ASTDumper ast_dumper(decl);
+ if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context_decl))
+ log->Printf(" 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());
+ else
+ log->Printf(" FELD[%d] Adding lexical %sDecl %s", current_id, decl->getDeclKindName(), ast_dumper.GetCString());
+ }
+
+ Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, original_ctx, decl);
+
+ if (!copied_decl)
+ continue;
+
+ if (FieldDecl *copied_field = dyn_cast<FieldDecl>(copied_decl))
+ {
+ QualType copied_field_type = copied_field->getType();
+
+ m_ast_importer_sp->RequireCompleteType(copied_field_type);
+ }
+
+ DeclContext *decl_context_non_const = const_cast<DeclContext *>(decl_context);
+
+ if (copied_decl->getDeclContext() != decl_context)
+ {
+ if (copied_decl->getDeclContext()->containsDecl(copied_decl))
+ copied_decl->getDeclContext()->removeDecl(copied_decl);
+ copied_decl->setDeclContext(decl_context_non_const);
+ }
+
+ if (!decl_context_non_const->containsDecl(copied_decl))
+ decl_context_non_const->addDeclInternal(copied_decl);
+ }
+ }
+
+ return;
+}
+
+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));
+
+ static unsigned int invocation_id = 0;
+ unsigned int current_id = invocation_id++;
+
+ if (log)
+ {
+ if (!context.m_decl_context)
+ log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a NULL DeclContext",
+ current_id, static_cast<void*>(m_ast_context),
+ name.GetCString());
+ else if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context.m_decl_context))
+ log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in '%s'",
+ current_id, static_cast<void*>(m_ast_context),
+ name.GetCString(),
+ context_named_decl->getNameAsString().c_str());
+ else
+ log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a '%s'",
+ current_id, static_cast<void*>(m_ast_context),
+ name.GetCString(),
+ context.m_decl_context->getDeclKindName());
+ }
+
+ context.m_namespace_map.reset(new ClangASTImporter::NamespaceMap);
+
+ if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(context.m_decl_context))
+ {
+ ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context);
+
+ if (log && log->GetVerbose())
+ log->Printf(" CAS::FEVD[%u] Inspecting namespace map %p (%d entries)",
+ current_id, static_cast<void*>(namespace_map.get()),
+ static_cast<int>(namespace_map->size()));
+
+ if (!namespace_map)
+ return;
+
+ for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end();
+ i != e;
+ ++i)
+ {
+ if (log)
+ log->Printf(" CAS::FEVD[%u] Searching namespace %s in module %s",
+ current_id,
+ i->second.GetName().AsCString(),
+ i->first->GetFileSpec().GetFilename().GetCString());
+
+ FindExternalVisibleDecls(context,
+ i->first,
+ i->second,
+ current_id);
+ }
+ }
+ 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
+ return;
+ }
+ else
+ {
+ CompilerDeclContext namespace_decl;
+
+ if (log)
+ log->Printf(" CAS::FEVD[%u] Searching the root namespace", current_id);
+
+ FindExternalVisibleDecls(context,
+ lldb::ModuleSP(),
+ namespace_decl,
+ current_id);
+ }
+
+ if (!context.m_namespace_map->empty())
+ {
+ if (log && log->GetVerbose())
+ log->Printf(" CAS::FEVD[%u] Registering namespace map %p (%d entries)",
+ current_id,
+ static_cast<void*>(context.m_namespace_map.get()),
+ static_cast<int>(context.m_namespace_map->size()));
+
+ NamespaceDecl *clang_namespace_decl = AddNamespace(context, context.m_namespace_map);
+
+ if (clang_namespace_decl)
+ clang_namespace_decl->setHasExternalVisibleStorage();
+ }
+}
+
+void
+ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context,
+ lldb::ModuleSP module_sp,
+ CompilerDeclContext &namespace_decl,
+ unsigned int current_id)
+{
+ assert (m_ast_context);
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ SymbolContextList sc_list;
+
+ const ConstString name(context.m_decl_name.getAsString().c_str());
+
+ const char *name_unique_cstr = name.GetCString();
+
+ static ConstString id_name("id");
+ static ConstString Class_name("Class");
+
+ if (name == id_name || name == Class_name)
+ return;
+
+ if (name_unique_cstr == NULL)
+ return;
+
+ // The ClangASTSource is not responsible for finding $-names.
+ if (name_unique_cstr[0] == '$')
+ return;
+
+ if (module_sp && namespace_decl)
+ {
+ CompilerDeclContext found_namespace_decl;
+
+ SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor();
+
+ if (symbol_vendor)
+ {
+ SymbolContext null_sc;
+
+ found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &namespace_decl);
+
+ if (found_namespace_decl)
+ {
+ context.m_namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>(module_sp, found_namespace_decl));
+
+ if (log)
+ log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s",
+ current_id,
+ name.GetCString(),
+ module_sp->GetFileSpec().GetFilename().GetCString());
+ }
+ }
+ }
+ else
+ {
+ const ModuleList &target_images = m_target->GetImages();
+ Mutex::Locker modules_locker (target_images.GetMutex());
+
+ for (size_t i = 0, e = target_images.GetSize(); i < e; ++i)
+ {
+ lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i);
+
+ if (!image)
+ continue;
+
+ CompilerDeclContext found_namespace_decl;
+
+ SymbolVendor *symbol_vendor = image->GetSymbolVendor();
+
+ if (!symbol_vendor)
+ continue;
+
+ SymbolContext null_sc;
+
+ found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &namespace_decl);
+
+ if (found_namespace_decl)
+ {
+ context.m_namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>(image, found_namespace_decl));
+
+ if (log)
+ log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s",
+ current_id,
+ name.GetCString(),
+ image->GetFileSpec().GetFilename().GetCString());
+ }
+ }
+ }
+
+ do
+ {
+ TypeList types;
+ SymbolContext null_sc;
+ const bool exact_match = false;
+
+ if (module_sp && namespace_decl)
+ module_sp->FindTypesInNamespace(null_sc, name, &namespace_decl, 1, types);
+ else
+ m_target->GetImages().FindTypes(null_sc, name, exact_match, 1, types);
+
+ bool found_a_type = false;
+
+ if (size_t num_types = types.GetSize())
+ {
+ for (size_t ti = 0; ti < num_types; ++ti)
+ {
+ lldb::TypeSP type_sp = types.GetTypeAtIndex(ti);
+
+ if (log)
+ {
+ const char *name_string = type_sp->GetName().GetCString();
+
+ log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\": %s",
+ current_id,
+ name.GetCString(),
+ (name_string ? name_string : "<anonymous>"));
+ }
+
+ CompilerType full_type = type_sp->GetFullCompilerType();
+
+ CompilerType copied_clang_type (GuardedCopyType(full_type));
+
+ if (!copied_clang_type)
+ {
+ if (log)
+ log->Printf(" CAS::FEVD[%u] - Couldn't export a type",
+ current_id);
+
+ continue;
+ }
+
+ context.AddTypeDecl(copied_clang_type);
+
+ found_a_type = true;
+ break;
+ }
+ }
+
+ if (!found_a_type)
+ {
+ // Try the modules next.
+
+ do
+ {
+ if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor())
+ {
+ bool append = false;
+ uint32_t max_matches = 1;
+ std::vector <clang::NamedDecl *> decls;
+
+ if (!modules_decl_vendor->FindDecls(name,
+ append,
+ max_matches,
+ decls))
+ break;
+
+ if (log)
+ {
+ log->Printf(" CAS::FEVD[%u] Matching entity found for \"%s\" in the modules",
+ current_id,
+ name.GetCString());
+ }
+
+ clang::NamedDecl *const decl_from_modules = decls[0];
+
+ if (llvm::isa<clang::TypeDecl>(decl_from_modules) ||
+ llvm::isa<clang::ObjCContainerDecl>(decl_from_modules) ||
+ llvm::isa<clang::EnumConstantDecl>(decl_from_modules))
+ {
+ clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules);
+ clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr;
+
+ if (!copied_named_decl)
+ {
+ if (log)
+ log->Printf(" CAS::FEVD[%u] - Couldn't export a type from the modules",
+ current_id);
+
+ break;
+ }
+
+ context.AddNamedDecl(copied_named_decl);
+
+ found_a_type = true;
+ }
+ }
+ } while (0);
+ }
+
+ if (!found_a_type)
+ {
+ do
+ {
+ // Couldn't find any types elsewhere. Try the Objective-C runtime if one exists.
+
+ lldb::ProcessSP process(m_target->GetProcessSP());
+
+ if (!process)
+ break;
+
+ ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime());
+
+ if (!language_runtime)
+ break;
+
+ DeclVendor *decl_vendor = language_runtime->GetDeclVendor();
+
+ if (!decl_vendor)
+ break;
+
+ bool append = false;
+ uint32_t max_matches = 1;
+ std::vector <clang::NamedDecl *> decls;
+
+ if (!decl_vendor->FindDecls(name,
+ append,
+ max_matches,
+ decls))
+ break;
+
+ if (log)
+ {
+ log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\" in the runtime",
+ current_id,
+ name.GetCString());
+ }
+
+ clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decls[0]->getASTContext(), decls[0]);
+ clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast<clang::NamedDecl>(copied_decl) : nullptr;
+
+ if (!copied_named_decl)
+ {
+ if (log)
+ log->Printf(" CAS::FEVD[%u] - Couldn't export a type from the runtime",
+ current_id);
+
+ break;
+ }
+
+ context.AddNamedDecl(copied_named_decl);
+ }
+ while(0);
+ }
+
+ } while(0);
+}
+
+template <class D> class TaggedASTDecl {
+public:
+ TaggedASTDecl() : decl(NULL) { }
+ TaggedASTDecl(D *_decl) : decl(_decl) { }
+ bool IsValid() const { return (decl != NULL); }
+ bool IsInvalid() const { return !IsValid(); }
+ D *operator->() const { return decl; }
+ D *decl;
+};
+
+template <class D2, template <class D> class TD, class D1>
+TD<D2>
+DynCast(TD<D1> source)
+{
+ return TD<D2> (dyn_cast<D2>(source.decl));
+}
+
+template <class D = Decl> class DeclFromParser;
+template <class D = Decl> class DeclFromUser;
+
+template <class D> class DeclFromParser : public TaggedASTDecl<D> {
+public:
+ DeclFromParser() : TaggedASTDecl<D>() { }
+ DeclFromParser(D *_decl) : TaggedASTDecl<D>(_decl) { }
+
+ DeclFromUser<D> GetOrigin(ClangASTImporter *importer);
+};
+
+template <class D> class DeclFromUser : public TaggedASTDecl<D> {
+public:
+ DeclFromUser() : TaggedASTDecl<D>() { }
+ DeclFromUser(D *_decl) : TaggedASTDecl<D>(_decl) { }
+
+ DeclFromParser<D> Import(ClangASTImporter *importer, ASTContext &dest_ctx);
+};
+
+template <class D>
+DeclFromUser<D>
+DeclFromParser<D>::GetOrigin(ClangASTImporter *importer)
+{
+ DeclFromUser <> origin_decl;
+ importer->ResolveDeclOrigin(this->decl, &origin_decl.decl, NULL);
+ if (origin_decl.IsInvalid())
+ return DeclFromUser<D>();
+ return DeclFromUser<D>(dyn_cast<D>(origin_decl.decl));
+}
+
+template <class D>
+DeclFromParser<D>
+DeclFromUser<D>::Import(ClangASTImporter *importer, ASTContext &dest_ctx)
+{
+ DeclFromParser <> parser_generic_decl(importer->CopyDecl(&dest_ctx, &this->decl->getASTContext(), this->decl));
+ if (parser_generic_decl.IsInvalid())
+ return DeclFromParser<D>();
+ return DeclFromParser<D>(dyn_cast<D>(parser_generic_decl.decl));
+}
+
+static bool
+FindObjCMethodDeclsWithOrigin (unsigned int current_id,
+ NameSearchContext &context,
+ ObjCInterfaceDecl *original_interface_decl,
+ clang::ASTContext *ast_context,
+ ClangASTImporter *ast_importer,
+ const char *log_info)
+{
+ const DeclarationName &decl_name(context.m_decl_name);
+ clang::ASTContext *original_ctx = &original_interface_decl->getASTContext();
+
+ Selector original_selector;
+
+ if (decl_name.isObjCZeroArgSelector())
+ {
+ IdentifierInfo *ident = &original_ctx->Idents.get(decl_name.getAsString());
+ original_selector = original_ctx->Selectors.getSelector(0, &ident);
+ }
+ else if (decl_name.isObjCOneArgSelector())
+ {
+ const std::string &decl_name_string = decl_name.getAsString();
+ std::string decl_name_string_without_colon(decl_name_string.c_str(), decl_name_string.length() - 1);
+ IdentifierInfo *ident = &original_ctx->Idents.get(decl_name_string_without_colon.c_str());
+ original_selector = original_ctx->Selectors.getSelector(1, &ident);
+ }
+ else
+ {
+ SmallVector<IdentifierInfo *, 4> idents;
+
+ clang::Selector sel = decl_name.getObjCSelector();
+
+ unsigned num_args = sel.getNumArgs();
+
+ for (unsigned i = 0;
+ i != num_args;
+ ++i)
+ {
+ idents.push_back(&original_ctx->Idents.get(sel.getNameForSlot(i)));
+ }
+
+ original_selector = original_ctx->Selectors.getSelector(num_args, idents.data());
+ }
+
+ DeclarationName original_decl_name(original_selector);
+
+ llvm::SmallVector<NamedDecl *, 1> methods;
+
+ ClangASTContext::GetCompleteDecl(original_ctx, original_interface_decl);
+
+ if (ObjCMethodDecl *instance_method_decl = original_interface_decl->lookupInstanceMethod(original_selector))
+ {
+ methods.push_back(instance_method_decl);
+ }
+ else if (ObjCMethodDecl *class_method_decl = original_interface_decl->lookupClassMethod(original_selector))
+ {
+ methods.push_back(class_method_decl);
+ }
+
+ if (methods.empty())
+ {
+ return false;
+ }
+
+ for (NamedDecl *named_decl : methods)
+ {
+ if (!named_decl)
+ continue;
+
+ ObjCMethodDecl *result_method = dyn_cast<ObjCMethodDecl>(named_decl);
+
+ if (!result_method)
+ continue;
+
+ Decl *copied_decl = ast_importer->CopyDecl(ast_context, &result_method->getASTContext(), result_method);
+
+ if (!copied_decl)
+ continue;
+
+ ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl);
+
+ if (!copied_method_decl)
+ continue;
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ {
+ ASTDumper dumper((Decl*)copied_method_decl);
+ log->Printf(" CAS::FOMD[%d] found (%s) %s", current_id, log_info, dumper.GetCString());
+ }
+
+ context.AddNamedDecl(copied_method_decl);
+ }
+
+ return true;
+}
+
+void
+ClangASTSource::FindObjCMethodDecls (NameSearchContext &context)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ static unsigned int invocation_id = 0;
+ unsigned int current_id = invocation_id++;
+
+ const DeclarationName &decl_name(context.m_decl_name);
+ const DeclContext *decl_ctx(context.m_decl_context);
+
+ const ObjCInterfaceDecl *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl_ctx);
+
+ if (!interface_decl)
+ return;
+
+ do
+ {
+ Decl *original_decl = NULL;
+ ASTContext *original_ctx = NULL;
+
+ m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx);
+
+ if (!original_decl)
+ break;
+
+ ObjCInterfaceDecl *original_interface_decl = dyn_cast<ObjCInterfaceDecl>(original_decl);
+
+ if (FindObjCMethodDeclsWithOrigin(current_id,
+ context,
+ original_interface_decl,
+ m_ast_context,
+ m_ast_importer_sp.get(),
+ "at origin"))
+ return; // found it, no need to look any further
+ } while (0);
+
+ StreamString ss;
+
+ if (decl_name.isObjCZeroArgSelector())
+ {
+ ss.Printf("%s", decl_name.getAsString().c_str());
+ }
+ else if (decl_name.isObjCOneArgSelector())
+ {
+ ss.Printf("%s", decl_name.getAsString().c_str());
+ }
+ else
+ {
+ clang::Selector sel = decl_name.getObjCSelector();
+
+ for (unsigned i = 0, e = sel.getNumArgs();
+ i != e;
+ ++i)
+ {
+ llvm::StringRef r = sel.getNameForSlot(i);
+ ss.Printf("%s:", r.str().c_str());
+ }
+ }
+ ss.Flush();
+
+ if (strstr(ss.GetData(), "$__lldb"))
+ return; // we don't need any results
+
+ ConstString selector_name(ss.GetData());
+
+ if (log)
+ log->Printf("ClangASTSource::FindObjCMethodDecls[%d] on (ASTContext*)%p for selector [%s %s]",
+ current_id, static_cast<void*>(m_ast_context),
+ interface_decl->getNameAsString().c_str(),
+ selector_name.AsCString());
+ SymbolContextList sc_list;
+
+ const bool include_symbols = false;
+ const bool include_inlines = false;
+ const bool append = false;
+
+ std::string interface_name = interface_decl->getNameAsString();
+
+ do
+ {
+ StreamString ms;
+ ms.Printf("-[%s %s]", interface_name.c_str(), selector_name.AsCString());
+ ms.Flush();
+ ConstString instance_method_name(ms.GetData());
+
+ m_target->GetImages().FindFunctions(instance_method_name, lldb::eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list);
+
+ if (sc_list.GetSize())
+ break;
+
+ ms.Clear();
+ ms.Printf("+[%s %s]", interface_name.c_str(), selector_name.AsCString());
+ ms.Flush();
+ ConstString class_method_name(ms.GetData());
+
+ m_target->GetImages().FindFunctions(class_method_name, lldb::eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list);
+
+ if (sc_list.GetSize())
+ break;
+
+ // Fall back and check for methods in categories. If we find methods this way, we need to check that they're actually in
+ // categories on the desired class.
+
+ SymbolContextList candidate_sc_list;
+
+ m_target->GetImages().FindFunctions(selector_name, lldb::eFunctionNameTypeSelector, include_symbols, include_inlines, append, candidate_sc_list);
+
+ for (uint32_t ci = 0, ce = candidate_sc_list.GetSize();
+ ci != ce;
+ ++ci)
+ {
+ SymbolContext candidate_sc;
+
+ if (!candidate_sc_list.GetContextAtIndex(ci, candidate_sc))
+ continue;
+
+ if (!candidate_sc.function)
+ continue;
+
+ const char *candidate_name = candidate_sc.function->GetName().AsCString();
+
+ const char *cursor = candidate_name;
+
+ if (*cursor != '+' && *cursor != '-')
+ continue;
+
+ ++cursor;
+
+ if (*cursor != '[')
+ continue;
+
+ ++cursor;
+
+ size_t interface_len = interface_name.length();
+
+ if (strncmp(cursor, interface_name.c_str(), interface_len))
+ continue;
+
+ cursor += interface_len;
+
+ if (*cursor == ' ' || *cursor == '(')
+ sc_list.Append(candidate_sc);
+ }
+ }
+ while (0);
+
+ if (sc_list.GetSize())
+ {
+ // We found a good function symbol. Use that.
+
+ for (uint32_t i = 0, e = sc_list.GetSize();
+ i != e;
+ ++i)
+ {
+ SymbolContext sc;
+
+ if (!sc_list.GetContextAtIndex(i, sc))
+ continue;
+
+ if (!sc.function)
+ continue;
+
+ CompilerDeclContext function_decl_ctx = sc.function->GetDeclContext();
+ if (!function_decl_ctx)
+ continue;
+
+ ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx);
+
+ if (!method_decl)
+ continue;
+
+ ObjCInterfaceDecl *found_interface_decl = method_decl->getClassInterface();
+
+ if (!found_interface_decl)
+ continue;
+
+ if (found_interface_decl->getName() == interface_decl->getName())
+ {
+ Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &method_decl->getASTContext(), method_decl);
+
+ if (!copied_decl)
+ continue;
+
+ ObjCMethodDecl *copied_method_decl = dyn_cast<ObjCMethodDecl>(copied_decl);
+
+ if (!copied_method_decl)
+ continue;
+
+ if (log)
+ {
+ ASTDumper dumper((Decl*)copied_method_decl);
+ log->Printf(" CAS::FOMD[%d] found (in symbols) %s", current_id, dumper.GetCString());
+ }
+
+ context.AddNamedDecl(copied_method_decl);
+ }
+ }
+
+ return;
+ }
+
+ // Try the debug information.
+
+ do
+ {
+ ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface(const_cast<ObjCInterfaceDecl*>(interface_decl));
+
+ if (!complete_interface_decl)
+ break;
+
+ // We found the complete interface. The runtime never needs to be queried in this scenario.
+
+ DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl(complete_interface_decl);
+
+ if (complete_interface_decl == interface_decl)
+ break; // already checked this one
+
+ if (log)
+ log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
+ current_id, static_cast<void*>(complete_interface_decl),
+ static_cast<void*>(&complete_iface_decl->getASTContext()));
+
+ FindObjCMethodDeclsWithOrigin(current_id,
+ context,
+ complete_interface_decl,
+ m_ast_context,
+ m_ast_importer_sp.get(),
+ "in debug info");
+
+ return;
+ }
+ while (0);
+
+ do
+ {
+ // Check the modules only if the debug information didn't have a complete interface.
+
+ if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor())
+ {
+ ConstString interface_name(interface_decl->getNameAsString().c_str());
+ bool append = false;
+ uint32_t max_matches = 1;
+ std::vector <clang::NamedDecl *> decls;
+
+ if (!modules_decl_vendor->FindDecls(interface_name,
+ append,
+ max_matches,
+ decls))
+ break;
+
+ ObjCInterfaceDecl *interface_decl_from_modules = dyn_cast<ObjCInterfaceDecl>(decls[0]);
+
+ if (!interface_decl_from_modules)
+ break;
+
+ if (FindObjCMethodDeclsWithOrigin(current_id,
+ context,
+ interface_decl_from_modules,
+ m_ast_context,
+ m_ast_importer_sp.get(),
+ "in modules"))
+ return;
+ }
+ }
+ while (0);
+
+ do
+ {
+ // Check the runtime only if the debug information didn't have a complete interface and the modules don't get us anywhere.
+
+ lldb::ProcessSP process(m_target->GetProcessSP());
+
+ if (!process)
+ break;
+
+ ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime());
+
+ if (!language_runtime)
+ break;
+
+ DeclVendor *decl_vendor = language_runtime->GetDeclVendor();
+
+ if (!decl_vendor)
+ break;
+
+ ConstString interface_name(interface_decl->getNameAsString().c_str());
+ bool append = false;
+ uint32_t max_matches = 1;
+ std::vector <clang::NamedDecl *> decls;
+
+ if (!decl_vendor->FindDecls(interface_name,
+ append,
+ max_matches,
+ decls))
+ break;
+
+ ObjCInterfaceDecl *runtime_interface_decl = dyn_cast<ObjCInterfaceDecl>(decls[0]);
+
+ if (!runtime_interface_decl)
+ break;
+
+ FindObjCMethodDeclsWithOrigin(current_id,
+ context,
+ runtime_interface_decl,
+ m_ast_context,
+ m_ast_importer_sp.get(),
+ "in runtime");
+ }
+ while(0);
+}
+
+static bool
+FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id,
+ NameSearchContext &context,
+ clang::ASTContext &ast_context,
+ ClangASTImporter *ast_importer,
+ DeclFromUser<const ObjCInterfaceDecl> &origin_iface_decl)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (origin_iface_decl.IsInvalid())
+ return false;
+
+ std::string name_str = context.m_decl_name.getAsString();
+ StringRef name(name_str.c_str());
+ IdentifierInfo &name_identifier(origin_iface_decl->getASTContext().Idents.get(name));
+
+ DeclFromUser<ObjCPropertyDecl> origin_property_decl(origin_iface_decl->FindPropertyDeclaration(&name_identifier));
+
+ bool found = false;
+
+ if (origin_property_decl.IsValid())
+ {
+ DeclFromParser<ObjCPropertyDecl> parser_property_decl(origin_property_decl.Import(ast_importer, ast_context));
+ if (parser_property_decl.IsValid())
+ {
+ if (log)
+ {
+ ASTDumper dumper((Decl*)parser_property_decl.decl);
+ log->Printf(" CAS::FOPD[%d] found %s", current_id, dumper.GetCString());
+ }
+
+ context.AddNamedDecl(parser_property_decl.decl);
+ found = true;
+ }
+ }
+
+ DeclFromUser<ObjCIvarDecl> origin_ivar_decl(origin_iface_decl->getIvarDecl(&name_identifier));
+
+ if (origin_ivar_decl.IsValid())
+ {
+ DeclFromParser<ObjCIvarDecl> parser_ivar_decl(origin_ivar_decl.Import(ast_importer, ast_context));
+ if (parser_ivar_decl.IsValid())
+ {
+ if (log)
+ {
+ ASTDumper dumper((Decl*)parser_ivar_decl.decl);
+ log->Printf(" CAS::FOPD[%d] found %s", current_id, dumper.GetCString());
+ }
+
+ context.AddNamedDecl(parser_ivar_decl.decl);
+ found = true;
+ }
+ }
+
+ return found;
+}
+
+void
+ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ static unsigned int invocation_id = 0;
+ unsigned int current_id = invocation_id++;
+
+ DeclFromParser<const ObjCInterfaceDecl> parser_iface_decl(cast<ObjCInterfaceDecl>(context.m_decl_context));
+ DeclFromUser<const ObjCInterfaceDecl> origin_iface_decl(parser_iface_decl.GetOrigin(m_ast_importer_sp.get()));
+
+ ConstString class_name(parser_iface_decl->getNameAsString().c_str());
+
+ if (log)
+ log->Printf("ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on (ASTContext*)%p for '%s.%s'",
+ current_id, static_cast<void*>(m_ast_context),
+ parser_iface_decl->getNameAsString().c_str(),
+ context.m_decl_name.getAsString().c_str());
+
+ if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
+ context,
+ *m_ast_context,
+ m_ast_importer_sp.get(),
+ origin_iface_decl))
+ return;
+
+ if (log)
+ log->Printf("CAS::FOPD[%d] couldn't find the property on origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p, searching elsewhere...",
+ current_id, static_cast<const void*>(origin_iface_decl.decl),
+ static_cast<void*>(&origin_iface_decl->getASTContext()));
+
+ SymbolContext null_sc;
+ TypeList type_list;
+
+ do
+ {
+ ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface(const_cast<ObjCInterfaceDecl*>(parser_iface_decl.decl));
+
+ if (!complete_interface_decl)
+ break;
+
+ // We found the complete interface. The runtime never needs to be queried in this scenario.
+
+ DeclFromUser<const ObjCInterfaceDecl> complete_iface_decl(complete_interface_decl);
+
+ if (complete_iface_decl.decl == origin_iface_decl.decl)
+ break; // already checked this one
+
+ if (log)
+ log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
+ current_id,
+ static_cast<const void*>(complete_iface_decl.decl),
+ static_cast<void*>(&complete_iface_decl->getASTContext()));
+
+ FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
+ context,
+ *m_ast_context,
+ m_ast_importer_sp.get(),
+ complete_iface_decl);
+
+ return;
+ }
+ while(0);
+
+ do
+ {
+ // Check the modules only if the debug information didn't have a complete interface.
+
+ ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor();
+
+ if (!modules_decl_vendor)
+ break;
+
+ bool append = false;
+ uint32_t max_matches = 1;
+ std::vector <clang::NamedDecl *> decls;
+
+ if (!modules_decl_vendor->FindDecls(class_name,
+ append,
+ max_matches,
+ decls))
+ break;
+
+ DeclFromUser<const ObjCInterfaceDecl> interface_decl_from_modules(dyn_cast<ObjCInterfaceDecl>(decls[0]));
+
+ if (!interface_decl_from_modules.IsValid())
+ break;
+
+ if (log)
+ log->Printf("CAS::FOPD[%d] trying module (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
+ current_id,
+ static_cast<const void*>(interface_decl_from_modules.decl),
+ static_cast<void*>(&interface_decl_from_modules->getASTContext()));
+
+ if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
+ context,
+ *m_ast_context,
+ m_ast_importer_sp.get(),
+ interface_decl_from_modules))
+ return;
+ }
+ while(0);
+
+ do
+ {
+ // Check the runtime only if the debug information didn't have a complete interface
+ // and nothing was in the modules.
+
+ lldb::ProcessSP process(m_target->GetProcessSP());
+
+ if (!process)
+ return;
+
+ ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime());
+
+ if (!language_runtime)
+ return;
+
+ DeclVendor *decl_vendor = language_runtime->GetDeclVendor();
+
+ if (!decl_vendor)
+ break;
+
+ bool append = false;
+ uint32_t max_matches = 1;
+ std::vector <clang::NamedDecl *> decls;
+
+ if (!decl_vendor->FindDecls(class_name,
+ append,
+ max_matches,
+ decls))
+ break;
+
+ DeclFromUser<const ObjCInterfaceDecl> interface_decl_from_runtime(dyn_cast<ObjCInterfaceDecl>(decls[0]));
+
+ if (!interface_decl_from_runtime.IsValid())
+ break;
+
+ if (log)
+ log->Printf("CAS::FOPD[%d] trying runtime (ObjCInterfaceDecl*)%p/(ASTContext*)%p...",
+ current_id,
+ static_cast<const void*>(interface_decl_from_runtime.decl),
+ static_cast<void*>(&interface_decl_from_runtime->getASTContext()));
+
+ if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id,
+ context,
+ *m_ast_context,
+ m_ast_importer_sp.get(),
+ interface_decl_from_runtime))
+ return;
+ }
+ while(0);
+}
+
+typedef llvm::DenseMap<const FieldDecl *, uint64_t> FieldOffsetMap;
+typedef llvm::DenseMap<const CXXRecordDecl *, CharUnits> BaseOffsetMap;
+
+template <class D, class O>
+static bool
+ImportOffsetMap(llvm::DenseMap<const D *, O> &destination_map, llvm::DenseMap<const D *, O> &source_map,
+ ClangASTImporter *importer, ASTContext &dest_ctx)
+{
+ // When importing fields into a new record, clang has a hard requirement that
+ // fields be imported in field offset order. Since they are stored in a DenseMap
+ // with a pointer as the key type, this means we cannot simply iterate over the
+ // map, as the order will be non-deterministic. Instead we have to sort by the offset
+ // and then insert in sorted order.
+ typedef llvm::DenseMap<const D *, O> MapType;
+ typedef typename MapType::value_type PairType;
+ std::vector<PairType> sorted_items;
+ sorted_items.reserve(source_map.size());
+ sorted_items.assign(source_map.begin(), source_map.end());
+ std::sort(sorted_items.begin(), sorted_items.end(),
+ [](const PairType &lhs, const PairType &rhs)
+ {
+ return lhs.second < rhs.second;
+ });
+
+ for (const auto &item : sorted_items)
+ {
+ DeclFromUser<D> user_decl(const_cast<D *>(item.first));
+ DeclFromParser <D> parser_decl(user_decl.Import(importer, dest_ctx));
+ if (parser_decl.IsInvalid())
+ return false;
+ destination_map.insert(std::pair<const D *, O>(parser_decl.decl, item.second));
+ }
+
+ return true;
+}
+
+template <bool IsVirtual>
+bool
+ExtractBaseOffsets(const ASTRecordLayout &record_layout, DeclFromUser<const CXXRecordDecl> &record,
+ BaseOffsetMap &base_offsets)
+{
+ for (CXXRecordDecl::base_class_const_iterator bi = (IsVirtual ? record->vbases_begin() : record->bases_begin()),
+ be = (IsVirtual ? record->vbases_end() : record->bases_end());
+ bi != be; ++bi)
+ {
+ if (!IsVirtual && bi->isVirtual())
+ continue;
+
+ const clang::Type *origin_base_type = bi->getType().getTypePtr();
+ const clang::RecordType *origin_base_record_type = origin_base_type->getAs<RecordType>();
+
+ if (!origin_base_record_type)
+ return false;
+
+ DeclFromUser <RecordDecl> origin_base_record(origin_base_record_type->getDecl());
+
+ if (origin_base_record.IsInvalid())
+ return false;
+
+ DeclFromUser <CXXRecordDecl> origin_base_cxx_record(DynCast<CXXRecordDecl>(origin_base_record));
+
+ if (origin_base_cxx_record.IsInvalid())
+ return false;
+
+ CharUnits base_offset;
+
+ if (IsVirtual)
+ base_offset = record_layout.getVBaseClassOffset(origin_base_cxx_record.decl);
+ else
+ base_offset = record_layout.getBaseClassOffset(origin_base_cxx_record.decl);
+
+ base_offsets.insert(std::pair<const CXXRecordDecl *, CharUnits>(origin_base_cxx_record.decl, base_offset));
+ }
+
+ return true;
+}
+
+bool
+ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, uint64_t &alignment,
+ FieldOffsetMap &field_offsets, BaseOffsetMap &base_offsets,
+ BaseOffsetMap &virtual_base_offsets)
+{
+ ClangASTMetrics::RegisterRecordLayout();
+
+ static unsigned int invocation_id = 0;
+ unsigned int current_id = invocation_id++;
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ log->Printf("LayoutRecordType[%u] on (ASTContext*)%p for (RecordDecl*)%p [name = '%s']",
+ current_id, static_cast<void*>(m_ast_context),
+ static_cast<const void*>(record),
+ record->getNameAsString().c_str());
+
+ DeclFromParser <const RecordDecl> parser_record(record);
+ DeclFromUser <const RecordDecl> origin_record(parser_record.GetOrigin(m_ast_importer_sp.get()));
+
+ if (origin_record.IsInvalid())
+ return false;
+
+ FieldOffsetMap origin_field_offsets;
+ BaseOffsetMap origin_base_offsets;
+ BaseOffsetMap origin_virtual_base_offsets;
+
+ ClangASTContext::GetCompleteDecl(&origin_record->getASTContext(), const_cast<RecordDecl*>(origin_record.decl));
+
+ clang::RecordDecl* definition = origin_record.decl->getDefinition();
+ if (!definition || !definition->isCompleteDefinition())
+ return false;
+
+ const ASTRecordLayout &record_layout(origin_record->getASTContext().getASTRecordLayout(origin_record.decl));
+
+ int field_idx = 0, field_count = record_layout.getFieldCount();
+
+ for (RecordDecl::field_iterator fi = origin_record->field_begin(), fe = origin_record->field_end(); fi != fe; ++fi)
+ {
+ if (field_idx >= field_count)
+ return false; // Layout didn't go well. Bail out.
+
+ uint64_t field_offset = record_layout.getFieldOffset(field_idx);
+
+ origin_field_offsets.insert(std::pair<const FieldDecl *, uint64_t>(*fi, field_offset));
+
+ field_idx++;
+ }
+
+ ASTContext &parser_ast_context(record->getASTContext());
+
+ DeclFromUser <const CXXRecordDecl> origin_cxx_record(DynCast<const CXXRecordDecl>(origin_record));
+
+ if (origin_cxx_record.IsValid())
+ {
+ if (!ExtractBaseOffsets<false>(record_layout, origin_cxx_record, origin_base_offsets) ||
+ !ExtractBaseOffsets<true>(record_layout, origin_cxx_record, origin_virtual_base_offsets))
+ return false;
+ }
+
+ if (!ImportOffsetMap(field_offsets, origin_field_offsets, m_ast_importer_sp.get(), parser_ast_context) ||
+ !ImportOffsetMap(base_offsets, origin_base_offsets, m_ast_importer_sp.get(), parser_ast_context) ||
+ !ImportOffsetMap(virtual_base_offsets, origin_virtual_base_offsets, m_ast_importer_sp.get(), parser_ast_context))
+ return false;
+
+ size = record_layout.getSize().getQuantity() * m_ast_context->getCharWidth();
+ alignment = record_layout.getAlignment().getQuantity() * m_ast_context->getCharWidth();
+
+ if (log)
+ {
+ log->Printf("LRT[%u] returned:", current_id);
+ log->Printf("LRT[%u] Original = (RecordDecl*)%p", current_id,
+ static_cast<const void*>(origin_record.decl));
+ log->Printf("LRT[%u] Size = %" PRId64, current_id, size);
+ log->Printf("LRT[%u] Alignment = %" PRId64, current_id, alignment);
+ log->Printf("LRT[%u] Fields:", current_id);
+ for (RecordDecl::field_iterator fi = record->field_begin(), fe = record->field_end();
+ fi != fe;
+ ++fi)
+ {
+ log->Printf("LRT[%u] (FieldDecl*)%p, Name = '%s', Offset = %" PRId64 " bits", current_id,
+ static_cast<void *>(*fi), fi->getNameAsString().c_str(), field_offsets[*fi]);
+ }
+ DeclFromParser <const CXXRecordDecl> parser_cxx_record = DynCast<const CXXRecordDecl>(parser_record);
+ if (parser_cxx_record.IsValid())
+ {
+ log->Printf("LRT[%u] Bases:", current_id);
+ for (CXXRecordDecl::base_class_const_iterator bi = parser_cxx_record->bases_begin(), be = parser_cxx_record->bases_end();
+ bi != be;
+ ++bi)
+ {
+ bool is_virtual = bi->isVirtual();
+
+ QualType base_type = bi->getType();
+ const RecordType *base_record_type = base_type->getAs<RecordType>();
+ DeclFromParser <RecordDecl> base_record(base_record_type->getDecl());
+ DeclFromParser <CXXRecordDecl> base_cxx_record = DynCast<CXXRecordDecl>(base_record);
+
+ log->Printf("LRT[%u] %s(CXXRecordDecl*)%p, Name = '%s', Offset = %" PRId64 " chars", current_id,
+ (is_virtual ? "Virtual " : ""), static_cast<void *>(base_cxx_record.decl),
+ base_cxx_record.decl->getNameAsString().c_str(),
+ (is_virtual ? virtual_base_offsets[base_cxx_record.decl].getQuantity()
+ : base_offsets[base_cxx_record.decl].getQuantity()));
+ }
+ }
+ else
+ {
+ log->Printf("LRD[%u] Not a CXXRecord, so no bases", current_id);
+ }
+ }
+
+ return true;
+}
+
+void
+ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespace_map,
+ const ConstString &name,
+ ClangASTImporter::NamespaceMapSP &parent_map) const
+{
+ static unsigned int invocation_id = 0;
+ unsigned int current_id = invocation_id++;
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ {
+ if (parent_map && parent_map->size())
+ log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s in namespace %s",
+ current_id, static_cast<void*>(m_ast_context),
+ name.GetCString(),
+ parent_map->begin()->second.GetName().AsCString());
+ else
+ log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s",
+ current_id, static_cast<void*>(m_ast_context),
+ name.GetCString());
+ }
+
+ if (parent_map)
+ {
+ for (ClangASTImporter::NamespaceMap::iterator i = parent_map->begin(), e = parent_map->end();
+ i != e;
+ ++i)
+ {
+ CompilerDeclContext found_namespace_decl;
+
+ lldb::ModuleSP module_sp = i->first;
+ CompilerDeclContext module_parent_namespace_decl = i->second;
+
+ SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor();
+
+ if (!symbol_vendor)
+ continue;
+
+ SymbolContext null_sc;
+
+ found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &module_parent_namespace_decl);
+
+ if (!found_namespace_decl)
+ continue;
+
+ namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>(module_sp, found_namespace_decl));
+
+ if (log)
+ log->Printf(" CMN[%u] Found namespace %s in module %s",
+ current_id,
+ name.GetCString(),
+ module_sp->GetFileSpec().GetFilename().GetCString());
+ }
+ }
+ else
+ {
+ const ModuleList &target_images = m_target->GetImages();
+ Mutex::Locker modules_locker(target_images.GetMutex());
+
+ CompilerDeclContext null_namespace_decl;
+
+ for (size_t i = 0, e = target_images.GetSize(); i < e; ++i)
+ {
+ lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i);
+
+ if (!image)
+ continue;
+
+ CompilerDeclContext found_namespace_decl;
+
+ SymbolVendor *symbol_vendor = image->GetSymbolVendor();
+
+ if (!symbol_vendor)
+ continue;
+
+ SymbolContext null_sc;
+
+ found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &null_namespace_decl);
+
+ if (!found_namespace_decl)
+ continue;
+
+ namespace_map->push_back(std::pair<lldb::ModuleSP, CompilerDeclContext>(image, found_namespace_decl));
+
+ if (log)
+ log->Printf(" CMN[%u] Found namespace %s in module %s",
+ current_id,
+ name.GetCString(),
+ image->GetFileSpec().GetFilename().GetCString());
+ }
+ }
+}
+
+NamespaceDecl *
+ClangASTSource::AddNamespace (NameSearchContext &context, ClangASTImporter::NamespaceMapSP &namespace_decls)
+{
+ if (!namespace_decls)
+ return nullptr;
+
+ const CompilerDeclContext &namespace_decl = namespace_decls->begin()->second;
+
+ clang::ASTContext *src_ast = ClangASTContext::DeclContextGetClangASTContext(namespace_decl);
+ if (!src_ast)
+ return nullptr;
+ clang::NamespaceDecl *src_namespace_decl = ClangASTContext::DeclContextGetAsNamespaceDecl(namespace_decl);
+
+ if (!src_namespace_decl)
+ return nullptr;
+
+ Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, src_ast, src_namespace_decl);
+
+ if (!copied_decl)
+ return nullptr;
+
+ NamespaceDecl *copied_namespace_decl = dyn_cast<NamespaceDecl>(copied_decl);
+
+ if (!copied_namespace_decl)
+ return nullptr;
+
+ context.m_decls.push_back(copied_namespace_decl);
+
+ m_ast_importer_sp->RegisterNamespaceMap(copied_namespace_decl, namespace_decls);
+
+ return dyn_cast<NamespaceDecl>(copied_decl);
+}
+
+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 = m_ast_importer_sp->CopyType (m_ast_context, src_ast->getASTContext(), ClangASTContext::GetQualType(src_type));
+
+ SetImportInProgress(false);
+
+ if (copied_qual_type.getAsOpaquePtr() && copied_qual_type->getCanonicalTypeInternal().isNull())
+ // this shouldn't happen, but we're hardening because the AST importer seems to be generating bad types
+ // on occasion.
+ return CompilerType();
+
+ return CompilerType(m_ast_context, copied_qual_type);
+}
+
+clang::NamedDecl *
+NameSearchContext::AddVarDecl(const CompilerType &type)
+{
+ assert (type && "Type for variable must be valid!");
+
+ if (!type.IsValid())
+ return NULL;
+
+ ClangASTContext* lldb_ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
+ if (!lldb_ast)
+ return NULL;
+
+ IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo();
+
+ clang::ASTContext *ast = lldb_ast->getASTContext();
+
+ clang::NamedDecl *Decl = VarDecl::Create(*ast,
+ const_cast<DeclContext*>(m_decl_context),
+ SourceLocation(),
+ SourceLocation(),
+ ii,
+ ClangASTContext::GetQualType(type),
+ 0,
+ SC_Static);
+ m_decls.push_back(Decl);
+
+ return Decl;
+}
+
+clang::NamedDecl *
+NameSearchContext::AddFunDecl (const CompilerType &type, bool extern_c)
+{
+ assert (type && "Type for variable must be valid!");
+
+ if (!type.IsValid())
+ return NULL;
+
+ if (m_function_types.count(type))
+ return NULL;
+
+ ClangASTContext* lldb_ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
+ if (!lldb_ast)
+ return NULL;
+
+ m_function_types.insert(type);
+
+ QualType qual_type (ClangASTContext::GetQualType(type));
+
+ clang::ASTContext *ast = lldb_ast->getASTContext();
+
+ const bool isInlineSpecified = false;
+ const bool hasWrittenPrototype = true;
+ const bool isConstexprSpecified = false;
+
+ clang::DeclContext *context = const_cast<DeclContext*>(m_decl_context);
+
+ if (extern_c) {
+ context = LinkageSpecDecl::Create(*ast,
+ context,
+ SourceLocation(),
+ SourceLocation(),
+ clang::LinkageSpecDecl::LanguageIDs::lang_c,
+ false);
+ }
+
+ // Pass the identifier info for functions the decl_name is needed for operators
+ clang::DeclarationName decl_name = m_decl_name.getNameKind() == DeclarationName::Identifier ? m_decl_name.getAsIdentifierInfo() : m_decl_name;
+
+ clang::FunctionDecl *func_decl = FunctionDecl::Create (*ast,
+ context,
+ SourceLocation(),
+ SourceLocation(),
+ decl_name,
+ qual_type,
+ NULL,
+ SC_Extern,
+ isInlineSpecified,
+ hasWrittenPrototype,
+ isConstexprSpecified);
+
+ // We have to do more than just synthesize the FunctionDecl. We have to
+ // synthesize ParmVarDecls for all of the FunctionDecl's arguments. To do
+ // this, we raid the function's FunctionProtoType for types.
+
+ const FunctionProtoType *func_proto_type = qual_type.getTypePtr()->getAs<FunctionProtoType>();
+
+ if (func_proto_type)
+ {
+ unsigned NumArgs = func_proto_type->getNumParams();
+ unsigned ArgIndex;
+
+ SmallVector<ParmVarDecl *, 5> parm_var_decls;
+
+ for (ArgIndex = 0; ArgIndex < NumArgs; ++ArgIndex)
+ {
+ QualType arg_qual_type (func_proto_type->getParamType(ArgIndex));
+
+ parm_var_decls.push_back(ParmVarDecl::Create (*ast,
+ const_cast<DeclContext*>(context),
+ SourceLocation(),
+ SourceLocation(),
+ NULL,
+ arg_qual_type,
+ NULL,
+ SC_Static,
+ NULL));
+ }
+
+ func_decl->setParams(ArrayRef<ParmVarDecl*>(parm_var_decls));
+ }
+ else
+ {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ log->Printf("Function type wasn't a FunctionProtoType");
+ }
+
+ m_decls.push_back(func_decl);
+
+ return func_decl;
+}
+
+clang::NamedDecl *
+NameSearchContext::AddGenericFunDecl()
+{
+ FunctionProtoType::ExtProtoInfo proto_info;
+
+ proto_info.Variadic = true;
+
+ QualType generic_function_type(m_ast_source.m_ast_context->getFunctionType (m_ast_source.m_ast_context->UnknownAnyTy, // result
+ ArrayRef<QualType>(), // argument types
+ proto_info));
+
+ return AddFunDecl(CompilerType (m_ast_source.m_ast_context, generic_function_type), true);
+}
+
+clang::NamedDecl *
+NameSearchContext::AddTypeDecl(const CompilerType &clang_type)
+{
+ if (clang_type)
+ {
+ QualType qual_type = ClangASTContext::GetQualType(clang_type);
+
+ if (const TypedefType *typedef_type = llvm::dyn_cast<TypedefType>(qual_type))
+ {
+ TypedefNameDecl *typedef_name_decl = typedef_type->getDecl();
+
+ m_decls.push_back(typedef_name_decl);
+
+ return (NamedDecl*)typedef_name_decl;
+ }
+ else if (const TagType *tag_type = qual_type->getAs<TagType>())
+ {
+ TagDecl *tag_decl = tag_type->getDecl();
+
+ m_decls.push_back(tag_decl);
+
+ return tag_decl;
+ }
+ else if (const ObjCObjectType *objc_object_type = qual_type->getAs<ObjCObjectType>())
+ {
+ ObjCInterfaceDecl *interface_decl = objc_object_type->getInterface();
+
+ m_decls.push_back((NamedDecl*)interface_decl);
+
+ return (NamedDecl*)interface_decl;
+ }
+ }
+ return NULL;
+}
+
+void
+NameSearchContext::AddLookupResult (clang::DeclContextLookupResult result)
+{
+ for (clang::NamedDecl *decl : result)
+ m_decls.push_back (decl);
+}
+
+void
+NameSearchContext::AddNamedDecl (clang::NamedDecl *decl)
+{
+ m_decls.push_back (decl);
+}
diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
new file mode 100644
index 000000000000..bb6384721f51
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
@@ -0,0 +1,526 @@
+//===-- ClangASTSource.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ClangASTSource_h_
+#define liblldb_ClangASTSource_h_
+
+#include <set>
+
+#include "clang/Basic/IdentifierTable.h"
+#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/ClangASTImporter.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Target/Target.h"
+
+#include "llvm/ADT/SmallSet.h"
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+/// @class ClangASTSource ClangASTSource.h "lldb/Expression/ClangASTSource.h"
+/// @brief Provider for named objects defined in the debug info for Clang
+///
+/// As Clang parses an expression, it may encounter names that are not
+/// defined inside the expression, including variables, functions, and
+/// types. Clang 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,
+ public ClangASTImporter::MapCompleter
+{
+public:
+ //------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// Initializes class variables.
+ ///
+ /// @param[in] declMap
+ /// A reference to the LLDB object that handles entity lookup.
+ //------------------------------------------------------------------
+ ClangASTSource (const lldb::TargetSP &target) :
+ m_import_in_progress (false),
+ m_lookups_enabled (false),
+ m_target (target),
+ m_ast_context (NULL),
+ m_active_lexical_decls (),
+ m_active_lookups ()
+ {
+ m_ast_importer_sp = m_target->GetClangASTImporter();
+ }
+
+ //------------------------------------------------------------------
+ /// Destructor
+ //------------------------------------------------------------------
+ ~ClangASTSource() override;
+
+ //------------------------------------------------------------------
+ /// Interface stubs.
+ //------------------------------------------------------------------
+ clang::Decl *GetExternalDecl (uint32_t) override { return NULL; }
+ clang::Stmt *GetExternalDeclStmt (uint64_t) override { return NULL; }
+ clang::Selector GetExternalSelector (uint32_t) override { return clang::Selector(); }
+ uint32_t GetNumExternalSelectors () override { return 0; }
+ clang::CXXBaseSpecifier *GetExternalCXXBaseSpecifiers (uint64_t Offset) override
+ { return NULL; }
+ void MaterializeVisibleDecls (const clang::DeclContext *DC)
+ { return; }
+
+ void InstallASTContext (clang::ASTContext *ast_context)
+ {
+ m_ast_context = ast_context;
+ m_ast_importer_sp->InstallMapCompleter(ast_context, *this);
+ }
+
+ //
+ // APIs for ExternalASTSource
+ //
+
+ //------------------------------------------------------------------
+ /// Look up all Decls that match a particular name. Only handles
+ /// Identifiers and DeclContexts that are either NamespaceDecls or
+ /// TranslationUnitDecls. Calls SetExternalVisibleDeclsForName with
+ /// the result.
+ ///
+ /// The work for this function is done by
+ /// void FindExternalVisibleDecls (NameSearchContext &);
+ ///
+ /// @param[in] DC
+ /// The DeclContext to register the found Decls in.
+ ///
+ /// @param[in] Name
+ /// The name to find entries for.
+ ///
+ /// @return
+ /// Whatever SetExternalVisibleDeclsForName returns.
+ //------------------------------------------------------------------
+ bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC, clang::DeclarationName Name) override;
+
+ //------------------------------------------------------------------
+ /// Enumerate all Decls in a given lexical context.
+ ///
+ /// @param[in] DC
+ /// The DeclContext being searched.
+ ///
+ /// @param[in] isKindWeWant
+ /// A callback function that returns true given the
+ /// DeclKinds of desired Decls, and false otherwise.
+ ///
+ /// @param[in] Decls
+ /// A vector that is filled in with matching Decls.
+ //------------------------------------------------------------------
+ void FindExternalLexicalDecls(
+ const clang::DeclContext *DC, llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
+ llvm::SmallVectorImpl<clang::Decl *> &Decls) override;
+
+ //------------------------------------------------------------------
+ /// Specify the layout of the contents of a RecordDecl.
+ ///
+ /// @param[in] Record
+ /// The record (in the parser's AST context) that needs to be
+ /// laid out.
+ ///
+ /// @param[out] Size
+ /// The total size of the record in bits.
+ ///
+ /// @param[out] Alignment
+ /// The alignment of the record in bits.
+ ///
+ /// @param[in] FieldOffsets
+ /// A map that must be populated with pairs of the record's
+ /// fields (in the parser's AST context) and their offsets
+ /// (measured in bits).
+ ///
+ /// @param[in] BaseOffsets
+ /// A map that must be populated with pairs of the record's
+ /// C++ concrete base classes (in the parser's AST context,
+ /// and only if the record is a CXXRecordDecl and has base
+ /// classes) and their offsets (measured in bytes).
+ ///
+ /// @param[in] VirtualBaseOffsets
+ /// A map that must be populated with pairs of the record's
+ /// C++ virtual base classes (in the parser's AST context,
+ /// and only if the record is a CXXRecordDecl and has base
+ /// classes) and their offsets (measured in bytes).
+ ///
+ /// @return
+ /// True <=> the layout is valid.
+ //-----------------------------------------------------------------
+ bool layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
+ llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets) override;
+
+ //------------------------------------------------------------------
+ /// Complete a TagDecl.
+ ///
+ /// @param[in] Tag
+ /// The Decl to be completed in place.
+ //------------------------------------------------------------------
+ void CompleteType(clang::TagDecl *Tag) override;
+
+ //------------------------------------------------------------------
+ /// Complete an ObjCInterfaceDecl.
+ ///
+ /// @param[in] Class
+ /// The Decl to be completed in place.
+ //------------------------------------------------------------------
+ void CompleteType(clang::ObjCInterfaceDecl *Class) override;
+
+ //------------------------------------------------------------------
+ /// Called on entering a translation unit. Tells Clang by calling
+ /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage()
+ /// that this object has something to say about undefined names.
+ ///
+ /// @param[in] ASTConsumer
+ /// Unused.
+ //------------------------------------------------------------------
+ void StartTranslationUnit(clang::ASTConsumer *Consumer) override;
+
+ //
+ // APIs for NamespaceMapCompleter
+ //
+
+ //------------------------------------------------------------------
+ /// Look up the modules containing a given namespace and put the
+ /// appropriate entries in the namespace map.
+ ///
+ /// @param[in] namespace_map
+ /// The map to be completed.
+ ///
+ /// @param[in] name
+ /// The name of the namespace to be found.
+ ///
+ /// @param[in] parent_map
+ /// The map for the namespace's parent namespace, if there is
+ /// one.
+ //------------------------------------------------------------------
+ void CompleteNamespaceMap(ClangASTImporter::NamespaceMapSP &namespace_map, const ConstString &name,
+ ClangASTImporter::NamespaceMapSP &parent_map) const override;
+
+ //
+ // Helper APIs
+ //
+
+ clang::NamespaceDecl *
+ AddNamespace (NameSearchContext &context,
+ ClangASTImporter::NamespaceMapSP &namespace_decls);
+
+ //------------------------------------------------------------------
+ /// The worker function for FindExternalVisibleDeclsByName.
+ ///
+ /// @param[in] context
+ /// The NameSearchContext to use when filing results.
+ //------------------------------------------------------------------
+ virtual void FindExternalVisibleDecls (NameSearchContext &context);
+
+ void SetImportInProgress (bool import_in_progress) { m_import_in_progress = import_in_progress; }
+ bool GetImportInProgress () { return m_import_in_progress; }
+
+ void SetLookupsEnabled (bool lookups_enabled) { m_lookups_enabled = lookups_enabled; }
+ bool GetLookupsEnabled () { return m_lookups_enabled; }
+
+ //----------------------------------------------------------------------
+ /// @class ClangASTSourceProxy ClangASTSource.h "lldb/Expression/ClangASTSource.h"
+ /// @brief Proxy for ClangASTSource
+ ///
+ /// Clang AST contexts like to own their AST sources, so this is a
+ /// state-free proxy object.
+ //----------------------------------------------------------------------
+ class ClangASTSourceProxy : public ClangExternalASTSourceCommon
+ {
+ public:
+ ClangASTSourceProxy (ClangASTSource &original) :
+ m_original(original)
+ {
+ }
+
+ bool
+ FindExternalVisibleDeclsByName(const clang::DeclContext *DC, clang::DeclarationName Name) override
+ {
+ return m_original.FindExternalVisibleDeclsByName(DC, Name);
+ }
+
+ void
+ FindExternalLexicalDecls(const clang::DeclContext *DC,
+ llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
+ llvm::SmallVectorImpl<clang::Decl *> &Decls) override
+ {
+ return m_original.FindExternalLexicalDecls(DC, IsKindWeWant, Decls);
+ }
+
+ void
+ CompleteType(clang::TagDecl *Tag) override
+ {
+ return m_original.CompleteType(Tag);
+ }
+
+ void
+ CompleteType(clang::ObjCInterfaceDecl *Class) override
+ {
+ return m_original.CompleteType(Class);
+ }
+
+ bool
+ layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
+ llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets) override
+ {
+ return m_original.layoutRecordType(Record,
+ Size,
+ Alignment,
+ FieldOffsets,
+ BaseOffsets,
+ VirtualBaseOffsets);
+ }
+
+ void
+ StartTranslationUnit(clang::ASTConsumer *Consumer) override
+ {
+ 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;
+ };
+
+ clang::ExternalASTSource *CreateProxy()
+ {
+ return new ClangASTSourceProxy(*this);
+ }
+
+protected:
+ //------------------------------------------------------------------
+ /// Look for the complete version of an Objective-C interface, and
+ /// return it if found.
+ ///
+ /// @param[in] interface_decl
+ /// An ObjCInterfaceDecl that may not be the complete one.
+ ///
+ /// @return
+ /// NULL if the complete interface couldn't be found;
+ /// the complete interface otherwise.
+ //------------------------------------------------------------------
+ clang::ObjCInterfaceDecl *
+ GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_decl);
+
+ //------------------------------------------------------------------
+ /// Find all entities matching a given name in a given module,
+ /// using a NameSearchContext to make Decls for them.
+ ///
+ /// @param[in] context
+ /// The NameSearchContext that can construct Decls for this name.
+ ///
+ /// @param[in] module
+ /// If non-NULL, the module to query.
+ ///
+ /// @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.
+ ///
+ /// @return
+ /// True on success; false otherwise.
+ //------------------------------------------------------------------
+ void
+ FindExternalVisibleDecls (NameSearchContext &context,
+ lldb::ModuleSP module,
+ CompilerDeclContext &namespace_decl,
+ unsigned int current_id);
+
+ //------------------------------------------------------------------
+ /// Find all Objective-C methods matching a given selector.
+ ///
+ /// @param[in] context
+ /// The NameSearchContext that can construct Decls for this name.
+ /// Its m_decl_name contains the selector and its m_decl_context
+ /// is the containing object.
+ //------------------------------------------------------------------
+ void
+ FindObjCMethodDecls (NameSearchContext &context);
+
+ //------------------------------------------------------------------
+ /// Find all Objective-C properties and ivars with a given name.
+ ///
+ /// @param[in] context
+ /// The NameSearchContext that can construct Decls for this name.
+ /// Its m_decl_name contains the name and its m_decl_context
+ /// is the containing object.
+ //------------------------------------------------------------------
+ void
+ FindObjCPropertyAndIvarDecls (NameSearchContext &context);
+
+ //------------------------------------------------------------------
+ /// 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.
+ ///
+ /// @return
+ /// The imported type.
+ //------------------------------------------------------------------
+ CompilerType
+ GuardedCopyType (const CompilerType &src_type);
+
+ friend struct NameSearchContext;
+
+ 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.
+ lldb::ClangASTImporterSP m_ast_importer_sp; ///< The target's AST importer.
+ std::set<const clang::Decl *> m_active_lexical_decls;
+ std::set<const char *> m_active_lookups;
+};
+
+//----------------------------------------------------------------------
+/// @class NameSearchContext ClangASTSource.h "lldb/Expression/ClangASTSource.h"
+/// @brief Container for all objects relevant to a single name lookup
+///
+/// LLDB needs to create Decls for entities it finds. This class communicates
+/// 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
+
+ struct {
+ bool variable : 1;
+ bool function_with_type_info : 1;
+ bool function : 1;
+ } m_found;
+
+ //------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// Initializes class variables.
+ ///
+ /// @param[in] astSource
+ /// A reference to the AST source making a request.
+ ///
+ /// @param[in] decls
+ /// A reference to a list into which new Decls will be placed. This
+ /// list is typically empty when the function is called.
+ ///
+ /// @param[in] name
+ /// The name being searched for (always an Identifier).
+ ///
+ /// @param[in] dc
+ /// The DeclContext to register Decls in.
+ //------------------------------------------------------------------
+ NameSearchContext (ClangASTSource &astSource,
+ llvm::SmallVectorImpl<clang::NamedDecl*> &decls,
+ clang::DeclarationName &name,
+ const clang::DeclContext *dc) :
+ m_ast_source(astSource),
+ m_decls(decls),
+ m_decl_name(name),
+ m_decl_context(dc)
+ {
+ memset(&m_found, 0, sizeof(m_found));
+ }
+
+ //------------------------------------------------------------------
+ /// Create a VarDecl with the name being searched for and the provided
+ /// type and register it in the right places.
+ ///
+ /// @param[in] type
+ /// The opaque QualType for the VarDecl being registered.
+ //------------------------------------------------------------------
+ clang::NamedDecl *AddVarDecl(const CompilerType &type);
+
+ //------------------------------------------------------------------
+ /// Create a FunDecl with the name being searched for and the provided
+ /// type and register it in the right places.
+ ///
+ /// @param[in] type
+ /// The opaque QualType for the FunDecl being registered.
+ ///
+ /// @param[in] extern_c
+ /// If true, build an extern "C" linkage specification for this.
+ //------------------------------------------------------------------
+ clang::NamedDecl *AddFunDecl(const CompilerType &type,
+ bool extern_c = false);
+
+ //------------------------------------------------------------------
+ /// Create a FunDecl with the name being searched for and generic
+ /// type (i.e. intptr_t NAME_GOES_HERE(...)) and register it in the
+ /// right places.
+ //------------------------------------------------------------------
+ clang::NamedDecl *AddGenericFunDecl();
+
+ //------------------------------------------------------------------
+ /// Create a TypeDecl with the name being searched for and the provided
+ /// type and register it in the right places.
+ ///
+ /// @param[in] compiler_type
+ /// The opaque QualType for the TypeDecl being registered.
+ //------------------------------------------------------------------
+ clang::NamedDecl *AddTypeDecl(const CompilerType &compiler_type);
+
+
+ //------------------------------------------------------------------
+ /// Add Decls from the provided DeclContextLookupResult to the list
+ /// of results.
+ ///
+ /// @param[in] result
+ /// The DeclContextLookupResult, usually returned as the result
+ /// of querying a DeclContext.
+ //------------------------------------------------------------------
+ void AddLookupResult (clang::DeclContextLookupResult result);
+
+ //------------------------------------------------------------------
+ /// Add a NamedDecl to the list of results.
+ ///
+ /// @param[in] decl
+ /// The NamedDecl, usually returned as the result
+ /// of querying a DeclContext.
+ //------------------------------------------------------------------
+ void AddNamedDecl (clang::NamedDecl *decl);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ClangASTSource_h_
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
new file mode 100644
index 000000000000..c9bc4b6487cd
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -0,0 +1,2351 @@
+//===-- ClangExpressionDeclMap.cpp -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangExpressionDeclMap.h"
+
+#include "ASTDumper.h"
+#include "ClangASTSource.h"
+#include "ClangModulesDeclVendor.h"
+#include "ClangPersistentVariables.h"
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Decl.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/Expression/Materializer.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/CompilerDecl.h"
+#include "lldb/Symbol/CompilerDeclContext.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/Variable.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/CPPLanguageRuntime.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace clang;
+
+ClangExpressionDeclMap::ClangExpressionDeclMap (bool keep_result_in_memory,
+ Materializer::PersistentVariableDelegate *result_delegate,
+ ExecutionContext &exe_ctx) :
+ ClangASTSource (exe_ctx.GetTargetSP()),
+ m_found_entities (),
+ m_struct_members (),
+ m_keep_result_in_memory (keep_result_in_memory),
+ m_result_delegate (result_delegate),
+ m_parser_vars (),
+ m_struct_vars ()
+{
+ EnableStructVars();
+}
+
+ClangExpressionDeclMap::~ClangExpressionDeclMap()
+{
+ // Note: The model is now that the parser's AST context and all associated
+ // data does not vanish until the expression has been executed. This means
+ // that valuable lookup data (like namespaces) doesn't vanish, but
+
+ DidParse();
+ DisableStructVars();
+}
+
+bool
+ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx,
+ Materializer *materializer)
+{
+ ClangASTMetrics::ClearLocalCounters();
+
+ EnableParserVars();
+ m_parser_vars->m_exe_ctx = exe_ctx;
+
+ Target *target = exe_ctx.GetTargetPtr();
+ if (exe_ctx.GetFramePtr())
+ m_parser_vars->m_sym_ctx = exe_ctx.GetFramePtr()->GetSymbolContext(lldb::eSymbolContextEverything);
+ else if (exe_ctx.GetThreadPtr() && exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(0))
+ m_parser_vars->m_sym_ctx = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(0)->GetSymbolContext(lldb::eSymbolContextEverything);
+ else if (exe_ctx.GetProcessPtr())
+ {
+ m_parser_vars->m_sym_ctx.Clear(true);
+ m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP();
+ }
+ else if (target)
+ {
+ m_parser_vars->m_sym_ctx.Clear(true);
+ m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP();
+ }
+
+ if (target)
+ {
+ m_parser_vars->m_persistent_vars = llvm::cast<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(eLanguageTypeC));
+
+ if (!target->GetScratchClangASTContext())
+ return false;
+ }
+
+ m_parser_vars->m_target_info = GetTargetInfo();
+ m_parser_vars->m_materializer = materializer;
+
+ return true;
+}
+
+void
+ClangExpressionDeclMap::InstallCodeGenerator (clang::ASTConsumer *code_gen)
+{
+ assert(m_parser_vars);
+ m_parser_vars->m_code_gen = code_gen;
+}
+
+void
+ClangExpressionDeclMap::DidParse()
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ ClangASTMetrics::DumpCounters(log);
+
+ if (m_parser_vars.get())
+ {
+ for (size_t entity_index = 0, num_entities = m_found_entities.GetSize();
+ entity_index < num_entities;
+ ++entity_index)
+ {
+ ExpressionVariableSP var_sp(m_found_entities.GetVariableAtIndex(entity_index));
+ if (var_sp)
+ llvm::cast<ClangExpressionVariable>(var_sp.get())->DisableParserVars(GetParserID());
+ }
+
+ for (size_t pvar_index = 0, num_pvars = m_parser_vars->m_persistent_vars->GetSize();
+ pvar_index < num_pvars;
+ ++pvar_index)
+ {
+ ExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariableAtIndex(pvar_index));
+ if (ClangExpressionVariable *clang_var = llvm::dyn_cast<ClangExpressionVariable>(pvar_sp.get()))
+ clang_var->DisableParserVars(GetParserID());
+ }
+
+ DisableParserVars();
+ }
+}
+
+// Interface for IRForTarget
+
+ClangExpressionDeclMap::TargetInfo
+ClangExpressionDeclMap::GetTargetInfo()
+{
+ assert (m_parser_vars.get());
+
+ TargetInfo ret;
+
+ ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx;
+
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process)
+ {
+ ret.byte_order = process->GetByteOrder();
+ ret.address_byte_size = process->GetAddressByteSize();
+ }
+ else
+ {
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target)
+ {
+ ret.byte_order = target->GetArchitecture().GetByteOrder();
+ ret.address_byte_size = target->GetArchitecture().GetAddressByteSize();
+ }
+ }
+
+ return ret;
+}
+
+bool
+ClangExpressionDeclMap::AddPersistentVariable
+(
+ const NamedDecl *decl,
+ const ConstString &name,
+ TypeFromParser parser_type,
+ bool is_result,
+ bool is_lvalue
+)
+{
+ assert (m_parser_vars.get());
+
+ ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(parser_type.GetTypeSystem());
+ if (ast == nullptr)
+ return false;
+
+ if (m_parser_vars->m_materializer && is_result)
+ {
+ Error err;
+
+ ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx;
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target == nullptr)
+ return false;
+
+ ClangASTContext *context(target->GetScratchClangASTContext());
+
+ TypeFromUser user_type(m_ast_importer_sp->DeportType(context->getASTContext(),
+ ast->getASTContext(),
+ parser_type.GetOpaqueQualType()),
+ context);
+
+ uint32_t offset = m_parser_vars->m_materializer->AddResultVariable(user_type,
+ is_lvalue,
+ m_keep_result_in_memory,
+ m_result_delegate,
+ err);
+
+ ClangExpressionVariable *var = new ClangExpressionVariable(exe_ctx.GetBestExecutionContextScope(),
+ name,
+ user_type,
+ m_parser_vars->m_target_info.byte_order,
+ m_parser_vars->m_target_info.address_byte_size);
+
+ m_found_entities.AddNewlyConstructedVariable(var);
+
+ var->EnableParserVars(GetParserID());
+
+ ClangExpressionVariable::ParserVars *parser_vars = var->GetParserVars(GetParserID());
+
+ parser_vars->m_named_decl = decl;
+ parser_vars->m_parser_type = parser_type;
+
+ var->EnableJITVars(GetParserID());
+
+ ClangExpressionVariable::JITVars *jit_vars = var->GetJITVars(GetParserID());
+
+ jit_vars->m_offset = offset;
+
+ return true;
+ }
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx;
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target == NULL)
+ return false;
+
+ ClangASTContext *context(target->GetScratchClangASTContext());
+
+ TypeFromUser user_type(m_ast_importer_sp->DeportType(context->getASTContext(),
+ ast->getASTContext(),
+ parser_type.GetOpaqueQualType()),
+ context);
+
+ if (!user_type.GetOpaqueQualType())
+ {
+ if (log)
+ log->Printf("Persistent variable's type wasn't copied successfully");
+ return false;
+ }
+
+ if (!m_parser_vars->m_target_info.IsValid())
+ return false;
+
+ ClangExpressionVariable *var = llvm::cast<ClangExpressionVariable>(m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx.GetBestExecutionContextScope (),
+ name,
+ user_type,
+ m_parser_vars->m_target_info.byte_order,
+ m_parser_vars->m_target_info.address_byte_size).get());
+
+ if (!var)
+ return false;
+
+ var->m_frozen_sp->SetHasCompleteType();
+
+ if (is_result)
+ var->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry;
+ else
+ var->m_flags |= ClangExpressionVariable::EVKeepInTarget; // explicitly-declared persistent variables should persist
+
+ if (is_lvalue)
+ {
+ var->m_flags |= ClangExpressionVariable::EVIsProgramReference;
+ }
+ else
+ {
+ var->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
+ var->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
+ }
+
+ if (m_keep_result_in_memory)
+ {
+ var->m_flags |= ClangExpressionVariable::EVKeepInTarget;
+ }
+
+ if (log)
+ log->Printf("Created persistent variable with flags 0x%hx", var->m_flags);
+
+ var->EnableParserVars(GetParserID());
+
+ ClangExpressionVariable::ParserVars *parser_vars = var->GetParserVars(GetParserID());
+
+ parser_vars->m_named_decl = decl;
+ parser_vars->m_parser_type = parser_type;
+
+ return true;
+}
+
+bool
+ClangExpressionDeclMap::AddValueToStruct
+(
+ const NamedDecl *decl,
+ const ConstString &name,
+ llvm::Value *value,
+ size_t size,
+ lldb::offset_t alignment
+)
+{
+ assert (m_struct_vars.get());
+ assert (m_parser_vars.get());
+
+ bool is_persistent_variable = false;
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ m_struct_vars->m_struct_laid_out = false;
+
+ if (ClangExpressionVariable::FindVariableInList(m_struct_members, decl, GetParserID()))
+ return true;
+
+ ClangExpressionVariable *var(ClangExpressionVariable::FindVariableInList(m_found_entities, decl, GetParserID()));
+
+ if (!var)
+ {
+ var = ClangExpressionVariable::FindVariableInList(*m_parser_vars->m_persistent_vars, decl, GetParserID());
+ is_persistent_variable = true;
+ }
+
+ if (!var)
+ return false;
+
+ if (log)
+ log->Printf("Adding value for (NamedDecl*)%p [%s - %s] to the structure",
+ static_cast<const void*>(decl), name.GetCString(),
+ var->GetName().GetCString());
+
+ // We know entity->m_parser_vars is valid because we used a parser variable
+ // to find it
+
+ ClangExpressionVariable::ParserVars *parser_vars = llvm::cast<ClangExpressionVariable>(var)->GetParserVars(GetParserID());
+
+ parser_vars->m_llvm_value = value;
+
+ if (ClangExpressionVariable::JITVars *jit_vars = llvm::cast<ClangExpressionVariable>(var)->GetJITVars(GetParserID()))
+ {
+ // We already laid this out; do not touch
+
+ if (log)
+ log->Printf("Already placed at 0x%llx", (unsigned long long)jit_vars->m_offset);
+ }
+
+ llvm::cast<ClangExpressionVariable>(var)->EnableJITVars(GetParserID());
+
+ ClangExpressionVariable::JITVars *jit_vars = llvm::cast<ClangExpressionVariable>(var)->GetJITVars(GetParserID());
+
+ jit_vars->m_alignment = alignment;
+ jit_vars->m_size = size;
+
+ m_struct_members.AddVariable(var->shared_from_this());
+
+ if (m_parser_vars->m_materializer)
+ {
+ uint32_t offset = 0;
+
+ Error err;
+
+ if (is_persistent_variable)
+ {
+ ExpressionVariableSP var_sp(var->shared_from_this());
+ offset = m_parser_vars->m_materializer->AddPersistentVariable(var_sp, nullptr, err);
+ }
+ else
+ {
+ if (const lldb_private::Symbol *sym = parser_vars->m_lldb_sym)
+ offset = m_parser_vars->m_materializer->AddSymbol(*sym, err);
+ else if (const RegisterInfo *reg_info = var->GetRegisterInfo())
+ offset = m_parser_vars->m_materializer->AddRegister(*reg_info, err);
+ else if (parser_vars->m_lldb_var)
+ offset = m_parser_vars->m_materializer->AddVariable(parser_vars->m_lldb_var, err);
+ }
+
+ if (!err.Success())
+ return false;
+
+ if (log)
+ log->Printf("Placed at 0x%llx", (unsigned long long)offset);
+
+ jit_vars->m_offset = offset; // TODO DoStructLayout() should not change this.
+ }
+
+ return true;
+}
+
+bool
+ClangExpressionDeclMap::DoStructLayout ()
+{
+ assert (m_struct_vars.get());
+
+ if (m_struct_vars->m_struct_laid_out)
+ return true;
+
+ if (!m_parser_vars->m_materializer)
+ return false;
+
+ m_struct_vars->m_struct_alignment = m_parser_vars->m_materializer->GetStructAlignment();
+ m_struct_vars->m_struct_size = m_parser_vars->m_materializer->GetStructByteSize();
+ m_struct_vars->m_struct_laid_out = true;
+ return true;
+}
+
+bool ClangExpressionDeclMap::GetStructInfo
+(
+ uint32_t &num_elements,
+ size_t &size,
+ lldb::offset_t &alignment
+)
+{
+ assert (m_struct_vars.get());
+
+ if (!m_struct_vars->m_struct_laid_out)
+ return false;
+
+ num_elements = m_struct_members.GetSize();
+ size = m_struct_vars->m_struct_size;
+ alignment = m_struct_vars->m_struct_alignment;
+
+ return true;
+}
+
+bool
+ClangExpressionDeclMap::GetStructElement
+(
+ const NamedDecl *&decl,
+ llvm::Value *&value,
+ lldb::offset_t &offset,
+ ConstString &name,
+ uint32_t index
+)
+{
+ assert (m_struct_vars.get());
+
+ if (!m_struct_vars->m_struct_laid_out)
+ return false;
+
+ if (index >= m_struct_members.GetSize())
+ return false;
+
+ ExpressionVariableSP member_sp(m_struct_members.GetVariableAtIndex(index));
+
+ if (!member_sp)
+ return false;
+
+ ClangExpressionVariable::ParserVars *parser_vars = llvm::cast<ClangExpressionVariable>(member_sp.get())->GetParserVars(GetParserID());
+ ClangExpressionVariable::JITVars *jit_vars = llvm::cast<ClangExpressionVariable>(member_sp.get())->GetJITVars(GetParserID());
+
+ if (!parser_vars ||
+ !jit_vars ||
+ !member_sp->GetValueObject())
+ return false;
+
+ decl = parser_vars->m_named_decl;
+ value = parser_vars->m_llvm_value;
+ offset = jit_vars->m_offset;
+ name = member_sp->GetName();
+
+ return true;
+}
+
+bool
+ClangExpressionDeclMap::GetFunctionInfo
+(
+ const NamedDecl *decl,
+ uint64_t &ptr
+)
+{
+ ClangExpressionVariable *entity(ClangExpressionVariable::FindVariableInList(m_found_entities, decl, GetParserID()));
+
+ if (!entity)
+ return false;
+
+ // We know m_parser_vars is valid since we searched for the variable by
+ // its NamedDecl
+
+ ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID());
+
+ ptr = parser_vars->m_lldb_value.GetScalar().ULongLong();
+
+ return true;
+}
+
+static void
+FindCodeSymbolInContext
+(
+ const ConstString &name,
+ SymbolContext &sym_ctx,
+ uint32_t name_type_mask,
+ SymbolContextList &sc_list
+)
+{
+ sc_list.Clear();
+ SymbolContextList temp_sc_list;
+ if (sym_ctx.module_sp)
+ sym_ctx.module_sp->FindFunctions(name,
+ NULL,
+ name_type_mask,
+ true, // include_symbols
+ false, // include_inlines
+ true, // append
+ temp_sc_list);
+ if (temp_sc_list.GetSize() == 0)
+ {
+ if (sym_ctx.target_sp)
+ sym_ctx.target_sp->GetImages().FindFunctions(name,
+ name_type_mask,
+ true, // include_symbols
+ false, // include_inlines
+ true, // append
+ temp_sc_list);
+ }
+
+ SymbolContextList internal_symbol_sc_list;
+ unsigned temp_sc_list_size = temp_sc_list.GetSize();
+ for (unsigned i = 0; i < temp_sc_list_size; i++)
+ {
+ SymbolContext sc;
+ temp_sc_list.GetContextAtIndex(i, sc);
+ if (sc.function)
+ {
+ sc_list.Append(sc);
+ }
+ else if (sc.symbol)
+ {
+ if (sc.symbol->IsExternal())
+ {
+ sc_list.Append(sc);
+ }
+ else
+ {
+ internal_symbol_sc_list.Append(sc);
+ }
+ }
+ }
+
+ // If we had internal symbols and we didn't find any external symbols or
+ // functions in debug info, then fallback to the internal symbols
+ if (sc_list.GetSize() == 0 && internal_symbol_sc_list.GetSize())
+ {
+ sc_list = internal_symbol_sc_list;
+ }
+}
+
+bool
+ClangExpressionDeclMap::GetFunctionAddress
+(
+ const ConstString &name,
+ uint64_t &func_addr
+)
+{
+ assert (m_parser_vars.get());
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx;
+ Target *target = exe_ctx.GetTargetPtr();
+ // Back out in all cases where we're not fully initialized
+ if (target == NULL)
+ return false;
+ if (!m_parser_vars->m_sym_ctx.target_sp)
+ return false;
+
+ SymbolContextList sc_list;
+
+ FindCodeSymbolInContext(name, m_parser_vars->m_sym_ctx, eFunctionNameTypeAuto, sc_list);
+
+ uint32_t sc_list_size = sc_list.GetSize();
+
+ if (sc_list_size == 0)
+ {
+ SymbolContext &sc = m_parser_vars->m_sym_ctx;
+ if (sc.comp_unit)
+ {
+ LanguageType lang_type = sc.comp_unit->GetLanguage();
+ if (Language::LanguageIsCPlusPlus(lang_type) &&
+ CPlusPlusLanguage::IsCPPMangledName(name.AsCString()))
+ {
+ // 1. Demangle the name
+ Mangled mangled(name, true);
+ ConstString demangled = mangled.GetDemangledName(lang_type);
+
+ if (demangled)
+ {
+ FindCodeSymbolInContext(
+ demangled, m_parser_vars->m_sym_ctx, eFunctionNameTypeFull, sc_list);
+ sc_list_size = sc_list.GetSize();
+ }
+ }
+ }
+ }
+
+ if (sc_list_size == 0)
+ {
+ // We occasionally get debug information in which a const function is reported
+ // as non-const, so the mangled name is wrong. This is a hack to compensate.
+
+ if (!strncmp(name.GetCString(), "_ZN", 3) &&
+ strncmp(name.GetCString(), "_ZNK", 4))
+ {
+ std::string fixed_scratch("_ZNK");
+ fixed_scratch.append(name.GetCString() + 3);
+ ConstString fixed_name(fixed_scratch.c_str());
+
+ if (log)
+ log->Printf("Failed to find symbols given non-const name %s; trying %s", name.GetCString(), fixed_name.GetCString());
+
+ FindCodeSymbolInContext(
+ fixed_name, m_parser_vars->m_sym_ctx, eFunctionNameTypeAuto, sc_list);
+ sc_list_size = sc_list.GetSize();
+ }
+ }
+
+ lldb::addr_t intern_callable_load_addr = LLDB_INVALID_ADDRESS;
+
+ for (uint32_t i=0; i<sc_list_size; ++i)
+ {
+ SymbolContext sym_ctx;
+ sc_list.GetContextAtIndex(i, sym_ctx);
+
+
+ lldb::addr_t callable_load_addr = LLDB_INVALID_ADDRESS;
+
+ if (sym_ctx.function)
+ {
+ const Address func_so_addr = sym_ctx.function->GetAddressRange().GetBaseAddress();
+ if (func_so_addr.IsValid())
+ {
+ callable_load_addr = func_so_addr.GetCallableLoadAddress(target, false);
+ }
+ }
+ else if (sym_ctx.symbol)
+ {
+ if (sym_ctx.symbol->IsExternal())
+ callable_load_addr = sym_ctx.symbol->ResolveCallableAddress(*target);
+ else
+ {
+ if (intern_callable_load_addr == LLDB_INVALID_ADDRESS)
+ intern_callable_load_addr = sym_ctx.symbol->ResolveCallableAddress(*target);
+ }
+ }
+
+ if (callable_load_addr != LLDB_INVALID_ADDRESS)
+ {
+ func_addr = callable_load_addr;
+ return true;
+ }
+ }
+
+ // See if we found an internal symbol
+ if (intern_callable_load_addr != LLDB_INVALID_ADDRESS)
+ {
+ func_addr = intern_callable_load_addr;
+ return true;
+ }
+
+ return false;
+}
+
+addr_t
+ClangExpressionDeclMap::GetSymbolAddress (Target &target,
+ Process *process,
+ const ConstString &name,
+ lldb::SymbolType symbol_type,
+ lldb_private::Module *module)
+{
+ SymbolContextList sc_list;
+
+ if (module)
+ module->FindSymbolsWithNameAndType(name, symbol_type, sc_list);
+ else
+ target.GetImages().FindSymbolsWithNameAndType(name, symbol_type, sc_list);
+
+ const uint32_t num_matches = sc_list.GetSize();
+ addr_t symbol_load_addr = LLDB_INVALID_ADDRESS;
+
+ for (uint32_t i=0; i<num_matches && (symbol_load_addr == 0 || symbol_load_addr == LLDB_INVALID_ADDRESS); i++)
+ {
+ SymbolContext sym_ctx;
+ sc_list.GetContextAtIndex(i, sym_ctx);
+
+ const Address sym_address = sym_ctx.symbol->GetAddress();
+
+ if (!sym_address.IsValid())
+ continue;
+
+ switch (sym_ctx.symbol->GetType())
+ {
+ case eSymbolTypeCode:
+ case eSymbolTypeTrampoline:
+ symbol_load_addr = sym_address.GetCallableLoadAddress (&target);
+ break;
+
+ case eSymbolTypeResolver:
+ symbol_load_addr = sym_address.GetCallableLoadAddress (&target, true);
+ break;
+
+ case eSymbolTypeReExported:
+ {
+ ConstString reexport_name = sym_ctx.symbol->GetReExportedSymbolName();
+ if (reexport_name)
+ {
+ ModuleSP reexport_module_sp;
+ ModuleSpec reexport_module_spec;
+ reexport_module_spec.GetPlatformFileSpec() = sym_ctx.symbol->GetReExportedSymbolSharedLibrary();
+ if (reexport_module_spec.GetPlatformFileSpec())
+ {
+ reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec);
+ if (!reexport_module_sp)
+ {
+ reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear();
+ reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec);
+ }
+ }
+ symbol_load_addr = GetSymbolAddress(target, process, sym_ctx.symbol->GetReExportedSymbolName(), symbol_type, reexport_module_sp.get());
+ }
+ }
+ break;
+
+ case eSymbolTypeData:
+ case eSymbolTypeRuntime:
+ case eSymbolTypeVariable:
+ case eSymbolTypeLocal:
+ case eSymbolTypeParam:
+ case eSymbolTypeInvalid:
+ case eSymbolTypeAbsolute:
+ case eSymbolTypeException:
+ case eSymbolTypeSourceFile:
+ case eSymbolTypeHeaderFile:
+ case eSymbolTypeObjectFile:
+ case eSymbolTypeCommonBlock:
+ case eSymbolTypeBlock:
+ case eSymbolTypeVariableType:
+ case eSymbolTypeLineEntry:
+ case eSymbolTypeLineHeader:
+ case eSymbolTypeScopeBegin:
+ case eSymbolTypeScopeEnd:
+ case eSymbolTypeAdditional:
+ case eSymbolTypeCompiler:
+ case eSymbolTypeInstrumentation:
+ case eSymbolTypeUndefined:
+ case eSymbolTypeObjCClass:
+ case eSymbolTypeObjCMetaClass:
+ case eSymbolTypeObjCIVar:
+ symbol_load_addr = sym_address.GetLoadAddress (&target);
+ break;
+ }
+ }
+
+ if (symbol_load_addr == LLDB_INVALID_ADDRESS && process)
+ {
+ ObjCLanguageRuntime *runtime = process->GetObjCLanguageRuntime();
+
+ if (runtime)
+ {
+ symbol_load_addr = runtime->LookupRuntimeSymbol(name);
+ }
+ }
+
+ return symbol_load_addr;
+}
+
+addr_t
+ClangExpressionDeclMap::GetSymbolAddress (const ConstString &name, lldb::SymbolType symbol_type)
+{
+ assert (m_parser_vars.get());
+
+ if (!m_parser_vars->m_exe_ctx.GetTargetPtr())
+ return false;
+
+ return GetSymbolAddress(m_parser_vars->m_exe_ctx.GetTargetRef(), m_parser_vars->m_exe_ctx.GetProcessPtr(), name, symbol_type);
+}
+
+const Symbol *
+ClangExpressionDeclMap::FindGlobalDataSymbol (Target &target,
+ const ConstString &name,
+ lldb_private::Module *module)
+{
+ SymbolContextList sc_list;
+
+ if (module)
+ module->FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list);
+ else
+ target.GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list);
+
+ const uint32_t matches = sc_list.GetSize();
+ for (uint32_t i=0; i<matches; ++i)
+ {
+ SymbolContext sym_ctx;
+ sc_list.GetContextAtIndex(i, sym_ctx);
+ if (sym_ctx.symbol)
+ {
+ const Symbol *symbol = sym_ctx.symbol;
+ const Address sym_address = symbol->GetAddress();
+
+ if (sym_address.IsValid())
+ {
+ switch (symbol->GetType())
+ {
+ case eSymbolTypeData:
+ case eSymbolTypeRuntime:
+ case eSymbolTypeAbsolute:
+ case eSymbolTypeObjCClass:
+ case eSymbolTypeObjCMetaClass:
+ case eSymbolTypeObjCIVar:
+ if (symbol->GetDemangledNameIsSynthesized())
+ {
+ // If the demangled name was synthesized, then don't use it
+ // for expressions. Only let the symbol match if the mangled
+ // named matches for these symbols.
+ if (symbol->GetMangled().GetMangledName() != name)
+ break;
+ }
+ return symbol;
+
+ case eSymbolTypeReExported:
+ {
+ ConstString reexport_name = symbol->GetReExportedSymbolName();
+ if (reexport_name)
+ {
+ ModuleSP reexport_module_sp;
+ ModuleSpec reexport_module_spec;
+ reexport_module_spec.GetPlatformFileSpec() = symbol->GetReExportedSymbolSharedLibrary();
+ if (reexport_module_spec.GetPlatformFileSpec())
+ {
+ reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec);
+ if (!reexport_module_sp)
+ {
+ reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear();
+ reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec);
+ }
+ }
+ // Don't allow us to try and resolve a re-exported symbol if it is the same
+ // as the current symbol
+ if (name == symbol->GetReExportedSymbolName() && module == reexport_module_sp.get())
+ return NULL;
+
+ return FindGlobalDataSymbol(target, symbol->GetReExportedSymbolName(), reexport_module_sp.get());
+ }
+ }
+ break;
+
+ case eSymbolTypeCode: // We already lookup functions elsewhere
+ case eSymbolTypeVariable:
+ case eSymbolTypeLocal:
+ case eSymbolTypeParam:
+ case eSymbolTypeTrampoline:
+ case eSymbolTypeInvalid:
+ case eSymbolTypeException:
+ case eSymbolTypeSourceFile:
+ case eSymbolTypeHeaderFile:
+ case eSymbolTypeObjectFile:
+ case eSymbolTypeCommonBlock:
+ case eSymbolTypeBlock:
+ case eSymbolTypeVariableType:
+ case eSymbolTypeLineEntry:
+ case eSymbolTypeLineHeader:
+ case eSymbolTypeScopeBegin:
+ case eSymbolTypeScopeEnd:
+ case eSymbolTypeAdditional:
+ case eSymbolTypeCompiler:
+ case eSymbolTypeInstrumentation:
+ case eSymbolTypeUndefined:
+ case eSymbolTypeResolver:
+ break;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+lldb::VariableSP
+ClangExpressionDeclMap::FindGlobalVariable
+(
+ Target &target,
+ ModuleSP &module,
+ const ConstString &name,
+ CompilerDeclContext *namespace_decl,
+ TypeFromUser *type
+)
+{
+ VariableList vars;
+
+ if (module && namespace_decl)
+ module->FindGlobalVariables (name, namespace_decl, true, -1, vars);
+ else
+ target.GetImages().FindGlobalVariables(name, true, -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();
+}
+
+// Interface for ClangASTSource
+
+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));
+
+ if (GetImportInProgress())
+ {
+ if (log && log->GetVerbose())
+ log->Printf("Ignoring a query during an import");
+ return;
+ }
+
+ static unsigned int invocation_id = 0;
+ unsigned int current_id = invocation_id++;
+
+ if (log)
+ {
+ if (!context.m_decl_context)
+ log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in a NULL DeclContext", current_id, name.GetCString());
+ else if (const NamedDecl *context_named_decl = dyn_cast<NamedDecl>(context.m_decl_context))
+ log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in '%s'", current_id, name.GetCString(), context_named_decl->getNameAsString().c_str());
+ else
+ log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in a '%s'", current_id, name.GetCString(), context.m_decl_context->getDeclKindName());
+ }
+
+ if (const NamespaceDecl *namespace_context = dyn_cast<NamespaceDecl>(context.m_decl_context))
+ {
+ ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context);
+
+ if (log && log->GetVerbose())
+ log->Printf(" CEDM::FEVD[%u] Inspecting (NamespaceMap*)%p (%d entries)",
+ current_id, static_cast<void*>(namespace_map.get()),
+ (int)namespace_map->size());
+
+ if (!namespace_map)
+ return;
+
+ for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end();
+ i != e;
+ ++i)
+ {
+ if (log)
+ log->Printf(" CEDM::FEVD[%u] Searching namespace %s in module %s",
+ current_id,
+ i->second.GetName().AsCString(),
+ i->first->GetFileSpec().GetFilename().GetCString());
+
+ FindExternalVisibleDecls(context,
+ i->first,
+ i->second,
+ current_id);
+ }
+ }
+ else if (isa<TranslationUnitDecl>(context.m_decl_context))
+ {
+ CompilerDeclContext namespace_decl;
+
+ if (log)
+ log->Printf(" CEDM::FEVD[%u] Searching the root namespace", current_id);
+
+ FindExternalVisibleDecls(context,
+ lldb::ModuleSP(),
+ namespace_decl,
+ current_id);
+ }
+
+ if (!context.m_found.variable)
+ ClangASTSource::FindExternalVisibleDecls(context);
+}
+
+void
+ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context,
+ lldb::ModuleSP module_sp,
+ CompilerDeclContext &namespace_decl,
+ unsigned int current_id)
+{
+ assert (m_ast_context);
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ SymbolContextList sc_list;
+
+ const ConstString name(context.m_decl_name.getAsString().c_str());
+
+ const char *name_unique_cstr = name.GetCString();
+
+ if (name_unique_cstr == NULL)
+ return;
+
+ static ConstString id_name("id");
+ static ConstString Class_name("Class");
+
+ if (name == id_name || name == Class_name)
+ 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();
+ StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
+ SymbolContext sym_ctx;
+ if (frame != nullptr)
+ sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock);
+ if (name_unique_cstr[0] == '$' && !namespace_decl)
+ {
+ static ConstString g_lldb_class_name ("$__lldb_class");
+
+ if (name == g_lldb_class_name)
+ {
+ // Clang is looking for the type of "this"
+
+ if (frame == NULL)
+ return;
+
+
+ // Find the block that defines the function represented by "sym_ctx"
+ Block *function_block = sym_ctx.GetFunctionBlock();
+
+ if (!function_block)
+ return;
+
+ CompilerDeclContext function_decl_ctx = function_block->GetDeclContext();
+
+ if (!function_decl_ctx)
+ return;
+
+ clang::CXXMethodDecl *method_decl = ClangASTContext::DeclContextGetAsCXXMethodDecl(function_decl_ctx);
+
+ if (method_decl)
+ {
+ clang::CXXRecordDecl *class_decl = method_decl->getParent();
+
+ QualType class_qual_type(class_decl->getTypeForDecl(), 0);
+
+ TypeFromUser class_user_type (class_qual_type.getAsOpaquePtr(),
+ ClangASTContext::GetASTContext(&class_decl->getASTContext()));
+
+ if (log)
+ {
+ ASTDumper ast_dumper(class_qual_type);
+ log->Printf(" CEDM::FEVD[%u] Adding type for $__lldb_class: %s", current_id, ast_dumper.GetCString());
+ }
+
+ AddThisType(context, class_user_type, current_id);
+
+ if (method_decl->isInstance())
+ {
+ // self is a pointer to the object
+
+ QualType class_pointer_type = method_decl->getASTContext().getPointerType(class_qual_type);
+
+ TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(),
+ ClangASTContext::GetASTContext(&method_decl->getASTContext()));
+
+ 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.
+
+ VariableList *vars = frame->GetVariableList(false);
+
+ lldb::VariableSP this_var = vars->FindVariable(ConstString("this"));
+
+ if (this_var &&
+ this_var->IsInScope(frame) &&
+ this_var->LocationIsValidForFrame (frame))
+ {
+ Type *this_type = this_var->GetType();
+
+ if (!this_type)
+ return;
+
+ TypeFromUser pointee_type = this_type->GetForwardCompilerType ().GetPointeeType();
+
+ if (pointee_type.IsValid())
+ {
+ if (log)
+ {
+ ASTDumper ast_dumper(pointee_type);
+ log->Printf(" FEVD[%u] Adding type for $__lldb_class: %s", current_id, ast_dumper.GetCString());
+ }
+
+ AddThisType(context, pointee_type, current_id);
+ TypeFromUser this_user_type(this_type->GetFullCompilerType ());
+ m_struct_vars->m_object_pointer_type = this_user_type;
+ return;
+ }
+ }
+ }
+
+ return;
+ }
+
+ static ConstString g_lldb_objc_class_name ("$__lldb_objc_class");
+ if (name == g_lldb_objc_class_name)
+ {
+ // Clang is looking for the type of "*self"
+
+ if (!frame)
+ return;
+
+ SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock);
+
+ // Find the block that defines the function represented by "sym_ctx"
+ Block *function_block = sym_ctx.GetFunctionBlock();
+
+ if (!function_block)
+ return;
+
+ CompilerDeclContext function_decl_ctx = function_block->GetDeclContext();
+
+ if (!function_decl_ctx)
+ return;
+
+ clang::ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx);
+
+ if (method_decl)
+ {
+ ObjCInterfaceDecl* self_interface = method_decl->getClassInterface();
+
+ if (!self_interface)
+ return;
+
+ const clang::Type *interface_type = self_interface->getTypeForDecl();
+
+ if (!interface_type)
+ return; // This is unlikely, but we have seen crashes where this occurred
+
+ TypeFromUser class_user_type(QualType(interface_type, 0).getAsOpaquePtr(),
+ ClangASTContext::GetASTContext(&method_decl->getASTContext()));
+
+ if (log)
+ {
+ ASTDumper ast_dumper(interface_type);
+ log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString());
+ }
+
+ AddOneType(context, class_user_type, current_id);
+
+ if (method_decl->isInstanceMethod())
+ {
+ // self is a pointer to the object
+
+ QualType class_pointer_type = method_decl->getASTContext().getObjCObjectPointerType(QualType(interface_type, 0));
+
+ TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(),
+ ClangASTContext::GetASTContext(&method_decl->getASTContext()));
+
+ m_struct_vars->m_object_pointer_type = self_user_type;
+ }
+ else
+ {
+ // self is a Class pointer
+ QualType class_type = method_decl->getASTContext().getObjCClassType();
+
+ TypeFromUser self_user_type(class_type.getAsOpaquePtr(),
+ ClangASTContext::GetASTContext(&method_decl->getASTContext()));
+
+ 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.
+
+ VariableList *vars = frame->GetVariableList(false);
+
+ lldb::VariableSP self_var = vars->FindVariable(ConstString("self"));
+
+ if (self_var &&
+ self_var->IsInScope(frame) &&
+ self_var->LocationIsValidForFrame (frame))
+ {
+ Type *self_type = self_var->GetType();
+
+ if (!self_type)
+ return;
+
+ CompilerType self_clang_type = self_type->GetFullCompilerType ();
+
+ if (ClangASTContext::IsObjCClassType(self_clang_type))
+ {
+ return;
+ }
+ else if (ClangASTContext::IsObjCObjectPointerType(self_clang_type))
+ {
+ self_clang_type = self_clang_type.GetPointeeType();
+
+ if (!self_clang_type)
+ return;
+
+ if (log)
+ {
+ ASTDumper ast_dumper(self_type->GetFullCompilerType ());
+ log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString());
+ }
+
+ TypeFromUser class_user_type (self_clang_type);
+
+ AddOneType(context, class_user_type, current_id);
+
+ TypeFromUser self_user_type(self_type->GetFullCompilerType ());
+
+ m_struct_vars->m_object_pointer_type = self_user_type;
+ return;
+ }
+ }
+ }
+
+ return;
+ }
+
+ // any other $__lldb names should be weeded out now
+ if (!::strncmp(name_unique_cstr, "$__lldb", sizeof("$__lldb") - 1))
+ return;
+
+ do
+ {
+ if (!target)
+ break;
+
+ ClangASTContext *scratch_clang_ast_context = target->GetScratchClangASTContext();
+
+ if (!scratch_clang_ast_context)
+ break;
+
+ ASTContext *scratch_ast_context = scratch_clang_ast_context->getASTContext();
+
+ if (!scratch_ast_context)
+ break;
+
+ TypeDecl *ptype_type_decl = m_parser_vars->m_persistent_vars->GetPersistentType(name);
+
+ if (!ptype_type_decl)
+ break;
+
+ Decl *parser_ptype_decl = m_ast_importer_sp->CopyDecl(m_ast_context, scratch_ast_context, ptype_type_decl);
+
+ if (!parser_ptype_decl)
+ break;
+
+ TypeDecl *parser_ptype_type_decl = dyn_cast<TypeDecl>(parser_ptype_decl);
+
+ if (!parser_ptype_type_decl)
+ break;
+
+ if (log)
+ log->Printf(" CEDM::FEVD[%u] Found persistent type %s", current_id, name.GetCString());
+
+ context.AddNamedDecl(parser_ptype_type_decl);
+ } while (0);
+
+ ExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariable(name));
+
+ if (pvar_sp)
+ {
+ AddOneVariable(context, pvar_sp, current_id);
+ return;
+ }
+
+ const char *reg_name(&name.GetCString()[1]);
+
+ if (m_parser_vars->m_exe_ctx.GetRegisterContext())
+ {
+ const RegisterInfo *reg_info(m_parser_vars->m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName(reg_name));
+
+ if (reg_info)
+ {
+ if (log)
+ log->Printf(" CEDM::FEVD[%u] Found register %s", current_id, reg_info->name);
+
+ AddOneRegister(context, reg_info, current_id);
+ }
+ }
+ }
+ else
+ {
+ ValueObjectSP valobj;
+ VariableSP var;
+
+ if (frame && !namespace_decl)
+ {
+ 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
+ std::vector<CompilerDecl> found_decls = compiler_decl_context.FindDeclByName(name);
+
+ bool variable_found = false;
+ for (CompilerDecl decl : found_decls)
+ {
+ var = decl.GetAsVariable();
+ if (var)
+ {
+ variable_found = true;
+ valobj = ValueObjectVariable::Create(frame, var);
+ AddOneVariable(context, var, valobj, current_id);
+ context.m_found.variable = true;
+ }
+ }
+ if (variable_found)
+ return;
+ }
+ }
+ if (target)
+ {
+ var = FindGlobalVariable (*target,
+ module_sp,
+ name,
+ &namespace_decl,
+ NULL);
+
+ if (var)
+ {
+ valobj = ValueObjectVariable::Create(target, var);
+ AddOneVariable(context, var, valobj, current_id);
+ context.m_found.variable = true;
+ return;
+ }
+ }
+
+ std::vector<clang::NamedDecl *> decls_from_modules;
+
+ if (target)
+ {
+ if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor())
+ {
+ decl_vendor->FindDecls(name, false, UINT32_MAX, decls_from_modules);
+ }
+ }
+
+ if (!context.m_found.variable)
+ {
+ const bool include_inlines = false;
+ const bool append = false;
+
+ if (namespace_decl && module_sp)
+ {
+ const bool include_symbols = false;
+
+ module_sp->FindFunctions(name,
+ &namespace_decl,
+ eFunctionNameTypeBase,
+ include_symbols,
+ include_inlines,
+ append,
+ sc_list);
+ }
+ else if (target && !namespace_decl)
+ {
+ const bool include_symbols = true;
+
+ // TODO Fix FindFunctions so that it doesn't return
+ // instance methods for eFunctionNameTypeBase.
+
+ target->GetImages().FindFunctions(name,
+ eFunctionNameTypeFull,
+ include_symbols,
+ include_inlines,
+ append,
+ sc_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)
+ {
+ 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;
+ }
+
+ 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);
+ }
+
+ // 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));
+ }
+
+ // 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);
+
+ // Rejoin the lists with the functions in front.
+ sc_list = sc_func_list;
+ sc_list.Append(sc_sym_list);
+ }
+ }
+
+ if (sc_list.GetSize())
+ {
+ Symbol *extern_symbol = NULL;
+ Symbol *non_extern_symbol = NULL;
+
+ for (uint32_t index = 0, num_indices = sc_list.GetSize();
+ index < num_indices;
+ ++index)
+ {
+ SymbolContext sym_ctx;
+ sc_list.GetContextAtIndex(index, sym_ctx);
+
+ if (sym_ctx.function)
+ {
+ CompilerDeclContext decl_ctx = sym_ctx.function->GetDeclContext();
+
+ if (!decl_ctx)
+ continue;
+
+ // Filter out class/instance methods.
+ if (decl_ctx.IsClassMethod(nullptr, nullptr, nullptr))
+ continue;
+
+ AddOneFunction(context, sym_ctx.function, NULL, 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 == NULL)
+ 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<FunctionDecl>(m_ast_importer_sp->CopyDecl(m_ast_context, &decl->getASTContext(), 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, NULL, extern_symbol, current_id);
+ context.m_found.function = true;
+ }
+ else if (non_extern_symbol)
+ {
+ AddOneFunction (context, NULL, non_extern_symbol, current_id);
+ context.m_found.function = true;
+ }
+ }
+ }
+
+ if (!context.m_found.function_with_type_info)
+ {
+ // Try the modules next.
+
+ do
+ {
+ if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor())
+ {
+ bool append = false;
+ uint32_t max_matches = 1;
+ std::vector <clang::NamedDecl *> decls;
+
+ if (!modules_decl_vendor->FindDecls(name,
+ append,
+ max_matches,
+ decls))
+ break;
+
+ clang::NamedDecl *const decl_from_modules = decls[0];
+
+ if (llvm::isa<clang::FunctionDecl>(decl_from_modules))
+ {
+ if (log)
+ {
+ log->Printf(" CAS::FEVD[%u] Matching function found for \"%s\" in the modules",
+ current_id,
+ name.GetCString());
+ }
+
+ clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules);
+ clang::FunctionDecl *copied_function_decl = copied_decl ? dyn_cast<clang::FunctionDecl>(copied_decl) : nullptr;
+
+ if (!copied_function_decl)
+ {
+ if (log)
+ log->Printf(" CAS::FEVD[%u] - Couldn't export a function declaration from the modules",
+ current_id);
+
+ break;
+ }
+
+ 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);
+ }
+
+ context.AddNamedDecl(copied_function_decl);
+
+ context.m_found.function_with_type_info = true;
+ context.m_found.function = true;
+ }
+ else if (llvm::isa<clang::VarDecl>(decl_from_modules))
+ {
+ if (log)
+ {
+ log->Printf(" CAS::FEVD[%u] Matching variable found for \"%s\" in the modules",
+ current_id,
+ name.GetCString());
+ }
+
+ clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules);
+ clang::VarDecl *copied_var_decl = copied_decl ? dyn_cast_or_null<clang::VarDecl>(copied_decl) : nullptr;
+
+ if (!copied_var_decl)
+ {
+ if (log)
+ log->Printf(" CAS::FEVD[%u] - Couldn't export a variable declaration from the modules",
+ current_id);
+
+ break;
+ }
+
+ context.AddNamedDecl(copied_var_decl);
+
+ context.m_found.variable = true;
+ }
+ }
+ } while (0);
+ }
+
+ 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.
+
+ const Symbol *data_symbol = FindGlobalDataSymbol(*target, name);
+
+ 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;
+ }
+ }
+ }
+ }
+}
+
+//static opaque_compiler_type_t
+//MaybePromoteToBlockPointerType
+//(
+// ASTContext *ast_context,
+// opaque_compiler_type_t candidate_type
+//)
+//{
+// if (!candidate_type)
+// return candidate_type;
+//
+// QualType candidate_qual_type = QualType::getFromOpaquePtr(candidate_type);
+//
+// const PointerType *candidate_pointer_type = dyn_cast<PointerType>(candidate_qual_type);
+//
+// if (!candidate_pointer_type)
+// return candidate_type;
+//
+// QualType pointee_qual_type = candidate_pointer_type->getPointeeType();
+//
+// const RecordType *pointee_record_type = dyn_cast<RecordType>(pointee_qual_type);
+//
+// if (!pointee_record_type)
+// return candidate_type;
+//
+// RecordDecl *pointee_record_decl = pointee_record_type->getDecl();
+//
+// if (!pointee_record_decl->isRecord())
+// return candidate_type;
+//
+// if (!pointee_record_decl->getName().startswith(llvm::StringRef("__block_literal_")))
+// return candidate_type;
+//
+// QualType generic_function_type = ast_context->getFunctionNoProtoType(ast_context->UnknownAnyTy);
+// QualType block_pointer_type = ast_context->getBlockPointerType(generic_function_type);
+//
+// return block_pointer_type.getAsOpaquePtr();
+//}
+
+bool
+ClangExpressionDeclMap::GetVariableValue (VariableSP &var,
+ lldb_private::Value &var_location,
+ TypeFromUser *user_type,
+ TypeFromParser *parser_type)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ Type *var_type = var->GetType();
+
+ if (!var_type)
+ {
+ if (log)
+ log->PutCString("Skipped a definition because it has no type");
+ return false;
+ }
+
+ CompilerType var_clang_type = var_type->GetFullCompilerType ();
+
+ if (!var_clang_type)
+ {
+ if (log)
+ log->PutCString("Skipped a definition because it has no Clang type");
+ return false;
+ }
+
+ ClangASTContext *clang_ast = llvm::dyn_cast_or_null<ClangASTContext>(var_type->GetForwardCompilerType().GetTypeSystem());
+
+ if (!clang_ast)
+ {
+ if (log)
+ log->PutCString("Skipped a definition because it has no Clang AST");
+ 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;
+ }
+ //var_clang_type = MaybePromoteToBlockPointerType (ast, var_clang_type);
+
+ DWARFExpression &var_location_expr = var->LocationExpression();
+
+ Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
+ Error err;
+
+ if (var->GetLocationIsConstantValueData())
+ {
+ DataExtractor const_value_extractor;
+
+ if (var_location_expr.GetExpressionData(const_value_extractor))
+ {
+ var_location = Value(const_value_extractor.GetDataStart(), const_value_extractor.GetByteSize());
+ var_location.SetValueType(Value::eValueTypeHostAddress);
+ }
+ else
+ {
+ if (log)
+ log->Printf("Error evaluating constant variable: %s", err.AsCString());
+ return false;
+ }
+ }
+
+ CompilerType type_to_use = GuardedCopyType(var_clang_type);
+
+ if (!type_to_use)
+ {
+ if (log)
+ log->Printf("Couldn't copy a variable's type into the parser's AST context");
+
+ return false;
+ }
+
+ if (parser_type)
+ *parser_type = TypeFromParser(type_to_use);
+
+ if (var_location.GetContextType() == Value::eContextTypeInvalid)
+ var_location.SetCompilerType(type_to_use);
+
+ if (var_location.GetValueType() == Value::eValueTypeFileAddress)
+ {
+ SymbolContext var_sc;
+ var->CalculateSymbolContext(&var_sc);
+
+ if (!var_sc.module_sp)
+ return false;
+
+ Address so_addr(var_location.GetScalar().ULongLong(), var_sc.module_sp->GetSectionList());
+
+ lldb::addr_t load_addr = so_addr.GetLoadAddress(target);
+
+ if (load_addr != LLDB_INVALID_ADDRESS)
+ {
+ var_location.GetScalar() = load_addr;
+ var_location.SetValueType(Value::eValueTypeLoadAddress);
+ }
+ }
+
+ if (user_type)
+ *user_type = TypeFromUser(var_clang_type);
+
+ return true;
+}
+
+void
+ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP var, ValueObjectSP valobj, unsigned int current_id)
+{
+ assert (m_parser_vars.get());
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ TypeFromUser ut;
+ TypeFromParser pt;
+ Value var_location;
+
+ if (!GetVariableValue (var, var_location, &ut, &pt))
+ return;
+
+ clang::QualType parser_opaque_type = QualType::getFromOpaquePtr(pt.GetOpaqueQualType());
+
+ if (parser_opaque_type.isNull())
+ return;
+
+ if (const clang::Type *parser_type = parser_opaque_type.getTypePtr())
+ {
+ if (const TagType *tag_type = dyn_cast<TagType>(parser_type))
+ CompleteType(tag_type->getDecl());
+ if (const ObjCObjectPointerType *objc_object_ptr_type = dyn_cast<ObjCObjectPointerType>(parser_type))
+ CompleteType(objc_object_ptr_type->getInterfaceDecl());
+ }
+
+
+ bool is_reference = pt.IsReferenceType();
+
+ NamedDecl *var_decl = NULL;
+ if (is_reference)
+ var_decl = context.AddVarDecl(pt);
+ else
+ var_decl = context.AddVarDecl(pt.GetLValueReferenceType());
+
+ std::string decl_name(context.m_decl_name.getAsString());
+ ConstString entity_name(decl_name.c_str());
+ ClangExpressionVariable *entity(new ClangExpressionVariable(valobj));
+ m_found_entities.AddNewlyConstructedVariable(entity);
+
+ assert (entity);
+ entity->EnableParserVars(GetParserID());
+ ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID());
+ parser_vars->m_parser_type = pt;
+ parser_vars->m_named_decl = var_decl;
+ parser_vars->m_llvm_value = NULL;
+ parser_vars->m_lldb_value = var_location;
+ parser_vars->m_lldb_var = var;
+
+ if (is_reference)
+ entity->m_flags |= ClangExpressionVariable::EVTypeIsReference;
+
+ if (log)
+ {
+ ASTDumper orig_dumper(ut.GetOpaqueQualType());
+ ASTDumper ast_dumper(var_decl);
+ log->Printf(" CEDM::FEVD[%u] Found variable %s, returned %s (original %s)", current_id, decl_name.c_str(), ast_dumper.GetCString(), orig_dumper.GetCString());
+ }
+}
+
+void
+ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
+ ExpressionVariableSP &pvar_sp,
+ unsigned int current_id)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ TypeFromUser user_type (llvm::cast<ClangExpressionVariable>(pvar_sp.get())->GetTypeFromUser());
+
+ TypeFromParser parser_type (GuardedCopyType(user_type));
+
+ if (!parser_type.GetOpaqueQualType())
+ {
+ if (log)
+ log->Printf(" CEDM::FEVD[%u] Couldn't import type for pvar %s", current_id, pvar_sp->GetName().GetCString());
+ return;
+ }
+
+ NamedDecl *var_decl = context.AddVarDecl(parser_type.GetLValueReferenceType());
+
+ llvm::cast<ClangExpressionVariable>(pvar_sp.get())->EnableParserVars(GetParserID());
+ ClangExpressionVariable::ParserVars *parser_vars = llvm::cast<ClangExpressionVariable>(pvar_sp.get())->GetParserVars(GetParserID());
+ parser_vars->m_parser_type = parser_type;
+ parser_vars->m_named_decl = var_decl;
+ parser_vars->m_llvm_value = NULL;
+ parser_vars->m_lldb_value.Clear();
+
+ if (log)
+ {
+ ASTDumper ast_dumper(var_decl);
+ log->Printf(" CEDM::FEVD[%u] Added pvar %s, returned %s", current_id, pvar_sp->GetName().GetCString(), ast_dumper.GetCString());
+ }
+}
+
+void
+ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context,
+ const Symbol &symbol,
+ unsigned int current_id)
+{
+ assert(m_parser_vars.get());
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
+
+ if (target == NULL)
+ return;
+
+ ASTContext *scratch_ast_context = target->GetScratchClangASTContext()->getASTContext();
+
+ TypeFromUser user_type (ClangASTContext::GetBasicType(scratch_ast_context, eBasicTypeVoid).GetPointerType().GetLValueReferenceType());
+ TypeFromParser parser_type (ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid).GetPointerType().GetLValueReferenceType());
+ NamedDecl *var_decl = context.AddVarDecl(parser_type);
+
+ std::string decl_name(context.m_decl_name.getAsString());
+ ConstString entity_name(decl_name.c_str());
+ ClangExpressionVariable *entity(new ClangExpressionVariable(m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (),
+ entity_name,
+ user_type,
+ m_parser_vars->m_target_info.byte_order,
+ m_parser_vars->m_target_info.address_byte_size));
+ m_found_entities.AddNewlyConstructedVariable(entity);
+
+ entity->EnableParserVars(GetParserID());
+ ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID());
+
+ const Address symbol_address = symbol.GetAddress();
+ lldb::addr_t symbol_load_addr = symbol_address.GetLoadAddress(target);
+
+ //parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, user_type.GetOpaqueQualType());
+ parser_vars->m_lldb_value.SetCompilerType(user_type);
+ parser_vars->m_lldb_value.GetScalar() = symbol_load_addr;
+ parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress);
+
+ parser_vars->m_parser_type = parser_type;
+ parser_vars->m_named_decl = var_decl;
+ parser_vars->m_llvm_value = NULL;
+ parser_vars->m_lldb_sym = &symbol;
+
+ if (log)
+ {
+ ASTDumper ast_dumper(var_decl);
+
+ log->Printf(" 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();
+
+ ClangASTContext *scratch_ast_context = 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)
+ {
+ if (log)
+ log->Printf("Entity of unknown type does not have a VarDecl");
+ return false;
+ }
+
+ if (log)
+ {
+ ASTDumper ast_dumper(const_cast<VarDecl*>(var_decl));
+ log->Printf("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 = m_ast_importer_sp->CopyType(scratch_ast_context->getASTContext(), &var_decl->getASTContext(), var_type.getAsOpaquePtr());
+
+ if (!copied_type)
+ {
+ if (log)
+ log->Printf("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;
+}
+
+void
+ClangExpressionDeclMap::AddOneRegister (NameSearchContext &context,
+ const RegisterInfo *reg_info,
+ unsigned int current_id)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ CompilerType clang_type = ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (m_ast_context,
+ reg_info->encoding,
+ reg_info->byte_size * 8);
+
+ if (!clang_type)
+ {
+ if (log)
+ log->Printf(" Tried to add a type for %s, but couldn't get one", context.m_decl_name.getAsString().c_str());
+ return;
+ }
+
+ TypeFromParser parser_clang_type (clang_type);
+
+ NamedDecl *var_decl = context.AddVarDecl(parser_clang_type);
+
+ ClangExpressionVariable *entity(new ClangExpressionVariable(m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(),
+ m_parser_vars->m_target_info.byte_order,
+ m_parser_vars->m_target_info.address_byte_size));
+ m_found_entities.AddNewlyConstructedVariable(entity);
+
+ std::string decl_name(context.m_decl_name.getAsString());
+ entity->SetName (ConstString (decl_name.c_str()));
+ entity->SetRegisterInfo (reg_info);
+ entity->EnableParserVars(GetParserID());
+ ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID());
+ parser_vars->m_parser_type = parser_clang_type;
+ parser_vars->m_named_decl = var_decl;
+ parser_vars->m_llvm_value = NULL;
+ parser_vars->m_lldb_value.Clear();
+ entity->m_flags |= ClangExpressionVariable::EVBareRegister;
+
+ if (log)
+ {
+ ASTDumper ast_dumper(var_decl);
+ log->Printf(" CEDM::FEVD[%d] Added register %s, returned %s", current_id, context.m_decl_name.getAsString().c_str(), ast_dumper.GetCString());
+ }
+}
+
+void
+ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context,
+ Function* function,
+ Symbol* symbol,
+ unsigned int current_id)
+{
+ assert (m_parser_vars.get());
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ NamedDecl *function_decl = NULL;
+ Address fun_address;
+ CompilerType function_clang_type;
+
+ bool is_indirect_function = false;
+
+ if (function)
+ {
+ Type *function_type = function->GetType();
+
+ if (!function_type)
+ {
+ if (log)
+ log->PutCString(" Skipped a function because it has no type");
+ return;
+ }
+
+ function_clang_type = function_type->GetFullCompilerType ();
+
+ if (!function_clang_type)
+ {
+ if (log)
+ log->PutCString(" Skipped a function because it has no Clang type");
+ return;
+ }
+
+ fun_address = function->GetAddressRange().GetBaseAddress();
+
+ CompilerType copied_function_type = GuardedCopyType(function_clang_type);
+ if (copied_function_type)
+ {
+ function_decl = context.AddFunDecl(copied_function_type);
+
+ if (!function_decl)
+ {
+ if (log)
+ {
+ log->Printf (" Failed to create a function decl for '%s' {0x%8.8" PRIx64 "}",
+ function_type->GetName().GetCString(),
+ function_type->GetID());
+ }
+
+ return;
+ }
+ }
+ else
+ {
+ // We failed to copy the type we found
+ if (log)
+ {
+ log->Printf (" Failed to import the function type '%s' {0x%8.8" PRIx64 "} into the expression parser AST contenxt",
+ function_type->GetName().GetCString(),
+ function_type->GetID());
+ }
+
+ return;
+ }
+ }
+ else if (symbol)
+ {
+ fun_address = symbol->GetAddress();
+ function_decl = context.AddGenericFunDecl();
+ is_indirect_function = symbol->IsIndirect();
+ }
+ else
+ {
+ if (log)
+ log->PutCString(" AddOneFunction called with no function and no symbol");
+ return;
+ }
+
+ Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
+
+ lldb::addr_t load_addr = fun_address.GetCallableLoadAddress(target, is_indirect_function);
+
+ ClangExpressionVariable *entity(new ClangExpressionVariable (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (),
+ m_parser_vars->m_target_info.byte_order,
+ m_parser_vars->m_target_info.address_byte_size));
+ m_found_entities.AddNewlyConstructedVariable(entity);
+
+ std::string decl_name(context.m_decl_name.getAsString());
+ entity->SetName(ConstString(decl_name.c_str()));
+ entity->SetCompilerType (function_clang_type);
+ entity->EnableParserVars(GetParserID());
+
+ ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID());
+
+ if (load_addr != LLDB_INVALID_ADDRESS)
+ {
+ parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress);
+ parser_vars->m_lldb_value.GetScalar() = load_addr;
+ }
+ else
+ {
+ // We have to try finding a file address.
+
+ lldb::addr_t file_addr = fun_address.GetFileAddress();
+
+ parser_vars->m_lldb_value.SetValueType(Value::eValueTypeFileAddress);
+ parser_vars->m_lldb_value.GetScalar() = file_addr;
+ }
+
+
+ parser_vars->m_named_decl = function_decl;
+ parser_vars->m_llvm_value = NULL;
+
+ if (log)
+ {
+ ASTDumper ast_dumper(function_decl);
+
+ StreamString ss;
+
+ fun_address.Dump(&ss, m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription);
+
+ log->Printf(" CEDM::FEVD[%u] Found %s function %s (description %s), returned %s",
+ current_id,
+ (function ? "specific" : "generic"),
+ decl_name.c_str(),
+ ss.GetData(),
+ ast_dumper.GetCString());
+ }
+}
+
+void
+ClangExpressionDeclMap::AddThisType(NameSearchContext &context,
+ TypeFromUser &ut,
+ unsigned int current_id)
+{
+ CompilerType copied_clang_type = GuardedCopyType(ut);
+
+ if (!copied_clang_type)
+ {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ log->Printf("ClangExpressionDeclMap::AddThisType - Couldn't import the type");
+
+ return;
+ }
+
+ if (copied_clang_type.IsAggregateType() && copied_clang_type.GetCompleteType ())
+ {
+ CompilerType void_clang_type = ClangASTContext::GetBasicType(m_ast_context, 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,
+ copied_clang_type.GetTypeQualifiers());
+
+ const bool is_virtual = false;
+ const bool is_static = false;
+ const bool is_inline = false;
+ const bool is_explicit = false;
+ const bool is_attr_used = true;
+ const bool is_artificial = false;
+
+ ClangASTContext::GetASTContext(m_ast_context)->
+ AddMethodToCXXRecordType (copied_clang_type.GetOpaqueQualType(),
+ "$__lldb_expr",
+ method_type,
+ lldb::eAccessPublic,
+ is_virtual,
+ is_static,
+ is_inline,
+ is_explicit,
+ is_attr_used,
+ is_artificial);
+ }
+
+ if (!copied_clang_type.IsValid())
+ return;
+
+ TypeSourceInfo *type_source_info = m_ast_context->getTrivialTypeSourceInfo(QualType::getFromOpaquePtr(copied_clang_type.GetOpaqueQualType()));
+
+ if (!type_source_info)
+ return;
+
+ // Construct a typedef type because if "*this" is a templated type we can't just return ClassTemplateSpecializationDecls in response to name queries.
+ // Using a typedef makes this much more robust.
+
+ TypedefDecl *typedef_decl = TypedefDecl::Create(*m_ast_context,
+ m_ast_context->getTranslationUnitDecl(),
+ SourceLocation(),
+ SourceLocation(),
+ context.m_decl_name.getAsIdentifierInfo(),
+ type_source_info);
+
+
+ if (!typedef_decl)
+ return;
+
+ context.AddNamedDecl(typedef_decl);
+
+ return;
+}
+
+void
+ClangExpressionDeclMap::AddOneType(NameSearchContext &context,
+ TypeFromUser &ut,
+ unsigned int current_id)
+{
+ CompilerType copied_clang_type = GuardedCopyType(ut);
+
+ if (!copied_clang_type)
+ {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ log->Printf("ClangExpressionDeclMap::AddOneType - Couldn't import the type");
+
+ return;
+ }
+
+ context.AddTypeDecl(copied_clang_type);
+}
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
new file mode 100644
index 000000000000..b3f890c7acc7
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
@@ -0,0 +1,714 @@
+//===-- ClangExpressionDeclMap.h --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ClangExpressionDeclMap_h_
+#define liblldb_ClangExpressionDeclMap_h_
+
+// C Includes
+#include <signal.h>
+#include <stdint.h>
+
+// C++ Includes
+#include <vector>
+
+#include "ClangExpressionVariable.h"
+#include "ClangASTSource.h"
+
+// Other libraries and framework includes
+// Project includes
+#include "llvm/ADT/DenseMap.h"
+#include "clang/AST/Decl.h"
+#include "lldb/lldb-public.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Expression/Materializer.h"
+#include "lldb/Symbol/TaggedASTType.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/ExecutionContext.h"
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+/// @class ClangExpressionDeclMap ClangExpressionDeclMap.h "lldb/Expression/ClangExpressionDeclMap.h"
+/// @brief Manages named entities that are defined in LLDB's debug information.
+///
+/// The Clang parser uses the ClangASTSource as an interface to request named
+/// entities from outside an expression. The ClangASTSource reports back, listing
+/// all possible objects corresponding to a particular name. But it in turn
+/// relies on ClangExpressionDeclMap, which performs several important functions.
+///
+/// First, it records what variables and functions were looked up and what Decls
+/// were returned for them.
+///
+/// Second, it constructs a struct on behalf of IRForTarget, recording which
+/// variables should be placed where and relaying this information back so that
+/// IRForTarget can generate context-independent code.
+///
+/// Third, it "materializes" this struct on behalf of the expression command,
+/// finding the current values of each variable and placing them into the
+/// struct so that it can be passed to the JITted version of the IR.
+///
+/// Fourth and finally, it "dematerializes" the struct after the JITted code has
+/// has executed, placing the new values back where it found the old ones.
+//----------------------------------------------------------------------
+class ClangExpressionDeclMap :
+ public ClangASTSource
+{
+public:
+ //------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// Initializes class variables.
+ ///
+ /// @param[in] keep_result_in_memory
+ /// If true, inhibits the normal deallocation of the memory for
+ /// the result persistent variable, and instead marks the variable
+ /// as persisting.
+ ///
+ /// @param[in] 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.
+ //------------------------------------------------------------------
+ ClangExpressionDeclMap (bool keep_result_in_memory,
+ Materializer::PersistentVariableDelegate *result_delegate,
+ ExecutionContext &exe_ctx);
+
+ //------------------------------------------------------------------
+ /// Destructor
+ //------------------------------------------------------------------
+ ~ClangExpressionDeclMap() override;
+
+ //------------------------------------------------------------------
+ /// Enable the state needed for parsing and IR transformation.
+ ///
+ /// @param[in] exe_ctx
+ /// The execution context to use when finding types for variables.
+ /// Also used to find a "scratch" AST context to store result types.
+ ///
+ /// @param[in] materializer
+ /// If non-NULL, the materializer to populate with information about
+ /// the variables to use
+ ///
+ /// @return
+ /// True if parsing is possible; false if it is unsafe to continue.
+ //------------------------------------------------------------------
+ bool
+ WillParse (ExecutionContext &exe_ctx,
+ Materializer *materializer);
+
+ 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 ();
+
+ //------------------------------------------------------------------
+ /// [Used by IRForTarget] Add a variable to the list of persistent
+ /// variables for the process.
+ ///
+ /// @param[in] decl
+ /// The Clang declaration for the persistent variable, used for
+ /// lookup during parsing.
+ ///
+ /// @param[in] name
+ /// The name of the persistent variable, usually $something.
+ ///
+ /// @param[in] type
+ /// The type of the variable, in the Clang parser's context.
+ ///
+ /// @return
+ /// True on success; false otherwise.
+ //------------------------------------------------------------------
+ bool
+ AddPersistentVariable (const clang::NamedDecl *decl,
+ const ConstString &name,
+ TypeFromParser type,
+ bool is_result,
+ bool is_lvalue);
+
+ //------------------------------------------------------------------
+ /// [Used by IRForTarget] Add a variable to the struct that needs to
+ /// be materialized each time the expression runs.
+ ///
+ /// @param[in] decl
+ /// The Clang declaration for the variable.
+ ///
+ /// @param[in] name
+ /// The name of the variable.
+ ///
+ /// @param[in] value
+ /// The LLVM IR value for this variable.
+ ///
+ /// @param[in] size
+ /// The size of the variable in bytes.
+ ///
+ /// @param[in] alignment
+ /// The required alignment of the variable in bytes.
+ ///
+ /// @return
+ /// True on success; false otherwise.
+ //------------------------------------------------------------------
+ bool
+ AddValueToStruct (const clang::NamedDecl *decl,
+ const ConstString &name,
+ llvm::Value *value,
+ size_t size,
+ lldb::offset_t alignment);
+
+ //------------------------------------------------------------------
+ /// [Used by IRForTarget] Finalize the struct, laying out the position
+ /// of each object in it.
+ ///
+ /// @return
+ /// True on success; false otherwise.
+ //------------------------------------------------------------------
+ bool
+ DoStructLayout ();
+
+ //------------------------------------------------------------------
+ /// [Used by IRForTarget] Get general information about the laid-out
+ /// struct after DoStructLayout() has been called.
+ ///
+ /// @param[out] num_elements
+ /// The number of elements in the struct.
+ ///
+ /// @param[out] size
+ /// The size of the struct, in bytes.
+ ///
+ /// @param[out] alignment
+ /// The alignment of the struct, in bytes.
+ ///
+ /// @return
+ /// True if the information could be retrieved; false otherwise.
+ //------------------------------------------------------------------
+ bool
+ GetStructInfo (uint32_t &num_elements,
+ size_t &size,
+ lldb::offset_t &alignment);
+
+ //------------------------------------------------------------------
+ /// [Used by IRForTarget] Get specific information about one field
+ /// of the laid-out struct after DoStructLayout() has been called.
+ ///
+ /// @param[out] decl
+ /// The parsed Decl for the field, as generated by ClangASTSource
+ /// on ClangExpressionDeclMap's behalf. In the case of the result
+ /// value, this will have the name $__lldb_result even if the
+ /// result value ends up having the name $1. This is an
+ /// implementation detail of IRForTarget.
+ ///
+ /// @param[out] value
+ /// The IR value for the field (usually a GlobalVariable). In
+ /// the case of the result value, this will have the correct
+ /// name ($1, for instance). This is an implementation detail
+ /// of IRForTarget.
+ ///
+ /// @param[out] offset
+ /// The offset of the field from the beginning of the struct.
+ /// As long as the struct is aligned according to its required
+ /// alignment, this offset will align the field correctly.
+ ///
+ /// @param[out] name
+ /// The name of the field as used in materialization.
+ ///
+ /// @param[in] index
+ /// The index of the field about which information is requested.
+ ///
+ /// @return
+ /// True if the information could be retrieved; false otherwise.
+ //------------------------------------------------------------------
+ bool
+ GetStructElement (const clang::NamedDecl *&decl,
+ llvm::Value *&value,
+ lldb::offset_t &offset,
+ ConstString &name,
+ uint32_t index);
+
+ //------------------------------------------------------------------
+ /// [Used by IRForTarget] Get information about a function given its
+ /// Decl.
+ ///
+ /// @param[in] decl
+ /// The parsed Decl for the Function, as generated by ClangASTSource
+ /// on ClangExpressionDeclMap's behalf.
+ ///
+ /// @param[out] ptr
+ /// The absolute address of the function in the target.
+ ///
+ /// @return
+ /// True if the information could be retrieved; false otherwise.
+ //------------------------------------------------------------------
+ bool
+ GetFunctionInfo (const clang::NamedDecl *decl,
+ uint64_t &ptr);
+
+ //------------------------------------------------------------------
+ /// [Used by IRForTarget] Get the address of a function given nothing
+ /// but its name. Some functions are needed but didn't get Decls made
+ /// during parsing -- specifically, sel_registerName is never called
+ /// in the generated IR but we need to call it nonetheless.
+ ///
+ /// @param[in] name
+ /// The name of the function.
+ ///
+ /// @param[out] ptr
+ /// The absolute address of the function in the target.
+ ///
+ /// @return
+ /// True if the address could be retrieved; false otherwise.
+ //------------------------------------------------------------------
+ bool
+ GetFunctionAddress (const ConstString &name,
+ uint64_t &ptr);
+
+ //------------------------------------------------------------------
+ /// [Used by IRForTarget] Get the address of a symbol given nothing
+ /// but its name.
+ ///
+ /// @param[in] target
+ /// The target to find the symbol in. If not provided,
+ /// then the current parsing context's Target.
+ ///
+ /// @param[in] process
+ /// The process to use. For Objective-C symbols, the process's
+ /// Objective-C language runtime may be queried if the process
+ /// is non-NULL.
+ ///
+ /// @param[in] name
+ /// The name of the symbol.
+ ///
+ /// @param[in] module
+ /// The module to limit the search to. This can be NULL
+ ///
+ /// @return
+ /// Valid load address for the symbol
+ //------------------------------------------------------------------
+ lldb::addr_t
+ GetSymbolAddress (Target &target,
+ Process *process,
+ const ConstString &name,
+ lldb::SymbolType symbol_type,
+ Module *module = NULL);
+
+ lldb::addr_t
+ GetSymbolAddress (const 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;
+
+ TargetInfo() :
+ byte_order(lldb::eByteOrderInvalid),
+ address_byte_size(0)
+ {
+ }
+
+ bool IsValid()
+ {
+ return (byte_order != lldb::eByteOrderInvalid &&
+ address_byte_size != 0);
+ }
+ };
+ TargetInfo GetTargetInfo();
+
+ //------------------------------------------------------------------
+ /// [Used by ClangASTSource] Find all entities matching a given name,
+ /// using a NameSearchContext to make Decls for them.
+ ///
+ /// @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,
+ /// using a NameSearchContext to make Decls for them.
+ ///
+ /// @param[in] context
+ /// The NameSearchContext that can construct Decls for this name.
+ ///
+ /// @param[in] module
+ /// If non-NULL, the module to query.
+ ///
+ /// @param[in] namespace_decl
+ /// If valid and module is non-NULL, the parent namespace.
+ ///
+ /// @param[in] name
+ /// The name as a plain C string. The NameSearchContext contains
+ /// a DeclarationName for the name so at first the name may seem
+ /// redundant, but ClangExpressionDeclMap operates in RTTI land so
+ /// it can't access DeclarationName.
+ ///
+ /// @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);
+private:
+ ExpressionVariableList m_found_entities; ///< All entities that were looked up for the parser.
+ ExpressionVariableList m_struct_members; ///< All entities that need to be placed in the struct.
+ bool m_keep_result_in_memory; ///< True if result persistent variables generated by this expression should stay in memory.
+ Materializer::PersistentVariableDelegate *m_result_delegate; ///< If non-NULL, used to report expression results to ClangUserExpression.
+
+ //----------------------------------------------------------------------
+ /// The following values should not live beyond parsing
+ //----------------------------------------------------------------------
+ class ParserVars
+ {
+ public:
+ ParserVars(ClangExpressionDeclMap &decl_map) :
+ m_decl_map(decl_map)
+ {
+ }
+
+ Target *
+ GetTarget()
+ {
+ if (m_exe_ctx.GetTargetPtr())
+ return m_exe_ctx.GetTargetPtr();
+ else if (m_sym_ctx.target_sp)
+ m_sym_ctx.target_sp.get();
+ return NULL;
+ }
+
+ ExecutionContext m_exe_ctx; ///< The execution context to use when parsing.
+ SymbolContext m_sym_ctx; ///< The symbol context to use in finding variables and types.
+ ClangPersistentVariables *m_persistent_vars = nullptr; ///< The persistent variables for the process.
+ bool m_enable_lookups = false; ///< Set to true during parsing if we have found the first "$__lldb" name.
+ TargetInfo m_target_info; ///< Basic information about the target.
+ Materializer *m_materializer = nullptr; ///< If non-NULL, the materializer to use when reporting used variables.
+ clang::ASTConsumer *m_code_gen = nullptr; ///< If non-NULL, a code generator that receives new top-level functions.
+ private:
+ ClangExpressionDeclMap &m_decl_map;
+ DISALLOW_COPY_AND_ASSIGN (ParserVars);
+ };
+
+ std::unique_ptr<ParserVars> m_parser_vars;
+
+ //----------------------------------------------------------------------
+ /// Activate parser-specific variables
+ //----------------------------------------------------------------------
+ void
+ EnableParserVars()
+ {
+ if (!m_parser_vars.get())
+ m_parser_vars.reset(new ParserVars(*this));
+ }
+
+ //----------------------------------------------------------------------
+ /// Deallocate parser-specific variables
+ //----------------------------------------------------------------------
+ void
+ DisableParserVars()
+ {
+ m_parser_vars.reset();
+ }
+
+ //----------------------------------------------------------------------
+ /// The following values contain layout information for the materialized
+ /// struct, but are not specific to a single materialization
+ //----------------------------------------------------------------------
+ struct StructVars {
+ StructVars() :
+ m_struct_alignment(0),
+ m_struct_size(0),
+ m_struct_laid_out(false),
+ m_result_name(),
+ m_object_pointer_type(NULL, NULL)
+ {
+ }
+
+ lldb::offset_t m_struct_alignment; ///< The alignment of the struct in bytes.
+ size_t m_struct_size; ///< The size of the struct in bytes.
+ bool m_struct_laid_out; ///< True if the struct has been laid out and the layout is valid (that is, no new fields have been added since).
+ ConstString m_result_name; ///< The name of the result variable ($1, for example)
+ TypeFromUser m_object_pointer_type; ///< The type of the "this" variable, if one exists
+ };
+
+ std::unique_ptr<StructVars> m_struct_vars;
+
+ //----------------------------------------------------------------------
+ /// Activate struct variables
+ //----------------------------------------------------------------------
+ void
+ EnableStructVars()
+ {
+ if (!m_struct_vars.get())
+ m_struct_vars.reset(new struct StructVars);
+ }
+
+ //----------------------------------------------------------------------
+ /// Deallocate struct variables
+ //----------------------------------------------------------------------
+ void
+ DisableStructVars()
+ {
+ m_struct_vars.reset();
+ }
+
+ //----------------------------------------------------------------------
+ /// Get this parser's ID for use in extracting parser- and JIT-specific
+ /// data from persistent variables.
+ //----------------------------------------------------------------------
+ uint64_t
+ GetParserID()
+ {
+ return (uint64_t)this;
+ }
+
+ //------------------------------------------------------------------
+ /// Given a target, find a data symbol that has the given name.
+ ///
+ /// @param[in] target
+ /// The target to use as the basis for the search.
+ ///
+ /// @param[in] name
+ /// The name as a plain C string.
+ ///
+ /// @param[in] module
+ /// The module to limit the search to. This can be NULL
+ ///
+ /// @return
+ /// The LLDB Symbol found, or NULL if none was found.
+ //------------------------------------------------------------------
+ const Symbol *
+ FindGlobalDataSymbol (Target &target,
+ const ConstString &name,
+ Module *module = NULL);
+
+ //------------------------------------------------------------------
+ /// Given a target, find a variable that matches the given name and
+ /// type.
+ ///
+ /// @param[in] target
+ /// The target to use as a basis for finding the variable.
+ ///
+ /// @param[in] module
+ /// If non-NULL, the module to search.
+ ///
+ /// @param[in] name
+ /// The name as a plain C string.
+ ///
+ /// @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,
+ const ConstString &name,
+ CompilerDeclContext *namespace_decl,
+ TypeFromUser *type = NULL);
+
+ //------------------------------------------------------------------
+ /// Get the value of a variable in a given execution context and return
+ /// the associated Types if needed.
+ ///
+ /// @param[in] var
+ /// The variable to evaluate.
+ ///
+ /// @param[out] var_location
+ /// The variable location value to fill in
+ ///
+ /// @param[out] found_type
+ /// The type of the found value, as it was found in the user process.
+ /// This is only useful when the variable is being inspected on behalf
+ /// of the parser, hence the default.
+ ///
+ /// @param[out] parser_type
+ /// The type of the found value, as it was copied into the parser's
+ /// 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,
+ lldb_private::Value &var_location,
+ TypeFromUser *found_type = NULL,
+ TypeFromParser *parser_type = NULL);
+
+ //------------------------------------------------------------------
+ /// Use the NameSearchContext to generate a Decl for the given LLDB
+ /// Variable, and put it in the Tuple list.
+ ///
+ /// @param[in] context
+ /// The NameSearchContext to use when constructing the Decl.
+ ///
+ /// @param[in] var
+ /// The LLDB Variable that needs a Decl.
+ ///
+ /// @param[in] valobj
+ /// The LLDB ValueObject for that variable.
+ //------------------------------------------------------------------
+ void
+ AddOneVariable (NameSearchContext &context,
+ lldb::VariableSP var,
+ lldb::ValueObjectSP valobj,
+ unsigned int current_id);
+
+ //------------------------------------------------------------------
+ /// Use the NameSearchContext to generate a Decl for the given
+ /// persistent variable, and put it in the list of found entities.
+ ///
+ /// @param[in] context
+ /// The NameSearchContext to use when constructing the Decl.
+ ///
+ /// @param[in] pvar
+ /// The persistent variable that needs a Decl.
+ ///
+ /// @param[in] current_id
+ /// The ID of the current invocation of FindExternalVisibleDecls
+ /// for logging purposes.
+ //------------------------------------------------------------------
+ void
+ AddOneVariable (NameSearchContext &context,
+ lldb::ExpressionVariableSP &pvar_sp,
+ unsigned int current_id);
+
+ //------------------------------------------------------------------
+ /// 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);
+
+ //------------------------------------------------------------------
+ /// Use the NameSearchContext to generate a Decl for the given
+ /// function. (Functions are not placed in the Tuple list.) Can
+ /// handle both fully typed functions and generic functions.
+ ///
+ /// @param[in] context
+ /// The NameSearchContext to use when constructing the Decl.
+ ///
+ /// @param[in] fun
+ /// The Function that needs to be created. If non-NULL, this is
+ /// a fully-typed function.
+ ///
+ /// @param[in] sym
+ /// The Symbol that corresponds to a function that needs to be
+ /// created with generic type (unitptr_t foo(...)).
+ //------------------------------------------------------------------
+ void
+ AddOneFunction (NameSearchContext &context,
+ Function *fun,
+ Symbol *sym,
+ unsigned int current_id);
+
+ //------------------------------------------------------------------
+ /// Use the NameSearchContext to generate a Decl for the given
+ /// register.
+ ///
+ /// @param[in] context
+ /// The NameSearchContext to use when constructing the Decl.
+ ///
+ /// @param[in] reg_info
+ /// The information corresponding to that register.
+ //------------------------------------------------------------------
+ void
+ AddOneRegister (NameSearchContext &context,
+ const RegisterInfo *reg_info,
+ unsigned int current_id);
+
+ //------------------------------------------------------------------
+ /// Use the NameSearchContext to generate a Decl for the given
+ /// type. (Types are not placed in the Tuple list.)
+ ///
+ /// @param[in] context
+ /// The NameSearchContext to use when constructing the Decl.
+ ///
+ /// @param[in] type
+ /// The type that needs to be created.
+ //------------------------------------------------------------------
+ void
+ AddOneType (NameSearchContext &context,
+ TypeFromUser &type,
+ unsigned int current_id);
+
+ //------------------------------------------------------------------
+ /// Generate a Decl for "*this" and add a member function declaration
+ /// to it for the expression, then report it.
+ ///
+ /// @param[in] context
+ /// The NameSearchContext to use when constructing the Decl.
+ ///
+ /// @param[in] type
+ /// The type for *this.
+ //------------------------------------------------------------------
+ void
+ AddThisType(NameSearchContext &context,
+ TypeFromUser &type,
+ unsigned int current_id);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ClangExpressionDeclMap_h_
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h
new file mode 100644
index 000000000000..bb620def691f
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h
@@ -0,0 +1,79 @@
+//===-- ClangExpression.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ClangExpression_h_
+#define liblldb_ClangExpression_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+#include <map>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Expression/ExpressionTypeSystemHelper.h"
+
+namespace lldb_private {
+
+class RecordingMemoryManager;
+
+//----------------------------------------------------------------------
+// ClangExpressionHelper
+//----------------------------------------------------------------------
+class ClangExpressionHelper : public ExpressionTypeSystemHelper
+{
+public:
+ static bool classof(const ExpressionTypeSystemHelper *ts)
+ {
+ return ts->getKind() == eKindClangHelper;
+ }
+
+ ClangExpressionHelper () :
+ ExpressionTypeSystemHelper(ExpressionTypeSystemHelper::LLVMCastKind::eKindClangHelper)
+ {
+ }
+
+ //------------------------------------------------------------------
+ /// Destructor
+ //------------------------------------------------------------------
+ virtual ~ClangExpressionHelper ()
+ {
+ }
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should use when resolving external
+ /// values. May be NULL if everything should be self-contained.
+ //------------------------------------------------------------------
+ virtual ClangExpressionDeclMap *
+ DeclMap () = 0;
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should allow to access ASTs.
+ /// May be NULL if the ASTs do not need to be transformed.
+ ///
+ /// @param[in] passthrough
+ /// The ASTConsumer that the returned transformer should send
+ /// the ASTs to after transformation.
+ //------------------------------------------------------------------
+ virtual clang::ASTConsumer *
+ ASTTransformer (clang::ASTConsumer *passthrough) = 0;
+
+
+protected:
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ClangExpression_h_
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
new file mode 100644
index 000000000000..72c33fec8105
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -0,0 +1,657 @@
+//===-- ClangExpressionParser.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Version.h"
+#include "clang/CodeGen/CodeGenAction.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/FrontendPluginRegistry.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/ParseAST.h"
+#include "clang/Rewrite/Frontend/FrontendActions.h"
+#include "clang/Sema/SemaConsumer.h"
+#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/TargetSelect.h"
+
+#include "llvm/ExecutionEngine/MCJIT.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/Signals.h"
+
+// Project includes
+#include "ClangExpressionParser.h"
+
+#include "ClangASTSource.h"
+#include "ClangExpressionHelper.h"
+#include "ClangExpressionDeclMap.h"
+#include "ClangModulesDeclVendor.h"
+#include "ClangPersistentVariables.h"
+#include "IRForTarget.h"
+
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Expression/IRDynamicChecks.h"
+#include "lldb/Expression/IRInterpreter.h"
+#include "lldb/Host/File.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace clang;
+using namespace llvm;
+using namespace lldb_private;
+
+//===----------------------------------------------------------------------===//
+// Utility Methods for Clang
+//===----------------------------------------------------------------------===//
+
+std::string GetBuiltinIncludePath(const char *Argv0) {
+ SmallString<128> P(llvm::sys::fs::getMainExecutable(
+ Argv0, (void *)(intptr_t) GetBuiltinIncludePath));
+
+ if (!P.empty()) {
+ llvm::sys::path::remove_filename(P); // Remove /clang from foo/bin/clang
+ llvm::sys::path::remove_filename(P); // Remove /bin from foo/bin
+
+ // Get foo/lib/clang/<version>/include
+ llvm::sys::path::append(P, "lib", "clang", CLANG_VERSION_STRING,
+ "include");
+ }
+
+ return P.str();
+}
+
+class ClangExpressionParser::LLDBPreprocessorCallbacks : public PPCallbacks
+{
+ ClangModulesDeclVendor &m_decl_vendor;
+ ClangPersistentVariables &m_persistent_vars;
+ StreamString m_error_stream;
+ bool m_has_errors = false;
+
+public:
+ LLDBPreprocessorCallbacks(ClangModulesDeclVendor &decl_vendor,
+ ClangPersistentVariables &persistent_vars) :
+ m_decl_vendor(decl_vendor),
+ m_persistent_vars(persistent_vars)
+ {
+ }
+
+ void
+ moduleImport(SourceLocation import_location,
+ clang::ModuleIdPath path,
+ const clang::Module * /*null*/) override
+ {
+ std::vector<ConstString> string_path;
+
+ for (const std::pair<IdentifierInfo *, SourceLocation> &component : path)
+ {
+ string_path.push_back(ConstString(component.first->getName()));
+ }
+
+ StreamString error_stream;
+
+ ClangModulesDeclVendor::ModuleVector exported_modules;
+
+ if (!m_decl_vendor.AddModule(string_path, &exported_modules, m_error_stream))
+ {
+ m_has_errors = true;
+ }
+
+ for (ClangModulesDeclVendor::ModuleID module : exported_modules)
+ {
+ m_persistent_vars.AddHandLoadedClangModule(module);
+ }
+ }
+
+ bool hasErrors()
+ {
+ return m_has_errors;
+ }
+
+ const std::string &getErrorString()
+ {
+ return m_error_stream.GetString();
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// Implementation of ClangExpressionParser
+//===----------------------------------------------------------------------===//
+
+ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
+ Expression &expr,
+ bool generate_debug_info) :
+ ExpressionParser (exe_scope, expr, generate_debug_info),
+ m_compiler (),
+ m_code_generator (),
+ m_pp_callbacks(nullptr)
+{
+ // 1. Create a new compiler instance.
+ m_compiler.reset(new CompilerInstance());
+
+ // 2. Install the target.
+
+ lldb::TargetSP target_sp;
+ if (exe_scope)
+ target_sp = exe_scope->CalculateTarget();
+
+ // TODO: figure out what to really do when we don't have a valid target.
+ // Sometimes this will be ok to just use the host target triple (when we
+ // evaluate say "2+3", but other expressions like breakpoint conditions
+ // and other things that _are_ target specific really shouldn't just be
+ // using the host triple. This needs to be fixed in a better way.
+ if (target_sp && target_sp->GetArchitecture().IsValid())
+ {
+ std::string triple = target_sp->GetArchitecture().GetTriple().str();
+ m_compiler->getTargetOpts().Triple = triple;
+ }
+ else
+ {
+ m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple();
+ }
+
+ if (target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86 ||
+ target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86_64)
+ {
+ m_compiler->getTargetOpts().Features.push_back("+sse");
+ m_compiler->getTargetOpts().Features.push_back("+sse2");
+ }
+
+ // Any arm32 iOS environment, but not on arm64
+ if (m_compiler->getTargetOpts().Triple.find("arm64") == std::string::npos &&
+ m_compiler->getTargetOpts().Triple.find("arm") != std::string::npos &&
+ m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos)
+ {
+ m_compiler->getTargetOpts().ABI = "apcs-gnu";
+ }
+
+ m_compiler->createDiagnostics();
+
+ // Create the target instance.
+ m_compiler->setTarget(TargetInfo::CreateTargetInfo(
+ m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts));
+
+ assert (m_compiler->hasTarget());
+
+ // 3. Set options.
+
+ lldb::LanguageType language = expr.Language();
+
+ switch (language)
+ {
+ case lldb::eLanguageTypeC:
+ case lldb::eLanguageTypeC89:
+ case lldb::eLanguageTypeC99:
+ case lldb::eLanguageTypeC11:
+ // FIXME: the following language option is a temporary workaround,
+ // to "ask for C, get C++."
+ // For now, the expression parser must use C++ anytime the
+ // language is a C family language, because the expression parser
+ // uses features of C++ to capture values.
+ m_compiler->getLangOpts().CPlusPlus = true;
+ break;
+ case lldb::eLanguageTypeObjC:
+ m_compiler->getLangOpts().ObjC1 = true;
+ m_compiler->getLangOpts().ObjC2 = true;
+ // FIXME: the following language option is a temporary workaround,
+ // to "ask for ObjC, get ObjC++" (see comment above).
+ m_compiler->getLangOpts().CPlusPlus = true;
+ break;
+ case lldb::eLanguageTypeC_plus_plus:
+ case lldb::eLanguageTypeC_plus_plus_11:
+ case lldb::eLanguageTypeC_plus_plus_14:
+ m_compiler->getLangOpts().CPlusPlus11 = true;
+ m_compiler->getHeaderSearchOpts().UseLibcxx = true;
+ // fall thru ...
+ case lldb::eLanguageTypeC_plus_plus_03:
+ m_compiler->getLangOpts().CPlusPlus = true;
+ // FIXME: the following language option is a temporary workaround,
+ // to "ask for C++, get ObjC++". Apple hopes to remove this requirement
+ // on non-Apple platforms, but for now it is needed.
+ m_compiler->getLangOpts().ObjC1 = true;
+ break;
+ case lldb::eLanguageTypeObjC_plus_plus:
+ case lldb::eLanguageTypeUnknown:
+ default:
+ m_compiler->getLangOpts().ObjC1 = true;
+ m_compiler->getLangOpts().ObjC2 = true;
+ m_compiler->getLangOpts().CPlusPlus = true;
+ m_compiler->getLangOpts().CPlusPlus11 = true;
+ m_compiler->getHeaderSearchOpts().UseLibcxx = true;
+ break;
+ }
+
+ m_compiler->getLangOpts().Bool = true;
+ m_compiler->getLangOpts().WChar = true;
+ m_compiler->getLangOpts().Blocks = true;
+ m_compiler->getLangOpts().DebuggerSupport = true; // Features specifically for debugger clients
+ if (expr.DesiredResultType() == Expression::eResultTypeId)
+ m_compiler->getLangOpts().DebuggerCastResultToId = true;
+
+ m_compiler->getLangOpts().CharIsSigned =
+ ArchSpec(m_compiler->getTargetOpts().Triple.c_str()).CharIsSignedByDefault();
+
+ // Spell checking is a nice feature, but it ends up completing a
+ // lot of types that we didn't strictly speaking need to complete.
+ // As a result, we spend a long time parsing and importing debug
+ // information.
+ m_compiler->getLangOpts().SpellChecking = false;
+
+ lldb::ProcessSP process_sp;
+ if (exe_scope)
+ process_sp = exe_scope->CalculateProcess();
+
+ if (process_sp && m_compiler->getLangOpts().ObjC1)
+ {
+ if (process_sp->GetObjCLanguageRuntime())
+ {
+ if (process_sp->GetObjCLanguageRuntime()->GetRuntimeVersion() == ObjCLanguageRuntime::ObjCRuntimeVersions::eAppleObjC_V2)
+ m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7));
+ else
+ m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::FragileMacOSX, VersionTuple(10, 7));
+
+ if (process_sp->GetObjCLanguageRuntime()->HasNewLiteralsAndIndexing())
+ m_compiler->getLangOpts().DebuggerObjCLiteral = true;
+ }
+ }
+
+ m_compiler->getLangOpts().ThreadsafeStatics = false;
+ m_compiler->getLangOpts().AccessControl = false; // Debuggers get universal access
+ m_compiler->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name
+
+ // Set CodeGen options
+ m_compiler->getCodeGenOpts().EmitDeclMetadata = true;
+ m_compiler->getCodeGenOpts().InstrumentFunctions = false;
+ m_compiler->getCodeGenOpts().DisableFPElim = true;
+ m_compiler->getCodeGenOpts().OmitLeafFramePointer = false;
+ if (generate_debug_info)
+ m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::FullDebugInfo);
+ else
+ m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::NoDebugInfo);
+
+ // Disable some warnings.
+ m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError,
+ "unused-value", clang::diag::Severity::Ignored, SourceLocation());
+ m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError,
+ "odr", clang::diag::Severity::Ignored, SourceLocation());
+
+ // Inform the target of the language options
+ //
+ // FIXME: We shouldn't need to do this, the target should be immutable once
+ // created. This complexity should be lifted elsewhere.
+ m_compiler->getTarget().adjust(m_compiler->getLangOpts());
+
+ // 4. Set up the diagnostic buffer for reporting errors
+
+ m_compiler->getDiagnostics().setClient(new clang::TextDiagnosticBuffer);
+
+ // 5. Set up the source management objects inside the compiler
+
+ clang::FileSystemOptions file_system_options;
+ m_file_manager.reset(new clang::FileManager(file_system_options));
+
+ if (!m_compiler->hasSourceManager())
+ m_compiler->createSourceManager(*m_file_manager.get());
+
+ m_compiler->createFileManager();
+ m_compiler->createPreprocessor(TU_Complete);
+
+ if (ClangModulesDeclVendor *decl_vendor = target_sp->GetClangModulesDeclVendor())
+ {
+ ClangPersistentVariables *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_pp_callbacks = static_cast<LLDBPreprocessorCallbacks*>(pp_callbacks.get());
+ m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks));
+ }
+
+ // 6. Most of this we get from the CompilerInstance, but we
+ // also want to give the context an ExternalASTSource.
+ m_selector_table.reset(new SelectorTable());
+ m_builtin_context.reset(new Builtin::Context());
+
+ std::unique_ptr<clang::ASTContext> ast_context(new ASTContext(m_compiler->getLangOpts(),
+ m_compiler->getSourceManager(),
+ m_compiler->getPreprocessor().getIdentifierTable(),
+ *m_selector_table.get(),
+ *m_builtin_context.get()));
+
+ ast_context->InitBuiltinTypes(m_compiler->getTarget());
+
+ ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());
+ ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap();
+
+ if (decl_map)
+ {
+ llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source(decl_map->CreateProxy());
+ decl_map->InstallASTContext(ast_context.get());
+ ast_context->setExternalSource(ast_source);
+ }
+
+ m_ast_context.reset(new ClangASTContext(m_compiler->getTargetOpts().Triple.c_str()));
+ m_ast_context->setASTContext(ast_context.get());
+ m_compiler->setASTContext(ast_context.release());
+
+ std::string module_name("$__lldb_module");
+
+ m_llvm_context.reset(new LLVMContext());
+ m_code_generator.reset(CreateLLVMCodeGen(m_compiler->getDiagnostics(),
+ module_name,
+ m_compiler->getHeaderSearchOpts(),
+ m_compiler->getPreprocessorOpts(),
+ m_compiler->getCodeGenOpts(),
+ *m_llvm_context));
+}
+
+ClangExpressionParser::~ClangExpressionParser()
+{
+}
+
+unsigned
+ClangExpressionParser::Parse (Stream &stream)
+{
+ TextDiagnosticBuffer *diag_buf = static_cast<TextDiagnosticBuffer*>(m_compiler->getDiagnostics().getClient());
+
+ diag_buf->FlushDiagnostics (m_compiler->getDiagnostics());
+
+ const char *expr_text = m_expr.Text();
+
+ clang::SourceManager &SourceMgr = m_compiler->getSourceManager();
+ bool created_main_file = false;
+ if (m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo)
+ {
+ std::string temp_source_path;
+
+ int temp_fd = -1;
+ llvm::SmallString<PATH_MAX> result_path;
+ FileSpec tmpdir_file_spec;
+ if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
+ {
+ tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr");
+ temp_source_path = tmpdir_file_spec.GetPath();
+ llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path);
+ }
+ else
+ {
+ llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path);
+ }
+
+ if (temp_fd != -1)
+ {
+ lldb_private::File file (temp_fd, true);
+ const size_t expr_text_len = strlen(expr_text);
+ size_t bytes_written = expr_text_len;
+ if (file.Write(expr_text, bytes_written).Success())
+ {
+ if (bytes_written == expr_text_len)
+ {
+ file.Close();
+ SourceMgr.setMainFileID(SourceMgr.createFileID(
+ m_file_manager->getFile(result_path),
+ SourceLocation(), SrcMgr::C_User));
+ created_main_file = true;
+ }
+ }
+ }
+ }
+
+ if (!created_main_file)
+ {
+ std::unique_ptr<MemoryBuffer> memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__);
+ SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(memory_buffer)));
+ }
+
+ diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor());
+
+ ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());
+
+ ASTConsumer *ast_transformer = type_system_helper->ASTTransformer(m_code_generator.get());
+
+ if (ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap())
+ decl_map->InstallCodeGenerator(m_code_generator.get());
+
+ if (ast_transformer)
+ {
+ ast_transformer->Initialize(m_compiler->getASTContext());
+ ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext());
+ }
+ else
+ {
+ m_code_generator->Initialize(m_compiler->getASTContext());
+ ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext());
+ }
+
+ diag_buf->EndSourceFile();
+
+ TextDiagnosticBuffer::const_iterator diag_iterator;
+
+ int num_errors = 0;
+
+ if (m_pp_callbacks && m_pp_callbacks->hasErrors())
+ {
+ num_errors++;
+
+ stream.PutCString(m_pp_callbacks->getErrorString().c_str());
+ }
+
+ for (diag_iterator = diag_buf->warn_begin();
+ diag_iterator != diag_buf->warn_end();
+ ++diag_iterator)
+ stream.Printf("warning: %s\n", (*diag_iterator).second.c_str());
+
+ for (diag_iterator = diag_buf->err_begin();
+ diag_iterator != diag_buf->err_end();
+ ++diag_iterator)
+ {
+ num_errors++;
+ stream.Printf("error: %s\n", (*diag_iterator).second.c_str());
+ }
+
+ for (diag_iterator = diag_buf->note_begin();
+ diag_iterator != diag_buf->note_end();
+ ++diag_iterator)
+ stream.Printf("note: %s\n", (*diag_iterator).second.c_str());
+
+ if (!num_errors)
+ {
+ if (type_system_helper->DeclMap() && !type_system_helper->DeclMap()->ResolveUnknownTypes())
+ {
+ stream.Printf("error: Couldn't infer the type of a variable\n");
+ num_errors++;
+ }
+ }
+
+ return num_errors;
+}
+
+static bool FindFunctionInModule (ConstString &mangled_name,
+ llvm::Module *module,
+ const char *orig_name)
+{
+ for (llvm::Module::iterator fi = module->getFunctionList().begin(), fe = module->getFunctionList().end();
+ fi != fe;
+ ++fi)
+ {
+ if (fi->getName().str().find(orig_name) != std::string::npos)
+ {
+ mangled_name.SetCString(fi->getName().str().c_str());
+ return true;
+ }
+ }
+
+ return false;
+}
+
+Error
+ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
+ lldb::addr_t &func_end,
+ lldb::IRExecutionUnitSP &execution_unit_sp,
+ ExecutionContext &exe_ctx,
+ bool &can_interpret,
+ ExecutionPolicy execution_policy)
+{
+ func_addr = LLDB_INVALID_ADDRESS;
+ func_end = LLDB_INVALID_ADDRESS;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ Error err;
+
+ std::unique_ptr<llvm::Module> llvm_module_ap (m_code_generator->ReleaseModule());
+
+ if (!llvm_module_ap.get())
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("IR doesn't contain a module");
+ return err;
+ }
+
+ // Find the actual name of the function (it's often mangled somehow)
+
+ ConstString function_name;
+
+ if (!FindFunctionInModule(function_name, llvm_module_ap.get(), m_expr.FunctionName()))
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName());
+ return err;
+ }
+ else
+ {
+ if (log)
+ log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName());
+ }
+
+ execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here
+ llvm_module_ap, // handed off here
+ function_name,
+ exe_ctx.GetTargetSP(),
+ m_compiler->getTargetOpts().Features));
+
+ ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());
+ ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap(); // result can be NULL
+
+ if (decl_map)
+ {
+ Stream *error_stream = NULL;
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target)
+ error_stream = target->GetDebugger().GetErrorFile().get();
+
+ IRForTarget ir_for_target(decl_map,
+ m_expr.NeedsVariableResolution(),
+ *execution_unit_sp,
+ error_stream,
+ function_name.AsCString());
+
+ bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule());
+
+ Error interpret_error;
+ Process *process = exe_ctx.GetProcessPtr();
+
+ bool interpret_function_calls = !process ? false : process->CanInterpretFunctionCalls();
+ can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error, interpret_function_calls);
+
+
+ if (!ir_can_run)
+ {
+ err.SetErrorString("The expression could not be prepared to run in the target");
+ return err;
+ }
+
+ if (!can_interpret && execution_policy == eExecutionPolicyNever)
+ {
+ err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString());
+ return err;
+ }
+
+ if (!process && execution_policy == eExecutionPolicyAlways)
+ {
+ err.SetErrorString("Expression needed to run in the target, but the target can't be run");
+ return err;
+ }
+
+ if (execution_policy == eExecutionPolicyAlways || !can_interpret)
+ {
+ if (m_expr.NeedsValidation() && process)
+ {
+ if (!process->GetDynamicCheckers())
+ {
+ DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
+
+ StreamString install_errors;
+
+ if (!dynamic_checkers->Install(install_errors, exe_ctx))
+ {
+ if (install_errors.GetString().empty())
+ err.SetErrorString ("couldn't install checkers, unknown error");
+ else
+ err.SetErrorString (install_errors.GetString().c_str());
+
+ return err;
+ }
+
+ process->SetDynamicCheckers(dynamic_checkers);
+
+ if (log)
+ log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers ==");
+ }
+
+ IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString());
+
+ if (!ir_dynamic_checks.runOnModule(*execution_unit_sp->GetModule()))
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("Couldn't add dynamic checks to the expression");
+ return err;
+ }
+ }
+
+ execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
+ }
+ }
+ else
+ {
+ execution_unit_sp->GetRunnableInfo(err, func_addr, func_end);
+ }
+
+ return err;
+}
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
new file mode 100644
index 000000000000..3c055380b839
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
@@ -0,0 +1,136 @@
+//===-- ClangExpressionParser.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ClangExpressionParser_h_
+#define liblldb_ClangExpressionParser_h_
+
+#include "lldb/lldb-public.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Expression/ExpressionParser.h"
+
+#include <string>
+#include <vector>
+
+namespace lldb_private
+{
+
+class IRExecutionUnit;
+
+//----------------------------------------------------------------------
+/// @class ClangExpressionParser ClangExpressionParser.h "lldb/Expression/ClangExpressionParser.h"
+/// @brief Encapsulates an instance of Clang that can parse expressions.
+///
+/// ClangExpressionParser is responsible for preparing an instance of
+/// ClangExpression for execution. ClangExpressionParser uses ClangExpression
+/// as a glorified parameter list, performing the required parsing and
+/// conversion to formats (DWARF bytecode, or JIT compiled machine code)
+/// that can be executed.
+//----------------------------------------------------------------------
+class ClangExpressionParser : public ExpressionParser
+{
+public:
+ //------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// Initializes class variables.
+ ///
+ /// @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.
+ ///
+ /// @param[in] expr
+ /// The expression to be parsed.
+ //------------------------------------------------------------------
+ ClangExpressionParser (ExecutionContextScope *exe_scope,
+ Expression &expr,
+ bool generate_debug_info);
+
+ //------------------------------------------------------------------
+ /// Destructor
+ //------------------------------------------------------------------
+ ~ClangExpressionParser () override;
+
+ //------------------------------------------------------------------
+ /// Parse a single expression and convert it to IR using Clang. Don't
+ /// wrap the expression in anything at all.
+ ///
+ /// @param[in] stream
+ /// The stream to print errors to.
+ ///
+ /// @return
+ /// The number of errors encountered during parsing. 0 means
+ /// success.
+ //------------------------------------------------------------------
+ unsigned
+ Parse (Stream &stream) override;
+
+ //------------------------------------------------------------------
+ /// Ready an already-parsed expression for execution, possibly
+ /// evaluating it statically.
+ ///
+ /// @param[out] func_addr
+ /// The address to which the function has been written.
+ ///
+ /// @param[out] func_end
+ /// The end of the function's allocated memory region. (func_addr
+ /// and func_end do not delimit an allocated region; the allocated
+ /// region may begin before func_addr.)
+ ///
+ /// @param[in] execution_unit_sp
+ /// After parsing, ownership of the execution unit for
+ /// for the expression is handed to this shared pointer.
+ ///
+ /// @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
+ /// opportunistically.
+ ///
+ /// @return
+ /// An error code indicating the success or failure of the operation.
+ /// Test with Success().
+ //------------------------------------------------------------------
+ Error
+ PrepareForExecution (lldb::addr_t &func_addr,
+ lldb::addr_t &func_end,
+ lldb::IRExecutionUnitSP &execution_unit_sp,
+ ExecutionContext &exe_ctx,
+ bool &can_interpret,
+ lldb_private::ExecutionPolicy execution_policy) override;
+
+private:
+ std::unique_ptr<llvm::LLVMContext> m_llvm_context; ///< The LLVM context to generate IR into
+ std::unique_ptr<clang::FileManager> m_file_manager; ///< The Clang file manager object used by the compiler
+ std::unique_ptr<clang::CompilerInstance> m_compiler; ///< The Clang compiler used to parse expressions into IR
+ std::unique_ptr<clang::Builtin::Context> m_builtin_context; ///< Context for Clang built-ins
+ std::unique_ptr<clang::SelectorTable> m_selector_table; ///< Selector table for Objective-C methods
+ std::unique_ptr<clang::CodeGenerator> m_code_generator; ///< The Clang object that generates IR
+
+ class LLDBPreprocessorCallbacks;
+ LLDBPreprocessorCallbacks *m_pp_callbacks; ///< Called when the preprocessor encounters module imports
+ std::unique_ptr<ClangASTContext> m_ast_context;
+};
+
+}
+
+#endif // liblldb_ClangExpressionParser_h_
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp
new file mode 100644
index 000000000000..908546b3ecdb
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp
@@ -0,0 +1,76 @@
+//===-- ClangExpressionVariable.cpp -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangExpressionVariable.h"
+
+#include "clang/AST/ASTContext.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb_private;
+using namespace clang;
+
+const char *g_clang_expression_variable_kind_name = "ClangExpressionVariable";
+
+ClangExpressionVariable::ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size) :
+ ExpressionVariable(LLVMCastKind::eKindClang),
+ m_parser_vars(),
+ m_jit_vars ()
+{
+ m_flags = EVNone;
+ m_frozen_sp = ValueObjectConstResult::Create (exe_scope, byte_order, addr_byte_size);
+}
+
+ClangExpressionVariable::ClangExpressionVariable (ExecutionContextScope *exe_scope,
+ Value &value,
+ const ConstString &name,
+ uint16_t flags) :
+ ExpressionVariable(LLVMCastKind::eKindClang),
+ m_parser_vars(),
+ m_jit_vars ()
+{
+ m_flags = flags;
+ m_frozen_sp = ValueObjectConstResult::Create (exe_scope, value, name);
+}
+
+ClangExpressionVariable::ClangExpressionVariable (const lldb::ValueObjectSP &valobj_sp) :
+ ExpressionVariable(LLVMCastKind::eKindClang),
+ m_parser_vars(),
+ m_jit_vars ()
+{
+ m_flags = EVNone;
+ m_frozen_sp = valobj_sp;
+}
+
+ClangExpressionVariable::ClangExpressionVariable(ExecutionContextScope *exe_scope,
+ const ConstString &name,
+ const TypeFromUser& user_type,
+ lldb::ByteOrder byte_order,
+ uint32_t addr_byte_size) :
+ ExpressionVariable(LLVMCastKind::eKindClang),
+ m_parser_vars(),
+ m_jit_vars()
+{
+ m_flags = EVNone;
+ m_frozen_sp = ValueObjectConstResult::Create (exe_scope, byte_order, addr_byte_size);
+ SetName (name);
+ SetCompilerType (user_type);
+}
+
+TypeFromUser
+ClangExpressionVariable::GetTypeFromUser()
+{
+ TypeFromUser tfu (m_frozen_sp->GetCompilerType());
+ return tfu;
+}
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
new file mode 100644
index 000000000000..a4596148f6c7
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
@@ -0,0 +1,265 @@
+//===-- ClangExpressionVariable.h -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ClangExpressionVariable_h_
+#define liblldb_ClangExpressionVariable_h_
+
+// C Includes
+#include <signal.h>
+#include <stdint.h>
+#include <string.h>
+
+// C++ Includes
+#include <map>
+#include <string>
+#include <vector>
+
+// Other libraries and framework includes
+#include "llvm/Support/Casting.h"
+
+// Project includes
+#include "lldb/lldb-public.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Expression/ExpressionVariable.h"
+#include "lldb/Symbol/TaggedASTType.h"
+
+namespace llvm {
+ class Value;
+}
+
+namespace lldb_private {
+
+class ValueObjectConstResult;
+
+//----------------------------------------------------------------------
+/// @class ClangExpressionVariable ClangExpressionVariable.h "lldb/Expression/ClangExpressionVariable.h"
+/// @brief Encapsulates one variable for the expression parser.
+///
+/// The expression parser uses variables in three different contexts:
+///
+/// First, it stores persistent variables along with the process for use
+/// in expressions. These persistent variables contain their own data
+/// and are typed.
+///
+/// Second, in an interpreted expression, it stores the local variables
+/// for the expression along with the expression. These variables
+/// contain their own data and are typed.
+///
+/// Third, in a JIT-compiled expression, it stores the variables that
+/// the expression needs to have materialized and dematerialized at each
+/// execution. These do not contain their own data but are named and
+/// typed.
+///
+/// This class supports all of these use cases using simple type
+/// polymorphism, and provides necessary support methods. Its interface
+/// is RTTI-neutral.
+//----------------------------------------------------------------------
+class ClangExpressionVariable : public ExpressionVariable
+{
+public:
+ ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size);
+
+ ClangExpressionVariable (ExecutionContextScope *exe_scope,
+ Value &value,
+ const ConstString &name,
+ uint16_t flags = EVNone);
+
+ ClangExpressionVariable(const lldb::ValueObjectSP &valobj_sp);
+
+ ClangExpressionVariable(ExecutionContextScope *exe_scope,
+ const ConstString &name,
+ const TypeFromUser& user_type,
+ lldb::ByteOrder byte_order,
+ uint32_t addr_byte_size);
+
+ //----------------------------------------------------------------------
+ /// Utility functions for dealing with ExpressionVariableLists in Clang-specific ways
+ //----------------------------------------------------------------------
+
+ //----------------------------------------------------------------------
+ /// 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 *
+ FindVariableInList (ExpressionVariableList &list, const clang::NamedDecl *decl, uint64_t parser_id)
+ {
+ lldb::ExpressionVariableSP var_sp;
+ for (size_t index = 0, size = list.GetSize(); index < size; ++index)
+ {
+ var_sp = list.GetVariableAtIndex(index);
+
+ if (ClangExpressionVariable *clang_var = llvm::dyn_cast<ClangExpressionVariable>(var_sp.get()))
+ {
+ ClangExpressionVariable::ParserVars *parser_vars = clang_var->GetParserVars(parser_id);
+
+ if (parser_vars && parser_vars->m_named_decl == decl)
+ return clang_var;
+ }
+ }
+ return nullptr;
+ }
+
+ //----------------------------------------------------------------------
+ /// If the variable contains its own data, make a Value point at it.
+ /// If \a exe_ctx in not NULL, the value will be resolved in with
+ /// that execution context.
+ ///
+ /// @param[in] value
+ /// The value to point at the data.
+ ///
+ /// @param[in] exe_ctx
+ /// The execution context to use to resolve \a value.
+ ///
+ /// @return
+ /// True on success; false otherwise (in particular, if this variable
+ /// does not contain its own data).
+ //----------------------------------------------------------------------
+ bool
+ PointValueAtData(Value &value, ExecutionContext *exe_ctx);
+
+ //----------------------------------------------------------------------
+ /// The following values should not live beyond parsing
+ //----------------------------------------------------------------------
+ class ParserVars
+ {
+ public:
+
+ ParserVars() :
+ m_parser_type(),
+ m_named_decl (NULL),
+ m_llvm_value (NULL),
+ m_lldb_value (),
+ m_lldb_var (),
+ m_lldb_sym (NULL)
+ {
+ }
+
+ TypeFromParser m_parser_type; ///< The type of the variable according to the parser
+ const clang::NamedDecl *m_named_decl; ///< The Decl corresponding to this variable
+ llvm::Value *m_llvm_value; ///< The IR value corresponding to this variable; usually a GlobalValue
+ lldb_private::Value m_lldb_value; ///< The value found in LLDB for this variable
+ lldb::VariableSP m_lldb_var; ///< The original variable for this variable
+ const lldb_private::Symbol *m_lldb_sym; ///< The original symbol for this variable, if it was a symbol
+ };
+
+private:
+ typedef std::map <uint64_t, ParserVars> ParserVarMap;
+ ParserVarMap m_parser_vars;
+
+public:
+ //----------------------------------------------------------------------
+ /// Make this variable usable by the parser by allocating space for
+ /// parser-specific variables
+ //----------------------------------------------------------------------
+ void
+ EnableParserVars(uint64_t parser_id)
+ {
+ m_parser_vars.insert(std::make_pair(parser_id, ParserVars()));
+ }
+
+ //----------------------------------------------------------------------
+ /// Deallocate parser-specific variables
+ //----------------------------------------------------------------------
+ void
+ DisableParserVars(uint64_t parser_id)
+ {
+ m_parser_vars.erase(parser_id);
+ }
+
+ //----------------------------------------------------------------------
+ /// Access parser-specific variables
+ //----------------------------------------------------------------------
+ ParserVars *
+ GetParserVars(uint64_t parser_id)
+ {
+ ParserVarMap::iterator i = m_parser_vars.find(parser_id);
+
+ if (i == m_parser_vars.end())
+ return NULL;
+ else
+ return &i->second;
+ }
+
+ //----------------------------------------------------------------------
+ /// The following values are valid if the variable is used by JIT code
+ //----------------------------------------------------------------------
+ struct JITVars {
+ JITVars () :
+ m_alignment (0),
+ m_size (0),
+ m_offset (0)
+ {
+ }
+
+ lldb::offset_t m_alignment; ///< The required alignment of the variable, in bytes
+ size_t m_size; ///< The space required for the variable, in bytes
+ lldb::offset_t m_offset; ///< The offset of the variable in the struct, in bytes
+ };
+
+private:
+ typedef std::map <uint64_t, JITVars> JITVarMap;
+ JITVarMap m_jit_vars;
+
+public:
+ //----------------------------------------------------------------------
+ /// Make this variable usable for materializing for the JIT by allocating
+ /// space for JIT-specific variables
+ //----------------------------------------------------------------------
+ void
+ EnableJITVars(uint64_t parser_id)
+ {
+ m_jit_vars.insert(std::make_pair(parser_id, JITVars()));
+ }
+
+ //----------------------------------------------------------------------
+ /// Deallocate JIT-specific variables
+ //----------------------------------------------------------------------
+ void
+ DisableJITVars(uint64_t parser_id)
+ {
+ m_jit_vars.erase(parser_id);
+ }
+
+ JITVars *GetJITVars(uint64_t parser_id)
+ {
+ JITVarMap::iterator i = m_jit_vars.find(parser_id);
+
+ if (i == m_jit_vars.end())
+ return NULL;
+ else
+ return &i->second;
+ }
+
+ TypeFromUser
+ GetTypeFromUser ();
+
+ //------------------------------------------------------------------
+ // llvm casting support
+ //------------------------------------------------------------------
+ static bool classof(const ExpressionVariable *ev)
+ {
+ return ev->getKind() == ExpressionVariable::eKindClang;
+ }
+
+ //----------------------------------------------------------------------
+ /// Members
+ //----------------------------------------------------------------------
+ DISALLOW_COPY_AND_ASSIGN (ClangExpressionVariable);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ClangExpressionVariable_h_
diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
new file mode 100644
index 000000000000..0d0d7475a00e
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
@@ -0,0 +1,221 @@
+//===-- ClangFunctionCallerCaller.cpp ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangFunctionCaller.h"
+
+#include "ASTStructExtractor.h"
+#include "ClangExpressionParser.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/CodeGen/CodeGenAction.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/IR/Module.h"
+
+// Project includes
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectList.h"
+#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallFunction.h"
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ClangFunctionCaller constructor
+//----------------------------------------------------------------------
+ClangFunctionCaller::ClangFunctionCaller
+(
+ ExecutionContextScope &exe_scope,
+ const CompilerType &return_type,
+ const Address& functionAddress,
+ const ValueList &arg_value_list,
+ const char *name
+) :
+ FunctionCaller(exe_scope, return_type, functionAddress, arg_value_list, name),
+ m_type_system_helper (*this)
+{
+ m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess());
+ // Can't make a ClangFunctionCaller without a process.
+ assert (m_jit_process_wp.lock());
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ClangFunctionCaller::~ClangFunctionCaller()
+{
+}
+
+unsigned
+ClangFunctionCaller::CompileFunction (Stream &errors)
+{
+ if (m_compiled)
+ return 0;
+
+ // FIXME: How does clang tell us there's no return value? We need to handle that case.
+ unsigned num_errors = 0;
+
+ std::string return_type_str (m_function_return_type.GetTypeName().AsCString(""));
+
+ // Cons up the function we're going to wrap our call in, then compile it...
+ // We declare the function "extern "C"" because the compiler might be in C++
+ // mode which would mangle the name and then we couldn't find it again...
+ m_wrapper_function_text.clear();
+ m_wrapper_function_text.append ("extern \"C\" void ");
+ m_wrapper_function_text.append (m_wrapper_function_name);
+ m_wrapper_function_text.append (" (void *input)\n{\n struct ");
+ m_wrapper_function_text.append (m_wrapper_struct_name);
+ m_wrapper_function_text.append (" \n {\n");
+ m_wrapper_function_text.append (" ");
+ m_wrapper_function_text.append (return_type_str);
+ m_wrapper_function_text.append (" (*fn_ptr) (");
+
+ // Get the number of arguments. If we have a function type and it is prototyped,
+ // trust that, otherwise use the values we were given.
+
+ // FIXME: This will need to be extended to handle Variadic functions. We'll need
+ // to pull the defined arguments out of the function, then add the types from the
+ // arguments list for the variable arguments.
+
+ uint32_t num_args = UINT32_MAX;
+ bool trust_function = false;
+ // GetArgumentCount returns -1 for an unprototyped function.
+ CompilerType function_clang_type;
+ if (m_function_ptr)
+ {
+ function_clang_type = m_function_ptr->GetCompilerType();
+ if (function_clang_type)
+ {
+ int num_func_args = function_clang_type.GetFunctionArgumentCount();
+ if (num_func_args >= 0)
+ {
+ trust_function = true;
+ num_args = num_func_args;
+ }
+ }
+ }
+
+ if (num_args == UINT32_MAX)
+ num_args = m_arg_values.GetSize();
+
+ std::string args_buffer; // This one stores the definition of all the args in "struct caller".
+ std::string args_list_buffer; // This one stores the argument list called from the structure.
+ for (size_t i = 0; i < num_args; i++)
+ {
+ std::string type_name;
+
+ if (trust_function)
+ {
+ type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i).GetTypeName().AsCString("");
+ }
+ else
+ {
+ CompilerType clang_qual_type = m_arg_values.GetValueAtIndex(i)->GetCompilerType ();
+ if (clang_qual_type)
+ {
+ type_name = clang_qual_type.GetTypeName().AsCString("");
+ }
+ else
+ {
+ errors.Printf("Could not determine type of input value %" PRIu64 ".", (uint64_t)i);
+ return 1;
+ }
+ }
+
+ m_wrapper_function_text.append (type_name);
+ if (i < num_args - 1)
+ m_wrapper_function_text.append (", ");
+
+ char arg_buf[32];
+ args_buffer.append (" ");
+ args_buffer.append (type_name);
+ snprintf(arg_buf, 31, "arg_%" PRIu64, (uint64_t)i);
+ args_buffer.push_back (' ');
+ args_buffer.append (arg_buf);
+ args_buffer.append (";\n");
+
+ args_list_buffer.append ("__lldb_fn_data->");
+ args_list_buffer.append (arg_buf);
+ if (i < num_args - 1)
+ args_list_buffer.append (", ");
+
+ }
+ m_wrapper_function_text.append (");\n"); // Close off the function calling prototype.
+
+ m_wrapper_function_text.append (args_buffer);
+
+ m_wrapper_function_text.append (" ");
+ m_wrapper_function_text.append (return_type_str);
+ m_wrapper_function_text.append (" return_value;");
+ m_wrapper_function_text.append ("\n };\n struct ");
+ m_wrapper_function_text.append (m_wrapper_struct_name);
+ m_wrapper_function_text.append ("* __lldb_fn_data = (struct ");
+ m_wrapper_function_text.append (m_wrapper_struct_name);
+ m_wrapper_function_text.append (" *) input;\n");
+
+ m_wrapper_function_text.append (" __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr (");
+ m_wrapper_function_text.append (args_list_buffer);
+ m_wrapper_function_text.append (");\n}\n");
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ if (log)
+ log->Printf ("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str());
+
+ // Okay, now compile this expression
+
+ 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 (errors);
+ }
+ else
+ {
+ errors.Printf("no process - unable to inject function");
+ num_errors = 1;
+ }
+
+ m_compiled = (num_errors == 0);
+
+ if (!m_compiled)
+ return num_errors;
+
+ return num_errors;
+}
+
+clang::ASTConsumer *
+ClangFunctionCaller::ClangFunctionCallerHelper::ASTTransformer (clang::ASTConsumer *passthrough)
+{
+ m_struct_extractor.reset(new ASTStructExtractor(passthrough, m_owner.GetWrapperStructName(), m_owner));
+
+ return m_struct_extractor.get();
+}
diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h
new file mode 100644
index 000000000000..3e30f818a932
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h
@@ -0,0 +1,173 @@
+//===-- ClangFunctionCaller.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ClangFunctionCaller_h_
+#define liblldb_ClangFunctionCaller_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "ClangExpressionHelper.h"
+
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectList.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Target/Process.h"
+
+namespace lldb_private
+{
+
+class ASTStructExtractor;
+class ClangExpressionParser;
+
+//----------------------------------------------------------------------
+/// @class ClangFunctionCaller ClangFunctionCaller.h "lldb/Expression/ClangFunctionCaller.h"
+/// @brief Encapsulates a function that can be called.
+///
+/// A given ClangFunctionCaller object can handle a single function signature.
+/// Once constructed, it can set up any number of concurrent calls to
+/// functions with that signature.
+///
+/// It performs the call by synthesizing a structure that contains the pointer
+/// to the function and the arguments that should be passed to that function,
+/// and producing a special-purpose JIT-compiled function that accepts a void*
+/// pointing to this struct as its only argument and calls the function in the
+/// struct with the written arguments. This method lets Clang handle the
+/// vagaries of function calling conventions.
+///
+/// The simplest use of the ClangFunctionCaller is to construct it with a
+/// function representative of the signature you want to use, then call
+/// ExecuteFunction(ExecutionContext &, Stream &, Value &).
+///
+/// If you need to reuse the arguments for several calls, you can call
+/// InsertFunction() followed by WriteFunctionArguments(), which will return
+/// the location of the args struct for the wrapper function in args_addr_ref.
+///
+/// If you need to call the function on the thread plan stack, you can also
+/// call InsertFunction() followed by GetThreadPlanToCallFunction().
+///
+/// Any of the methods that take arg_addr_ptr or arg_addr_ref can be passed
+/// a pointer set to LLDB_INVALID_ADDRESS and new structure will be allocated
+/// and its address returned in that variable.
+///
+/// Any of the methods that take arg_addr_ptr can be passed NULL, and the
+/// argument space will be managed for you.
+//----------------------------------------------------------------------
+class ClangFunctionCaller : public FunctionCaller
+{
+ friend class ASTStructExtractor;
+
+ class ClangFunctionCallerHelper : public ClangExpressionHelper
+ {
+ public:
+ ClangFunctionCallerHelper (ClangFunctionCaller &owner) :
+ m_owner(owner)
+ {
+ }
+
+ ~ClangFunctionCallerHelper() override = default;
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should use when resolving external
+ /// values. May be NULL if everything should be self-contained.
+ //------------------------------------------------------------------
+ ClangExpressionDeclMap *
+ DeclMap() override
+ {
+ return NULL;
+ }
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should allow to access ASTs.
+ /// May be NULL if the ASTs do not need to be transformed.
+ ///
+ /// @param[in] passthrough
+ /// The ASTConsumer that the returned transformer should send
+ /// the ASTs to after transformation.
+ //------------------------------------------------------------------
+ clang::ASTConsumer *
+ ASTTransformer(clang::ASTConsumer *passthrough) override;
+
+ private:
+ ClangFunctionCaller &m_owner;
+ std::unique_ptr<ASTStructExtractor> m_struct_extractor; ///< The class that generates the argument struct layout.
+ };
+
+public:
+ //------------------------------------------------------------------
+ /// 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
+ /// defined in ast_context.
+ ///
+ /// @param[in] function_address
+ /// The address of the function to call.
+ ///
+ /// @param[in] arg_value_list
+ /// The default values to use when calling this function. Can
+ /// be overridden using WriteFunctionArguments().
+ //------------------------------------------------------------------
+ ClangFunctionCaller (ExecutionContextScope &exe_scope,
+ const CompilerType &return_type,
+ const Address& function_address,
+ const ValueList &arg_value_list,
+ const char *name);
+
+ ~ClangFunctionCaller() override;
+
+ //------------------------------------------------------------------
+ /// Compile the wrapper function
+ ///
+ /// @param[in] errors
+ /// The stream to print parser errors to.
+ ///
+ /// @return
+ /// The number of errors.
+ //------------------------------------------------------------------
+ unsigned
+ CompileFunction (Stream &errors) override;
+
+ ExpressionTypeSystemHelper *
+ GetTypeSystemHelper () override
+ {
+ return &m_type_system_helper;
+ }
+
+protected:
+ const char *GetWrapperStructName()
+ {
+ return m_wrapper_struct_name.c_str();
+ }
+
+private:
+ //------------------------------------------------------------------
+ // For ClangFunctionCaller only
+ //------------------------------------------------------------------
+
+ // Note: the parser needs to be destructed before the execution unit, so
+ // declare the execution unit first.
+ ClangFunctionCallerHelper m_type_system_helper;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ClangFunctionCaller_h_
diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
new file mode 100644
index 000000000000..05d8a320a5a4
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
@@ -0,0 +1,731 @@
+//===-- ClangModulesDeclVendor.cpp ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+#include <mutex>
+
+// Other libraries and framework includes
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Serialization/ASTReader.h"
+
+// Project includes
+#include "ClangModulesDeclVendor.h"
+
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/LLDBAssert.h"
+
+using namespace lldb_private;
+
+namespace {
+ // Any Clang compiler requires a consumer for diagnostics. This one stores them as strings
+ // so we can provide them to the user in case a module failed to load.
+ class StoringDiagnosticConsumer : public clang::DiagnosticConsumer
+ {
+ public:
+ StoringDiagnosticConsumer ();
+
+ void
+ HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel,
+ const clang::Diagnostic &info) override;
+
+ void
+ ClearDiagnostics ();
+
+ void
+ DumpDiagnostics (Stream &error_stream);
+
+ private:
+ typedef std::pair<clang::DiagnosticsEngine::Level, std::string> IDAndDiagnostic;
+ std::vector<IDAndDiagnostic> m_diagnostics;
+ Log * m_log;
+ };
+
+ // The private implementation of our ClangModulesDeclVendor. Contains all the Clang state required
+ // to load modules.
+ class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor
+ {
+ public:
+ ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> &diagnostics_engine,
+ llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> &compiler_invocation,
+ std::unique_ptr<clang::CompilerInstance> &&compiler_instance,
+ std::unique_ptr<clang::Parser> &&parser);
+
+ ~ClangModulesDeclVendorImpl() override = default;
+
+ bool
+ AddModule(ModulePath &path,
+ ModuleVector *exported_modules,
+ Stream &error_stream) override;
+
+ bool
+ AddModulesForCompileUnit(CompileUnit &cu,
+ ModuleVector &exported_modules,
+ Stream &error_stream) override;
+
+ uint32_t
+ FindDecls(const ConstString &name,
+ bool append,
+ uint32_t max_matches,
+ std::vector <clang::NamedDecl*> &decls) override;
+
+ void
+ ForEachMacro(const ModuleVector &modules,
+ std::function<bool (const std::string &)> handler) override;
+
+ private:
+ void
+ ReportModuleExportsHelper (std::set<ClangModulesDeclVendor::ModuleID> &exports,
+ clang::Module *module);
+
+ void
+ ReportModuleExports (ModuleVector &exports,
+ clang::Module *module);
+
+ clang::ModuleLoadResult
+ DoGetModule(clang::ModuleIdPath path, bool make_visible);
+
+ bool m_enabled = false;
+
+ llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> m_diagnostics_engine;
+ llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> m_compiler_invocation;
+ std::unique_ptr<clang::CompilerInstance> m_compiler_instance;
+ std::unique_ptr<clang::Parser> m_parser;
+ size_t m_source_location_index = 0; // used to give name components fake SourceLocations
+
+ typedef std::vector<ConstString> ImportedModule;
+ typedef std::map<ImportedModule, clang::Module *> ImportedModuleMap;
+ typedef std::set<ModuleID> ImportedModuleSet;
+ ImportedModuleMap m_imported_modules;
+ ImportedModuleSet m_user_imported_modules;
+ };
+} // anonymous namespace
+
+StoringDiagnosticConsumer::StoringDiagnosticConsumer ()
+{
+ m_log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
+}
+
+void
+StoringDiagnosticConsumer::HandleDiagnostic (clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info)
+{
+ llvm::SmallVector<char, 256> diagnostic_string;
+
+ info.FormatDiagnostic(diagnostic_string);
+
+ m_diagnostics.push_back(IDAndDiagnostic(DiagLevel, std::string(diagnostic_string.data(), diagnostic_string.size())));
+}
+
+void
+StoringDiagnosticConsumer::ClearDiagnostics ()
+{
+ m_diagnostics.clear();
+}
+
+void
+StoringDiagnosticConsumer::DumpDiagnostics (Stream &error_stream)
+{
+ for (IDAndDiagnostic &diag : m_diagnostics)
+ {
+ switch (diag.first)
+ {
+ default:
+ error_stream.PutCString(diag.second.c_str());
+ error_stream.PutChar('\n');
+ break;
+ case clang::DiagnosticsEngine::Level::Ignored:
+ break;
+ }
+ }
+}
+
+static FileSpec
+GetResourceDir ()
+{
+ static FileSpec g_cached_resource_dir;
+
+ static std::once_flag g_once_flag;
+
+ std::call_once(g_once_flag, [](){
+ HostInfo::GetLLDBPath (lldb::ePathTypeClangDir, g_cached_resource_dir);
+ });
+
+ return g_cached_resource_dir;
+}
+
+ClangModulesDeclVendor::ClangModulesDeclVendor()
+{
+}
+
+ClangModulesDeclVendor::~ClangModulesDeclVendor()
+{
+}
+
+ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> &diagnostics_engine,
+ llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> &compiler_invocation,
+ std::unique_ptr<clang::CompilerInstance> &&compiler_instance,
+ std::unique_ptr<clang::Parser> &&parser) :
+ ClangModulesDeclVendor(),
+ m_diagnostics_engine(diagnostics_engine),
+ m_compiler_invocation(compiler_invocation),
+ m_compiler_instance(std::move(compiler_instance)),
+ m_parser(std::move(parser)),
+ m_imported_modules()
+{
+}
+
+void
+ClangModulesDeclVendorImpl::ReportModuleExportsHelper (std::set<ClangModulesDeclVendor::ModuleID> &exports,
+ clang::Module *module)
+{
+ if (exports.count(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module)))
+ return;
+
+ exports.insert(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module));
+
+ llvm::SmallVector<clang::Module*, 2> sub_exports;
+
+ module->getExportedModules(sub_exports);
+
+ for (clang::Module *module : sub_exports)
+ {
+ ReportModuleExportsHelper(exports, module);
+ }
+}
+
+void
+ClangModulesDeclVendorImpl::ReportModuleExports (ClangModulesDeclVendor::ModuleVector &exports,
+ clang::Module *module)
+{
+ std::set<ClangModulesDeclVendor::ModuleID> exports_set;
+
+ ReportModuleExportsHelper(exports_set, module);
+
+ for (ModuleID module : exports_set)
+ {
+ exports.push_back(module);
+ }
+}
+
+bool
+ClangModulesDeclVendorImpl::AddModule(ModulePath &path,
+ ModuleVector *exported_modules,
+ Stream &error_stream)
+{
+ // Fail early.
+
+ if (m_compiler_instance->hadModuleLoaderFatalFailure())
+ {
+ error_stream.PutCString("error: Couldn't load a module because the module loader is in a fatal state.\n");
+ return false;
+ }
+
+ // Check if we've already imported this module.
+
+ std::vector<ConstString> imported_module;
+
+ for (ConstString path_component : path)
+ {
+ imported_module.push_back(path_component);
+ }
+
+ {
+ ImportedModuleMap::iterator mi = m_imported_modules.find(imported_module);
+
+ if (mi != m_imported_modules.end())
+ {
+ if (exported_modules)
+ {
+ ReportModuleExports(*exported_modules, mi->second);
+ }
+ return true;
+ }
+ }
+
+ if (!m_compiler_instance->getPreprocessor().getHeaderSearchInfo().lookupModule(path[0].GetStringRef()))
+ {
+ error_stream.Printf("error: Header search couldn't locate module %s\n", path[0].AsCString());
+ return false;
+ }
+
+ llvm::SmallVector<std::pair<clang::IdentifierInfo *, clang::SourceLocation>, 4> clang_path;
+
+ {
+ clang::SourceManager &source_manager = m_compiler_instance->getASTContext().getSourceManager();
+
+ for (ConstString path_component : path)
+ {
+ clang_path.push_back(std::make_pair(&m_compiler_instance->getASTContext().Idents.get(path_component.GetStringRef()),
+ source_manager.getLocForStartOfFile(source_manager.getMainFileID()).getLocWithOffset(m_source_location_index++)));
+ }
+ }
+
+ StoringDiagnosticConsumer *diagnostic_consumer = static_cast<StoringDiagnosticConsumer *>(m_compiler_instance->getDiagnostics().getClient());
+
+ diagnostic_consumer->ClearDiagnostics();
+
+ clang::Module *top_level_module = DoGetModule(clang_path.front(), false);
+
+ if (!top_level_module)
+ {
+ diagnostic_consumer->DumpDiagnostics(error_stream);
+ error_stream.Printf("error: Couldn't load top-level module %s\n", path[0].AsCString());
+ return false;
+ }
+
+ clang::Module *submodule = top_level_module;
+
+ for (size_t ci = 1; ci < path.size(); ++ci)
+ {
+ llvm::StringRef component = path[ci].GetStringRef();
+ submodule = submodule->findSubmodule(component.str());
+ if (!submodule)
+ {
+ diagnostic_consumer->DumpDiagnostics(error_stream);
+ error_stream.Printf("error: Couldn't load submodule %s\n", component.str().c_str());
+ return false;
+ }
+ }
+
+ clang::Module *requested_module = DoGetModule(clang_path, true);
+
+ if (requested_module != nullptr)
+ {
+ if (exported_modules)
+ {
+ ReportModuleExports(*exported_modules, requested_module);
+ }
+
+ m_imported_modules[imported_module] = requested_module;
+
+ m_enabled = true;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool
+ClangModulesDeclVendor::LanguageSupportsClangModules (lldb::LanguageType language)
+{
+ switch (language)
+ {
+ default:
+ return false;
+ // C++ and friends to be added
+ case lldb::LanguageType::eLanguageTypeC:
+ case lldb::LanguageType::eLanguageTypeC11:
+ case lldb::LanguageType::eLanguageTypeC89:
+ case lldb::LanguageType::eLanguageTypeC99:
+ case lldb::LanguageType::eLanguageTypeObjC:
+ return true;
+ }
+}
+
+bool
+ClangModulesDeclVendorImpl::AddModulesForCompileUnit(CompileUnit &cu,
+ ClangModulesDeclVendor::ModuleVector &exported_modules,
+ Stream &error_stream)
+{
+ if (LanguageSupportsClangModules(cu.GetLanguage()))
+ {
+ std::vector<ConstString> imported_modules = cu.GetImportedModules();
+
+ for (ConstString imported_module : imported_modules)
+ {
+ std::vector<ConstString> path;
+
+ path.push_back(imported_module);
+
+ if (!AddModule(path, &exported_modules, error_stream))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ return true;
+}
+
+// ClangImporter::lookupValue
+
+uint32_t
+ClangModulesDeclVendorImpl::FindDecls (const ConstString &name,
+ bool append,
+ uint32_t max_matches,
+ std::vector <clang::NamedDecl*> &decls)
+{
+ if (!m_enabled)
+ {
+ return 0;
+ }
+
+ if (!append)
+ decls.clear();
+
+ clang::IdentifierInfo &ident = m_compiler_instance->getASTContext().Idents.get(name.GetStringRef());
+
+ clang::LookupResult lookup_result(m_compiler_instance->getSema(),
+ clang::DeclarationName(&ident),
+ clang::SourceLocation(),
+ clang::Sema::LookupOrdinaryName);
+
+ m_compiler_instance->getSema().LookupName(lookup_result, m_compiler_instance->getSema().getScopeForContext(m_compiler_instance->getASTContext().getTranslationUnitDecl()));
+
+ uint32_t num_matches = 0;
+
+ for (clang::NamedDecl *named_decl : lookup_result)
+ {
+ if (num_matches >= max_matches)
+ return num_matches;
+
+ decls.push_back(named_decl);
+ ++num_matches;
+ }
+
+ return num_matches;
+}
+
+void
+ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVector &modules,
+ std::function<bool (const std::string &)> handler)
+{
+ if (!m_enabled)
+ {
+ return;
+ }
+
+ typedef std::map<ModuleID, ssize_t> ModulePriorityMap;
+ ModulePriorityMap module_priorities;
+
+ ssize_t priority = 0;
+
+ for (ModuleID module : modules)
+ {
+ module_priorities[module] = priority++;
+ }
+
+ if (m_compiler_instance->getPreprocessor().getExternalSource())
+ {
+ m_compiler_instance->getPreprocessor().getExternalSource()->ReadDefinedMacros();
+ }
+
+ for (clang::Preprocessor::macro_iterator mi = m_compiler_instance->getPreprocessor().macro_begin(),
+ me = m_compiler_instance->getPreprocessor().macro_end();
+ mi != me;
+ ++mi)
+ {
+ const clang::IdentifierInfo *ii = nullptr;
+
+ {
+ if (clang::IdentifierInfoLookup *lookup = m_compiler_instance->getPreprocessor().getIdentifierTable().getExternalIdentifierLookup())
+ {
+ lookup->get(mi->first->getName());
+ }
+ if (!ii)
+ {
+ ii = mi->first;
+ }
+ }
+
+ ssize_t found_priority = -1;
+ clang::MacroInfo *macro_info = nullptr;
+
+ for (clang::ModuleMacro *module_macro : m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii))
+ {
+ clang::Module *module = module_macro->getOwningModule();
+
+ {
+ ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast<ModuleID>(module));
+
+ if (pi != module_priorities.end() && pi->second > found_priority)
+ {
+ macro_info = module_macro->getMacroInfo();
+ found_priority = pi->second;
+ }
+ }
+
+ clang::Module *top_level_module = module->getTopLevelModule();
+
+ if (top_level_module != module)
+ {
+ ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast<ModuleID>(top_level_module));
+
+ if ((pi != module_priorities.end()) && pi->second > found_priority)
+ {
+ macro_info = module_macro->getMacroInfo();
+ found_priority = pi->second;
+ }
+ }
+ }
+
+ if (macro_info)
+ {
+ std::string macro_expansion = "#define ";
+ macro_expansion.append(mi->first->getName().str().c_str());
+
+ {
+ if (macro_info->isFunctionLike())
+ {
+ macro_expansion.append("(");
+
+ bool first_arg = true;
+
+ for (clang::MacroInfo::arg_iterator ai = macro_info->arg_begin(),
+ ae = macro_info->arg_end();
+ ai != ae;
+ ++ai)
+ {
+ if (!first_arg)
+ {
+ macro_expansion.append(", ");
+ }
+ else
+ {
+ first_arg = false;
+ }
+
+ macro_expansion.append((*ai)->getName().str());
+ }
+
+ if (macro_info->isC99Varargs())
+ {
+ if (first_arg)
+ {
+ macro_expansion.append("...");
+ }
+ else
+ {
+ macro_expansion.append(", ...");
+ }
+ }
+ else if (macro_info->isGNUVarargs())
+ {
+ macro_expansion.append("...");
+ }
+
+ macro_expansion.append(")");
+ }
+
+ macro_expansion.append(" ");
+
+ bool first_token = true;
+
+ for (clang::MacroInfo::tokens_iterator ti = macro_info->tokens_begin(),
+ te = macro_info->tokens_end();
+ ti != te;
+ ++ti)
+ {
+ if (!first_token)
+ {
+ macro_expansion.append(" ");
+ }
+ else
+ {
+ first_token = false;
+ }
+
+ if (ti->isLiteral())
+ {
+ if (const char *literal_data = ti->getLiteralData())
+ {
+ std::string token_str(literal_data, ti->getLength());
+ macro_expansion.append(token_str);
+ }
+ else
+ {
+ bool invalid = false;
+ const char *literal_source = m_compiler_instance->getSourceManager().getCharacterData(ti->getLocation(), &invalid);
+
+ if (invalid)
+ {
+ lldbassert(!"Unhandled token kind");
+ macro_expansion.append("<unknown literal value>");
+ }
+ else
+ {
+ macro_expansion.append(std::string(literal_source, ti->getLength()));
+ }
+ }
+ }
+ else if (const char *punctuator_spelling = clang::tok::getPunctuatorSpelling(ti->getKind()))
+ {
+ macro_expansion.append(punctuator_spelling);
+ }
+ else if (const char *keyword_spelling = clang::tok::getKeywordSpelling(ti->getKind()))
+ {
+ macro_expansion.append(keyword_spelling);
+ }
+ else
+ {
+ switch (ti->getKind())
+ {
+ case clang::tok::TokenKind::identifier:
+ macro_expansion.append(ti->getIdentifierInfo()->getName().str());
+ break;
+ case clang::tok::TokenKind::raw_identifier:
+ macro_expansion.append(ti->getRawIdentifier().str());
+ default:
+ macro_expansion.append(ti->getName());
+ break;
+ }
+ }
+ }
+
+ if (handler(macro_expansion))
+ {
+ return;
+ }
+ }
+ }
+ }
+}
+
+clang::ModuleLoadResult
+ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path,
+ bool make_visible)
+{
+ clang::Module::NameVisibilityKind visibility = make_visible ? clang::Module::AllVisible : clang::Module::Hidden;
+
+ const bool is_inclusion_directive = false;
+
+ return m_compiler_instance->loadModule(path.front().second, path, visibility, is_inclusion_directive);
+}
+
+static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer";
+
+lldb_private::ClangModulesDeclVendor *
+ClangModulesDeclVendor::Create(Target &target)
+{
+ // FIXME we should insure programmatically that the expression parser's compiler and the modules runtime's
+ // compiler are both initialized in the same way – preferably by the same code.
+
+ if (!target.GetPlatform()->SupportsModules())
+ return nullptr;
+
+ const ArchSpec &arch = target.GetArchitecture();
+
+ std::vector<std::string> compiler_invocation_arguments =
+ {
+ "-fmodules",
+ "-fcxx-modules",
+ "-fsyntax-only",
+ "-femit-all-decls",
+ "-target", arch.GetTriple().str(),
+ "-fmodules-validate-system-headers",
+ "-Werror=non-modular-include-in-framework-module"
+ };
+
+ target.GetPlatform()->AddClangModuleCompilationOptions(&target, compiler_invocation_arguments);
+
+ compiler_invocation_arguments.push_back(ModuleImportBufferName);
+
+ // Add additional search paths with { "-I", path } or { "-F", path } here.
+
+ {
+ llvm::SmallString<128> DefaultModuleCache;
+ const bool erased_on_reboot = false;
+ llvm::sys::path::system_temp_directory(erased_on_reboot, DefaultModuleCache);
+ llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang");
+ llvm::sys::path::append(DefaultModuleCache, "ModuleCache");
+ std::string module_cache_argument("-fmodules-cache-path=");
+ module_cache_argument.append(DefaultModuleCache.str().str());
+ compiler_invocation_arguments.push_back(module_cache_argument);
+ }
+
+ FileSpecList &module_search_paths = target.GetClangModuleSearchPaths();
+
+ for (size_t spi = 0, spe = module_search_paths.GetSize(); spi < spe; ++spi)
+ {
+ const FileSpec &search_path = module_search_paths.GetFileSpecAtIndex(spi);
+
+ std::string search_path_argument = "-I";
+ search_path_argument.append(search_path.GetPath());
+
+ compiler_invocation_arguments.push_back(search_path_argument);
+ }
+
+ {
+ FileSpec clang_resource_dir = GetResourceDir();
+
+ if (clang_resource_dir.IsDirectory())
+ {
+ compiler_invocation_arguments.push_back("-resource-dir");
+ compiler_invocation_arguments.push_back(clang_resource_dir.GetPath());
+ }
+ }
+
+ llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine = clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions,
+ new StoringDiagnosticConsumer);
+
+ std::vector<const char *> compiler_invocation_argument_cstrs;
+
+ for (const std::string &arg : compiler_invocation_arguments) {
+ compiler_invocation_argument_cstrs.push_back(arg.c_str());
+ }
+
+ llvm::IntrusiveRefCntPtr<clang::CompilerInvocation> invocation(clang::createInvocationFromCommandLine(compiler_invocation_argument_cstrs, diagnostics_engine));
+
+ if (!invocation)
+ return nullptr;
+
+ std::unique_ptr<llvm::MemoryBuffer> source_buffer = llvm::MemoryBuffer::getMemBuffer("extern int __lldb __attribute__((unavailable));",
+ ModuleImportBufferName);
+
+ invocation->getPreprocessorOpts().addRemappedFile(ModuleImportBufferName, source_buffer.release());
+
+ std::unique_ptr<clang::CompilerInstance> instance(new clang::CompilerInstance);
+
+ instance->setDiagnostics(diagnostics_engine.get());
+ instance->setInvocation(invocation.get());
+
+ std::unique_ptr<clang::FrontendAction> action(new clang::SyntaxOnlyAction);
+
+ instance->setTarget(clang::TargetInfo::CreateTargetInfo(*diagnostics_engine, instance->getInvocation().TargetOpts));
+
+ if (!instance->hasTarget())
+ return nullptr;
+
+ instance->getTarget().adjust(instance->getLangOpts());
+
+ if (!action->BeginSourceFile(*instance, instance->getFrontendOpts().Inputs[0]))
+ return nullptr;
+
+ instance->getPreprocessor().enableIncrementalProcessing();
+
+ instance->createModuleManager();
+
+ instance->createSema(action->getTranslationUnitKind(), nullptr);
+
+ const bool skipFunctionBodies = false;
+ std::unique_ptr<clang::Parser> parser(new clang::Parser(instance->getPreprocessor(), instance->getSema(), skipFunctionBodies));
+
+ instance->getPreprocessor().EnterMainSourceFile();
+ parser->Initialize();
+
+ clang::Parser::DeclGroupPtrTy parsed;
+
+ while (!parser->ParseTopLevelDecl(parsed));
+
+ return new ClangModulesDeclVendorImpl (diagnostics_engine, invocation, std::move(instance), std::move(parser));
+}
diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h
new file mode 100644
index 000000000000..df3b20550f9a
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h
@@ -0,0 +1,128 @@
+//===-- ClangModulesDeclVendor.h --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ClangModulesDeclVendor_h
+#define liblldb_ClangModulesDeclVendor_h
+
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Symbol/DeclVendor.h"
+#include "lldb/Target/Platform.h"
+
+#include <set>
+#include <vector>
+
+namespace lldb_private
+{
+
+class ClangModulesDeclVendor : public DeclVendor
+{
+public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ ClangModulesDeclVendor();
+
+ ~ClangModulesDeclVendor() override;
+
+ static ClangModulesDeclVendor *
+ Create(Target &target);
+
+ typedef std::vector<ConstString> ModulePath;
+ typedef uintptr_t ModuleID;
+ typedef std::vector<ModuleID> ModuleVector;
+
+ //------------------------------------------------------------------
+ /// Add a module to the list of modules to search.
+ ///
+ /// @param[in] path
+ /// The path to the exact module to be loaded. E.g., if the desired
+ /// module is std.io, then this should be { "std", "io" }.
+ ///
+ /// @param[in] exported_modules
+ /// If non-NULL, a pointer to a vector to populate with the ID of every
+ /// module that is re-exported by the specified module.
+ ///
+ /// @param[in] error_stream
+ /// A stream to populate with the output of the Clang parser when
+ /// it tries to load the module.
+ ///
+ /// @return
+ /// True if the module could be loaded; false if not. If the
+ /// compiler encountered a fatal error during a previous module
+ /// load, then this will always return false for this ModuleImporter.
+ //------------------------------------------------------------------
+ virtual bool
+ AddModule(ModulePath &path,
+ ModuleVector *exported_modules,
+ Stream &error_stream) = 0;
+
+ //------------------------------------------------------------------
+ /// Add all modules referred to in a given compilation unit to the list
+ /// of modules to search.
+ ///
+ /// @param[in] cu
+ /// The compilation unit to scan for imported modules.
+ ///
+ /// @param[in] exported_modules
+ /// A vector to populate with the ID of each module loaded (directly
+ /// and via re-exports) in this way.
+ ///
+ /// @param[in] error_stream
+ /// A stream to populate with the output of the Clang parser when
+ /// it tries to load the modules.
+ ///
+ /// @return
+ /// True if all modules referred to by the compilation unit could be
+ /// loaded; false if one could not be loaded. If the compiler
+ /// encountered a fatal error during a previous module
+ /// load, then this will always return false for this ModuleImporter.
+ //------------------------------------------------------------------
+ virtual bool
+ AddModulesForCompileUnit(CompileUnit &cu,
+ ModuleVector &exported_modules,
+ Stream &error_stream) = 0;
+
+ //------------------------------------------------------------------
+ /// Enumerate all the macros that are defined by a given set of modules
+ /// that are already imported.
+ ///
+ /// @param[in] modules
+ /// The unique IDs for all modules to query. Later modules have higher
+ /// priority, just as if you @imported them in that order. This matters
+ /// if module A #defines a macro and module B #undefs it.
+ ///
+ /// @param[in] handler
+ /// A function to call with the text of each #define (including the
+ /// #define directive). #undef directives are not included; we simply
+ /// elide any corresponding #define. If this function returns true,
+ /// we stop the iteration immediately.
+ //------------------------------------------------------------------
+ virtual void
+ ForEachMacro(const ModuleVector &modules,
+ std::function<bool (const std::string &)> handler) = 0;
+
+ //------------------------------------------------------------------
+ /// Query whether Clang supports modules for a particular language.
+ /// LLDB uses this to decide whether to try to find the modules loaded
+ /// by a gaiven compile unit.
+ ///
+ /// @param[in] language
+ /// The language to query for.
+ ///
+ /// @return
+ /// True if Clang has modules for the given language.
+ //------------------------------------------------------------------
+ static bool
+ LanguageSupportsClangModules (lldb::LanguageType language);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ClangModulesDeclVendor_h
diff --git a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
new file mode 100644
index 000000000000..9bf9d435d7ea
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp
@@ -0,0 +1,84 @@
+//===-- ClangPersistentVariables.cpp ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangPersistentVariables.h"
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Value.h"
+
+#include "llvm/ADT/StringMap.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+ClangPersistentVariables::ClangPersistentVariables () :
+ lldb_private::PersistentExpressionState(LLVMCastKind::eKindClang),
+ m_next_persistent_variable_id (0)
+{
+}
+
+ExpressionVariableSP
+ClangPersistentVariables::CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp)
+{
+ return AddNewlyConstructedVariable(new ClangExpressionVariable(valobj_sp));
+}
+
+ExpressionVariableSP
+ClangPersistentVariables::CreatePersistentVariable (ExecutionContextScope *exe_scope,
+ const ConstString &name,
+ const CompilerType& compiler_type,
+ lldb::ByteOrder byte_order,
+ uint32_t addr_byte_size)
+{
+ return AddNewlyConstructedVariable(new ClangExpressionVariable(exe_scope, name, compiler_type, byte_order, addr_byte_size));
+}
+
+void
+ClangPersistentVariables::RemovePersistentVariable (lldb::ExpressionVariableSP variable)
+{
+ RemoveVariable(variable);
+
+ const char *name = variable->GetName().AsCString();
+
+ if (*name != '$')
+ return;
+ name++;
+
+ if (strtoul(name, NULL, 0) == m_next_persistent_variable_id - 1)
+ m_next_persistent_variable_id--;
+}
+
+ConstString
+ClangPersistentVariables::GetNextPersistentVariableName ()
+{
+ char name_cstr[256];
+ ::snprintf (name_cstr, sizeof(name_cstr), "$%u", m_next_persistent_variable_id++);
+ ConstString name(name_cstr);
+ return name;
+}
+
+void
+ClangPersistentVariables::RegisterPersistentType (const ConstString &name,
+ clang::TypeDecl *type_decl)
+{
+ m_persistent_types.insert(std::pair<const char*, clang::TypeDecl*>(name.GetCString(), type_decl));
+}
+
+clang::TypeDecl *
+ClangPersistentVariables::GetPersistentType (const ConstString &name)
+{
+ PersistentTypeMap::const_iterator i = m_persistent_types.find(name.GetCString());
+
+ if (i == m_persistent_types.end())
+ return NULL;
+ else
+ return i->second;
+}
diff --git a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
new file mode 100644
index 000000000000..0e03d013d049
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
@@ -0,0 +1,106 @@
+//===-- ClangPersistentVariables.h ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ClangPersistentVariables_h_
+#define liblldb_ClangPersistentVariables_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/ADT/DenseMap.h"
+
+// Project includes
+#include "ClangExpressionVariable.h"
+#include "ClangModulesDeclVendor.h"
+
+#include "lldb/Expression/ExpressionVariable.h"
+
+namespace lldb_private
+{
+
+//----------------------------------------------------------------------
+/// @class ClangPersistentVariables ClangPersistentVariables.h "lldb/Expression/ClangPersistentVariables.h"
+/// @brief Manages persistent values that need to be preserved between expression invocations.
+///
+/// A list of variables that can be accessed and updated by any expression. See
+/// ClangPersistentVariable for more discussion. Also provides an increasing,
+/// 0-based counter for naming result variables.
+//----------------------------------------------------------------------
+class ClangPersistentVariables : public PersistentExpressionState
+{
+public:
+ ClangPersistentVariables();
+
+ ~ClangPersistentVariables() override = default;
+
+ //------------------------------------------------------------------
+ // llvm casting support
+ //------------------------------------------------------------------
+ static bool classof(const PersistentExpressionState *pv)
+ {
+ return pv->getKind() == PersistentExpressionState::eKindClang;
+ }
+
+ lldb::ExpressionVariableSP
+ CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp) override;
+
+ lldb::ExpressionVariableSP
+ CreatePersistentVariable (ExecutionContextScope *exe_scope,
+ const ConstString &name,
+ const CompilerType& compiler_type,
+ lldb::ByteOrder byte_order,
+ uint32_t addr_byte_size) override;
+
+ //----------------------------------------------------------------------
+ /// Return the next entry in the sequence of strings "$0", "$1", ... for
+ /// use naming persistent expression convenience variables.
+ ///
+ /// @return
+ /// A string that contains the next persistent variable name.
+ //----------------------------------------------------------------------
+ ConstString
+ GetNextPersistentVariableName () override;
+
+ void
+ RemovePersistentVariable (lldb::ExpressionVariableSP variable) override;
+
+ lldb::addr_t
+ LookupSymbol (const ConstString &name) override { return LLDB_INVALID_ADDRESS; }
+
+ void
+ RegisterPersistentType (const ConstString &name,
+ clang::TypeDecl *tag_decl);
+
+ clang::TypeDecl *
+ GetPersistentType (const ConstString &name);
+
+ void
+ AddHandLoadedClangModule(ClangModulesDeclVendor::ModuleID module)
+ {
+ m_hand_loaded_clang_modules.push_back(module);
+ }
+
+ const ClangModulesDeclVendor::ModuleVector &GetHandLoadedClangModules()
+ {
+ return m_hand_loaded_clang_modules;
+ }
+
+private:
+ uint32_t m_next_persistent_variable_id; ///< The counter used by GetNextResultName().
+
+ typedef llvm::DenseMap<const char *, clang::TypeDecl *> PersistentTypeMap;
+ PersistentTypeMap m_persistent_types; ///< The persistent types declared by the user.
+
+ ClangModulesDeclVendor::ModuleVector m_hand_loaded_clang_modules; ///< These are Clang modules we hand-loaded; these are the highest-
+ ///< priority source for macros.
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ClangPersistentVariables_h_
diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
new file mode 100644
index 000000000000..11f7f84ff5f1
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
@@ -0,0 +1,673 @@
+//===-- ClangUserExpression.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <cstdlib>
+#include <string>
+#include <map>
+
+#include "ClangUserExpression.h"
+
+#include "ASTResultSynthesizer.h"
+#include "ClangExpressionDeclMap.h"
+#include "ClangExpressionParser.h"
+#include "ClangModulesDeclVendor.h"
+#include "ClangPersistentVariables.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Expression/ExpressionSourceCode.h"
+#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Expression/IRInterpreter.h"
+#include "lldb/Expression/Materializer.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallUserExpression.h"
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+
+using namespace lldb_private;
+
+ClangUserExpression::ClangUserExpression (ExecutionContextScope &exe_scope,
+ const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ ResultType desired_type,
+ const EvaluateExpressionOptions &options) :
+ LLVMUserExpression (exe_scope, expr, expr_prefix, language, desired_type, options),
+ m_type_system_helper(*m_target_wp.lock().get())
+{
+ switch (m_language)
+ {
+ case lldb::eLanguageTypeC_plus_plus:
+ m_allow_cxx = true;
+ break;
+ case lldb::eLanguageTypeObjC:
+ m_allow_objc = true;
+ break;
+ case lldb::eLanguageTypeObjC_plus_plus:
+ default:
+ m_allow_cxx = true;
+ m_allow_objc = true;
+ break;
+ }
+}
+
+ClangUserExpression::~ClangUserExpression ()
+{
+}
+
+void
+ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ log->Printf("ClangUserExpression::ScanContext()");
+
+ m_target = exe_ctx.GetTargetPtr();
+
+ if (!(m_allow_cxx || m_allow_objc))
+ {
+ if (log)
+ log->Printf(" [CUE::SC] Settings inhibit C++ and Objective-C");
+ return;
+ }
+
+ StackFrame *frame = exe_ctx.GetFramePtr();
+ if (frame == NULL)
+ {
+ if (log)
+ log->Printf(" [CUE::SC] Null stack frame");
+ return;
+ }
+
+ SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | lldb::eSymbolContextBlock);
+
+ if (!sym_ctx.function)
+ {
+ if (log)
+ log->Printf(" [CUE::SC] Null function");
+ return;
+ }
+
+ // Find the block that defines the function represented by "sym_ctx"
+ Block *function_block = sym_ctx.GetFunctionBlock();
+
+ if (!function_block)
+ {
+ if (log)
+ log->Printf(" [CUE::SC] Null function block");
+ return;
+ }
+
+ CompilerDeclContext decl_context = function_block->GetDeclContext();
+
+ if (!decl_context)
+ {
+ if (log)
+ log->Printf(" [CUE::SC] Null decl context");
+ return;
+ }
+
+ if (clang::CXXMethodDecl *method_decl = ClangASTContext::DeclContextGetAsCXXMethodDecl(decl_context))
+ {
+ if (m_allow_cxx && method_decl->isInstance())
+ {
+ if (m_enforce_valid_object)
+ {
+ lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
+
+ const char *thisErrorString = "Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context";
+
+ if (!variable_list_sp)
+ {
+ err.SetErrorString(thisErrorString);
+ return;
+ }
+
+ lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this")));
+
+ if (!this_var_sp ||
+ !this_var_sp->IsInScope(frame) ||
+ !this_var_sp->LocationIsValidForFrame (frame))
+ {
+ err.SetErrorString(thisErrorString);
+ return;
+ }
+ }
+
+ m_in_cplusplus_method = true;
+ m_needs_object_ptr = true;
+ }
+ }
+ else if (clang::ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(decl_context))
+ {
+ if (m_allow_objc)
+ {
+ if (m_enforce_valid_object)
+ {
+ lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
+
+ const char *selfErrorString = "Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context";
+
+ if (!variable_list_sp)
+ {
+ err.SetErrorString(selfErrorString);
+ return;
+ }
+
+ lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self"));
+
+ if (!self_variable_sp ||
+ !self_variable_sp->IsInScope(frame) ||
+ !self_variable_sp->LocationIsValidForFrame (frame))
+ {
+ err.SetErrorString(selfErrorString);
+ return;
+ }
+ }
+
+ m_in_objectivec_method = true;
+ m_needs_object_ptr = true;
+
+ if (!method_decl->isInstanceMethod())
+ m_in_static_method = true;
+ }
+ }
+ else if (clang::FunctionDecl *function_decl = ClangASTContext::DeclContextGetAsFunctionDecl(decl_context))
+ {
+ // We might also have a function that said in the debug information that it captured an
+ // object pointer. The best way to deal with getting to the ivars at present is by pretending
+ // that this is a method of a class in whatever runtime the debug info says the object pointer
+ // belongs to. Do that here.
+
+ ClangASTMetadata *metadata = ClangASTContext::DeclContextGetMetaData (decl_context, function_decl);
+ if (metadata && metadata->HasObjectPtr())
+ {
+ lldb::LanguageType language = metadata->GetObjectPtrLanguage();
+ if (language == lldb::eLanguageTypeC_plus_plus)
+ {
+ if (m_enforce_valid_object)
+ {
+ lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
+
+ const char *thisErrorString = "Stopped in a context claiming to capture a C++ object pointer, but 'this' isn't available; pretending we are in a generic context";
+
+ if (!variable_list_sp)
+ {
+ err.SetErrorString(thisErrorString);
+ return;
+ }
+
+ lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this")));
+
+ if (!this_var_sp ||
+ !this_var_sp->IsInScope(frame) ||
+ !this_var_sp->LocationIsValidForFrame (frame))
+ {
+ err.SetErrorString(thisErrorString);
+ return;
+ }
+ }
+
+ m_in_cplusplus_method = true;
+ m_needs_object_ptr = true;
+ }
+ else if (language == lldb::eLanguageTypeObjC)
+ {
+ if (m_enforce_valid_object)
+ {
+ lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true));
+
+ const char *selfErrorString = "Stopped in a context claiming to capture an Objective-C object pointer, but 'self' isn't available; pretending we are in a generic context";
+
+ if (!variable_list_sp)
+ {
+ err.SetErrorString(selfErrorString);
+ return;
+ }
+
+ lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self"));
+
+ if (!self_variable_sp ||
+ !self_variable_sp->IsInScope(frame) ||
+ !self_variable_sp->LocationIsValidForFrame (frame))
+ {
+ err.SetErrorString(selfErrorString);
+ return;
+ }
+
+ Type *self_type = self_variable_sp->GetType();
+
+ if (!self_type)
+ {
+ err.SetErrorString(selfErrorString);
+ return;
+ }
+
+ CompilerType self_clang_type = self_type->GetForwardCompilerType ();
+
+ if (!self_clang_type)
+ {
+ err.SetErrorString(selfErrorString);
+ return;
+ }
+
+ if (ClangASTContext::IsObjCClassType(self_clang_type))
+ {
+ return;
+ }
+ else if (ClangASTContext::IsObjCObjectPointerType(self_clang_type))
+ {
+ m_in_objectivec_method = true;
+ m_needs_object_ptr = true;
+ }
+ else
+ {
+ err.SetErrorString(selfErrorString);
+ return;
+ }
+ }
+ else
+ {
+ m_in_objectivec_method = true;
+ m_needs_object_ptr = true;
+ }
+ }
+ }
+ }
+}
+
+// This is a really nasty hack, meant to fix Objective-C expressions of the form
+// (int)[myArray count]. Right now, because the type information for count is
+// not available, [myArray count] returns id, which can't be directly cast to
+// int without causing a clang error.
+static void
+ApplyObjcCastHack(std::string &expr)
+{
+#define OBJC_CAST_HACK_FROM "(int)["
+#define OBJC_CAST_HACK_TO "(int)(long long)["
+
+ size_t from_offset;
+
+ while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos)
+ expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO);
+
+#undef OBJC_CAST_HACK_TO
+#undef OBJC_CAST_HACK_FROM
+}
+
+bool
+ClangUserExpression::Parse (Stream &error_stream,
+ ExecutionContext &exe_ctx,
+ lldb_private::ExecutionPolicy execution_policy,
+ bool keep_result_in_memory,
+ bool generate_debug_info)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ Error err;
+
+ InstallContext(exe_ctx);
+
+ if (Target *target = exe_ctx.GetTargetPtr())
+ {
+ if (PersistentExpressionState *persistent_state = target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))
+ {
+ m_result_delegate.RegisterPersistentState(persistent_state);
+ }
+ else
+ {
+ error_stream.PutCString ("error: couldn't start parsing (no persistent data)");
+ return false;
+ }
+ }
+ else
+ {
+ error_stream.PutCString ("error: couldn't start parsing (no target)");
+ return false;
+ }
+
+ ScanContext(exe_ctx, err);
+
+ if (!err.Success())
+ {
+ error_stream.Printf("warning: %s\n", err.AsCString());
+ }
+
+ StreamString m_transformed_stream;
+
+ ////////////////////////////////////
+ // Generate the expression
+ //
+
+ ApplyObjcCastHack(m_expr_text);
+ //ApplyUnicharHack(m_expr_text);
+
+ std::string prefix = m_expr_prefix;
+
+ if (ClangModulesDeclVendor *decl_vendor = m_target->GetClangModulesDeclVendor())
+ {
+ const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = llvm::cast<ClangPersistentVariables>(m_target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))->GetHandLoadedClangModules();
+ ClangModulesDeclVendor::ModuleVector modules_for_macros;
+
+ for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules)
+ {
+ modules_for_macros.push_back(module);
+ }
+
+ if (m_target->GetEnableAutoImportClangModules())
+ {
+ if (StackFrame *frame = exe_ctx.GetFramePtr())
+ {
+ if (Block *block = frame->GetFrameBlock())
+ {
+ SymbolContext sc;
+
+ block->CalculateSymbolContext(&sc);
+
+ if (sc.comp_unit)
+ {
+ StreamString error_stream;
+
+ decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream);
+ }
+ }
+ }
+ }
+ }
+
+ std::unique_ptr<ExpressionSourceCode> source_code (ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str()));
+
+ lldb::LanguageType lang_type;
+
+ if (m_in_cplusplus_method)
+ lang_type = lldb::eLanguageTypeC_plus_plus;
+ else if (m_in_objectivec_method)
+ lang_type = lldb::eLanguageTypeObjC;
+ else
+ lang_type = lldb::eLanguageTypeC;
+
+ if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_in_static_method, exe_ctx))
+ {
+ error_stream.PutCString ("error: couldn't construct expression body");
+ return false;
+ }
+
+ if (log)
+ log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
+
+ ////////////////////////////////////
+ // Set up the target and compiler
+ //
+
+ Target *target = exe_ctx.GetTargetPtr();
+
+ if (!target)
+ {
+ error_stream.PutCString ("error: invalid target\n");
+ return false;
+ }
+
+ //////////////////////////
+ // Parse the expression
+ //
+
+ m_materializer_ap.reset(new Materializer());
+
+ ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory);
+
+ class OnExit
+ {
+ public:
+ typedef std::function <void (void)> Callback;
+
+ OnExit (Callback const &callback) :
+ m_callback(callback)
+ {
+ }
+
+ ~OnExit ()
+ {
+ m_callback();
+ }
+ private:
+ Callback m_callback;
+ };
+
+ OnExit on_exit([this]() { ResetDeclMap(); });
+
+ if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get()))
+ {
+ error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
+
+ ResetDeclMap(); // We are being careful here in the case of breakpoint conditions.
+
+ return false;
+ }
+
+ Process *process = exe_ctx.GetProcessPtr();
+ ExecutionContextScope *exe_scope = process;
+
+ if (!exe_scope)
+ exe_scope = exe_ctx.GetTargetPtr();
+
+ ClangExpressionParser parser(exe_scope, *this, generate_debug_info);
+
+ unsigned num_errors = parser.Parse (error_stream);
+
+ if (num_errors)
+ {
+ error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
+
+ ResetDeclMap(); // We are being careful here in the case of breakpoint conditions.
+
+ return false;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+ // Prepare the output of the parser for execution, evaluating it statically if possible
+ //
+
+ Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
+ m_jit_end_addr,
+ m_execution_unit_sp,
+ exe_ctx,
+ m_can_interpret,
+ execution_policy);
+
+ if (generate_debug_info)
+ {
+ lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
+
+ if (jit_module_sp)
+ {
+ ConstString const_func_name(FunctionName());
+ FileSpec jit_file;
+ jit_file.GetFilename() = const_func_name;
+ jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
+ m_jit_module_wp = jit_module_sp;
+ target->GetImages().Append(jit_module_sp);
+ }
+// lldb_private::ObjectFile *jit_obj_file = jit_module_sp->GetObjectFile();
+// StreamFile strm (stdout, false);
+// if (jit_obj_file)
+// {
+// jit_obj_file->GetSectionList();
+// jit_obj_file->GetSymtab();
+// jit_obj_file->Dump(&strm);
+// }
+// lldb_private::SymbolVendor *jit_sym_vendor = jit_module_sp->GetSymbolVendor();
+// if (jit_sym_vendor)
+// {
+// lldb_private::SymbolContextList sc_list;
+// jit_sym_vendor->FindFunctions(const_func_name, NULL, lldb::eFunctionNameTypeFull, true, false, sc_list);
+// sc_list.Dump(&strm, target);
+// jit_sym_vendor->Dump(&strm);
+// }
+ }
+
+ ResetDeclMap(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any ClangASTImporter::Minions.
+
+ if (jit_error.Success())
+ {
+ if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS)
+ m_jit_process_wp = lldb::ProcessWP(process->shared_from_this());
+ return true;
+ }
+ else
+ {
+ const char *error_cstr = jit_error.AsCString();
+ if (error_cstr && error_cstr[0])
+ error_stream.Printf ("error: %s\n", error_cstr);
+ else
+ error_stream.Printf ("error: expression can't be interpreted or run\n");
+ return false;
+ }
+}
+
+bool
+ClangUserExpression::AddArguments (ExecutionContext &exe_ctx,
+ std::vector<lldb::addr_t> &args,
+ lldb::addr_t struct_address,
+ Stream &error_stream)
+{
+ lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS;
+ lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS;
+
+ if (m_needs_object_ptr)
+ {
+ lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
+ if (!frame_sp)
+ return true;
+
+ ConstString object_name;
+
+ if (m_in_cplusplus_method)
+ {
+ object_name.SetCString("this");
+ }
+ else if (m_in_objectivec_method)
+ {
+ object_name.SetCString("self");
+ }
+ else
+ {
+ error_stream.Printf("Need object pointer but don't know the language\n");
+ return false;
+ }
+
+ Error object_ptr_error;
+
+ object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error);
+
+ if (!object_ptr_error.Success())
+ {
+ error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
+ object_ptr = 0;
+ }
+
+ if (m_in_objectivec_method)
+ {
+ ConstString cmd_name("_cmd");
+
+ cmd_ptr = GetObjectPointer(frame_sp, cmd_name, object_ptr_error);
+
+ if (!object_ptr_error.Success())
+ {
+ error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
+ cmd_ptr = 0;
+ }
+ }
+ if (object_ptr)
+ args.push_back(object_ptr);
+
+ if (m_in_objectivec_method)
+ args.push_back(cmd_ptr);
+
+ args.push_back(struct_address);
+ }
+ else
+ {
+ args.push_back(struct_address);
+ }
+ return true;
+}
+
+lldb::ExpressionVariableSP
+ClangUserExpression::GetResultAfterDematerialization(ExecutionContextScope *exe_scope)
+{
+ return m_result_delegate.GetVariable();
+}
+
+void
+ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(ExecutionContext &exe_ctx, Materializer::PersistentVariableDelegate &delegate, bool keep_result_in_memory)
+{
+ m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, &delegate, exe_ctx));
+}
+
+clang::ASTConsumer *
+ClangUserExpression::ClangUserExpressionHelper::ASTTransformer (clang::ASTConsumer *passthrough)
+{
+ m_result_synthesizer_up.reset(new ASTResultSynthesizer(passthrough,
+ m_target));
+
+ return m_result_synthesizer_up.get();
+}
+
+ClangUserExpression::ResultDelegate::ResultDelegate()
+{
+}
+
+ConstString
+ClangUserExpression::ResultDelegate::GetName()
+{
+ return m_persistent_state->GetNextPersistentVariableName();
+}
+
+void
+ClangUserExpression::ResultDelegate::DidDematerialize(lldb::ExpressionVariableSP &variable)
+{
+ m_variable = variable;
+}
+
+void
+ClangUserExpression::ResultDelegate::RegisterPersistentState(PersistentExpressionState *persistent_state)
+{
+ m_persistent_state = persistent_state;
+}
+
+lldb::ExpressionVariableSP &
+ClangUserExpression::ResultDelegate::GetVariable()
+{
+ return m_variable;
+}
+
diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
new file mode 100644
index 000000000000..f2bfe31dce09
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
@@ -0,0 +1,218 @@
+//===-- ClangUserExpression.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ClangUserExpression_h_
+#define liblldb_ClangUserExpression_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "ASTStructExtractor.h"
+#include "ASTResultSynthesizer.h"
+#include "ClangExpressionDeclMap.h"
+#include "ClangExpressionHelper.h"
+#include "ClangExpressionVariable.h"
+#include "IRForTarget.h"
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Expression/LLVMUserExpression.h"
+#include "lldb/Expression/Materializer.h"
+#include "lldb/Target/ExecutionContext.h"
+
+namespace lldb_private
+{
+
+//----------------------------------------------------------------------
+/// @class ClangUserExpression ClangUserExpression.h "lldb/Expression/ClangUserExpression.h"
+/// @brief Encapsulates a single expression for use with Clang
+///
+/// LLDB uses expressions for various purposes, notably to call functions
+/// and as a backend for the expr command. ClangUserExpression encapsulates
+/// 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
+{
+public:
+ enum { kDefaultTimeout = 500000u };
+
+ class ClangUserExpressionHelper : public ClangExpressionHelper
+ {
+ public:
+ ClangUserExpressionHelper (Target &target) :
+ m_target(target)
+ {
+ }
+
+ ~ClangUserExpressionHelper() override = default;
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should use when resolving external
+ /// values. May be NULL if everything should be self-contained.
+ //------------------------------------------------------------------
+ ClangExpressionDeclMap *
+ DeclMap() override
+ {
+ return m_expr_decl_map_up.get();
+ }
+
+ void
+ ResetDeclMap()
+ {
+ m_expr_decl_map_up.reset();
+ }
+
+ void
+ ResetDeclMap (ExecutionContext & exe_ctx, Materializer::PersistentVariableDelegate &result_delegate, bool keep_result_in_memory);
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should allow to access ASTs.
+ /// May be NULL if the ASTs do not need to be transformed.
+ ///
+ /// @param[in] passthrough
+ /// The ASTConsumer that the returned transformer should send
+ /// the ASTs to after transformation.
+ //------------------------------------------------------------------
+ clang::ASTConsumer *
+ ASTTransformer(clang::ASTConsumer *passthrough) override;
+
+ private:
+ Target &m_target;
+ std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map_up;
+ std::unique_ptr<ASTStructExtractor> m_struct_extractor_up; ///< The class that generates the argument struct layout.
+ std::unique_ptr<ASTResultSynthesizer> m_result_synthesizer_up;
+ };
+
+ //------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// @param[in] expr
+ /// The expression to parse.
+ ///
+ /// @param[in] expr_prefix
+ /// If non-NULL, a C string containing translation-unit level
+ /// definitions to be included when the expression is parsed.
+ ///
+ /// @param[in] language
+ /// If not eLanguageTypeUnknown, a language to use when parsing
+ /// the expression. Currently restricted to those languages
+ /// supported by Clang.
+ ///
+ /// @param[in] desired_type
+ /// If not eResultTypeAny, the type to use for the expression
+ /// result.
+ //------------------------------------------------------------------
+ ClangUserExpression (ExecutionContextScope &exe_scope,
+ const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ ResultType desired_type,
+ const EvaluateExpressionOptions &options);
+
+ ~ClangUserExpression() override;
+
+ //------------------------------------------------------------------
+ /// Parse the expression
+ ///
+ /// @param[in] error_stream
+ /// A stream to print parse errors and warnings to.
+ ///
+ /// @param[in] exe_ctx
+ /// The execution context to use when looking up entities that
+ /// are needed for parsing (locations of functions, types of
+ /// variables, persistent variables, etc.)
+ ///
+ /// @param[in] execution_policy
+ /// Determines whether interpretation is possible or mandatory.
+ ///
+ /// @param[in] keep_result_in_memory
+ /// True if the resulting persistent variable should reside in
+ /// target memory, if applicable.
+ ///
+ /// @return
+ /// True on success (no errors); false otherwise.
+ //------------------------------------------------------------------
+ bool
+ Parse (Stream &error_stream,
+ ExecutionContext &exe_ctx,
+ lldb_private::ExecutionPolicy execution_policy,
+ bool keep_result_in_memory,
+ bool generate_debug_info) override;
+
+ ExpressionTypeSystemHelper *
+ GetTypeSystemHelper () override
+ {
+ return &m_type_system_helper;
+ }
+
+ ClangExpressionDeclMap *
+ DeclMap ()
+ {
+ return m_type_system_helper.DeclMap();
+ }
+
+ void
+ ResetDeclMap ()
+ {
+ m_type_system_helper.ResetDeclMap();
+ }
+
+ void
+ ResetDeclMap (ExecutionContext & exe_ctx, Materializer::PersistentVariableDelegate &result_delegate, bool keep_result_in_memory)
+ {
+ m_type_system_helper.ResetDeclMap(exe_ctx, result_delegate, keep_result_in_memory);
+ }
+
+ lldb::ExpressionVariableSP
+ GetResultAfterDematerialization(ExecutionContextScope *exe_scope) override;
+
+private:
+ //------------------------------------------------------------------
+ /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the environment.
+ //------------------------------------------------------------------
+
+ void
+ ScanContext (ExecutionContext &exe_ctx,
+ lldb_private::Error &err) override;
+
+ bool
+ AddArguments (ExecutionContext &exe_ctx,
+ std::vector<lldb::addr_t> &args,
+ lldb::addr_t struct_address,
+ Stream &error_stream) override;
+
+ ClangUserExpressionHelper m_type_system_helper;
+
+ class ResultDelegate : public Materializer::PersistentVariableDelegate
+ {
+ public:
+ ResultDelegate();
+ ConstString GetName() override;
+ void DidDematerialize(lldb::ExpressionVariableSP &variable) override;
+
+ void RegisterPersistentState(PersistentExpressionState *persistent_state);
+ lldb::ExpressionVariableSP &GetVariable();
+
+ private:
+ PersistentExpressionState *m_persistent_state;
+ lldb::ExpressionVariableSP m_variable;
+ };
+
+ ResultDelegate m_result_delegate;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ClangUserExpression_h_
diff --git a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
new file mode 100644
index 000000000000..fe044c17ac78
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
@@ -0,0 +1,189 @@
+//===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangExpressionDeclMap.h"
+#include "ClangExpressionParser.h"
+#include "ClangUtilityFunction.h"
+
+// C Includes
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+// C++ Includes
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Expression/ExpressionSourceCode.h"
+#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb_private;
+
+//------------------------------------------------------------------
+/// Constructor
+///
+/// @param[in] text
+/// The text of the function. Must be a full translation unit.
+///
+/// @param[in] name
+/// 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)
+{
+}
+
+ClangUtilityFunction::~ClangUtilityFunction ()
+{
+}
+
+//------------------------------------------------------------------
+/// Install the utility function into a process
+///
+/// @param[in] error_stream
+/// A stream to print parse errors and warnings to.
+///
+/// @param[in] exe_ctx
+/// The execution context to install the utility function to.
+///
+/// @return
+/// True on success (no errors); false otherwise.
+//------------------------------------------------------------------
+bool
+ClangUtilityFunction::Install (Stream &error_stream,
+ ExecutionContext &exe_ctx)
+{
+ if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
+ {
+ error_stream.PutCString("error: already installed\n");
+ return false;
+ }
+
+ ////////////////////////////////////
+ // Set up the target and compiler
+ //
+
+ Target *target = exe_ctx.GetTargetPtr();
+
+ if (!target)
+ {
+ error_stream.PutCString ("error: invalid target\n");
+ return false;
+ }
+
+ Process *process = exe_ctx.GetProcessPtr();
+
+ if (!process)
+ {
+ error_stream.PutCString ("error: invalid process\n");
+ return false;
+ }
+
+ //////////////////////////
+ // Parse the expression
+ //
+
+ bool keep_result_in_memory = false;
+
+ ResetDeclMap(exe_ctx, keep_result_in_memory);
+
+ if (!DeclMap()->WillParse(exe_ctx, NULL))
+ {
+ error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
+ return false;
+ }
+
+ const bool generate_debug_info = true;
+ ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info);
+
+ unsigned num_errors = parser.Parse (error_stream);
+
+ if (num_errors)
+ {
+ error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
+
+ ResetDeclMap();
+
+ return false;
+ }
+
+ //////////////////////////////////
+ // JIT the output of the parser
+ //
+
+ bool can_interpret = false; // should stay that way
+
+ Error jit_error = parser.PrepareForExecution (m_jit_start_addr,
+ m_jit_end_addr,
+ m_execution_unit_sp,
+ exe_ctx,
+ can_interpret,
+ eExecutionPolicyAlways);
+
+ if (m_jit_start_addr != LLDB_INVALID_ADDRESS)
+ {
+ m_jit_process_wp = process->shared_from_this();
+ if (parser.GetGenerateDebugInfo())
+ {
+ lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule());
+
+ if (jit_module_sp)
+ {
+ ConstString const_func_name(FunctionName());
+ FileSpec jit_file;
+ jit_file.GetFilename() = const_func_name;
+ jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString());
+ m_jit_module_wp = jit_module_sp;
+ target->GetImages().Append(jit_module_sp);
+ }
+ }
+ }
+
+#if 0
+ // jingham: look here
+ StreamFile logfile ("/tmp/exprs.txt", "a");
+ logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n",
+ m_jit_start_addr,
+ m_function_name.c_str(),
+ m_function_text.c_str());
+#endif
+
+ DeclMap()->DidParse();
+
+ ResetDeclMap();
+
+ if (jit_error.Success())
+ {
+ return true;
+ }
+ else
+ {
+ const char *error_cstr = jit_error.AsCString();
+ if (error_cstr && error_cstr[0])
+ error_stream.Printf ("error: %s\n", error_cstr);
+ else
+ error_stream.Printf ("error: expression can't be interpreted or run\n");
+ return false;
+ }
+}
+
+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));
+}
diff --git a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
new file mode 100644
index 000000000000..74839717946b
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
@@ -0,0 +1,137 @@
+//===-- ClangUtilityFunction.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ClangUtilityFunction_h_
+#define liblldb_ClangUtilityFunction_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+#include <map>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "ClangExpressionHelper.h"
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Expression/UtilityFunction.h"
+
+namespace lldb_private
+{
+
+//----------------------------------------------------------------------
+/// @class ClangUtilityFunction ClangUtilityFunction.h "lldb/Expression/ClangUtilityFunction.h"
+/// @brief Encapsulates a single expression for use with Clang
+///
+/// LLDB uses expressions for various purposes, notably to call functions
+/// and as a backend for the expr command. ClangUtilityFunction encapsulates
+/// a self-contained function meant to be used from other code. Utility
+/// functions can perform error-checking for ClangUserExpressions, or can
+/// simply provide a way to push a function into the target for the debugger to
+/// call later on.
+//----------------------------------------------------------------------
+class ClangUtilityFunction : public UtilityFunction
+{
+public:
+ class ClangUtilityFunctionHelper : public ClangExpressionHelper
+ {
+ public:
+ ClangUtilityFunctionHelper ()
+ {
+ }
+
+ ~ClangUtilityFunctionHelper() override {}
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should use when resolving external
+ /// values. May be NULL if everything should be self-contained.
+ //------------------------------------------------------------------
+ ClangExpressionDeclMap *
+ DeclMap() override
+ {
+ return m_expr_decl_map_up.get();
+ }
+
+ void
+ ResetDeclMap()
+ {
+ m_expr_decl_map_up.reset();
+ }
+
+ void
+ ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory);
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should allow to access ASTs.
+ /// May be NULL if the ASTs do not need to be transformed.
+ ///
+ /// @param[in] passthrough
+ /// The ASTConsumer that the returned transformer should send
+ /// the ASTs to after transformation.
+ //------------------------------------------------------------------
+ clang::ASTConsumer *
+ ASTTransformer(clang::ASTConsumer *passthrough) override
+ {
+ return nullptr;
+ }
+ private:
+ std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map_up;
+ };
+ //------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// @param[in] text
+ /// The text of the function. Must be a full translation unit.
+ ///
+ /// @param[in] name
+ /// The name of the function, as used in the text.
+ //------------------------------------------------------------------
+ ClangUtilityFunction (ExecutionContextScope &exe_scope,
+ const char *text,
+ const char *name);
+
+ ~ClangUtilityFunction() override;
+
+ ExpressionTypeSystemHelper *
+ GetTypeSystemHelper () override
+ {
+ return &m_type_system_helper;
+ }
+
+ ClangExpressionDeclMap *
+ DeclMap()
+ {
+ return m_type_system_helper.DeclMap();
+ }
+
+ void
+ ResetDeclMap ()
+ {
+ m_type_system_helper.ResetDeclMap();
+ }
+
+ void
+ ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory)
+ {
+ m_type_system_helper.ResetDeclMap(exe_ctx, keep_result_in_memory);
+ }
+
+ bool
+ Install (Stream &error_stream, ExecutionContext &exe_ctx) override;
+
+private:
+ ClangUtilityFunctionHelper m_type_system_helper; ///< The map to use when parsing and materializing the expression.
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ClangUtilityFunction_h_
diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
new file mode 100644
index 000000000000..37b7bd1d2c84
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
@@ -0,0 +1,2820 @@
+//===-- IRForTarget.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "IRForTarget.h"
+
+#include "ClangExpressionDeclMap.h"
+
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/IR/ValueSymbolTable.h"
+
+#include "clang/AST/ASTContext.h"
+
+#include "lldb/Core/dwarf.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Expression/IRInterpreter.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Target/CPPLanguageRuntime.h"
+
+#include <map>
+
+using namespace llvm;
+
+static char ID;
+
+IRForTarget::StaticDataAllocator::StaticDataAllocator(lldb_private::IRExecutionUnit &execution_unit) :
+ m_execution_unit(execution_unit),
+ m_stream_string(lldb_private::Stream::eBinary, execution_unit.GetAddressByteSize(), execution_unit.GetByteOrder()),
+ m_allocation(LLDB_INVALID_ADDRESS)
+{
+}
+
+IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker) :
+ m_maker(maker),
+ m_values()
+{
+}
+
+IRForTarget::FunctionValueCache::~FunctionValueCache()
+{
+}
+
+llvm::Value *
+IRForTarget::FunctionValueCache::GetValue(llvm::Function *function)
+{
+ if (!m_values.count(function))
+ {
+ llvm::Value *ret = m_maker(function);
+ m_values[function] = ret;
+ return ret;
+ }
+ return m_values[function];
+}
+
+lldb::addr_t
+IRForTarget::StaticDataAllocator::Allocate()
+{
+ lldb_private::Error err;
+
+ if (m_allocation != LLDB_INVALID_ADDRESS)
+ {
+ m_execution_unit.FreeNow(m_allocation);
+ m_allocation = LLDB_INVALID_ADDRESS;
+ }
+
+ m_allocation = m_execution_unit.WriteNow((const uint8_t*)m_stream_string.GetData(), m_stream_string.GetSize(), err);
+
+ return m_allocation;
+}
+
+lldb::TargetSP
+IRForTarget::StaticDataAllocator::GetTarget()
+{
+ return m_execution_unit.GetTarget();
+}
+
+static llvm::Value *
+FindEntryInstruction (llvm::Function *function)
+{
+ if (function->empty())
+ return NULL;
+
+ return function->getEntryBlock().getFirstNonPHIOrDbg();
+}
+
+IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map,
+ bool resolve_vars,
+ lldb_private::IRExecutionUnit &execution_unit,
+ lldb_private::Stream *error_stream,
+ const char *func_name) :
+ ModulePass(ID),
+ m_resolve_vars(resolve_vars),
+ m_func_name(func_name),
+ m_module(NULL),
+ m_decl_map(decl_map),
+ m_data_allocator(execution_unit),
+ m_CFStringCreateWithBytes(NULL),
+ m_sel_registerName(NULL),
+ m_intptr_ty(NULL),
+ m_error_stream(error_stream),
+ m_result_store(NULL),
+ m_result_is_pointer(false),
+ m_reloc_placeholder(NULL),
+ m_entry_instruction_finder (FindEntryInstruction)
+{
+}
+
+/* Handy utility functions used at several places in the code */
+
+static std::string
+PrintValue(const Value *value, bool truncate = false)
+{
+ std::string s;
+ if (value)
+ {
+ raw_string_ostream rso(s);
+ value->print(rso);
+ rso.flush();
+ if (truncate)
+ s.resize(s.length() - 1);
+ }
+ return s;
+}
+
+static std::string
+PrintType(const llvm::Type *type, bool truncate = false)
+{
+ std::string s;
+ raw_string_ostream rso(s);
+ type->print(rso);
+ rso.flush();
+ if (truncate)
+ s.resize(s.length() - 1);
+ return s;
+}
+
+IRForTarget::~IRForTarget()
+{
+}
+
+bool
+IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function)
+{
+ llvm_function.setLinkage(GlobalValue::ExternalLinkage);
+
+ std::string name = llvm_function.getName().str();
+
+ return true;
+}
+
+IRForTarget::LookupResult
+IRForTarget::GetFunctionAddress (llvm::Function *fun,
+ uint64_t &fun_addr,
+ lldb_private::ConstString &name,
+ Constant **&value_ptr)
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ fun_addr = LLDB_INVALID_ADDRESS;
+ name.Clear();
+ value_ptr = NULL;
+
+ if (fun->isIntrinsic())
+ {
+ Intrinsic::ID intrinsic_id = (Intrinsic::ID)fun->getIntrinsicID();
+
+ switch (intrinsic_id)
+ {
+ default:
+ if (log)
+ log->Printf("Unresolved intrinsic \"%s\"", Intrinsic::getName(intrinsic_id).c_str());
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Call to unhandled compiler intrinsic '%s'\n", Intrinsic::getName(intrinsic_id).c_str());
+
+ return LookupResult::Fail;
+ case Intrinsic::memcpy:
+ {
+ static lldb_private::ConstString g_memcpy_str ("memcpy");
+ name = g_memcpy_str;
+ }
+ break;
+ case Intrinsic::memset:
+ {
+ static lldb_private::ConstString g_memset_str ("memset");
+ name = g_memset_str;
+ }
+ break;
+ case Intrinsic::dbg_declare:
+ case Intrinsic::dbg_value:
+ return LookupResult::Ignore;
+ }
+
+ if (log && name)
+ log->Printf("Resolved intrinsic name \"%s\"", name.GetCString());
+ }
+ else
+ {
+ name.SetCStringWithLength (fun->getName().data(), fun->getName().size());
+ }
+
+ // Find the address of the function.
+
+ clang::NamedDecl *fun_decl = DeclForGlobal (fun);
+
+ if (fun_decl)
+ {
+ if (!m_decl_map->GetFunctionInfo (fun_decl, fun_addr))
+ {
+ std::vector<lldb_private::ConstString> alternates;
+ bool found_it = m_decl_map->GetFunctionAddress (name, fun_addr);
+ if (!found_it)
+ {
+ if (log)
+ log->Printf("Address of function \"%s\" not found.\n", name.GetCString());
+ // Check for an alternate mangling for names from the standard library.
+ // For example, "std::basic_string<...>" has an alternate mangling scheme per
+ // the Itanium C++ ABI.
+ lldb::ProcessSP process_sp = m_data_allocator.GetTarget()->GetProcessSP();
+ if (process_sp)
+ {
+ lldb_private::CPPLanguageRuntime *cpp_runtime = process_sp->GetCPPLanguageRuntime();
+ if (cpp_runtime && cpp_runtime->GetAlternateManglings(name, alternates))
+ {
+ for (size_t i = 0; i < alternates.size(); ++i)
+ {
+ const lldb_private::ConstString &alternate_name = alternates[i];
+ if (log)
+ log->Printf("Looking up address of function \"%s\" with alternate name \"%s\"",
+ name.GetCString(), alternate_name.GetCString());
+ if ((found_it = m_decl_map->GetFunctionAddress (alternate_name, fun_addr)))
+ {
+ if (log)
+ log->Printf("Found address of function \"%s\" with alternate name \"%s\"",
+ name.GetCString(), alternate_name.GetCString());
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (!found_it)
+ {
+ lldb_private::Mangled mangled_name(name);
+ if (m_error_stream)
+ {
+ if (mangled_name.GetMangledName())
+ m_error_stream->Printf("error: call to a function '%s' ('%s') that is not present in the target\n",
+ mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString(),
+ mangled_name.GetMangledName().GetCString());
+ else
+ m_error_stream->Printf("error: call to a function '%s' that is not present in the target\n",
+ mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString());
+ }
+ return LookupResult::Fail;
+ }
+ }
+ }
+ else
+ {
+ if (!m_decl_map->GetFunctionAddress (name, fun_addr))
+ {
+ if (log)
+ log->Printf ("Metadataless function \"%s\" had no address", name.GetCString());
+
+ if (m_error_stream)
+ m_error_stream->Printf("Error [IRForTarget]: Call to a symbol-only function '%s' that is not present in the target\n", name.GetCString());
+
+ return LookupResult::Fail;
+ }
+ }
+
+ if (log)
+ log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), fun_addr);
+
+ return LookupResult::Success;
+}
+
+llvm::Constant *
+IRForTarget::BuildFunctionPointer (llvm::Type *type,
+ uint64_t ptr)
+{
+ PointerType *fun_ptr_ty = PointerType::getUnqual(type);
+ Constant *fun_addr_int = ConstantInt::get(m_intptr_ty, ptr, false);
+ return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
+}
+
+void
+IRForTarget::RegisterFunctionMetadata(LLVMContext &context,
+ llvm::Value *function_ptr,
+ const char *name)
+{
+ for (llvm::User *user : function_ptr->users())
+ {
+ if (Instruction *user_inst = dyn_cast<Instruction>(user))
+ {
+ MDString* md_name = MDString::get(context, StringRef(name));
+
+ MDNode *metadata = MDNode::get(context, md_name);
+
+ user_inst->setMetadata("lldb.call.realName", metadata);
+ }
+ else
+ {
+ RegisterFunctionMetadata (context, user, name);
+ }
+ }
+}
+
+bool
+IRForTarget::ResolveFunctionPointers(llvm::Module &llvm_module)
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ for (llvm::Module::iterator fi = llvm_module.begin();
+ fi != llvm_module.end();
+ ++fi)
+ {
+ Function *fun = &*fi;
+
+ bool is_decl = fun->isDeclaration();
+
+ if (log)
+ log->Printf("Examining %s function %s", (is_decl ? "declaration" : "non-declaration"), fun->getName().str().c_str());
+
+ if (!is_decl)
+ continue;
+
+ if (fun->use_empty())
+ continue; // ignore
+
+ uint64_t addr = LLDB_INVALID_ADDRESS;
+ lldb_private::ConstString name;
+ Constant **value_ptr = NULL;
+
+ LookupResult result = GetFunctionAddress(fun,
+ addr,
+ name,
+ value_ptr);
+
+ switch (result)
+ {
+ case LookupResult::Fail:
+ return false; // GetFunctionAddress reports its own errors
+
+ case LookupResult::Ignore:
+ break; // Nothing to do
+
+ case LookupResult::Success:
+ {
+ Constant *value = BuildFunctionPointer(fun->getFunctionType(), addr);
+
+ RegisterFunctionMetadata (llvm_module.getContext(), fun, name.AsCString());
+
+ if (value_ptr)
+ *value_ptr = value;
+
+ // If we are replacing a function with the nobuiltin attribute, it may
+ // be called with the builtin attribute on call sites. Remove any such
+ // attributes since it's illegal to have a builtin call to something
+ // other than a nobuiltin function.
+ if (fun->hasFnAttribute(llvm::Attribute::NoBuiltin)) {
+ llvm::Attribute builtin = llvm::Attribute::get(fun->getContext(), llvm::Attribute::Builtin);
+
+ for (auto u : fun->users()) {
+ if (auto call = dyn_cast<CallInst>(u)) {
+ call->removeAttribute(AttributeSet::FunctionIndex, builtin);
+ }
+ }
+ }
+
+ fun->replaceAllUsesWith(value);
+ }
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+clang::NamedDecl *
+IRForTarget::DeclForGlobal (const GlobalValue *global_val, Module *module)
+{
+ NamedMDNode *named_metadata = module->getNamedMetadata("clang.global.decl.ptrs");
+
+ if (!named_metadata)
+ return NULL;
+
+ unsigned num_nodes = named_metadata->getNumOperands();
+ unsigned node_index;
+
+ for (node_index = 0;
+ node_index < num_nodes;
+ ++node_index)
+ {
+ llvm::MDNode *metadata_node = dyn_cast<llvm::MDNode>(named_metadata->getOperand(node_index));
+ if (!metadata_node)
+ return NULL;
+
+ if (metadata_node->getNumOperands() != 2)
+ continue;
+
+ if (mdconst::dyn_extract_or_null<GlobalValue>(metadata_node->getOperand(0)) != global_val)
+ continue;
+
+ ConstantInt *constant_int = mdconst::dyn_extract<ConstantInt>(metadata_node->getOperand(1));
+
+ if (!constant_int)
+ return NULL;
+
+ uintptr_t ptr = constant_int->getZExtValue();
+
+ return reinterpret_cast<clang::NamedDecl *>(ptr);
+ }
+
+ return NULL;
+}
+
+clang::NamedDecl *
+IRForTarget::DeclForGlobal (GlobalValue *global_val)
+{
+ return DeclForGlobal(global_val, m_module);
+}
+
+bool
+IRForTarget::CreateResultVariable (llvm::Function &llvm_function)
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (!m_resolve_vars)
+ return true;
+
+ // Find the result variable. If it doesn't exist, we can give up right here.
+
+ ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable();
+
+ std::string result_name_str;
+ const char *result_name = NULL;
+
+ for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end();
+ vi != ve;
+ ++vi)
+ {
+ result_name_str = vi->first().str();
+ const char *value_name = result_name_str.c_str();
+
+ if (strstr(value_name, "$__lldb_expr_result_ptr") &&
+ strncmp(value_name, "_ZGV", 4))
+ {
+ result_name = value_name;
+ m_result_is_pointer = true;
+ break;
+ }
+
+ if (strstr(value_name, "$__lldb_expr_result") &&
+ strncmp(value_name, "_ZGV", 4))
+ {
+ result_name = value_name;
+ m_result_is_pointer = false;
+ break;
+ }
+ }
+
+ if (!result_name)
+ {
+ if (log)
+ log->PutCString("Couldn't find result variable");
+
+ return true;
+ }
+
+ if (log)
+ log->Printf("Result name: \"%s\"", result_name);
+
+ Value *result_value = m_module->getNamedValue(result_name);
+
+ if (!result_value)
+ {
+ if (log)
+ log->PutCString("Result variable had no data");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Result variable's name (%s) exists, but not its definition\n", result_name);
+
+ return false;
+ }
+
+ if (log)
+ log->Printf("Found result in the IR: \"%s\"", PrintValue(result_value, false).c_str());
+
+ GlobalVariable *result_global = dyn_cast<GlobalVariable>(result_value);
+
+ if (!result_global)
+ {
+ if (log)
+ log->PutCString("Result variable isn't a GlobalVariable");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) is defined, but is not a global variable\n", result_name);
+
+ return false;
+ }
+
+ clang::NamedDecl *result_decl = DeclForGlobal (result_global);
+ if (!result_decl)
+ {
+ if (log)
+ log->PutCString("Result variable doesn't have a corresponding Decl");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) does not have a corresponding Clang entity\n", result_name);
+
+ return false;
+ }
+
+ if (log)
+ {
+ std::string decl_desc_str;
+ raw_string_ostream decl_desc_stream(decl_desc_str);
+ result_decl->print(decl_desc_stream);
+ decl_desc_stream.flush();
+
+ log->Printf("Found result decl: \"%s\"", decl_desc_str.c_str());
+ }
+
+ clang::VarDecl *result_var = dyn_cast<clang::VarDecl>(result_decl);
+ if (!result_var)
+ {
+ if (log)
+ log->PutCString("Result variable Decl isn't a VarDecl");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s)'s corresponding Clang entity isn't a variable\n", result_name);
+
+ return false;
+ }
+
+ // Get the next available result name from m_decl_map and create the persistent
+ // variable for it
+
+ // If the result is an Lvalue, it is emitted as a pointer; see
+ // ASTResultSynthesizer::SynthesizeBodyResult.
+ if (m_result_is_pointer)
+ {
+ clang::QualType pointer_qual_type = result_var->getType();
+ const clang::Type *pointer_type = pointer_qual_type.getTypePtr();
+
+ const clang::PointerType *pointer_pointertype = pointer_type->getAs<clang::PointerType>();
+ const clang::ObjCObjectPointerType *pointer_objcobjpointertype = pointer_type->getAs<clang::ObjCObjectPointerType>();
+
+ if (pointer_pointertype)
+ {
+ clang::QualType element_qual_type = pointer_pointertype->getPointeeType();
+
+ m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(),
+ lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext()));
+ }
+ else if (pointer_objcobjpointertype)
+ {
+ clang::QualType element_qual_type = clang::QualType(pointer_objcobjpointertype->getObjectType(), 0);
+
+ m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(),
+ lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext()));
+ }
+ else
+ {
+ if (log)
+ log->PutCString("Expected result to have pointer type, but it did not");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Lvalue result (%s) is not a pointer variable\n", result_name);
+
+ return false;
+ }
+ }
+ else
+ {
+ m_result_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(),
+ lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext()));
+ }
+
+
+ lldb::TargetSP target_sp (m_data_allocator.GetTarget());
+ lldb_private::ExecutionContext exe_ctx (target_sp, true);
+ if (m_result_type.GetBitSize(exe_ctx.GetBestExecutionContextScope()) == 0)
+ {
+ lldb_private::StreamString type_desc_stream;
+ m_result_type.DumpTypeDescription(&type_desc_stream);
+
+ if (log)
+ log->Printf("Result type has size 0");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Error [IRForTarget]: Size of result type '%s' couldn't be determined\n",
+ type_desc_stream.GetData());
+ return false;
+ }
+
+ if (log)
+ {
+ lldb_private::StreamString type_desc_stream;
+ m_result_type.DumpTypeDescription(&type_desc_stream);
+
+ log->Printf("Result decl type: \"%s\"", type_desc_stream.GetData());
+ }
+
+ m_result_name = lldb_private::ConstString("$RESULT_NAME");
+
+ if (log)
+ log->Printf("Creating a new result global: \"%s\" with size 0x%" PRIx64,
+ m_result_name.GetCString(),
+ m_result_type.GetByteSize(nullptr));
+
+ // Construct a new result global and set up its metadata
+
+ GlobalVariable *new_result_global = new GlobalVariable((*m_module),
+ result_global->getType()->getElementType(),
+ false, /* not constant */
+ GlobalValue::ExternalLinkage,
+ NULL, /* no initializer */
+ m_result_name.GetCString ());
+
+ // It's too late in compilation to create a new VarDecl for this, but we don't
+ // need to. We point the metadata at the old VarDecl. This creates an odd
+ // anomaly: a variable with a Value whose name is something like $0 and a
+ // Decl whose name is $__lldb_expr_result. This condition is handled in
+ // ClangExpressionDeclMap::DoMaterialize, and the name of the variable is
+ // fixed up.
+
+ ConstantInt *new_constant_int = ConstantInt::get(llvm::Type::getInt64Ty(m_module->getContext()),
+ reinterpret_cast<uint64_t>(result_decl),
+ false);
+
+ llvm::Metadata *values[2];
+ values[0] = ConstantAsMetadata::get(new_result_global);
+ values[1] = ConstantAsMetadata::get(new_constant_int);
+
+ ArrayRef<Metadata *> value_ref(values, 2);
+
+ MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref);
+ NamedMDNode *named_metadata = m_module->getNamedMetadata("clang.global.decl.ptrs");
+ named_metadata->addOperand(persistent_global_md);
+
+ if (log)
+ log->Printf("Replacing \"%s\" with \"%s\"",
+ PrintValue(result_global).c_str(),
+ PrintValue(new_result_global).c_str());
+
+ if (result_global->use_empty())
+ {
+ // We need to synthesize a store for this variable, because otherwise
+ // there's nothing to put into its equivalent persistent variable.
+
+ BasicBlock &entry_block(llvm_function.getEntryBlock());
+ Instruction *first_entry_instruction(entry_block.getFirstNonPHIOrDbg());
+
+ if (!first_entry_instruction)
+ return false;
+
+ if (!result_global->hasInitializer())
+ {
+ if (log)
+ log->Printf("Couldn't find initializer for unused variable");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) has no writes and no initializer\n", result_name);
+
+ return false;
+ }
+
+ Constant *initializer = result_global->getInitializer();
+
+ StoreInst *synthesized_store = new StoreInst(initializer,
+ new_result_global,
+ first_entry_instruction);
+
+ if (log)
+ log->Printf("Synthesized result store \"%s\"\n", PrintValue(synthesized_store).c_str());
+ }
+ else
+ {
+ result_global->replaceAllUsesWith(new_result_global);
+ }
+
+ if (!m_decl_map->AddPersistentVariable(result_decl,
+ m_result_name,
+ m_result_type,
+ true,
+ m_result_is_pointer))
+ return false;
+
+ result_global->eraseFromParent();
+
+ return true;
+}
+
+bool
+IRForTarget::RewriteObjCConstString (llvm::GlobalVariable *ns_str,
+ llvm::GlobalVariable *cstr)
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ Type *ns_str_ty = ns_str->getType();
+
+ Type *i8_ptr_ty = Type::getInt8PtrTy(m_module->getContext());
+ Type *i32_ty = Type::getInt32Ty(m_module->getContext());
+ Type *i8_ty = Type::getInt8Ty(m_module->getContext());
+
+ if (!m_CFStringCreateWithBytes)
+ {
+ lldb::addr_t CFStringCreateWithBytes_addr;
+
+ static lldb_private::ConstString g_CFStringCreateWithBytes_str ("CFStringCreateWithBytes");
+
+ if (!m_decl_map->GetFunctionAddress (g_CFStringCreateWithBytes_str, CFStringCreateWithBytes_addr))
+ {
+ if (log)
+ log->PutCString("Couldn't find CFStringCreateWithBytes in the target");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Error [IRForTarget]: Rewriting an Objective-C constant string requires CFStringCreateWithBytes\n");
+
+ return false;
+ }
+
+ if (log)
+ log->Printf("Found CFStringCreateWithBytes at 0x%" PRIx64, CFStringCreateWithBytes_addr);
+
+ // Build the function type:
+ //
+ // CFStringRef CFStringCreateWithBytes (
+ // CFAllocatorRef alloc,
+ // const UInt8 *bytes,
+ // CFIndex numBytes,
+ // CFStringEncoding encoding,
+ // Boolean isExternalRepresentation
+ // );
+ //
+ // We make the following substitutions:
+ //
+ // CFStringRef -> i8*
+ // CFAllocatorRef -> i8*
+ // UInt8 * -> i8*
+ // CFIndex -> long (i32 or i64, as appropriate; we ask the module for its pointer size for now)
+ // CFStringEncoding -> i32
+ // Boolean -> i8
+
+ Type *arg_type_array[5];
+
+ arg_type_array[0] = i8_ptr_ty;
+ arg_type_array[1] = i8_ptr_ty;
+ arg_type_array[2] = m_intptr_ty;
+ arg_type_array[3] = i32_ty;
+ arg_type_array[4] = i8_ty;
+
+ ArrayRef<Type *> CFSCWB_arg_types(arg_type_array, 5);
+
+ llvm::Type *CFSCWB_ty = FunctionType::get(ns_str_ty, CFSCWB_arg_types, false);
+
+ // Build the constant containing the pointer to the function
+ PointerType *CFSCWB_ptr_ty = PointerType::getUnqual(CFSCWB_ty);
+ Constant *CFSCWB_addr_int = ConstantInt::get(m_intptr_ty, CFStringCreateWithBytes_addr, false);
+ m_CFStringCreateWithBytes = ConstantExpr::getIntToPtr(CFSCWB_addr_int, CFSCWB_ptr_ty);
+ }
+
+ ConstantDataSequential *string_array = NULL;
+
+ if (cstr)
+ string_array = dyn_cast<ConstantDataSequential>(cstr->getInitializer());
+
+ Constant *alloc_arg = Constant::getNullValue(i8_ptr_ty);
+ Constant *bytes_arg = cstr ? ConstantExpr::getBitCast(cstr, i8_ptr_ty) : Constant::getNullValue(i8_ptr_ty);
+ Constant *numBytes_arg = ConstantInt::get(m_intptr_ty, cstr ? string_array->getNumElements() - 1 : 0, false);
+ Constant *encoding_arg = ConstantInt::get(i32_ty, 0x0600, false); /* 0x0600 is kCFStringEncodingASCII */
+ Constant *isExternal_arg = ConstantInt::get(i8_ty, 0x0, false); /* 0x0 is false */
+
+ Value *argument_array[5];
+
+ argument_array[0] = alloc_arg;
+ argument_array[1] = bytes_arg;
+ argument_array[2] = numBytes_arg;
+ argument_array[3] = encoding_arg;
+ argument_array[4] = isExternal_arg;
+
+ ArrayRef <Value *> CFSCWB_arguments(argument_array, 5);
+
+ FunctionValueCache CFSCWB_Caller ([this, &CFSCWB_arguments] (llvm::Function *function)->llvm::Value * {
+ return CallInst::Create(m_CFStringCreateWithBytes,
+ CFSCWB_arguments,
+ "CFStringCreateWithBytes",
+ llvm::cast<Instruction>(m_entry_instruction_finder.GetValue(function)));
+ });
+
+ if (!UnfoldConstant(ns_str, CFSCWB_Caller, m_entry_instruction_finder))
+ {
+ if (log)
+ log->PutCString("Couldn't replace the NSString with the result of the call");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Error [IRForTarget]: Couldn't replace an Objective-C constant string with a dynamic string\n");
+
+ return false;
+ }
+
+ ns_str->eraseFromParent();
+
+ return true;
+}
+
+bool
+IRForTarget::RewriteObjCConstStrings()
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable();
+
+ for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end();
+ vi != ve;
+ ++vi)
+ {
+ std::string value_name = vi->first().str();
+ const char *value_name_cstr = value_name.c_str();
+
+ if (strstr(value_name_cstr, "_unnamed_cfstring_"))
+ {
+ Value *nsstring_value = vi->second;
+
+ GlobalVariable *nsstring_global = dyn_cast<GlobalVariable>(nsstring_value);
+
+ if (!nsstring_global)
+ {
+ if (log)
+ log->PutCString("NSString variable is not a GlobalVariable");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string is not a global variable\n");
+
+ return false;
+ }
+
+ if (!nsstring_global->hasInitializer())
+ {
+ if (log)
+ log->PutCString("NSString variable does not have an initializer");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string does not have an initializer\n");
+
+ return false;
+ }
+
+ ConstantStruct *nsstring_struct = dyn_cast<ConstantStruct>(nsstring_global->getInitializer());
+
+ if (!nsstring_struct)
+ {
+ if (log)
+ log->PutCString("NSString variable's initializer is not a ConstantStruct");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string is not a structure constant\n");
+
+ return false;
+ }
+
+ // We expect the following structure:
+ //
+ // struct {
+ // int *isa;
+ // int flags;
+ // char *str;
+ // long length;
+ // };
+
+ if (nsstring_struct->getNumOperands() != 4)
+ {
+ if (log)
+ log->Printf("NSString variable's initializer structure has an unexpected number of members. Should be 4, is %d", nsstring_struct->getNumOperands());
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: The struct for an Objective-C constant string is not as expected\n");
+
+ return false;
+ }
+
+ Constant *nsstring_member = nsstring_struct->getOperand(2);
+
+ if (!nsstring_member)
+ {
+ if (log)
+ log->PutCString("NSString initializer's str element was empty");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string does not have a string initializer\n");
+
+ return false;
+ }
+
+ ConstantExpr *nsstring_expr = dyn_cast<ConstantExpr>(nsstring_member);
+
+ if (!nsstring_expr)
+ {
+ if (log)
+ log->PutCString("NSString initializer's str element is not a ConstantExpr");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer is not constant\n");
+
+ return false;
+ }
+
+ if (nsstring_expr->getOpcode() != Instruction::GetElementPtr)
+ {
+ if (log)
+ log->Printf("NSString initializer's str element is not a GetElementPtr expression, it's a %s", nsstring_expr->getOpcodeName());
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer is not an array\n");
+
+ return false;
+ }
+
+ Constant *nsstring_cstr = nsstring_expr->getOperand(0);
+
+ GlobalVariable *cstr_global = dyn_cast<GlobalVariable>(nsstring_cstr);
+
+ if (!cstr_global)
+ {
+ if (log)
+ log->PutCString("NSString initializer's str element is not a GlobalVariable");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a global\n");
+
+ return false;
+ }
+
+ if (!cstr_global->hasInitializer())
+ {
+ if (log)
+ log->PutCString("NSString initializer's str element does not have an initializer");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to initialized data\n");
+
+ return false;
+ }
+
+ /*
+ if (!cstr_array)
+ {
+ if (log)
+ log->PutCString("NSString initializer's str element is not a ConstantArray");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to an array\n");
+
+ return false;
+ }
+
+ if (!cstr_array->isCString())
+ {
+ if (log)
+ log->PutCString("NSString initializer's str element is not a C string array");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a C string\n");
+
+ return false;
+ }
+ */
+
+ ConstantDataArray *cstr_array = dyn_cast<ConstantDataArray>(cstr_global->getInitializer());
+
+ if (log)
+ {
+ if (cstr_array)
+ log->Printf("Found NSString constant %s, which contains \"%s\"", value_name_cstr, cstr_array->getAsString().str().c_str());
+ else
+ log->Printf("Found NSString constant %s, which contains \"\"", value_name_cstr);
+ }
+
+ if (!cstr_array)
+ cstr_global = NULL;
+
+ if (!RewriteObjCConstString(nsstring_global, cstr_global))
+ {
+ if (log)
+ log->PutCString("Error rewriting the constant string");
+
+ // We don't print an error message here because RewriteObjCConstString has done so for us.
+
+ return false;
+ }
+ }
+ }
+
+ for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end();
+ vi != ve;
+ ++vi)
+ {
+ std::string value_name = vi->first().str();
+ const char *value_name_cstr = value_name.c_str();
+
+ if (!strcmp(value_name_cstr, "__CFConstantStringClassReference"))
+ {
+ GlobalVariable *gv = dyn_cast<GlobalVariable>(vi->second);
+
+ if (!gv)
+ {
+ if (log)
+ log->PutCString("__CFConstantStringClassReference is not a global variable");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Found a CFConstantStringClassReference, but it is not a global object\n");
+
+ return false;
+ }
+
+ gv->eraseFromParent();
+
+ break;
+ }
+ }
+
+ return true;
+}
+
+static bool IsObjCSelectorRef (Value *value)
+{
+ GlobalVariable *global_variable = dyn_cast<GlobalVariable>(value);
+
+ if (!global_variable || !global_variable->hasName() || !global_variable->getName().startswith("OBJC_SELECTOR_REFERENCES_"))
+ return false;
+
+ return true;
+}
+
+// This function does not report errors; its callers are responsible.
+bool
+IRForTarget::RewriteObjCSelector (Instruction* selector_load)
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ LoadInst *load = dyn_cast<LoadInst>(selector_load);
+
+ if (!load)
+ return false;
+
+ // Unpack the message name from the selector. In LLVM IR, an objc_msgSend gets represented as
+ //
+ // %tmp = load i8** @"OBJC_SELECTOR_REFERENCES_" ; <i8*>
+ // %call = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...) ; <i8*>
+ //
+ // where %obj is the object pointer and %tmp is the selector.
+ //
+ // @"OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_".
+ // @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_" contains the string.
+
+ // Find the pointer's initializer (a ConstantExpr with opcode GetElementPtr) and get the string from its target
+
+ GlobalVariable *_objc_selector_references_ = dyn_cast<GlobalVariable>(load->getPointerOperand());
+
+ if (!_objc_selector_references_ || !_objc_selector_references_->hasInitializer())
+ return false;
+
+ Constant *osr_initializer = _objc_selector_references_->getInitializer();
+
+ ConstantExpr *osr_initializer_expr = dyn_cast<ConstantExpr>(osr_initializer);
+
+ if (!osr_initializer_expr || osr_initializer_expr->getOpcode() != Instruction::GetElementPtr)
+ return false;
+
+ Value *osr_initializer_base = osr_initializer_expr->getOperand(0);
+
+ if (!osr_initializer_base)
+ return false;
+
+ // Find the string's initializer (a ConstantArray) and get the string from it
+
+ GlobalVariable *_objc_meth_var_name_ = dyn_cast<GlobalVariable>(osr_initializer_base);
+
+ if (!_objc_meth_var_name_ || !_objc_meth_var_name_->hasInitializer())
+ return false;
+
+ Constant *omvn_initializer = _objc_meth_var_name_->getInitializer();
+
+ ConstantDataArray *omvn_initializer_array = dyn_cast<ConstantDataArray>(omvn_initializer);
+
+ if (!omvn_initializer_array->isString())
+ return false;
+
+ std::string omvn_initializer_string = omvn_initializer_array->getAsString();
+
+ if (log)
+ log->Printf("Found Objective-C selector reference \"%s\"", omvn_initializer_string.c_str());
+
+ // Construct a call to sel_registerName
+
+ if (!m_sel_registerName)
+ {
+ lldb::addr_t sel_registerName_addr;
+
+ static lldb_private::ConstString g_sel_registerName_str ("sel_registerName");
+ if (!m_decl_map->GetFunctionAddress (g_sel_registerName_str, sel_registerName_addr))
+ return false;
+
+ if (log)
+ log->Printf("Found sel_registerName at 0x%" PRIx64, sel_registerName_addr);
+
+ // Build the function type: struct objc_selector *sel_registerName(uint8_t*)
+
+ // The below code would be "more correct," but in actuality what's required is uint8_t*
+ //Type *sel_type = StructType::get(m_module->getContext());
+ //Type *sel_ptr_type = PointerType::getUnqual(sel_type);
+ Type *sel_ptr_type = Type::getInt8PtrTy(m_module->getContext());
+
+ Type *type_array[1];
+
+ type_array[0] = llvm::Type::getInt8PtrTy(m_module->getContext());
+
+ ArrayRef<Type *> srN_arg_types(type_array, 1);
+
+ llvm::Type *srN_type = FunctionType::get(sel_ptr_type, srN_arg_types, false);
+
+ // Build the constant containing the pointer to the function
+ PointerType *srN_ptr_ty = PointerType::getUnqual(srN_type);
+ Constant *srN_addr_int = ConstantInt::get(m_intptr_ty, sel_registerName_addr, false);
+ m_sel_registerName = ConstantExpr::getIntToPtr(srN_addr_int, srN_ptr_ty);
+ }
+
+ Value *argument_array[1];
+
+ Constant *omvn_pointer = ConstantExpr::getBitCast(_objc_meth_var_name_, Type::getInt8PtrTy(m_module->getContext()));
+
+ argument_array[0] = omvn_pointer;
+
+ ArrayRef<Value *> srN_arguments(argument_array, 1);
+
+ CallInst *srN_call = CallInst::Create(m_sel_registerName,
+ srN_arguments,
+ "sel_registerName",
+ selector_load);
+
+ // Replace the load with the call in all users
+
+ selector_load->replaceAllUsesWith(srN_call);
+
+ selector_load->eraseFromParent();
+
+ return true;
+}
+
+bool
+IRForTarget::RewriteObjCSelectors (BasicBlock &basic_block)
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ BasicBlock::iterator ii;
+
+ typedef SmallVector <Instruction*, 2> InstrList;
+ typedef InstrList::iterator InstrIterator;
+
+ InstrList selector_loads;
+
+ for (ii = basic_block.begin();
+ ii != basic_block.end();
+ ++ii)
+ {
+ Instruction &inst = *ii;
+
+ if (LoadInst *load = dyn_cast<LoadInst>(&inst))
+ if (IsObjCSelectorRef(load->getPointerOperand()))
+ selector_loads.push_back(&inst);
+ }
+
+ InstrIterator iter;
+
+ for (iter = selector_loads.begin();
+ iter != selector_loads.end();
+ ++iter)
+ {
+ if (!RewriteObjCSelector(*iter))
+ {
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Couldn't change a static reference to an Objective-C selector to a dynamic reference\n");
+
+ if (log)
+ log->PutCString("Couldn't rewrite a reference to an Objective-C selector");
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// This function does not report errors; its callers are responsible.
+bool
+IRForTarget::RewritePersistentAlloc (llvm::Instruction *persistent_alloc)
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ AllocaInst *alloc = dyn_cast<AllocaInst>(persistent_alloc);
+
+ MDNode *alloc_md = alloc->getMetadata("clang.decl.ptr");
+
+ if (!alloc_md || !alloc_md->getNumOperands())
+ return false;
+
+ ConstantInt *constant_int = mdconst::dyn_extract<ConstantInt>(alloc_md->getOperand(0));
+
+ if (!constant_int)
+ return false;
+
+ // We attempt to register this as a new persistent variable with the DeclMap.
+
+ uintptr_t ptr = constant_int->getZExtValue();
+
+ clang::VarDecl *decl = reinterpret_cast<clang::VarDecl *>(ptr);
+
+ lldb_private::TypeFromParser result_decl_type (decl->getType().getAsOpaquePtr(),
+ lldb_private::ClangASTContext::GetASTContext(&decl->getASTContext()));
+
+ StringRef decl_name (decl->getName());
+ lldb_private::ConstString persistent_variable_name (decl_name.data(), decl_name.size());
+ if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, result_decl_type, false, false))
+ return false;
+
+ GlobalVariable *persistent_global = new GlobalVariable((*m_module),
+ alloc->getType(),
+ false, /* not constant */
+ GlobalValue::ExternalLinkage,
+ NULL, /* no initializer */
+ alloc->getName().str().c_str());
+
+ // What we're going to do here is make believe this was a regular old external
+ // variable. That means we need to make the metadata valid.
+
+ NamedMDNode *named_metadata = m_module->getOrInsertNamedMetadata("clang.global.decl.ptrs");
+
+ llvm::Metadata *values[2];
+ values[0] = ConstantAsMetadata::get(persistent_global);
+ values[1] = ConstantAsMetadata::get(constant_int);
+
+ ArrayRef<llvm::Metadata *> value_ref(values, 2);
+
+ MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref);
+ named_metadata->addOperand(persistent_global_md);
+
+ // Now, since the variable is a pointer variable, we will drop in a load of that
+ // pointer variable.
+
+ LoadInst *persistent_load = new LoadInst (persistent_global, "", alloc);
+
+ if (log)
+ log->Printf("Replacing \"%s\" with \"%s\"",
+ PrintValue(alloc).c_str(),
+ PrintValue(persistent_load).c_str());
+
+ alloc->replaceAllUsesWith(persistent_load);
+ alloc->eraseFromParent();
+
+ return true;
+}
+
+bool
+IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block)
+{
+ if (!m_resolve_vars)
+ return true;
+
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ BasicBlock::iterator ii;
+
+ typedef SmallVector <Instruction*, 2> InstrList;
+ typedef InstrList::iterator InstrIterator;
+
+ InstrList pvar_allocs;
+
+ for (ii = basic_block.begin();
+ ii != basic_block.end();
+ ++ii)
+ {
+ Instruction &inst = *ii;
+
+ if (AllocaInst *alloc = dyn_cast<AllocaInst>(&inst))
+ {
+ llvm::StringRef alloc_name = alloc->getName();
+
+ if (alloc_name.startswith("$") &&
+ !alloc_name.startswith("$__lldb"))
+ {
+ if (alloc_name.find_first_of("0123456789") == 1)
+ {
+ if (log)
+ log->Printf("Rejecting a numeric persistent variable.");
+
+ if (m_error_stream)
+ m_error_stream->Printf("Error [IRForTarget]: Names starting with $0, $1, ... are reserved for use as result names\n");
+
+ return false;
+ }
+
+ pvar_allocs.push_back(alloc);
+ }
+ }
+ }
+
+ InstrIterator iter;
+
+ for (iter = pvar_allocs.begin();
+ iter != pvar_allocs.end();
+ ++iter)
+ {
+ if (!RewritePersistentAlloc(*iter))
+ {
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite the creation of a persistent variable\n");
+
+ if (log)
+ log->PutCString("Couldn't rewrite the creation of a persistent variable");
+
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+IRForTarget::MaterializeInitializer (uint8_t *data, Constant *initializer)
+{
+ if (!initializer)
+ return true;
+
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log && log->GetVerbose())
+ log->Printf(" MaterializeInitializer(%p, %s)", (void *)data, PrintValue(initializer).c_str());
+
+ Type *initializer_type = initializer->getType();
+
+ if (ConstantInt *int_initializer = dyn_cast<ConstantInt>(initializer))
+ {
+ memcpy (data, int_initializer->getValue().getRawData(), m_target_data->getTypeStoreSize(initializer_type));
+ return true;
+ }
+ else if (ConstantDataArray *array_initializer = dyn_cast<ConstantDataArray>(initializer))
+ {
+ if (array_initializer->isString())
+ {
+ std::string array_initializer_string = array_initializer->getAsString();
+ memcpy (data, array_initializer_string.c_str(), m_target_data->getTypeStoreSize(initializer_type));
+ }
+ else
+ {
+ ArrayType *array_initializer_type = array_initializer->getType();
+ Type *array_element_type = array_initializer_type->getElementType();
+
+ size_t element_size = m_target_data->getTypeAllocSize(array_element_type);
+
+ for (unsigned i = 0; i < array_initializer->getNumOperands(); ++i)
+ {
+ Value *operand_value = array_initializer->getOperand(i);
+ Constant *operand_constant = dyn_cast<Constant>(operand_value);
+
+ if (!operand_constant)
+ return false;
+
+ if (!MaterializeInitializer(data + (i * element_size), operand_constant))
+ return false;
+ }
+ }
+ return true;
+ }
+ else if (ConstantStruct *struct_initializer = dyn_cast<ConstantStruct>(initializer))
+ {
+ StructType *struct_initializer_type = struct_initializer->getType();
+ const StructLayout *struct_layout = m_target_data->getStructLayout(struct_initializer_type);
+
+ for (unsigned i = 0;
+ i < struct_initializer->getNumOperands();
+ ++i)
+ {
+ if (!MaterializeInitializer(data + struct_layout->getElementOffset(i), struct_initializer->getOperand(i)))
+ return false;
+ }
+ return true;
+ }
+ else if (isa<ConstantAggregateZero>(initializer))
+ {
+ memset(data, 0, m_target_data->getTypeStoreSize(initializer_type));
+ return true;
+ }
+ return false;
+}
+
+bool
+IRForTarget::MaterializeInternalVariable (GlobalVariable *global_variable)
+{
+ if (GlobalVariable::isExternalLinkage(global_variable->getLinkage()))
+ return false;
+
+ if (global_variable == m_reloc_placeholder)
+ return true;
+
+ uint64_t offset = m_data_allocator.GetStream().GetSize();
+
+ llvm::Type *variable_type = global_variable->getType();
+
+ Constant *initializer = global_variable->getInitializer();
+
+ llvm::Type *initializer_type = initializer->getType();
+
+ size_t size = m_target_data->getTypeAllocSize(initializer_type);
+ size_t align = m_target_data->getPrefTypeAlignment(initializer_type);
+
+ const size_t mask = (align - 1);
+ uint64_t aligned_offset = (offset + mask) & ~mask;
+ m_data_allocator.GetStream().PutNHex8(aligned_offset - offset, 0);
+ offset = aligned_offset;
+
+ lldb_private::DataBufferHeap data(size, '\0');
+
+ if (initializer)
+ if (!MaterializeInitializer(data.GetBytes(), initializer))
+ return false;
+
+ m_data_allocator.GetStream().Write(data.GetBytes(), data.GetByteSize());
+
+ Constant *new_pointer = BuildRelocation(variable_type, offset);
+
+ global_variable->replaceAllUsesWith(new_pointer);
+
+ global_variable->eraseFromParent();
+
+ return true;
+}
+
+// This function does not report errors; its callers are responsible.
+bool
+IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr)
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ log->Printf("MaybeHandleVariable (%s)", PrintValue(llvm_value_ptr).c_str());
+
+ if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(llvm_value_ptr))
+ {
+ switch (constant_expr->getOpcode())
+ {
+ default:
+ break;
+ case Instruction::GetElementPtr:
+ case Instruction::BitCast:
+ Value *s = constant_expr->getOperand(0);
+ if (!MaybeHandleVariable(s))
+ return false;
+ }
+ }
+ else if (GlobalVariable *global_variable = dyn_cast<GlobalVariable>(llvm_value_ptr))
+ {
+ if (!GlobalValue::isExternalLinkage(global_variable->getLinkage()))
+ return MaterializeInternalVariable(global_variable);
+
+ clang::NamedDecl *named_decl = DeclForGlobal(global_variable);
+
+ if (!named_decl)
+ {
+ if (IsObjCSelectorRef(llvm_value_ptr))
+ return true;
+
+ if (!global_variable->hasExternalLinkage())
+ return true;
+
+ if (log)
+ log->Printf("Found global variable \"%s\" without metadata", global_variable->getName().str().c_str());
+
+ return false;
+ }
+
+ std::string name (named_decl->getName().str());
+
+ clang::ValueDecl *value_decl = dyn_cast<clang::ValueDecl>(named_decl);
+ if (value_decl == NULL)
+ return false;
+
+ lldb_private::CompilerType compiler_type(&value_decl->getASTContext(), value_decl->getType());
+
+ const Type *value_type = NULL;
+
+ if (name[0] == '$')
+ {
+ // The $__lldb_expr_result name indicates the return value has allocated as
+ // a static variable. Per the comment at ASTResultSynthesizer::SynthesizeBodyResult,
+ // accesses to this static variable need to be redirected to the result of dereferencing
+ // a pointer that is passed in as one of the arguments.
+ //
+ // Consequently, when reporting the size of the type, we report a pointer type pointing
+ // to the type of $__lldb_expr_result, not the type itself.
+ //
+ // We also do this for any user-declared persistent variables.
+ compiler_type = compiler_type.GetPointerType();
+ value_type = PointerType::get(global_variable->getType(), 0);
+ }
+ else
+ {
+ value_type = global_variable->getType();
+ }
+
+ const uint64_t value_size = compiler_type.GetByteSize(nullptr);
+ lldb::offset_t value_alignment = (compiler_type.GetTypeBitAlign() + 7ull) / 8ull;
+
+ if (log)
+ {
+ log->Printf("Type of \"%s\" is [clang \"%s\", llvm \"%s\"] [size %" PRIu64 ", align %" PRIu64 "]",
+ name.c_str(),
+ lldb_private::ClangASTContext::GetQualType(compiler_type).getAsString().c_str(),
+ PrintType(value_type).c_str(),
+ value_size,
+ value_alignment);
+ }
+
+
+ if (named_decl && !m_decl_map->AddValueToStruct(named_decl,
+ lldb_private::ConstString (name.c_str()),
+ llvm_value_ptr,
+ value_size,
+ value_alignment))
+ {
+ if (!global_variable->hasExternalLinkage())
+ return true;
+ else if (HandleSymbol (global_variable))
+ return true;
+ else
+ return false;
+ }
+ }
+ else if (dyn_cast<llvm::Function>(llvm_value_ptr))
+ {
+ if (log)
+ log->Printf("Function pointers aren't handled right now");
+
+ return false;
+ }
+
+ return true;
+}
+
+// This function does not report errors; its callers are responsible.
+bool
+IRForTarget::HandleSymbol (Value *symbol)
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ lldb_private::ConstString name(symbol->getName().str().c_str());
+
+ lldb::addr_t symbol_addr = m_decl_map->GetSymbolAddress (name, lldb::eSymbolTypeAny);
+
+ if (symbol_addr == LLDB_INVALID_ADDRESS)
+ {
+ if (log)
+ log->Printf ("Symbol \"%s\" had no address", name.GetCString());
+
+ return false;
+ }
+
+ if (log)
+ log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), symbol_addr);
+
+ Type *symbol_type = symbol->getType();
+
+ Constant *symbol_addr_int = ConstantInt::get(m_intptr_ty, symbol_addr, false);
+
+ Value *symbol_addr_ptr = ConstantExpr::getIntToPtr(symbol_addr_int, symbol_type);
+
+ if (log)
+ log->Printf("Replacing %s with %s", PrintValue(symbol).c_str(), PrintValue(symbol_addr_ptr).c_str());
+
+ symbol->replaceAllUsesWith(symbol_addr_ptr);
+
+ return true;
+}
+
+bool
+IRForTarget::MaybeHandleCallArguments (CallInst *Old)
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ log->Printf("MaybeHandleCallArguments(%s)", PrintValue(Old).c_str());
+
+ for (unsigned op_index = 0, num_ops = Old->getNumArgOperands();
+ op_index < num_ops;
+ ++op_index)
+ if (!MaybeHandleVariable(Old->getArgOperand(op_index))) // conservatively believe that this is a store
+ {
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite one of the arguments of a function call.\n");
+
+ return false;
+ }
+
+ return true;
+}
+
+bool
+IRForTarget::HandleObjCClass(Value *classlist_reference)
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ GlobalVariable *global_variable = dyn_cast<GlobalVariable>(classlist_reference);
+
+ if (!global_variable)
+ return false;
+
+ Constant *initializer = global_variable->getInitializer();
+
+ if (!initializer)
+ return false;
+
+ if (!initializer->hasName())
+ return false;
+
+ StringRef name(initializer->getName());
+ lldb_private::ConstString name_cstr(name.str().c_str());
+ lldb::addr_t class_ptr = m_decl_map->GetSymbolAddress(name_cstr, lldb::eSymbolTypeObjCClass);
+
+ if (log)
+ log->Printf("Found reference to Objective-C class %s (0x%llx)", name_cstr.AsCString(), (unsigned long long)class_ptr);
+
+ if (class_ptr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ if (global_variable->use_empty())
+ return false;
+
+ SmallVector<LoadInst *, 2> load_instructions;
+
+ for (llvm::User *u : global_variable->users())
+ {
+ if (LoadInst *load_instruction = dyn_cast<LoadInst>(u))
+ load_instructions.push_back(load_instruction);
+ }
+
+ if (load_instructions.empty())
+ return false;
+
+ Constant *class_addr = ConstantInt::get(m_intptr_ty, (uint64_t)class_ptr);
+
+ for (LoadInst *load_instruction : load_instructions)
+ {
+ Constant *class_bitcast = ConstantExpr::getIntToPtr(class_addr, load_instruction->getType());
+
+ load_instruction->replaceAllUsesWith(class_bitcast);
+
+ load_instruction->eraseFromParent();
+ }
+
+ return true;
+}
+
+bool
+IRForTarget::RemoveCXAAtExit (BasicBlock &basic_block)
+{
+ BasicBlock::iterator ii;
+
+ std::vector<CallInst *> calls_to_remove;
+
+ for (ii = basic_block.begin();
+ ii != basic_block.end();
+ ++ii)
+ {
+ Instruction &inst = *ii;
+
+ CallInst *call = dyn_cast<CallInst>(&inst);
+
+ // MaybeHandleCallArguments handles error reporting; we are silent here
+ if (!call)
+ continue;
+
+ bool remove = false;
+
+ llvm::Function *func = call->getCalledFunction();
+
+ if (func && func->getName() == "__cxa_atexit")
+ remove = true;
+
+ llvm::Value *val = call->getCalledValue();
+
+ if (val && val->getName() == "__cxa_atexit")
+ remove = true;
+
+ if (remove)
+ calls_to_remove.push_back(call);
+ }
+
+ for (std::vector<CallInst *>::iterator ci = calls_to_remove.begin(), ce = calls_to_remove.end();
+ ci != ce;
+ ++ci)
+ {
+ (*ci)->eraseFromParent();
+ }
+
+ return true;
+}
+
+bool
+IRForTarget::ResolveCalls(BasicBlock &basic_block)
+{
+ /////////////////////////////////////////////////////////////////////////
+ // Prepare the current basic block for execution in the remote process
+ //
+
+ BasicBlock::iterator ii;
+
+ for (ii = basic_block.begin();
+ ii != basic_block.end();
+ ++ii)
+ {
+ Instruction &inst = *ii;
+
+ CallInst *call = dyn_cast<CallInst>(&inst);
+
+ // MaybeHandleCallArguments handles error reporting; we are silent here
+ if (call && !MaybeHandleCallArguments(call))
+ return false;
+ }
+
+ return true;
+}
+
+bool
+IRForTarget::ResolveExternals (Function &llvm_function)
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ for (GlobalVariable &global_var : m_module->globals())
+ {
+ std::string global_name = global_var.getName().str();
+
+ if (log)
+ log->Printf("Examining %s, DeclForGlobalValue returns %p",
+ global_name.c_str(),
+ static_cast<void*>(DeclForGlobal(&global_var)));
+
+ if (global_name.find("OBJC_IVAR") == 0)
+ {
+ if (!HandleSymbol(&global_var))
+ {
+ if (m_error_stream)
+ m_error_stream->Printf("Error [IRForTarget]: Couldn't find Objective-C indirect ivar symbol %s\n", global_name.c_str());
+
+ return false;
+ }
+ }
+ else if (global_name.find("OBJC_CLASSLIST_REFERENCES_$") != global_name.npos)
+ {
+ if (!HandleObjCClass(&global_var))
+ {
+ if (m_error_stream)
+ m_error_stream->Printf("Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call\n");
+
+ return false;
+ }
+ }
+ else if (global_name.find("OBJC_CLASSLIST_SUP_REFS_$") != global_name.npos)
+ {
+ if (!HandleObjCClass(&global_var))
+ {
+ if (m_error_stream)
+ m_error_stream->Printf("Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call\n");
+
+ return false;
+ }
+ }
+ else if (DeclForGlobal(&global_var))
+ {
+ if (!MaybeHandleVariable (&global_var))
+ {
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite external variable %s\n", global_name.c_str());
+
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool
+IRForTarget::ReplaceStrings ()
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ typedef std::map <GlobalVariable *, size_t> OffsetsTy;
+
+ OffsetsTy offsets;
+
+ for (GlobalVariable &gv : m_module->globals())
+ {
+ if (!gv.hasInitializer())
+ continue;
+
+ Constant *gc = gv.getInitializer();
+
+ std::string str;
+
+ if (gc->isNullValue())
+ {
+ Type *gc_type = gc->getType();
+
+ ArrayType *gc_array_type = dyn_cast<ArrayType>(gc_type);
+
+ if (!gc_array_type)
+ continue;
+
+ Type *gc_element_type = gc_array_type->getElementType();
+
+ IntegerType *gc_integer_type = dyn_cast<IntegerType>(gc_element_type);
+
+ if (gc_integer_type->getBitWidth() != 8)
+ continue;
+
+ str = "";
+ }
+ else
+ {
+ ConstantDataArray *gc_array = dyn_cast<ConstantDataArray>(gc);
+
+ if (!gc_array)
+ continue;
+
+ if (!gc_array->isCString())
+ continue;
+
+ if (log)
+ log->Printf("Found a GlobalVariable with string initializer %s", PrintValue(gc).c_str());
+
+ str = gc_array->getAsString();
+ }
+
+ offsets[&gv] = m_data_allocator.GetStream().GetSize();
+
+ m_data_allocator.GetStream().Write(str.c_str(), str.length() + 1);
+ }
+
+ Type *char_ptr_ty = Type::getInt8PtrTy(m_module->getContext());
+
+ for (OffsetsTy::iterator oi = offsets.begin(), oe = offsets.end();
+ oi != oe;
+ ++oi)
+ {
+ GlobalVariable *gv = oi->first;
+ size_t offset = oi->second;
+
+ Constant *new_initializer = BuildRelocation(char_ptr_ty, offset);
+
+ if (log)
+ log->Printf("Replacing GV %s with %s", PrintValue(gv).c_str(), PrintValue(new_initializer).c_str());
+
+ for (llvm::User *u : gv->users())
+ {
+ if (log)
+ log->Printf("Found use %s", PrintValue(u).c_str());
+
+ ConstantExpr *const_expr = dyn_cast<ConstantExpr>(u);
+ StoreInst *store_inst = dyn_cast<StoreInst>(u);
+
+ if (const_expr)
+ {
+ if (const_expr->getOpcode() != Instruction::GetElementPtr)
+ {
+ if (log)
+ log->Printf("Use (%s) of string variable is not a GetElementPtr constant", PrintValue(const_expr).c_str());
+
+ return false;
+ }
+
+ Constant *bit_cast = ConstantExpr::getBitCast(new_initializer, const_expr->getOperand(0)->getType());
+ Constant *new_gep = const_expr->getWithOperandReplaced(0, bit_cast);
+
+ const_expr->replaceAllUsesWith(new_gep);
+ }
+ else if (store_inst)
+ {
+ Constant *bit_cast = ConstantExpr::getBitCast(new_initializer, store_inst->getValueOperand()->getType());
+
+ store_inst->setOperand(0, bit_cast);
+ }
+ else
+ {
+ if (log)
+ log->Printf("Use (%s) of string variable is neither a constant nor a store", PrintValue(const_expr).c_str());
+
+ return false;
+ }
+ }
+
+ gv->eraseFromParent();
+ }
+
+ return true;
+}
+
+bool
+IRForTarget::ReplaceStaticLiterals (llvm::BasicBlock &basic_block)
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ typedef SmallVector <Value*, 2> ConstantList;
+ typedef SmallVector <llvm::Instruction*, 2> UserList;
+ typedef ConstantList::iterator ConstantIterator;
+ typedef UserList::iterator UserIterator;
+
+ ConstantList static_constants;
+ UserList static_users;
+
+ for (BasicBlock::iterator ii = basic_block.begin(), ie = basic_block.end();
+ ii != ie;
+ ++ii)
+ {
+ llvm::Instruction &inst = *ii;
+
+ for (Value *operand_val : inst.operand_values())
+ {
+ ConstantFP *operand_constant_fp = dyn_cast<ConstantFP>(operand_val);
+
+ if (operand_constant_fp/* && operand_constant_fp->getType()->isX86_FP80Ty()*/)
+ {
+ static_constants.push_back(operand_val);
+ static_users.push_back(&*ii);
+ }
+ }
+ }
+
+ ConstantIterator constant_iter;
+ UserIterator user_iter;
+
+ for (constant_iter = static_constants.begin(), user_iter = static_users.begin();
+ constant_iter != static_constants.end();
+ ++constant_iter, ++user_iter)
+ {
+ Value *operand_val = *constant_iter;
+ llvm::Instruction *inst = *user_iter;
+
+ ConstantFP *operand_constant_fp = dyn_cast<ConstantFP>(operand_val);
+
+ if (operand_constant_fp)
+ {
+ Type *operand_type = operand_constant_fp->getType();
+
+ APFloat operand_apfloat = operand_constant_fp->getValueAPF();
+ APInt operand_apint = operand_apfloat.bitcastToAPInt();
+
+ const uint8_t* operand_raw_data = (const uint8_t*)operand_apint.getRawData();
+ size_t operand_data_size = operand_apint.getBitWidth() / 8;
+
+ if (log)
+ {
+ std::string s;
+ raw_string_ostream ss(s);
+ for (size_t index = 0;
+ index < operand_data_size;
+ ++index)
+ {
+ ss << (uint32_t)operand_raw_data[index];
+ ss << " ";
+ }
+ ss.flush();
+
+ log->Printf("Found ConstantFP with size %" PRIu64 " and raw data %s", (uint64_t)operand_data_size, s.c_str());
+ }
+
+ lldb_private::DataBufferHeap data(operand_data_size, 0);
+
+ if (lldb_private::endian::InlHostByteOrder() != m_data_allocator.GetStream().GetByteOrder())
+ {
+ uint8_t *data_bytes = data.GetBytes();
+
+ for (size_t index = 0;
+ index < operand_data_size;
+ ++index)
+ {
+ data_bytes[index] = operand_raw_data[operand_data_size - (1 + index)];
+ }
+ }
+ else
+ {
+ memcpy(data.GetBytes(), operand_raw_data, operand_data_size);
+ }
+
+ uint64_t offset = m_data_allocator.GetStream().GetSize();
+
+ size_t align = m_target_data->getPrefTypeAlignment(operand_type);
+
+ const size_t mask = (align - 1);
+ uint64_t aligned_offset = (offset + mask) & ~mask;
+ m_data_allocator.GetStream().PutNHex8(aligned_offset - offset, 0);
+
+ m_data_allocator.GetStream().Write(data.GetBytes(), operand_data_size);
+
+ llvm::Type *fp_ptr_ty = operand_constant_fp->getType()->getPointerTo();
+
+ Constant *new_pointer = BuildRelocation(fp_ptr_ty, aligned_offset);
+
+ llvm::LoadInst *fp_load = new llvm::LoadInst(new_pointer, "fp_load", inst);
+
+ operand_constant_fp->replaceAllUsesWith(fp_load);
+ }
+ }
+
+ return true;
+}
+
+static bool isGuardVariableRef(Value *V)
+{
+ Constant *Old = NULL;
+
+ if (!(Old = dyn_cast<Constant>(V)))
+ return false;
+
+ ConstantExpr *CE = NULL;
+
+ if ((CE = dyn_cast<ConstantExpr>(V)))
+ {
+ if (CE->getOpcode() != Instruction::BitCast)
+ return false;
+
+ Old = CE->getOperand(0);
+ }
+
+ GlobalVariable *GV = dyn_cast<GlobalVariable>(Old);
+
+ if (!GV || !GV->hasName() ||
+ (!GV->getName().startswith("_ZGV") && // Itanium ABI guard variable
+ !GV->getName().endswith("@4IA"))) // Microsoft ABI guard variable
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void
+IRForTarget::TurnGuardLoadIntoZero(llvm::Instruction* guard_load)
+{
+ Constant *zero(Constant::getNullValue(guard_load->getType()));
+ guard_load->replaceAllUsesWith(zero);
+ guard_load->eraseFromParent();
+}
+
+static void ExciseGuardStore(Instruction* guard_store)
+{
+ guard_store->eraseFromParent();
+}
+
+bool
+IRForTarget::RemoveGuards(BasicBlock &basic_block)
+{
+ ///////////////////////////////////////////////////////
+ // Eliminate any reference to guard variables found.
+ //
+
+ BasicBlock::iterator ii;
+
+ typedef SmallVector <Instruction*, 2> InstrList;
+ typedef InstrList::iterator InstrIterator;
+
+ InstrList guard_loads;
+ InstrList guard_stores;
+
+ for (ii = basic_block.begin();
+ ii != basic_block.end();
+ ++ii)
+ {
+ Instruction &inst = *ii;
+
+ if (LoadInst *load = dyn_cast<LoadInst>(&inst))
+ if (isGuardVariableRef(load->getPointerOperand()))
+ guard_loads.push_back(&inst);
+
+ if (StoreInst *store = dyn_cast<StoreInst>(&inst))
+ if (isGuardVariableRef(store->getPointerOperand()))
+ guard_stores.push_back(&inst);
+ }
+
+ InstrIterator iter;
+
+ for (iter = guard_loads.begin();
+ iter != guard_loads.end();
+ ++iter)
+ TurnGuardLoadIntoZero(*iter);
+
+ for (iter = guard_stores.begin();
+ iter != guard_stores.end();
+ ++iter)
+ ExciseGuardStore(*iter);
+
+ return true;
+}
+
+// This function does not report errors; its callers are responsible.
+bool
+IRForTarget::UnfoldConstant(Constant *old_constant,
+ FunctionValueCache &value_maker,
+ FunctionValueCache &entry_instruction_finder)
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ SmallVector<User*, 16> users;
+
+ // We do this because the use list might change, invalidating our iterator.
+ // Much better to keep a work list ourselves.
+ for (llvm::User *u : old_constant->users())
+ users.push_back(u);
+
+ for (size_t i = 0;
+ i < users.size();
+ ++i)
+ {
+ User *user = users[i];
+
+ if (Constant *constant = dyn_cast<Constant>(user))
+ {
+ // synthesize a new non-constant equivalent of the constant
+
+ if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant))
+ {
+ switch (constant_expr->getOpcode())
+ {
+ default:
+ if (log)
+ log->Printf("Unhandled constant expression type: \"%s\"", PrintValue(constant_expr).c_str());
+ return false;
+ case Instruction::BitCast:
+ {
+ FunctionValueCache bit_cast_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* {
+ // UnaryExpr
+ // OperandList[0] is value
+
+ if (constant_expr->getOperand(0) != old_constant)
+ return constant_expr;
+
+ return new BitCastInst(value_maker.GetValue(function),
+ constant_expr->getType(),
+ "",
+ llvm::cast<Instruction>(entry_instruction_finder.GetValue(function)));
+ });
+
+ if (!UnfoldConstant(constant_expr, bit_cast_maker, entry_instruction_finder))
+ return false;
+ }
+ break;
+ case Instruction::GetElementPtr:
+ {
+ // GetElementPtrConstantExpr
+ // OperandList[0] is base
+ // OperandList[1]... are indices
+
+ FunctionValueCache get_element_pointer_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* {
+ Value *ptr = constant_expr->getOperand(0);
+
+ if (ptr == old_constant)
+ ptr = value_maker.GetValue(function);
+
+ std::vector<Value*> index_vector;
+
+ unsigned operand_index;
+ unsigned num_operands = constant_expr->getNumOperands();
+
+ for (operand_index = 1;
+ operand_index < num_operands;
+ ++operand_index)
+ {
+ Value *operand = constant_expr->getOperand(operand_index);
+
+ if (operand == old_constant)
+ operand = value_maker.GetValue(function);
+
+ index_vector.push_back(operand);
+ }
+
+ ArrayRef <Value*> indices(index_vector);
+
+ return GetElementPtrInst::Create(nullptr, ptr, indices, "", llvm::cast<Instruction>(entry_instruction_finder.GetValue(function)));
+ });
+
+ if (!UnfoldConstant(constant_expr, get_element_pointer_maker, entry_instruction_finder))
+ return false;
+ }
+ break;
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf("Unhandled constant type: \"%s\"", PrintValue(constant).c_str());
+ return false;
+ }
+ }
+ else
+ {
+ if (Instruction *inst = llvm::dyn_cast<Instruction>(user))
+ {
+ inst->replaceUsesOfWith(old_constant, value_maker.GetValue(inst->getParent()->getParent()));
+ }
+ else
+ {
+ if (log)
+ log->Printf("Unhandled non-constant type: \"%s\"", PrintValue(user).c_str());
+ return false;
+ }
+ }
+ }
+
+ if (!isa<GlobalValue>(old_constant))
+ {
+ old_constant->destroyConstant();
+ }
+
+ return true;
+}
+
+bool
+IRForTarget::ReplaceVariables (Function &llvm_function)
+{
+ if (!m_resolve_vars)
+ return true;
+
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ m_decl_map->DoStructLayout();
+
+ if (log)
+ log->Printf("Element arrangement:");
+
+ uint32_t num_elements;
+ uint32_t element_index;
+
+ size_t size;
+ lldb::offset_t alignment;
+
+ if (!m_decl_map->GetStructInfo (num_elements, size, alignment))
+ return false;
+
+ Function::arg_iterator iter(llvm_function.getArgumentList().begin());
+
+ if (iter == llvm_function.getArgumentList().end())
+ {
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes no arguments (should take at least a struct pointer)");
+
+ return false;
+ }
+
+ Argument *argument = &*iter;
+
+ if (argument->getName().equals("this"))
+ {
+ ++iter;
+
+ if (iter == llvm_function.getArgumentList().end())
+ {
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'this' argument (should take a struct pointer too)");
+
+ return false;
+ }
+
+ argument = &*iter;
+ }
+ else if (argument->getName().equals("self"))
+ {
+ ++iter;
+
+ if (iter == llvm_function.getArgumentList().end())
+ {
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'self' argument (should take '_cmd' and a struct pointer too)");
+
+ return false;
+ }
+
+ if (!iter->getName().equals("_cmd"))
+ {
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes '%s' after 'self' argument (should take '_cmd')", iter->getName().str().c_str());
+
+ return false;
+ }
+
+ ++iter;
+
+ if (iter == llvm_function.getArgumentList().end())
+ {
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'self' and '_cmd' arguments (should take a struct pointer too)");
+
+ return false;
+ }
+
+ argument = &*iter;
+ }
+
+ if (!argument->getName().equals("$__lldb_arg"))
+ {
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes an argument named '%s' instead of the struct pointer", argument->getName().str().c_str());
+
+ return false;
+ }
+
+ if (log)
+ log->Printf("Arg: \"%s\"", PrintValue(argument).c_str());
+
+ BasicBlock &entry_block(llvm_function.getEntryBlock());
+ Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg());
+
+ if (!FirstEntryInstruction)
+ {
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find the first instruction in the wrapper for use in rewriting");
+
+ return false;
+ }
+
+ LLVMContext &context(m_module->getContext());
+ IntegerType *offset_type(Type::getInt32Ty(context));
+
+ if (!offset_type)
+ {
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Couldn't produce an offset type");
+
+ return false;
+ }
+
+ for (element_index = 0; element_index < num_elements; ++element_index)
+ {
+ const clang::NamedDecl *decl = NULL;
+ Value *value = NULL;
+ lldb::offset_t offset;
+ lldb_private::ConstString name;
+
+ if (!m_decl_map->GetStructElement (decl, value, offset, name, element_index))
+ {
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Structure information is incomplete");
+
+ return false;
+ }
+
+ if (log)
+ log->Printf(" \"%s\" (\"%s\") placed at %" PRIu64,
+ name.GetCString(),
+ decl->getNameAsString().c_str(),
+ offset);
+
+ if (value)
+ {
+ if (log)
+ log->Printf(" Replacing [%s]", PrintValue(value).c_str());
+
+ FunctionValueCache body_result_maker ([this, name, offset_type, offset, argument, value] (llvm::Function *function)->llvm::Value * {
+ // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, in cases where the result
+ // variable is an rvalue, we have to synthesize a dereference of the appropriate structure
+ // entry in order to produce the static variable that the AST thinks it is accessing.
+
+ llvm::Instruction *entry_instruction = llvm::cast<Instruction>(m_entry_instruction_finder.GetValue(function));
+
+ ConstantInt *offset_int(ConstantInt::get(offset_type, offset, true));
+ GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(nullptr,
+ argument,
+ offset_int,
+ "",
+ entry_instruction);
+
+ if (name == m_result_name && !m_result_is_pointer)
+ {
+ BitCastInst *bit_cast = new BitCastInst(get_element_ptr,
+ value->getType()->getPointerTo(),
+ "",
+ entry_instruction);
+
+ LoadInst *load = new LoadInst(bit_cast, "", entry_instruction);
+
+ return load;
+ }
+ else
+ {
+ BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType(), "", entry_instruction);
+
+ return bit_cast;
+ }
+ });
+
+ if (Constant *constant = dyn_cast<Constant>(value))
+ {
+ UnfoldConstant(constant, body_result_maker, m_entry_instruction_finder);
+ }
+ else if (Instruction *instruction = dyn_cast<Instruction>(value))
+ {
+ value->replaceAllUsesWith(body_result_maker.GetValue(instruction->getParent()->getParent()));
+ }
+ else
+ {
+ if (log)
+ log->Printf("Unhandled non-constant type: \"%s\"", PrintValue(value).c_str());
+ return false;
+ }
+
+ if (GlobalVariable *var = dyn_cast<GlobalVariable>(value))
+ var->eraseFromParent();
+ }
+ }
+
+ if (log)
+ log->Printf("Total structure [align %" PRId64 ", size %" PRIu64 "]", (int64_t)alignment, (uint64_t)size);
+
+ return true;
+}
+
+llvm::Constant *
+IRForTarget::BuildRelocation(llvm::Type *type, uint64_t offset)
+{
+ llvm::Constant *offset_int = ConstantInt::get(m_intptr_ty, offset);
+
+ llvm::Constant *offset_array[1];
+
+ offset_array[0] = offset_int;
+
+ llvm::ArrayRef<llvm::Constant *> offsets(offset_array, 1);
+ llvm::Type *char_type = llvm::Type::getInt8Ty(m_module->getContext());
+ llvm::Type *char_pointer_type = char_type->getPointerTo();
+
+ llvm::Constant *reloc_placeholder_bitcast = ConstantExpr::getBitCast(m_reloc_placeholder, char_pointer_type);
+ llvm::Constant *reloc_getelementptr = ConstantExpr::getGetElementPtr(char_type, reloc_placeholder_bitcast, offsets);
+ llvm::Constant *reloc_bitcast = ConstantExpr::getBitCast(reloc_getelementptr, type);
+
+ return reloc_bitcast;
+}
+
+bool
+IRForTarget::CompleteDataAllocation ()
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (!m_data_allocator.GetStream().GetSize())
+ return true;
+
+ lldb::addr_t allocation = m_data_allocator.Allocate();
+
+ if (log)
+ {
+ if (allocation)
+ log->Printf("Allocated static data at 0x%llx", (unsigned long long)allocation);
+ else
+ log->Printf("Failed to allocate static data");
+ }
+
+ if (!allocation || allocation == LLDB_INVALID_ADDRESS)
+ return false;
+
+ Constant *relocated_addr = ConstantInt::get(m_intptr_ty, (uint64_t)allocation);
+ Constant *relocated_bitcast = ConstantExpr::getIntToPtr(relocated_addr, llvm::Type::getInt8PtrTy(m_module->getContext()));
+
+ m_reloc_placeholder->replaceAllUsesWith(relocated_bitcast);
+
+ m_reloc_placeholder->eraseFromParent();
+
+ return true;
+}
+
+bool
+IRForTarget::StripAllGVs (Module &llvm_module)
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ std::vector<GlobalVariable *> global_vars;
+ std::set<GlobalVariable *>erased_vars;
+
+ bool erased = true;
+
+ while (erased)
+ {
+ erased = false;
+
+ for (GlobalVariable &global_var : llvm_module.globals())
+ {
+ global_var.removeDeadConstantUsers();
+
+ if (global_var.use_empty())
+ {
+ if (log)
+ log->Printf("Did remove %s",
+ PrintValue(&global_var).c_str());
+ global_var.eraseFromParent();
+ erased = true;
+ break;
+ }
+ }
+ }
+
+ for (GlobalVariable &global_var : llvm_module.globals())
+ {
+ GlobalValue::user_iterator ui = global_var.user_begin();
+
+ if (log)
+ log->Printf("Couldn't remove %s because of %s",
+ PrintValue(&global_var).c_str(),
+ PrintValue(*ui).c_str());
+ }
+
+ return true;
+}
+
+bool
+IRForTarget::runOnModule (Module &llvm_module)
+{
+ lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ m_module = &llvm_module;
+ m_target_data.reset(new DataLayout(m_module));
+ m_intptr_ty = llvm::Type::getIntNTy(m_module->getContext(), m_target_data->getPointerSizeInBits());
+
+ if (log)
+ {
+ std::string s;
+ raw_string_ostream oss(s);
+
+ m_module->print(oss, NULL);
+
+ oss.flush();
+
+ log->Printf("Module as passed in to IRForTarget: \n\"%s\"", s.c_str());
+ }
+
+ Function* main_function = m_module->getFunction(StringRef(m_func_name.c_str()));
+
+ if (!main_function)
+ {
+ if (log)
+ log->Printf("Couldn't find \"%s()\" in the module", m_func_name.c_str());
+
+ if (m_error_stream)
+ m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find wrapper '%s' in the module", m_func_name.c_str());
+
+ return false;
+ }
+
+ if (!FixFunctionLinkage (*main_function))
+ {
+ if (log)
+ log->Printf("Couldn't fix the linkage for the function");
+
+ return false;
+ }
+
+ llvm::Type *int8_ty = Type::getInt8Ty(m_module->getContext());
+
+ m_reloc_placeholder = new llvm::GlobalVariable((*m_module),
+ int8_ty,
+ false /* IsConstant */,
+ GlobalVariable::InternalLinkage,
+ Constant::getNullValue(int8_ty),
+ "reloc_placeholder",
+ NULL /* InsertBefore */,
+ GlobalVariable::NotThreadLocal /* ThreadLocal */,
+ 0 /* AddressSpace */);
+
+ ////////////////////////////////////////////////////////////
+ // Replace $__lldb_expr_result with a persistent variable
+ //
+
+ if (!CreateResultVariable(*main_function))
+ {
+ if (log)
+ log->Printf("CreateResultVariable() failed");
+
+ // CreateResultVariable() reports its own errors, so we don't do so here
+
+ return false;
+ }
+
+ if (log && log->GetVerbose())
+ {
+ std::string s;
+ raw_string_ostream oss(s);
+
+ m_module->print(oss, NULL);
+
+ oss.flush();
+
+ log->Printf("Module after creating the result variable: \n\"%s\"", s.c_str());
+ }
+
+ for (Module::iterator fi = m_module->begin(), fe = m_module->end();
+ fi != fe;
+ ++fi)
+ {
+ llvm::Function *function = &*fi;
+
+ if (function->begin() == function->end())
+ continue;
+
+ Function::iterator bbi;
+
+ for (bbi = function->begin();
+ bbi != function->end();
+ ++bbi)
+ {
+ if (!RemoveGuards(*bbi))
+ {
+ if (log)
+ log->Printf("RemoveGuards() failed");
+
+ // RemoveGuards() reports its own errors, so we don't do so here
+
+ return false;
+ }
+
+ if (!RewritePersistentAllocs(*bbi))
+ {
+ if (log)
+ log->Printf("RewritePersistentAllocs() failed");
+
+ // RewritePersistentAllocs() reports its own errors, so we don't do so here
+
+ return false;
+ }
+
+ if (!RemoveCXAAtExit(*bbi))
+ {
+ if (log)
+ log->Printf("RemoveCXAAtExit() failed");
+
+ // RemoveCXAAtExit() reports its own errors, so we don't do so here
+
+ return false;
+ }
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Fix all Objective-C constant strings to use NSStringWithCString:encoding:
+ //
+
+ if (!RewriteObjCConstStrings())
+ {
+ if (log)
+ log->Printf("RewriteObjCConstStrings() failed");
+
+ // RewriteObjCConstStrings() reports its own errors, so we don't do so here
+
+ return false;
+ }
+
+ ///////////////////////////////
+ // Resolve function pointers
+ //
+
+ if (!ResolveFunctionPointers(llvm_module))
+ {
+ if (log)
+ log->Printf("ResolveFunctionPointers() failed");
+
+ // ResolveFunctionPointers() reports its own errors, so we don't do so here
+
+ return false;
+ }
+
+ for (Module::iterator fi = m_module->begin(), fe = m_module->end();
+ fi != fe;
+ ++fi)
+ {
+ llvm::Function *function = &*fi;
+
+ for (llvm::Function::iterator bbi = function->begin(), bbe = function->end();
+ bbi != bbe;
+ ++bbi)
+ {
+ if (!RewriteObjCSelectors(*bbi))
+ {
+ if (log)
+ log->Printf("RewriteObjCSelectors() failed");
+
+ // RewriteObjCSelectors() reports its own errors, so we don't do so here
+
+ return false;
+ }
+ }
+ }
+
+ for (Module::iterator fi = m_module->begin(), fe = m_module->end();
+ fi != fe;
+ ++fi)
+ {
+ llvm::Function *function = &*fi;
+
+ for (llvm::Function::iterator bbi = function->begin(), bbe = function->end();
+ bbi != bbe;
+ ++bbi)
+ {
+ if (!ResolveCalls(*bbi))
+ {
+ if (log)
+ log->Printf("ResolveCalls() failed");
+
+ // ResolveCalls() reports its own errors, so we don't do so here
+
+ return false;
+ }
+
+ if (!ReplaceStaticLiterals(*bbi))
+ {
+ if (log)
+ log->Printf("ReplaceStaticLiterals() failed");
+
+ return false;
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Run function-level passes that only make sense on the main function
+ //
+
+ if (!ResolveExternals(*main_function))
+ {
+ if (log)
+ log->Printf("ResolveExternals() failed");
+
+ // ResolveExternals() reports its own errors, so we don't do so here
+
+ return false;
+ }
+
+ if (!ReplaceVariables(*main_function))
+ {
+ if (log)
+ log->Printf("ReplaceVariables() failed");
+
+ // ReplaceVariables() reports its own errors, so we don't do so here
+
+ return false;
+ }
+
+ if (!ReplaceStrings())
+ {
+ if (log)
+ log->Printf("ReplaceStrings() failed");
+
+ return false;
+ }
+
+ if (!CompleteDataAllocation())
+ {
+ if (log)
+ log->Printf("CompleteDataAllocation() failed");
+
+ return false;
+ }
+
+ if (!StripAllGVs(llvm_module))
+ {
+ if (log)
+ log->Printf("StripAllGVs() failed");
+ }
+
+ if (log && log->GetVerbose())
+ {
+ std::string s;
+ raw_string_ostream oss(s);
+
+ m_module->print(oss, NULL);
+
+ oss.flush();
+
+ log->Printf("Module after preparing for execution: \n\"%s\"", s.c_str());
+ }
+
+ return true;
+}
+
+void
+IRForTarget::assignPassManager (PMStack &pass_mgr_stack, PassManagerType pass_mgr_type)
+{
+}
+
+PassManagerType
+IRForTarget::getPotentialPassManagerType() const
+{
+ return PMT_ModulePassManager;
+}
diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.h b/source/Plugins/ExpressionParser/Clang/IRForTarget.h
new file mode 100644
index 000000000000..fb4abcc103de
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.h
@@ -0,0 +1,745 @@
+//===-- IRForTarget.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_IRForTarget_h_
+#define liblldb_IRForTarget_h_
+
+#include "lldb/lldb-public.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Symbol/TaggedASTType.h"
+#include "llvm/Pass.h"
+
+#include <map>
+#include <functional>
+
+namespace llvm {
+ class BasicBlock;
+ class CallInst;
+ class Constant;
+ class ConstantInt;
+ class Function;
+ class GlobalValue;
+ class GlobalVariable;
+ class Instruction;
+ class IntegerType;
+ class Module;
+ class StoreInst;
+ class DataLayout;
+ class Type;
+ class Value;
+}
+
+namespace lldb_private {
+ class ClangExpressionDeclMap;
+ class IRExecutionUnit;
+ class IRMemoryMap;
+}
+
+//----------------------------------------------------------------------
+/// @class IRForTarget IRForTarget.h "lldb/Expression/IRForTarget.h"
+/// @brief Transforms the IR for a function to run in the target
+///
+/// Once an expression has been parsed and converted to IR, it can run
+/// in two contexts: interpreted by LLDB as a DWARF location expression,
+/// or compiled by the JIT and inserted into the target process for
+/// execution.
+///
+/// IRForTarget makes the second possible, by applying a series of
+/// transformations to the IR which make it relocatable. These
+/// transformations are discussed in more detail next to their relevant
+/// functions.
+//----------------------------------------------------------------------
+class IRForTarget : public llvm::ModulePass
+{
+public:
+ enum class LookupResult {
+ Success,
+ Fail,
+ Ignore
+ };
+
+ //------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// @param[in] decl_map
+ /// The list of externally-referenced variables for the expression,
+ /// for use in looking up globals and allocating the argument
+ /// struct. See the documentation for ClangExpressionDeclMap.
+ ///
+ /// @param[in] resolve_vars
+ /// True if the external variable references (including persistent
+ /// 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.
+ ///
+ /// @param[in] error_stream
+ /// If non-NULL, a stream on which errors can be printed.
+ ///
+ /// @param[in] func_name
+ /// The name of the function to prepare for execution in the target.
+ //------------------------------------------------------------------
+ IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map,
+ bool resolve_vars,
+ lldb_private::IRExecutionUnit &execution_unit,
+ lldb_private::Stream *error_stream,
+ const char* func_name = "$__lldb_expr");
+
+ //------------------------------------------------------------------
+ /// Destructor
+ //------------------------------------------------------------------
+ ~IRForTarget() override;
+
+ //------------------------------------------------------------------
+ /// Run this IR transformer on a single module
+ ///
+ /// Implementation of the llvm::ModulePass::runOnModule() function.
+ ///
+ /// @param[in] llvm_module
+ /// The module to run on. This module is searched for the function
+ /// $__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;
+
+ //------------------------------------------------------------------
+ /// Interface stub
+ ///
+ /// Implementation of the llvm::ModulePass::assignPassManager()
+ /// function.
+ //------------------------------------------------------------------
+ void
+ assignPassManager(llvm::PMStack &pass_mgr_stack,
+ llvm::PassManagerType pass_mgr_type = llvm::PMT_ModulePassManager) override;
+
+ //------------------------------------------------------------------
+ /// Returns PMT_ModulePassManager
+ ///
+ /// Implementation of the llvm::ModulePass::getPotentialPassManagerType()
+ /// function.
+ //------------------------------------------------------------------
+ llvm::PassManagerType
+ getPotentialPassManagerType() const override;
+
+private:
+ //------------------------------------------------------------------
+ /// Ensures that the current function's linkage is set to external.
+ /// Otherwise the JIT may not return an address for it.
+ ///
+ /// @param[in] llvm_function
+ /// The function whose linkage is to be fixed.
+ ///
+ /// @return
+ /// True on success; false otherwise.
+ //------------------------------------------------------------------
+ bool
+ FixFunctionLinkage (llvm::Function &llvm_function);
+
+ //------------------------------------------------------------------
+ /// A module-level pass to replace all function pointers with their
+ /// integer equivalents.
+ //------------------------------------------------------------------
+
+ //------------------------------------------------------------------
+ /// The top-level pass implementation
+ ///
+ /// @param[in] llvm_module
+ /// The module currently being processed.
+ ///
+ /// @param[in] llvm_function
+ /// The function currently being processed.
+ ///
+ /// @return
+ /// True on success; false otherwise.
+ //------------------------------------------------------------------
+ bool
+ HasSideEffects (llvm::Function &llvm_function);
+
+ //------------------------------------------------------------------
+ /// A function-level pass to check whether the function has side
+ /// effects.
+ //------------------------------------------------------------------
+
+ //------------------------------------------------------------------
+ /// Get the address of a function, and a location to put the complete
+ /// Value of the function if one is available.
+ ///
+ /// @param[in] function
+ /// The function to find the location of.
+ ///
+ /// @param[out] ptr
+ /// The location of the function in the target.
+ ///
+ /// @param[out] name
+ /// The resolved name of the function (matters for intrinsics).
+ ///
+ /// @param[out] value_ptr
+ /// A variable to put the function's completed Value* in, or NULL
+ /// if the Value* shouldn't be stored anywhere.
+ ///
+ /// @return
+ /// The pointer.
+ //------------------------------------------------------------------
+ LookupResult
+ GetFunctionAddress (llvm::Function *function,
+ uint64_t &ptr,
+ lldb_private::ConstString &name,
+ llvm::Constant **&value_ptr);
+
+ //------------------------------------------------------------------
+ /// Build a function pointer given a type and a raw pointer.
+ ///
+ /// @param[in] type
+ /// The type of the function pointer to be built.
+ ///
+ /// @param[in] ptr
+ /// The value of the pointer.
+ ///
+ /// @return
+ /// The pointer.
+ //------------------------------------------------------------------
+ llvm::Constant *
+ BuildFunctionPointer (llvm::Type *type,
+ uint64_t ptr);
+
+ void
+ RegisterFunctionMetadata (llvm::LLVMContext &context,
+ llvm::Value *function_ptr,
+ const char *name);
+
+ //------------------------------------------------------------------
+ /// The top-level pass implementation
+ ///
+ /// @param[in] llvm_function
+ /// The function currently being processed.
+ ///
+ /// @return
+ /// True if the function has side effects (or if this cannot
+ /// be determined); false otherwise.
+ //------------------------------------------------------------------
+ bool
+ ResolveFunctionPointers (llvm::Module &llvm_module);
+
+ //------------------------------------------------------------------
+ /// A function-level pass to take the generated global value
+ /// $__lldb_expr_result and make it into a persistent variable.
+ /// Also see ASTResultSynthesizer.
+ //------------------------------------------------------------------
+
+ //------------------------------------------------------------------
+ /// Find the NamedDecl corresponding to a Value. This interface is
+ /// exposed for the IR interpreter.
+ ///
+ /// @param[in] module
+ /// The module containing metadata to search
+ ///
+ /// @param[in] global
+ /// The global entity to search for
+ ///
+ /// @return
+ /// The corresponding variable declaration
+ //------------------------------------------------------------------
+public:
+ static clang::NamedDecl *
+ DeclForGlobal (const llvm::GlobalValue *global_val, llvm::Module *module);
+private:
+ clang::NamedDecl *
+ DeclForGlobal (llvm::GlobalValue *global);
+
+ //------------------------------------------------------------------
+ /// Set the constant result variable m_const_result to the provided
+ /// constant, assuming it can be evaluated. The result variable
+ /// will be reset to NULL later if the expression has side effects.
+ ///
+ /// @param[in] initializer
+ /// The constant initializer for the variable.
+ ///
+ /// @param[in] name
+ /// The name of the result variable.
+ ///
+ /// @param[in] type
+ /// The Clang type of the result variable.
+ //------------------------------------------------------------------
+ void
+ MaybeSetConstantResult (llvm::Constant *initializer,
+ const lldb_private::ConstString &name,
+ lldb_private::TypeFromParser type);
+
+ //------------------------------------------------------------------
+ /// If the IR represents a cast of a variable, set m_const_result
+ /// to the result of the cast. The result variable will be reset to
+ /// NULL latger if the expression has side effects.
+ ///
+ /// @param[in] type
+ /// The Clang type of the result variable.
+ //------------------------------------------------------------------
+ void
+ MaybeSetCastResult (lldb_private::TypeFromParser type);
+
+ //------------------------------------------------------------------
+ /// The top-level pass implementation
+ ///
+ /// @param[in] llvm_function
+ /// The function currently being processed.
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ CreateResultVariable (llvm::Function &llvm_function);
+
+ //------------------------------------------------------------------
+ /// A module-level pass to find Objective-C constant strings and
+ /// transform them to calls to CFStringCreateWithBytes.
+ //------------------------------------------------------------------
+
+ //------------------------------------------------------------------
+ /// Rewrite a single Objective-C constant string.
+ ///
+ /// @param[in] NSStr
+ /// The constant NSString to be transformed
+ ///
+ /// @param[in] CStr
+ /// The constant C string inside the NSString. This will be
+ /// passed as the bytes argument to CFStringCreateWithBytes.
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ RewriteObjCConstString (llvm::GlobalVariable *NSStr,
+ llvm::GlobalVariable *CStr);
+
+ //------------------------------------------------------------------
+ /// The top-level pass implementation
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ RewriteObjCConstStrings ();
+
+ //------------------------------------------------------------------
+ /// A basic block-level pass to find all Objective-C method calls and
+ /// rewrite them to use sel_registerName instead of statically allocated
+ /// selectors. The reason is that the selectors are created on the
+ /// assumption that the Objective-C runtime will scan the appropriate
+ /// section and prepare them. This doesn't happen when code is copied
+ /// into the target, though, and there's no easy way to induce the
+ /// runtime to scan them. So instead we get our selectors from
+ /// sel_registerName.
+ //------------------------------------------------------------------
+
+ //------------------------------------------------------------------
+ /// Replace a single selector reference
+ ///
+ /// @param[in] selector_load
+ /// The load of the statically-allocated selector.
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ RewriteObjCSelector (llvm::Instruction* selector_load);
+
+ //------------------------------------------------------------------
+ /// The top-level pass implementation
+ ///
+ /// @param[in] basic_block
+ /// The basic block currently being processed.
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ RewriteObjCSelectors (llvm::BasicBlock &basic_block);
+
+ //------------------------------------------------------------------
+ /// A basic block-level pass to find all newly-declared persistent
+ /// variables and register them with the ClangExprDeclMap. This
+ /// allows them to be materialized and dematerialized like normal
+ /// external variables. Before transformation, these persistent
+ /// variables look like normal locals, so they have an allocation.
+ /// This pass excises these allocations and makes references look
+ /// like external references where they will be resolved -- like all
+ /// other external references -- by ResolveExternals().
+ //------------------------------------------------------------------
+
+ //------------------------------------------------------------------
+ /// Handle a single allocation of a persistent variable
+ ///
+ /// @param[in] persistent_alloc
+ /// The allocation of the persistent variable.
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ RewritePersistentAlloc (llvm::Instruction *persistent_alloc);
+
+ //------------------------------------------------------------------
+ /// The top-level pass implementation
+ ///
+ /// @param[in] basic_block
+ /// The basic block currently being processed.
+ //------------------------------------------------------------------
+ bool
+ RewritePersistentAllocs (llvm::BasicBlock &basic_block);
+
+ //------------------------------------------------------------------
+ /// A function-level pass to find all external variables and functions
+ /// used in the IR. Each found external variable is added to the
+ /// struct, and each external function is resolved in place, its call
+ /// replaced with a call to a function pointer whose value is the
+ /// address of the function in the target process.
+ //------------------------------------------------------------------
+
+ //------------------------------------------------------------------
+ /// Write an initializer to a memory array of assumed sufficient
+ /// size.
+ ///
+ /// @param[in] data
+ /// A pointer to the data to write to.
+ ///
+ /// @param[in] initializer
+ /// The initializer itself.
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ MaterializeInitializer (uint8_t *data, llvm::Constant *initializer);
+
+ //------------------------------------------------------------------
+ /// Move an internal variable into the static allocation section.
+ ///
+ /// @param[in] global_variable
+ /// The variable.
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ MaterializeInternalVariable (llvm::GlobalVariable *global_variable);
+
+ //------------------------------------------------------------------
+ /// Handle a single externally-defined variable
+ ///
+ /// @param[in] value
+ /// The variable.
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ MaybeHandleVariable (llvm::Value *value);
+
+ //------------------------------------------------------------------
+ /// Handle a single externally-defined symbol
+ ///
+ /// @param[in] symbol
+ /// The symbol.
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ HandleSymbol (llvm::Value *symbol);
+
+ //------------------------------------------------------------------
+ /// Handle a single externally-defined Objective-C class
+ ///
+ /// @param[in] classlist_reference
+ /// The reference, usually "01L_OBJC_CLASSLIST_REFERENCES_$_n"
+ /// where n (if present) is an index.
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ HandleObjCClass(llvm::Value *classlist_reference);
+
+ //------------------------------------------------------------------
+ /// Handle all the arguments to a function call
+ ///
+ /// @param[in] C
+ /// The call instruction.
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ MaybeHandleCallArguments (llvm::CallInst *call_inst);
+
+ //------------------------------------------------------------------
+ /// Resolve variable references in calls to external functions
+ ///
+ /// @param[in] basic_block
+ /// The basic block currently being processed.
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ ResolveCalls (llvm::BasicBlock &basic_block);
+
+ //------------------------------------------------------------------
+ /// Remove calls to __cxa_atexit, which should never be generated by
+ /// expressions.
+ ///
+ /// @param[in] call_inst
+ /// The call instruction.
+ ///
+ /// @return
+ /// True if the scan was successful; false if some operation
+ /// failed
+ //------------------------------------------------------------------
+ bool
+ RemoveCXAAtExit (llvm::BasicBlock &basic_block);
+
+ //------------------------------------------------------------------
+ /// The top-level pass implementation
+ ///
+ /// @param[in] basic_block
+ /// The function currently being processed.
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ ResolveExternals (llvm::Function &llvm_function);
+
+ //------------------------------------------------------------------
+ /// A basic block-level pass to excise guard variables from the code.
+ /// The result for the function is passed through Clang as a static
+ /// variable. Static variables normally have guard variables to
+ /// ensure that they are only initialized once.
+ //------------------------------------------------------------------
+
+ //------------------------------------------------------------------
+ /// Rewrite a load to a guard variable to return constant 0.
+ ///
+ /// @param[in] guard_load
+ /// The load instruction to zero out.
+ //------------------------------------------------------------------
+ void
+ TurnGuardLoadIntoZero(llvm::Instruction* guard_load);
+
+ //------------------------------------------------------------------
+ /// The top-level pass implementation
+ ///
+ /// @param[in] basic_block
+ /// The basic block currently being processed.
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ RemoveGuards (llvm::BasicBlock &basic_block);
+
+ //------------------------------------------------------------------
+ /// A module-level pass to allocate all string literals in a separate
+ /// allocation and redirect references to them.
+ //------------------------------------------------------------------
+
+ //------------------------------------------------------------------
+ /// The top-level pass implementation
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ ReplaceStrings ();
+
+ //------------------------------------------------------------------
+ /// A basic block-level pass to find all literals that will be
+ /// allocated as statics by the JIT (in contrast to the Strings,
+ /// which already are statics) and synthesize loads for them.
+ //------------------------------------------------------------------
+
+ //------------------------------------------------------------------
+ /// The top-level pass implementation
+ ///
+ /// @param[in] basic_block
+ /// The basic block currently being processed.
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ ReplaceStaticLiterals (llvm::BasicBlock &basic_block);
+
+ //------------------------------------------------------------------
+ /// A function-level pass to make all external variable references
+ /// point at the correct offsets from the void* passed into the
+ /// function. ClangExpressionDeclMap::DoStructLayout() must be called
+ /// beforehand, so that the offsets are valid.
+ //------------------------------------------------------------------
+
+ //------------------------------------------------------------------
+ /// The top-level pass implementation
+ ///
+ /// @param[in] llvm_function
+ /// The function currently being processed.
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ ReplaceVariables (llvm::Function &llvm_function);
+
+ //------------------------------------------------------------------
+ /// A module-level pass to remove all global variables from the
+ /// module since it no longer should export or import any symbols.
+ //------------------------------------------------------------------
+
+ //------------------------------------------------------------------
+ /// The top-level pass implementation
+ ///
+ /// @param[in] llvm_module
+ /// The module currently being processed.
+ ///
+ /// @return
+ /// True on success; false otherwise
+ //------------------------------------------------------------------
+ bool
+ StripAllGVs (llvm::Module &llvm_module);
+
+ class StaticDataAllocator {
+ public:
+ StaticDataAllocator(lldb_private::IRExecutionUnit &execution_unit);
+ lldb_private::StreamString &GetStream()
+ {
+ return m_stream_string;
+ }
+ lldb::addr_t Allocate();
+
+ lldb::TargetSP
+ GetTarget();
+ private:
+ lldb_private::IRExecutionUnit &m_execution_unit;
+ lldb_private::StreamString m_stream_string;
+ lldb::addr_t m_allocation;
+ };
+
+ /// Flags
+ bool m_resolve_vars; ///< True if external variable references and persistent variable references should be resolved
+ std::string m_func_name; ///< The name of the function to translate
+ lldb_private::ConstString m_result_name; ///< The name of the result variable ($0, $1, ...)
+ lldb_private::TypeFromParser m_result_type; ///< The type of the result variable.
+ llvm::Module *m_module; ///< The module being processed, or NULL if that has not been determined yet.
+ std::unique_ptr<llvm::DataLayout> m_target_data; ///< The target data for the module being processed, or NULL if there is no module.
+ lldb_private::ClangExpressionDeclMap *m_decl_map; ///< The DeclMap containing the Decls
+ StaticDataAllocator m_data_allocator; ///< The allocator to use for constant strings
+ llvm::Constant *m_CFStringCreateWithBytes; ///< The address of the function CFStringCreateWithBytes, cast to the appropriate function pointer type
+ llvm::Constant *m_sel_registerName; ///< The address of the function sel_registerName, cast to the appropriate function pointer type
+ llvm::IntegerType *m_intptr_ty; ///< The type of an integer large enough to hold a pointer.
+ lldb_private::Stream *m_error_stream; ///< If non-NULL, the stream on which errors should be printed
+
+ llvm::StoreInst *m_result_store; ///< If non-NULL, the store instruction that writes to the result variable. If m_has_side_effects is true, this is NULL.
+ bool m_result_is_pointer; ///< True if the function's result in the AST is a 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
+ //------------------------------------------------------------------
+
+ class FunctionValueCache {
+ public:
+ typedef std::function <llvm::Value *(llvm::Function *)> Maker;
+
+ FunctionValueCache (Maker const &maker);
+ ~FunctionValueCache ();
+ llvm::Value *GetValue (llvm::Function *function);
+ private:
+ Maker const m_maker;
+ typedef std::map<llvm::Function *, llvm::Value *> FunctionValueMap;
+ FunctionValueMap m_values;
+ };
+
+ FunctionValueCache m_entry_instruction_finder;
+
+ static bool
+ UnfoldConstant (llvm::Constant *old_constant,
+ FunctionValueCache &value_maker,
+ FunctionValueCache &entry_instruction_finder);
+
+ //------------------------------------------------------------------
+ /// Construct a reference to m_reloc_placeholder with a given type
+ /// and offset. This typically happens after inserting data into
+ /// m_data_allocator.
+ ///
+ /// @param[in] type
+ /// The type of the value being loaded.
+ ///
+ /// @param[in] offset
+ /// The offset of the value from the base of m_data_allocator.
+ ///
+ /// @return
+ /// The Constant for the reference, usually a ConstantExpr.
+ //------------------------------------------------------------------
+ llvm::Constant *
+ BuildRelocation(llvm::Type *type,
+ uint64_t offset);
+
+ //------------------------------------------------------------------
+ /// 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 ();
+
+};
+
+#endif // liblldb_IRForTarget_h_
diff --git a/source/Plugins/ExpressionParser/Go/GoAST.h b/source/Plugins/ExpressionParser/Go/GoAST.h
new file mode 100644
index 000000000000..6d51240eab5c
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Go/GoAST.h
@@ -0,0 +1,3225 @@
+//===-- GoAST.h -------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// DO NOT EDIT.
+// Generated by gen_go_ast.py
+
+#ifndef liblldb_GoAST_h
+#define liblldb_GoAST_h
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "llvm/Support/Casting.h"
+#include "Plugins/ExpressionParser/Go/GoLexer.h"
+
+namespace lldb_private
+{
+
+class GoASTNode
+{
+ public:
+ typedef GoLexer::TokenType TokenType;
+ typedef GoLexer::Token Token;
+ enum ChanDir
+ {
+ eChanBidir,
+ eChanSend,
+ eChanRecv,
+ };
+ enum NodeKind
+ {
+ eBadDecl,
+ eFuncDecl,
+ eGenDecl,
+ eArrayType,
+ eBadExpr,
+ eBasicLit,
+ eBinaryExpr,
+ eIdent,
+ eCallExpr,
+ eChanType,
+ eCompositeLit,
+ eEllipsis,
+ eFuncType,
+ eFuncLit,
+ eIndexExpr,
+ eInterfaceType,
+ eKeyValueExpr,
+ eMapType,
+ eParenExpr,
+ eSelectorExpr,
+ eSliceExpr,
+ eStarExpr,
+ eStructType,
+ eTypeAssertExpr,
+ eUnaryExpr,
+ eImportSpec,
+ eTypeSpec,
+ eValueSpec,
+ eAssignStmt,
+ eBadStmt,
+ eBlockStmt,
+ eBranchStmt,
+ eCaseClause,
+ eCommClause,
+ eDeclStmt,
+ eDeferStmt,
+ eEmptyStmt,
+ eExprStmt,
+ eForStmt,
+ eGoStmt,
+ eIfStmt,
+ eIncDecStmt,
+ eLabeledStmt,
+ eRangeStmt,
+ eReturnStmt,
+ eSelectStmt,
+ eSendStmt,
+ eSwitchStmt,
+ eTypeSwitchStmt,
+ eField,
+ eFieldList,
+ };
+
+ virtual ~GoASTNode() = default;
+
+ NodeKind
+ GetKind() const
+ {
+ return m_kind;
+ }
+
+ virtual const char *GetKindName() const = 0;
+
+ template <typename V> void WalkChildren(V &v);
+
+ protected:
+ explicit GoASTNode(NodeKind kind) : m_kind(kind) { }
+
+ private:
+ const NodeKind m_kind;
+
+ GoASTNode(const GoASTNode &) = delete;
+ const GoASTNode &operator=(const GoASTNode &) = delete;
+};
+
+
+class GoASTDecl : public GoASTNode
+{
+ public:
+ template <typename R, typename V> R Visit(V *v) const;
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() >= eBadDecl && n->GetKind() <= eGenDecl;
+ }
+
+ protected:
+ explicit GoASTDecl(NodeKind kind) : GoASTNode(kind) { }
+ private:
+
+ GoASTDecl(const GoASTDecl &) = delete;
+ const GoASTDecl &operator=(const GoASTDecl &) = delete;
+};
+
+class GoASTExpr : public GoASTNode
+{
+ public:
+ template <typename R, typename V> R Visit(V *v) const;
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() >= eArrayType && n->GetKind() <= eUnaryExpr;
+ }
+
+ protected:
+ explicit GoASTExpr(NodeKind kind) : GoASTNode(kind) { }
+ private:
+
+ GoASTExpr(const GoASTExpr &) = delete;
+ const GoASTExpr &operator=(const GoASTExpr &) = delete;
+};
+
+class GoASTSpec : public GoASTNode
+{
+ public:
+ template <typename R, typename V> R Visit(V *v) const;
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() >= eImportSpec && n->GetKind() <= eValueSpec;
+ }
+
+ protected:
+ explicit GoASTSpec(NodeKind kind) : GoASTNode(kind) { }
+ private:
+
+ GoASTSpec(const GoASTSpec &) = delete;
+ const GoASTSpec &operator=(const GoASTSpec &) = delete;
+};
+
+class GoASTStmt : public GoASTNode
+{
+ public:
+ template <typename R, typename V> R Visit(V *v) const;
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() >= eAssignStmt && n->GetKind() <= eTypeSwitchStmt;
+ }
+
+ protected:
+ explicit GoASTStmt(NodeKind kind) : GoASTNode(kind) { }
+ private:
+
+ GoASTStmt(const GoASTStmt &) = delete;
+ const GoASTStmt &operator=(const GoASTStmt &) = delete;
+};
+
+
+class GoASTArrayType : public GoASTExpr
+{
+ public:
+ GoASTArrayType(GoASTExpr *len, GoASTExpr *elt) : GoASTExpr(eArrayType), m_len_up(len), m_elt_up(elt) {}
+ ~GoASTArrayType() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "ArrayType";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eArrayType;
+ }
+
+ const GoASTExpr *
+ GetLen() const
+ {
+ return m_len_up.get();
+ }
+ void
+ SetLen(GoASTExpr *len)
+ {
+ m_len_up.reset(len);
+ }
+
+ const GoASTExpr *
+ GetElt() const
+ {
+ return m_elt_up.get();
+ }
+ void
+ SetElt(GoASTExpr *elt)
+ {
+ m_elt_up.reset(elt);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_len_up;
+ std::unique_ptr<GoASTExpr> m_elt_up;
+
+ GoASTArrayType(const GoASTArrayType &) = delete;
+ const GoASTArrayType &operator=(const GoASTArrayType &) = delete;
+};
+
+class GoASTAssignStmt : public GoASTStmt
+{
+ public:
+ explicit GoASTAssignStmt(bool define) : GoASTStmt(eAssignStmt), m_define(define) {}
+ ~GoASTAssignStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "AssignStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eAssignStmt;
+ }
+
+ size_t
+ NumLhs() const
+ {
+ return m_lhs.size();
+ }
+ const GoASTExpr *
+ GetLhs(int i) const
+ {
+ return m_lhs[i].get();
+ }
+ void
+ AddLhs(GoASTExpr *lhs)
+ {
+ m_lhs.push_back(std::unique_ptr<GoASTExpr>(lhs));
+ }
+
+ size_t
+ NumRhs() const
+ {
+ return m_rhs.size();
+ }
+ const GoASTExpr *
+ GetRhs(int i) const
+ {
+ return m_rhs[i].get();
+ }
+ void
+ AddRhs(GoASTExpr *rhs)
+ {
+ m_rhs.push_back(std::unique_ptr<GoASTExpr>(rhs));
+ }
+
+ bool
+ GetDefine() const
+ {
+ return m_define;
+ }
+ void
+ SetDefine(bool define)
+ {
+ m_define = define;
+ }
+
+ private:
+ friend class GoASTNode;
+ std::vector<std::unique_ptr<GoASTExpr> > m_lhs;
+ std::vector<std::unique_ptr<GoASTExpr> > m_rhs;
+ bool m_define;
+
+ GoASTAssignStmt(const GoASTAssignStmt &) = delete;
+ const GoASTAssignStmt &operator=(const GoASTAssignStmt &) = delete;
+};
+
+class GoASTBadDecl : public GoASTDecl
+{
+ public:
+ GoASTBadDecl() : GoASTDecl(eBadDecl) {}
+ ~GoASTBadDecl() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "BadDecl";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eBadDecl;
+ }
+
+ GoASTBadDecl(const GoASTBadDecl &) = delete;
+ const GoASTBadDecl &operator=(const GoASTBadDecl &) = delete;
+};
+
+class GoASTBadExpr : public GoASTExpr
+{
+ public:
+ GoASTBadExpr() : GoASTExpr(eBadExpr) {}
+ ~GoASTBadExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "BadExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eBadExpr;
+ }
+
+ GoASTBadExpr(const GoASTBadExpr &) = delete;
+ const GoASTBadExpr &operator=(const GoASTBadExpr &) = delete;
+};
+
+class GoASTBadStmt : public GoASTStmt
+{
+ public:
+ GoASTBadStmt() : GoASTStmt(eBadStmt) {}
+ ~GoASTBadStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "BadStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eBadStmt;
+ }
+
+ GoASTBadStmt(const GoASTBadStmt &) = delete;
+ const GoASTBadStmt &operator=(const GoASTBadStmt &) = delete;
+};
+
+class GoASTBasicLit : public GoASTExpr
+{
+ public:
+ explicit GoASTBasicLit(Token value) : GoASTExpr(eBasicLit), m_value(value) {}
+ ~GoASTBasicLit() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "BasicLit";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eBasicLit;
+ }
+
+ Token
+ GetValue() const
+ {
+ return m_value;
+ }
+ void
+ SetValue(Token value)
+ {
+ m_value = value;
+ }
+
+ private:
+ friend class GoASTNode;
+ Token m_value;
+
+ GoASTBasicLit(const GoASTBasicLit &) = delete;
+ const GoASTBasicLit &operator=(const GoASTBasicLit &) = delete;
+};
+
+class GoASTBinaryExpr : public GoASTExpr
+{
+ public:
+ GoASTBinaryExpr(GoASTExpr *x, GoASTExpr *y, TokenType op) : GoASTExpr(eBinaryExpr), m_x_up(x), m_y_up(y), m_op(op) {}
+ ~GoASTBinaryExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "BinaryExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eBinaryExpr;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ const GoASTExpr *
+ GetY() const
+ {
+ return m_y_up.get();
+ }
+ void
+ SetY(GoASTExpr *y)
+ {
+ m_y_up.reset(y);
+ }
+
+ TokenType
+ GetOp() const
+ {
+ return m_op;
+ }
+ void
+ SetOp(TokenType op)
+ {
+ m_op = op;
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_x_up;
+ std::unique_ptr<GoASTExpr> m_y_up;
+ TokenType m_op;
+
+ GoASTBinaryExpr(const GoASTBinaryExpr &) = delete;
+ const GoASTBinaryExpr &operator=(const GoASTBinaryExpr &) = delete;
+};
+
+class GoASTBlockStmt : public GoASTStmt
+{
+ public:
+ GoASTBlockStmt() : GoASTStmt(eBlockStmt) {}
+ ~GoASTBlockStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "BlockStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eBlockStmt;
+ }
+
+ size_t
+ NumList() const
+ {
+ return m_list.size();
+ }
+ const GoASTStmt *
+ GetList(int i) const
+ {
+ return m_list[i].get();
+ }
+ void
+ AddList(GoASTStmt *list)
+ {
+ m_list.push_back(std::unique_ptr<GoASTStmt>(list));
+ }
+
+ private:
+ friend class GoASTNode;
+ std::vector<std::unique_ptr<GoASTStmt> > m_list;
+
+ GoASTBlockStmt(const GoASTBlockStmt &) = delete;
+ const GoASTBlockStmt &operator=(const GoASTBlockStmt &) = delete;
+};
+
+class GoASTIdent : public GoASTExpr
+{
+ public:
+ explicit GoASTIdent(Token name) : GoASTExpr(eIdent), m_name(name) {}
+ ~GoASTIdent() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "Ident";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eIdent;
+ }
+
+ Token
+ GetName() const
+ {
+ return m_name;
+ }
+ void
+ SetName(Token name)
+ {
+ m_name = name;
+ }
+
+ private:
+ friend class GoASTNode;
+ Token m_name;
+
+ GoASTIdent(const GoASTIdent &) = delete;
+ const GoASTIdent &operator=(const GoASTIdent &) = delete;
+};
+
+class GoASTBranchStmt : public GoASTStmt
+{
+ public:
+ GoASTBranchStmt(GoASTIdent *label, TokenType tok) : GoASTStmt(eBranchStmt), m_label_up(label), m_tok(tok) {}
+ ~GoASTBranchStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "BranchStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eBranchStmt;
+ }
+
+ const GoASTIdent *
+ GetLabel() const
+ {
+ return m_label_up.get();
+ }
+ void
+ SetLabel(GoASTIdent *label)
+ {
+ m_label_up.reset(label);
+ }
+
+ TokenType
+ GetTok() const
+ {
+ return m_tok;
+ }
+ void
+ SetTok(TokenType tok)
+ {
+ m_tok = tok;
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTIdent> m_label_up;
+ TokenType m_tok;
+
+ GoASTBranchStmt(const GoASTBranchStmt &) = delete;
+ const GoASTBranchStmt &operator=(const GoASTBranchStmt &) = delete;
+};
+
+class GoASTCallExpr : public GoASTExpr
+{
+ public:
+ explicit GoASTCallExpr(bool ellipsis) : GoASTExpr(eCallExpr), m_ellipsis(ellipsis) {}
+ ~GoASTCallExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "CallExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eCallExpr;
+ }
+
+ const GoASTExpr *
+ GetFun() const
+ {
+ return m_fun_up.get();
+ }
+ void
+ SetFun(GoASTExpr *fun)
+ {
+ m_fun_up.reset(fun);
+ }
+
+ size_t
+ NumArgs() const
+ {
+ return m_args.size();
+ }
+ const GoASTExpr *
+ GetArgs(int i) const
+ {
+ return m_args[i].get();
+ }
+ void
+ AddArgs(GoASTExpr *args)
+ {
+ m_args.push_back(std::unique_ptr<GoASTExpr>(args));
+ }
+
+ bool
+ GetEllipsis() const
+ {
+ return m_ellipsis;
+ }
+ void
+ SetEllipsis(bool ellipsis)
+ {
+ m_ellipsis = ellipsis;
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_fun_up;
+ std::vector<std::unique_ptr<GoASTExpr> > m_args;
+ bool m_ellipsis;
+
+ GoASTCallExpr(const GoASTCallExpr &) = delete;
+ const GoASTCallExpr &operator=(const GoASTCallExpr &) = delete;
+};
+
+class GoASTCaseClause : public GoASTStmt
+{
+ public:
+ GoASTCaseClause() : GoASTStmt(eCaseClause) {}
+ ~GoASTCaseClause() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "CaseClause";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eCaseClause;
+ }
+
+ size_t
+ NumList() const
+ {
+ return m_list.size();
+ }
+ const GoASTExpr *
+ GetList(int i) const
+ {
+ return m_list[i].get();
+ }
+ void
+ AddList(GoASTExpr *list)
+ {
+ m_list.push_back(std::unique_ptr<GoASTExpr>(list));
+ }
+
+ size_t
+ NumBody() const
+ {
+ return m_body.size();
+ }
+ const GoASTStmt *
+ GetBody(int i) const
+ {
+ return m_body[i].get();
+ }
+ void
+ AddBody(GoASTStmt *body)
+ {
+ m_body.push_back(std::unique_ptr<GoASTStmt>(body));
+ }
+
+ private:
+ friend class GoASTNode;
+ std::vector<std::unique_ptr<GoASTExpr> > m_list;
+ std::vector<std::unique_ptr<GoASTStmt> > m_body;
+
+ GoASTCaseClause(const GoASTCaseClause &) = delete;
+ const GoASTCaseClause &operator=(const GoASTCaseClause &) = delete;
+};
+
+class GoASTChanType : public GoASTExpr
+{
+ public:
+ GoASTChanType(ChanDir dir, GoASTExpr *value) : GoASTExpr(eChanType), m_dir(dir), m_value_up(value) {}
+ ~GoASTChanType() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "ChanType";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eChanType;
+ }
+
+ ChanDir
+ GetDir() const
+ {
+ return m_dir;
+ }
+ void
+ SetDir(ChanDir dir)
+ {
+ m_dir = dir;
+ }
+
+ const GoASTExpr *
+ GetValue() const
+ {
+ return m_value_up.get();
+ }
+ void
+ SetValue(GoASTExpr *value)
+ {
+ m_value_up.reset(value);
+ }
+
+ private:
+ friend class GoASTNode;
+ ChanDir m_dir;
+ std::unique_ptr<GoASTExpr> m_value_up;
+
+ GoASTChanType(const GoASTChanType &) = delete;
+ const GoASTChanType &operator=(const GoASTChanType &) = delete;
+};
+
+class GoASTCommClause : public GoASTStmt
+{
+ public:
+ GoASTCommClause() : GoASTStmt(eCommClause) {}
+ ~GoASTCommClause() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "CommClause";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eCommClause;
+ }
+
+ const GoASTStmt *
+ GetComm() const
+ {
+ return m_comm_up.get();
+ }
+ void
+ SetComm(GoASTStmt *comm)
+ {
+ m_comm_up.reset(comm);
+ }
+
+ size_t
+ NumBody() const
+ {
+ return m_body.size();
+ }
+ const GoASTStmt *
+ GetBody(int i) const
+ {
+ return m_body[i].get();
+ }
+ void
+ AddBody(GoASTStmt *body)
+ {
+ m_body.push_back(std::unique_ptr<GoASTStmt>(body));
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTStmt> m_comm_up;
+ std::vector<std::unique_ptr<GoASTStmt> > m_body;
+
+ GoASTCommClause(const GoASTCommClause &) = delete;
+ const GoASTCommClause &operator=(const GoASTCommClause &) = delete;
+};
+
+class GoASTCompositeLit : public GoASTExpr
+{
+ public:
+ GoASTCompositeLit() : GoASTExpr(eCompositeLit) {}
+ ~GoASTCompositeLit() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "CompositeLit";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eCompositeLit;
+ }
+
+ const GoASTExpr *
+ GetType() const
+ {
+ return m_type_up.get();
+ }
+ void
+ SetType(GoASTExpr *type)
+ {
+ m_type_up.reset(type);
+ }
+
+ size_t
+ NumElts() const
+ {
+ return m_elts.size();
+ }
+ const GoASTExpr *
+ GetElts(int i) const
+ {
+ return m_elts[i].get();
+ }
+ void
+ AddElts(GoASTExpr *elts)
+ {
+ m_elts.push_back(std::unique_ptr<GoASTExpr>(elts));
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_type_up;
+ std::vector<std::unique_ptr<GoASTExpr> > m_elts;
+
+ GoASTCompositeLit(const GoASTCompositeLit &) = delete;
+ const GoASTCompositeLit &operator=(const GoASTCompositeLit &) = delete;
+};
+
+class GoASTDeclStmt : public GoASTStmt
+{
+ public:
+ explicit GoASTDeclStmt(GoASTDecl *decl) : GoASTStmt(eDeclStmt), m_decl_up(decl) {}
+ ~GoASTDeclStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "DeclStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eDeclStmt;
+ }
+
+ const GoASTDecl *
+ GetDecl() const
+ {
+ return m_decl_up.get();
+ }
+ void
+ SetDecl(GoASTDecl *decl)
+ {
+ m_decl_up.reset(decl);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTDecl> m_decl_up;
+
+ GoASTDeclStmt(const GoASTDeclStmt &) = delete;
+ const GoASTDeclStmt &operator=(const GoASTDeclStmt &) = delete;
+};
+
+class GoASTDeferStmt : public GoASTStmt
+{
+ public:
+ explicit GoASTDeferStmt(GoASTCallExpr *call) : GoASTStmt(eDeferStmt), m_call_up(call) {}
+ ~GoASTDeferStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "DeferStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eDeferStmt;
+ }
+
+ const GoASTCallExpr *
+ GetCall() const
+ {
+ return m_call_up.get();
+ }
+ void
+ SetCall(GoASTCallExpr *call)
+ {
+ m_call_up.reset(call);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTCallExpr> m_call_up;
+
+ GoASTDeferStmt(const GoASTDeferStmt &) = delete;
+ const GoASTDeferStmt &operator=(const GoASTDeferStmt &) = delete;
+};
+
+class GoASTEllipsis : public GoASTExpr
+{
+ public:
+ explicit GoASTEllipsis(GoASTExpr *elt) : GoASTExpr(eEllipsis), m_elt_up(elt) {}
+ ~GoASTEllipsis() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "Ellipsis";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eEllipsis;
+ }
+
+ const GoASTExpr *
+ GetElt() const
+ {
+ return m_elt_up.get();
+ }
+ void
+ SetElt(GoASTExpr *elt)
+ {
+ m_elt_up.reset(elt);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_elt_up;
+
+ GoASTEllipsis(const GoASTEllipsis &) = delete;
+ const GoASTEllipsis &operator=(const GoASTEllipsis &) = delete;
+};
+
+class GoASTEmptyStmt : public GoASTStmt
+{
+ public:
+ GoASTEmptyStmt() : GoASTStmt(eEmptyStmt) {}
+ ~GoASTEmptyStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "EmptyStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eEmptyStmt;
+ }
+
+ GoASTEmptyStmt(const GoASTEmptyStmt &) = delete;
+ const GoASTEmptyStmt &operator=(const GoASTEmptyStmt &) = delete;
+};
+
+class GoASTExprStmt : public GoASTStmt
+{
+ public:
+ explicit GoASTExprStmt(GoASTExpr *x) : GoASTStmt(eExprStmt), m_x_up(x) {}
+ ~GoASTExprStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "ExprStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eExprStmt;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_x_up;
+
+ GoASTExprStmt(const GoASTExprStmt &) = delete;
+ const GoASTExprStmt &operator=(const GoASTExprStmt &) = delete;
+};
+
+class GoASTField : public GoASTNode
+{
+ public:
+ GoASTField() : GoASTNode(eField) {}
+ ~GoASTField() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "Field";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eField;
+ }
+
+ size_t
+ NumNames() const
+ {
+ return m_names.size();
+ }
+ const GoASTIdent *
+ GetNames(int i) const
+ {
+ return m_names[i].get();
+ }
+ void
+ AddNames(GoASTIdent *names)
+ {
+ m_names.push_back(std::unique_ptr<GoASTIdent>(names));
+ }
+
+ const GoASTExpr *
+ GetType() const
+ {
+ return m_type_up.get();
+ }
+ void
+ SetType(GoASTExpr *type)
+ {
+ m_type_up.reset(type);
+ }
+
+ const GoASTBasicLit *
+ GetTag() const
+ {
+ return m_tag_up.get();
+ }
+ void
+ SetTag(GoASTBasicLit *tag)
+ {
+ m_tag_up.reset(tag);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::vector<std::unique_ptr<GoASTIdent> > m_names;
+ std::unique_ptr<GoASTExpr> m_type_up;
+ std::unique_ptr<GoASTBasicLit> m_tag_up;
+
+ GoASTField(const GoASTField &) = delete;
+ const GoASTField &operator=(const GoASTField &) = delete;
+};
+
+class GoASTFieldList : public GoASTNode
+{
+ public:
+ GoASTFieldList() : GoASTNode(eFieldList) {}
+ ~GoASTFieldList() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "FieldList";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eFieldList;
+ }
+
+ size_t
+ NumList() const
+ {
+ return m_list.size();
+ }
+ const GoASTField *
+ GetList(int i) const
+ {
+ return m_list[i].get();
+ }
+ void
+ AddList(GoASTField *list)
+ {
+ m_list.push_back(std::unique_ptr<GoASTField>(list));
+ }
+
+ private:
+ friend class GoASTNode;
+ std::vector<std::unique_ptr<GoASTField> > m_list;
+
+ GoASTFieldList(const GoASTFieldList &) = delete;
+ const GoASTFieldList &operator=(const GoASTFieldList &) = delete;
+};
+
+class GoASTForStmt : public GoASTStmt
+{
+ public:
+ GoASTForStmt(GoASTStmt *init, GoASTExpr *cond, GoASTStmt *post, GoASTBlockStmt *body) : GoASTStmt(eForStmt), m_init_up(init), m_cond_up(cond), m_post_up(post), m_body_up(body) {}
+ ~GoASTForStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "ForStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eForStmt;
+ }
+
+ const GoASTStmt *
+ GetInit() const
+ {
+ return m_init_up.get();
+ }
+ void
+ SetInit(GoASTStmt *init)
+ {
+ m_init_up.reset(init);
+ }
+
+ const GoASTExpr *
+ GetCond() const
+ {
+ return m_cond_up.get();
+ }
+ void
+ SetCond(GoASTExpr *cond)
+ {
+ m_cond_up.reset(cond);
+ }
+
+ const GoASTStmt *
+ GetPost() const
+ {
+ return m_post_up.get();
+ }
+ void
+ SetPost(GoASTStmt *post)
+ {
+ m_post_up.reset(post);
+ }
+
+ const GoASTBlockStmt *
+ GetBody() const
+ {
+ return m_body_up.get();
+ }
+ void
+ SetBody(GoASTBlockStmt *body)
+ {
+ m_body_up.reset(body);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTStmt> m_init_up;
+ std::unique_ptr<GoASTExpr> m_cond_up;
+ std::unique_ptr<GoASTStmt> m_post_up;
+ std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+ GoASTForStmt(const GoASTForStmt &) = delete;
+ const GoASTForStmt &operator=(const GoASTForStmt &) = delete;
+};
+
+class GoASTFuncType : public GoASTExpr
+{
+ public:
+ GoASTFuncType(GoASTFieldList *params, GoASTFieldList *results) : GoASTExpr(eFuncType), m_params_up(params), m_results_up(results) {}
+ ~GoASTFuncType() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "FuncType";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eFuncType;
+ }
+
+ const GoASTFieldList *
+ GetParams() const
+ {
+ return m_params_up.get();
+ }
+ void
+ SetParams(GoASTFieldList *params)
+ {
+ m_params_up.reset(params);
+ }
+
+ const GoASTFieldList *
+ GetResults() const
+ {
+ return m_results_up.get();
+ }
+ void
+ SetResults(GoASTFieldList *results)
+ {
+ m_results_up.reset(results);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTFieldList> m_params_up;
+ std::unique_ptr<GoASTFieldList> m_results_up;
+
+ GoASTFuncType(const GoASTFuncType &) = delete;
+ const GoASTFuncType &operator=(const GoASTFuncType &) = delete;
+};
+
+class GoASTFuncDecl : public GoASTDecl
+{
+ public:
+ GoASTFuncDecl(GoASTFieldList *recv, GoASTIdent *name, GoASTFuncType *type, GoASTBlockStmt *body) : GoASTDecl(eFuncDecl), m_recv_up(recv), m_name_up(name), m_type_up(type), m_body_up(body) {}
+ ~GoASTFuncDecl() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "FuncDecl";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eFuncDecl;
+ }
+
+ const GoASTFieldList *
+ GetRecv() const
+ {
+ return m_recv_up.get();
+ }
+ void
+ SetRecv(GoASTFieldList *recv)
+ {
+ m_recv_up.reset(recv);
+ }
+
+ const GoASTIdent *
+ GetName() const
+ {
+ return m_name_up.get();
+ }
+ void
+ SetName(GoASTIdent *name)
+ {
+ m_name_up.reset(name);
+ }
+
+ const GoASTFuncType *
+ GetType() const
+ {
+ return m_type_up.get();
+ }
+ void
+ SetType(GoASTFuncType *type)
+ {
+ m_type_up.reset(type);
+ }
+
+ const GoASTBlockStmt *
+ GetBody() const
+ {
+ return m_body_up.get();
+ }
+ void
+ SetBody(GoASTBlockStmt *body)
+ {
+ m_body_up.reset(body);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTFieldList> m_recv_up;
+ std::unique_ptr<GoASTIdent> m_name_up;
+ std::unique_ptr<GoASTFuncType> m_type_up;
+ std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+ GoASTFuncDecl(const GoASTFuncDecl &) = delete;
+ const GoASTFuncDecl &operator=(const GoASTFuncDecl &) = delete;
+};
+
+class GoASTFuncLit : public GoASTExpr
+{
+ public:
+ GoASTFuncLit(GoASTFuncType *type, GoASTBlockStmt *body) : GoASTExpr(eFuncLit), m_type_up(type), m_body_up(body) {}
+ ~GoASTFuncLit() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "FuncLit";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eFuncLit;
+ }
+
+ const GoASTFuncType *
+ GetType() const
+ {
+ return m_type_up.get();
+ }
+ void
+ SetType(GoASTFuncType *type)
+ {
+ m_type_up.reset(type);
+ }
+
+ const GoASTBlockStmt *
+ GetBody() const
+ {
+ return m_body_up.get();
+ }
+ void
+ SetBody(GoASTBlockStmt *body)
+ {
+ m_body_up.reset(body);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTFuncType> m_type_up;
+ std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+ GoASTFuncLit(const GoASTFuncLit &) = delete;
+ const GoASTFuncLit &operator=(const GoASTFuncLit &) = delete;
+};
+
+class GoASTGenDecl : public GoASTDecl
+{
+ public:
+ explicit GoASTGenDecl(TokenType tok) : GoASTDecl(eGenDecl), m_tok(tok) {}
+ ~GoASTGenDecl() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "GenDecl";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eGenDecl;
+ }
+
+ TokenType
+ GetTok() const
+ {
+ return m_tok;
+ }
+ void
+ SetTok(TokenType tok)
+ {
+ m_tok = tok;
+ }
+
+ size_t
+ NumSpecs() const
+ {
+ return m_specs.size();
+ }
+ const GoASTSpec *
+ GetSpecs(int i) const
+ {
+ return m_specs[i].get();
+ }
+ void
+ AddSpecs(GoASTSpec *specs)
+ {
+ m_specs.push_back(std::unique_ptr<GoASTSpec>(specs));
+ }
+
+ private:
+ friend class GoASTNode;
+ TokenType m_tok;
+ std::vector<std::unique_ptr<GoASTSpec> > m_specs;
+
+ GoASTGenDecl(const GoASTGenDecl &) = delete;
+ const GoASTGenDecl &operator=(const GoASTGenDecl &) = delete;
+};
+
+class GoASTGoStmt : public GoASTStmt
+{
+ public:
+ explicit GoASTGoStmt(GoASTCallExpr *call) : GoASTStmt(eGoStmt), m_call_up(call) {}
+ ~GoASTGoStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "GoStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eGoStmt;
+ }
+
+ const GoASTCallExpr *
+ GetCall() const
+ {
+ return m_call_up.get();
+ }
+ void
+ SetCall(GoASTCallExpr *call)
+ {
+ m_call_up.reset(call);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTCallExpr> m_call_up;
+
+ GoASTGoStmt(const GoASTGoStmt &) = delete;
+ const GoASTGoStmt &operator=(const GoASTGoStmt &) = delete;
+};
+
+class GoASTIfStmt : public GoASTStmt
+{
+ public:
+ GoASTIfStmt(GoASTStmt *init, GoASTExpr *cond, GoASTBlockStmt *body, GoASTStmt *els) : GoASTStmt(eIfStmt), m_init_up(init), m_cond_up(cond), m_body_up(body), m_els_up(els) {}
+ ~GoASTIfStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "IfStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eIfStmt;
+ }
+
+ const GoASTStmt *
+ GetInit() const
+ {
+ return m_init_up.get();
+ }
+ void
+ SetInit(GoASTStmt *init)
+ {
+ m_init_up.reset(init);
+ }
+
+ const GoASTExpr *
+ GetCond() const
+ {
+ return m_cond_up.get();
+ }
+ void
+ SetCond(GoASTExpr *cond)
+ {
+ m_cond_up.reset(cond);
+ }
+
+ const GoASTBlockStmt *
+ GetBody() const
+ {
+ return m_body_up.get();
+ }
+ void
+ SetBody(GoASTBlockStmt *body)
+ {
+ m_body_up.reset(body);
+ }
+
+ const GoASTStmt *
+ GetEls() const
+ {
+ return m_els_up.get();
+ }
+ void
+ SetEls(GoASTStmt *els)
+ {
+ m_els_up.reset(els);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTStmt> m_init_up;
+ std::unique_ptr<GoASTExpr> m_cond_up;
+ std::unique_ptr<GoASTBlockStmt> m_body_up;
+ std::unique_ptr<GoASTStmt> m_els_up;
+
+ GoASTIfStmt(const GoASTIfStmt &) = delete;
+ const GoASTIfStmt &operator=(const GoASTIfStmt &) = delete;
+};
+
+class GoASTImportSpec : public GoASTSpec
+{
+ public:
+ GoASTImportSpec(GoASTIdent *name, GoASTBasicLit *path) : GoASTSpec(eImportSpec), m_name_up(name), m_path_up(path) {}
+ ~GoASTImportSpec() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "ImportSpec";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eImportSpec;
+ }
+
+ const GoASTIdent *
+ GetName() const
+ {
+ return m_name_up.get();
+ }
+ void
+ SetName(GoASTIdent *name)
+ {
+ m_name_up.reset(name);
+ }
+
+ const GoASTBasicLit *
+ GetPath() const
+ {
+ return m_path_up.get();
+ }
+ void
+ SetPath(GoASTBasicLit *path)
+ {
+ m_path_up.reset(path);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTIdent> m_name_up;
+ std::unique_ptr<GoASTBasicLit> m_path_up;
+
+ GoASTImportSpec(const GoASTImportSpec &) = delete;
+ const GoASTImportSpec &operator=(const GoASTImportSpec &) = delete;
+};
+
+class GoASTIncDecStmt : public GoASTStmt
+{
+ public:
+ GoASTIncDecStmt(GoASTExpr *x, TokenType tok) : GoASTStmt(eIncDecStmt), m_x_up(x), m_tok(tok) {}
+ ~GoASTIncDecStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "IncDecStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eIncDecStmt;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ TokenType
+ GetTok() const
+ {
+ return m_tok;
+ }
+ void
+ SetTok(TokenType tok)
+ {
+ m_tok = tok;
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_x_up;
+ TokenType m_tok;
+
+ GoASTIncDecStmt(const GoASTIncDecStmt &) = delete;
+ const GoASTIncDecStmt &operator=(const GoASTIncDecStmt &) = delete;
+};
+
+class GoASTIndexExpr : public GoASTExpr
+{
+ public:
+ GoASTIndexExpr(GoASTExpr *x, GoASTExpr *index) : GoASTExpr(eIndexExpr), m_x_up(x), m_index_up(index) {}
+ ~GoASTIndexExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "IndexExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eIndexExpr;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ const GoASTExpr *
+ GetIndex() const
+ {
+ return m_index_up.get();
+ }
+ void
+ SetIndex(GoASTExpr *index)
+ {
+ m_index_up.reset(index);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_x_up;
+ std::unique_ptr<GoASTExpr> m_index_up;
+
+ GoASTIndexExpr(const GoASTIndexExpr &) = delete;
+ const GoASTIndexExpr &operator=(const GoASTIndexExpr &) = delete;
+};
+
+class GoASTInterfaceType : public GoASTExpr
+{
+ public:
+ explicit GoASTInterfaceType(GoASTFieldList *methods) : GoASTExpr(eInterfaceType), m_methods_up(methods) {}
+ ~GoASTInterfaceType() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "InterfaceType";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eInterfaceType;
+ }
+
+ const GoASTFieldList *
+ GetMethods() const
+ {
+ return m_methods_up.get();
+ }
+ void
+ SetMethods(GoASTFieldList *methods)
+ {
+ m_methods_up.reset(methods);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTFieldList> m_methods_up;
+
+ GoASTInterfaceType(const GoASTInterfaceType &) = delete;
+ const GoASTInterfaceType &operator=(const GoASTInterfaceType &) = delete;
+};
+
+class GoASTKeyValueExpr : public GoASTExpr
+{
+ public:
+ GoASTKeyValueExpr(GoASTExpr *key, GoASTExpr *value) : GoASTExpr(eKeyValueExpr), m_key_up(key), m_value_up(value) {}
+ ~GoASTKeyValueExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "KeyValueExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eKeyValueExpr;
+ }
+
+ const GoASTExpr *
+ GetKey() const
+ {
+ return m_key_up.get();
+ }
+ void
+ SetKey(GoASTExpr *key)
+ {
+ m_key_up.reset(key);
+ }
+
+ const GoASTExpr *
+ GetValue() const
+ {
+ return m_value_up.get();
+ }
+ void
+ SetValue(GoASTExpr *value)
+ {
+ m_value_up.reset(value);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_key_up;
+ std::unique_ptr<GoASTExpr> m_value_up;
+
+ GoASTKeyValueExpr(const GoASTKeyValueExpr &) = delete;
+ const GoASTKeyValueExpr &operator=(const GoASTKeyValueExpr &) = delete;
+};
+
+class GoASTLabeledStmt : public GoASTStmt
+{
+ public:
+ GoASTLabeledStmt(GoASTIdent *label, GoASTStmt *stmt) : GoASTStmt(eLabeledStmt), m_label_up(label), m_stmt_up(stmt) {}
+ ~GoASTLabeledStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "LabeledStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eLabeledStmt;
+ }
+
+ const GoASTIdent *
+ GetLabel() const
+ {
+ return m_label_up.get();
+ }
+ void
+ SetLabel(GoASTIdent *label)
+ {
+ m_label_up.reset(label);
+ }
+
+ const GoASTStmt *
+ GetStmt() const
+ {
+ return m_stmt_up.get();
+ }
+ void
+ SetStmt(GoASTStmt *stmt)
+ {
+ m_stmt_up.reset(stmt);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTIdent> m_label_up;
+ std::unique_ptr<GoASTStmt> m_stmt_up;
+
+ GoASTLabeledStmt(const GoASTLabeledStmt &) = delete;
+ const GoASTLabeledStmt &operator=(const GoASTLabeledStmt &) = delete;
+};
+
+class GoASTMapType : public GoASTExpr
+{
+ public:
+ GoASTMapType(GoASTExpr *key, GoASTExpr *value) : GoASTExpr(eMapType), m_key_up(key), m_value_up(value) {}
+ ~GoASTMapType() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "MapType";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eMapType;
+ }
+
+ const GoASTExpr *
+ GetKey() const
+ {
+ return m_key_up.get();
+ }
+ void
+ SetKey(GoASTExpr *key)
+ {
+ m_key_up.reset(key);
+ }
+
+ const GoASTExpr *
+ GetValue() const
+ {
+ return m_value_up.get();
+ }
+ void
+ SetValue(GoASTExpr *value)
+ {
+ m_value_up.reset(value);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_key_up;
+ std::unique_ptr<GoASTExpr> m_value_up;
+
+ GoASTMapType(const GoASTMapType &) = delete;
+ const GoASTMapType &operator=(const GoASTMapType &) = delete;
+};
+
+class GoASTParenExpr : public GoASTExpr
+{
+ public:
+ explicit GoASTParenExpr(GoASTExpr *x) : GoASTExpr(eParenExpr), m_x_up(x) {}
+ ~GoASTParenExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "ParenExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eParenExpr;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_x_up;
+
+ GoASTParenExpr(const GoASTParenExpr &) = delete;
+ const GoASTParenExpr &operator=(const GoASTParenExpr &) = delete;
+};
+
+class GoASTRangeStmt : public GoASTStmt
+{
+ public:
+ GoASTRangeStmt(GoASTExpr *key, GoASTExpr *value, bool define, GoASTExpr *x, GoASTBlockStmt *body) : GoASTStmt(eRangeStmt), m_key_up(key), m_value_up(value), m_define(define), m_x_up(x), m_body_up(body) {}
+ ~GoASTRangeStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "RangeStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eRangeStmt;
+ }
+
+ const GoASTExpr *
+ GetKey() const
+ {
+ return m_key_up.get();
+ }
+ void
+ SetKey(GoASTExpr *key)
+ {
+ m_key_up.reset(key);
+ }
+
+ const GoASTExpr *
+ GetValue() const
+ {
+ return m_value_up.get();
+ }
+ void
+ SetValue(GoASTExpr *value)
+ {
+ m_value_up.reset(value);
+ }
+
+ bool
+ GetDefine() const
+ {
+ return m_define;
+ }
+ void
+ SetDefine(bool define)
+ {
+ m_define = define;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ const GoASTBlockStmt *
+ GetBody() const
+ {
+ return m_body_up.get();
+ }
+ void
+ SetBody(GoASTBlockStmt *body)
+ {
+ m_body_up.reset(body);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_key_up;
+ std::unique_ptr<GoASTExpr> m_value_up;
+ bool m_define;
+ std::unique_ptr<GoASTExpr> m_x_up;
+ std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+ GoASTRangeStmt(const GoASTRangeStmt &) = delete;
+ const GoASTRangeStmt &operator=(const GoASTRangeStmt &) = delete;
+};
+
+class GoASTReturnStmt : public GoASTStmt
+{
+ public:
+ GoASTReturnStmt() : GoASTStmt(eReturnStmt) {}
+ ~GoASTReturnStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "ReturnStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eReturnStmt;
+ }
+
+ size_t
+ NumResults() const
+ {
+ return m_results.size();
+ }
+ const GoASTExpr *
+ GetResults(int i) const
+ {
+ return m_results[i].get();
+ }
+ void
+ AddResults(GoASTExpr *results)
+ {
+ m_results.push_back(std::unique_ptr<GoASTExpr>(results));
+ }
+
+ private:
+ friend class GoASTNode;
+ std::vector<std::unique_ptr<GoASTExpr> > m_results;
+
+ GoASTReturnStmt(const GoASTReturnStmt &) = delete;
+ const GoASTReturnStmt &operator=(const GoASTReturnStmt &) = delete;
+};
+
+class GoASTSelectStmt : public GoASTStmt
+{
+ public:
+ explicit GoASTSelectStmt(GoASTBlockStmt *body) : GoASTStmt(eSelectStmt), m_body_up(body) {}
+ ~GoASTSelectStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "SelectStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eSelectStmt;
+ }
+
+ const GoASTBlockStmt *
+ GetBody() const
+ {
+ return m_body_up.get();
+ }
+ void
+ SetBody(GoASTBlockStmt *body)
+ {
+ m_body_up.reset(body);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+ GoASTSelectStmt(const GoASTSelectStmt &) = delete;
+ const GoASTSelectStmt &operator=(const GoASTSelectStmt &) = delete;
+};
+
+class GoASTSelectorExpr : public GoASTExpr
+{
+ public:
+ GoASTSelectorExpr(GoASTExpr *x, GoASTIdent *sel) : GoASTExpr(eSelectorExpr), m_x_up(x), m_sel_up(sel) {}
+ ~GoASTSelectorExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "SelectorExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eSelectorExpr;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ const GoASTIdent *
+ GetSel() const
+ {
+ return m_sel_up.get();
+ }
+ void
+ SetSel(GoASTIdent *sel)
+ {
+ m_sel_up.reset(sel);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_x_up;
+ std::unique_ptr<GoASTIdent> m_sel_up;
+
+ GoASTSelectorExpr(const GoASTSelectorExpr &) = delete;
+ const GoASTSelectorExpr &operator=(const GoASTSelectorExpr &) = delete;
+};
+
+class GoASTSendStmt : public GoASTStmt
+{
+ public:
+ GoASTSendStmt(GoASTExpr *chan, GoASTExpr *value) : GoASTStmt(eSendStmt), m_chan_up(chan), m_value_up(value) {}
+ ~GoASTSendStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "SendStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eSendStmt;
+ }
+
+ const GoASTExpr *
+ GetChan() const
+ {
+ return m_chan_up.get();
+ }
+ void
+ SetChan(GoASTExpr *chan)
+ {
+ m_chan_up.reset(chan);
+ }
+
+ const GoASTExpr *
+ GetValue() const
+ {
+ return m_value_up.get();
+ }
+ void
+ SetValue(GoASTExpr *value)
+ {
+ m_value_up.reset(value);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_chan_up;
+ std::unique_ptr<GoASTExpr> m_value_up;
+
+ GoASTSendStmt(const GoASTSendStmt &) = delete;
+ const GoASTSendStmt &operator=(const GoASTSendStmt &) = delete;
+};
+
+class GoASTSliceExpr : public GoASTExpr
+{
+ public:
+ GoASTSliceExpr(GoASTExpr *x, GoASTExpr *low, GoASTExpr *high, GoASTExpr *max, bool slice3) : GoASTExpr(eSliceExpr), m_x_up(x), m_low_up(low), m_high_up(high), m_max_up(max), m_slice3(slice3) {}
+ ~GoASTSliceExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "SliceExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eSliceExpr;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ const GoASTExpr *
+ GetLow() const
+ {
+ return m_low_up.get();
+ }
+ void
+ SetLow(GoASTExpr *low)
+ {
+ m_low_up.reset(low);
+ }
+
+ const GoASTExpr *
+ GetHigh() const
+ {
+ return m_high_up.get();
+ }
+ void
+ SetHigh(GoASTExpr *high)
+ {
+ m_high_up.reset(high);
+ }
+
+ const GoASTExpr *
+ GetMax() const
+ {
+ return m_max_up.get();
+ }
+ void
+ SetMax(GoASTExpr *max)
+ {
+ m_max_up.reset(max);
+ }
+
+ bool
+ GetSlice3() const
+ {
+ return m_slice3;
+ }
+ void
+ SetSlice3(bool slice3)
+ {
+ m_slice3 = slice3;
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_x_up;
+ std::unique_ptr<GoASTExpr> m_low_up;
+ std::unique_ptr<GoASTExpr> m_high_up;
+ std::unique_ptr<GoASTExpr> m_max_up;
+ bool m_slice3;
+
+ GoASTSliceExpr(const GoASTSliceExpr &) = delete;
+ const GoASTSliceExpr &operator=(const GoASTSliceExpr &) = delete;
+};
+
+class GoASTStarExpr : public GoASTExpr
+{
+ public:
+ explicit GoASTStarExpr(GoASTExpr *x) : GoASTExpr(eStarExpr), m_x_up(x) {}
+ ~GoASTStarExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "StarExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eStarExpr;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_x_up;
+
+ GoASTStarExpr(const GoASTStarExpr &) = delete;
+ const GoASTStarExpr &operator=(const GoASTStarExpr &) = delete;
+};
+
+class GoASTStructType : public GoASTExpr
+{
+ public:
+ explicit GoASTStructType(GoASTFieldList *fields) : GoASTExpr(eStructType), m_fields_up(fields) {}
+ ~GoASTStructType() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "StructType";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eStructType;
+ }
+
+ const GoASTFieldList *
+ GetFields() const
+ {
+ return m_fields_up.get();
+ }
+ void
+ SetFields(GoASTFieldList *fields)
+ {
+ m_fields_up.reset(fields);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTFieldList> m_fields_up;
+
+ GoASTStructType(const GoASTStructType &) = delete;
+ const GoASTStructType &operator=(const GoASTStructType &) = delete;
+};
+
+class GoASTSwitchStmt : public GoASTStmt
+{
+ public:
+ GoASTSwitchStmt(GoASTStmt *init, GoASTExpr *tag, GoASTBlockStmt *body) : GoASTStmt(eSwitchStmt), m_init_up(init), m_tag_up(tag), m_body_up(body) {}
+ ~GoASTSwitchStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "SwitchStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eSwitchStmt;
+ }
+
+ const GoASTStmt *
+ GetInit() const
+ {
+ return m_init_up.get();
+ }
+ void
+ SetInit(GoASTStmt *init)
+ {
+ m_init_up.reset(init);
+ }
+
+ const GoASTExpr *
+ GetTag() const
+ {
+ return m_tag_up.get();
+ }
+ void
+ SetTag(GoASTExpr *tag)
+ {
+ m_tag_up.reset(tag);
+ }
+
+ const GoASTBlockStmt *
+ GetBody() const
+ {
+ return m_body_up.get();
+ }
+ void
+ SetBody(GoASTBlockStmt *body)
+ {
+ m_body_up.reset(body);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTStmt> m_init_up;
+ std::unique_ptr<GoASTExpr> m_tag_up;
+ std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+ GoASTSwitchStmt(const GoASTSwitchStmt &) = delete;
+ const GoASTSwitchStmt &operator=(const GoASTSwitchStmt &) = delete;
+};
+
+class GoASTTypeAssertExpr : public GoASTExpr
+{
+ public:
+ GoASTTypeAssertExpr(GoASTExpr *x, GoASTExpr *type) : GoASTExpr(eTypeAssertExpr), m_x_up(x), m_type_up(type) {}
+ ~GoASTTypeAssertExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "TypeAssertExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eTypeAssertExpr;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ const GoASTExpr *
+ GetType() const
+ {
+ return m_type_up.get();
+ }
+ void
+ SetType(GoASTExpr *type)
+ {
+ m_type_up.reset(type);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTExpr> m_x_up;
+ std::unique_ptr<GoASTExpr> m_type_up;
+
+ GoASTTypeAssertExpr(const GoASTTypeAssertExpr &) = delete;
+ const GoASTTypeAssertExpr &operator=(const GoASTTypeAssertExpr &) = delete;
+};
+
+class GoASTTypeSpec : public GoASTSpec
+{
+ public:
+ GoASTTypeSpec(GoASTIdent *name, GoASTExpr *type) : GoASTSpec(eTypeSpec), m_name_up(name), m_type_up(type) {}
+ ~GoASTTypeSpec() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "TypeSpec";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eTypeSpec;
+ }
+
+ const GoASTIdent *
+ GetName() const
+ {
+ return m_name_up.get();
+ }
+ void
+ SetName(GoASTIdent *name)
+ {
+ m_name_up.reset(name);
+ }
+
+ const GoASTExpr *
+ GetType() const
+ {
+ return m_type_up.get();
+ }
+ void
+ SetType(GoASTExpr *type)
+ {
+ m_type_up.reset(type);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTIdent> m_name_up;
+ std::unique_ptr<GoASTExpr> m_type_up;
+
+ GoASTTypeSpec(const GoASTTypeSpec &) = delete;
+ const GoASTTypeSpec &operator=(const GoASTTypeSpec &) = delete;
+};
+
+class GoASTTypeSwitchStmt : public GoASTStmt
+{
+ public:
+ GoASTTypeSwitchStmt(GoASTStmt *init, GoASTStmt *assign, GoASTBlockStmt *body) : GoASTStmt(eTypeSwitchStmt), m_init_up(init), m_assign_up(assign), m_body_up(body) {}
+ ~GoASTTypeSwitchStmt() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "TypeSwitchStmt";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eTypeSwitchStmt;
+ }
+
+ const GoASTStmt *
+ GetInit() const
+ {
+ return m_init_up.get();
+ }
+ void
+ SetInit(GoASTStmt *init)
+ {
+ m_init_up.reset(init);
+ }
+
+ const GoASTStmt *
+ GetAssign() const
+ {
+ return m_assign_up.get();
+ }
+ void
+ SetAssign(GoASTStmt *assign)
+ {
+ m_assign_up.reset(assign);
+ }
+
+ const GoASTBlockStmt *
+ GetBody() const
+ {
+ return m_body_up.get();
+ }
+ void
+ SetBody(GoASTBlockStmt *body)
+ {
+ m_body_up.reset(body);
+ }
+
+ private:
+ friend class GoASTNode;
+ std::unique_ptr<GoASTStmt> m_init_up;
+ std::unique_ptr<GoASTStmt> m_assign_up;
+ std::unique_ptr<GoASTBlockStmt> m_body_up;
+
+ GoASTTypeSwitchStmt(const GoASTTypeSwitchStmt &) = delete;
+ const GoASTTypeSwitchStmt &operator=(const GoASTTypeSwitchStmt &) = delete;
+};
+
+class GoASTUnaryExpr : public GoASTExpr
+{
+ public:
+ GoASTUnaryExpr(TokenType op, GoASTExpr *x) : GoASTExpr(eUnaryExpr), m_op(op), m_x_up(x) {}
+ ~GoASTUnaryExpr() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "UnaryExpr";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eUnaryExpr;
+ }
+
+ TokenType
+ GetOp() const
+ {
+ return m_op;
+ }
+ void
+ SetOp(TokenType op)
+ {
+ m_op = op;
+ }
+
+ const GoASTExpr *
+ GetX() const
+ {
+ return m_x_up.get();
+ }
+ void
+ SetX(GoASTExpr *x)
+ {
+ m_x_up.reset(x);
+ }
+
+ private:
+ friend class GoASTNode;
+ TokenType m_op;
+ std::unique_ptr<GoASTExpr> m_x_up;
+
+ GoASTUnaryExpr(const GoASTUnaryExpr &) = delete;
+ const GoASTUnaryExpr &operator=(const GoASTUnaryExpr &) = delete;
+};
+
+class GoASTValueSpec : public GoASTSpec
+{
+ public:
+ GoASTValueSpec() : GoASTSpec(eValueSpec) {}
+ ~GoASTValueSpec() override = default;
+
+ const char *
+ GetKindName() const override
+ {
+ return "ValueSpec";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == eValueSpec;
+ }
+
+ size_t
+ NumNames() const
+ {
+ return m_names.size();
+ }
+ const GoASTIdent *
+ GetNames(int i) const
+ {
+ return m_names[i].get();
+ }
+ void
+ AddNames(GoASTIdent *names)
+ {
+ m_names.push_back(std::unique_ptr<GoASTIdent>(names));
+ }
+
+ const GoASTExpr *
+ GetType() const
+ {
+ return m_type_up.get();
+ }
+ void
+ SetType(GoASTExpr *type)
+ {
+ m_type_up.reset(type);
+ }
+
+ size_t
+ NumValues() const
+ {
+ return m_values.size();
+ }
+ const GoASTExpr *
+ GetValues(int i) const
+ {
+ return m_values[i].get();
+ }
+ void
+ AddValues(GoASTExpr *values)
+ {
+ m_values.push_back(std::unique_ptr<GoASTExpr>(values));
+ }
+
+ private:
+ friend class GoASTNode;
+ std::vector<std::unique_ptr<GoASTIdent> > m_names;
+ std::unique_ptr<GoASTExpr> m_type_up;
+ std::vector<std::unique_ptr<GoASTExpr> > m_values;
+
+ GoASTValueSpec(const GoASTValueSpec &) = delete;
+ const GoASTValueSpec &operator=(const GoASTValueSpec &) = delete;
+};
+
+
+template <typename R, typename V>
+R GoASTDecl::Visit(V* v) const
+{
+ switch(GetKind())
+ {
+ case eBadDecl:
+ return v->VisitBadDecl(llvm::cast<const GoASTBadDecl>(this));
+ case eFuncDecl:
+ return v->VisitFuncDecl(llvm::cast<const GoASTFuncDecl>(this));
+ case eGenDecl:
+ return v->VisitGenDecl(llvm::cast<const GoASTGenDecl>(this));
+ default:
+ assert(false && "Invalid kind");
+ }
+}
+
+template <typename R, typename V>
+R GoASTExpr::Visit(V* v) const
+{
+ switch(GetKind())
+ {
+ case eArrayType:
+ return v->VisitArrayType(llvm::cast<const GoASTArrayType>(this));
+ case eBadExpr:
+ return v->VisitBadExpr(llvm::cast<const GoASTBadExpr>(this));
+ case eBasicLit:
+ return v->VisitBasicLit(llvm::cast<const GoASTBasicLit>(this));
+ case eBinaryExpr:
+ return v->VisitBinaryExpr(llvm::cast<const GoASTBinaryExpr>(this));
+ case eIdent:
+ return v->VisitIdent(llvm::cast<const GoASTIdent>(this));
+ case eCallExpr:
+ return v->VisitCallExpr(llvm::cast<const GoASTCallExpr>(this));
+ case eChanType:
+ return v->VisitChanType(llvm::cast<const GoASTChanType>(this));
+ case eCompositeLit:
+ return v->VisitCompositeLit(llvm::cast<const GoASTCompositeLit>(this));
+ case eEllipsis:
+ return v->VisitEllipsis(llvm::cast<const GoASTEllipsis>(this));
+ case eFuncType:
+ return v->VisitFuncType(llvm::cast<const GoASTFuncType>(this));
+ case eFuncLit:
+ return v->VisitFuncLit(llvm::cast<const GoASTFuncLit>(this));
+ case eIndexExpr:
+ return v->VisitIndexExpr(llvm::cast<const GoASTIndexExpr>(this));
+ case eInterfaceType:
+ return v->VisitInterfaceType(llvm::cast<const GoASTInterfaceType>(this));
+ case eKeyValueExpr:
+ return v->VisitKeyValueExpr(llvm::cast<const GoASTKeyValueExpr>(this));
+ case eMapType:
+ return v->VisitMapType(llvm::cast<const GoASTMapType>(this));
+ case eParenExpr:
+ return v->VisitParenExpr(llvm::cast<const GoASTParenExpr>(this));
+ case eSelectorExpr:
+ return v->VisitSelectorExpr(llvm::cast<const GoASTSelectorExpr>(this));
+ case eSliceExpr:
+ return v->VisitSliceExpr(llvm::cast<const GoASTSliceExpr>(this));
+ case eStarExpr:
+ return v->VisitStarExpr(llvm::cast<const GoASTStarExpr>(this));
+ case eStructType:
+ return v->VisitStructType(llvm::cast<const GoASTStructType>(this));
+ case eTypeAssertExpr:
+ return v->VisitTypeAssertExpr(llvm::cast<const GoASTTypeAssertExpr>(this));
+ case eUnaryExpr:
+ return v->VisitUnaryExpr(llvm::cast<const GoASTUnaryExpr>(this));
+ default:
+ assert(false && "Invalid kind");
+ }
+}
+
+template <typename R, typename V>
+R GoASTSpec::Visit(V* v) const
+{
+ switch(GetKind())
+ {
+ case eImportSpec:
+ return v->VisitImportSpec(llvm::cast<const GoASTImportSpec>(this));
+ case eTypeSpec:
+ return v->VisitTypeSpec(llvm::cast<const GoASTTypeSpec>(this));
+ case eValueSpec:
+ return v->VisitValueSpec(llvm::cast<const GoASTValueSpec>(this));
+ default:
+ assert(false && "Invalid kind");
+ }
+}
+
+template <typename R, typename V>
+R GoASTStmt::Visit(V* v) const
+{
+ switch(GetKind())
+ {
+ case eAssignStmt:
+ return v->VisitAssignStmt(llvm::cast<const GoASTAssignStmt>(this));
+ case eBadStmt:
+ return v->VisitBadStmt(llvm::cast<const GoASTBadStmt>(this));
+ case eBlockStmt:
+ return v->VisitBlockStmt(llvm::cast<const GoASTBlockStmt>(this));
+ case eBranchStmt:
+ return v->VisitBranchStmt(llvm::cast<const GoASTBranchStmt>(this));
+ case eCaseClause:
+ return v->VisitCaseClause(llvm::cast<const GoASTCaseClause>(this));
+ case eCommClause:
+ return v->VisitCommClause(llvm::cast<const GoASTCommClause>(this));
+ case eDeclStmt:
+ return v->VisitDeclStmt(llvm::cast<const GoASTDeclStmt>(this));
+ case eDeferStmt:
+ return v->VisitDeferStmt(llvm::cast<const GoASTDeferStmt>(this));
+ case eEmptyStmt:
+ return v->VisitEmptyStmt(llvm::cast<const GoASTEmptyStmt>(this));
+ case eExprStmt:
+ return v->VisitExprStmt(llvm::cast<const GoASTExprStmt>(this));
+ case eForStmt:
+ return v->VisitForStmt(llvm::cast<const GoASTForStmt>(this));
+ case eGoStmt:
+ return v->VisitGoStmt(llvm::cast<const GoASTGoStmt>(this));
+ case eIfStmt:
+ return v->VisitIfStmt(llvm::cast<const GoASTIfStmt>(this));
+ case eIncDecStmt:
+ return v->VisitIncDecStmt(llvm::cast<const GoASTIncDecStmt>(this));
+ case eLabeledStmt:
+ return v->VisitLabeledStmt(llvm::cast<const GoASTLabeledStmt>(this));
+ case eRangeStmt:
+ return v->VisitRangeStmt(llvm::cast<const GoASTRangeStmt>(this));
+ case eReturnStmt:
+ return v->VisitReturnStmt(llvm::cast<const GoASTReturnStmt>(this));
+ case eSelectStmt:
+ return v->VisitSelectStmt(llvm::cast<const GoASTSelectStmt>(this));
+ case eSendStmt:
+ return v->VisitSendStmt(llvm::cast<const GoASTSendStmt>(this));
+ case eSwitchStmt:
+ return v->VisitSwitchStmt(llvm::cast<const GoASTSwitchStmt>(this));
+ case eTypeSwitchStmt:
+ return v->VisitTypeSwitchStmt(llvm::cast<const GoASTTypeSwitchStmt>(this));
+ default:
+ assert(false && "Invalid kind");
+ }
+}
+
+template <typename V>
+void GoASTNode::WalkChildren(V &v)
+{
+ switch (m_kind)
+ {
+
+
+ case eArrayType:
+ {
+ GoASTArrayType *n = llvm::cast<GoASTArrayType>(this);
+ (void)n;
+ v(n->m_len_up.get());
+ v(n->m_elt_up.get());
+ return;
+ }
+ case eAssignStmt:
+ {
+ GoASTAssignStmt *n = llvm::cast<GoASTAssignStmt>(this);
+ (void)n;
+ for (auto& e : n->m_lhs) { v(e.get()); }
+ for (auto& e : n->m_rhs) { v(e.get()); }
+ return;
+ }
+ case eBasicLit:
+ {
+ GoASTBasicLit *n = llvm::cast<GoASTBasicLit>(this);
+ (void)n;
+ return;
+ }
+ case eBinaryExpr:
+ {
+ GoASTBinaryExpr *n = llvm::cast<GoASTBinaryExpr>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ v(n->m_y_up.get());
+ return;
+ }
+ case eBlockStmt:
+ {
+ GoASTBlockStmt *n = llvm::cast<GoASTBlockStmt>(this);
+ (void)n;
+ for (auto& e : n->m_list) { v(e.get()); }
+ return;
+ }
+ case eIdent:
+ {
+ GoASTIdent *n = llvm::cast<GoASTIdent>(this);
+ (void)n;
+ return;
+ }
+ case eBranchStmt:
+ {
+ GoASTBranchStmt *n = llvm::cast<GoASTBranchStmt>(this);
+ (void)n;
+ v(n->m_label_up.get());
+ return;
+ }
+ case eCallExpr:
+ {
+ GoASTCallExpr *n = llvm::cast<GoASTCallExpr>(this);
+ (void)n;
+ v(n->m_fun_up.get());
+ for (auto& e : n->m_args) { v(e.get()); }
+ return;
+ }
+ case eCaseClause:
+ {
+ GoASTCaseClause *n = llvm::cast<GoASTCaseClause>(this);
+ (void)n;
+ for (auto& e : n->m_list) { v(e.get()); }
+ for (auto& e : n->m_body) { v(e.get()); }
+ return;
+ }
+ case eChanType:
+ {
+ GoASTChanType *n = llvm::cast<GoASTChanType>(this);
+ (void)n;
+ v(n->m_value_up.get());
+ return;
+ }
+ case eCommClause:
+ {
+ GoASTCommClause *n = llvm::cast<GoASTCommClause>(this);
+ (void)n;
+ v(n->m_comm_up.get());
+ for (auto& e : n->m_body) { v(e.get()); }
+ return;
+ }
+ case eCompositeLit:
+ {
+ GoASTCompositeLit *n = llvm::cast<GoASTCompositeLit>(this);
+ (void)n;
+ v(n->m_type_up.get());
+ for (auto& e : n->m_elts) { v(e.get()); }
+ return;
+ }
+ case eDeclStmt:
+ {
+ GoASTDeclStmt *n = llvm::cast<GoASTDeclStmt>(this);
+ (void)n;
+ v(n->m_decl_up.get());
+ return;
+ }
+ case eDeferStmt:
+ {
+ GoASTDeferStmt *n = llvm::cast<GoASTDeferStmt>(this);
+ (void)n;
+ v(n->m_call_up.get());
+ return;
+ }
+ case eEllipsis:
+ {
+ GoASTEllipsis *n = llvm::cast<GoASTEllipsis>(this);
+ (void)n;
+ v(n->m_elt_up.get());
+ return;
+ }
+ case eExprStmt:
+ {
+ GoASTExprStmt *n = llvm::cast<GoASTExprStmt>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ return;
+ }
+ case eField:
+ {
+ GoASTField *n = llvm::cast<GoASTField>(this);
+ (void)n;
+ for (auto& e : n->m_names) { v(e.get()); }
+ v(n->m_type_up.get());
+ v(n->m_tag_up.get());
+ return;
+ }
+ case eFieldList:
+ {
+ GoASTFieldList *n = llvm::cast<GoASTFieldList>(this);
+ (void)n;
+ for (auto& e : n->m_list) { v(e.get()); }
+ return;
+ }
+ case eForStmt:
+ {
+ GoASTForStmt *n = llvm::cast<GoASTForStmt>(this);
+ (void)n;
+ v(n->m_init_up.get());
+ v(n->m_cond_up.get());
+ v(n->m_post_up.get());
+ v(n->m_body_up.get());
+ return;
+ }
+ case eFuncType:
+ {
+ GoASTFuncType *n = llvm::cast<GoASTFuncType>(this);
+ (void)n;
+ v(n->m_params_up.get());
+ v(n->m_results_up.get());
+ return;
+ }
+ case eFuncDecl:
+ {
+ GoASTFuncDecl *n = llvm::cast<GoASTFuncDecl>(this);
+ (void)n;
+ v(n->m_recv_up.get());
+ v(n->m_name_up.get());
+ v(n->m_type_up.get());
+ v(n->m_body_up.get());
+ return;
+ }
+ case eFuncLit:
+ {
+ GoASTFuncLit *n = llvm::cast<GoASTFuncLit>(this);
+ (void)n;
+ v(n->m_type_up.get());
+ v(n->m_body_up.get());
+ return;
+ }
+ case eGenDecl:
+ {
+ GoASTGenDecl *n = llvm::cast<GoASTGenDecl>(this);
+ (void)n;
+ for (auto& e : n->m_specs) { v(e.get()); }
+ return;
+ }
+ case eGoStmt:
+ {
+ GoASTGoStmt *n = llvm::cast<GoASTGoStmt>(this);
+ (void)n;
+ v(n->m_call_up.get());
+ return;
+ }
+ case eIfStmt:
+ {
+ GoASTIfStmt *n = llvm::cast<GoASTIfStmt>(this);
+ (void)n;
+ v(n->m_init_up.get());
+ v(n->m_cond_up.get());
+ v(n->m_body_up.get());
+ v(n->m_els_up.get());
+ return;
+ }
+ case eImportSpec:
+ {
+ GoASTImportSpec *n = llvm::cast<GoASTImportSpec>(this);
+ (void)n;
+ v(n->m_name_up.get());
+ v(n->m_path_up.get());
+ return;
+ }
+ case eIncDecStmt:
+ {
+ GoASTIncDecStmt *n = llvm::cast<GoASTIncDecStmt>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ return;
+ }
+ case eIndexExpr:
+ {
+ GoASTIndexExpr *n = llvm::cast<GoASTIndexExpr>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ v(n->m_index_up.get());
+ return;
+ }
+ case eInterfaceType:
+ {
+ GoASTInterfaceType *n = llvm::cast<GoASTInterfaceType>(this);
+ (void)n;
+ v(n->m_methods_up.get());
+ return;
+ }
+ case eKeyValueExpr:
+ {
+ GoASTKeyValueExpr *n = llvm::cast<GoASTKeyValueExpr>(this);
+ (void)n;
+ v(n->m_key_up.get());
+ v(n->m_value_up.get());
+ return;
+ }
+ case eLabeledStmt:
+ {
+ GoASTLabeledStmt *n = llvm::cast<GoASTLabeledStmt>(this);
+ (void)n;
+ v(n->m_label_up.get());
+ v(n->m_stmt_up.get());
+ return;
+ }
+ case eMapType:
+ {
+ GoASTMapType *n = llvm::cast<GoASTMapType>(this);
+ (void)n;
+ v(n->m_key_up.get());
+ v(n->m_value_up.get());
+ return;
+ }
+ case eParenExpr:
+ {
+ GoASTParenExpr *n = llvm::cast<GoASTParenExpr>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ return;
+ }
+ case eRangeStmt:
+ {
+ GoASTRangeStmt *n = llvm::cast<GoASTRangeStmt>(this);
+ (void)n;
+ v(n->m_key_up.get());
+ v(n->m_value_up.get());
+ v(n->m_x_up.get());
+ v(n->m_body_up.get());
+ return;
+ }
+ case eReturnStmt:
+ {
+ GoASTReturnStmt *n = llvm::cast<GoASTReturnStmt>(this);
+ (void)n;
+ for (auto& e : n->m_results) { v(e.get()); }
+ return;
+ }
+ case eSelectStmt:
+ {
+ GoASTSelectStmt *n = llvm::cast<GoASTSelectStmt>(this);
+ (void)n;
+ v(n->m_body_up.get());
+ return;
+ }
+ case eSelectorExpr:
+ {
+ GoASTSelectorExpr *n = llvm::cast<GoASTSelectorExpr>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ v(n->m_sel_up.get());
+ return;
+ }
+ case eSendStmt:
+ {
+ GoASTSendStmt *n = llvm::cast<GoASTSendStmt>(this);
+ (void)n;
+ v(n->m_chan_up.get());
+ v(n->m_value_up.get());
+ return;
+ }
+ case eSliceExpr:
+ {
+ GoASTSliceExpr *n = llvm::cast<GoASTSliceExpr>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ v(n->m_low_up.get());
+ v(n->m_high_up.get());
+ v(n->m_max_up.get());
+ return;
+ }
+ case eStarExpr:
+ {
+ GoASTStarExpr *n = llvm::cast<GoASTStarExpr>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ return;
+ }
+ case eStructType:
+ {
+ GoASTStructType *n = llvm::cast<GoASTStructType>(this);
+ (void)n;
+ v(n->m_fields_up.get());
+ return;
+ }
+ case eSwitchStmt:
+ {
+ GoASTSwitchStmt *n = llvm::cast<GoASTSwitchStmt>(this);
+ (void)n;
+ v(n->m_init_up.get());
+ v(n->m_tag_up.get());
+ v(n->m_body_up.get());
+ return;
+ }
+ case eTypeAssertExpr:
+ {
+ GoASTTypeAssertExpr *n = llvm::cast<GoASTTypeAssertExpr>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ v(n->m_type_up.get());
+ return;
+ }
+ case eTypeSpec:
+ {
+ GoASTTypeSpec *n = llvm::cast<GoASTTypeSpec>(this);
+ (void)n;
+ v(n->m_name_up.get());
+ v(n->m_type_up.get());
+ return;
+ }
+ case eTypeSwitchStmt:
+ {
+ GoASTTypeSwitchStmt *n = llvm::cast<GoASTTypeSwitchStmt>(this);
+ (void)n;
+ v(n->m_init_up.get());
+ v(n->m_assign_up.get());
+ v(n->m_body_up.get());
+ return;
+ }
+ case eUnaryExpr:
+ {
+ GoASTUnaryExpr *n = llvm::cast<GoASTUnaryExpr>(this);
+ (void)n;
+ v(n->m_x_up.get());
+ return;
+ }
+ case eValueSpec:
+ {
+ GoASTValueSpec *n = llvm::cast<GoASTValueSpec>(this);
+ (void)n;
+ for (auto& e : n->m_names) { v(e.get()); }
+ v(n->m_type_up.get());
+ for (auto& e : n->m_values) { v(e.get()); }
+ return;
+ }
+
+ case eEmptyStmt:
+ case eBadDecl:
+ case eBadExpr:
+ case eBadStmt:
+ break;
+ }
+}
+
+} // namespace lldb_private
+
+#endif
+
diff --git a/source/Plugins/ExpressionParser/Go/GoLexer.cpp b/source/Plugins/ExpressionParser/Go/GoLexer.cpp
new file mode 100644
index 000000000000..6de0f5619ca8
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Go/GoLexer.cpp
@@ -0,0 +1,402 @@
+//===-- GoLexer.cpp ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+
+#include "GoLexer.h"
+
+using namespace lldb_private;
+
+llvm::StringMap<GoLexer::TokenType> *GoLexer::m_keywords;
+
+GoLexer::GoLexer(const char *src) : m_src(src), m_end(src + strlen(src)), m_last_token(TOK_INVALID, "")
+{
+}
+
+bool
+GoLexer::SkipWhitespace()
+{
+ bool saw_newline = false;
+ for (; m_src < m_end; ++m_src)
+ {
+ if (*m_src == '\n')
+ saw_newline = true;
+ if (*m_src == '/' && !SkipComment())
+ return saw_newline;
+ else if (!IsWhitespace(*m_src))
+ return saw_newline;
+ }
+ return saw_newline;
+}
+
+bool
+GoLexer::SkipComment()
+{
+ if (m_src[0] == '/' && m_src[1] == '/')
+ {
+ for (const char *c = m_src + 2; c < m_end; ++c)
+ {
+ if (*c == '\n')
+ {
+ m_src = c - 1;
+ return true;
+ }
+ }
+ return true;
+ }
+ else if (m_src[0] == '/' && m_src[1] == '*')
+ {
+ for (const char *c = m_src + 2; c < m_end; ++c)
+ {
+ if (c[0] == '*' && c[1] == '/')
+ {
+ m_src = c + 1;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+const GoLexer::Token &
+GoLexer::Lex()
+{
+ bool newline = SkipWhitespace();
+ const char *start = m_src;
+ m_last_token.m_type = InternalLex(newline);
+ m_last_token.m_value = llvm::StringRef(start, m_src - start);
+ return m_last_token;
+}
+
+GoLexer::TokenType
+GoLexer::InternalLex(bool newline)
+{
+ if (m_src >= m_end)
+ {
+ return TOK_EOF;
+ }
+ if (newline)
+ {
+ switch (m_last_token.m_type)
+ {
+ case TOK_IDENTIFIER:
+ case LIT_FLOAT:
+ case LIT_IMAGINARY:
+ case LIT_INTEGER:
+ case LIT_RUNE:
+ case LIT_STRING:
+ case KEYWORD_BREAK:
+ case KEYWORD_CONTINUE:
+ case KEYWORD_FALLTHROUGH:
+ case KEYWORD_RETURN:
+ case OP_PLUS_PLUS:
+ case OP_MINUS_MINUS:
+ case OP_RPAREN:
+ case OP_RBRACK:
+ case OP_RBRACE:
+ return OP_SEMICOLON;
+ default:
+ break;
+ }
+ }
+ char c = *m_src;
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return DoNumber();
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case '&':
+ case '|':
+ case '^':
+ case '<':
+ case '>':
+ case '!':
+ case ':':
+ case ';':
+ case '(':
+ case ')':
+ case '[':
+ case ']':
+ case '{':
+ case '}':
+ case ',':
+ case '=':
+ return DoOperator();
+ case '.':
+ if (IsDecimal(m_src[1]))
+ return DoNumber();
+ return DoOperator();
+ case '$':
+ // For lldb persistent vars.
+ return DoIdent();
+ case '"':
+ case '`':
+ return DoString();
+ case '\'':
+ return DoRune();
+ default:
+ break;
+ }
+ if (IsLetterOrDigit(c))
+ return DoIdent();
+ ++m_src;
+ return TOK_INVALID;
+}
+
+GoLexer::TokenType
+GoLexer::DoOperator()
+{
+ TokenType t = TOK_INVALID;
+ if (m_end - m_src > 2)
+ {
+ t = LookupKeyword(llvm::StringRef(m_src, 3));
+ if (t != TOK_INVALID)
+ m_src += 3;
+ }
+ if (t == TOK_INVALID && m_end - m_src > 1)
+ {
+ t = LookupKeyword(llvm::StringRef(m_src, 2));
+ if (t != TOK_INVALID)
+ m_src += 2;
+ }
+ if (t == TOK_INVALID)
+ {
+ t = LookupKeyword(llvm::StringRef(m_src, 1));
+ ++m_src;
+ }
+ return t;
+}
+
+GoLexer::TokenType
+GoLexer::DoIdent()
+{
+ const char *start = m_src++;
+ while (m_src < m_end && IsLetterOrDigit(*m_src))
+ {
+ ++m_src;
+ }
+ TokenType kw = LookupKeyword(llvm::StringRef(start, m_src - start));
+ if (kw != TOK_INVALID)
+ return kw;
+ return TOK_IDENTIFIER;
+}
+
+GoLexer::TokenType
+GoLexer::DoNumber()
+{
+ if (m_src[0] == '0' && (m_src[1] == 'x' || m_src[1] == 'X'))
+ {
+ m_src += 2;
+ while (IsHexChar(*m_src))
+ ++m_src;
+ return LIT_INTEGER;
+ }
+ bool dot_ok = true;
+ bool e_ok = true;
+ while (true)
+ {
+ while (IsDecimal(*m_src))
+ ++m_src;
+ switch (*m_src)
+ {
+ case 'i':
+ ++m_src;
+ return LIT_IMAGINARY;
+ case '.':
+ if (!dot_ok)
+ return LIT_FLOAT;
+ ++m_src;
+ dot_ok = false;
+ break;
+ case 'e':
+ case 'E':
+ if (!e_ok)
+ return LIT_FLOAT;
+ dot_ok = e_ok = false;
+ ++m_src;
+ if (*m_src == '+' || *m_src == '-')
+ ++m_src;
+ break;
+ default:
+ if (dot_ok)
+ return LIT_INTEGER;
+ return LIT_FLOAT;
+ }
+ }
+}
+
+GoLexer::TokenType
+GoLexer::DoRune()
+{
+ while (++m_src < m_end)
+ {
+ switch (*m_src)
+ {
+ case '\'':
+ ++m_src;
+ return LIT_RUNE;
+ case '\n':
+ return TOK_INVALID;
+ case '\\':
+ if (m_src[1] == '\n')
+ return TOK_INVALID;
+ ++m_src;
+ }
+ }
+ return TOK_INVALID;
+}
+
+GoLexer::TokenType
+GoLexer::DoString()
+{
+ if (*m_src == '`')
+ {
+ while (++m_src < m_end)
+ {
+ if (*m_src == '`')
+ {
+ ++m_src;
+ return LIT_STRING;
+ }
+ }
+ return TOK_INVALID;
+ }
+ while (++m_src < m_end)
+ {
+ switch (*m_src)
+ {
+ case '"':
+ ++m_src;
+ return LIT_STRING;
+ case '\n':
+ return TOK_INVALID;
+ case '\\':
+ if (m_src[1] == '\n')
+ return TOK_INVALID;
+ ++m_src;
+ }
+ }
+ return TOK_INVALID;
+}
+
+GoLexer::TokenType
+GoLexer::LookupKeyword(llvm::StringRef id)
+{
+ if (m_keywords == nullptr)
+ m_keywords = InitKeywords();
+ const auto &it = m_keywords->find(id);
+ if (it == m_keywords->end())
+ return TOK_INVALID;
+ return it->second;
+}
+
+llvm::StringRef
+GoLexer::LookupToken(TokenType t)
+{
+ if (m_keywords == nullptr)
+ m_keywords = InitKeywords();
+ for (const auto &e : *m_keywords)
+ {
+ if (e.getValue() == t)
+ return e.getKey();
+ }
+ return "";
+}
+
+llvm::StringMap<GoLexer::TokenType> *
+GoLexer::InitKeywords()
+{
+ auto &result = *new llvm::StringMap<TokenType>(128);
+ result["break"] = KEYWORD_BREAK;
+ result["default"] = KEYWORD_DEFAULT;
+ result["func"] = KEYWORD_FUNC;
+ result["interface"] = KEYWORD_INTERFACE;
+ result["select"] = KEYWORD_SELECT;
+ result["case"] = KEYWORD_CASE;
+ result["defer"] = KEYWORD_DEFER;
+ result["go"] = KEYWORD_GO;
+ result["map"] = KEYWORD_MAP;
+ result["struct"] = KEYWORD_STRUCT;
+ result["chan"] = KEYWORD_CHAN;
+ result["else"] = KEYWORD_ELSE;
+ result["goto"] = KEYWORD_GOTO;
+ result["package"] = KEYWORD_PACKAGE;
+ result["switch"] = KEYWORD_SWITCH;
+ result["const"] = KEYWORD_CONST;
+ result["fallthrough"] = KEYWORD_FALLTHROUGH;
+ result["if"] = KEYWORD_IF;
+ result["range"] = KEYWORD_RANGE;
+ result["type"] = KEYWORD_TYPE;
+ result["continue"] = KEYWORD_CONTINUE;
+ result["for"] = KEYWORD_FOR;
+ result["import"] = KEYWORD_IMPORT;
+ result["return"] = KEYWORD_RETURN;
+ result["var"] = KEYWORD_VAR;
+ result["+"] = OP_PLUS;
+ result["-"] = OP_MINUS;
+ result["*"] = OP_STAR;
+ result["/"] = OP_SLASH;
+ result["%"] = OP_PERCENT;
+ result["&"] = OP_AMP;
+ result["|"] = OP_PIPE;
+ result["^"] = OP_CARET;
+ result["<<"] = OP_LSHIFT;
+ result[">>"] = OP_RSHIFT;
+ result["&^"] = OP_AMP_CARET;
+ result["+="] = OP_PLUS_EQ;
+ result["-="] = OP_MINUS_EQ;
+ result["*="] = OP_STAR_EQ;
+ result["/="] = OP_SLASH_EQ;
+ result["%="] = OP_PERCENT_EQ;
+ result["&="] = OP_AMP_EQ;
+ result["|="] = OP_PIPE_EQ;
+ result["^="] = OP_CARET_EQ;
+ result["<<="] = OP_LSHIFT_EQ;
+ result[">>="] = OP_RSHIFT_EQ;
+ result["&^="] = OP_AMP_CARET_EQ;
+ result["&&"] = OP_AMP_AMP;
+ result["||"] = OP_PIPE_PIPE;
+ result["<-"] = OP_LT_MINUS;
+ result["++"] = OP_PLUS_PLUS;
+ result["--"] = OP_MINUS_MINUS;
+ result["=="] = OP_EQ_EQ;
+ result["<"] = OP_LT;
+ result[">"] = OP_GT;
+ result["="] = OP_EQ;
+ result["!"] = OP_BANG;
+ result["!="] = OP_BANG_EQ;
+ result["<="] = OP_LT_EQ;
+ result[">="] = OP_GT_EQ;
+ result[":="] = OP_COLON_EQ;
+ result["..."] = OP_DOTS;
+ result["("] = OP_LPAREN;
+ result["["] = OP_LBRACK;
+ result["{"] = OP_LBRACE;
+ result[","] = OP_COMMA;
+ result["."] = OP_DOT;
+ result[")"] = OP_RPAREN;
+ result["]"] = OP_RBRACK;
+ result["}"] = OP_RBRACE;
+ result[";"] = OP_SEMICOLON;
+ result[":"] = OP_COLON;
+ return &result;
+}
diff --git a/source/Plugins/ExpressionParser/Go/GoLexer.h b/source/Plugins/ExpressionParser/Go/GoLexer.h
new file mode 100644
index 000000000000..e8e1635bab77
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Go/GoLexer.h
@@ -0,0 +1,201 @@
+//===-- GoLexer.h -----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GoLexer_h
+#define liblldb_GoLexer_h
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringMap.h"
+
+namespace lldb_private
+{
+
+class GoLexer
+{
+ public:
+ explicit GoLexer(const char *src);
+
+ enum TokenType
+ {
+ TOK_EOF,
+ TOK_INVALID,
+ TOK_IDENTIFIER,
+ LIT_INTEGER,
+ LIT_FLOAT,
+ LIT_IMAGINARY,
+ LIT_RUNE,
+ LIT_STRING,
+ KEYWORD_BREAK,
+ KEYWORD_DEFAULT,
+ KEYWORD_FUNC,
+ KEYWORD_INTERFACE,
+ KEYWORD_SELECT,
+ KEYWORD_CASE,
+ KEYWORD_DEFER,
+ KEYWORD_GO,
+ KEYWORD_MAP,
+ KEYWORD_STRUCT,
+ KEYWORD_CHAN,
+ KEYWORD_ELSE,
+ KEYWORD_GOTO,
+ KEYWORD_PACKAGE,
+ KEYWORD_SWITCH,
+ KEYWORD_CONST,
+ KEYWORD_FALLTHROUGH,
+ KEYWORD_IF,
+ KEYWORD_RANGE,
+ KEYWORD_TYPE,
+ KEYWORD_CONTINUE,
+ KEYWORD_FOR,
+ KEYWORD_IMPORT,
+ KEYWORD_RETURN,
+ KEYWORD_VAR,
+ OP_PLUS,
+ OP_MINUS,
+ OP_STAR,
+ OP_SLASH,
+ OP_PERCENT,
+ OP_AMP,
+ OP_PIPE,
+ OP_CARET,
+ OP_LSHIFT,
+ OP_RSHIFT,
+ OP_AMP_CARET,
+ OP_PLUS_EQ,
+ OP_MINUS_EQ,
+ OP_STAR_EQ,
+ OP_SLASH_EQ,
+ OP_PERCENT_EQ,
+ OP_AMP_EQ,
+ OP_PIPE_EQ,
+ OP_CARET_EQ,
+ OP_LSHIFT_EQ,
+ OP_RSHIFT_EQ,
+ OP_AMP_CARET_EQ,
+ OP_AMP_AMP,
+ OP_PIPE_PIPE,
+ OP_LT_MINUS,
+ OP_PLUS_PLUS,
+ OP_MINUS_MINUS,
+ OP_EQ_EQ,
+ OP_LT,
+ OP_GT,
+ OP_EQ,
+ OP_BANG,
+ OP_BANG_EQ,
+ OP_LT_EQ,
+ OP_GT_EQ,
+ OP_COLON_EQ,
+ OP_DOTS,
+ OP_LPAREN,
+ OP_LBRACK,
+ OP_LBRACE,
+ OP_COMMA,
+ OP_DOT,
+ OP_RPAREN,
+ OP_RBRACK,
+ OP_RBRACE,
+ OP_SEMICOLON,
+ OP_COLON,
+ };
+
+ struct Token
+ {
+ explicit Token(TokenType t, llvm::StringRef text) : m_type(t), m_value(text) {}
+ TokenType m_type;
+ llvm::StringRef m_value;
+ };
+
+ const Token &Lex();
+
+ size_t
+ BytesRemaining() const
+ {
+ return m_end - m_src;
+ }
+ llvm::StringRef
+ GetString(int len) const
+ {
+ return llvm::StringRef(m_src, len);
+ }
+
+ static TokenType LookupKeyword(llvm::StringRef id);
+ static llvm::StringRef LookupToken(TokenType t);
+
+ private:
+ bool
+ IsDecimal(char c)
+ {
+ return c >= '0' && c <= '9';
+ }
+ bool
+ IsHexChar(char c)
+ {
+ if (c >= '0' && c <= '9')
+ return true;
+ if (c >= 'A' && c <= 'F')
+ return true;
+ if (c >= 'a' && c <= 'f')
+ return true;
+ return false;
+ }
+ bool
+ IsLetterOrDigit(char c)
+ {
+ if (c >= 'a' && c <= 'z')
+ return true;
+ if (c >= 'A' && c <= 'Z')
+ return true;
+ if (c == '_')
+ return true;
+ if (c >= '0' && c <= '9')
+ return true;
+ // Treat all non-ascii chars as letters for simplicity.
+ return 0 != (c & 0x80);
+ }
+ bool
+ IsWhitespace(char c)
+ {
+ switch (c)
+ {
+ case ' ':
+ case '\t':
+ case '\r':
+ return true;
+ }
+ return false;
+ }
+
+ bool SkipWhitespace();
+ bool SkipComment();
+
+ TokenType InternalLex(bool newline);
+
+ TokenType DoOperator();
+
+ TokenType DoIdent();
+
+ TokenType DoNumber();
+
+ TokenType DoRune();
+
+ TokenType DoString();
+
+ static llvm::StringMap<TokenType> *InitKeywords();
+
+ static llvm::StringMap<TokenType> *m_keywords;
+
+ const char *m_src;
+ const char *m_end;
+ Token m_last_token;
+};
+
+} // namespace lldb_private
+
+#endif
diff --git a/source/Plugins/ExpressionParser/Go/GoParser.cpp b/source/Plugins/ExpressionParser/Go/GoParser.cpp
new file mode 100644
index 000000000000..0f136f7e61dc
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Go/GoParser.cpp
@@ -0,0 +1,1035 @@
+//===-- GoParser.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <vector>
+
+#include "GoParser.h"
+
+#include "lldb/Core/Error.h"
+#include "llvm/ADT/SmallString.h"
+#include "Plugins/ExpressionParser/Go/GoAST.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+namespace
+{
+llvm::StringRef
+DescribeToken(GoLexer::TokenType t)
+{
+ switch (t)
+ {
+ case GoLexer::TOK_EOF:
+ return "<eof>";
+ case GoLexer::TOK_IDENTIFIER:
+ return "identifier";
+ case GoLexer::LIT_FLOAT:
+ return "float";
+ case GoLexer::LIT_IMAGINARY:
+ return "imaginary";
+ case GoLexer::LIT_INTEGER:
+ return "integer";
+ case GoLexer::LIT_RUNE:
+ return "rune";
+ case GoLexer::LIT_STRING:
+ return "string";
+ default:
+ return GoLexer::LookupToken(t);
+ }
+}
+} // namespace
+
+class GoParser::Rule
+{
+ public:
+ Rule(llvm::StringRef name, GoParser *p) : m_name(name), m_parser(p), m_pos(p->m_pos) {}
+
+ std::nullptr_t
+ error()
+ {
+ if (!m_parser->m_failed)
+ {
+ // Set m_error in case this is the top level.
+ if (m_parser->m_last_tok == GoLexer::TOK_INVALID)
+ m_parser->m_error = m_parser->m_last;
+ else
+ m_parser->m_error = DescribeToken(m_parser->m_last_tok);
+ // And set m_last in case it isn't.
+ m_parser->m_last = m_name;
+ m_parser->m_last_tok = GoLexer::TOK_INVALID;
+ m_parser->m_pos = m_pos;
+ }
+ return nullptr;
+ }
+
+ private:
+ llvm::StringRef m_name;
+ GoParser *m_parser;
+ size_t m_pos;
+};
+
+GoParser::GoParser(const char *src) : m_lexer(src), m_pos(0), m_failed(false)
+{
+}
+
+GoASTStmt *
+GoParser::Statement()
+{
+ Rule r("Statement", this);
+ GoLexer::TokenType t = peek();
+ GoASTStmt *ret = nullptr;
+ switch (t)
+ {
+ case GoLexer::TOK_EOF:
+ case GoLexer::OP_SEMICOLON:
+ case GoLexer::OP_RPAREN:
+ case GoLexer::OP_RBRACE:
+ case GoLexer::TOK_INVALID:
+ return EmptyStmt();
+ case GoLexer::OP_LBRACE:
+ return Block();
+
+ /* TODO:
+ case GoLexer::KEYWORD_GO:
+ return GoStmt();
+ case GoLexer::KEYWORD_RETURN:
+ return ReturnStmt();
+ case GoLexer::KEYWORD_BREAK:
+ case GoLexer::KEYWORD_CONTINUE:
+ case GoLexer::KEYWORD_GOTO:
+ case GoLexer::KEYWORD_FALLTHROUGH:
+ return BranchStmt();
+ case GoLexer::KEYWORD_IF:
+ return IfStmt();
+ case GoLexer::KEYWORD_SWITCH:
+ return SwitchStmt();
+ case GoLexer::KEYWORD_SELECT:
+ return SelectStmt();
+ case GoLexer::KEYWORD_FOR:
+ return ForStmt();
+ case GoLexer::KEYWORD_DEFER:
+ return DeferStmt();
+ case GoLexer::KEYWORD_CONST:
+ case GoLexer::KEYWORD_TYPE:
+ case GoLexer::KEYWORD_VAR:
+ return DeclStmt();
+ case GoLexer::TOK_IDENTIFIER:
+ if ((ret = LabeledStmt()) ||
+ (ret = ShortVarDecl()))
+ {
+ return ret;
+ }
+*/
+ default:
+ break;
+ }
+ GoASTExpr *expr = Expression();
+ if (expr == nullptr)
+ return r.error();
+ if (/*(ret = SendStmt(expr)) ||*/
+ (ret = IncDecStmt(expr)) || (ret = Assignment(expr)) || (ret = ExpressionStmt(expr)))
+ {
+ return ret;
+ }
+ delete expr;
+ return r.error();
+}
+
+GoASTStmt *
+GoParser::ExpressionStmt(GoASTExpr *e)
+{
+ if (Semicolon())
+ return new GoASTExprStmt(e);
+ return nullptr;
+}
+
+GoASTStmt *
+GoParser::IncDecStmt(GoASTExpr *e)
+{
+ Rule r("IncDecStmt", this);
+ if (match(GoLexer::OP_PLUS_PLUS))
+ return Semicolon() ? new GoASTIncDecStmt(e, GoLexer::OP_PLUS_PLUS) : r.error();
+ if (match(GoLexer::OP_MINUS_MINUS))
+ return Semicolon() ? new GoASTIncDecStmt(e, GoLexer::OP_MINUS_MINUS) : r.error();
+ return nullptr;
+}
+
+GoASTStmt *
+GoParser::Assignment(lldb_private::GoASTExpr *e)
+{
+ Rule r("Assignment", this);
+ std::vector<std::unique_ptr<GoASTExpr>> lhs;
+ for (GoASTExpr *l = MoreExpressionList(); l; l = MoreExpressionList())
+ lhs.push_back(std::unique_ptr<GoASTExpr>(l));
+ switch (peek())
+ {
+ case GoLexer::OP_EQ:
+ case GoLexer::OP_PLUS_EQ:
+ case GoLexer::OP_MINUS_EQ:
+ case GoLexer::OP_PIPE_EQ:
+ case GoLexer::OP_CARET_EQ:
+ case GoLexer::OP_STAR_EQ:
+ case GoLexer::OP_SLASH_EQ:
+ case GoLexer::OP_PERCENT_EQ:
+ case GoLexer::OP_LSHIFT_EQ:
+ case GoLexer::OP_RSHIFT_EQ:
+ case GoLexer::OP_AMP_EQ:
+ case GoLexer::OP_AMP_CARET_EQ:
+ break;
+ default:
+ return r.error();
+ }
+ // We don't want to own e until we know this is an assignment.
+ std::unique_ptr<GoASTAssignStmt> stmt(new GoASTAssignStmt(false));
+ stmt->AddLhs(e);
+ for (auto &l : lhs)
+ stmt->AddLhs(l.release());
+ for (GoASTExpr *r = Expression(); r; r = MoreExpressionList())
+ stmt->AddRhs(r);
+ if (!Semicolon() || stmt->NumRhs() == 0)
+ return new GoASTBadStmt;
+ return stmt.release();
+}
+
+GoASTStmt *
+GoParser::EmptyStmt()
+{
+ if (match(GoLexer::TOK_EOF))
+ return nullptr;
+ if (Semicolon())
+ return new GoASTEmptyStmt;
+ return nullptr;
+}
+
+GoASTStmt *
+GoParser::GoStmt()
+{
+ if (match(GoLexer::KEYWORD_GO))
+ {
+ if (GoASTCallExpr *e = llvm::dyn_cast_or_null<GoASTCallExpr>(Expression()))
+ {
+ return FinishStmt(new GoASTGoStmt(e));
+ }
+ m_last = "call expression";
+ m_failed = true;
+ return new GoASTBadStmt();
+ }
+ return nullptr;
+}
+
+GoASTStmt *
+GoParser::ReturnStmt()
+{
+ if (match(GoLexer::KEYWORD_RETURN))
+ {
+ std::unique_ptr<GoASTReturnStmt> r(new GoASTReturnStmt());
+ for (GoASTExpr *e = Expression(); e; e = MoreExpressionList())
+ r->AddResults(e);
+ return FinishStmt(r.release());
+ }
+ return nullptr;
+}
+
+GoASTStmt *
+GoParser::BranchStmt()
+{
+ GoLexer::Token *tok;
+ if ((tok = match(GoLexer::KEYWORD_BREAK)) || (tok = match(GoLexer::KEYWORD_CONTINUE)) ||
+ (tok = match(GoLexer::KEYWORD_GOTO)))
+ {
+ auto *e = Identifier();
+ if (tok->m_type == GoLexer::KEYWORD_GOTO && !e)
+ return syntaxerror();
+ return FinishStmt(new GoASTBranchStmt(e, tok->m_type));
+ }
+ if ((tok = match(GoLexer::KEYWORD_FALLTHROUGH)))
+ return FinishStmt(new GoASTBranchStmt(nullptr, tok->m_type));
+
+ return nullptr;
+}
+
+GoASTIdent *
+GoParser::Identifier()
+{
+ if (auto *tok = match(GoLexer::TOK_IDENTIFIER))
+ return new GoASTIdent(*tok);
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::MoreExpressionList()
+{
+ if (match(GoLexer::OP_COMMA))
+ {
+ auto *e = Expression();
+ if (!e)
+ return syntaxerror();
+ return e;
+ }
+ return nullptr;
+}
+
+GoASTIdent *
+GoParser::MoreIdentifierList()
+{
+ if (match(GoLexer::OP_COMMA))
+ {
+ auto *i = Identifier();
+ if (!i)
+ return syntaxerror();
+ return i;
+ }
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::Expression()
+{
+ Rule r("Expression", this);
+ if (GoASTExpr *ret = OrExpr())
+ return ret;
+ return r.error();
+}
+
+GoASTExpr *
+GoParser::UnaryExpr()
+{
+ switch (peek())
+ {
+ case GoLexer::OP_PLUS:
+ case GoLexer::OP_MINUS:
+ case GoLexer::OP_BANG:
+ case GoLexer::OP_CARET:
+ case GoLexer::OP_STAR:
+ case GoLexer::OP_AMP:
+ case GoLexer::OP_LT_MINUS:
+ {
+ const GoLexer::Token t = next();
+ if (GoASTExpr *e = UnaryExpr())
+ {
+ if (t.m_type == GoLexer::OP_STAR)
+ return new GoASTStarExpr(e);
+ else
+ return new GoASTUnaryExpr(t.m_type, e);
+ }
+ return syntaxerror();
+ }
+ default:
+ return PrimaryExpr();
+ }
+}
+
+GoASTExpr *
+GoParser::OrExpr()
+{
+ std::unique_ptr<GoASTExpr> l(AndExpr());
+ if (l)
+ {
+ while (match(GoLexer::OP_PIPE_PIPE))
+ {
+ GoASTExpr *r = AndExpr();
+ if (r)
+ l.reset(new GoASTBinaryExpr(l.release(), r, GoLexer::OP_PIPE_PIPE));
+ else
+ return syntaxerror();
+ }
+ return l.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::AndExpr()
+{
+ std::unique_ptr<GoASTExpr> l(RelExpr());
+ if (l)
+ {
+ while (match(GoLexer::OP_AMP_AMP))
+ {
+ GoASTExpr *r = RelExpr();
+ if (r)
+ l.reset(new GoASTBinaryExpr(l.release(), r, GoLexer::OP_AMP_AMP));
+ else
+ return syntaxerror();
+ }
+ return l.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::RelExpr()
+{
+ std::unique_ptr<GoASTExpr> l(AddExpr());
+ if (l)
+ {
+ for (GoLexer::Token *t; (t = match(GoLexer::OP_EQ_EQ)) || (t = match(GoLexer::OP_BANG_EQ)) ||
+ (t = match(GoLexer::OP_LT)) || (t = match(GoLexer::OP_LT_EQ)) ||
+ (t = match(GoLexer::OP_GT)) || (t = match(GoLexer::OP_GT_EQ));)
+ {
+ GoLexer::TokenType op = t->m_type;
+ GoASTExpr *r = AddExpr();
+ if (r)
+ l.reset(new GoASTBinaryExpr(l.release(), r, op));
+ else
+ return syntaxerror();
+ }
+ return l.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::AddExpr()
+{
+ std::unique_ptr<GoASTExpr> l(MulExpr());
+ if (l)
+ {
+ for (GoLexer::Token *t; (t = match(GoLexer::OP_PLUS)) || (t = match(GoLexer::OP_MINUS)) ||
+ (t = match(GoLexer::OP_PIPE)) || (t = match(GoLexer::OP_CARET));)
+ {
+ GoLexer::TokenType op = t->m_type;
+ GoASTExpr *r = MulExpr();
+ if (r)
+ l.reset(new GoASTBinaryExpr(l.release(), r, op));
+ else
+ return syntaxerror();
+ }
+ return l.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::MulExpr()
+{
+ std::unique_ptr<GoASTExpr> l(UnaryExpr());
+ if (l)
+ {
+ for (GoLexer::Token *t; (t = match(GoLexer::OP_STAR)) || (t = match(GoLexer::OP_SLASH)) ||
+ (t = match(GoLexer::OP_PERCENT)) || (t = match(GoLexer::OP_LSHIFT)) ||
+ (t = match(GoLexer::OP_RSHIFT)) || (t = match(GoLexer::OP_AMP)) ||
+ (t = match(GoLexer::OP_AMP_CARET));)
+ {
+ GoLexer::TokenType op = t->m_type;
+ GoASTExpr *r = UnaryExpr();
+ if (r)
+ l.reset(new GoASTBinaryExpr(l.release(), r, op));
+ else
+ return syntaxerror();
+ }
+ return l.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::PrimaryExpr()
+{
+ GoASTExpr *l;
+ GoASTExpr *r;
+ (l = Conversion()) || (l = Operand());
+ if (!l)
+ return nullptr;
+ while ((r = Selector(l)) || (r = IndexOrSlice(l)) || (r = TypeAssertion(l)) || (r = Arguments(l)))
+ {
+ l = r;
+ }
+ return l;
+}
+
+GoASTExpr *
+GoParser::Operand()
+{
+ GoLexer::Token *lit;
+ if ((lit = match(GoLexer::LIT_INTEGER)) || (lit = match(GoLexer::LIT_FLOAT)) ||
+ (lit = match(GoLexer::LIT_IMAGINARY)) || (lit = match(GoLexer::LIT_RUNE)) || (lit = match(GoLexer::LIT_STRING)))
+ return new GoASTBasicLit(*lit);
+ if (match(GoLexer::OP_LPAREN))
+ {
+ GoASTExpr *e;
+ if (!((e = Expression()) && match(GoLexer::OP_RPAREN)))
+ return syntaxerror();
+ return e;
+ }
+ // MethodExpr should be handled by Selector
+ if (GoASTExpr *e = CompositeLit())
+ return e;
+ if (GoASTExpr *n = Name())
+ return n;
+ return FunctionLit();
+}
+
+GoASTExpr *
+GoParser::FunctionLit()
+{
+ if (!match(GoLexer::KEYWORD_FUNC))
+ return nullptr;
+ auto *sig = Signature();
+ if (!sig)
+ return syntaxerror();
+ auto *body = Block();
+ if (!body)
+ {
+ delete sig;
+ return syntaxerror();
+ }
+ return new GoASTFuncLit(sig, body);
+}
+
+GoASTBlockStmt *
+GoParser::Block()
+{
+ if (!match(GoLexer::OP_LBRACE))
+ return nullptr;
+ std::unique_ptr<GoASTBlockStmt> block(new GoASTBlockStmt);
+ for (auto *s = Statement(); s; s = Statement())
+ block->AddList(s);
+ if (!match(GoLexer::OP_RBRACE))
+ return syntaxerror();
+ return block.release();
+}
+
+GoASTExpr *
+GoParser::CompositeLit()
+{
+ Rule r("CompositeLit", this);
+ GoASTExpr *type;
+ (type = StructType()) || (type = ArrayOrSliceType(true)) || (type = MapType()) || (type = Name());
+ if (!type)
+ return r.error();
+ GoASTCompositeLit *lit = LiteralValue();
+ if (!lit)
+ return r.error();
+ lit->SetType(type);
+ return lit;
+}
+
+GoASTCompositeLit *
+GoParser::LiteralValue()
+{
+ if (!match(GoLexer::OP_LBRACE))
+ return nullptr;
+ std::unique_ptr<GoASTCompositeLit> lit(new GoASTCompositeLit);
+ for (GoASTExpr *e = Element(); e; e = Element())
+ {
+ lit->AddElts(e);
+ if (!match(GoLexer::OP_COMMA))
+ break;
+ }
+ if (!mustMatch(GoLexer::OP_RBRACE))
+ return nullptr;
+ return lit.release();
+}
+
+GoASTExpr *
+GoParser::Element()
+{
+ GoASTExpr *key;
+ if (!((key = Expression()) || (key = LiteralValue())))
+ return nullptr;
+ if (!match(GoLexer::OP_COLON))
+ return key;
+ GoASTExpr *value;
+ if ((value = Expression()) || (value = LiteralValue()))
+ return new GoASTKeyValueExpr(key, value);
+ delete key;
+ return syntaxerror();
+}
+
+GoASTExpr *
+GoParser::Selector(GoASTExpr *e)
+{
+ Rule r("Selector", this);
+ if (match(GoLexer::OP_DOT))
+ {
+ if (auto *name = Identifier())
+ return new GoASTSelectorExpr(e, name);
+ }
+ return r.error();
+}
+
+GoASTExpr *
+GoParser::IndexOrSlice(GoASTExpr *e)
+{
+ Rule r("IndexOrSlice", this);
+ if (match(GoLexer::OP_LBRACK))
+ {
+ std::unique_ptr<GoASTExpr> i1(Expression()), i2, i3;
+ bool slice = false;
+ if (match(GoLexer::OP_COLON))
+ {
+ slice = true;
+ i2.reset(Expression());
+ if (i2 && match(GoLexer::OP_COLON))
+ {
+ i3.reset(Expression());
+ if (!i3)
+ return syntaxerror();
+ }
+ }
+ if (!(slice || i1))
+ return syntaxerror();
+ if (!mustMatch(GoLexer::OP_RBRACK))
+ return nullptr;
+ if (slice)
+ {
+ bool slice3 = i3.get();
+ return new GoASTSliceExpr(e, i1.release(), i2.release(), i3.release(), slice3);
+ }
+ return new GoASTIndexExpr(e, i1.release());
+ }
+ return r.error();
+}
+
+GoASTExpr *
+GoParser::TypeAssertion(GoASTExpr *e)
+{
+ Rule r("TypeAssertion", this);
+ if (match(GoLexer::OP_DOT) && match(GoLexer::OP_LPAREN))
+ {
+ if (auto *t = Type())
+ {
+ if (!mustMatch(GoLexer::OP_RPAREN))
+ return nullptr;
+ return new GoASTTypeAssertExpr(e, t);
+ }
+ return syntaxerror();
+ }
+ return r.error();
+}
+
+GoASTExpr *
+GoParser::Arguments(GoASTExpr *e)
+{
+ if (match(GoLexer::OP_LPAREN))
+ {
+ std::unique_ptr<GoASTCallExpr> call(new GoASTCallExpr(false));
+ GoASTExpr *arg;
+ // ( ExpressionList | Type [ "," ExpressionList ] )
+ for ((arg = Expression()) || (arg = Type()); arg; arg = MoreExpressionList())
+ {
+ call->AddArgs(arg);
+ }
+ if (match(GoLexer::OP_DOTS))
+ call->SetEllipsis(true);
+
+ // Eat trailing comma
+ match(GoLexer::OP_COMMA);
+
+ if (!mustMatch(GoLexer::OP_RPAREN))
+ return nullptr;
+ call->SetFun(e);
+ return call.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::Conversion()
+{
+ Rule r("Conversion", this);
+ if (GoASTExpr *t = Type2())
+ {
+ if (match(GoLexer::OP_LPAREN))
+ {
+ GoASTExpr *v = Expression();
+ if (!v)
+ return syntaxerror();
+ match(GoLexer::OP_COMMA);
+ if (!mustMatch(GoLexer::OP_RPAREN))
+ return r.error();
+ GoASTCallExpr *call = new GoASTCallExpr(false);
+ call->SetFun(t);
+ call->AddArgs(v);
+ return call;
+ }
+ }
+ return r.error();
+}
+
+GoASTExpr *
+GoParser::Type2()
+{
+ switch (peek())
+ {
+ case GoLexer::OP_LBRACK:
+ return ArrayOrSliceType(false);
+ case GoLexer::KEYWORD_STRUCT:
+ return StructType();
+ case GoLexer::KEYWORD_FUNC:
+ return FunctionType();
+ case GoLexer::KEYWORD_INTERFACE:
+ return InterfaceType();
+ case GoLexer::KEYWORD_MAP:
+ return MapType();
+ case GoLexer::KEYWORD_CHAN:
+ return ChanType2();
+ default:
+ return nullptr;
+ }
+}
+
+GoASTExpr *
+GoParser::ArrayOrSliceType(bool allowEllipsis)
+{
+ Rule r("ArrayType", this);
+ if (match(GoLexer::OP_LBRACK))
+ {
+ std::unique_ptr<GoASTExpr> len;
+ if (allowEllipsis && match(GoLexer::OP_DOTS))
+ {
+ len.reset(new GoASTEllipsis(nullptr));
+ }
+ else
+ {
+ len.reset(Expression());
+ }
+
+ if (!match(GoLexer::OP_RBRACK))
+ return r.error();
+ GoASTExpr *elem = Type();
+ if (!elem)
+ return syntaxerror();
+ return new GoASTArrayType(len.release(), elem);
+ }
+ return r.error();
+}
+
+GoASTExpr *
+GoParser::StructType()
+{
+ if (!(match(GoLexer::KEYWORD_STRUCT) && mustMatch(GoLexer::OP_LBRACE)))
+ return nullptr;
+ std::unique_ptr<GoASTFieldList> fields(new GoASTFieldList);
+ while (auto *field = FieldDecl())
+ fields->AddList(field);
+ if (!mustMatch(GoLexer::OP_RBRACE))
+ return nullptr;
+ return new GoASTStructType(fields.release());
+}
+
+GoASTField *
+GoParser::FieldDecl()
+{
+ std::unique_ptr<GoASTField> f(new GoASTField);
+ GoASTExpr *t = FieldNamesAndType(f.get());
+ if (!t)
+ t = AnonymousFieldType();
+ if (!t)
+ return nullptr;
+
+ if (auto *tok = match(GoLexer::LIT_STRING))
+ f->SetTag(new GoASTBasicLit(*tok));
+ if (!Semicolon())
+ return syntaxerror();
+ return f.release();
+}
+
+GoASTExpr *
+GoParser::FieldNamesAndType(GoASTField *field)
+{
+ Rule r("FieldNames", this);
+ for (auto *id = Identifier(); id; id = MoreIdentifierList())
+ field->AddNames(id);
+ if (m_failed)
+ return nullptr;
+ GoASTExpr *t = Type();
+ if (t)
+ return t;
+ return r.error();
+}
+
+GoASTExpr *
+GoParser::AnonymousFieldType()
+{
+ bool pointer = match(GoLexer::OP_STAR);
+ GoASTExpr *t = Type();
+ if (!t)
+ return nullptr;
+ if (pointer)
+ return new GoASTStarExpr(t);
+ return t;
+}
+
+GoASTExpr *
+GoParser::FunctionType()
+{
+ if (!match(GoLexer::KEYWORD_FUNC))
+ return nullptr;
+ return Signature();
+}
+
+GoASTFuncType *
+GoParser::Signature()
+{
+ auto *params = Params();
+ if (!params)
+ return syntaxerror();
+ auto *result = Params();
+ if (!result)
+ {
+ if (auto *t = Type())
+ {
+ result = new GoASTFieldList;
+ auto *f = new GoASTField;
+ f->SetType(t);
+ result->AddList(f);
+ }
+ }
+ return new GoASTFuncType(params, result);
+}
+
+GoASTFieldList *
+GoParser::Params()
+{
+ if (!match(GoLexer::OP_LPAREN))
+ return nullptr;
+ std::unique_ptr<GoASTFieldList> l(new GoASTFieldList);
+ while (GoASTField *p = ParamDecl())
+ {
+ l->AddList(p);
+ if (!match(GoLexer::OP_COMMA))
+ break;
+ }
+ if (!mustMatch(GoLexer::OP_RPAREN))
+ return nullptr;
+ return l.release();
+}
+
+GoASTField *
+GoParser::ParamDecl()
+{
+ std::unique_ptr<GoASTField> field(new GoASTField);
+ GoASTIdent *id = Identifier();
+ if (id)
+ {
+ // Try `IdentifierList [ "..." ] Type`.
+ // If that fails, backtrack and try `[ "..." ] Type`.
+ Rule r("NamedParam", this);
+ for (; id; id = MoreIdentifierList())
+ field->AddNames(id);
+ GoASTExpr *t = ParamType();
+ if (t)
+ {
+ field->SetType(t);
+ return field.release();
+ }
+ field.reset(new GoASTField);
+ r.error();
+ }
+ GoASTExpr *t = ParamType();
+ if (t)
+ {
+ field->SetType(t);
+ return field.release();
+ }
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::ParamType()
+{
+ bool dots = match(GoLexer::OP_DOTS);
+ GoASTExpr *t = Type();
+ if (!dots)
+ return t;
+ if (!t)
+ return syntaxerror();
+ return new GoASTEllipsis(t);
+}
+
+GoASTExpr *
+GoParser::InterfaceType()
+{
+ if (!match(GoLexer::KEYWORD_INTERFACE) || !mustMatch(GoLexer::OP_LBRACE))
+ return nullptr;
+ std::unique_ptr<GoASTFieldList> methods(new GoASTFieldList);
+ while (true)
+ {
+ Rule r("MethodSpec", this);
+ // ( identifier Signature | TypeName ) ;
+ std::unique_ptr<GoASTIdent> id(Identifier());
+ if (!id)
+ break;
+ GoASTExpr *type = Signature();
+ if (!type)
+ {
+ r.error();
+ id.reset();
+ type = Name();
+ }
+ if (!Semicolon())
+ return syntaxerror();
+ auto *f = new GoASTField;
+ if (id)
+ f->AddNames(id.release());
+ f->SetType(type);
+ methods->AddList(f);
+ }
+ if (!mustMatch(GoLexer::OP_RBRACE))
+ return nullptr;
+ return new GoASTInterfaceType(methods.release());
+}
+
+GoASTExpr *
+GoParser::MapType()
+{
+ if (!(match(GoLexer::KEYWORD_MAP) && mustMatch(GoLexer::OP_LBRACK)))
+ return nullptr;
+ std::unique_ptr<GoASTExpr> key(Type());
+ if (!key)
+ return syntaxerror();
+ if (!mustMatch(GoLexer::OP_RBRACK))
+ return nullptr;
+ auto *elem = Type();
+ if (!elem)
+ return syntaxerror();
+ return new GoASTMapType(key.release(), elem);
+}
+
+GoASTExpr *
+GoParser::ChanType()
+{
+ Rule r("chan", this);
+ if (match(GoLexer::OP_LT_MINUS))
+ {
+ if (match(GoLexer::KEYWORD_CHAN))
+ {
+ auto *elem = Type();
+ if (!elem)
+ return syntaxerror();
+ return new GoASTChanType(GoASTNode::eChanRecv, elem);
+ }
+ return r.error();
+ }
+ return ChanType2();
+}
+
+GoASTExpr *
+GoParser::ChanType2()
+{
+ if (!match(GoLexer::KEYWORD_CHAN))
+ return nullptr;
+ auto dir = GoASTNode::eChanBidir;
+ if (match(GoLexer::OP_LT_MINUS))
+ dir = GoASTNode::eChanSend;
+ auto *elem = Type();
+ if (!elem)
+ return syntaxerror();
+ return new GoASTChanType(dir, elem);
+}
+
+GoASTExpr *
+GoParser::Type()
+{
+ if (GoASTExpr *t = Type2())
+ return t;
+ if (GoASTExpr *t = Name())
+ return t;
+ if (GoASTExpr *t = ChanType())
+ return t;
+ if (match(GoLexer::OP_STAR))
+ {
+ GoASTExpr *t = Type();
+ if (!t)
+ return syntaxerror();
+ return new GoASTStarExpr(t);
+ }
+ if (match(GoLexer::OP_LPAREN))
+ {
+ std::unique_ptr<GoASTExpr> t(Type());
+ if (!t || !match(GoLexer::OP_RPAREN))
+ return syntaxerror();
+ return t.release();
+ }
+ return nullptr;
+}
+
+bool
+GoParser::Semicolon()
+{
+ if (match(GoLexer::OP_SEMICOLON))
+ return true;
+ switch (peek())
+ {
+ case GoLexer::OP_RPAREN:
+ case GoLexer::OP_RBRACE:
+ case GoLexer::TOK_EOF:
+ return true;
+ default:
+ return false;
+ }
+}
+
+GoASTExpr *
+GoParser::Name()
+{
+ if (auto *id = Identifier())
+ {
+ if (GoASTExpr *qual = QualifiedIdent(id))
+ return qual;
+ return id;
+ }
+ return nullptr;
+}
+
+GoASTExpr *
+GoParser::QualifiedIdent(lldb_private::GoASTIdent *p)
+{
+ Rule r("QualifiedIdent", this);
+ llvm::SmallString<32> path(p->GetName().m_value);
+ GoLexer::Token *next;
+ bool have_slashes = false;
+ // LLDB extension: support full/package/path.name
+ while (match(GoLexer::OP_SLASH) && (next = match(GoLexer::TOK_IDENTIFIER)))
+ {
+ have_slashes = true;
+ path.append("/");
+ path.append(next->m_value);
+ }
+ if (match(GoLexer::OP_DOT))
+ {
+ auto *name = Identifier();
+ if (name)
+ {
+ if (have_slashes)
+ {
+ p->SetName(GoLexer::Token(GoLexer::TOK_IDENTIFIER, CopyString(path)));
+ }
+ return new GoASTSelectorExpr(p, name);
+ }
+ }
+ return r.error();
+}
+
+llvm::StringRef
+GoParser::CopyString(llvm::StringRef s)
+{
+ return m_strings.insert(std::make_pair(s, 'x')).first->getKey();
+}
+
+void
+GoParser::GetError(Error &error)
+{
+ llvm::StringRef want;
+ if (m_failed)
+ want = m_last_tok == GoLexer::TOK_INVALID ? DescribeToken(m_last_tok) : m_last;
+ else
+ want = m_error;
+ size_t len = m_lexer.BytesRemaining();
+ if (len > 10)
+ len = 10;
+ llvm::StringRef got;
+ if (len == 0)
+ got = "<eof>";
+ else
+ got = m_lexer.GetString(len);
+ error.SetErrorStringWithFormat("Syntax error: expected %s before '%s'.", want.str().c_str(), got.str().c_str());
+}
diff --git a/source/Plugins/ExpressionParser/Go/GoParser.h b/source/Plugins/ExpressionParser/Go/GoParser.h
new file mode 100644
index 000000000000..9ceb670ccd11
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Go/GoParser.h
@@ -0,0 +1,165 @@
+//===-- GoParser.h -----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GoParser_h
+#define liblldb_GoParser_h
+
+#include "lldb/lldb-private.h"
+#include "Plugins/ExpressionParser/Go/GoAST.h"
+#include "Plugins/ExpressionParser/Go/GoLexer.h"
+
+namespace lldb_private
+{
+class GoParser
+{
+ public:
+ explicit GoParser(const char *src);
+
+ GoASTStmt *Statement();
+
+ GoASTStmt *GoStmt();
+ GoASTStmt *ReturnStmt();
+ GoASTStmt *BranchStmt();
+ GoASTStmt *EmptyStmt();
+ GoASTStmt *ExpressionStmt(GoASTExpr *e);
+ GoASTStmt *IncDecStmt(GoASTExpr *e);
+ GoASTStmt *Assignment(GoASTExpr *e);
+ GoASTBlockStmt *Block();
+
+ GoASTExpr *MoreExpressionList(); // ["," Expression]
+ GoASTIdent *MoreIdentifierList(); // ["," Identifier]
+
+ GoASTExpr *Expression();
+ GoASTExpr *UnaryExpr();
+ GoASTExpr *OrExpr();
+ GoASTExpr *AndExpr();
+ GoASTExpr *RelExpr();
+ GoASTExpr *AddExpr();
+ GoASTExpr *MulExpr();
+ GoASTExpr *PrimaryExpr();
+ GoASTExpr *Operand();
+ GoASTExpr *Conversion();
+
+ GoASTExpr *Selector(GoASTExpr *e);
+ GoASTExpr *IndexOrSlice(GoASTExpr *e);
+ GoASTExpr *TypeAssertion(GoASTExpr *e);
+ GoASTExpr *Arguments(GoASTExpr *e);
+
+ GoASTExpr *Type();
+ GoASTExpr *Type2();
+ GoASTExpr *ArrayOrSliceType(bool allowEllipsis);
+ GoASTExpr *StructType();
+ GoASTExpr *FunctionType();
+ GoASTExpr *InterfaceType();
+ GoASTExpr *MapType();
+ GoASTExpr *ChanType();
+ GoASTExpr *ChanType2();
+
+ GoASTExpr *Name();
+ GoASTExpr *QualifiedIdent(GoASTIdent *p);
+ GoASTIdent *Identifier();
+
+ GoASTField *FieldDecl();
+ GoASTExpr *AnonymousFieldType();
+ GoASTExpr *FieldNamesAndType(GoASTField *f);
+
+ GoASTFieldList *Params();
+ GoASTField *ParamDecl();
+ GoASTExpr *ParamType();
+ GoASTFuncType *Signature();
+ GoASTExpr *CompositeLit();
+ GoASTExpr *FunctionLit();
+ GoASTExpr *Element();
+ GoASTCompositeLit *LiteralValue();
+
+ bool
+ Failed() const
+ {
+ return m_failed;
+ }
+ bool
+ AtEOF() const
+ {
+ return m_lexer.BytesRemaining() == 0 && m_pos == m_tokens.size();
+ }
+
+ void GetError(Error &error);
+
+ private:
+ class Rule;
+ friend class Rule;
+
+ std::nullptr_t
+ syntaxerror()
+ {
+ m_failed = true;
+ return nullptr;
+ }
+ GoLexer::Token &
+ next()
+ {
+ if (m_pos >= m_tokens.size())
+ {
+ if (m_pos != 0 &&
+ (m_tokens.back().m_type == GoLexer::TOK_EOF || m_tokens.back().m_type == GoLexer::TOK_INVALID))
+ return m_tokens.back();
+ m_pos = m_tokens.size();
+ m_tokens.push_back(m_lexer.Lex());
+ }
+ return m_tokens[m_pos++];
+ }
+ GoLexer::TokenType
+ peek()
+ {
+ GoLexer::Token &tok = next();
+ --m_pos;
+ return tok.m_type;
+ }
+ GoLexer::Token *
+ match(GoLexer::TokenType t)
+ {
+ GoLexer::Token &tok = next();
+ if (tok.m_type == t)
+ return &tok;
+ --m_pos;
+ m_last_tok = t;
+ return nullptr;
+ }
+ GoLexer::Token *
+ mustMatch(GoLexer::TokenType t)
+ {
+ GoLexer::Token *tok = match(t);
+ if (tok)
+ return tok;
+ return syntaxerror();
+ }
+ bool Semicolon();
+
+ GoASTStmt *
+ FinishStmt(GoASTStmt *s)
+ {
+ if (!Semicolon())
+ m_failed = true;
+ return s;
+ }
+
+ llvm::StringRef CopyString(llvm::StringRef s);
+
+ GoLexer m_lexer;
+ std::vector<GoLexer::Token> m_tokens;
+ size_t m_pos;
+ llvm::StringRef m_error;
+ llvm::StringRef m_last;
+ GoLexer::TokenType m_last_tok;
+ llvm::StringMap<uint8_t> m_strings;
+ bool m_failed;
+};
+}
+
+#endif
diff --git a/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp b/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp
new file mode 100644
index 000000000000..3f12a2b6255b
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp
@@ -0,0 +1,756 @@
+//===-- GoUserExpression.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+// C++ Includes
+#include <cstdlib>
+#include <memory>
+#include <string>
+#include <vector>
+
+// Other libraries and framework includes
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringMap.h"
+
+// Project includes
+#include "GoUserExpression.h"
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataEncoder.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Core/ValueObjectRegister.h"
+#include "lldb/Expression/ExpressionVariable.h"
+#include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/GoASTContext.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallUserExpression.h"
+
+#include "Plugins/ExpressionParser/Go/GoAST.h"
+#include "Plugins/ExpressionParser/Go/GoParser.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+class GoUserExpression::GoInterpreter
+{
+ public:
+ GoInterpreter(ExecutionContext &exe_ctx, const char *expr)
+ : m_exe_ctx(exe_ctx), m_frame(exe_ctx.GetFrameSP()), m_parser(expr)
+ {
+ if (m_frame)
+ {
+ const SymbolContext &ctx = m_frame->GetSymbolContext(eSymbolContextFunction);
+ ConstString fname = ctx.GetFunctionName();
+ if (fname.GetLength() > 0)
+ {
+ size_t dot = fname.GetStringRef().find('.');
+ if (dot != llvm::StringRef::npos)
+ m_package = llvm::StringRef(fname.AsCString(), dot);
+ }
+ }
+ }
+
+ void
+ set_use_dynamic(DynamicValueType use_dynamic)
+ {
+ m_use_dynamic = use_dynamic;
+ }
+
+ bool Parse();
+ lldb::ValueObjectSP Evaluate(ExecutionContext &exe_ctx);
+ lldb::ValueObjectSP EvaluateStatement(const GoASTStmt *s);
+ lldb::ValueObjectSP EvaluateExpr(const GoASTExpr *e);
+
+ ValueObjectSP
+ VisitBadExpr(const GoASTBadExpr *e)
+ {
+ m_parser.GetError(m_error);
+ return nullptr;
+ }
+
+ ValueObjectSP VisitParenExpr(const GoASTParenExpr *e);
+ ValueObjectSP VisitIdent(const GoASTIdent *e);
+ ValueObjectSP VisitStarExpr(const GoASTStarExpr *e);
+ ValueObjectSP VisitSelectorExpr(const GoASTSelectorExpr *e);
+ ValueObjectSP VisitBasicLit(const GoASTBasicLit *e);
+ ValueObjectSP VisitIndexExpr(const GoASTIndexExpr *e);
+ ValueObjectSP VisitUnaryExpr(const GoASTUnaryExpr *e);
+ ValueObjectSP VisitCallExpr(const GoASTCallExpr *e);
+
+ ValueObjectSP
+ VisitTypeAssertExpr(const GoASTTypeAssertExpr *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitBinaryExpr(const GoASTBinaryExpr *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitArrayType(const GoASTArrayType *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitChanType(const GoASTChanType *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitCompositeLit(const GoASTCompositeLit *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitEllipsis(const GoASTEllipsis *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitFuncType(const GoASTFuncType *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitFuncLit(const GoASTFuncLit *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitInterfaceType(const GoASTInterfaceType *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitKeyValueExpr(const GoASTKeyValueExpr *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitMapType(const GoASTMapType *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitSliceExpr(const GoASTSliceExpr *e)
+ {
+ return NotImplemented(e);
+ }
+
+ ValueObjectSP
+ VisitStructType(const GoASTStructType *e)
+ {
+ return NotImplemented(e);
+ }
+
+ CompilerType EvaluateType(const GoASTExpr *e);
+
+ Error &
+ error()
+ {
+ return m_error;
+ }
+
+ private:
+ std::nullptr_t
+ NotImplemented(const GoASTExpr *e)
+ {
+ m_error.SetErrorStringWithFormat("%s node not implemented", e->GetKindName());
+ return nullptr;
+ }
+
+ ExecutionContext m_exe_ctx;
+ lldb::StackFrameSP m_frame;
+ GoParser m_parser;
+ DynamicValueType m_use_dynamic;
+ Error m_error;
+ llvm::StringRef m_package;
+ std::vector<std::unique_ptr<GoASTStmt>> m_statements;
+};
+
+VariableSP
+FindGlobalVariable(TargetSP target, llvm::Twine name)
+{
+ ConstString fullname(name.str());
+ VariableList variable_list;
+ const bool append = true;
+ if (!target)
+ {
+ return nullptr;
+ }
+ const uint32_t match_count = target->GetImages().FindGlobalVariables(fullname, append, 1, variable_list);
+ if (match_count == 1)
+ {
+ return variable_list.GetVariableAtIndex(0);
+ }
+ return nullptr;
+}
+
+CompilerType
+LookupType(TargetSP target, ConstString name)
+{
+ if (!target)
+ return CompilerType();
+ SymbolContext sc;
+ TypeList type_list;
+ uint32_t num_matches = target->GetImages().FindTypes(sc, name, false, 2, type_list);
+ if (num_matches > 0)
+ {
+ return type_list.GetTypeAtIndex(0)->GetFullCompilerType();
+ }
+ return CompilerType();
+}
+
+GoUserExpression::GoUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix,
+ lldb::LanguageType language, ResultType desired_type,
+ const EvaluateExpressionOptions &options)
+ : UserExpression(exe_scope, expr, expr_prefix, language, desired_type, options)
+{
+}
+
+bool
+GoUserExpression::Parse(Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy,
+ bool keep_result_in_memory, bool generate_debug_info)
+{
+ InstallContext(exe_ctx);
+ m_interpreter.reset(new GoInterpreter(exe_ctx, GetUserText()));
+ if (m_interpreter->Parse())
+ return true;
+ const char *error_cstr = m_interpreter->error().AsCString();
+ if (error_cstr && error_cstr[0])
+ error_stream.Printf("error: %s\n", error_cstr);
+ else
+ error_stream.Printf("error: expression can't be interpreted or run\n");
+ return false;
+}
+
+lldb::ExpressionResults
+GoUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options,
+ lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result)
+{
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
+
+ lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
+ lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
+
+ Process *process = exe_ctx.GetProcessPtr();
+ Target *target = exe_ctx.GetTargetPtr();
+
+ if (target == nullptr || process == nullptr || process->GetState() != lldb::eStateStopped)
+ {
+ if (execution_policy == eExecutionPolicyAlways)
+ {
+ if (log)
+ log->Printf("== [GoUserExpression::Evaluate] Expression may not run, but is not constant ==");
+
+ error_stream.Printf("expression needed to run but couldn't");
+
+ return execution_results;
+ }
+ }
+
+ m_interpreter->set_use_dynamic(options.GetUseDynamic());
+ ValueObjectSP result_val_sp = m_interpreter->Evaluate(exe_ctx);
+ Error err = m_interpreter->error();
+ m_interpreter.reset();
+
+ if (!result_val_sp)
+ {
+ const char *error_cstr = err.AsCString();
+ if (error_cstr && error_cstr[0])
+ error_stream.Printf("error: %s\n", error_cstr);
+ else
+ error_stream.Printf("error: expression can't be interpreted or run\n");
+ return lldb::eExpressionDiscarded;
+ }
+ result.reset(new ExpressionVariable(ExpressionVariable::eKindGo));
+ result->m_live_sp = result->m_frozen_sp = result_val_sp;
+ result->m_flags |= ExpressionVariable::EVIsProgramReference;
+ PersistentExpressionState *pv = target->GetPersistentExpressionStateForLanguage(eLanguageTypeGo);
+ if (pv != nullptr)
+ {
+ result->SetName(pv->GetNextPersistentVariableName());
+ pv->AddVariable(result);
+ }
+ return lldb::eExpressionCompleted;
+}
+
+bool
+GoUserExpression::GoInterpreter::Parse()
+{
+ for (std::unique_ptr<GoASTStmt> stmt(m_parser.Statement()); stmt; stmt.reset(m_parser.Statement()))
+ {
+ if (m_parser.Failed())
+ break;
+ m_statements.emplace_back(std::move(stmt));
+ }
+ if (m_parser.Failed() || !m_parser.AtEOF())
+ m_parser.GetError(m_error);
+
+ return m_error.Success();
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::Evaluate(ExecutionContext &exe_ctx)
+{
+ m_exe_ctx = exe_ctx;
+ ValueObjectSP result;
+ for (const std::unique_ptr<GoASTStmt> &stmt : m_statements)
+ {
+ result = EvaluateStatement(stmt.get());
+ if (m_error.Fail())
+ return nullptr;
+ }
+ return result;
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::EvaluateStatement(const lldb_private::GoASTStmt *stmt)
+{
+ ValueObjectSP result;
+ switch (stmt->GetKind())
+ {
+ case GoASTNode::eBlockStmt:
+ {
+ const GoASTBlockStmt *block = llvm::cast<GoASTBlockStmt>(stmt);
+ for (size_t i = 0; i < block->NumList(); ++i)
+ result = EvaluateStatement(block->GetList(i));
+ break;
+ }
+ case GoASTNode::eBadStmt:
+ m_parser.GetError(m_error);
+ break;
+ case GoASTNode::eExprStmt:
+ {
+ const GoASTExprStmt *expr = llvm::cast<GoASTExprStmt>(stmt);
+ return EvaluateExpr(expr->GetX());
+ }
+ default:
+ m_error.SetErrorStringWithFormat("%s node not supported", stmt->GetKindName());
+ }
+ return result;
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::EvaluateExpr(const lldb_private::GoASTExpr *e)
+{
+ if (e)
+ return e->Visit<ValueObjectSP>(this);
+ return ValueObjectSP();
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitParenExpr(const lldb_private::GoASTParenExpr *e)
+{
+ return EvaluateExpr(e->GetX());
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitIdent(const GoASTIdent *e)
+{
+ ValueObjectSP val;
+ if (m_frame)
+ {
+ VariableSP var_sp;
+ std::string varname = e->GetName().m_value.str();
+ if (varname.size() > 1 && varname[0] == '$')
+ {
+ RegisterContextSP reg_ctx_sp = m_frame->GetRegisterContext();
+ const RegisterInfo *reg = reg_ctx_sp->GetRegisterInfoByName(varname.c_str() + 1);
+ if (reg)
+ {
+ std::string type;
+ switch (reg->encoding)
+ {
+ case lldb::eEncodingSint:
+ type.append("int");
+ break;
+ case lldb::eEncodingUint:
+ type.append("uint");
+ break;
+ case lldb::eEncodingIEEE754:
+ type.append("float");
+ break;
+ default:
+ m_error.SetErrorString("Invaild register encoding");
+ return nullptr;
+ }
+ switch (reg->byte_size)
+ {
+ case 8:
+ type.append("64");
+ break;
+ case 4:
+ type.append("32");
+ break;
+ case 2:
+ type.append("16");
+ break;
+ case 1:
+ type.append("8");
+ break;
+ default:
+ m_error.SetErrorString("Invaild register size");
+ return nullptr;
+ }
+ ValueObjectSP regVal =
+ ValueObjectRegister::Create(m_frame.get(), reg_ctx_sp, reg->kinds[eRegisterKindLLDB]);
+ CompilerType goType = LookupType(m_frame->CalculateTarget(), ConstString(type));
+ if (regVal)
+ {
+ regVal = regVal->Cast(goType);
+ return regVal;
+ }
+ }
+ m_error.SetErrorString("Invaild register name");
+ return nullptr;
+ }
+ VariableListSP var_list_sp(m_frame->GetInScopeVariableList(false));
+ if (var_list_sp)
+ {
+ var_sp = var_list_sp->FindVariable(ConstString(varname));
+ if (var_sp)
+ val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic);
+ else
+ {
+ // When a variable is on the heap instead of the stack, go records a variable
+ // '&x' instead of 'x'.
+ var_sp = var_list_sp->FindVariable(ConstString("&" + varname));
+ if (var_sp)
+ {
+ val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic);
+ if (val)
+ val = val->Dereference(m_error);
+ if (m_error.Fail())
+ return nullptr;
+ }
+ }
+ }
+ if (!val)
+ {
+ m_error.Clear();
+ TargetSP target = m_frame->CalculateTarget();
+ if (!target)
+ {
+ m_error.SetErrorString("No target");
+ return nullptr;
+ }
+ var_sp = FindGlobalVariable(target, m_package + "." + e->GetName().m_value);
+ if (var_sp)
+ return m_frame->TrackGlobalVariable(var_sp, m_use_dynamic);
+ }
+ }
+ if (!val)
+ m_error.SetErrorStringWithFormat("Unknown variable %s", e->GetName().m_value.str().c_str());
+ return val;
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitStarExpr(const GoASTStarExpr *e)
+{
+ ValueObjectSP target = EvaluateExpr(e->GetX());
+ if (!target)
+ return nullptr;
+ return target->Dereference(m_error);
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitSelectorExpr(const lldb_private::GoASTSelectorExpr *e)
+{
+ ValueObjectSP target = EvaluateExpr(e->GetX());
+ if (target)
+ {
+ if (target->GetCompilerType().IsPointerType())
+ {
+ target = target->Dereference(m_error);
+ if (m_error.Fail())
+ return nullptr;
+ }
+ ConstString field(e->GetSel()->GetName().m_value);
+ ValueObjectSP result = target->GetChildMemberWithName(field, true);
+ if (!result)
+ m_error.SetErrorStringWithFormat("Unknown child %s", field.AsCString());
+ return result;
+ }
+ if (const GoASTIdent *package = llvm::dyn_cast<GoASTIdent>(e->GetX()))
+ {
+ if (VariableSP global = FindGlobalVariable(m_exe_ctx.GetTargetSP(),
+ package->GetName().m_value + "." + e->GetSel()->GetName().m_value))
+ {
+ if (m_frame)
+ {
+ m_error.Clear();
+ return m_frame->GetValueObjectForFrameVariable(global, m_use_dynamic);
+ }
+ }
+ }
+ if (const GoASTBasicLit *packageLit = llvm::dyn_cast<GoASTBasicLit>(e->GetX()))
+ {
+ if (packageLit->GetValue().m_type == GoLexer::LIT_STRING)
+ {
+ std::string value = packageLit->GetValue().m_value.str();
+ value = value.substr(1, value.size() - 2);
+ if (VariableSP global =
+ FindGlobalVariable(m_exe_ctx.GetTargetSP(), value + "." + e->GetSel()->GetName().m_value))
+ {
+ if (m_frame)
+ {
+ m_error.Clear();
+ return m_frame->TrackGlobalVariable(global, m_use_dynamic);
+ }
+ }
+ }
+ }
+ // EvaluateExpr should have already set m_error.
+ return target;
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitBasicLit(const lldb_private::GoASTBasicLit *e)
+{
+ std::string value = e->GetValue().m_value.str();
+ if (e->GetValue().m_type != GoLexer::LIT_INTEGER)
+ {
+ m_error.SetErrorStringWithFormat("Unsupported literal %s", value.c_str());
+ return nullptr;
+ }
+ errno = 0;
+ int64_t intvalue = strtol(value.c_str(), nullptr, 0);
+ if (errno != 0)
+ {
+ m_error.SetErrorToErrno();
+ return nullptr;
+ }
+ DataBufferSP buf(new DataBufferHeap(sizeof(intvalue), 0));
+ TargetSP target = m_exe_ctx.GetTargetSP();
+ if (!target)
+ {
+ m_error.SetErrorString("No target");
+ return nullptr;
+ }
+ ByteOrder order = target->GetArchitecture().GetByteOrder();
+ uint8_t addr_size = target->GetArchitecture().GetAddressByteSize();
+ DataEncoder enc(buf, order, addr_size);
+ enc.PutU64(0, static_cast<uint64_t>(intvalue));
+ DataExtractor data(buf, order, addr_size);
+
+ CompilerType type = LookupType(target, ConstString("int64"));
+ return ValueObject::CreateValueObjectFromData(nullptr, data, m_exe_ctx, type);
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitIndexExpr(const lldb_private::GoASTIndexExpr *e)
+{
+ ValueObjectSP target = EvaluateExpr(e->GetX());
+ if (!target)
+ return nullptr;
+ ValueObjectSP index = EvaluateExpr(e->GetIndex());
+ if (!index)
+ return nullptr;
+ bool is_signed;
+ if (!index->GetCompilerType().IsIntegerType(is_signed))
+ {
+ m_error.SetErrorString("Unsupported index");
+ return nullptr;
+ }
+ size_t idx;
+ if (is_signed)
+ idx = index->GetValueAsSigned(0);
+ else
+ idx = index->GetValueAsUnsigned(0);
+ if (GoASTContext::IsGoSlice(target->GetCompilerType()))
+ {
+ target = target->GetStaticValue();
+ ValueObjectSP cap = target->GetChildMemberWithName(ConstString("cap"), true);
+ if (cap)
+ {
+ uint64_t capval = cap->GetValueAsUnsigned(0);
+ if (idx >= capval)
+ {
+ m_error.SetErrorStringWithFormat("Invalid index %" PRIu64 " , cap = %" PRIu64, uint64_t(idx), capval);
+ return nullptr;
+ }
+ }
+ target = target->GetChildMemberWithName(ConstString("array"), true);
+ if (target && m_use_dynamic != eNoDynamicValues)
+ {
+ ValueObjectSP dynamic = target->GetDynamicValue(m_use_dynamic);
+ if (dynamic)
+ target = dynamic;
+ }
+ if (!target)
+ return nullptr;
+ return target->GetSyntheticArrayMember(idx, true);
+ }
+ return target->GetChildAtIndex(idx, true);
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitUnaryExpr(const GoASTUnaryExpr *e)
+{
+ ValueObjectSP x = EvaluateExpr(e->GetX());
+ if (!x)
+ return nullptr;
+ switch (e->GetOp())
+ {
+ case GoLexer::OP_AMP:
+ {
+ CompilerType type = x->GetCompilerType().GetPointerType();
+ uint64_t address = x->GetAddressOf();
+ return ValueObject::CreateValueObjectFromAddress(nullptr, address, m_exe_ctx, type);
+ }
+ case GoLexer::OP_PLUS:
+ return x;
+ default:
+ m_error.SetErrorStringWithFormat("Operator %s not supported",
+ GoLexer::LookupToken(e->GetOp()).str().c_str());
+ return nullptr;
+ }
+}
+
+CompilerType
+GoUserExpression::GoInterpreter::EvaluateType(const GoASTExpr *e)
+{
+ TargetSP target = m_exe_ctx.GetTargetSP();
+ if (auto *id = llvm::dyn_cast<GoASTIdent>(e))
+ {
+ CompilerType result = LookupType(target, ConstString(id->GetName().m_value));
+ if (result.IsValid())
+ return result;
+ std::string fullname = (m_package + "." + id->GetName().m_value).str();
+ result = LookupType(target, ConstString(fullname));
+ if (!result)
+ m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str());
+ return result;
+ }
+ if (auto *sel = llvm::dyn_cast<GoASTSelectorExpr>(e))
+ {
+ std::string package;
+ if (auto *pkg_node = llvm::dyn_cast<GoASTIdent>(sel->GetX()))
+ {
+ package = pkg_node->GetName().m_value.str();
+ }
+ else if (auto *str_node = llvm::dyn_cast<GoASTBasicLit>(sel->GetX()))
+ {
+ if (str_node->GetValue().m_type == GoLexer::LIT_STRING)
+ {
+ package = str_node->GetValue().m_value.substr(1).str();
+ package.resize(package.length() - 1);
+ }
+ }
+ if (package.empty())
+ {
+ m_error.SetErrorStringWithFormat("Invalid %s in type expression", sel->GetX()->GetKindName());
+ return CompilerType();
+ }
+ std::string fullname = (package + "." + sel->GetSel()->GetName().m_value).str();
+ CompilerType result = LookupType(target, ConstString(fullname));
+ if (!result)
+ m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str());
+ return result;
+ }
+ if (auto *star = llvm::dyn_cast<GoASTStarExpr>(e))
+ {
+ CompilerType elem = EvaluateType(star->GetX());
+ return elem.GetPointerType();
+ }
+ if (auto *paren = llvm::dyn_cast<GoASTParenExpr>(e))
+ return EvaluateType(paren->GetX());
+ if (auto *array = llvm::dyn_cast<GoASTArrayType>(e))
+ {
+ CompilerType elem = EvaluateType(array->GetElt());
+ }
+
+ m_error.SetErrorStringWithFormat("Invalid %s in type expression", e->GetKindName());
+ return CompilerType();
+}
+
+ValueObjectSP
+GoUserExpression::GoInterpreter::VisitCallExpr(const lldb_private::GoASTCallExpr *e)
+{
+ ValueObjectSP x = EvaluateExpr(e->GetFun());
+ if (x || e->NumArgs() != 1)
+ {
+ m_error.SetErrorStringWithFormat("Code execution not supported");
+ return nullptr;
+ }
+ m_error.Clear();
+ CompilerType type = EvaluateType(e->GetFun());
+ if (!type)
+ {
+ return nullptr;
+ }
+ ValueObjectSP value = EvaluateExpr(e->GetArgs(0));
+ if (!value)
+ return nullptr;
+ // TODO: Handle special conversions
+ return value->Cast(type);
+}
+
+GoPersistentExpressionState::GoPersistentExpressionState() : PersistentExpressionState(eKindGo)
+{
+}
+
+ConstString
+GoPersistentExpressionState::GetNextPersistentVariableName()
+{
+ char name_cstr[256];
+ // We can't use the same variable format as clang.
+ ::snprintf(name_cstr, sizeof(name_cstr), "$go%u", m_next_persistent_variable_id++);
+ ConstString name(name_cstr);
+ return name;
+}
+
+void
+GoPersistentExpressionState::RemovePersistentVariable(lldb::ExpressionVariableSP variable)
+{
+ RemoveVariable(variable);
+
+ const char *name = variable->GetName().AsCString();
+
+ if (*(name++) != '$')
+ return;
+ if (*(name++) != 'g')
+ return;
+ if (*(name++) != 'o')
+ return;
+
+ if (strtoul(name, nullptr, 0) == m_next_persistent_variable_id - 1)
+ m_next_persistent_variable_id--;
+}
diff --git a/source/Plugins/ExpressionParser/Go/GoUserExpression.h b/source/Plugins/ExpressionParser/Go/GoUserExpression.h
new file mode 100644
index 000000000000..b429c68f023d
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Go/GoUserExpression.h
@@ -0,0 +1,98 @@
+//===-- GoUserExpression.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GoUserExpression_h_
+#define liblldb_GoUserExpression_h_
+
+// C Includes
+// C++ Includes
+#include <memory>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Expression/UserExpression.h"
+#include "lldb/Expression/ExpressionVariable.h"
+#include "lldb/Target/ExecutionContext.h"
+
+namespace lldb_private
+{
+class GoParser;
+
+class GoPersistentExpressionState : public PersistentExpressionState
+{
+ public:
+ GoPersistentExpressionState();
+
+ ConstString GetNextPersistentVariableName() override;
+
+ void RemovePersistentVariable(lldb::ExpressionVariableSP variable) override;
+
+ lldb::addr_t
+ LookupSymbol(const ConstString &name) override
+ {
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ static bool
+ classof(const PersistentExpressionState *pv)
+ {
+ return pv->getKind() == PersistentExpressionState::eKindGo;
+ }
+
+ private:
+ uint32_t m_next_persistent_variable_id; ///< The counter used by GetNextResultName().
+};
+
+//----------------------------------------------------------------------
+/// @class GoUserExpression GoUserExpression.h "lldb/Expression/GoUserExpression.h"
+/// @brief Encapsulates a single expression for use with Go
+///
+/// LLDB uses expressions for various purposes, notably to call functions
+/// and as a backend for the expr command. GoUserExpression encapsulates
+/// the objects needed to parse and interpret an expression.
+//----------------------------------------------------------------------
+class GoUserExpression : public UserExpression
+{
+ public:
+ GoUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix,
+ lldb::LanguageType language, ResultType desired_type, const EvaluateExpressionOptions &options);
+
+ bool
+ Parse(Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy,
+ bool keep_result_in_memory, bool generate_debug_info) override;
+
+ lldb::ExpressionResults
+ Execute(Stream &error_stream, ExecutionContext &exe_ctx,
+ const EvaluateExpressionOptions &options,
+ lldb::UserExpressionSP &shared_ptr_to_me,
+ lldb::ExpressionVariableSP &result) override;
+
+ bool
+ CanInterpret() override
+ {
+ return true;
+ }
+ bool
+ FinalizeJITExecution(Stream &error_stream, ExecutionContext &exe_ctx, lldb::ExpressionVariableSP &result,
+ lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS,
+ lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS) override
+ {
+ return true;
+ }
+
+ private:
+ class GoInterpreter;
+ std::unique_ptr<GoInterpreter> m_interpreter;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_GoUserExpression_h_
diff --git a/source/Plugins/ExpressionParser/Go/gen_go_ast.py b/source/Plugins/ExpressionParser/Go/gen_go_ast.py
new file mode 100644
index 000000000000..05b589a9976c
--- /dev/null
+++ b/source/Plugins/ExpressionParser/Go/gen_go_ast.py
@@ -0,0 +1,356 @@
+import StringIO
+
+def addNodes():
+ addNode("ArrayType", "Expr", "len", "Expr", "elt", "Expr")
+ addNode("AssignStmt", "Stmt", "lhs", "[]Expr", "rhs", "[]Expr", "define", "bool")
+ addNode("BadDecl", "Decl")
+ addNode("BadExpr", "Expr")
+ addNode("BadStmt", "Stmt")
+ addNode("BasicLit", "Expr", "value", "Token")
+ addNode("BinaryExpr", "Expr", "x", "Expr", "y", "Expr", "op", "TokenType")
+ addNode("BlockStmt", "Stmt", "list", "[]Stmt")
+ addNode("Ident", "Expr", "name", "Token")
+ addNode("BranchStmt", "Stmt", "label", "Ident", "tok", "TokenType")
+ addNode("CallExpr", "Expr", "fun", "Expr", "args", "[]Expr", "ellipsis", "bool")
+ addNode("CaseClause", "Stmt", "list", "[]Expr", "body", "[]Stmt")
+ addNode("ChanType", "Expr", "dir", "ChanDir", "value", "Expr")
+ addNode("CommClause", "Stmt", "comm", "Stmt", "body", "[]Stmt")
+ addNode("CompositeLit", "Expr", "type", "Expr", "elts", "[]Expr")
+ addNode("DeclStmt", "Stmt", "decl", "Decl")
+ addNode("DeferStmt", "Stmt", "call", "CallExpr")
+ addNode("Ellipsis", "Expr", "elt", "Expr")
+ addNode("EmptyStmt", "Stmt")
+ addNode("ExprStmt", "Stmt", "x", "Expr")
+ addNode("Field", "Node", "names", "[]Ident", "type", "Expr", "tag", "BasicLit")
+ addNode("FieldList", "Node", "list", "[]Field")
+ addNode("ForStmt", "Stmt", "init", "Stmt", "cond", "Expr", "post", "Stmt", "body", "BlockStmt")
+ addNode("FuncType", "Expr", "params", "FieldList", "results", "FieldList")
+ addNode("FuncDecl", "Decl", "recv", "FieldList", "name", "Ident", "type", "FuncType", "body", "BlockStmt")
+ addNode("FuncLit", "Expr", "type", "FuncType", "body", "BlockStmt")
+ addNode("GenDecl", "Decl", "tok", "TokenType", "specs", "[]Spec")
+ addNode("GoStmt", "Stmt", "call", "CallExpr")
+ addNode("IfStmt", "Stmt", "init", "Stmt", "cond", "Expr", "body", "BlockStmt", "els", "Stmt")
+ addNode("ImportSpec", "Spec", "name", "Ident", "path", "BasicLit")
+ addNode("IncDecStmt", "Stmt", "x", "Expr", "tok", "TokenType")
+ addNode("IndexExpr", "Expr", "x", "Expr", "index", "Expr")
+ addNode("InterfaceType", "Expr", "methods", "FieldList")
+ addNode("KeyValueExpr", "Expr", "key", "Expr", "value", "Expr")
+ addNode("LabeledStmt", "Stmt", "label", "Ident", "stmt", "Stmt")
+ addNode("MapType", "Expr", "key", "Expr", "value", "Expr")
+ addNode("ParenExpr", "Expr", "x", "Expr")
+ addNode("RangeStmt", "Stmt", "key", "Expr", "value", "Expr", "define", "bool", "x", "Expr", "body", "BlockStmt")
+ addNode("ReturnStmt", "Stmt", "results", "[]Expr")
+ addNode("SelectStmt", "Stmt", "body", "BlockStmt")
+ addNode("SelectorExpr", "Expr", "x", "Expr", "sel", "Ident")
+ addNode("SendStmt", "Stmt", "chan", "Expr", "value", "Expr")
+ addNode("SliceExpr", "Expr", "x", "Expr", "low", "Expr", "high", "Expr", "max", "Expr", "slice3", "bool")
+ addNode("StarExpr", "Expr", "x", "Expr")
+ addNode("StructType", "Expr", "fields", "FieldList")
+ addNode("SwitchStmt", "Stmt", "init", "Stmt", "tag", "Expr", "body", "BlockStmt")
+ addNode("TypeAssertExpr", "Expr", "x", "Expr", "type", "Expr")
+ addNode("TypeSpec", "Spec", "name", "Ident", "type", "Expr")
+ addNode("TypeSwitchStmt", "Stmt", "init", "Stmt", "assign", "Stmt", "body", "BlockStmt")
+ addNode("UnaryExpr", "Expr", "op", "TokenType", "x", "Expr")
+ addNode("ValueSpec", "Spec", "names", "[]Ident", "type", "Expr", "values", "[]Expr")
+ addParent("Decl", "Node")
+ addParent("Expr", "Node")
+ addParent("Spec", "Node")
+ addParent("Stmt", "Node")
+
+
+class Member(object):
+ def __init__(self, name, typename):
+ self.title = name.title()
+ self.sname = name
+ self.mname = 'm_' + name
+ self.is_list = typename.startswith("[]")
+ self.is_value = isValueType(typename)
+ if self.is_value:
+ self.argtype = typename
+ self.mtype = typename
+ elif self.is_list:
+ self.argtype = 'GoAST' + typename[2:]
+ self.mtype = 'std::vector<std::unique_ptr<%s> >' % self.argtype
+ else:
+ self.argtype = 'GoAST' + typename
+ self.mtype = 'std::unique_ptr<%s>' % self.argtype
+ self.mname = self.mname + '_up'
+
+
+kinds = {}
+parentClasses = StringIO.StringIO()
+childClasses = StringIO.StringIO()
+walker = StringIO.StringIO()
+
+def startClass(name, parent, out):
+ out.write("""
+class GoAST%s : public GoAST%s
+{
+ public:
+""" % (name, parent))
+
+def endClass(name, out):
+ out.write("""
+ %(name)s(const %(name)s &) = delete;
+ const %(name)s &operator=(const %(name)s &) = delete;
+};
+""" % {'name': 'GoAST' + name})
+
+def addNode(name, parent, *children):
+ startClass(name, parent, childClasses)
+ l = kinds.setdefault(parent, [])
+ l.append(name)
+ children = createMembers(name, children)
+ addConstructor(name, parent, children)
+ childClasses.write("""
+ const char *
+ GetKindName() const override
+ {
+ return "%(name)s";
+ }
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() == e%(name)s;
+ }
+ """ % {'name':name})
+ addChildren(name, children)
+ endClass(name, childClasses)
+
+def isValueType(typename):
+ if typename[0].islower():
+ return True
+ if typename[0].isupper():
+ return typename.startswith('Token') or typename == 'ChanDir'
+ return False
+
+
+def createMembers(name, children):
+ l = len(children)
+ if (l % 2) != 0:
+ raise Exception("Invalid children for %s: %s" % (name, children))
+ return [Member(children[i], children[i + 1]) for i in xrange(0, l, 2)]
+
+
+def addConstructor(name, parent, children):
+ for c in children:
+ if c.is_list:
+ children = [x for x in children if x.is_value]
+ break
+ childClasses.write(' ')
+ if len(children) == 1:
+ childClasses.write('explicit ')
+ childClasses.write('GoAST%s(' % name)
+ for i in xrange(len(children)):
+ if i > 0:
+ childClasses.write(', ')
+
+ c = children[i]
+ if c.is_value:
+ childClasses.write(c.argtype)
+ childClasses.write(' ')
+ else:
+ childClasses.write('%s *' % c.argtype)
+ childClasses.write(c.sname)
+ childClasses.write(') : GoAST%s(e%s)' % (parent, name))
+ for c in children:
+ childClasses.write(', ')
+ childClasses.write('%(mname)s(%(sname)s)' % c.__dict__)
+ childClasses.write(""" {}
+ ~GoAST%s() override = default;
+""" % name)
+
+
+def addChildren(name, children):
+ if len(children) == 0:
+ return
+ walker.write("""
+ case e%(n)s:
+ {
+ GoAST%(n)s *n = llvm::cast<GoAST%(n)s>(this);
+ (void)n;""" % {'n':name})
+ for c in children:
+ if c.is_list:
+ childClasses.write("""
+ size_t
+ Num%(title)s() const
+ {
+ return %(mname)s.size();
+ }
+ const %(argtype)s *
+ Get%(title)s(int i) const
+ {
+ return %(mname)s[i].get();
+ }
+ void
+ Add%(title)s(%(argtype)s *%(sname)s)
+ {
+ %(mname)s.push_back(std::unique_ptr<%(argtype)s>(%(sname)s));
+ }
+""" % c.__dict__)
+ walker.write("""
+ for (auto& e : n->%s) { v(e.get()); }""" % c.mname)
+ else:
+ const = ''
+ get = ''
+ set = ''
+ t = c.argtype
+ if isValueType(t):
+ set = '%(mname)s = %(sname)s' % c.__dict__
+ t = t + ' '
+ else:
+ t = t + ' *'
+ const = 'const '
+ get = '.get()'
+ set = '%(mname)s.reset(%(sname)s)' % c.__dict__
+ walker.write("""
+ v(n->%s.get());""" % c.mname)
+ childClasses.write("""
+ %(const)s%(type)s
+ Get%(title)s() const
+ {
+ return %(mname)s%(get)s;
+ }
+ void
+ Set%(title)s(%(type)s%(sname)s)
+ {
+ %(set)s;
+ }
+""" % {'const':const, 'title': c.title, 'sname': c.sname, 'get': get, 'set': set, 'type': t, 'mname': c.mname})
+ childClasses.write('\n private:\n friend class GoASTNode;\n')
+ walker.write("""
+ return;
+ }""")
+ for c in children:
+ childClasses.write(' %s %s;\n' %(c.mtype, c.mname))
+
+
+def addParent(name, parent):
+ startClass(name, parent, parentClasses)
+ l = kinds[name]
+ minName = l[0]
+ maxName = l[-1]
+ parentClasses.write(""" template <typename R, typename V> R Visit(V *v) const;
+
+ static bool
+ classof(const GoASTNode *n)
+ {
+ return n->GetKind() >= e%s && n->GetKind() <= e%s;
+ }
+
+ protected:
+ explicit GoAST%s(NodeKind kind) : GoASTNode(kind) { }
+ private:
+""" % (minName, maxName, name))
+ endClass(name, parentClasses)
+
+addNodes()
+
+print """//===-- GoAST.h -------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// DO NOT EDIT.
+// Generated by gen_go_ast.py
+
+#ifndef liblldb_GoAST_h
+#define liblldb_GoAST_h
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "llvm/Support/Casting.h"
+#include "Plugins/ExpressionParser/Go/GoLexer.h"
+
+namespace lldb_private
+{
+
+class GoASTNode
+{
+ public:
+ typedef GoLexer::TokenType TokenType;
+ typedef GoLexer::Token Token;
+ enum ChanDir
+ {
+ eChanBidir,
+ eChanSend,
+ eChanRecv,
+ };
+ enum NodeKind
+ {"""
+for l in kinds.itervalues():
+ for x in l:
+ print " e%s," % x
+print """ };
+
+ virtual ~GoASTNode() = default;
+
+ NodeKind
+ GetKind() const
+ {
+ return m_kind;
+ }
+
+ virtual const char *GetKindName() const = 0;
+
+ template <typename V> void WalkChildren(V &v);
+
+ protected:
+ explicit GoASTNode(NodeKind kind) : m_kind(kind) { }
+
+ private:
+ const NodeKind m_kind;
+
+ GoASTNode(const GoASTNode &) = delete;
+ const GoASTNode &operator=(const GoASTNode &) = delete;
+};
+"""
+
+
+print parentClasses.getvalue()
+print childClasses.getvalue()
+
+for k, l in kinds.iteritems():
+ if k == 'Node':
+ continue
+ print """
+template <typename R, typename V>
+R GoAST%s::Visit(V* v) const
+{
+ switch(GetKind())
+ {""" % k
+ for subtype in l:
+ print """ case e%(n)s:
+ return v->Visit%(n)s(llvm::cast<const GoAST%(n)s>(this));""" % {'n':subtype}
+
+ print """ default:
+ assert(false && "Invalid kind");
+ }
+}"""
+
+print """
+template <typename V>
+void GoASTNode::WalkChildren(V &v)
+{
+ switch (m_kind)
+ {
+"""
+print walker.getvalue()
+print"""
+ case eEmptyStmt:
+ case eBadDecl:
+ case eBadExpr:
+ case eBadStmt:
+ break;
+ }
+}
+
+} // namespace lldb_private
+
+#endif
+"""
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index 95ae549e0e4b..d646d4d4754a 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -290,9 +290,8 @@ EmulateInstructionARM::GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t re
uint32_t
EmulateInstructionARM::GetFramePointerRegisterNumber () const
{
- if (m_arch.GetTriple().getEnvironment() == llvm::Triple::Android)
+ if (m_arch.GetTriple().isAndroid())
return LLDB_INVALID_REGNUM; // Don't use frame pointer on android
-
bool is_apple = false;
if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
is_apple = true;
@@ -301,6 +300,8 @@ EmulateInstructionARM::GetFramePointerRegisterNumber () const
case llvm::Triple::Darwin:
case llvm::Triple::MacOSX:
case llvm::Triple::IOS:
+ case llvm::Triple::TvOS:
+ case llvm::Triple::WatchOS:
is_apple = true;
break;
default:
@@ -387,9 +388,8 @@ EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding enc
}
#endif
- bool conditional = false;
bool success = false;
- if (ConditionPassed(opcode, &conditional))
+ if (ConditionPassed(opcode))
{
const uint32_t addr_byte_size = GetAddressByteSize();
const addr_t sp = ReadCoreReg (SP_REG, &success);
@@ -442,10 +442,7 @@ EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding enc
uint32_t i;
EmulateInstruction::Context context;
- if (conditional)
- context.type = EmulateInstruction::eContextRegisterStore;
- else
- context.type = EmulateInstruction::eContextPushRegisterOnStack;
+ context.type = EmulateInstruction::eContextPushRegisterOnStack;
RegisterInfo reg_info;
RegisterInfo sp_reg;
GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
@@ -511,8 +508,7 @@ EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding enco
bool success = false;
- bool conditional = false;
- if (ConditionPassed(opcode, &conditional))
+ if (ConditionPassed(opcode))
{
const uint32_t addr_byte_size = GetAddressByteSize();
const addr_t sp = ReadCoreReg (SP_REG, &success);
@@ -574,10 +570,7 @@ EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding enco
uint32_t i, data;
EmulateInstruction::Context context;
- if (conditional)
- context.type = EmulateInstruction::eContextRegisterLoad;
- else
- context.type = EmulateInstruction::eContextPopRegisterOffStack;
+ context.type = EmulateInstruction::eContextPopRegisterOffStack;
RegisterInfo sp_reg;
GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
@@ -586,7 +579,7 @@ EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding enco
{
if (BitIsSet (registers, i))
{
- context.SetRegisterPlusOffset (sp_reg, addr - sp);
+ context.SetAddress(addr);
data = MemARead(context, addr, 4, 0, &success);
if (!success)
return false;
@@ -900,12 +893,12 @@ EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding
break;
case eEncodingA1:
- // d = UInt(Rd); setflags = (S == Ô1Õ); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
+ // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
Rd = Bits32 (opcode, 15, 12);
setflags = BitIsSet (opcode, 20);
imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
- // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
+ // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
if ((Rd == 15) && setflags)
return EmulateSUBSPcLrEtc (opcode, encoding);
@@ -1971,9 +1964,8 @@ EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding
}
#endif
- bool conditional = false;
bool success = false;
- if (ConditionPassed(opcode, &conditional))
+ if (ConditionPassed(opcode))
{
const uint32_t addr_byte_size = GetAddressByteSize();
const addr_t sp = ReadCoreReg (SP_REG, &success);
@@ -2018,10 +2010,7 @@ EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding
addr = sp;
EmulateInstruction::Context context;
- if (conditional)
- context.type = EmulateInstruction::eContextRegisterStore;
- else
- context.type = EmulateInstruction::eContextPushRegisterOnStack;
+ context.type = EmulateInstruction::eContextPushRegisterOnStack;
RegisterInfo sp_reg;
RegisterInfo dwarf_reg;
@@ -2082,8 +2071,7 @@ EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding en
#endif
bool success = false;
- bool conditional = false;
- if (ConditionPassed(opcode, &conditional))
+ if (ConditionPassed(opcode))
{
const uint32_t addr_byte_size = GetAddressByteSize();
const addr_t sp = ReadCoreReg (SP_REG, &success);
@@ -2125,10 +2113,8 @@ EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding en
uint32_t i;
EmulateInstruction::Context context;
- if (conditional)
- context.type = EmulateInstruction::eContextRegisterStore;
- else
- context.type = EmulateInstruction::eContextPushRegisterOnStack;
+ context.type = EmulateInstruction::eContextPushRegisterOnStack;
+
RegisterInfo dwarf_reg;
RegisterInfo sp_reg;
GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
@@ -2178,8 +2164,7 @@ EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding enc
#endif
bool success = false;
- bool conditional = false;
- if (ConditionPassed(opcode, &conditional))
+ if (ConditionPassed(opcode))
{
const uint32_t addr_byte_size = GetAddressByteSize();
const addr_t sp = ReadCoreReg (SP_REG, &success);
@@ -2222,17 +2207,15 @@ EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding enc
uint64_t data; // uint64_t to accommodate 64-bit registers.
EmulateInstruction::Context context;
- if (conditional)
- context.type = EmulateInstruction::eContextRegisterLoad;
- else
- context.type = EmulateInstruction::eContextPopRegisterOffStack;
+ context.type = EmulateInstruction::eContextPopRegisterOffStack;
+
RegisterInfo dwarf_reg;
RegisterInfo sp_reg;
GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
for (i=0; i<regs; ++i)
{
GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
- context.SetRegisterPlusOffset (sp_reg, addr - sp);
+ context.SetAddress(addr);
data = MemARead(context, addr, reg_byte_size, 0, &success);
if (!success)
return false;
@@ -3462,8 +3445,7 @@ EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding enco
#endif
bool success = false;
- bool conditional = false;
- if (ConditionPassed(opcode, &conditional))
+ if (ConditionPassed(opcode))
{
uint32_t n;
uint32_t registers = 0;
@@ -3536,10 +3518,8 @@ EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding enco
context.SetRegisterPlusOffset (dwarf_reg, offset);
if (wback && (n == 13)) // Pop Instruction
{
- if (conditional)
- context.type = EmulateInstruction::eContextRegisterLoad;
- else
- context.type = EmulateInstruction::eContextPopRegisterOffStack;
+ context.type = EmulateInstruction::eContextPopRegisterOffStack;
+ context.SetAddress(base_address + offset);
}
// R[i] = MemA [address, 4]; address = address + 4;
@@ -4459,7 +4439,7 @@ EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding en
break;
case eEncodingA1:
- // if W == '1' && Rn == '1101Õ && BitCount(register_list) >= 2 then SEE PUSH;
+ // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE PUSH;
if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
{
// See Push
@@ -4801,7 +4781,11 @@ EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding
address = base_address;
EmulateInstruction::Context context;
- context.type = eContextRegisterStore;
+ if (n == 13)
+ context.type = eContextPushRegisterOnStack;
+ else
+ context.type = eContextRegisterStore;
+
RegisterInfo base_reg;
GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
@@ -4829,8 +4813,12 @@ EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding
// if wback then R[n] = offset_addr;
if (wback)
{
- context.type = eContextRegisterLoad;
+ if (n == 13)
+ context.type = eContextAdjustStackPointer;
+ else
+ context.type = eContextAdjustBaseRegister;
context.SetAddress (offset_addr);
+
if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
return false;
}
@@ -9579,7 +9567,7 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding
if ConditionPassed() then
EncodingSpecificOperations();
shifted = Shift(R[m], shift_t, shift_n, APSR.C);
- (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
+ (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
if d == 15 then // Can only occur for ARM encoding
ALUWritePC(result); // setflags is always FALSE here
else
@@ -9604,7 +9592,7 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding
switch (encoding)
{
case eEncodingT1:
- // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
+ // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
d = Bits32 (opcode, 11, 8);
m = Bits32 (opcode, 3, 0);
setflags = BitIsSet (opcode, 20);
@@ -9622,12 +9610,12 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding
break;
case eEncodingA1:
- // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ);
+ // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
d = Bits32 (opcode, 15, 12);
m = Bits32 (opcode, 3, 0);
setflags = BitIsSet (opcode, 20);
- // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
+ // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
if (d == 15 && setflags)
EmulateSUBSPcLrEtc (opcode, encoding);
@@ -9648,7 +9636,7 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding
if (!success)
return false;
- // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ);
+ // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
uint32_t sp_val = ReadCoreReg (SP_REG, &success);
if (!success)
return false;
@@ -9679,7 +9667,7 @@ EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncod
EncodingSpecificOperations();
shift_n = UInt(R[s]<7:0>);
shifted = Shift(R[m], shift_t, shift_n, APSR.C);
- (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
+ (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
R[d] = result;
if setflags then
APSR.N = result<31>;
@@ -9708,7 +9696,7 @@ EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncod
m = Bits32 (opcode, 3, 0);
s = Bits32 (opcode, 11, 8);
- // setflags = (S == Ô1Õ); shift_t = DecodeRegShift(type);
+ // setflags = (S == '1'); shift_t = DecodeRegShift(type);
setflags = BitIsSet (opcode, 20);
shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
@@ -9737,7 +9725,7 @@ EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncod
if (!success)
return false;
- // (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ);
+ // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
uint32_t Rn = ReadCoreReg (n, &success);
if (!success)
return false;
@@ -9776,7 +9764,7 @@ EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding e
if ConditionPassed() then
EncodingSpecificOperations();
shifted = Shift(R[m], shift_t, shift_n, APSR.C);
- (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
+ (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
if d == 15 then // Can only occur for ARM encoding
ALUWritePC(result); // setflags is always FALSE here
else
@@ -9839,14 +9827,14 @@ EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding e
break;
case eEncodingA1:
- // if Rn == Ô1101Õ then SEE SUB (SP minus register);
- // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ);
+ // if Rn == '1101' then SEE SUB (SP minus register);
+ // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
d = Bits32 (opcode, 15, 12);
n = Bits32 (opcode, 19, 16);
m = Bits32 (opcode, 3, 0);
setflags = BitIsSet (opcode, 20);
- // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions;
+ // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
if ((d == 15) && setflags)
EmulateSUBSPcLrEtc (opcode, encoding);
@@ -9868,7 +9856,7 @@ EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding e
if (!success)
return false;
- // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ);
+ // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
uint32_t Rn = ReadCoreReg (n, &success);
if (!success)
return false;
@@ -9929,7 +9917,7 @@ EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding en
switch (encoding)
{
case eEncodingT1:
- // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
+ // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
d = Bits32 (opcode, 11, 8);
t = Bits32 (opcode, 15, 12);
n = Bits32 (opcode, 19, 16);
@@ -10037,13 +10025,13 @@ EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncodi
switch (encoding)
{
case eEncodingA1:
- // if P == Ô0Õ && W == Ô1Õ then SEE STRBT;
+ // if P == '0' && W == '1' then SEE STRBT;
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
t = Bits32 (opcode, 15, 12);
n = Bits32 (opcode, 19, 16);
imm32 = Bits32 (opcode, 11, 0);
- // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
index = BitIsSet (opcode, 24);
add = BitIsSet (opcode, 23);
wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
@@ -10135,14 +10123,14 @@ EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncodin
switch (encoding)
{
case eEncodingA1:
- // if P == Ô0Õ && W == Ô1Õ then SEE STRT;
- // if Rn == Ô1101Õ && P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && imm12 == Ô000000000100Õ then SEE PUSH;
+ // if P == '0' && W == '1' then SEE STRT;
+ // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 == '000000000100' then SEE PUSH;
// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
t = Bits32 (opcode, 15, 12);
n = Bits32 (opcode, 19, 16);
imm32 = Bits32 (opcode, 11, 0);
- // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
index = BitIsSet (opcode, 24);
add = BitIsSet (opcode, 23);
wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
@@ -10247,15 +10235,15 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc
switch (encoding)
{
case eEncodingT1:
- //if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
- //if Rn == Ô1111Õ then SEE LDRD (literal);
- //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
+ //if P == '0' && W == '0' then SEE 'Related encodings';
+ //if Rn == '1111' then SEE LDRD (literal);
+ //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
t = Bits32 (opcode, 15, 12);
t2 = Bits32 (opcode, 11, 8);
n = Bits32 (opcode, 19, 16);
imm32 = Bits32 (opcode, 7, 0) << 2;
- //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
+ //index = (P == '1'); add = (U == '1'); wback = (W == '1');
index = BitIsSet (opcode, 24);
add = BitIsSet (opcode, 23);
wback = BitIsSet (opcode, 21);
@@ -10271,8 +10259,8 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc
break;
case eEncodingA1:
- //if Rn == Ô1111Õ then SEE LDRD (literal);
- //if Rt<0> == Ô1Õ then UNPREDICTABLE;
+ //if Rn == '1111' then SEE LDRD (literal);
+ //if Rt<0> == '1' then UNPREDICTABLE;
//t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
t = Bits32 (opcode, 15, 12);
if (BitIsSet (t, 0))
@@ -10281,12 +10269,12 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc
n = Bits32 (opcode, 19, 16);
imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
- //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
+ //index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
index = BitIsSet (opcode, 24);
add = BitIsSet (opcode, 23);
wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
- //if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
+ //if P == '0' && W == '1' then UNPREDICTABLE;
if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
return false;
@@ -10327,8 +10315,11 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc
GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
EmulateInstruction::Context context;
- context.type = eContextRegisterLoad;
- context.SetRegisterPlusOffset (base_reg, address - Rn);
+ if (n == 13)
+ context.type = eContextPopRegisterOffStack;
+ else
+ context.type = eContextRegisterLoad;
+ context.SetAddress(address);
const uint32_t addr_byte_size = GetAddressByteSize();
uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
@@ -10339,8 +10330,7 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc
return false;
//R[t2] = MemA[address+4,4];
-
- context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
+ context.SetAddress(address + 4);
data = MemARead (context, address + 4, addr_byte_size, 0, &success);
if (!success)
return false;
@@ -10392,7 +10382,7 @@ EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEnco
switch (encoding)
{
case eEncodingA1:
- // if Rt<0> == Ô1Õ then UNPREDICTABLE;
+ // if Rt<0> == '1' then UNPREDICTABLE;
// t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
t = Bits32 (opcode, 15, 12);
if (BitIsSet (t, 0))
@@ -10401,12 +10391,12 @@ EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEnco
n = Bits32 (opcode, 19, 16);
m = Bits32 (opcode, 3, 0);
- // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
index = BitIsSet (opcode, 24);
add = BitIsSet (opcode, 23);
wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
- // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
+ // if P == '0' && W == '1' then UNPREDICTABLE;
if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
return false;
@@ -10454,8 +10444,11 @@ EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEnco
address = Rn;
EmulateInstruction::Context context;
- context.type = eContextRegisterLoad;
- context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
+ if (n == 13)
+ context.type = eContextPopRegisterOffStack;
+ else
+ context.type = eContextRegisterLoad;
+ context.SetAddress(address);
// R[t] = MemA[address,4];
const uint32_t addr_byte_size = GetAddressByteSize();
@@ -10519,14 +10512,14 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding
switch (encoding)
{
case eEncodingT1:
- // if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
- // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
+ // if P == '0' && W == '0' then SEE 'Related encodings';
+ // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
t = Bits32 (opcode, 15, 12);
t2 = Bits32 (opcode, 11, 8);
n = Bits32 (opcode, 19, 16);
imm32 = Bits32 (opcode, 7, 0) << 2;
- // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ);
+ // index = (P == '1'); add = (U == '1'); wback = (W == '1');
index = BitIsSet (opcode, 24);
add = BitIsSet (opcode, 23);
wback = BitIsSet (opcode, 21);
@@ -10542,7 +10535,7 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding
break;
case eEncodingA1:
- // if Rt<0> == Ô1Õ then UNPREDICTABLE;
+ // if Rt<0> == '1' then UNPREDICTABLE;
// t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
t = Bits32 (opcode, 15, 12);
if (BitIsSet (t, 0))
@@ -10552,12 +10545,12 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding
n = Bits32 (opcode, 19, 16);
imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
- // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
index = BitIsSet (opcode, 24);
add = BitIsSet (opcode, 23);
wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
- // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
+ // if P == '0' && W == '1' then UNPREDICTABLE;
if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
return false;
@@ -10605,7 +10598,10 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding
return false;
EmulateInstruction::Context context;
- context.type = eContextRegisterStore;
+ if (n == 13)
+ context.type = eContextPushRegisterOnStack;
+ else
+ context.type = eContextRegisterStore;
context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
const uint32_t addr_byte_size = GetAddressByteSize();
@@ -10627,9 +10623,12 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding
//if wback then R[n] = offset_addr;
if (wback)
{
- context.type = eContextAdjustBaseRegister;
+ if (n == 13)
+ context.type = eContextAdjustStackPointer;
+ else
+ context.type = eContextAdjustBaseRegister;
context.SetAddress (offset_addr);
-
+
if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
return false;
}
@@ -10667,7 +10666,7 @@ EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding
switch (encoding)
{
case eEncodingA1:
- // if Rt<0> == Ô1Õ then UNPREDICTABLE;
+ // if Rt<0> == '1' then UNPREDICTABLE;
// t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
t = Bits32 (opcode, 15, 12);
if (BitIsSet (t, 0))
@@ -10677,12 +10676,12 @@ EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding
n = Bits32 (opcode, 19, 16);
m = Bits32 (opcode, 3, 0);
- // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ);
+ // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
index = BitIsSet (opcode, 24);
add = BitIsSet (opcode, 23);
wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
- // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE;
+ // if P == '0' && W == '1' then UNPREDICTABLE;
if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
return false;
@@ -10737,7 +10736,11 @@ EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding
return false;
EmulateInstruction::Context context;
- context.type = eContextRegisterStore;
+ if (t == 13)
+ context.type = eContextPushRegisterOnStack;
+ else
+ context.type = eContextRegisterStore;
+
GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
@@ -10808,25 +10811,25 @@ EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding enc
{
case eEncodingT1:
case eEncodingA1:
- // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
- // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
- // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
- // if P == U && W == Ô1Õ then UNDEFINED;
+ // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
+ // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
+ // if P == '1' && W == '0' then SEE VLDR;
+ // if P == U && W == '1' then UNDEFINED;
if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
return false;
// // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
- // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
+ // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
single_regs = false;
add = BitIsSet (opcode, 23);
wback = BitIsSet (opcode, 21);
- // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
+ // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
n = Bits32 (opcode, 19, 16);
imm32 = Bits32 (opcode, 7, 0) << 2;
- // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFLDMXÓ.
+ // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'.
regs = Bits32 (opcode, 7, 0) / 2;
// if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
@@ -10841,22 +10844,22 @@ EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding enc
case eEncodingT2:
case eEncodingA2:
- // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
- // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP;
- // if P == Ô1Õ && W == Ô0Õ then SEE VLDR;
- // if P == U && W == Ô1Õ then UNDEFINED;
+ // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
+ // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
+ // if P == '1' && W == '0' then SEE VLDR;
+ // if P == U && W == '1' then UNDEFINED;
if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
return false;
// // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
- // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
+ // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d = UInt(Vd:D); n = UInt(Rn);
single_regs = true;
add = BitIsSet (opcode, 23);
wback = BitIsSet (opcode, 21);
d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
n = Bits32 (opcode, 19, 16);
- // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
+ // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
imm32 = Bits32 (opcode, 7, 0) << 2;
regs = Bits32 (opcode, 7, 0);
@@ -11000,25 +11003,25 @@ EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding enc
{
case eEncodingT1:
case eEncodingA1:
- // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
- // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
- // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
- // if P == U && W == Ô1Õ then UNDEFINED;
+ // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
+ // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
+ // if P == '1' && W == '0' then SEE VSTR;
+ // if P == U && W == '1' then UNDEFINED;
if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
return false;
// // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
- // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ);
+ // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
single_regs = false;
add = BitIsSet (opcode, 23);
wback = BitIsSet (opcode, 21);
- // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
+ // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
n = Bits32 (opcode, 19, 16);
imm32 = Bits32 (opcode, 7, 0) << 2;
- // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFSTMXÓ.
+ // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'.
regs = Bits32 (opcode, 7, 0) / 2;
// if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
@@ -11033,22 +11036,22 @@ EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding enc
case eEncodingT2:
case eEncodingA2:
- // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ;
- // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH;
- // if P == Ô1Õ && W == Ô0Õ then SEE VSTR;
- // if P == U && W == Ô1Õ then UNDEFINED;
+ // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
+ // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
+ // if P == '1' && W == '0' then SEE VSTR;
+ // if P == U && W == '1' then UNDEFINED;
if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
return false;
// // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
- // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn);
+ // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d = UInt(Vd:D); n = UInt(Rn);
single_regs = true;
add = BitIsSet (opcode, 23);
wback = BitIsSet (opcode, 21);
d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
n = Bits32 (opcode, 19, 16);
- // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8);
+ // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
imm32 = Bits32 (opcode, 7, 0) << 2;
regs = Bits32 (opcode, 7, 0);
@@ -11193,7 +11196,7 @@ EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
{
case eEncodingT1:
case eEncodingA1:
- // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
+ // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
single_reg = false;
add = BitIsSet (opcode, 23);
imm32 = Bits32 (opcode, 7, 0) << 2;
@@ -11206,7 +11209,7 @@ EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
case eEncodingT2:
case eEncodingA2:
- // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
+ // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
single_reg = true;
add = BitIsSet (opcode, 23);
imm32 = Bits32 (opcode, 7, 0) << 2;
@@ -11322,7 +11325,7 @@ EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
{
case eEncodingT1:
case eEncodingA1:
- // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
+ // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
single_reg = false;
add = BitIsSet (opcode, 23);
imm32 = Bits32 (opcode, 7, 0) << 2;
@@ -11339,7 +11342,7 @@ EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
case eEncodingT2:
case eEncodingA2:
- // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32);
+ // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
single_reg = true;
add = BitIsSet (opcode, 23);
imm32 = Bits32 (opcode, 7, 0) << 2;
@@ -11461,16 +11464,16 @@ EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding e
case eEncodingA1:
{
// case type of
- // when Ô0111Õ
- // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
- // when Ô1010Õ
- // regs = 2; if align == Ô11Õ then UNDEFINED;
- // when Ô0110Õ
- // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
- // when Ô0010Õ
+ // when '0111'
+ // regs = 1; if align<1> == '1' then UNDEFINED;
+ // when '1010'
+ // regs = 2; if align == '11' then UNDEFINED;
+ // when '0110'
+ // regs = 3; if align<1> == '1' then UNDEFINED;
+ // when '0010'
// regs = 4;
// otherwise
- // SEE ÒRelated encodingsÓ;
+ // SEE 'Related encodings';
uint32_t type = Bits32 (opcode, 11, 8);
uint32_t align = Bits32 (opcode, 5, 4);
if (type == 7) // '0111'
@@ -11499,7 +11502,7 @@ EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding e
else
return false;
- // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
+ // alignment = if align == '00' then 1 else 4 << UInt(align);
if (align == 0)
alignment = 1;
else
@@ -11624,13 +11627,13 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi
{
uint32_t size = Bits32 (opcode, 11, 10);
uint32_t index_align = Bits32 (opcode, 7, 4);
- // if size == Ô11Õ then SEE VLD1 (single element to all lanes);
+ // if size == '11' then SEE VLD1 (single element to all lanes);
if (size == 3)
return EmulateVLD1SingleAll (opcode, encoding);
// case size of
if (size == 0) // when '00'
{
- // if index_align<0> != Ô0Õ then UNDEFINED;
+ // if index_align<0> != '0' then UNDEFINED;
if (BitIsClear (index_align, 0))
return false;
@@ -11640,9 +11643,9 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi
index = Bits32 (index_align, 3, 1);
alignment = 1;
}
- else if (size == 1) // when Ô01Õ
+ else if (size == 1) // when '01'
{
- // if index_align<1> != Ô0Õ then UNDEFINED;
+ // if index_align<1> != '0' then UNDEFINED;
if (BitIsClear (index_align, 1))
return false;
@@ -11651,19 +11654,19 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi
esize = 16;
index = Bits32 (index_align, 3, 2);
- // alignment = if index_align<0> == Ô0Õ then 1 else 2;
+ // alignment = if index_align<0> == '0' then 1 else 2;
if (BitIsClear (index_align, 0))
alignment = 1;
else
alignment = 2;
}
- else if (size == 2) // when Ô10Õ
+ else if (size == 2) // when '10'
{
- // if index_align<2> != Ô0Õ then UNDEFINED;
+ // if index_align<2> != '0' then UNDEFINED;
if (BitIsClear (index_align, 2))
return false;
- // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
+ // if index_align<1:0> != '00' && index_align<1:0> != '11' then UNDEFINED;
if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
return false;
@@ -11672,7 +11675,7 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi
esize = 32;
index = Bit32 (index_align, 3);
- // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
+ // alignment = if index_align<1:0> == '00' then 1 else 4;
if (Bits32 (index_align, 1, 0) == 0)
alignment = 1;
else
@@ -11806,35 +11809,35 @@ EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding e
uint32_t align = Bits32 (opcode, 5, 4);
// case type of
- if (type == 7) // when Ô0111Õ
+ if (type == 7) // when '0111'
{
- // regs = 1; if align<1> == Ô1Õ then UNDEFINED;
+ // regs = 1; if align<1> == '1' then UNDEFINED;
regs = 1;
if (BitIsSet (align, 1))
return false;
}
- else if (type == 10) // when Ô1010Õ
+ else if (type == 10) // when '1010'
{
- // regs = 2; if align == Ô11Õ then UNDEFINED;
+ // regs = 2; if align == '11' then UNDEFINED;
regs = 2;
if (align == 3)
return false;
}
- else if (type == 6) // when Ô0110Õ
+ else if (type == 6) // when '0110'
{
- // regs = 3; if align<1> == Ô1Õ then UNDEFINED;
+ // regs = 3; if align<1> == '1' then UNDEFINED;
regs = 3;
if (BitIsSet (align, 1))
return false;
}
- else if (type == 2) // when Ô0010Õ
+ else if (type == 2) // when '0010'
// regs = 4;
regs = 4;
else // otherwise
- // SEE ÒRelated encodingsÓ;
+ // SEE 'Related encodings';
return false;
- // alignment = if align == Ô00Õ then 1 else 4 << UInt(align);
+ // alignment = if align == '00' then 1 else 4 << UInt(align);
if (align == 0)
alignment = 1;
else
@@ -11964,14 +11967,14 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc
uint32_t size = Bits32 (opcode, 11, 10);
uint32_t index_align = Bits32 (opcode, 7, 4);
- // if size == Ô11Õ then UNDEFINED;
+ // if size == '11' then UNDEFINED;
if (size == 3)
return false;
// case size of
- if (size == 0) // when Ô00Õ
+ if (size == 0) // when '00'
{
- // if index_align<0> != Ô0Õ then UNDEFINED;
+ // if index_align<0> != '0' then UNDEFINED;
if (BitIsClear (index_align, 0))
return false;
// ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
@@ -11980,9 +11983,9 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc
index = Bits32 (index_align, 3, 1);
alignment = 1;
}
- else if (size == 1) // when Ô01Õ
+ else if (size == 1) // when '01'
{
- // if index_align<1> != Ô0Õ then UNDEFINED;
+ // if index_align<1> != '0' then UNDEFINED;
if (BitIsClear (index_align, 1))
return false;
@@ -11991,19 +11994,19 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc
esize = 16;
index = Bits32 (index_align, 3, 2);
- // alignment = if index_align<0> == Ô0Õ then 1 else 2;
+ // alignment = if index_align<0> == '0' then 1 else 2;
if (BitIsClear (index_align, 0))
alignment = 1;
else
alignment = 2;
}
- else if (size == 2) // when Ô10Õ
+ else if (size == 2) // when '10'
{
- // if index_align<2> != Ô0Õ then UNDEFINED;
+ // if index_align<2> != '0' then UNDEFINED;
if (BitIsClear (index_align, 2))
return false;
- // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED;
+ // if index_align<1:0> != '00' && index_align<1:0> != '11' then UNDEFINED;
if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
return false;
@@ -12012,7 +12015,7 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc
esize = 32;
index = Bit32 (index_align, 3);
- // alignment = if index_align<1:0> == Ô00Õ then 1 else 4;
+ // alignment = if index_align<1:0> == '00' then 1 else 4;
if (Bits32 (index_align, 1, 0) == 0)
alignment = 1;
else
@@ -12125,12 +12128,12 @@ EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEnc
case eEncodingT1:
case eEncodingA1:
{
- //if size == Ô11Õ || (size == Ô00Õ && a == Ô1Õ) then UNDEFINED;
+ //if size == '11' || (size == '00' && a == '1') then UNDEFINED;
uint32_t size = Bits32 (opcode, 7, 6);
if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4)))
return false;
- //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == Ô0Õ then 1 else 2;
+ //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0' then 1 else 2;
ebytes = 1 << size;
elements = 8 / ebytes;
if (BitIsClear (opcode, 5))
@@ -12138,7 +12141,7 @@ EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEnc
else
regs = 2;
- //alignment = if a == Ô0Õ then 1 else ebytes;
+ //alignment = if a == '0' then 1 else ebytes;
if (BitIsClear (opcode, 4))
alignment = 1;
else
@@ -12235,19 +12238,19 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod
UNPREDICTABLE;
operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
case opcode of
- when Ô0000Õ result = R[n] AND operand2; // AND
- when Ô0001Õ result = R[n] EOR operand2; // EOR
- when Ô0010Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
- when Ô0011Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
- when Ô0100Õ (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
- when Ô0101Õ (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
- when Ô0110Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
- when Ô0111Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
- when Ô1100Õ result = R[n] OR operand2; // ORR
- when Ô1101Õ result = operand2; // MOV
- when Ô1110Õ result = R[n] AND NOT(operand2); // BIC
- when Ô1111Õ result = NOT(operand2); // MVN
- CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
+ when '0000' result = R[n] AND operand2; // AND
+ when '0001' result = R[n] EOR operand2; // EOR
+ when '0010' (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
+ when '0011' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
+ when '0100' (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
+ when '0101' (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
+ when '0110' (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
+ when '0111' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
+ when '1100' result = R[n] OR operand2; // ORR
+ when '1101' result = operand2; // MOV
+ when '1110' result = R[n] AND NOT(operand2); // BIC
+ when '1111' result = NOT(operand2); // MVN
+ CPSRWriteByInstr(SPSR[], '1111', TRUE);
BranchWritePC(result);
#endif
@@ -12267,7 +12270,7 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod
{
case eEncodingT1:
// if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
- // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = Ô0010Õ; // = SUB
+ // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010'; // = SUB
n = 14;
imm32 = Bits32 (opcode, 7, 0);
register_form = false;
@@ -12329,62 +12332,62 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod
// case opcode of
switch (code)
{
- case 0: // when Ô0000Õ
+ case 0: // when '0000'
// result = R[n] AND operand2; // AND
result.result = Rn & operand2;
break;
- case 1: // when Ô0001Õ
+ case 1: // when '0001'
// result = R[n] EOR operand2; // EOR
result.result = Rn ^ operand2;
break;
- case 2: // when Ô0010Õ
- // (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB
+ case 2: // when '0010'
+ // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
result = AddWithCarry (Rn, ~(operand2), 1);
break;
- case 3: // when Ô0011Õ
- // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB
+ case 3: // when '0011'
+ // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
result = AddWithCarry (~(Rn), operand2, 1);
break;
- case 4: // when Ô0100Õ
- // (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD
+ case 4: // when '0100'
+ // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
result = AddWithCarry (Rn, operand2, 0);
break;
- case 5: // when Ô0101Õ
+ case 5: // when '0101'
// (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
result = AddWithCarry (Rn, operand2, APSR_C);
break;
- case 6: // when Ô0110Õ
+ case 6: // when '0110'
// (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
result = AddWithCarry (Rn, ~(operand2), APSR_C);
break;
- case 7: // when Ô0111Õ
+ case 7: // when '0111'
// (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
result = AddWithCarry (~(Rn), operand2, APSR_C);
break;
- case 10: // when Ô1100Õ
+ case 10: // when '1100'
// result = R[n] OR operand2; // ORR
result.result = Rn | operand2;
break;
- case 11: // when Ô1101Õ
+ case 11: // when '1101'
// result = operand2; // MOV
result.result = operand2;
break;
- case 12: // when Ô1110Õ
+ case 12: // when '1110'
// result = R[n] AND NOT(operand2); // BIC
result.result = Rn & ~(operand2);
break;
- case 15: // when Ô1111Õ
+ case 15: // when '1111'
// result = NOT(operand2); // MVN
result.result = ~(operand2);
break;
@@ -12392,7 +12395,7 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod
default:
return false;
}
- // CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE);
+ // CPSRWriteByInstr(SPSR[], '1111', TRUE);
// For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for
// the best.
@@ -13076,7 +13079,7 @@ EmulateInstructionARM::ArchVersion ()
}
bool
-EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditional)
+EmulateInstructionARM::ConditionPassed (const uint32_t opcode)
{
// If we are ignoring conditions, then always return true.
// this allows us to iterate over disassembly code and still
@@ -13084,12 +13087,8 @@ EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditio
// bits set in the CPSR register...
if (m_ignore_conditions)
return true;
-
- if (is_conditional)
- *is_conditional = true;
const uint32_t cond = CurrentCond (opcode);
-
if (cond == UINT32_MAX)
return false;
@@ -13149,8 +13148,6 @@ EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditio
case 7:
// Always execute (cond == 0b1110, or the special 0b1111 which gives
// opcodes different meanings, but always means execution happens.
- if (is_conditional)
- *is_conditional = false;
return true;
}
@@ -13643,6 +13640,13 @@ EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options)
}
bool
+EmulateInstructionARM::IsInstructionConditional()
+{
+ const uint32_t cond = CurrentCond (m_opcode.GetOpcode32());
+ return cond != 0xe && cond != 0xf && cond != UINT32_MAX;
+}
+
+bool
EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)
{
if (!test_data)
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
index d107ca6bc702..893f43f19977 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
@@ -94,20 +94,20 @@ public:
return false;
}
- virtual lldb_private::ConstString
- GetPluginName()
+ lldb_private::ConstString
+ GetPluginName() override
{
return GetPluginNameStatic();
}
- virtual uint32_t
- GetPluginVersion()
+ uint32_t
+ GetPluginVersion() override
{
return 1;
}
bool
- SetTargetTriple (const ArchSpec &arch);
+ SetTargetTriple (const ArchSpec &arch) override;
enum Mode
{
@@ -148,8 +148,8 @@ public:
// {
// }
- virtual bool
- SupportsEmulatingInstructionsOfType (InstructionType inst_type)
+ bool
+ SupportsEmulatingInstructionsOfType (InstructionType inst_type) override
{
return SupportsEmulatingInstructionsOfTypeStatic (inst_type);
}
@@ -157,32 +157,32 @@ public:
virtual bool
SetArchitecture (const ArchSpec &arch);
- virtual bool
- ReadInstruction ();
+ bool
+ ReadInstruction () override;
- virtual bool
- SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target);
+ bool
+ SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target) override;
- virtual bool
- EvaluateInstruction (uint32_t evaluate_options);
-
- virtual bool
- TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data);
+ bool
+ EvaluateInstruction (uint32_t evaluate_options) override;
- virtual bool
- GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterInfo &reg_info);
-
+ bool
+ IsInstructionConditional() override;
- virtual bool
- CreateFunctionEntryUnwind (UnwindPlan &unwind_plan);
+ bool
+ TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) override;
+
+ bool
+ GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterInfo &reg_info) override;
+
+ bool
+ CreateFunctionEntryUnwind (UnwindPlan &unwind_plan) override;
uint32_t
ArchVersion();
bool
- ConditionPassed (const uint32_t opcode,
- bool *is_conditional = NULL); // Filled in with true if the opcode is a conditional opcode
- // Filled in with false if the opcode is always executed
+ ConditionPassed (const uint32_t opcode);
uint32_t
CurrentCond (const uint32_t opcode);
diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
index 992df1fba59e..372ccf9b05f4 100644
--- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
+++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
@@ -231,58 +231,72 @@ EmulateInstructionARM64::GetOpcodeForInstruction (const uint32_t opcode)
//----------------------------------------------------------------------
// push register(s)
- { 0xff000000, 0xd1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUB <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" },
- { 0xff000000, 0xf1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUBS <Xd>, <Xn|SP>, #<imm> {, <shift>}" },
- { 0xff000000, 0x91000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADD <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" },
- { 0xff000000, 0xb1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADDS <Xd>, <Xn|SP>, #<imm> {, <shift>}" },
-
- { 0xff000000, 0x51000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUB <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" },
- { 0xff000000, 0x71000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}" },
- { 0xff000000, 0x11000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADD <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" },
- { 0xff000000, 0x31000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADDS <Wd>, <Wn|WSP>, #<imm> {, <shift>}" },
-
- { 0xffc00000, 0x29000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0xa9000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0x2d000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <St>, <St2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0x6d000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0xad000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" },
-
- { 0xffc00000, 0x29800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0xa9800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0x2d800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0x6d800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0xad800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
-
- { 0xffc00000, 0x28800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0xa8800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0x2c800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0x6c800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0xac800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
-
- { 0xffc00000, 0x29400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0xa9400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0x2d400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP <St>, <St2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0x6d400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" },
- { 0xffc00000, 0xad400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" },
-
- { 0xffc00000, 0x29c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0xa9c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0x2dc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0x6dc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0xadc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
-
- { 0xffc00000, 0x28c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0xa8c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0x2cc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0x6cc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
- { 0xffc00000, 0xacc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
-
- { 0xfc000000, 0x14000000, No_VFP, &EmulateInstructionARM64::EmulateB, "B <label>" },
- { 0xff000010, 0x54000000, No_VFP, &EmulateInstructionARM64::EmulateBcond, "B.<cond> <label>" },
- { 0x7f000000, 0x34000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ, "CBZ <Wt>, <label>" },
- { 0x7f000000, 0x35000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ, "CBNZ <Wt>, <label>" },
- { 0x7f000000, 0x36000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ, "TBZ <R><t>, #<imm>, <label>" },
- { 0x7f000000, 0x37000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ, "TBNZ <R><t>, #<imm>, <label>" },
+ { 0xff000000, 0xd1000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUB <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" },
+ { 0xff000000, 0xf1000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUBS <Xd>, <Xn|SP>, #<imm> {, <shift>}" },
+ { 0xff000000, 0x91000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADD <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" },
+ { 0xff000000, 0xb1000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADDS <Xd>, <Xn|SP>, #<imm> {, <shift>}" },
+
+ { 0xff000000, 0x51000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUB <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" },
+ { 0xff000000, 0x71000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}" },
+ { 0xff000000, 0x11000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADD <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" },
+ { 0xff000000, 0x31000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADDS <Wd>, <Wn|WSP>, #<imm> {, <shift>}" },
+
+ { 0xffc00000, 0x29000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0xa9000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0x2d000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <St>, <St2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0x6d000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0xad000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" },
+
+ { 0xffc00000, 0x29800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xa9800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x2d800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x6d800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xad800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
+
+ { 0xffc00000, 0x28800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xa8800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x2c800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x6c800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xac800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
+
+ { 0xffc00000, 0x29400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0xa9400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0x2d400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <St>, <St2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0x6d400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" },
+ { 0xffc00000, 0xad400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" },
+
+ { 0xffc00000, 0x29c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xa9c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x2dc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x6dc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xadc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
+
+ { 0xffc00000, 0x28c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xa8c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x2cc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0x6cc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" },
+ { 0xffc00000, 0xacc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" },
+
+ { 0xffe00c00, 0xb8000400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "STR <Wt>, [<Xn|SP>], #<simm>" },
+ { 0xffe00c00, 0xf8000400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "STR <Xt>, [<Xn|SP>], #<simm>" },
+ { 0xffe00c00, 0xb8000c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, "STR <Wt>, [<Xn|SP>, #<simm>]!" },
+ { 0xffe00c00, 0xf8000c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, "STR <Xt>, [<Xn|SP>, #<simm>]!" },
+ { 0xffc00000, 0xb9000000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, "STR <Wt>, [<Xn|SP>{, #<pimm>}]" },
+ { 0xffc00000, 0xf9000000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, "STR <Xt>, [<Xn|SP>{, #<pimm>}]" },
+
+ { 0xffe00c00, 0xb8400400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "LDR <Wt>, [<Xn|SP>], #<simm>" },
+ { 0xffe00c00, 0xf8400400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "LDR <Xt>, [<Xn|SP>], #<simm>" },
+ { 0xffe00c00, 0xb8400c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, "LDR <Wt>, [<Xn|SP>, #<simm>]!" },
+ { 0xffe00c00, 0xf8400c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, "LDR <Xt>, [<Xn|SP>, #<simm>]!" },
+ { 0xffc00000, 0xb9400000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, "LDR <Wt>, [<Xn|SP>{, #<pimm>}]" },
+ { 0xffc00000, 0xf9400000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, "LDR <Xt>, [<Xn|SP>{, #<pimm>}]" },
+
+ { 0xfc000000, 0x14000000, No_VFP, &EmulateInstructionARM64::EmulateB, "B <label>" },
+ { 0xff000010, 0x54000000, No_VFP, &EmulateInstructionARM64::EmulateBcond, "B.<cond> <label>" },
+ { 0x7f000000, 0x34000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ, "CBZ <Wt>, <label>" },
+ { 0x7f000000, 0x35000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ, "CBNZ <Wt>, <label>" },
+ { 0x7f000000, 0x36000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ, "TBZ <R><t>, #<imm>, <label>" },
+ { 0x7f000000, 0x37000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ, "TBNZ <R><t>, #<imm>, <label>" },
};
static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_opcodes);
@@ -391,7 +405,7 @@ EmulateInstructionARM64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
uint32_t
EmulateInstructionARM64::GetFramePointerRegisterNumber () const
{
- if (m_arch.GetTriple().getEnvironment() == llvm::Triple::Android)
+ if (m_arch.GetTriple().isAndroid())
return LLDB_INVALID_REGNUM; // Don't use frame pointer on android
return arm64_dwarf::sp;
@@ -462,7 +476,7 @@ EmulateInstructionARM64::BranchTo (const Context &context, uint32_t N, addr_t ta
}
bool
-EmulateInstructionARM64::ConditionHolds (const uint32_t cond, bool *is_conditional)
+EmulateInstructionARM64::ConditionHolds (const uint32_t cond)
{
// If we are ignoring conditions, then always return true.
// this allows us to iterate over disassembly code and still
@@ -470,10 +484,7 @@ EmulateInstructionARM64::ConditionHolds (const uint32_t cond, bool *is_condition
// bits set in the CPSR register...
if (m_ignore_conditions)
return true;
-
- if (is_conditional)
- *is_conditional = true;
-
+
bool result = false;
switch (UnsignedBits(cond, 3, 1))
{
@@ -499,19 +510,18 @@ EmulateInstructionARM64::ConditionHolds (const uint32_t cond, bool *is_condition
result = (m_opcode_pstate.N == m_opcode_pstate.V && m_opcode_pstate.Z == 0);
break;
case 7:
- result = true;
- if (is_conditional)
- *is_conditional = false;
- break;
+ // Always execute (cond == 0b1110, or the special 0b1111 which gives
+ // opcodes different meanings, but always means execution happens.
+ return true;
}
- if (cond & 1 && cond != 15)
+ if (cond & 1)
result = !result;
return result;
}
bool
-EmulateInstructionARM64::Emulate_addsub_imm (const uint32_t opcode)
+EmulateInstructionARM64::EmulateADDSUBImm (const uint32_t opcode)
{
// integer d = UInt(Rd);
// integer n = UInt(Rn);
@@ -628,26 +638,8 @@ EmulateInstructionARM64::Emulate_addsub_imm (const uint32_t opcode)
return false;
}
-bool
-EmulateInstructionARM64::Emulate_ldstpair_off (const uint32_t opcode)
-{
- return Emulate_ldstpair (opcode, AddrMode_OFF);
-}
-
-bool
-EmulateInstructionARM64::Emulate_ldstpair_pre (const uint32_t opcode)
-{
- return Emulate_ldstpair (opcode, AddrMode_PRE);
-}
-
-bool
-EmulateInstructionARM64::Emulate_ldstpair_post (const uint32_t opcode)
-{
- return Emulate_ldstpair (opcode, AddrMode_POST);
-}
-
-bool
-EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mode)
+template <EmulateInstructionARM64::AddrMode a_mode> bool
+EmulateInstructionARM64::EmulateLDPSTP (const uint32_t opcode)
{
uint32_t opc = Bits32(opcode, 31, 30);
uint32_t V = Bit32(opcode, 26);
@@ -776,10 +768,6 @@ EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mod
Context context_t;
Context context_t2;
- context_t.type = eContextRegisterPlusOffset;
- context_t2.type = eContextRegisterPlusOffset;
- context_t.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, 0);
- context_t2.SetRegisterToRegisterPlusOffset (reg_info_Rt2, reg_info_base, size);
uint8_t buffer [RegisterValue::kMaxRegisterByteSize];
Error error;
@@ -792,6 +780,13 @@ EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mod
context_t.type = eContextPushRegisterOnStack;
context_t2.type = eContextPushRegisterOnStack;
}
+ else
+ {
+ context_t.type = eContextRegisterStore;
+ context_t2.type = eContextRegisterStore;
+ }
+ context_t.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, 0);
+ context_t2.SetRegisterToRegisterPlusOffset (reg_info_Rt2, reg_info_base, size);
if (!ReadRegister (&reg_info_Rt, data_Rt))
return false;
@@ -820,6 +815,13 @@ EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mod
context_t.type = eContextPopRegisterOffStack;
context_t2.type = eContextPopRegisterOffStack;
}
+ else
+ {
+ context_t.type = eContextRegisterLoad;
+ context_t2.type = eContextRegisterLoad;
+ }
+ context_t.SetAddress(address);
+ context_t2.SetAddress(address + size);
if (rt_unknown)
memset (buffer, 'U', reg_info_Rt.byte_size);
@@ -874,6 +876,132 @@ EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mod
return true;
}
+template <EmulateInstructionARM64::AddrMode a_mode> bool
+EmulateInstructionARM64::EmulateLDRSTRImm (const uint32_t opcode)
+{
+ uint32_t size = Bits32(opcode, 31, 30);
+ uint32_t opc = Bits32(opcode, 23, 22);
+ uint32_t n = Bits32(opcode, 9, 5);
+ uint32_t t = Bits32(opcode, 4, 0);
+
+ bool wback;
+ bool postindex;
+ uint64_t offset;
+
+ switch (a_mode)
+ {
+ case AddrMode_POST:
+ wback = true;
+ postindex = true;
+ offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12));
+ break;
+ case AddrMode_PRE:
+ wback = true;
+ postindex = false;
+ offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12));
+ break;
+ case AddrMode_OFF:
+ wback = false;
+ postindex = false;
+ offset = LSL(Bits32(opcode, 21, 10), size);
+ break;
+ }
+
+ MemOp memop;
+
+ if (Bit32(opc, 1) == 0)
+ {
+ memop = Bit32(opc, 0) == 1 ? MemOp_LOAD : MemOp_STORE;
+ }
+ else
+ {
+ memop = MemOp_LOAD;
+ if (size == 2 && Bit32(opc, 0) == 1)
+ return false;
+ }
+
+ Error error;
+ bool success = false;
+ uint64_t address;
+ uint8_t buffer[RegisterValue::kMaxRegisterByteSize];
+ RegisterValue data_Rt;
+
+ if (n == 31)
+ address = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::sp, 0, &success);
+ else
+ address = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::x0 + n, 0, &success);
+
+ if (!success)
+ return false;
+
+ if (!postindex)
+ address += offset;
+
+ RegisterInfo reg_info_base;
+ if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + n, reg_info_base))
+ return false;
+
+ RegisterInfo reg_info_Rt;
+ if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + t, reg_info_Rt))
+ return false;
+
+ Context context;
+ switch (memop)
+ {
+ case MemOp_STORE:
+ if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is based off of the sp or fp register
+ context.type = eContextPushRegisterOnStack;
+ else
+ context.type = eContextRegisterStore;
+ context.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, postindex ? 0 : offset);
+
+ if (!ReadRegister (&reg_info_Rt, data_Rt))
+ return false;
+
+ if (data_Rt.GetAsMemoryData(&reg_info_Rt, buffer, reg_info_Rt.byte_size, eByteOrderLittle, error) == 0)
+ return false;
+
+ if (!WriteMemory(context, address, buffer, reg_info_Rt.byte_size))
+ return false;
+ break;
+
+ case MemOp_LOAD:
+ if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is based off of the sp or fp register
+ context.type = eContextPopRegisterOffStack;
+ else
+ context.type = eContextRegisterLoad;
+ context.SetAddress(address);
+
+ if (!ReadMemory (context, address, buffer, reg_info_Rt.byte_size))
+ return false;
+
+ if (data_Rt.SetFromMemoryData(&reg_info_Rt, buffer, reg_info_Rt.byte_size, eByteOrderLittle, error) == 0)
+ return false;
+
+ if (!WriteRegister (context, &reg_info_Rt, data_Rt))
+ return false;
+
+ default:
+ return false;
+ }
+
+ if (wback)
+ {
+ if (postindex)
+ address += offset;
+
+ if (n == 31)
+ context.type = eContextAdjustStackPointer;
+ else
+ context.type = eContextAdjustBaseRegister;
+ context.SetImmediateSigned (offset);
+
+ if (!WriteRegisterUnsigned (context, &reg_info_base, address))
+ return false;
+ }
+ return true;
+}
+
bool
EmulateInstructionARM64::EmulateB (const uint32_t opcode)
{
diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h
index b74eddeaaf63..d9333c2824d2 100644
--- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h
+++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h
@@ -1,4 +1,4 @@
-//===-- EmulateInstructionARM64.h ------------------------------------*- C++ -*-===//
+//===-- EmulateInstructionARM64.h -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,6 +10,10 @@
#ifndef EmulateInstructionARM64_h_
#define EmulateInstructionARM64_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/EmulateInstruction.h"
#include "lldb/Core/Error.h"
#include "lldb/Interpreter/OptionValue.h"
@@ -18,6 +22,14 @@
class EmulateInstructionARM64 : public lldb_private::EmulateInstruction
{
public:
+ EmulateInstructionARM64 (const lldb_private::ArchSpec &arch) :
+ EmulateInstruction (arch),
+ m_opcode_pstate (),
+ m_emulated_pstate (),
+ m_ignore_conditions (false)
+ {
+ }
+
static void
Initialize ();
@@ -50,61 +62,46 @@ public:
return false;
}
- virtual lldb_private::ConstString
- GetPluginName();
-
- virtual lldb_private::ConstString
- GetShortPluginName()
- {
- return GetPluginNameStatic();
- }
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion()
+ uint32_t
+ GetPluginVersion() override
{
return 1;
}
bool
- SetTargetTriple (const lldb_private::ArchSpec &arch);
+ SetTargetTriple(const lldb_private::ArchSpec &arch) override;
- EmulateInstructionARM64 (const lldb_private::ArchSpec &arch) :
- EmulateInstruction (arch),
- m_opcode_pstate (),
- m_emulated_pstate (),
- m_ignore_conditions (false)
- {
- }
-
- virtual bool
- SupportsEmulatingInstructionsOfType (lldb_private::InstructionType inst_type)
+ bool
+ SupportsEmulatingInstructionsOfType(lldb_private::InstructionType inst_type) override
{
return SupportsEmulatingInstructionsOfTypeStatic (inst_type);
}
- virtual bool
- ReadInstruction ();
+ bool
+ ReadInstruction() override;
- virtual bool
- EvaluateInstruction (uint32_t evaluate_options);
+ bool
+ EvaluateInstruction(uint32_t evaluate_options) override;
- virtual bool
- TestEmulation (lldb_private::Stream *out_stream,
- lldb_private::ArchSpec &arch,
- lldb_private::OptionValueDictionary *test_data)
+ bool
+ TestEmulation(lldb_private::Stream *out_stream,
+ lldb_private::ArchSpec &arch,
+ lldb_private::OptionValueDictionary *test_data) override
{
return false;
}
- virtual bool
- GetRegisterInfo (lldb::RegisterKind reg_kind,
- uint32_t reg_num,
- lldb_private::RegisterInfo &reg_info);
+ bool
+ GetRegisterInfo(lldb::RegisterKind reg_kind,
+ uint32_t reg_num,
+ lldb_private::RegisterInfo &reg_info) override;
- virtual bool
- CreateFunctionEntryUnwind (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwind(lldb_private::UnwindPlan &unwind_plan) override;
-
typedef enum
{
AddrMode_OFF,
@@ -141,7 +138,6 @@ public:
BitwiseOp_NOT,
BitwiseOp_RBIT
} BitwiseOp;
-
typedef enum
{
@@ -252,7 +248,6 @@ public:
} ProcState;
protected:
-
typedef struct
{
uint32_t mask;
@@ -272,25 +267,19 @@ protected:
BranchTo (const Context &context, uint32_t N, lldb::addr_t target);
bool
- ConditionHolds (const uint32_t cond, bool *is_conditional = nullptr);
+ ConditionHolds (const uint32_t cond);
bool
UsingAArch32 ();
bool
- Emulate_addsub_imm (const uint32_t opcode);
-
- bool
- Emulate_ldstpair_off (const uint32_t opcode);
+ EmulateADDSUBImm (const uint32_t opcode);
- bool
- Emulate_ldstpair_pre (const uint32_t opcode);
-
- bool
- Emulate_ldstpair_post (const uint32_t opcode);
+ template <AddrMode a_mode> bool
+ EmulateLDPSTP (const uint32_t opcode);
- bool
- Emulate_ldstpair (const uint32_t opcode, AddrMode a_mode);
+ template <AddrMode a_mode> bool
+ EmulateLDRSTRImm (const uint32_t opcode);
bool
EmulateB (const uint32_t opcode);
@@ -309,4 +298,4 @@ protected:
bool m_ignore_conditions;
};
-#endif // EmulateInstructionARM64_h_
+#endif // EmulateInstructionARM64_h_
diff --git a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
index 66866c73a5cb..d6485f686e2c 100644
--- a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
+++ b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
@@ -29,6 +29,7 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Target.h"
#include "llvm/ADT/STLExtras.h"
@@ -132,10 +133,6 @@ EmulateInstructionMIPS::EmulateInstructionMIPS (const lldb_private::ArchSpec &ar
features += "+dsp,";
if (arch_flags & ArchSpec::eMIPSAse_dspr2)
features += "+dspr2,";
- if (arch_flags & ArchSpec::eMIPSAse_mips16)
- features += "+mips16,";
- if (arch_flags & ArchSpec::eMIPSAse_micromips)
- features += "+micromips,";
m_reg_info.reset (target->createMCRegInfo (triple.getTriple()));
assert (m_reg_info.get());
@@ -152,6 +149,21 @@ EmulateInstructionMIPS::EmulateInstructionMIPS (const lldb_private::ArchSpec &ar
m_disasm.reset (target->createMCDisassembler (*m_subtype_info, *m_context));
assert (m_disasm.get());
+
+ /* Create alternate disassembler for microMIPS */
+ if (arch_flags & ArchSpec::eMIPSAse_mips16)
+ features += "+mips16,";
+ else if (arch_flags & ArchSpec::eMIPSAse_micromips)
+ features += "+micromips,";
+
+ m_alt_subtype_info.reset (target->createMCSubtargetInfo (triple.getTriple(), cpu, features));
+ assert (m_alt_subtype_info.get());
+
+ m_alt_disasm.reset (target->createMCDisassembler (*m_alt_subtype_info, *m_context));
+ assert (m_alt_disasm.get());
+
+ m_next_inst_size = 0;
+ m_use_alt_disaasm = false;
}
void
@@ -221,41 +233,76 @@ EmulateInstructionMIPS::GetRegisterName (unsigned reg_num, bool alternate_name)
{
switch (reg_num)
{
- case gcc_dwarf_sp_mips: return "r29";
- case gcc_dwarf_r30_mips: return "r30";
- case gcc_dwarf_ra_mips: return "r31";
- case gcc_dwarf_f0_mips: return "f0";
- case gcc_dwarf_f1_mips: return "f1";
- case gcc_dwarf_f2_mips: return "f2";
- case gcc_dwarf_f3_mips: return "f3";
- case gcc_dwarf_f4_mips: return "f4";
- case gcc_dwarf_f5_mips: return "f5";
- case gcc_dwarf_f6_mips: return "f6";
- case gcc_dwarf_f7_mips: return "f7";
- case gcc_dwarf_f8_mips: return "f8";
- case gcc_dwarf_f9_mips: return "f9";
- case gcc_dwarf_f10_mips: return "f10";
- case gcc_dwarf_f11_mips: return "f11";
- case gcc_dwarf_f12_mips: return "f12";
- case gcc_dwarf_f13_mips: return "f13";
- case gcc_dwarf_f14_mips: return "f14";
- case gcc_dwarf_f15_mips: return "f15";
- case gcc_dwarf_f16_mips: return "f16";
- case gcc_dwarf_f17_mips: return "f17";
- case gcc_dwarf_f18_mips: return "f18";
- case gcc_dwarf_f19_mips: return "f19";
- case gcc_dwarf_f20_mips: return "f20";
- case gcc_dwarf_f21_mips: return "f21";
- case gcc_dwarf_f22_mips: return "f22";
- case gcc_dwarf_f23_mips: return "f23";
- case gcc_dwarf_f24_mips: return "f24";
- case gcc_dwarf_f25_mips: return "f25";
- case gcc_dwarf_f26_mips: return "f26";
- case gcc_dwarf_f27_mips: return "f27";
- case gcc_dwarf_f28_mips: return "f28";
- case gcc_dwarf_f29_mips: return "f29";
- case gcc_dwarf_f30_mips: return "f30";
- case gcc_dwarf_f31_mips: return "f31";
+ case dwarf_sp_mips: return "r29";
+ case dwarf_r30_mips: return "r30";
+ case dwarf_ra_mips: return "r31";
+ case dwarf_f0_mips: return "f0";
+ case dwarf_f1_mips: return "f1";
+ case dwarf_f2_mips: return "f2";
+ case dwarf_f3_mips: return "f3";
+ case dwarf_f4_mips: return "f4";
+ case dwarf_f5_mips: return "f5";
+ case dwarf_f6_mips: return "f6";
+ case dwarf_f7_mips: return "f7";
+ case dwarf_f8_mips: return "f8";
+ case dwarf_f9_mips: return "f9";
+ case dwarf_f10_mips: return "f10";
+ case dwarf_f11_mips: return "f11";
+ case dwarf_f12_mips: return "f12";
+ case dwarf_f13_mips: return "f13";
+ case dwarf_f14_mips: return "f14";
+ case dwarf_f15_mips: return "f15";
+ case dwarf_f16_mips: return "f16";
+ case dwarf_f17_mips: return "f17";
+ case dwarf_f18_mips: return "f18";
+ case dwarf_f19_mips: return "f19";
+ case dwarf_f20_mips: return "f20";
+ case dwarf_f21_mips: return "f21";
+ case dwarf_f22_mips: return "f22";
+ case dwarf_f23_mips: return "f23";
+ case dwarf_f24_mips: return "f24";
+ case dwarf_f25_mips: return "f25";
+ case dwarf_f26_mips: return "f26";
+ case dwarf_f27_mips: return "f27";
+ case dwarf_f28_mips: return "f28";
+ case dwarf_f29_mips: return "f29";
+ case dwarf_f30_mips: return "f30";
+ case dwarf_f31_mips: return "f31";
+ case dwarf_w0_mips: return "w0";
+ case dwarf_w1_mips: return "w1";
+ case dwarf_w2_mips: return "w2";
+ case dwarf_w3_mips: return "w3";
+ case dwarf_w4_mips: return "w4";
+ case dwarf_w5_mips: return "w5";
+ case dwarf_w6_mips: return "w6";
+ case dwarf_w7_mips: return "w7";
+ case dwarf_w8_mips: return "w8";
+ case dwarf_w9_mips: return "w9";
+ case dwarf_w10_mips: return "w10";
+ case dwarf_w11_mips: return "w11";
+ case dwarf_w12_mips: return "w12";
+ case dwarf_w13_mips: return "w13";
+ case dwarf_w14_mips: return "w14";
+ case dwarf_w15_mips: return "w15";
+ case dwarf_w16_mips: return "w16";
+ case dwarf_w17_mips: return "w17";
+ case dwarf_w18_mips: return "w18";
+ case dwarf_w19_mips: return "w19";
+ case dwarf_w20_mips: return "w20";
+ case dwarf_w21_mips: return "w21";
+ case dwarf_w22_mips: return "w22";
+ case dwarf_w23_mips: return "w23";
+ case dwarf_w24_mips: return "w24";
+ case dwarf_w25_mips: return "w25";
+ case dwarf_w26_mips: return "w26";
+ case dwarf_w27_mips: return "w27";
+ case dwarf_w28_mips: return "w28";
+ case dwarf_w29_mips: return "w29";
+ case dwarf_w30_mips: return "w30";
+ case dwarf_w31_mips: return "w31";
+ case dwarf_mir_mips: return "mir";
+ case dwarf_mcsr_mips: return "mcsr";
+ case dwarf_config5_mips: return "config5";
default:
break;
}
@@ -264,78 +311,113 @@ EmulateInstructionMIPS::GetRegisterName (unsigned reg_num, bool alternate_name)
switch (reg_num)
{
- case gcc_dwarf_zero_mips: return "r0";
- case gcc_dwarf_r1_mips: return "r1";
- case gcc_dwarf_r2_mips: return "r2";
- case gcc_dwarf_r3_mips: return "r3";
- case gcc_dwarf_r4_mips: return "r4";
- case gcc_dwarf_r5_mips: return "r5";
- case gcc_dwarf_r6_mips: return "r6";
- case gcc_dwarf_r7_mips: return "r7";
- case gcc_dwarf_r8_mips: return "r8";
- case gcc_dwarf_r9_mips: return "r9";
- case gcc_dwarf_r10_mips: return "r10";
- case gcc_dwarf_r11_mips: return "r11";
- case gcc_dwarf_r12_mips: return "r12";
- case gcc_dwarf_r13_mips: return "r13";
- case gcc_dwarf_r14_mips: return "r14";
- case gcc_dwarf_r15_mips: return "r15";
- case gcc_dwarf_r16_mips: return "r16";
- case gcc_dwarf_r17_mips: return "r17";
- case gcc_dwarf_r18_mips: return "r18";
- case gcc_dwarf_r19_mips: return "r19";
- case gcc_dwarf_r20_mips: return "r20";
- case gcc_dwarf_r21_mips: return "r21";
- case gcc_dwarf_r22_mips: return "r22";
- case gcc_dwarf_r23_mips: return "r23";
- case gcc_dwarf_r24_mips: return "r24";
- case gcc_dwarf_r25_mips: return "r25";
- case gcc_dwarf_r26_mips: return "r26";
- case gcc_dwarf_r27_mips: return "r27";
- case gcc_dwarf_gp_mips: return "gp";
- case gcc_dwarf_sp_mips: return "sp";
- case gcc_dwarf_r30_mips: return "fp";
- case gcc_dwarf_ra_mips: return "ra";
- case gcc_dwarf_sr_mips: return "sr";
- case gcc_dwarf_lo_mips: return "lo";
- case gcc_dwarf_hi_mips: return "hi";
- case gcc_dwarf_bad_mips: return "bad";
- case gcc_dwarf_cause_mips: return "cause";
- case gcc_dwarf_pc_mips: return "pc";
- case gcc_dwarf_f0_mips: return "f0";
- case gcc_dwarf_f1_mips: return "f1";
- case gcc_dwarf_f2_mips: return "f2";
- case gcc_dwarf_f3_mips: return "f3";
- case gcc_dwarf_f4_mips: return "f4";
- case gcc_dwarf_f5_mips: return "f5";
- case gcc_dwarf_f6_mips: return "f6";
- case gcc_dwarf_f7_mips: return "f7";
- case gcc_dwarf_f8_mips: return "f8";
- case gcc_dwarf_f9_mips: return "f9";
- case gcc_dwarf_f10_mips: return "f10";
- case gcc_dwarf_f11_mips: return "f11";
- case gcc_dwarf_f12_mips: return "f12";
- case gcc_dwarf_f13_mips: return "f13";
- case gcc_dwarf_f14_mips: return "f14";
- case gcc_dwarf_f15_mips: return "f15";
- case gcc_dwarf_f16_mips: return "f16";
- case gcc_dwarf_f17_mips: return "f17";
- case gcc_dwarf_f18_mips: return "f18";
- case gcc_dwarf_f19_mips: return "f19";
- case gcc_dwarf_f20_mips: return "f20";
- case gcc_dwarf_f21_mips: return "f21";
- case gcc_dwarf_f22_mips: return "f22";
- case gcc_dwarf_f23_mips: return "f23";
- case gcc_dwarf_f24_mips: return "f24";
- case gcc_dwarf_f25_mips: return "f25";
- case gcc_dwarf_f26_mips: return "f26";
- case gcc_dwarf_f27_mips: return "f27";
- case gcc_dwarf_f28_mips: return "f28";
- case gcc_dwarf_f29_mips: return "f29";
- case gcc_dwarf_f30_mips: return "f30";
- case gcc_dwarf_f31_mips: return "f31";
- case gcc_dwarf_fcsr_mips: return "fcsr";
- case gcc_dwarf_fir_mips: return "fir";
+ case dwarf_zero_mips: return "r0";
+ case dwarf_r1_mips: return "r1";
+ case dwarf_r2_mips: return "r2";
+ case dwarf_r3_mips: return "r3";
+ case dwarf_r4_mips: return "r4";
+ case dwarf_r5_mips: return "r5";
+ case dwarf_r6_mips: return "r6";
+ case dwarf_r7_mips: return "r7";
+ case dwarf_r8_mips: return "r8";
+ case dwarf_r9_mips: return "r9";
+ case dwarf_r10_mips: return "r10";
+ case dwarf_r11_mips: return "r11";
+ case dwarf_r12_mips: return "r12";
+ case dwarf_r13_mips: return "r13";
+ case dwarf_r14_mips: return "r14";
+ case dwarf_r15_mips: return "r15";
+ case dwarf_r16_mips: return "r16";
+ case dwarf_r17_mips: return "r17";
+ case dwarf_r18_mips: return "r18";
+ case dwarf_r19_mips: return "r19";
+ case dwarf_r20_mips: return "r20";
+ case dwarf_r21_mips: return "r21";
+ case dwarf_r22_mips: return "r22";
+ case dwarf_r23_mips: return "r23";
+ case dwarf_r24_mips: return "r24";
+ case dwarf_r25_mips: return "r25";
+ case dwarf_r26_mips: return "r26";
+ case dwarf_r27_mips: return "r27";
+ case dwarf_gp_mips: return "gp";
+ case dwarf_sp_mips: return "sp";
+ case dwarf_r30_mips: return "fp";
+ case dwarf_ra_mips: return "ra";
+ case dwarf_sr_mips: return "sr";
+ case dwarf_lo_mips: return "lo";
+ case dwarf_hi_mips: return "hi";
+ case dwarf_bad_mips: return "bad";
+ case dwarf_cause_mips: return "cause";
+ case dwarf_pc_mips: return "pc";
+ case dwarf_f0_mips: return "f0";
+ case dwarf_f1_mips: return "f1";
+ case dwarf_f2_mips: return "f2";
+ case dwarf_f3_mips: return "f3";
+ case dwarf_f4_mips: return "f4";
+ case dwarf_f5_mips: return "f5";
+ case dwarf_f6_mips: return "f6";
+ case dwarf_f7_mips: return "f7";
+ case dwarf_f8_mips: return "f8";
+ case dwarf_f9_mips: return "f9";
+ case dwarf_f10_mips: return "f10";
+ case dwarf_f11_mips: return "f11";
+ case dwarf_f12_mips: return "f12";
+ case dwarf_f13_mips: return "f13";
+ case dwarf_f14_mips: return "f14";
+ case dwarf_f15_mips: return "f15";
+ case dwarf_f16_mips: return "f16";
+ case dwarf_f17_mips: return "f17";
+ case dwarf_f18_mips: return "f18";
+ case dwarf_f19_mips: return "f19";
+ case dwarf_f20_mips: return "f20";
+ case dwarf_f21_mips: return "f21";
+ case dwarf_f22_mips: return "f22";
+ case dwarf_f23_mips: return "f23";
+ case dwarf_f24_mips: return "f24";
+ case dwarf_f25_mips: return "f25";
+ case dwarf_f26_mips: return "f26";
+ case dwarf_f27_mips: return "f27";
+ case dwarf_f28_mips: return "f28";
+ case dwarf_f29_mips: return "f29";
+ case dwarf_f30_mips: return "f30";
+ case dwarf_f31_mips: return "f31";
+ case dwarf_fcsr_mips: return "fcsr";
+ case dwarf_fir_mips: return "fir";
+ case dwarf_w0_mips: return "w0";
+ case dwarf_w1_mips: return "w1";
+ case dwarf_w2_mips: return "w2";
+ case dwarf_w3_mips: return "w3";
+ case dwarf_w4_mips: return "w4";
+ case dwarf_w5_mips: return "w5";
+ case dwarf_w6_mips: return "w6";
+ case dwarf_w7_mips: return "w7";
+ case dwarf_w8_mips: return "w8";
+ case dwarf_w9_mips: return "w9";
+ case dwarf_w10_mips: return "w10";
+ case dwarf_w11_mips: return "w11";
+ case dwarf_w12_mips: return "w12";
+ case dwarf_w13_mips: return "w13";
+ case dwarf_w14_mips: return "w14";
+ case dwarf_w15_mips: return "w15";
+ case dwarf_w16_mips: return "w16";
+ case dwarf_w17_mips: return "w17";
+ case dwarf_w18_mips: return "w18";
+ case dwarf_w19_mips: return "w19";
+ case dwarf_w20_mips: return "w20";
+ case dwarf_w21_mips: return "w21";
+ case dwarf_w22_mips: return "w22";
+ case dwarf_w23_mips: return "w23";
+ case dwarf_w24_mips: return "w24";
+ case dwarf_w25_mips: return "w25";
+ case dwarf_w26_mips: return "w26";
+ case dwarf_w27_mips: return "w27";
+ case dwarf_w28_mips: return "w28";
+ case dwarf_w29_mips: return "w29";
+ case dwarf_w30_mips: return "w30";
+ case dwarf_w31_mips: return "w31";
+ case dwarf_mcsr_mips: return "mcsr";
+ case dwarf_mir_mips: return "mir";
+ case dwarf_config5_mips: return "config5";
}
return nullptr;
}
@@ -347,11 +429,11 @@ EmulateInstructionMIPS::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num
{
switch (reg_num)
{
- case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_pc_mips; break;
- case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sp_mips; break;
- case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_r30_mips; break;
- case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_ra_mips; break;
- case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sr_mips; break;
+ case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = dwarf_pc_mips; break;
+ case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sp_mips; break;
+ case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_r30_mips; break;
+ case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = dwarf_ra_mips; break;
+ case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sr_mips; break;
default:
return false;
}
@@ -362,18 +444,24 @@ EmulateInstructionMIPS::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num
::memset (&reg_info, 0, sizeof(RegisterInfo));
::memset (reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
- if (reg_num == gcc_dwarf_sr_mips || reg_num == gcc_dwarf_fcsr_mips || reg_num == gcc_dwarf_fir_mips)
+ if (reg_num == dwarf_sr_mips || reg_num == dwarf_fcsr_mips || reg_num == dwarf_fir_mips || reg_num == dwarf_mcsr_mips || reg_num == dwarf_mir_mips || reg_num == dwarf_config5_mips)
{
reg_info.byte_size = 4;
reg_info.format = eFormatHex;
reg_info.encoding = eEncodingUint;
}
- else if ((int)reg_num >= gcc_dwarf_zero_mips && (int)reg_num <= gcc_dwarf_f31_mips)
+ else if ((int)reg_num >= dwarf_zero_mips && (int)reg_num <= dwarf_f31_mips)
{
reg_info.byte_size = 4;
reg_info.format = eFormatHex;
reg_info.encoding = eEncodingUint;
}
+ else if ((int)reg_num >= dwarf_w0_mips && (int)reg_num <= dwarf_w31_mips)
+ {
+ reg_info.byte_size = 16;
+ reg_info.format = eFormatVectorOfUInt8;
+ reg_info.encoding = eEncodingVector;
+ }
else
{
return false;
@@ -385,11 +473,11 @@ EmulateInstructionMIPS::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num
switch (reg_num)
{
- case gcc_dwarf_r30_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break;
- case gcc_dwarf_ra_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break;
- case gcc_dwarf_sp_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break;
- case gcc_dwarf_pc_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break;
- case gcc_dwarf_sr_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break;
+ case dwarf_r30_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break;
+ case dwarf_ra_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break;
+ case dwarf_sp_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break;
+ case dwarf_pc_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break;
+ case dwarf_sr_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break;
default: break;
}
return true;
@@ -409,6 +497,96 @@ EmulateInstructionMIPS::GetOpcodeForInstruction (const char *op_name)
{ "ADDiu", &EmulateInstructionMIPS::Emulate_ADDiu, "ADDIU rt,rs,immediate" },
{ "SW", &EmulateInstructionMIPS::Emulate_SW, "SW rt,offset(rs)" },
{ "LW", &EmulateInstructionMIPS::Emulate_LW, "LW rt,offset(base)" },
+ //----------------------------------------------------------------------
+ // MicroMIPS Prologue/Epilogue instructions
+ //----------------------------------------------------------------------
+ { "ADDIUSP_MM", &EmulateInstructionMIPS::Emulate_ADDIUSP, "ADDIU immediate" },
+ { "ADDIUS5_MM", &EmulateInstructionMIPS::Emulate_ADDIUS5, "ADDIUS5 rd,immediate" },
+ { "SWSP_MM", &EmulateInstructionMIPS::Emulate_SWSP, "SWSP rt,offset(sp)" },
+ { "SWM16_MM", &EmulateInstructionMIPS::Emulate_SWM16_32, "SWM16 reglist,offset(sp)" },
+ { "SWM32_MM", &EmulateInstructionMIPS::Emulate_SWM16_32, "SWM32 reglist,offset(base)" },
+ { "SWP_MM", &EmulateInstructionMIPS::Emulate_SWM16_32, "SWP rs1,offset(base)" },
+ { "LWSP_MM", &EmulateInstructionMIPS::Emulate_LWSP, "LWSP rt,offset(sp)" },
+ { "LWM16_MM", &EmulateInstructionMIPS::Emulate_LWM16_32, "LWM16 reglist,offset(sp)" },
+ { "LWM32_MM", &EmulateInstructionMIPS::Emulate_LWM16_32, "LWM32 reglist,offset(base)" },
+ { "LWP_MM", &EmulateInstructionMIPS::Emulate_LWM16_32, "LWP rd,offset(base)" },
+ { "JRADDIUSP", &EmulateInstructionMIPS::Emulate_JRADDIUSP, "JRADDIUSP immediate" },
+ //----------------------------------------------------------------------
+
+ // Load/Store instructions
+ //----------------------------------------------------------------------
+ /* Following list of emulated instructions are required by implementation of hardware watchpoint
+ for MIPS in lldb. As we just need the address accessed by instructions, we have generalised
+ all these instructions in 2 functions depending on their addressing modes */
+
+ { "LB", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LB rt, offset(base)" },
+ { "LBE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LBE rt, offset(base)" },
+ { "LBU", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LBU rt, offset(base)" },
+ { "LBUE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LBUE rt, offset(base)" },
+ { "LDC1", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LDC1 ft, offset(base)" },
+ { "LD", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LD rt, offset(base)" },
+ { "LDL", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LDL rt, offset(base)" },
+ { "LDR", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LDR rt, offset(base)" },
+ { "LLD", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LLD rt, offset(base)" },
+ { "LDC2", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LDC2 rt, offset(base)" },
+ { "LDXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, "LDXC1 fd, index (base)" },
+ { "LH", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LH rt, offset(base)" },
+ { "LHE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LHE rt, offset(base)" },
+ { "LHU", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LHU rt, offset(base)" },
+ { "LHUE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LHUE rt, offset(base)" },
+ { "LL", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LL rt, offset(base)" },
+ { "LLE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LLE rt, offset(base)" },
+ { "LUXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, "LUXC1 fd, index (base)" },
+ { "LW", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LW rt, offset(base)" },
+ { "LWC1", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWC1 ft, offset(base)" },
+ { "LWC2", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWC2 rt, offset(base)" },
+ { "LWE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWE rt, offset(base)" },
+ { "LWL", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWL rt, offset(base)" },
+ { "LWLE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWLE rt, offset(base)" },
+ { "LWR", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWR rt, offset(base)" },
+ { "LWRE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWRE rt, offset(base)" },
+ { "LWXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, "LWXC1 fd, index (base)" },
+ { "LLX", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LLX rt, offset(base)" },
+ { "LLXE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LLXE rt, offset(base)" },
+ { "LLDX", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LLDX rt, offset(base)" },
+
+ { "SB", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SB rt, offset(base)" },
+ { "SBE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SBE rt, offset(base)" },
+ { "SC", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SC rt, offset(base)" },
+ { "SCE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SCE rt, offset(base)" },
+ { "SCD", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SCD rt, offset(base)" },
+ { "SD", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SD rt, offset(base)" },
+ { "SDL", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SDL rt, offset(base)" },
+ { "SDR", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SDR rt, offset(base)" },
+ { "SDC1", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SDC1 ft, offset(base)" },
+ { "SDC2", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SDC2 rt, offset(base)" },
+ { "SDXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, "SDXC1 fs, index(base)" },
+ { "SH", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SH rt, offset(base)" },
+ { "SHE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SHE rt, offset(base)" },
+ { "SUXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, "SUXC1 fs, index (base)" },
+ { "SWC1", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWC1 ft, offset(base)" },
+ { "SWC2", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWC2 rt, offset(base)" },
+ { "SWE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWE rt, offset(base)" },
+ { "SWL", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWL rt, offset(base)" },
+ { "SWLE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWLE rt, offset(base)" },
+ { "SWR", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWR rt, offset(base)" },
+ { "SWRE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWRE rt, offset(base)" },
+ { "SWXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, "SWXC1 fs, index (base)" },
+ { "SCX", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SCX rt, offset(base)" },
+ { "SCXE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SCXE rt, offset(base)" },
+ { "SCDX", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SCDX rt, offset(base)" },
+
+ //----------------------------------------------------------------------
+ // MicroMIPS Load/Store instructions
+ //----------------------------------------------------------------------
+ { "LBU16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LBU16 rt, decoded_offset(base)" },
+ { "LHU16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LHU16 rt, left_shifted_offset(base)" },
+ { "LW16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LW16 rt, left_shifted_offset(base)" },
+ { "LWGP_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWGP rt, left_shifted_offset(gp)" },
+ { "SH16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SH16 rt, left_shifted_offset(base)" },
+ { "SW16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SW16 rt, left_shifted_offset(base)" },
+ { "SW_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWSP rt, left_shifted_offset(base)" },
+ { "SB16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SB16 rt, offset(base)" },
//----------------------------------------------------------------------
// Branch instructions
@@ -471,6 +649,34 @@ EmulateInstructionMIPS::GetOpcodeForInstruction (const char *op_name)
{ "BC1ANY2T", &EmulateInstructionMIPS::Emulate_BC1ANY2T, "BC1ANY2T cc, offset" },
{ "BC1ANY4F", &EmulateInstructionMIPS::Emulate_BC1ANY4F, "BC1ANY4F cc, offset" },
{ "BC1ANY4T", &EmulateInstructionMIPS::Emulate_BC1ANY4T, "BC1ANY4T cc, offset" },
+ { "BNZ_B", &EmulateInstructionMIPS::Emulate_BNZB, "BNZ.b wt,s16" },
+ { "BNZ_H", &EmulateInstructionMIPS::Emulate_BNZH, "BNZ.h wt,s16" },
+ { "BNZ_W", &EmulateInstructionMIPS::Emulate_BNZW, "BNZ.w wt,s16" },
+ { "BNZ_D", &EmulateInstructionMIPS::Emulate_BNZD, "BNZ.d wt,s16" },
+ { "BZ_B", &EmulateInstructionMIPS::Emulate_BZB, "BZ.b wt,s16" },
+ { "BZ_H", &EmulateInstructionMIPS::Emulate_BZH, "BZ.h wt,s16" },
+ { "BZ_W", &EmulateInstructionMIPS::Emulate_BZW, "BZ.w wt,s16" },
+ { "BZ_D", &EmulateInstructionMIPS::Emulate_BZD, "BZ.d wt,s16" },
+ { "BNZ_V", &EmulateInstructionMIPS::Emulate_BNZV, "BNZ.V wt,s16" },
+ { "BZ_V", &EmulateInstructionMIPS::Emulate_BZV, "BZ.V wt,s16" },
+
+ //----------------------------------------------------------------------
+ // MicroMIPS Branch instructions
+ //----------------------------------------------------------------------
+ { "B16_MM", &EmulateInstructionMIPS::Emulate_B16_MM, "B16 offset" },
+ { "BEQZ16_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, "BEQZ16 rs, offset" },
+ { "BNEZ16_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, "BNEZ16 rs, offset" },
+ { "BEQZC_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, "BEQZC rs, offset" },
+ { "BNEZC_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, "BNEZC rs, offset" },
+ { "BGEZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, "BGEZALS rs, offset" },
+ { "BLTZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, "BLTZALS rs, offset" },
+ { "JALR16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALR16 rs" },
+ { "JALRS16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALRS16 rs" },
+ { "JR16_MM", &EmulateInstructionMIPS::Emulate_JR, "JR16 rs rs" },
+ { "JRC16_MM", &EmulateInstructionMIPS::Emulate_JR, "JRC16 rs rs" },
+ { "JALS_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALS target" },
+ { "JALX_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALX target" },
+ { "JALRS_MM", &EmulateInstructionMIPS::Emulate_JALRS, "JALRS rt, rs" },
};
static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes);
@@ -484,6 +690,76 @@ EmulateInstructionMIPS::GetOpcodeForInstruction (const char *op_name)
return NULL;
}
+uint32_t
+EmulateInstructionMIPS::GetSizeOfInstruction (lldb_private::DataExtractor& data, uint64_t inst_addr)
+{
+ uint64_t next_inst_size = 0;
+ llvm::MCInst mc_insn;
+ 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, next_inst_size, raw_insn, inst_addr, llvm::nulls(), llvm::nulls());
+ else
+ decode_status = m_disasm->getInstruction (mc_insn, next_inst_size, raw_insn, inst_addr, llvm::nulls(), llvm::nulls());
+
+ if (decode_status != llvm::MCDisassembler::Success)
+ return false;
+
+ return m_insn_info->get(mc_insn.getOpcode()).getSize();
+}
+
+bool
+EmulateInstructionMIPS::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target)
+{
+ m_use_alt_disaasm = false;
+
+ if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target))
+ {
+ if (inst_addr.GetAddressClass() == eAddressClassCodeAlternateISA)
+ {
+ Error error;
+ lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
+
+ /*
+ * The address belongs to microMIPS function. To find the size of
+ * next instruction use microMIPS disassembler.
+ */
+ m_use_alt_disaasm = true;
+
+ uint32_t current_inst_size = insn_opcode.GetByteSize();
+ uint8_t buf[sizeof(uint32_t)];
+ uint64_t next_inst_addr = (m_addr & (~1ull)) + current_inst_size;
+ Address next_addr (next_inst_addr);
+
+ const size_t bytes_read = target->ReadMemory (next_addr, /* Address of next instruction */
+ true, /* prefer_file_cache */
+ buf,
+ sizeof(uint32_t),
+ error,
+ &load_addr);
+
+ if (bytes_read == 0)
+ return true;
+
+ DataExtractor data (buf, sizeof(uint32_t), GetByteOrder(), GetAddressByteSize());
+ m_next_inst_size = GetSizeOfInstruction (data, next_inst_addr);
+ return true;
+ }
+ else
+ {
+ /*
+ * If the address class is not eAddressClassCodeAlternateISA then
+ * the function is not microMIPS. In this case instruction size is
+ * always 4 bytes.
+ */
+ m_next_inst_size = 4;
+ return true;
+ }
+ }
+ return false;
+}
+
bool
EmulateInstructionMIPS::ReadInstruction ()
{
@@ -514,7 +790,11 @@ EmulateInstructionMIPS::EvaluateInstruction (uint32_t evaluate_options)
{
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());
+ if (m_use_alt_disaasm)
+ decode_status = m_alt_disasm->getInstruction (mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls());
+ else
+ decode_status = m_disasm->getInstruction (mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls());
+
if (decode_status != llvm::MCDisassembler::Success)
return false;
}
@@ -542,7 +822,7 @@ EmulateInstructionMIPS::EvaluateInstruction (uint32_t evaluate_options)
if (auto_advance_pc)
{
- old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
}
@@ -554,7 +834,7 @@ EmulateInstructionMIPS::EvaluateInstruction (uint32_t evaluate_options)
if (auto_advance_pc)
{
- new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
@@ -563,7 +843,7 @@ EmulateInstructionMIPS::EvaluateInstruction (uint32_t evaluate_options)
{
new_pc += 4;
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, new_pc))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, new_pc))
return false;
}
}
@@ -581,10 +861,10 @@ EmulateInstructionMIPS::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
const bool can_replace = false;
// Our previous Call Frame Address is the stack pointer
- row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_sp_mips, 0);
+ row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips, 0);
// Our previous PC is in the RA
- row->SetRegisterLocationToRegister(gcc_dwarf_pc_mips, gcc_dwarf_ra_mips, can_replace);
+ row->SetRegisterLocationToRegister(dwarf_pc_mips, dwarf_ra_mips, can_replace);
unwind_plan.AppendRow (row);
@@ -592,6 +872,7 @@ EmulateInstructionMIPS::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
unwind_plan.SetSourceName ("EmulateInstructionMIPS");
unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
+ unwind_plan.SetReturnAddressRegister (dwarf_ra_mips);
return true;
}
@@ -601,18 +882,18 @@ EmulateInstructionMIPS::nonvolatile_reg_p (uint32_t regnum)
{
switch (regnum)
{
- case gcc_dwarf_r16_mips:
- case gcc_dwarf_r17_mips:
- case gcc_dwarf_r18_mips:
- case gcc_dwarf_r19_mips:
- case gcc_dwarf_r20_mips:
- case gcc_dwarf_r21_mips:
- case gcc_dwarf_r22_mips:
- case gcc_dwarf_r23_mips:
- case gcc_dwarf_gp_mips:
- case gcc_dwarf_sp_mips:
- case gcc_dwarf_r30_mips:
- case gcc_dwarf_ra_mips:
+ case dwarf_r16_mips:
+ case dwarf_r17_mips:
+ case dwarf_r18_mips:
+ case dwarf_r19_mips:
+ case dwarf_r20_mips:
+ case dwarf_r21_mips:
+ case dwarf_r22_mips:
+ case dwarf_r23_mips:
+ case dwarf_gp_mips:
+ case dwarf_sp_mips:
+ case dwarf_r30_mips:
+ case dwarf_ra_mips:
return true;
default:
return false;
@@ -633,10 +914,10 @@ EmulateInstructionMIPS::Emulate_ADDiu (llvm::MCInst& insn)
src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
/* Check if this is addiu sp,<src>,imm16 */
- if (dst == gcc_dwarf_sp_mips)
+ if (dst == dwarf_sp_mips)
{
/* read <src> register */
- uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + src, 0, &success);
+ uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success);
if (!success)
return false;
@@ -644,13 +925,13 @@ EmulateInstructionMIPS::Emulate_ADDiu (llvm::MCInst& insn)
Context context;
RegisterInfo reg_info_sp;
- if (GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_sp_mips, reg_info_sp))
+ if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp))
context.SetRegisterPlusOffset (reg_info_sp, imm);
/* We are allocating bytes on stack */
context.type = eContextAdjustStackPointer;
- WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_sp_mips, result);
+ WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result);
}
return true;
@@ -663,30 +944,206 @@ EmulateInstructionMIPS::Emulate_SW (llvm::MCInst& insn)
uint32_t imm16 = insn.getOperand(2).getImm();
uint32_t imm = SignedBits(imm16, 15, 0);
uint32_t src, base;
+ int32_t address;
+ Context bad_vaddr_context;
+
+ RegisterInfo reg_info_base;
src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base))
+ return false;
+
+ /* read base register */
+ address = (int32_t)ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
+ if (!success)
+ return false;
+
+ /* destination address */
+ address = address + imm;
+
+ /* Set the bad_vaddr register with base address used in the instruction */
+ bad_vaddr_context.type = eContextInvalid;
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address);
+
/* We look for sp based non-volatile register stores */
- if (base == gcc_dwarf_sp_mips && nonvolatile_reg_p (src))
+ if (base == dwarf_sp_mips && nonvolatile_reg_p (src))
+ {
+
+ RegisterInfo reg_info_src;
+
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + src, reg_info_src))
+ return false;
+
+ Context context;
+ RegisterValue data_src;
+ context.type = eContextPushRegisterOnStack;
+ context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0);
+
+ uint8_t buffer [RegisterValue::kMaxRegisterByteSize];
+ Error error;
+
+ if (!ReadRegister (&reg_info_base, data_src))
+ return false;
+
+ if (data_src.GetAsMemoryData (&reg_info_src, buffer, reg_info_src.byte_size, eByteOrderLittle, error) == 0)
+ return false;
+
+ if (!WriteMemory (context, address, buffer, reg_info_src.byte_size))
+ return false;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_LW (llvm::MCInst& insn)
+{
+ bool success =false;
+ uint32_t src, base;
+ int32_t imm, address;
+ Context bad_vaddr_context;
+
+ src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ imm = insn.getOperand(2).getImm();
+
+ RegisterInfo reg_info_base;
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base))
+ return false;
+
+ /* read base register */
+ address = (int32_t)ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
+ if (!success)
+ return false;
+
+ /* destination address */
+ address = address + imm;
+
+ /* Set the bad_vaddr register with base address used in the instruction */
+ bad_vaddr_context.type = eContextInvalid;
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address);
+
+ if (base == dwarf_sp_mips && nonvolatile_reg_p (src))
{
- uint32_t address;
- RegisterInfo reg_info_base;
+ RegisterValue data_src;
RegisterInfo reg_info_src;
- if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips + base, reg_info_base)
- || !GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips + src, reg_info_src))
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + src, reg_info_src))
return false;
- /* read SP */
- address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + base, 0, &success);
+ Context context;
+ context.type = eContextPopRegisterOffStack;
+ context.SetAddress (address);
+
+ if (!WriteRegister (context, &reg_info_src, data_src))
+ return false;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_ADDIUSP (llvm::MCInst& insn)
+{
+ bool success = false;
+ const uint32_t imm9 = insn.getOperand(0).getImm();
+ uint64_t result;
+
+ // This instruction operates implicitly on stack pointer, so read <sp> register.
+ uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_sp_mips, 0, &success);
+ if (!success)
+ return false;
+
+ result = src_opd_val + imm9;
+
+ Context context;
+ RegisterInfo reg_info_sp;
+ if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp))
+ context.SetRegisterPlusOffset (reg_info_sp, imm9);
+
+ // We are adjusting the stack.
+ context.type = eContextAdjustStackPointer;
+
+ WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result);
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_ADDIUS5 (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t base;
+ const uint32_t imm4 = insn.getOperand(2).getImm();
+ uint64_t result;
+
+ // The source and destination register is same for this instruction.
+ base = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+
+ // We are looking for stack adjustment only
+ if (base == dwarf_sp_mips)
+ {
+ // Read stack pointer register
+ uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
if (!success)
return false;
- /* destination address */
- address = address + imm;
+ result = src_opd_val + imm4;
Context context;
+ RegisterInfo reg_info_sp;
+ if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp))
+ context.SetRegisterPlusOffset (reg_info_sp, imm4);
+
+ // We are adjusting the stack.
+ context.type = eContextAdjustStackPointer;
+
+ WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result);
+ }
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_SWSP (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t imm5 = insn.getOperand(2).getImm();
+ uint32_t src, base;
+ Context bad_vaddr_context;
+ uint32_t address;
+
+ src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+
+ RegisterInfo reg_info_base;
+
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base))
+ return false;
+
+ // read base register
+ address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
+ if (!success)
+ return false;
+
+ // destination address
+ address = address + imm5;
+
+ // We use bad_vaddr_context to store base address which is used by H/W watchpoint
+ // Set the bad_vaddr register with base address used in the instruction
+ bad_vaddr_context.type = eContextInvalid;
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address);
+
+ // We look for sp based non-volatile register stores.
+ if (base == dwarf_sp_mips && nonvolatile_reg_p (src))
+ {
+ RegisterInfo reg_info_src;
+ Context context;
RegisterValue data_src;
context.type = eContextPushRegisterOnStack;
context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0);
@@ -709,24 +1166,118 @@ EmulateInstructionMIPS::Emulate_SW (llvm::MCInst& insn)
return false;
}
+/* Emulate SWM16,SWM32 and SWP instruction.
+
+ SWM16 always has stack pointer as a base register (but it is still available in MCInst as an operand).
+ SWM32 and SWP can have base register other than stack pointer.
+*/
bool
-EmulateInstructionMIPS::Emulate_LW (llvm::MCInst& insn)
+EmulateInstructionMIPS::Emulate_SWM16_32 (llvm::MCInst& insn)
{
+ bool success = false;
uint32_t src, base;
+ uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on no of regs to store.
- src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ // Base register is second last operand of the instruction.
+ base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg());
+
+ // We are looking for sp based stores so if base is not a stack pointer then don't proceed.
+ if (base != dwarf_sp_mips)
+ return false;
+
+ // offset is always the last operand.
+ uint32_t offset = insn.getOperand(num_operands-1).getImm();
+
+ RegisterInfo reg_info_base;
+ RegisterInfo reg_info_src;
+
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base))
+ return false;
+
+ // read SP
+ uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
+ if (!success)
+ return false;
+
+ // Resulting base addrss
+ base_address = base_address + offset;
+
+ // Total no of registers to be stored are num_operands-2.
+ for (uint32_t i = 0; i < num_operands - 2; i++)
+ {
+ // Get the register number to be stored.
+ src = m_reg_info->getEncodingValue (insn.getOperand(i).getReg());
+
+ /*
+ Record only non-volatile stores.
+ This check is required for SWP instruction because source operand could be any register.
+ SWM16 and SWM32 instruction always has saved registers as source operands.
+ */
+ if (!nonvolatile_reg_p (src))
+ return false;
+
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + src, reg_info_src))
+ return false;
+
+ Context context;
+ RegisterValue data_src;
+ context.type = eContextPushRegisterOnStack;
+ context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0);
+
+ uint8_t buffer [RegisterValue::kMaxRegisterByteSize];
+ Error error;
+
+ if (!ReadRegister (&reg_info_base, data_src))
+ return false;
+
+ if (data_src.GetAsMemoryData (&reg_info_src, buffer, reg_info_src.byte_size, eByteOrderLittle, error) == 0)
+ return false;
+
+ if (!WriteMemory (context, base_address, buffer, reg_info_src.byte_size))
+ return false;
+
+ // Stack address for next register
+ base_address = base_address + reg_info_src.byte_size;
+ }
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_LWSP (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ uint32_t base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ uint32_t imm5 = insn.getOperand(2).getImm();
+ Context bad_vaddr_context;
+
+ RegisterInfo reg_info_base;
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base))
+ return false;
- if (base == gcc_dwarf_sp_mips && nonvolatile_reg_p (src))
+ // read base register
+ uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
+ if (!success)
+ return false;
+
+ base_address = base_address + imm5;
+
+ // We use bad_vaddr_context to store base address which is used by H/W watchpoint
+ // Set the bad_vaddr register with base address used in the instruction
+ bad_vaddr_context.type = eContextInvalid;
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, base_address);
+
+ if (base == dwarf_sp_mips && nonvolatile_reg_p (src))
{
RegisterValue data_src;
RegisterInfo reg_info_src;
- if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips + src, reg_info_src))
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + src, reg_info_src))
return false;
Context context;
- context.type = eContextRegisterLoad;
+ context.type = eContextPopRegisterOffStack;
+ context.SetAddress (base_address);
if (!WriteRegister (context, &reg_info_src, data_src))
return false;
@@ -737,6 +1288,105 @@ EmulateInstructionMIPS::Emulate_LW (llvm::MCInst& insn)
return false;
}
+/* Emulate LWM16, LWM32 and LWP instructions.
+
+ LWM16 always has stack pointer as a base register (but it is still available in MCInst as an operand).
+ LWM32 and LWP can have base register other than stack pointer.
+*/
+bool
+EmulateInstructionMIPS::Emulate_LWM16_32 (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t dst, base;
+ uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on no of regs to store.
+ uint32_t imm = insn.getOperand(num_operands-1).getImm(); // imm is the last operand in the instruction.
+
+ // Base register is second last operand of the instruction.
+ base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg());
+
+ // We are looking for sp based loads so if base is not a stack pointer then don't proceed.
+ if (base != dwarf_sp_mips)
+ return false;
+
+ uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
+ if (!success)
+ return false;
+
+ base_address = base_address + imm;
+
+ RegisterValue data_dst;
+ RegisterInfo reg_info_dst;
+
+ // Total no of registers to be re-stored are num_operands-2.
+ for (uint32_t i = 0; i < num_operands - 2; i++)
+ {
+ // Get the register number to be re-stored.
+ dst = m_reg_info->getEncodingValue (insn.getOperand(i).getReg());
+
+ /*
+ Record only non-volatile loads.
+ This check is required for LWP instruction because destination operand could be any register.
+ LWM16 and LWM32 instruction always has saved registers as destination operands.
+ */
+ if (!nonvolatile_reg_p (dst))
+ return false;
+
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + dst, reg_info_dst))
+ return false;
+
+ Context context;
+ context.type = eContextPopRegisterOffStack;
+ context.SetAddress (base_address + (i*4));
+
+ if (!WriteRegister (context, &reg_info_dst, data_dst))
+ return false;
+ }
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_JRADDIUSP (llvm::MCInst& insn)
+{
+ bool success = false;
+ int32_t imm5 = insn.getOperand(0).getImm();
+
+ /* JRADDIUSP immediate
+ * PC <- RA
+ * SP <- SP + zero_extend(Immediate << 2)
+ */
+
+ // This instruction operates implicitly on stack pointer, so read <sp> register.
+ int32_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_sp_mips, 0, &success);
+ if (!success)
+ return false;
+
+ int32_t ra_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_ra_mips, 0, &success);
+ if (!success)
+ return false;
+
+ int32_t result = src_opd_val + imm5;
+
+ Context context;
+
+ // Update the PC
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, ra_val))
+ return false;
+
+ RegisterInfo reg_info_sp;
+ if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp))
+ context.SetRegisterPlusOffset (reg_info_sp, imm5);
+
+ // We are adjusting stack
+ context.type = eContextAdjustStackPointer;
+
+ // update SP
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result))
+ return false;
+
+ return true;
+}
+
bool
EmulateInstructionMIPS::Emulate_BEQ (llvm::MCInst& insn)
{
@@ -754,15 +1404,15 @@ EmulateInstructionMIPS::Emulate_BEQ (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
if (!success)
return false;
@@ -774,13 +1424,270 @@ EmulateInstructionMIPS::Emulate_BEQ (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
}
bool
+EmulateInstructionMIPS::Emulate_B16_MM (llvm::MCInst& insn)
+{
+ bool success = false;
+ int32_t offset, pc, target;
+ uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
+
+ offset = insn.getOperand(0).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ // unconditional branch
+ target = pc + offset;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+ context.SetImmediate (current_inst_size + offset);
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+/*
+ BEQZC, BNEZC are 32 bit compact instructions without a delay slot.
+ BEQZ16, BNEZ16 are 16 bit instructions with delay slot.
+ BGEZALS, BLTZALS are 16 bit instructions with short (2-byte) delay slot.
+*/
+bool
+EmulateInstructionMIPS::Emulate_Branch_MM (llvm::MCInst& insn)
+{
+ bool success = false;
+ int32_t target = 0;
+ uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
+ bool update_ra = false;
+ uint32_t ra_offset = 0;
+
+ /*
+ * BEQZ16 rs, offset
+ * condition <- (GPR[rs] = 0)
+ * if condition then
+ * PC = PC + sign_ext (offset || 0)
+ *
+ * BNEZ16 rs, offset
+ * condition <- (GPR[rs] != 0)
+ * if condition then
+ * PC = PC + sign_ext (offset || 0)
+ *
+ * BEQZC rs, offset (compact instruction: No delay slot)
+ * condition <- (GPR[rs] == 0)
+ * if condition then
+ * PC = PC + 4 + sign_ext (offset || 0)
+ */
+
+ uint32_t rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ int32_t offset = insn.getOperand(1).getImm();
+
+ int32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ int32_t rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (!strcasecmp (op_name, "BEQZ16_MM"))
+ {
+ if (rs_val == 0)
+ target = pc + offset;
+ else
+ target = pc + current_inst_size + m_next_inst_size; // Skip delay slot instruction.
+ }
+ else if (!strcasecmp (op_name, "BNEZ16_MM"))
+ {
+ if (rs_val != 0)
+ target = pc + offset;
+ else
+ target = pc + current_inst_size + m_next_inst_size; // Skip delay slot instruction.
+ }
+ else if (!strcasecmp (op_name, "BEQZC_MM"))
+ {
+ if (rs_val == 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4; // 32 bit instruction and does not have delay slot instruction.
+ }
+ else if (!strcasecmp (op_name, "BNEZC_MM"))
+ {
+ if (rs_val != 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4; // 32 bit instruction and does not have delay slot instruction.
+ }
+ else if (!strcasecmp (op_name, "BGEZALS_MM"))
+ {
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 6; // 32 bit instruction with short (2-byte) delay slot
+
+ update_ra = true;
+ ra_offset = 6;
+ }
+ else if (!strcasecmp (op_name, "BLTZALS_MM"))
+ {
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 6; // 32 bit instruction with short (2-byte) delay slot
+
+ update_ra = true;
+ ra_offset = 6;
+ }
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+ context.SetImmediate (current_inst_size + offset);
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
+ return false;
+
+ if (update_ra)
+ {
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + ra_offset))
+ return false;
+ }
+ return true;
+}
+
+/* Emulate micromips jump instructions.
+ JALR16,JALRS16
+*/
+bool
+EmulateInstructionMIPS::Emulate_JALRx16_MM (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t ra_offset = 0;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
+
+ uint32_t rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+
+ uint32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ uint32_t rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ if (!strcasecmp (op_name, "JALR16_MM"))
+ ra_offset = 6; // 2-byte instruction with 4-byte delay slot.
+ else if (!strcasecmp (op_name, "JALRS16_MM"))
+ ra_offset = 4; // 2-byte instruction with 2-byte delay slot.
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + ra_offset))
+ return false;
+
+ return true;
+}
+
+/* Emulate JALS and JALX instructions.
+ JALS 32 bit instruction with short (2-byte) delay slot.
+ JALX 32 bit instruction with 4-byte delay slot.
+*/
+bool
+EmulateInstructionMIPS::Emulate_JALx (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t offset=0, target=0, pc=0, ra_offset=0;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
+
+ /*
+ * JALS target
+ * RA = PC + 6
+ * offset = sign_ext (offset << 1)
+ * PC = PC[31-27] | offset
+ * JALX target
+ * RA = PC + 8
+ * offset = sign_ext (offset << 2)
+ * PC = PC[31-28] | offset
+ */
+ offset = insn.getOperand(0).getImm();
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ // These are PC-region branches and not PC-relative.
+ if (!strcasecmp (op_name, "JALS_MM"))
+ {
+ // target address is in the “current†128 MB-aligned region
+ target = (pc & 0xF8000000UL) | offset;
+ ra_offset = 6;
+ }
+ else if (!strcasecmp (op_name, "JALX_MM"))
+ {
+ // target address is in the “current†256 MB-aligned region
+ target = (pc & 0xF0000000UL) | offset;
+ ra_offset = 8;
+ }
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
+ return false;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + ra_offset))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_JALRS (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t rs=0, rt=0;
+ int32_t pc=0, rs_val=0;
+
+ /*
+ JALRS rt, rs
+ GPR[rt] <- PC + 6
+ PC <- GPR[rs]
+ */
+
+ rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
+ if (!success)
+ return false;
+
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ Context context;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val))
+ return false;
+
+ // This is 4-byte instruction with 2-byte delay slot.
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips + rt, pc + 6))
+ return false;
+
+ return true;
+}
+
+bool
EmulateInstructionMIPS::Emulate_BNE (llvm::MCInst& insn)
{
bool success = false;
@@ -797,15 +1704,15 @@ EmulateInstructionMIPS::Emulate_BNE (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
if (!success)
return false;
@@ -817,7 +1724,7 @@ EmulateInstructionMIPS::Emulate_BNE (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -840,15 +1747,15 @@ EmulateInstructionMIPS::Emulate_BEQL (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
if (!success)
return false;
@@ -860,7 +1767,7 @@ EmulateInstructionMIPS::Emulate_BEQL (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -883,15 +1790,15 @@ EmulateInstructionMIPS::Emulate_BNEL (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
if (!success)
return false;
@@ -903,7 +1810,7 @@ EmulateInstructionMIPS::Emulate_BNEL (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -926,11 +1833,11 @@ EmulateInstructionMIPS::Emulate_BGEZL (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -942,7 +1849,7 @@ EmulateInstructionMIPS::Emulate_BGEZL (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -965,11 +1872,11 @@ EmulateInstructionMIPS::Emulate_BLTZL (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -981,7 +1888,7 @@ EmulateInstructionMIPS::Emulate_BLTZL (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -1004,11 +1911,11 @@ EmulateInstructionMIPS::Emulate_BGTZL (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -1020,7 +1927,7 @@ EmulateInstructionMIPS::Emulate_BGTZL (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -1043,11 +1950,11 @@ EmulateInstructionMIPS::Emulate_BLEZL (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -1059,7 +1966,7 @@ EmulateInstructionMIPS::Emulate_BLEZL (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -1082,11 +1989,11 @@ EmulateInstructionMIPS::Emulate_BGTZ (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -1098,7 +2005,7 @@ EmulateInstructionMIPS::Emulate_BGTZ (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -1121,11 +2028,11 @@ EmulateInstructionMIPS::Emulate_BLEZ (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -1137,7 +2044,7 @@ EmulateInstructionMIPS::Emulate_BLEZ (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -1160,11 +2067,11 @@ EmulateInstructionMIPS::Emulate_BLTZ (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -1176,7 +2083,7 @@ EmulateInstructionMIPS::Emulate_BLTZ (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -1199,11 +2106,11 @@ EmulateInstructionMIPS::Emulate_BGEZALL (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -1215,10 +2122,10 @@ EmulateInstructionMIPS::Emulate_BGEZALL (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8))
return false;
return true;
@@ -1238,7 +2145,7 @@ EmulateInstructionMIPS::Emulate_BAL (llvm::MCInst& insn)
*/
offset = insn.getOperand(0).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
@@ -1246,10 +2153,10 @@ EmulateInstructionMIPS::Emulate_BAL (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8))
return false;
return true;
@@ -1269,7 +2176,7 @@ EmulateInstructionMIPS::Emulate_BALC (llvm::MCInst& insn)
*/
offset = insn.getOperand(0).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
@@ -1277,10 +2184,10 @@ EmulateInstructionMIPS::Emulate_BALC (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4))
return false;
return true;
@@ -1305,11 +2212,11 @@ EmulateInstructionMIPS::Emulate_BGEZAL (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -1320,10 +2227,10 @@ EmulateInstructionMIPS::Emulate_BGEZAL (llvm::MCInst& insn)
else
target = pc + 8;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8))
return false;
return true;
@@ -1348,11 +2255,11 @@ EmulateInstructionMIPS::Emulate_BLTZAL (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -1363,10 +2270,10 @@ EmulateInstructionMIPS::Emulate_BLTZAL (llvm::MCInst& insn)
else
target = pc + 8;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8))
return false;
return true;
@@ -1391,11 +2298,11 @@ EmulateInstructionMIPS::Emulate_BLTZALL (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -1406,10 +2313,10 @@ EmulateInstructionMIPS::Emulate_BLTZALL (llvm::MCInst& insn)
else
target = pc + 8; /* skip delay slot */
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8))
return false;
return true;
@@ -1435,11 +2342,11 @@ EmulateInstructionMIPS::Emulate_BLEZALC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -1450,10 +2357,10 @@ EmulateInstructionMIPS::Emulate_BLEZALC (llvm::MCInst& insn)
else
target = pc + 4;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4))
return false;
return true;
@@ -1478,11 +2385,11 @@ EmulateInstructionMIPS::Emulate_BGEZALC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -1493,10 +2400,10 @@ EmulateInstructionMIPS::Emulate_BGEZALC (llvm::MCInst& insn)
else
target = pc + 4;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4))
return false;
return true;
@@ -1521,11 +2428,11 @@ EmulateInstructionMIPS::Emulate_BLTZALC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -1536,10 +2443,10 @@ EmulateInstructionMIPS::Emulate_BLTZALC (llvm::MCInst& insn)
else
target = pc + 4;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4))
return false;
return true;
@@ -1564,11 +2471,11 @@ EmulateInstructionMIPS::Emulate_BGTZALC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -1579,10 +2486,10 @@ EmulateInstructionMIPS::Emulate_BGTZALC (llvm::MCInst& insn)
else
target = pc + 4;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4))
return false;
return true;
@@ -1606,11 +2513,11 @@ EmulateInstructionMIPS::Emulate_BEQZALC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -1621,10 +2528,10 @@ EmulateInstructionMIPS::Emulate_BEQZALC (llvm::MCInst& insn)
else
target = pc + 4;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4))
return false;
return true;
@@ -1648,11 +2555,11 @@ EmulateInstructionMIPS::Emulate_BNEZALC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -1663,10 +2570,10 @@ EmulateInstructionMIPS::Emulate_BNEZALC (llvm::MCInst& insn)
else
target = pc + 4;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4))
return false;
return true;
@@ -1689,11 +2596,11 @@ EmulateInstructionMIPS::Emulate_BGEZ (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -1704,7 +2611,7 @@ EmulateInstructionMIPS::Emulate_BGEZ (llvm::MCInst& insn)
else
target = pc + 8;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -1723,7 +2630,7 @@ EmulateInstructionMIPS::Emulate_BC (llvm::MCInst& insn)
*/
offset = insn.getOperand(0).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
@@ -1731,7 +2638,7 @@ EmulateInstructionMIPS::Emulate_BC (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -1754,15 +2661,15 @@ EmulateInstructionMIPS::Emulate_BEQC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
if (!success)
return false;
@@ -1774,7 +2681,7 @@ EmulateInstructionMIPS::Emulate_BEQC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -1797,15 +2704,15 @@ EmulateInstructionMIPS::Emulate_BNEC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
if (!success)
return false;
@@ -1817,7 +2724,7 @@ EmulateInstructionMIPS::Emulate_BNEC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -1841,15 +2748,15 @@ EmulateInstructionMIPS::Emulate_BLTC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
if (!success)
return false;
@@ -1861,7 +2768,7 @@ EmulateInstructionMIPS::Emulate_BLTC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -1885,15 +2792,15 @@ EmulateInstructionMIPS::Emulate_BGEC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
if (!success)
return false;
@@ -1905,7 +2812,7 @@ EmulateInstructionMIPS::Emulate_BGEC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -1929,15 +2836,15 @@ EmulateInstructionMIPS::Emulate_BLTUC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
if (!success)
return false;
@@ -1949,7 +2856,7 @@ EmulateInstructionMIPS::Emulate_BLTUC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -1973,15 +2880,15 @@ EmulateInstructionMIPS::Emulate_BGEUC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
if (!success)
return false;
@@ -1993,7 +2900,7 @@ EmulateInstructionMIPS::Emulate_BGEUC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2016,11 +2923,11 @@ EmulateInstructionMIPS::Emulate_BLTZC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -2032,7 +2939,7 @@ EmulateInstructionMIPS::Emulate_BLTZC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2055,11 +2962,11 @@ EmulateInstructionMIPS::Emulate_BLEZC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -2071,7 +2978,7 @@ EmulateInstructionMIPS::Emulate_BLEZC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2094,11 +3001,11 @@ EmulateInstructionMIPS::Emulate_BGEZC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -2110,7 +3017,7 @@ EmulateInstructionMIPS::Emulate_BGEZC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2133,11 +3040,11 @@ EmulateInstructionMIPS::Emulate_BGTZC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -2149,7 +3056,7 @@ EmulateInstructionMIPS::Emulate_BGTZC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2172,11 +3079,11 @@ EmulateInstructionMIPS::Emulate_BEQZC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -2188,7 +3095,7 @@ EmulateInstructionMIPS::Emulate_BEQZC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2211,11 +3118,11 @@ EmulateInstructionMIPS::Emulate_BNEZC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
@@ -2227,7 +3134,7 @@ EmulateInstructionMIPS::Emulate_BNEZC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2258,15 +3165,15 @@ EmulateInstructionMIPS::Emulate_BOVC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
if (!success)
return false;
@@ -2278,7 +3185,7 @@ EmulateInstructionMIPS::Emulate_BOVC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2302,15 +3209,15 @@ EmulateInstructionMIPS::Emulate_BNVC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
if (!success)
return false;
@@ -2322,7 +3229,7 @@ EmulateInstructionMIPS::Emulate_BNVC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2341,7 +3248,7 @@ EmulateInstructionMIPS::Emulate_J (llvm::MCInst& insn)
*/
offset = insn.getOperand(0).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
@@ -2350,7 +3257,7 @@ EmulateInstructionMIPS::Emulate_J (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, pc))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, pc))
return false;
return true;
@@ -2369,7 +3276,7 @@ EmulateInstructionMIPS::Emulate_JAL (llvm::MCInst& insn)
*/
offset = insn.getOperand(0).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
@@ -2378,10 +3285,10 @@ EmulateInstructionMIPS::Emulate_JAL (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8))
return false;
return true;
@@ -2402,20 +3309,20 @@ EmulateInstructionMIPS::Emulate_JALR (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, rs_val))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips + rt, pc + 8))
return false;
return true;
@@ -2437,11 +3344,11 @@ EmulateInstructionMIPS::Emulate_JIALC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
if (!success)
return false;
@@ -2449,10 +3356,10 @@ EmulateInstructionMIPS::Emulate_JIALC (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4))
return false;
return true;
@@ -2473,7 +3380,7 @@ EmulateInstructionMIPS::Emulate_JIC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rt, 0, &success);
+ rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success);
if (!success)
return false;
@@ -2481,7 +3388,7 @@ EmulateInstructionMIPS::Emulate_JIC (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2500,13 +3407,13 @@ EmulateInstructionMIPS::Emulate_JR (llvm::MCInst& insn)
*/
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + rs, 0, &success);
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success);
if (!success)
return false;
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, rs_val))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val))
return false;
return true;
@@ -2529,11 +3436,11 @@ EmulateInstructionMIPS::Emulate_BC1F (llvm::MCInst& insn)
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);
if (!success)
return false;
@@ -2547,7 +3454,7 @@ EmulateInstructionMIPS::Emulate_BC1F (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2570,11 +3477,11 @@ EmulateInstructionMIPS::Emulate_BC1T (llvm::MCInst& insn)
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);
if (!success)
return false;
@@ -2588,7 +3495,7 @@ EmulateInstructionMIPS::Emulate_BC1T (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2611,11 +3518,11 @@ EmulateInstructionMIPS::Emulate_BC1FL (llvm::MCInst& insn)
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);
if (!success)
return false;
@@ -2629,7 +3536,7 @@ EmulateInstructionMIPS::Emulate_BC1FL (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2652,11 +3559,11 @@ EmulateInstructionMIPS::Emulate_BC1TL (llvm::MCInst& insn)
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);
if (!success)
return false;
@@ -2670,7 +3577,7 @@ EmulateInstructionMIPS::Emulate_BC1TL (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2694,11 +3601,11 @@ EmulateInstructionMIPS::Emulate_BC1EQZ (llvm::MCInst& insn)
ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + ft, 0, &success);
+ ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + ft, 0, &success);
if (!success)
return false;
@@ -2709,7 +3616,7 @@ EmulateInstructionMIPS::Emulate_BC1EQZ (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2733,11 +3640,11 @@ EmulateInstructionMIPS::Emulate_BC1NEZ (llvm::MCInst& insn)
ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips + ft, 0, &success);
+ ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + ft, 0, &success);
if (!success)
return false;
@@ -2748,7 +3655,7 @@ EmulateInstructionMIPS::Emulate_BC1NEZ (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2772,11 +3679,11 @@ EmulateInstructionMIPS::Emulate_BC1ANY2F (llvm::MCInst& insn)
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);
if (!success)
return false;
@@ -2791,7 +3698,7 @@ EmulateInstructionMIPS::Emulate_BC1ANY2F (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2815,11 +3722,11 @@ EmulateInstructionMIPS::Emulate_BC1ANY2T (llvm::MCInst& insn)
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);
if (!success)
return false;
@@ -2834,7 +3741,7 @@ EmulateInstructionMIPS::Emulate_BC1ANY2T (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2860,11 +3767,11 @@ EmulateInstructionMIPS::Emulate_BC1ANY4F (llvm::MCInst& insn)
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);
if (!success)
return false;
@@ -2879,7 +3786,7 @@ EmulateInstructionMIPS::Emulate_BC1ANY4F (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
@@ -2905,11 +3812,11 @@ EmulateInstructionMIPS::Emulate_BC1ANY4T (llvm::MCInst& insn)
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
if (!success)
return false;
- fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips, 0, &success);
+ fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success);
if (!success)
return false;
@@ -2924,8 +3831,234 @@ EmulateInstructionMIPS::Emulate_BC1ANY4T (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BNZB (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 1, true);
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BNZH (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 2, true);
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BNZW (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 4, true);
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BNZD (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 8, true);
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BZB (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 1, false);
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BZH (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 2, false);
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BZW (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 4, false);
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BZD (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 8, false);
+}
+
+bool
+EmulateInstructionMIPS::Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_byte_size, bool bnz)
+{
+ bool success = false, branch_hit = true;
+ int32_t target = 0;
+ RegisterValue reg_value;
+ uint8_t * ptr = NULL;
+
+ uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ int32_t offset = insn.getOperand(1).getImm();
+
+ int32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value))
+ ptr = (uint8_t *)reg_value.GetBytes();
+ else
+ return false;
+
+ for(int i = 0; i < 16 / element_byte_size; i++)
+ {
+ switch(element_byte_size)
+ {
+ case 1:
+ if((*ptr == 0 && bnz) || (*ptr != 0 && !bnz) )
+ branch_hit = false;
+ break;
+ case 2:
+ if((*(uint16_t *)ptr == 0 && bnz) || (*(uint16_t *)ptr != 0 && !bnz))
+ branch_hit = false;
+ break;
+ case 4:
+ if((*(uint32_t *)ptr == 0 && bnz) || (*(uint32_t *)ptr != 0 && !bnz))
+ branch_hit = false;
+ break;
+ case 8:
+ if((*(uint64_t *)ptr == 0 && bnz) || (*(uint64_t *)ptr != 0 && !bnz))
+ branch_hit = false;
+ break;
+ }
+ if(!branch_hit)
+ break;
+ ptr = ptr + element_byte_size;
+ }
+
+ if(branch_hit)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
return false;
return true;
}
+
+bool
+EmulateInstructionMIPS::Emulate_BNZV (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_V (insn, true);
+}
+
+bool
+EmulateInstructionMIPS::Emulate_BZV (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_V (insn, false);
+}
+
+bool
+EmulateInstructionMIPS::Emulate_MSA_Branch_V (llvm::MCInst& insn, bool bnz)
+{
+ bool success = false;
+ int32_t target = 0;
+ llvm::APInt wr_val = llvm::APInt::getNullValue(128);
+ llvm::APInt fail_value = llvm::APInt::getMaxValue(128);
+ llvm::APInt zero_value = llvm::APInt::getNullValue(128);
+ RegisterValue reg_value;
+
+ uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ int32_t offset = insn.getOperand(1).getImm();
+
+ int32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success);
+ if (!success)
+ return false;
+
+ if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value))
+ wr_val = reg_value.GetAsUInt128(fail_value);
+ else
+ return false;
+
+ if((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) || (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_LDST_Imm (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t base;
+ int32_t imm, address;
+ Context bad_vaddr_context;
+
+ uint32_t num_operands = insn.getNumOperands();
+ base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg());
+ imm = insn.getOperand(num_operands-1).getImm();
+
+ RegisterInfo reg_info_base;
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base))
+ return false;
+
+ /* read base register */
+ address =(int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
+ if (!success)
+ return false;
+
+ /* destination address */
+ address = address + imm;
+
+ /* Set the bad_vaddr register with base address used in the instruction */
+ bad_vaddr_context.type = eContextInvalid;
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address);
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS::Emulate_LDST_Reg (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t base, index;
+ int32_t address, index_address;
+ Context bad_vaddr_context;
+
+ uint32_t num_operands = insn.getNumOperands();
+ base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg());
+ index = m_reg_info->getEncodingValue (insn.getOperand(num_operands-1).getReg());
+
+ RegisterInfo reg_info_base, reg_info_index;
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base))
+ return false;
+
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + index, reg_info_index))
+ return false;
+
+ /* read base register */
+ address =(int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
+ if (!success)
+ return false;
+
+ /* read index register */
+ index_address =(int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + index, 0, &success);
+ if (!success)
+ return false;
+
+ /* destination address */
+ address = address + index_address;
+
+ /* Set the bad_vaddr register with base address used in the instruction */
+ bad_vaddr_context.type = eContextInvalid;
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address);
+
+ return true;
+}
diff --git a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h
index 25d8fc8891d5..e1340f983278 100644
--- a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h
+++ b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h
@@ -60,53 +60,52 @@ public:
return false;
}
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual lldb_private::ConstString
- GetShortPluginName()
- {
- return GetPluginNameStatic();
- }
-
- virtual uint32_t
- GetPluginVersion()
+ uint32_t
+ GetPluginVersion() override
{
return 1;
}
bool
- SetTargetTriple (const lldb_private::ArchSpec &arch);
+ SetTargetTriple (const lldb_private::ArchSpec &arch) override;
EmulateInstructionMIPS (const lldb_private::ArchSpec &arch);
- virtual bool
- SupportsEmulatingInstructionsOfType (lldb_private::InstructionType inst_type)
+ bool
+ SupportsEmulatingInstructionsOfType (lldb_private::InstructionType inst_type) override
{
return SupportsEmulatingInstructionsOfTypeStatic (inst_type);
}
- virtual bool
- ReadInstruction ();
-
- virtual bool
- EvaluateInstruction (uint32_t evaluate_options);
+ bool
+ ReadInstruction () override;
- virtual bool
+ bool
+ EvaluateInstruction (uint32_t evaluate_options) override;
+
+ bool
+ SetInstruction (const lldb_private::Opcode &insn_opcode,
+ const lldb_private::Address &inst_addr,
+ lldb_private::Target *target) override;
+
+ bool
TestEmulation (lldb_private::Stream *out_stream,
lldb_private::ArchSpec &arch,
- lldb_private::OptionValueDictionary *test_data)
+ lldb_private::OptionValueDictionary *test_data) override
{
return false;
}
- virtual bool
+ bool
GetRegisterInfo (lldb::RegisterKind reg_kind,
uint32_t reg_num,
- lldb_private::RegisterInfo &reg_info);
+ lldb_private::RegisterInfo &reg_info) override;
- virtual bool
- CreateFunctionEntryUnwind (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ CreateFunctionEntryUnwind (lldb_private::UnwindPlan &unwind_plan) override;
protected:
@@ -121,6 +120,9 @@ protected:
static MipsOpcode*
GetOpcodeForInstruction (const char *op_name);
+ uint32_t
+ GetSizeOfInstruction (lldb_private::DataExtractor& data, uint64_t inst_addr);
+
bool
Emulate_ADDiu (llvm::MCInst& insn);
@@ -131,6 +133,33 @@ protected:
Emulate_LW (llvm::MCInst& insn);
bool
+ Emulate_ADDIUSP (llvm::MCInst& insn);
+
+ bool
+ Emulate_ADDIUS5 (llvm::MCInst& insn);
+
+ bool
+ Emulate_SWSP (llvm::MCInst& insn);
+
+ bool
+ Emulate_SWM16_32 (llvm::MCInst& insn);
+
+ bool
+ Emulate_LWSP (llvm::MCInst& insn);
+
+ bool
+ Emulate_LWM16_32 (llvm::MCInst& insn);
+
+ bool
+ Emulate_JRADDIUSP (llvm::MCInst& insn);
+
+ bool
+ Emulate_LDST_Imm (llvm::MCInst& insn);
+
+ bool
+ Emulate_LDST_Reg (llvm::MCInst& insn);
+
+ bool
Emulate_BEQ (llvm::MCInst& insn);
bool
@@ -296,6 +325,57 @@ protected:
Emulate_BC1ANY4T (llvm::MCInst& insn);
bool
+ Emulate_BNZB (llvm::MCInst& insn);
+
+ bool
+ Emulate_BNZH (llvm::MCInst& insn);
+
+ bool
+ Emulate_BNZW (llvm::MCInst& insn);
+
+ bool
+ Emulate_BNZD (llvm::MCInst& insn);
+
+ bool
+ Emulate_BZB (llvm::MCInst& insn);
+
+ bool
+ Emulate_BZH (llvm::MCInst& insn);
+
+ bool
+ Emulate_BZW (llvm::MCInst& insn);
+
+ bool
+ Emulate_BZD (llvm::MCInst& insn);
+
+ bool
+ Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_byte_size, bool bnz);
+
+ bool
+ Emulate_BNZV (llvm::MCInst& insn);
+
+ bool
+ Emulate_BZV (llvm::MCInst& insn);
+
+ bool
+ Emulate_MSA_Branch_V (llvm::MCInst& insn, bool bnz);
+
+ bool
+ Emulate_B16_MM (llvm::MCInst& insn);
+
+ bool
+ Emulate_Branch_MM (llvm::MCInst& insn);
+
+ bool
+ Emulate_JALRx16_MM (llvm::MCInst& insn);
+
+ bool
+ Emulate_JALx (llvm::MCInst& insn);
+
+ bool
+ Emulate_JALRS (llvm::MCInst& insn);
+
+ bool
nonvolatile_reg_p (uint32_t regnum);
const char *
@@ -303,11 +383,15 @@ protected:
private:
std::unique_ptr<llvm::MCDisassembler> m_disasm;
+ std::unique_ptr<llvm::MCDisassembler> m_alt_disasm;
std::unique_ptr<llvm::MCSubtargetInfo> m_subtype_info;
+ std::unique_ptr<llvm::MCSubtargetInfo> m_alt_subtype_info;
std::unique_ptr<llvm::MCRegisterInfo> m_reg_info;
std::unique_ptr<llvm::MCAsmInfo> m_asm_info;
std::unique_ptr<llvm::MCContext> m_context;
std::unique_ptr<llvm::MCInstrInfo> m_insn_info;
+ uint32_t m_next_inst_size;
+ bool m_use_alt_disaasm;
};
#endif // EmulateInstructionMIPS_h_
diff --git a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
index a574e7d348e1..28eba093f317 100644
--- a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
+++ b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
@@ -221,41 +221,76 @@ EmulateInstructionMIPS64::GetRegisterName (unsigned reg_num, bool alternate_name
{
switch (reg_num)
{
- case gcc_dwarf_sp_mips64: return "r29";
- case gcc_dwarf_r30_mips64: return "r30";
- case gcc_dwarf_ra_mips64: return "r31";
- case gcc_dwarf_f0_mips64: return "f0";
- case gcc_dwarf_f1_mips64: return "f1";
- case gcc_dwarf_f2_mips64: return "f2";
- case gcc_dwarf_f3_mips64: return "f3";
- case gcc_dwarf_f4_mips64: return "f4";
- case gcc_dwarf_f5_mips64: return "f5";
- case gcc_dwarf_f6_mips64: return "f6";
- case gcc_dwarf_f7_mips64: return "f7";
- case gcc_dwarf_f8_mips64: return "f8";
- case gcc_dwarf_f9_mips64: return "f9";
- case gcc_dwarf_f10_mips64: return "f10";
- case gcc_dwarf_f11_mips64: return "f11";
- case gcc_dwarf_f12_mips64: return "f12";
- case gcc_dwarf_f13_mips64: return "f13";
- case gcc_dwarf_f14_mips64: return "f14";
- case gcc_dwarf_f15_mips64: return "f15";
- case gcc_dwarf_f16_mips64: return "f16";
- case gcc_dwarf_f17_mips64: return "f17";
- case gcc_dwarf_f18_mips64: return "f18";
- case gcc_dwarf_f19_mips64: return "f19";
- case gcc_dwarf_f20_mips64: return "f20";
- case gcc_dwarf_f21_mips64: return "f21";
- case gcc_dwarf_f22_mips64: return "f22";
- case gcc_dwarf_f23_mips64: return "f23";
- case gcc_dwarf_f24_mips64: return "f24";
- case gcc_dwarf_f25_mips64: return "f25";
- case gcc_dwarf_f26_mips64: return "f26";
- case gcc_dwarf_f27_mips64: return "f27";
- case gcc_dwarf_f28_mips64: return "f28";
- case gcc_dwarf_f29_mips64: return "f29";
- case gcc_dwarf_f30_mips64: return "f30";
- case gcc_dwarf_f31_mips64: return "f31";
+ case dwarf_sp_mips64: return "r29";
+ case dwarf_r30_mips64: return "r30";
+ case dwarf_ra_mips64: return "r31";
+ case dwarf_f0_mips64: return "f0";
+ case dwarf_f1_mips64: return "f1";
+ case dwarf_f2_mips64: return "f2";
+ case dwarf_f3_mips64: return "f3";
+ case dwarf_f4_mips64: return "f4";
+ case dwarf_f5_mips64: return "f5";
+ case dwarf_f6_mips64: return "f6";
+ case dwarf_f7_mips64: return "f7";
+ case dwarf_f8_mips64: return "f8";
+ case dwarf_f9_mips64: return "f9";
+ case dwarf_f10_mips64: return "f10";
+ case dwarf_f11_mips64: return "f11";
+ case dwarf_f12_mips64: return "f12";
+ case dwarf_f13_mips64: return "f13";
+ case dwarf_f14_mips64: return "f14";
+ case dwarf_f15_mips64: return "f15";
+ case dwarf_f16_mips64: return "f16";
+ case dwarf_f17_mips64: return "f17";
+ case dwarf_f18_mips64: return "f18";
+ case dwarf_f19_mips64: return "f19";
+ case dwarf_f20_mips64: return "f20";
+ case dwarf_f21_mips64: return "f21";
+ case dwarf_f22_mips64: return "f22";
+ case dwarf_f23_mips64: return "f23";
+ case dwarf_f24_mips64: return "f24";
+ case dwarf_f25_mips64: return "f25";
+ case dwarf_f26_mips64: return "f26";
+ case dwarf_f27_mips64: return "f27";
+ case dwarf_f28_mips64: return "f28";
+ case dwarf_f29_mips64: return "f29";
+ case dwarf_f30_mips64: return "f30";
+ case dwarf_f31_mips64: return "f31";
+ case dwarf_w0_mips64: return "w0";
+ case dwarf_w1_mips64: return "w1";
+ case dwarf_w2_mips64: return "w2";
+ case dwarf_w3_mips64: return "w3";
+ case dwarf_w4_mips64: return "w4";
+ case dwarf_w5_mips64: return "w5";
+ case dwarf_w6_mips64: return "w6";
+ case dwarf_w7_mips64: return "w7";
+ case dwarf_w8_mips64: return "w8";
+ case dwarf_w9_mips64: return "w9";
+ case dwarf_w10_mips64: return "w10";
+ case dwarf_w11_mips64: return "w11";
+ case dwarf_w12_mips64: return "w12";
+ case dwarf_w13_mips64: return "w13";
+ case dwarf_w14_mips64: return "w14";
+ case dwarf_w15_mips64: return "w15";
+ case dwarf_w16_mips64: return "w16";
+ case dwarf_w17_mips64: return "w17";
+ case dwarf_w18_mips64: return "w18";
+ case dwarf_w19_mips64: return "w19";
+ case dwarf_w20_mips64: return "w20";
+ case dwarf_w21_mips64: return "w21";
+ case dwarf_w22_mips64: return "w22";
+ case dwarf_w23_mips64: return "w23";
+ case dwarf_w24_mips64: return "w24";
+ case dwarf_w25_mips64: return "w25";
+ case dwarf_w26_mips64: return "w26";
+ case dwarf_w27_mips64: return "w27";
+ case dwarf_w28_mips64: return "w28";
+ case dwarf_w29_mips64: return "w29";
+ case dwarf_w30_mips64: return "w30";
+ case dwarf_w31_mips64: return "w31";
+ case dwarf_mir_mips64: return "mir";
+ case dwarf_mcsr_mips64: return "mcsr";
+ case dwarf_config5_mips64: return "config5";
default:
break;
}
@@ -264,78 +299,113 @@ EmulateInstructionMIPS64::GetRegisterName (unsigned reg_num, bool alternate_name
switch (reg_num)
{
- case gcc_dwarf_zero_mips64: return "r0";
- case gcc_dwarf_r1_mips64: return "r1";
- case gcc_dwarf_r2_mips64: return "r2";
- case gcc_dwarf_r3_mips64: return "r3";
- case gcc_dwarf_r4_mips64: return "r4";
- case gcc_dwarf_r5_mips64: return "r5";
- case gcc_dwarf_r6_mips64: return "r6";
- case gcc_dwarf_r7_mips64: return "r7";
- case gcc_dwarf_r8_mips64: return "r8";
- case gcc_dwarf_r9_mips64: return "r9";
- case gcc_dwarf_r10_mips64: return "r10";
- case gcc_dwarf_r11_mips64: return "r11";
- case gcc_dwarf_r12_mips64: return "r12";
- case gcc_dwarf_r13_mips64: return "r13";
- case gcc_dwarf_r14_mips64: return "r14";
- case gcc_dwarf_r15_mips64: return "r15";
- case gcc_dwarf_r16_mips64: return "r16";
- case gcc_dwarf_r17_mips64: return "r17";
- case gcc_dwarf_r18_mips64: return "r18";
- case gcc_dwarf_r19_mips64: return "r19";
- case gcc_dwarf_r20_mips64: return "r20";
- case gcc_dwarf_r21_mips64: return "r21";
- case gcc_dwarf_r22_mips64: return "r22";
- case gcc_dwarf_r23_mips64: return "r23";
- case gcc_dwarf_r24_mips64: return "r24";
- case gcc_dwarf_r25_mips64: return "r25";
- case gcc_dwarf_r26_mips64: return "r26";
- case gcc_dwarf_r27_mips64: return "r27";
- case gcc_dwarf_gp_mips64: return "gp";
- case gcc_dwarf_sp_mips64: return "sp";
- case gcc_dwarf_r30_mips64: return "fp";
- case gcc_dwarf_ra_mips64: return "ra";
- case gcc_dwarf_sr_mips64: return "sr";
- case gcc_dwarf_lo_mips64: return "lo";
- case gcc_dwarf_hi_mips64: return "hi";
- case gcc_dwarf_bad_mips64: return "bad";
- case gcc_dwarf_cause_mips64: return "cause";
- case gcc_dwarf_pc_mips64: return "pc";
- case gcc_dwarf_f0_mips64: return "f0";
- case gcc_dwarf_f1_mips64: return "f1";
- case gcc_dwarf_f2_mips64: return "f2";
- case gcc_dwarf_f3_mips64: return "f3";
- case gcc_dwarf_f4_mips64: return "f4";
- case gcc_dwarf_f5_mips64: return "f5";
- case gcc_dwarf_f6_mips64: return "f6";
- case gcc_dwarf_f7_mips64: return "f7";
- case gcc_dwarf_f8_mips64: return "f8";
- case gcc_dwarf_f9_mips64: return "f9";
- case gcc_dwarf_f10_mips64: return "f10";
- case gcc_dwarf_f11_mips64: return "f11";
- case gcc_dwarf_f12_mips64: return "f12";
- case gcc_dwarf_f13_mips64: return "f13";
- case gcc_dwarf_f14_mips64: return "f14";
- case gcc_dwarf_f15_mips64: return "f15";
- case gcc_dwarf_f16_mips64: return "f16";
- case gcc_dwarf_f17_mips64: return "f17";
- case gcc_dwarf_f18_mips64: return "f18";
- case gcc_dwarf_f19_mips64: return "f19";
- case gcc_dwarf_f20_mips64: return "f20";
- case gcc_dwarf_f21_mips64: return "f21";
- case gcc_dwarf_f22_mips64: return "f22";
- case gcc_dwarf_f23_mips64: return "f23";
- case gcc_dwarf_f24_mips64: return "f24";
- case gcc_dwarf_f25_mips64: return "f25";
- case gcc_dwarf_f26_mips64: return "f26";
- case gcc_dwarf_f27_mips64: return "f27";
- case gcc_dwarf_f28_mips64: return "f28";
- case gcc_dwarf_f29_mips64: return "f29";
- case gcc_dwarf_f30_mips64: return "f30";
- case gcc_dwarf_f31_mips64: return "f31";
- case gcc_dwarf_fcsr_mips64: return "fcsr";
- case gcc_dwarf_fir_mips64: return "fir";
+ case dwarf_zero_mips64: return "r0";
+ case dwarf_r1_mips64: return "r1";
+ case dwarf_r2_mips64: return "r2";
+ case dwarf_r3_mips64: return "r3";
+ case dwarf_r4_mips64: return "r4";
+ case dwarf_r5_mips64: return "r5";
+ case dwarf_r6_mips64: return "r6";
+ case dwarf_r7_mips64: return "r7";
+ case dwarf_r8_mips64: return "r8";
+ case dwarf_r9_mips64: return "r9";
+ case dwarf_r10_mips64: return "r10";
+ case dwarf_r11_mips64: return "r11";
+ case dwarf_r12_mips64: return "r12";
+ case dwarf_r13_mips64: return "r13";
+ case dwarf_r14_mips64: return "r14";
+ case dwarf_r15_mips64: return "r15";
+ case dwarf_r16_mips64: return "r16";
+ case dwarf_r17_mips64: return "r17";
+ case dwarf_r18_mips64: return "r18";
+ case dwarf_r19_mips64: return "r19";
+ case dwarf_r20_mips64: return "r20";
+ case dwarf_r21_mips64: return "r21";
+ case dwarf_r22_mips64: return "r22";
+ case dwarf_r23_mips64: return "r23";
+ case dwarf_r24_mips64: return "r24";
+ case dwarf_r25_mips64: return "r25";
+ case dwarf_r26_mips64: return "r26";
+ case dwarf_r27_mips64: return "r27";
+ case dwarf_gp_mips64: return "gp";
+ case dwarf_sp_mips64: return "sp";
+ case dwarf_r30_mips64: return "fp";
+ case dwarf_ra_mips64: return "ra";
+ case dwarf_sr_mips64: return "sr";
+ case dwarf_lo_mips64: return "lo";
+ case dwarf_hi_mips64: return "hi";
+ case dwarf_bad_mips64: return "bad";
+ case dwarf_cause_mips64: return "cause";
+ case dwarf_pc_mips64: return "pc";
+ case dwarf_f0_mips64: return "f0";
+ case dwarf_f1_mips64: return "f1";
+ case dwarf_f2_mips64: return "f2";
+ case dwarf_f3_mips64: return "f3";
+ case dwarf_f4_mips64: return "f4";
+ case dwarf_f5_mips64: return "f5";
+ case dwarf_f6_mips64: return "f6";
+ case dwarf_f7_mips64: return "f7";
+ case dwarf_f8_mips64: return "f8";
+ case dwarf_f9_mips64: return "f9";
+ case dwarf_f10_mips64: return "f10";
+ case dwarf_f11_mips64: return "f11";
+ case dwarf_f12_mips64: return "f12";
+ case dwarf_f13_mips64: return "f13";
+ case dwarf_f14_mips64: return "f14";
+ case dwarf_f15_mips64: return "f15";
+ case dwarf_f16_mips64: return "f16";
+ case dwarf_f17_mips64: return "f17";
+ case dwarf_f18_mips64: return "f18";
+ case dwarf_f19_mips64: return "f19";
+ case dwarf_f20_mips64: return "f20";
+ case dwarf_f21_mips64: return "f21";
+ case dwarf_f22_mips64: return "f22";
+ case dwarf_f23_mips64: return "f23";
+ case dwarf_f24_mips64: return "f24";
+ case dwarf_f25_mips64: return "f25";
+ case dwarf_f26_mips64: return "f26";
+ case dwarf_f27_mips64: return "f27";
+ case dwarf_f28_mips64: return "f28";
+ case dwarf_f29_mips64: return "f29";
+ case dwarf_f30_mips64: return "f30";
+ case dwarf_f31_mips64: return "f31";
+ case dwarf_fcsr_mips64: return "fcsr";
+ case dwarf_fir_mips64: return "fir";
+ case dwarf_w0_mips64: return "w0";
+ case dwarf_w1_mips64: return "w1";
+ case dwarf_w2_mips64: return "w2";
+ case dwarf_w3_mips64: return "w3";
+ case dwarf_w4_mips64: return "w4";
+ case dwarf_w5_mips64: return "w5";
+ case dwarf_w6_mips64: return "w6";
+ case dwarf_w7_mips64: return "w7";
+ case dwarf_w8_mips64: return "w8";
+ case dwarf_w9_mips64: return "w9";
+ case dwarf_w10_mips64: return "w10";
+ case dwarf_w11_mips64: return "w11";
+ case dwarf_w12_mips64: return "w12";
+ case dwarf_w13_mips64: return "w13";
+ case dwarf_w14_mips64: return "w14";
+ case dwarf_w15_mips64: return "w15";
+ case dwarf_w16_mips64: return "w16";
+ case dwarf_w17_mips64: return "w17";
+ case dwarf_w18_mips64: return "w18";
+ case dwarf_w19_mips64: return "w19";
+ case dwarf_w20_mips64: return "w20";
+ case dwarf_w21_mips64: return "w21";
+ case dwarf_w22_mips64: return "w22";
+ case dwarf_w23_mips64: return "w23";
+ case dwarf_w24_mips64: return "w24";
+ case dwarf_w25_mips64: return "w25";
+ case dwarf_w26_mips64: return "w26";
+ case dwarf_w27_mips64: return "w27";
+ case dwarf_w28_mips64: return "w28";
+ case dwarf_w29_mips64: return "w29";
+ case dwarf_w30_mips64: return "w30";
+ case dwarf_w31_mips64: return "w31";
+ case dwarf_mcsr_mips64: return "mcsr";
+ case dwarf_mir_mips64: return "mir";
+ case dwarf_config5_mips64: return "config5";
}
return nullptr;
}
@@ -347,11 +417,11 @@ EmulateInstructionMIPS64::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_n
{
switch (reg_num)
{
- case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_pc_mips64; break;
- case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sp_mips64; break;
- case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_r30_mips64; break;
- case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_ra_mips64; break;
- case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = gcc_dwarf_sr_mips64; break;
+ case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = dwarf_pc_mips64; break;
+ case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sp_mips64; break;
+ case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_r30_mips64; break;
+ case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = dwarf_ra_mips64; break;
+ case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sr_mips64; break;
default:
return false;
}
@@ -362,18 +432,24 @@ EmulateInstructionMIPS64::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_n
::memset (&reg_info, 0, sizeof(RegisterInfo));
::memset (reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
- if (reg_num == gcc_dwarf_sr_mips64 || reg_num == gcc_dwarf_fcsr_mips64 || reg_num == gcc_dwarf_fir_mips64)
+ if (reg_num == dwarf_sr_mips64 || reg_num == dwarf_fcsr_mips64 || reg_num == dwarf_fir_mips64 || reg_num == dwarf_mcsr_mips64 || reg_num == dwarf_mir_mips64 || reg_num == dwarf_config5_mips64)
{
reg_info.byte_size = 4;
reg_info.format = eFormatHex;
reg_info.encoding = eEncodingUint;
}
- else if ((int)reg_num >= gcc_dwarf_zero_mips64 && (int)reg_num <= gcc_dwarf_f31_mips64)
+ else if ((int)reg_num >= dwarf_zero_mips64 && (int)reg_num <= dwarf_f31_mips64)
{
reg_info.byte_size = 8;
reg_info.format = eFormatHex;
reg_info.encoding = eEncodingUint;
}
+ else if ((int)reg_num >= dwarf_w0_mips64 && (int)reg_num <= dwarf_w31_mips64)
+ {
+ reg_info.byte_size = 16;
+ reg_info.format = eFormatVectorOfUInt8;
+ reg_info.encoding = eEncodingVector;
+ }
else
{
return false;
@@ -385,11 +461,11 @@ EmulateInstructionMIPS64::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_n
switch (reg_num)
{
- case gcc_dwarf_r30_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break;
- case gcc_dwarf_ra_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break;
- case gcc_dwarf_sp_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break;
- case gcc_dwarf_pc_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break;
- case gcc_dwarf_sr_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break;
+ case dwarf_r30_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break;
+ case dwarf_ra_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break;
+ case dwarf_sp_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break;
+ case dwarf_pc_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break;
+ case dwarf_sr_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break;
default: break;
}
return true;
@@ -410,8 +486,65 @@ EmulateInstructionMIPS64::GetOpcodeForInstruction (const char *op_name)
{ "SD", &EmulateInstructionMIPS64::Emulate_SD, "SD rt,offset(rs)" },
{ "LD", &EmulateInstructionMIPS64::Emulate_LD, "LD rt,offset(base)" },
- { "SW", &EmulateInstructionMIPS64::Emulate_SW, "SW rt,offset(rs)" },
- { "LW", &EmulateInstructionMIPS64::Emulate_LW, "LW rt,offset(rs)" },
+
+
+
+ //----------------------------------------------------------------------
+ // Load/Store instructions
+ //----------------------------------------------------------------------
+ /* Following list of emulated instructions are required by implementation of hardware watchpoint
+ for MIPS in lldb. As we just need the address accessed by instructions, we have generalised
+ all these instructions in 2 functions depending on their addressing modes */
+
+ { "LB", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LB rt, offset(base)" },
+ { "LBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LBE rt, offset(base)" },
+ { "LBU", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LBU rt, offset(base)" },
+ { "LBUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LBUE rt, offset(base)" },
+ { "LDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDC1 ft, offset(base)" },
+ { "LDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDL rt, offset(base)" },
+ { "LDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDR rt, offset(base)" },
+ { "LLD", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LLD rt, offset(base)" },
+ { "LDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDC2 rt, offset(base)" },
+ { "LDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "LDXC1 fd, index (base)" },
+ { "LH", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LH rt, offset(base)" },
+ { "LHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LHE rt, offset(base)" },
+ { "LHU", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LHU rt, offset(base)" },
+ { "LHUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LHUE rt, offset(base)" },
+ { "LL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LL rt, offset(base)" },
+ { "LLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LLE rt, offset(base)" },
+ { "LUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "LUXC1 fd, index (base)" },
+ { "LW", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LW rt, offset(rs)" },
+ { "LWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWC1 ft, offset(base)" },
+ { "LWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWC2 rt, offset(base)" },
+ { "LWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWE rt, offset(base)" },
+ { "LWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWL rt, offset(base)" },
+ { "LWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWLE rt, offset(base)" },
+ { "LWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWR rt, offset(base)" },
+ { "LWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWRE rt, offset(base)" },
+ { "LWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "LWXC1 fd, index (base)" },
+
+ { "SB", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SB rt, offset(base)" },
+ { "SBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SBE rt, offset(base)" },
+ { "SC", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SC rt, offset(base)" },
+ { "SCE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SCE rt, offset(base)" },
+ { "SCD", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SCD rt, offset(base)" },
+ { "SDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDL rt, offset(base)" },
+ { "SDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDR rt, offset(base)" },
+ { "SDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDC1 ft, offset(base)" },
+ { "SDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDC2 rt, offset(base)" },
+ { "SDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "SDXC1 fs, index (base)" },
+ { "SH", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SH rt, offset(base)" },
+ { "SHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SHE rt, offset(base)" },
+ { "SUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "SUXC1 fs, index (base)" },
+ { "SW", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SW rt, offset(rs)" },
+ { "SWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWC1 ft, offset(base)" },
+ { "SWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWC2 rt, offset(base)" },
+ { "SWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWE rt, offset(base)" },
+ { "SWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWL rt, offset(base)" },
+ { "SWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWLE rt, offset(base)" },
+ { "SWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWR rt, offset(base)" },
+ { "SWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWRE rt, offset(base)" },
+ { "SWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "SWXC1 fs, index (base)" },
//----------------------------------------------------------------------
// Branch instructions
@@ -474,6 +607,16 @@ EmulateInstructionMIPS64::GetOpcodeForInstruction (const char *op_name)
{ "BC1ANY2T", &EmulateInstructionMIPS64::Emulate_BC1ANY2T, "BC1ANY2T cc, offset" },
{ "BC1ANY4F", &EmulateInstructionMIPS64::Emulate_BC1ANY4F, "BC1ANY4F cc, offset" },
{ "BC1ANY4T", &EmulateInstructionMIPS64::Emulate_BC1ANY4T, "BC1ANY4T cc, offset" },
+ { "BNZ_B", &EmulateInstructionMIPS64::Emulate_BNZB, "BNZ.b wt,s16" },
+ { "BNZ_H", &EmulateInstructionMIPS64::Emulate_BNZH, "BNZ.h wt,s16" },
+ { "BNZ_W", &EmulateInstructionMIPS64::Emulate_BNZW, "BNZ.w wt,s16" },
+ { "BNZ_D", &EmulateInstructionMIPS64::Emulate_BNZD, "BNZ.d wt,s16" },
+ { "BZ_B", &EmulateInstructionMIPS64::Emulate_BZB, "BZ.b wt,s16" },
+ { "BZ_H", &EmulateInstructionMIPS64::Emulate_BZH, "BZ.h wt,s16" },
+ { "BZ_W", &EmulateInstructionMIPS64::Emulate_BZW, "BZ.w wt,s16" },
+ { "BZ_D", &EmulateInstructionMIPS64::Emulate_BZD, "BZ.d wt,s16" },
+ { "BNZ_V", &EmulateInstructionMIPS64::Emulate_BNZV, "BNZ.V wt,s16" },
+ { "BZ_V", &EmulateInstructionMIPS64::Emulate_BZV, "BZ.V wt,s16" },
};
static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes);
@@ -545,7 +688,7 @@ EmulateInstructionMIPS64::EvaluateInstruction (uint32_t evaluate_options)
if (auto_advance_pc)
{
- old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
}
@@ -557,7 +700,7 @@ EmulateInstructionMIPS64::EvaluateInstruction (uint32_t evaluate_options)
if (auto_advance_pc)
{
- new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
@@ -566,7 +709,7 @@ EmulateInstructionMIPS64::EvaluateInstruction (uint32_t evaluate_options)
{
new_pc += 4;
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, new_pc))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, new_pc))
return false;
}
}
@@ -584,10 +727,10 @@ EmulateInstructionMIPS64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
const bool can_replace = false;
// Our previous Call Frame Address is the stack pointer
- row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_sp_mips64, 0);
+ row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips64, 0);
// Our previous PC is in the RA
- row->SetRegisterLocationToRegister(gcc_dwarf_pc_mips64, gcc_dwarf_ra_mips64, can_replace);
+ row->SetRegisterLocationToRegister(dwarf_pc_mips64, dwarf_ra_mips64, can_replace);
unwind_plan.AppendRow (row);
@@ -595,6 +738,7 @@ EmulateInstructionMIPS64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
unwind_plan.SetSourceName ("EmulateInstructionMIPS64");
unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
+ unwind_plan.SetReturnAddressRegister (dwarf_ra_mips64);
return true;
}
@@ -604,18 +748,18 @@ EmulateInstructionMIPS64::nonvolatile_reg_p (uint64_t regnum)
{
switch (regnum)
{
- case gcc_dwarf_r16_mips64:
- case gcc_dwarf_r17_mips64:
- case gcc_dwarf_r18_mips64:
- case gcc_dwarf_r19_mips64:
- case gcc_dwarf_r20_mips64:
- case gcc_dwarf_r21_mips64:
- case gcc_dwarf_r22_mips64:
- case gcc_dwarf_r23_mips64:
- case gcc_dwarf_gp_mips64:
- case gcc_dwarf_sp_mips64:
- case gcc_dwarf_r30_mips64:
- case gcc_dwarf_ra_mips64:
+ case dwarf_r16_mips64:
+ case dwarf_r17_mips64:
+ case dwarf_r18_mips64:
+ case dwarf_r19_mips64:
+ case dwarf_r20_mips64:
+ case dwarf_r21_mips64:
+ case dwarf_r22_mips64:
+ case dwarf_r23_mips64:
+ case dwarf_gp_mips64:
+ case dwarf_sp_mips64:
+ case dwarf_r30_mips64:
+ case dwarf_ra_mips64:
return true;
default:
return false;
@@ -636,10 +780,10 @@ EmulateInstructionMIPS64::Emulate_DADDiu (llvm::MCInst& insn)
src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
/* Check if this is daddiu sp,<src>,imm16 */
- if (dst == gcc_dwarf_sp_mips64)
+ if (dst == dwarf_sp_mips64)
{
/* read <src> register */
- uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, 0, &success);
+ uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
if (!success)
return false;
@@ -647,79 +791,19 @@ EmulateInstructionMIPS64::Emulate_DADDiu (llvm::MCInst& insn)
Context context;
RegisterInfo reg_info_sp;
- if (GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_sp_mips64, reg_info_sp))
+ if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp))
context.SetRegisterPlusOffset (reg_info_sp, imm);
/* We are allocating bytes on stack */
context.type = eContextAdjustStackPointer;
- WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_sp_mips64, result);
+ WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips64, result);
}
return true;
}
bool
-EmulateInstructionMIPS64::Emulate_SW (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t base;
- int64_t imm, address;
- Context bad_vaddr_context;
-
- base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- imm = insn.getOperand(2).getImm();
-
- RegisterInfo reg_info_base;
- if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, reg_info_base))
- return false;
-
- /* read base register */
- address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, 0, &success);
- if (!success)
- return false;
-
- /* destination address */
- address = address + imm;
-
- /* Set the bad_vaddr register with base address used in the instruction */
- bad_vaddr_context.type = eContextInvalid;
- WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, gcc_dwarf_bad_mips64, address);
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_LW (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t base;
- int64_t imm, address;
- Context bad_vaddr_context;
-
- base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- imm = insn.getOperand(2).getImm();
-
- RegisterInfo reg_info_base;
- if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, reg_info_base))
- return false;
-
- /* read base register */
- address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, 0, &success);
- if (!success)
- return false;
-
- /* destination address */
- address = address + imm;
-
- /* Set the bad_vaddr register with base address used in the instruction */
- bad_vaddr_context.type = eContextInvalid;
- WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, gcc_dwarf_bad_mips64, address);
-
- return true;
-}
-
-bool
EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn)
{
uint64_t address;
@@ -734,12 +818,12 @@ EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn)
src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, reg_info_base)
- || !GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src))
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + base, reg_info_base)
+ || !GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + src, reg_info_src))
return false;
/* read SP */
- address = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + base, 0, &success);
+ address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + base, 0, &success);
if (!success)
return false;
@@ -747,7 +831,7 @@ EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn)
address = address + imm;
/* We look for sp based non-volatile register stores */
- if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src))
+ if (base == dwarf_sp_mips64 && nonvolatile_reg_p (src))
{
Context context;
RegisterValue data_src;
@@ -769,7 +853,7 @@ EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn)
/* Set the bad_vaddr register with base address used in the instruction */
bad_vaddr_context.type = eContextInvalid;
- WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, gcc_dwarf_bad_mips64, address);
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64, address);
return true;
}
@@ -777,17 +861,38 @@ EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn)
bool
EmulateInstructionMIPS64::Emulate_LD (llvm::MCInst& insn)
{
+ bool success =false;
uint32_t src, base;
+ int64_t imm, address;
+ Context bad_vaddr_context;
src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
+ imm = insn.getOperand(2).getImm();
+
+ RegisterInfo reg_info_base;
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + base, reg_info_base))
+ return false;
+
+ /* read base register */
+ address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + base, 0, &success);
+ if (!success)
+ return false;
- if (base == gcc_dwarf_sp_mips64 && nonvolatile_reg_p (src))
+ /* destination address */
+ address = address + imm;
+
+ /* Set the bad_vaddr register with base address used in the instruction */
+ bad_vaddr_context.type = eContextInvalid;
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64, address);
+
+
+ if (base == dwarf_sp_mips64 && nonvolatile_reg_p (src))
{
RegisterValue data_src;
RegisterInfo reg_info_src;
- if (!GetRegisterInfo (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + src, reg_info_src))
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + src, reg_info_src))
return false;
Context context;
@@ -821,15 +926,15 @@ EmulateInstructionMIPS64::Emulate_BEQ (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
if (!success)
return false;
@@ -841,7 +946,7 @@ EmulateInstructionMIPS64::Emulate_BEQ (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -864,15 +969,15 @@ EmulateInstructionMIPS64::Emulate_BNE (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
if (!success)
return false;
@@ -884,7 +989,7 @@ EmulateInstructionMIPS64::Emulate_BNE (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -907,15 +1012,15 @@ EmulateInstructionMIPS64::Emulate_BEQL (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
if (!success)
return false;
@@ -927,7 +1032,7 @@ EmulateInstructionMIPS64::Emulate_BEQL (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -950,15 +1055,15 @@ EmulateInstructionMIPS64::Emulate_BNEL (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
if (!success)
return false;
@@ -970,7 +1075,7 @@ EmulateInstructionMIPS64::Emulate_BNEL (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -993,11 +1098,11 @@ EmulateInstructionMIPS64::Emulate_BGEZL (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -1009,7 +1114,7 @@ EmulateInstructionMIPS64::Emulate_BGEZL (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -1032,11 +1137,11 @@ EmulateInstructionMIPS64::Emulate_BLTZL (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -1048,7 +1153,7 @@ EmulateInstructionMIPS64::Emulate_BLTZL (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -1071,11 +1176,11 @@ EmulateInstructionMIPS64::Emulate_BGTZL (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -1087,7 +1192,7 @@ EmulateInstructionMIPS64::Emulate_BGTZL (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -1110,11 +1215,11 @@ EmulateInstructionMIPS64::Emulate_BLEZL (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -1126,7 +1231,7 @@ EmulateInstructionMIPS64::Emulate_BLEZL (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -1149,11 +1254,11 @@ EmulateInstructionMIPS64::Emulate_BGTZ (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -1165,7 +1270,7 @@ EmulateInstructionMIPS64::Emulate_BGTZ (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -1188,11 +1293,11 @@ EmulateInstructionMIPS64::Emulate_BLEZ (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -1204,7 +1309,7 @@ EmulateInstructionMIPS64::Emulate_BLEZ (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -1227,11 +1332,11 @@ EmulateInstructionMIPS64::Emulate_BLTZ (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -1243,7 +1348,7 @@ EmulateInstructionMIPS64::Emulate_BLTZ (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -1266,11 +1371,11 @@ EmulateInstructionMIPS64::Emulate_BGEZALL (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -1282,10 +1387,10 @@ EmulateInstructionMIPS64::Emulate_BGEZALL (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8))
return false;
return true;
@@ -1305,7 +1410,7 @@ EmulateInstructionMIPS64::Emulate_BAL (llvm::MCInst& insn)
*/
offset = insn.getOperand(0).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
@@ -1313,10 +1418,10 @@ EmulateInstructionMIPS64::Emulate_BAL (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8))
return false;
return true;
@@ -1336,7 +1441,7 @@ EmulateInstructionMIPS64::Emulate_BALC (llvm::MCInst& insn)
*/
offset = insn.getOperand(0).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
@@ -1344,10 +1449,10 @@ EmulateInstructionMIPS64::Emulate_BALC (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))
return false;
return true;
@@ -1372,11 +1477,11 @@ EmulateInstructionMIPS64::Emulate_BGEZAL (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -1387,10 +1492,10 @@ EmulateInstructionMIPS64::Emulate_BGEZAL (llvm::MCInst& insn)
else
target = pc + 8;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8))
return false;
return true;
@@ -1415,11 +1520,11 @@ EmulateInstructionMIPS64::Emulate_BLTZAL (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -1430,10 +1535,10 @@ EmulateInstructionMIPS64::Emulate_BLTZAL (llvm::MCInst& insn)
else
target = pc + 8;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8))
return false;
return true;
@@ -1458,11 +1563,11 @@ EmulateInstructionMIPS64::Emulate_BLTZALL (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -1473,10 +1578,10 @@ EmulateInstructionMIPS64::Emulate_BLTZALL (llvm::MCInst& insn)
else
target = pc + 8; /* skip delay slot */
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8))
return false;
return true;
@@ -1502,11 +1607,11 @@ EmulateInstructionMIPS64::Emulate_BLEZALC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -1517,10 +1622,10 @@ EmulateInstructionMIPS64::Emulate_BLEZALC (llvm::MCInst& insn)
else
target = pc + 4;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))
return false;
return true;
@@ -1545,11 +1650,11 @@ EmulateInstructionMIPS64::Emulate_BGEZALC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -1560,10 +1665,10 @@ EmulateInstructionMIPS64::Emulate_BGEZALC (llvm::MCInst& insn)
else
target = pc + 4;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))
return false;
return true;
@@ -1588,11 +1693,11 @@ EmulateInstructionMIPS64::Emulate_BLTZALC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -1603,10 +1708,10 @@ EmulateInstructionMIPS64::Emulate_BLTZALC (llvm::MCInst& insn)
else
target = pc + 4;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))
return false;
return true;
@@ -1631,11 +1736,11 @@ EmulateInstructionMIPS64::Emulate_BGTZALC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -1646,10 +1751,10 @@ EmulateInstructionMIPS64::Emulate_BGTZALC (llvm::MCInst& insn)
else
target = pc + 4;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))
return false;
return true;
@@ -1673,11 +1778,11 @@ EmulateInstructionMIPS64::Emulate_BEQZALC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -1688,10 +1793,10 @@ EmulateInstructionMIPS64::Emulate_BEQZALC (llvm::MCInst& insn)
else
target = pc + 4;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))
return false;
return true;
@@ -1715,11 +1820,11 @@ EmulateInstructionMIPS64::Emulate_BNEZALC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -1730,10 +1835,10 @@ EmulateInstructionMIPS64::Emulate_BNEZALC (llvm::MCInst& insn)
else
target = pc + 4;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))
return false;
return true;
@@ -1756,11 +1861,11 @@ EmulateInstructionMIPS64::Emulate_BGEZ (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -1771,7 +1876,7 @@ EmulateInstructionMIPS64::Emulate_BGEZ (llvm::MCInst& insn)
else
target = pc + 8;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -1790,7 +1895,7 @@ EmulateInstructionMIPS64::Emulate_BC (llvm::MCInst& insn)
*/
offset = insn.getOperand(0).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
@@ -1798,7 +1903,7 @@ EmulateInstructionMIPS64::Emulate_BC (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -1821,15 +1926,15 @@ EmulateInstructionMIPS64::Emulate_BEQC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
if (!success)
return false;
@@ -1841,7 +1946,7 @@ EmulateInstructionMIPS64::Emulate_BEQC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -1864,15 +1969,15 @@ EmulateInstructionMIPS64::Emulate_BNEC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
if (!success)
return false;
@@ -1884,7 +1989,7 @@ EmulateInstructionMIPS64::Emulate_BNEC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -1908,15 +2013,15 @@ EmulateInstructionMIPS64::Emulate_BLTC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
if (!success)
return false;
@@ -1928,7 +2033,7 @@ EmulateInstructionMIPS64::Emulate_BLTC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -1952,15 +2057,15 @@ EmulateInstructionMIPS64::Emulate_BGEC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
if (!success)
return false;
@@ -1972,7 +2077,7 @@ EmulateInstructionMIPS64::Emulate_BGEC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -1996,15 +2101,15 @@ EmulateInstructionMIPS64::Emulate_BLTUC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
- rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
if (!success)
return false;
@@ -2016,7 +2121,7 @@ EmulateInstructionMIPS64::Emulate_BLTUC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2040,15 +2145,15 @@ EmulateInstructionMIPS64::Emulate_BGEUC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
- rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
if (!success)
return false;
@@ -2060,7 +2165,7 @@ EmulateInstructionMIPS64::Emulate_BGEUC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2083,11 +2188,11 @@ EmulateInstructionMIPS64::Emulate_BLTZC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -2099,7 +2204,7 @@ EmulateInstructionMIPS64::Emulate_BLTZC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2122,11 +2227,11 @@ EmulateInstructionMIPS64::Emulate_BLEZC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -2138,7 +2243,7 @@ EmulateInstructionMIPS64::Emulate_BLEZC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2161,11 +2266,11 @@ EmulateInstructionMIPS64::Emulate_BGEZC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -2177,7 +2282,7 @@ EmulateInstructionMIPS64::Emulate_BGEZC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2200,11 +2305,11 @@ EmulateInstructionMIPS64::Emulate_BGTZC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -2216,7 +2321,7 @@ EmulateInstructionMIPS64::Emulate_BGTZC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2239,11 +2344,11 @@ EmulateInstructionMIPS64::Emulate_BEQZC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -2255,7 +2360,7 @@ EmulateInstructionMIPS64::Emulate_BEQZC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2278,11 +2383,11 @@ EmulateInstructionMIPS64::Emulate_BNEZC (llvm::MCInst& insn)
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
@@ -2294,7 +2399,7 @@ EmulateInstructionMIPS64::Emulate_BNEZC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2325,15 +2430,15 @@ EmulateInstructionMIPS64::Emulate_BOVC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
if (!success)
return false;
@@ -2345,7 +2450,7 @@ EmulateInstructionMIPS64::Emulate_BOVC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2369,15 +2474,15 @@ EmulateInstructionMIPS64::Emulate_BNVC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
if (!success)
return false;
@@ -2389,7 +2494,7 @@ EmulateInstructionMIPS64::Emulate_BNVC (llvm::MCInst& insn)
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2408,7 +2513,7 @@ EmulateInstructionMIPS64::Emulate_J (llvm::MCInst& insn)
*/
offset = insn.getOperand(0).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
@@ -2417,7 +2522,7 @@ EmulateInstructionMIPS64::Emulate_J (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, pc))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, pc))
return false;
return true;
@@ -2436,7 +2541,7 @@ EmulateInstructionMIPS64::Emulate_JAL (llvm::MCInst& insn)
*/
offset = insn.getOperand(0).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
@@ -2445,10 +2550,10 @@ EmulateInstructionMIPS64::Emulate_JAL (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8))
return false;
return true;
@@ -2469,20 +2574,20 @@ EmulateInstructionMIPS64::Emulate_JALR (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, rs_val))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, rs_val))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, pc + 8))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips64 + rt, pc + 8))
return false;
return true;
@@ -2504,11 +2609,11 @@ EmulateInstructionMIPS64::Emulate_JIALC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
if (!success)
return false;
@@ -2516,10 +2621,10 @@ EmulateInstructionMIPS64::Emulate_JIALC (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_ra_mips64, pc + 4))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))
return false;
return true;
@@ -2540,7 +2645,7 @@ EmulateInstructionMIPS64::Emulate_JIC (llvm::MCInst& insn)
rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rt, 0, &success);
+ rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
if (!success)
return false;
@@ -2548,7 +2653,7 @@ EmulateInstructionMIPS64::Emulate_JIC (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2567,13 +2672,13 @@ EmulateInstructionMIPS64::Emulate_JR (llvm::MCInst& insn)
*/
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + rs, 0, &success);
+ rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
if (!success)
return false;
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, rs_val))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, rs_val))
return false;
return true;
@@ -2596,11 +2701,11 @@ EmulateInstructionMIPS64::Emulate_BC1F (llvm::MCInst& insn)
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
if (!success)
return false;
@@ -2614,7 +2719,7 @@ EmulateInstructionMIPS64::Emulate_BC1F (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2637,11 +2742,11 @@ EmulateInstructionMIPS64::Emulate_BC1T (llvm::MCInst& insn)
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
if (!success)
return false;
@@ -2655,7 +2760,7 @@ EmulateInstructionMIPS64::Emulate_BC1T (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2678,11 +2783,11 @@ EmulateInstructionMIPS64::Emulate_BC1FL (llvm::MCInst& insn)
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
if (!success)
return false;
@@ -2696,7 +2801,7 @@ EmulateInstructionMIPS64::Emulate_BC1FL (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2719,11 +2824,11 @@ EmulateInstructionMIPS64::Emulate_BC1TL (llvm::MCInst& insn)
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
if (!success)
return false;
@@ -2737,7 +2842,7 @@ EmulateInstructionMIPS64::Emulate_BC1TL (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2761,11 +2866,11 @@ EmulateInstructionMIPS64::Emulate_BC1EQZ (llvm::MCInst& insn)
ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + ft, 0, &success);
+ ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0, &success);
if (!success)
return false;
@@ -2776,7 +2881,7 @@ EmulateInstructionMIPS64::Emulate_BC1EQZ (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2800,11 +2905,11 @@ EmulateInstructionMIPS64::Emulate_BC1NEZ (llvm::MCInst& insn)
ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_zero_mips64 + ft, 0, &success);
+ ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0, &success);
if (!success)
return false;
@@ -2815,7 +2920,7 @@ EmulateInstructionMIPS64::Emulate_BC1NEZ (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2839,11 +2944,11 @@ EmulateInstructionMIPS64::Emulate_BC1ANY2F (llvm::MCInst& insn)
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
if (!success)
return false;
@@ -2858,7 +2963,7 @@ EmulateInstructionMIPS64::Emulate_BC1ANY2F (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2882,11 +2987,11 @@ EmulateInstructionMIPS64::Emulate_BC1ANY2T (llvm::MCInst& insn)
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
if (!success)
return false;
@@ -2901,7 +3006,7 @@ EmulateInstructionMIPS64::Emulate_BC1ANY2T (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2927,11 +3032,11 @@ EmulateInstructionMIPS64::Emulate_BC1ANY4F (llvm::MCInst& insn)
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
if (!success)
return false;
@@ -2946,7 +3051,7 @@ EmulateInstructionMIPS64::Emulate_BC1ANY4F (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
@@ -2972,11 +3077,11 @@ EmulateInstructionMIPS64::Emulate_BC1ANY4T (llvm::MCInst& insn)
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_pc_mips64, 0, &success);
+ pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
- fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, gcc_dwarf_fcsr_mips64, 0, &success);
+ fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
if (!success)
return false;
@@ -2991,8 +3096,234 @@ EmulateInstructionMIPS64::Emulate_BC1ANY4T (llvm::MCInst& insn)
Context context;
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, gcc_dwarf_pc_mips64, target))
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
return true;
}
+
+bool
+EmulateInstructionMIPS64::Emulate_BNZB (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 1, true);
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BNZH (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 2, true);
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BNZW (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 4, true);
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BNZD (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 8, true);
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BZB (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 1, false);
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BZH (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 2, false);
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BZW (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 4, false);
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BZD (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_DF(insn, 8, false);
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_byte_size, bool bnz)
+{
+ bool success = false, branch_hit = true;
+ int64_t target = 0;
+ RegisterValue reg_value;
+ uint8_t * ptr = NULL;
+
+ uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ int64_t offset = insn.getOperand(1).getImm();
+
+ int64_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
+ ptr = (uint8_t *)reg_value.GetBytes();
+ else
+ return false;
+
+ for(int i = 0; i < 16 / element_byte_size; i++)
+ {
+ switch(element_byte_size)
+ {
+ case 1:
+ if((*ptr == 0 && bnz) || (*ptr != 0 && !bnz) )
+ branch_hit = false;
+ break;
+ case 2:
+ if((*(uint16_t *)ptr == 0 && bnz) || (*(uint16_t *)ptr != 0 && !bnz))
+ branch_hit = false;
+ break;
+ case 4:
+ if((*(uint32_t *)ptr == 0 && bnz) || (*(uint32_t *)ptr != 0 && !bnz))
+ branch_hit = false;
+ break;
+ case 8:
+ if((*(uint64_t *)ptr == 0 && bnz) || (*(uint64_t *)ptr != 0 && !bnz))
+ branch_hit = false;
+ break;
+ }
+ if(!branch_hit)
+ break;
+ ptr = ptr + element_byte_size;
+ }
+
+ if(branch_hit)
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BNZV (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_V (insn, true);
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_BZV (llvm::MCInst& insn)
+{
+ return Emulate_MSA_Branch_V (insn, false);
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_MSA_Branch_V (llvm::MCInst& insn, bool bnz)
+{
+ bool success = false;
+ int64_t target = 0;
+ llvm::APInt wr_val = llvm::APInt::getNullValue(128);
+ llvm::APInt fail_value = llvm::APInt::getMaxValue(128);
+ llvm::APInt zero_value = llvm::APInt::getNullValue(128);
+ RegisterValue reg_value;
+
+ uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
+ int64_t offset = insn.getOperand(1).getImm();
+
+ int64_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
+ if (!success)
+ return false;
+
+ if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value))
+ wr_val = reg_value.GetAsUInt128(fail_value);
+ else
+ return false;
+
+ if((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) || (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz))
+ target = pc + offset;
+ else
+ target = pc + 8;
+
+ Context context;
+ context.type = eContextRelativeBranchImmediate;
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
+ return false;
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_LDST_Imm (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t base;
+ int64_t imm, address;
+ Context bad_vaddr_context;
+
+ uint32_t num_operands = insn.getNumOperands();
+ base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg());
+ imm = insn.getOperand(num_operands-1).getImm();
+
+ RegisterInfo reg_info_base;
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base))
+ return false;
+
+ /* read base register */
+ address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
+ if (!success)
+ return false;
+
+ /* destination address */
+ address = address + imm;
+
+ /* Set the bad_vaddr register with base address used in the instruction */
+ bad_vaddr_context.type = eContextInvalid;
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address);
+
+ return true;
+}
+
+bool
+EmulateInstructionMIPS64::Emulate_LDST_Reg (llvm::MCInst& insn)
+{
+ bool success = false;
+ uint32_t base, index;
+ int64_t address, index_address;
+ Context bad_vaddr_context;
+
+ uint32_t num_operands = insn.getNumOperands();
+ base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg());
+ index = m_reg_info->getEncodingValue (insn.getOperand(num_operands-1).getReg());
+
+ RegisterInfo reg_info_base, reg_info_index;
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base))
+ return false;
+
+ if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + index, reg_info_index))
+ return false;
+
+ /* read base register */
+ address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success);
+ if (!success)
+ return false;
+
+ /* read index register */
+ index_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + index, 0, &success);
+ if (!success)
+ return false;
+
+ /* destination address */
+ address = address + index_address;
+
+ /* Set the bad_vaddr register with base address used in the instruction */
+ bad_vaddr_context.type = eContextInvalid;
+ WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address);
+
+ return true;
+}
diff --git a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h
index faefd329a8e4..e0b20792ae1f 100644
--- a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h
+++ b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h
@@ -1,4 +1,4 @@
-//===-- EmulateInstructionMIPS64.h ------------------------------------*- C++ -*-===//
+//===-- EmulateInstructionMIPS64.h ------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,6 +10,14 @@
#ifndef EmulateInstructionMIPS64_h_
#define EmulateInstructionMIPS64_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/EmulateInstruction.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Interpreter/OptionValue.h"
+
namespace llvm
{
class MCDisassembler;
@@ -19,15 +27,13 @@ namespace llvm
class MCContext;
class MCInstrInfo;
class MCInst;
-}
-
-#include "lldb/Core/EmulateInstruction.h"
-#include "lldb/Core/Error.h"
-#include "lldb/Interpreter/OptionValue.h"
+} // namespace llvm
class EmulateInstructionMIPS64 : public lldb_private::EmulateInstruction
{
public:
+ EmulateInstructionMIPS64(const lldb_private::ArchSpec &arch);
+
static void
Initialize ();
@@ -60,57 +66,47 @@ public:
return false;
}
- virtual lldb_private::ConstString
- GetPluginName();
-
- virtual lldb_private::ConstString
- GetShortPluginName()
- {
- return GetPluginNameStatic();
- }
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion()
+ uint32_t
+ GetPluginVersion() override
{
return 1;
}
bool
- SetTargetTriple (const lldb_private::ArchSpec &arch);
+ SetTargetTriple(const lldb_private::ArchSpec &arch) override;
- EmulateInstructionMIPS64 (const lldb_private::ArchSpec &arch);
-
- virtual bool
- SupportsEmulatingInstructionsOfType (lldb_private::InstructionType inst_type)
+ bool
+ SupportsEmulatingInstructionsOfType(lldb_private::InstructionType inst_type) override
{
return SupportsEmulatingInstructionsOfTypeStatic (inst_type);
}
- virtual bool
- ReadInstruction ();
+ bool
+ ReadInstruction() override;
- virtual bool
- EvaluateInstruction (uint32_t evaluate_options);
+ bool
+ EvaluateInstruction(uint32_t evaluate_options) override;
- virtual bool
- TestEmulation (lldb_private::Stream *out_stream,
- lldb_private::ArchSpec &arch,
- lldb_private::OptionValueDictionary *test_data)
+ bool
+ TestEmulation(lldb_private::Stream *out_stream,
+ lldb_private::ArchSpec &arch,
+ lldb_private::OptionValueDictionary *test_data) override
{
return false;
}
- virtual bool
- GetRegisterInfo (lldb::RegisterKind reg_kind,
- uint32_t reg_num,
- lldb_private::RegisterInfo &reg_info);
-
- virtual bool
- CreateFunctionEntryUnwind (lldb_private::UnwindPlan &unwind_plan);
+ bool
+ GetRegisterInfo(lldb::RegisterKind reg_kind,
+ uint32_t reg_num,
+ lldb_private::RegisterInfo &reg_info) override;
+ bool
+ CreateFunctionEntryUnwind(lldb_private::UnwindPlan &unwind_plan) override;
protected:
-
typedef struct
{
const char *op_name;
@@ -128,13 +124,13 @@ protected:
Emulate_SD (llvm::MCInst& insn);
bool
- Emulate_SW (llvm::MCInst& insn);
+ Emulate_LD (llvm::MCInst& insn);
bool
- Emulate_LW (llvm::MCInst& insn);
+ Emulate_LDST_Imm (llvm::MCInst& insn);
bool
- Emulate_LD (llvm::MCInst& insn);
+ Emulate_LDST_Reg (llvm::MCInst& insn);
bool
Emulate_BEQ (llvm::MCInst& insn);
@@ -302,6 +298,42 @@ protected:
Emulate_BC1ANY4T (llvm::MCInst& insn);
bool
+ Emulate_BNZB (llvm::MCInst& insn);
+
+ bool
+ Emulate_BNZH (llvm::MCInst& insn);
+
+ bool
+ Emulate_BNZW (llvm::MCInst& insn);
+
+ bool
+ Emulate_BNZD (llvm::MCInst& insn);
+
+ bool
+ Emulate_BZB (llvm::MCInst& insn);
+
+ bool
+ Emulate_BZH (llvm::MCInst& insn);
+
+ bool
+ Emulate_BZW (llvm::MCInst& insn);
+
+ bool
+ Emulate_BZD (llvm::MCInst& insn);
+
+ bool
+ Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_byte_size, bool bnz);
+
+ bool
+ Emulate_BNZV (llvm::MCInst& insn);
+
+ bool
+ Emulate_BZV (llvm::MCInst& insn);
+
+ bool
+ Emulate_MSA_Branch_V (llvm::MCInst& insn, bool bnz);
+
+ bool
nonvolatile_reg_p (uint64_t regnum);
const char *
@@ -316,4 +348,4 @@ private:
std::unique_ptr<llvm::MCInstrInfo> m_insn_info;
};
-#endif // EmulateInstructionMIPS64_h_
+#endif // EmulateInstructionMIPS64_h_
diff --git a/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp
index 9b72ceb71bd0..c2f1f2e95c83 100644
--- a/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp
+++ b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp
@@ -66,9 +66,11 @@ AddressSanitizerRuntime::GetTypeStatic()
AddressSanitizerRuntime::AddressSanitizerRuntime(const ProcessSP &process_sp) :
m_is_active(false),
m_runtime_module(),
- m_process(process_sp),
+ m_process_wp(),
m_breakpoint_id(0)
{
+ if (process_sp)
+ m_process_wp = process_sp;
}
AddressSanitizerRuntime::~AddressSanitizerRuntime()
@@ -78,14 +80,11 @@ AddressSanitizerRuntime::~AddressSanitizerRuntime()
bool ModuleContainsASanRuntime(Module * module)
{
- SymbolContextList sc_list;
- const bool include_symbols = true;
- const bool append = true;
- const bool include_inlines = true;
-
- size_t num_matches = module->FindFunctions(ConstString("__asan_get_alloc_stack"), NULL, eFunctionNameTypeAuto, include_symbols, include_inlines, append, sc_list);
-
- return num_matches > 0;
+ const Symbol* symbol = module->FindFirstSymbolWithNameAndType(
+ ConstString("__asan_get_alloc_stack"),
+ lldb::eSymbolTypeAny);
+
+ return symbol != nullptr;
}
void
@@ -164,7 +163,11 @@ t
StructuredData::ObjectSP
AddressSanitizerRuntime::RetrieveReportData()
{
- ThreadSP thread_sp = m_process->GetThreadList().GetSelectedThread();
+ ProcessSP process_sp = GetProcessSP();
+ if (!process_sp)
+ return StructuredData::ObjectSP();
+
+ ThreadSP thread_sp = process_sp->GetThreadList().GetSelectedThread();
StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
if (!frame_sp)
@@ -178,7 +181,7 @@ AddressSanitizerRuntime::RetrieveReportData()
options.SetTimeoutUsec(RETRIEVE_REPORT_DATA_FUNCTION_TIMEOUT_USEC);
ValueObjectSP return_value_sp;
- if (m_process->GetTarget().EvaluateExpression(address_sanitizer_retrieve_report_data_command, frame_sp.get(), return_value_sp, options) != eExpressionCompleted)
+ if (process_sp->GetTarget().EvaluateExpression(address_sanitizer_retrieve_report_data_command, frame_sp.get(), return_value_sp, options) != eExpressionCompleted)
return StructuredData::ObjectSP();
int present = return_value_sp->GetValueForExpressionPath(".present")->GetValueAsUnsigned(0);
@@ -196,7 +199,7 @@ AddressSanitizerRuntime::RetrieveReportData()
addr_t description_ptr = return_value_sp->GetValueForExpressionPath(".description")->GetValueAsUnsigned(0);
std::string description;
Error error;
- m_process->ReadCStringFromMemory(description_ptr, description, error);
+ process_sp->ReadCStringFromMemory(description_ptr, description, error);
StructuredData::Dictionary *dict = new StructuredData::Dictionary();
dict->AddStringItem("instrumentation_class", "AddressSanitizer");
@@ -252,27 +255,31 @@ AddressSanitizerRuntime::NotifyBreakpointHit(void *baton, StoppointCallbackConte
assert (baton && "null baton");
if (!baton)
return false;
-
+
AddressSanitizerRuntime *const instance = static_cast<AddressSanitizerRuntime*>(baton);
-
+
StructuredData::ObjectSP report = instance->RetrieveReportData();
std::string description;
if (report) {
description = instance->FormatDescription(report);
}
- ThreadSP thread = context->exe_ctx_ref.GetThreadSP();
- thread->SetStopInfo(InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData(*thread, description.c_str(), report));
-
- if (instance->m_process)
+ ProcessSP process_sp = instance->GetProcessSP();
+ // Make sure this is the right process
+ if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP())
{
- StreamFileSP stream_sp (instance->m_process->GetTarget().GetDebugger().GetOutputFile());
+ ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP();
+ if (thread_sp)
+ thread_sp->SetStopInfo(InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData(*thread_sp, description.c_str(), report));
+
+ StreamFileSP stream_sp (process_sp->GetTarget().GetDebugger().GetOutputFile());
if (stream_sp)
{
stream_sp->Printf ("AddressSanitizer report breakpoint hit. Use 'thread info -s' to get extended information about the report.\n");
}
+ return true; // Return true to stop the target
}
- // Return true to stop the target, false to just let the target run.
- return true;
+ else
+ return false; // Let target run
}
void
@@ -281,6 +288,10 @@ AddressSanitizerRuntime::Activate()
if (m_is_active)
return;
+ ProcessSP process_sp = GetProcessSP();
+ if (!process_sp)
+ return;
+
ConstString symbol_name ("__asan::AsanDie()");
const Symbol *symbol = m_runtime_module->FindFirstSymbolWithNameAndType (symbol_name, eSymbolTypeCode);
@@ -290,7 +301,7 @@ AddressSanitizerRuntime::Activate()
if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid())
return;
- Target &target = m_process->GetTarget();
+ Target &target = process_sp->GetTarget();
addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target);
if (symbol_address == LLDB_INVALID_ADDRESS)
@@ -298,18 +309,15 @@ AddressSanitizerRuntime::Activate()
bool internal = true;
bool hardware = false;
- Breakpoint *breakpoint = m_process->GetTarget().CreateBreakpoint(symbol_address, internal, hardware).get();
+ Breakpoint *breakpoint = process_sp->GetTarget().CreateBreakpoint(symbol_address, internal, hardware).get();
breakpoint->SetCallback (AddressSanitizerRuntime::NotifyBreakpointHit, this, true);
breakpoint->SetBreakpointKind ("address-sanitizer-report");
m_breakpoint_id = breakpoint->GetID();
- if (m_process)
+ StreamFileSP stream_sp (process_sp->GetTarget().GetDebugger().GetOutputFile());
+ if (stream_sp)
{
- StreamFileSP stream_sp (m_process->GetTarget().GetDebugger().GetOutputFile());
- if (stream_sp)
- {
- stream_sp->Printf ("AddressSanitizer debugger support is active. Memory error breakpoint has been installed and you can now use the 'memory history' command.\n");
- }
+ stream_sp->Printf ("AddressSanitizer debugger support is active. Memory error breakpoint has been installed and you can now use the 'memory history' command.\n");
}
m_is_active = true;
@@ -320,8 +328,12 @@ AddressSanitizerRuntime::Deactivate()
{
if (m_breakpoint_id != LLDB_INVALID_BREAK_ID)
{
- m_process->GetTarget().RemoveBreakpointByID(m_breakpoint_id);
- m_breakpoint_id = LLDB_INVALID_BREAK_ID;
+ ProcessSP process_sp = GetProcessSP();
+ if (process_sp)
+ {
+ process_sp->GetTarget().RemoveBreakpointByID(m_breakpoint_id);
+ m_breakpoint_id = LLDB_INVALID_BREAK_ID;
+ }
}
m_is_active = false;
}
diff --git a/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h
index 69c134cbedaf..fe12ab847e76 100644
--- a/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h
+++ b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.h
@@ -10,6 +10,10 @@
#ifndef liblldb_AddressSanitizerRuntime_h_
#define liblldb_AddressSanitizerRuntime_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/InstrumentationRuntime.h"
@@ -21,7 +25,8 @@ namespace lldb_private {
class AddressSanitizerRuntime : public lldb_private::InstrumentationRuntime
{
public:
-
+ ~AddressSanitizerRuntime() override;
+
static lldb::InstrumentationRuntimeSP
CreateInstance (const lldb::ProcessSP &process_sp);
@@ -36,29 +41,37 @@ public:
static lldb::InstrumentationRuntimeType
GetTypeStatic();
-
- virtual
- ~AddressSanitizerRuntime();
-
- virtual lldb_private::ConstString
- GetPluginName() { return GetPluginNameStatic(); }
+
+ lldb_private::ConstString
+ GetPluginName() override
+ {
+ return GetPluginNameStatic();
+ }
virtual lldb::InstrumentationRuntimeType
GetType() { return GetTypeStatic(); }
- virtual uint32_t
- GetPluginVersion() { return 1; }
+ uint32_t
+ GetPluginVersion() override
+ {
+ return 1;
+ }
- virtual void
- ModulesDidLoad(lldb_private::ModuleList &module_list);
+ void
+ ModulesDidLoad(lldb_private::ModuleList &module_list) override;
- virtual bool
- IsActive();
+ bool
+ IsActive() override;
private:
-
AddressSanitizerRuntime(const lldb::ProcessSP &process_sp);
-
+
+ lldb::ProcessSP
+ GetProcessSP ()
+ {
+ return m_process_wp.lock();
+ }
+
void
Activate();
@@ -76,11 +89,10 @@ private:
bool m_is_active;
lldb::ModuleSP m_runtime_module;
- lldb::ProcessSP m_process;
+ lldb::ProcessWP m_process_wp;
lldb::user_id_t m_breakpoint_id;
-
};
} // namespace lldb_private
-#endif // liblldb_InstrumentationRuntime_h_
+#endif // liblldb_AddressSanitizerRuntime_h_
diff --git a/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
index 8e454e712fe8..143e44794057 100644
--- a/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
+++ b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
@@ -16,6 +16,7 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Target/Process.h"
@@ -27,6 +28,58 @@
using namespace lldb;
using namespace lldb_private;
+namespace {
+
+ PropertyDefinition
+ g_properties[] =
+ {
+ { "enable-jit-breakpoint", OptionValue::eTypeBoolean, true, true , nullptr, nullptr, "Enable breakpoint on __jit_debug_register_code." },
+ { nullptr , OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr }
+ };
+
+ enum
+ {
+ ePropertyEnableJITBreakpoint
+ };
+
+
+ class PluginProperties : public Properties
+ {
+ public:
+ static ConstString
+ GetSettingName()
+ {
+ return JITLoaderGDB::GetPluginNameStatic();
+ }
+
+ PluginProperties()
+ {
+ m_collection_sp.reset (new OptionValueProperties(GetSettingName()));
+ m_collection_sp->Initialize(g_properties);
+ }
+
+ bool
+ GetEnableJITBreakpoint() const
+ {
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr,
+ ePropertyEnableJITBreakpoint,
+ g_properties[ePropertyEnableJITBreakpoint].default_uint_value != 0);
+ }
+
+ };
+
+ typedef std::shared_ptr<PluginProperties> JITLoaderGDBPropertiesSP;
+
+ static const JITLoaderGDBPropertiesSP&
+ GetGlobalPluginProperties()
+ {
+ static const auto g_settings_sp(std::make_shared<PluginProperties>());
+ return g_settings_sp;
+ }
+
+} // anonymous namespace end
+
//------------------------------------------------------------------
// Debug Interface Structures
//------------------------------------------------------------------
@@ -37,7 +90,6 @@ typedef enum
JIT_UNREGISTER_FN
} jit_actions_t;
-#pragma pack(push, 4)
template <typename ptr_t>
struct jit_code_entry
{
@@ -54,7 +106,6 @@ struct jit_descriptor
ptr_t relevant_entry; // pointer
ptr_t first_entry; // pointer
};
-#pragma pack(pop)
JITLoaderGDB::JITLoaderGDB (lldb_private::Process *process) :
JITLoader(process),
@@ -70,6 +121,19 @@ JITLoaderGDB::~JITLoaderGDB ()
m_process->GetTarget().RemoveBreakpointByID (m_jit_break_id);
}
+void
+JITLoaderGDB::DebuggerInitialize(Debugger &debugger)
+{
+ if (!PluginManager::GetSettingForJITLoaderPlugin(debugger, PluginProperties::GetSettingName()))
+ {
+ const bool is_global_setting = true;
+ PluginManager::CreateSettingForJITLoaderPlugin(debugger,
+ GetGlobalPluginProperties()->GetValueProperties(),
+ ConstString ("Properties for the JIT LoaderGDB plug-in."),
+ is_global_setting);
+ }
+}
+
void JITLoaderGDB::DidAttach()
{
Target &target = m_process->GetTarget();
@@ -88,7 +152,7 @@ void
JITLoaderGDB::ModulesDidLoad(ModuleList &module_list)
{
if (!DidSetJITBreakpoint() && m_process->IsAlive())
- SetJITBreakpoint(module_list);
+ SetJITBreakpoint(module_list);
}
//------------------------------------------------------------------
@@ -97,11 +161,13 @@ JITLoaderGDB::ModulesDidLoad(ModuleList &module_list)
void
JITLoaderGDB::SetJITBreakpoint(lldb_private::ModuleList &module_list)
{
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));
+ if (!GetGlobalPluginProperties()->GetEnableJITBreakpoint())
+ return;
if ( DidSetJITBreakpoint() )
return;
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_JIT_LOADER));
if (log)
log->Printf("JITLoaderGDB::%s looking for JIT register hook",
__FUNCTION__);
@@ -407,7 +473,8 @@ JITLoaderGDB::Initialize()
{
PluginManager::RegisterPlugin (GetPluginNameStatic(),
GetPluginDescriptionStatic(),
- CreateInstance);
+ CreateInstance,
+ DebuggerInitialize);
}
void
diff --git a/source/Plugins/JITLoader/GDB/JITLoaderGDB.h b/source/Plugins/JITLoader/GDB/JITLoaderGDB.h
index bfa1721d3349..10bd989c328f 100644
--- a/source/Plugins/JITLoader/GDB/JITLoaderGDB.h
+++ b/source/Plugins/JITLoader/GDB/JITLoaderGDB.h
@@ -13,15 +13,19 @@
// C Includes
// C++ Includes
#include <map>
-#include <vector>
-#include <string>
+// Other libraries and framework includes
+// Project includes
#include "lldb/Target/JITLoader.h"
#include "lldb/Target/Process.h"
class JITLoaderGDB : public lldb_private::JITLoader
{
public:
+ JITLoaderGDB(lldb_private::Process *process);
+
+ ~JITLoaderGDB() override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
@@ -40,31 +44,29 @@ public:
static lldb::JITLoaderSP
CreateInstance (lldb_private::Process *process, bool force);
- JITLoaderGDB (lldb_private::Process *process);
-
- virtual
- ~JITLoaderGDB ();
+ static void
+ DebuggerInitialize(lldb_private::Debugger &debugger);
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
//------------------------------------------------------------------
// JITLoader interface
//------------------------------------------------------------------
- virtual void
- DidAttach ();
+ void
+ DidAttach() override;
- virtual void
- DidLaunch ();
+ void
+ DidLaunch() override;
- virtual void
- ModulesDidLoad (lldb_private::ModuleList &module_list);
+ void
+ ModulesDidLoad(lldb_private::ModuleList &module_list) override;
private:
lldb::addr_t
@@ -105,4 +107,4 @@ private:
};
-#endif
+#endif // liblldb_JITLoaderGDB_h_
diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
new file mode 100644
index 000000000000..a554aa57d58e
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -0,0 +1,792 @@
+//===-- CPlusPlusLanguage.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CPlusPlusLanguage.h"
+
+
+#include "llvm/ADT/StringRef.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/UniqueCStringMap.h"
+#include "lldb/DataFormatters/CXXFunctionPointer.h"
+#include "lldb/DataFormatters/DataVisualization.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/DataFormatters/VectorType.h"
+
+#include "CxxStringTypes.h"
+#include "LibCxx.h"
+#include "LibStdcpp.h"
+
+#include <cstring>
+#include <cctype>
+#include <functional>
+#include <mutex>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+void
+CPlusPlusLanguage::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "C++ Language",
+ CreateInstance);
+}
+
+void
+CPlusPlusLanguage::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+CPlusPlusLanguage::GetPluginNameStatic()
+{
+ static ConstString g_name("cplusplus");
+ return g_name;
+}
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+CPlusPlusLanguage::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+CPlusPlusLanguage::GetPluginVersion()
+{
+ return 1;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+Language *
+CPlusPlusLanguage::CreateInstance (lldb::LanguageType language)
+{
+ if (Language::LanguageIsCPlusPlus(language))
+ return new CPlusPlusLanguage();
+ return nullptr;
+}
+
+void
+CPlusPlusLanguage::MethodName::Clear()
+{
+ m_full.Clear();
+ m_basename = llvm::StringRef();
+ m_context = llvm::StringRef();
+ m_arguments = llvm::StringRef();
+ m_qualifiers = llvm::StringRef();
+ m_type = eTypeInvalid;
+ m_parsed = false;
+ m_parse_error = false;
+}
+
+bool
+ReverseFindMatchingChars (const llvm::StringRef &s,
+ const llvm::StringRef &left_right_chars,
+ size_t &left_pos,
+ size_t &right_pos,
+ size_t pos = llvm::StringRef::npos)
+{
+ assert (left_right_chars.size() == 2);
+ left_pos = llvm::StringRef::npos;
+ const char left_char = left_right_chars[0];
+ const char right_char = left_right_chars[1];
+ pos = s.find_last_of(left_right_chars, pos);
+ if (pos == llvm::StringRef::npos || s[pos] == left_char)
+ return false;
+ right_pos = pos;
+ uint32_t depth = 1;
+ while (pos > 0 && depth > 0)
+ {
+ pos = s.find_last_of(left_right_chars, pos);
+ if (pos == llvm::StringRef::npos)
+ return false;
+ if (s[pos] == left_char)
+ {
+ if (--depth == 0)
+ {
+ left_pos = pos;
+ return left_pos < right_pos;
+ }
+ }
+ else if (s[pos] == right_char)
+ {
+ ++depth;
+ }
+ }
+ return false;
+}
+
+static bool
+IsValidBasename(const llvm::StringRef& basename)
+{
+ // Check that the basename matches with the following regular expression or is an operator name:
+ // "^~?([A-Za-z_][A-Za-z_0-9]*)(<.*>)?$"
+ // We are using a hand written implementation because it is significantly more efficient then
+ // using the general purpose regular expression library.
+ size_t idx = 0;
+ if (basename.size() > 0 && basename[0] == '~')
+ idx = 1;
+
+ if (basename.size() <= idx)
+ return false; // Empty string or "~"
+
+ if (!std::isalpha(basename[idx]) && basename[idx] != '_')
+ return false; // First charater (after removing the possible '~'') isn't in [A-Za-z_]
+
+ // Read all characters matching [A-Za-z_0-9]
+ ++idx;
+ while (idx < basename.size())
+ {
+ if (!std::isalnum(basename[idx]) && basename[idx] != '_')
+ break;
+ ++idx;
+ }
+
+ // We processed all characters. It is a vaild basename.
+ if (idx == basename.size())
+ return true;
+
+ // Check for basename with template arguments
+ // TODO: Improve the quality of the validation with validating the template arguments
+ if (basename[idx] == '<' && basename.back() == '>')
+ return true;
+
+ // Check if the basename is a vaild C++ operator name
+ if (!basename.startswith("operator"))
+ return false;
+
+ static RegularExpression g_operator_regex("^(operator)( ?)([A-Za-z_][A-Za-z_0-9]*|\\(\\)|\\[\\]|[\\^<>=!\\/*+-]+)(<.*>)?(\\[\\])?$");
+ std::string basename_str(basename.str());
+ return g_operator_regex.Execute(basename_str.c_str(), nullptr);
+}
+
+void
+CPlusPlusLanguage::MethodName::Parse()
+{
+ if (!m_parsed && m_full)
+ {
+// ConstString mangled;
+// m_full.GetMangledCounterpart(mangled);
+// printf ("\n parsing = '%s'\n", m_full.GetCString());
+// if (mangled)
+// printf (" mangled = '%s'\n", mangled.GetCString());
+ m_parse_error = false;
+ m_parsed = true;
+ llvm::StringRef full (m_full.GetCString());
+
+ size_t arg_start, arg_end;
+ llvm::StringRef parens("()", 2);
+ if (ReverseFindMatchingChars (full, parens, arg_start, arg_end))
+ {
+ m_arguments = full.substr(arg_start, arg_end - arg_start + 1);
+ if (arg_end + 1 < full.size())
+ m_qualifiers = full.substr(arg_end + 1);
+ if (arg_start > 0)
+ {
+ size_t basename_end = arg_start;
+ size_t context_start = 0;
+ size_t context_end = llvm::StringRef::npos;
+ if (basename_end > 0 && full[basename_end-1] == '>')
+ {
+ // TODO: handle template junk...
+ // Templated function
+ size_t template_start, template_end;
+ llvm::StringRef lt_gt("<>", 2);
+ if (ReverseFindMatchingChars (full, lt_gt, template_start, template_end, basename_end))
+ {
+ // Check for templated functions that include return type like: 'void foo<Int>()'
+ context_start = full.rfind(' ', template_start);
+ if (context_start == llvm::StringRef::npos)
+ context_start = 0;
+
+ context_end = full.rfind(':', template_start);
+ if (context_end == llvm::StringRef::npos || context_end < context_start)
+ context_end = context_start;
+ }
+ else
+ {
+ context_end = full.rfind(':', basename_end);
+ }
+ }
+ else if (context_end == llvm::StringRef::npos)
+ {
+ context_end = full.rfind(':', basename_end);
+ }
+
+ if (context_end == llvm::StringRef::npos)
+ m_basename = full.substr(0, basename_end);
+ else
+ {
+ if (context_start < context_end)
+ m_context = full.substr(context_start, context_end - 1);
+ const size_t basename_begin = context_end + 1;
+ m_basename = full.substr(basename_begin, basename_end - basename_begin);
+ }
+ m_type = eTypeUnknownMethod;
+ }
+ else
+ {
+ m_parse_error = true;
+ return;
+ }
+
+ if (!IsValidBasename(m_basename))
+ {
+ // The C++ basename doesn't match our regular expressions so this can't
+ // be a valid C++ method, clear everything out and indicate an error
+ m_context = llvm::StringRef();
+ m_basename = llvm::StringRef();
+ m_arguments = llvm::StringRef();
+ m_qualifiers = llvm::StringRef();
+ m_parse_error = true;
+ }
+ }
+ else
+ {
+ m_parse_error = true;
+ }
+ }
+}
+
+llvm::StringRef
+CPlusPlusLanguage::MethodName::GetBasename ()
+{
+ if (!m_parsed)
+ Parse();
+ return m_basename;
+}
+
+llvm::StringRef
+CPlusPlusLanguage::MethodName::GetContext ()
+{
+ if (!m_parsed)
+ Parse();
+ return m_context;
+}
+
+llvm::StringRef
+CPlusPlusLanguage::MethodName::GetArguments ()
+{
+ if (!m_parsed)
+ Parse();
+ return m_arguments;
+}
+
+llvm::StringRef
+CPlusPlusLanguage::MethodName::GetQualifiers ()
+{
+ if (!m_parsed)
+ Parse();
+ return m_qualifiers;
+}
+
+bool
+CPlusPlusLanguage::IsCPPMangledName (const char *name)
+{
+ // FIXME, we should really run through all the known C++ Language plugins and ask each one if
+ // this is a C++ mangled name, but we can put that off till there is actually more than one
+ // we care about.
+
+ if (name && name[0] == '_' && name[1] == 'Z')
+ return true;
+ else
+ return false;
+}
+
+bool
+CPlusPlusLanguage::ExtractContextAndIdentifier (const char *name, llvm::StringRef &context, llvm::StringRef &identifier)
+{
+ static RegularExpression g_basename_regex("^(([A-Za-z_][A-Za-z_0-9]*::)*)([A-Za-z_][A-Za-z_0-9]*)$");
+ RegularExpression::Match match(4);
+ if (g_basename_regex.Execute (name, &match))
+ {
+ match.GetMatchAtIndex(name, 1, context);
+ match.GetMatchAtIndex(name, 3, identifier);
+ return true;
+ }
+ return false;
+}
+
+class CPPRuntimeEquivalents
+{
+public:
+ CPPRuntimeEquivalents ()
+ {
+
+ m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("basic_string<char>"));
+
+ // these two (with a prefixed std::) occur when c++stdlib string class occurs as a template argument in some STL container
+ m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("std::basic_string<char>"));
+
+ m_impl.Sort();
+ }
+
+ void
+ Add (ConstString& type_name,
+ ConstString& type_equivalent)
+ {
+ m_impl.Insert(type_name.AsCString(), type_equivalent);
+ }
+
+ uint32_t
+ FindExactMatches (ConstString& type_name,
+ std::vector<ConstString>& equivalents)
+ {
+
+ uint32_t count = 0;
+
+ for (ImplData match = m_impl.FindFirstValueForName(type_name.AsCString());
+ match != NULL;
+ match = m_impl.FindNextValueForName(match))
+ {
+ equivalents.push_back(match->value);
+ count++;
+ }
+
+ return count;
+ }
+
+ // partial matches can occur when a name with equivalents is a template argument.
+ // e.g. we may have "class Foo" be a match for "struct Bar". if we have a typename
+ // such as "class Templatized<class Foo, Anything>" we want this to be replaced with
+ // "class Templatized<struct Bar, Anything>". Since partial matching is time consuming
+ // once we get a partial match, we add it to the exact matches list for faster retrieval
+ uint32_t
+ FindPartialMatches (ConstString& type_name,
+ std::vector<ConstString>& equivalents)
+ {
+
+ uint32_t count = 0;
+
+ const char* type_name_cstr = type_name.AsCString();
+
+ size_t items_count = m_impl.GetSize();
+
+ for (size_t item = 0; item < items_count; item++)
+ {
+ const char* key_cstr = m_impl.GetCStringAtIndex(item);
+ if ( strstr(type_name_cstr,key_cstr) )
+ {
+ count += AppendReplacements(type_name_cstr,
+ key_cstr,
+ equivalents);
+ }
+ }
+
+ return count;
+
+ }
+
+private:
+
+ std::string& replace (std::string& target,
+ std::string& pattern,
+ std::string& with)
+ {
+ size_t pos;
+ size_t pattern_len = pattern.size();
+
+ while ( (pos = target.find(pattern)) != std::string::npos )
+ target.replace(pos, pattern_len, with);
+
+ return target;
+ }
+
+ uint32_t
+ AppendReplacements (const char* original,
+ const char *matching_key,
+ std::vector<ConstString>& equivalents)
+ {
+
+ std::string matching_key_str(matching_key);
+ ConstString original_const(original);
+
+ uint32_t count = 0;
+
+ for (ImplData match = m_impl.FindFirstValueForName(matching_key);
+ match != NULL;
+ match = m_impl.FindNextValueForName(match))
+ {
+ std::string target(original);
+ std::string equiv_class(match->value.AsCString());
+
+ replace (target, matching_key_str, equiv_class);
+
+ ConstString target_const(target.c_str());
+
+// you will most probably want to leave this off since it might make this map grow indefinitely
+#ifdef ENABLE_CPP_EQUIVALENTS_MAP_TO_GROW
+ Add(original_const, target_const);
+#endif
+ equivalents.push_back(target_const);
+
+ count++;
+ }
+
+ return count;
+ }
+
+ typedef UniqueCStringMap<ConstString> Impl;
+ typedef const Impl::Entry* ImplData;
+ Impl m_impl;
+};
+
+static CPPRuntimeEquivalents&
+GetEquivalentsMap ()
+{
+ static CPPRuntimeEquivalents g_equivalents_map;
+ return g_equivalents_map;
+}
+
+
+uint32_t
+CPlusPlusLanguage::FindEquivalentNames(ConstString type_name, std::vector<ConstString>& equivalents)
+{
+ uint32_t count = GetEquivalentsMap().FindExactMatches(type_name, equivalents);
+
+ bool might_have_partials=
+ ( count == 0 ) // if we have a full name match just use it
+ && (strchr(type_name.AsCString(), '<') != NULL // we should only have partial matches when templates are involved, check that we have
+ && strchr(type_name.AsCString(), '>') != NULL); // angle brackets in the type_name before trying to scan for partial matches
+
+ if ( might_have_partials )
+ count = GetEquivalentsMap().FindPartialMatches(type_name, equivalents);
+
+ return count;
+}
+
+static void
+LoadLibCxxFormatters (lldb::TypeCategoryImplSP cpp_category_sp)
+{
+ if (!cpp_category_sp)
+ return;
+
+ TypeSummaryImpl::Flags stl_summary_flags;
+ stl_summary_flags.SetCascades(true)
+ .SetSkipPointers(false)
+ .SetSkipReferences(false)
+ .SetDontShowChildren(true)
+ .SetDontShowValue(true)
+ .SetShowMembersOneLiner(false)
+ .SetHideItemNames(false);
+
+#ifndef LLDB_DISABLE_PYTHON
+ lldb::TypeSummaryImplSP std_string_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags, lldb_private::formatters::LibcxxStringSummaryProvider, "std::string summary provider"));
+ lldb::TypeSummaryImplSP std_wstring_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags, lldb_private::formatters::LibcxxWStringSummaryProvider, "std::wstring summary provider"));
+
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::string"),
+ std_string_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >"),
+ std_string_summary_sp);
+
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::wstring"),
+ std_wstring_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >"),
+ std_wstring_summary_sp);
+
+ SyntheticChildren::Flags stl_synth_flags;
+ stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
+
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator, "libc++ std::vector synthetic children", ConstString("^std::__1::vector<.+>(( )?&)?$"), stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator, "libc++ std::list synthetic children", ConstString("^std::__1::list<.+>(( )?&)?$"), stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::map synthetic children", ConstString("^std::__1::map<.+> >(( )?&)?$"), stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<std::__1::allocator<bool> >"), stl_synth_flags);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_synth_flags);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::set synthetic children", ConstString("^std::__1::set<.+> >(( )?&)?$"), stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multiset synthetic children", ConstString("^std::__1::multiset<.+> >(( )?&)?$"), stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multimap synthetic children", ConstString("^std::__1::multimap<.+> >(( )?&)?$"), stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator, "libc++ std::unordered containers synthetic children", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator, "libc++ std::initializer_list synthetic children", ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags, true);
+
+ cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)deque<.+>(( )?&)?$")),
+ SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
+ "lldb.formatters.cpp.libcxx.stddeque_SynthProvider")));
+
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator, "shared_ptr synthetic children", ConstString("^(std::__1::)shared_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator, "weak_ptr synthetic children", ConstString("^(std::__1::)weak_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
+
+ stl_summary_flags.SetDontShowChildren(false);stl_summary_flags.SetSkipPointers(false);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_synth_flags);
+
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector summary provider", ConstString("^std::__1::vector<.+>(( )?&)?$"), stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::list summary provider", ConstString("^std::__1::list<.+>(( )?&)?$"), stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::map summary provider", ConstString("^std::__1::map<.+>(( )?&)?$"), stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::deque summary provider", ConstString("^std::__1::deque<.+>(( )?&)?$"), stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<std::__1::allocator<bool> >"), stl_summary_flags);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_summary_flags);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::set summary provider", ConstString("^std::__1::set<.+>(( )?&)?$"), stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multiset summary provider", ConstString("^std::__1::multiset<.+>(( )?&)?$"), stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multimap summary provider", ConstString("^std::__1::multimap<.+>(( )?&)?$"), stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::unordered containers summary provider", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_summary_flags, true);
+
+ stl_summary_flags.SetSkipPointers(true);
+
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxSmartPointerSummaryProvider, "libc++ std::shared_ptr summary provider", ConstString("^std::__1::shared_ptr<.+>(( )?&)?$"), stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxSmartPointerSummaryProvider, "libc++ std::weak_ptr summary provider", ConstString("^std::__1::weak_ptr<.+>(( )?&)?$"), stl_summary_flags, true);
+
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^std::__1::__wrap_iter<.+>$"), stl_synth_flags, true);
+
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_summary_flags);
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::__1::__map_iterator<.+>$"), stl_synth_flags, true);
+
+ AddFilter(cpp_category_sp, {"__a_"}, "libc++ std::atomic filter", ConstString("^std::__1::atomic<.*>$"), stl_synth_flags, true);
+#endif
+}
+
+static void
+LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp)
+{
+ if (!cpp_category_sp)
+ return;
+
+ TypeSummaryImpl::Flags stl_summary_flags;
+ stl_summary_flags.SetCascades(true)
+ .SetSkipPointers(false)
+ .SetSkipReferences(false)
+ .SetDontShowChildren(true)
+ .SetDontShowValue(true)
+ .SetShowMembersOneLiner(false)
+ .SetHideItemNames(false);
+
+ lldb::TypeSummaryImplSP std_string_summary_sp(new StringSummaryFormat(stl_summary_flags,
+ "${var._M_dataplus._M_p}"));
+
+ lldb::TypeSummaryImplSP cxx11_string_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags,
+ LibStdcppStringSummaryProvider,
+ "libstdc++ c++11 std::string summary provider"));
+ lldb::TypeSummaryImplSP cxx11_wstring_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags,
+ LibStdcppWStringSummaryProvider,
+ "libstdc++ c++11 std::wstring summary provider"));
+
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::string"),
+ std_string_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char>"),
+ std_string_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char,std::char_traits<char>,std::allocator<char> >"),
+ std_string_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >"),
+ std_string_summary_sp);
+
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::string"),
+ cxx11_string_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >"),
+ cxx11_string_summary_sp);
+
+ // making sure we force-pick the summary for printing wstring (_M_p is a wchar_t*)
+ lldb::TypeSummaryImplSP std_wstring_summary_sp(new StringSummaryFormat(stl_summary_flags,
+ "${var._M_dataplus._M_p%S}"));
+
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::wstring"),
+ std_wstring_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t>"),
+ std_wstring_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >"),
+ std_wstring_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >"),
+ std_wstring_summary_sp);
+
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::wstring"),
+ cxx11_wstring_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >"),
+ cxx11_wstring_summary_sp);
+
+#ifndef LLDB_DISABLE_PYTHON
+
+ SyntheticChildren::Flags stl_synth_flags;
+ stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
+
+ cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")),
+ SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
+ "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider")));
+ cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")),
+ SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
+ "lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider")));
+ cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$")),
+ SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
+ "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));
+ stl_summary_flags.SetDontShowChildren(false);stl_summary_flags.SetSkipPointers(true);
+ cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")),
+ TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
+ "size=${svar%#}")));
+ cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")),
+ TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
+ "size=${svar%#}")));
+ cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$")),
+ TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
+ "size=${svar%#}")));
+
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true);
+
+ AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true);
+#endif
+}
+
+static void
+LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp)
+{
+ if (!cpp_category_sp)
+ return;
+
+ TypeSummaryImpl::Flags string_flags;
+ string_flags.SetCascades(true)
+ .SetSkipPointers(true)
+ .SetSkipReferences(false)
+ .SetDontShowChildren(true)
+ .SetDontShowValue(false)
+ .SetShowMembersOneLiner(false)
+ .SetHideItemNames(false);
+
+ TypeSummaryImpl::Flags string_array_flags;
+ string_array_flags.SetCascades(true)
+ .SetSkipPointers(true)
+ .SetSkipReferences(false)
+ .SetDontShowChildren(true)
+ .SetDontShowValue(true)
+ .SetShowMembersOneLiner(false)
+ .SetHideItemNames(false);
+
+#ifndef LLDB_DISABLE_PYTHON
+ // FIXME because of a bug in the FormattersContainer we need to add a summary for both X* and const X* (<rdar://problem/12717717>)
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "char16_t * summary provider", ConstString("char16_t *"), string_flags);
+ AddCXXSummary(cpp_category_sp,
+ lldb_private::formatters::Char16StringSummaryProvider,
+ "char16_t [] summary provider",
+ ConstString("char16_t \\[[0-9]+\\]"),
+ string_array_flags,
+ true);
+
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char32StringSummaryProvider, "char32_t * summary provider", ConstString("char32_t *"), string_flags);
+ AddCXXSummary(cpp_category_sp,
+ lldb_private::formatters::Char32StringSummaryProvider,
+ "char32_t [] summary provider",
+ ConstString("char32_t \\[[0-9]+\\]"),
+ string_array_flags,
+ true);
+
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider, "wchar_t * summary provider", ConstString("wchar_t *"), string_flags);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider, "wchar_t * summary provider", ConstString("wchar_t \\[[0-9]+\\]"), string_array_flags, true);
+
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "unichar * summary provider", ConstString("unichar *"), string_flags);
+
+ TypeSummaryImpl::Flags widechar_flags;
+ widechar_flags.SetDontShowValue(true)
+ .SetSkipPointers(true)
+ .SetSkipReferences(false)
+ .SetCascades(true)
+ .SetDontShowChildren(true)
+ .SetHideItemNames(true)
+ .SetShowMembersOneLiner(false);
+
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16SummaryProvider, "char16_t summary provider", ConstString("char16_t"), widechar_flags);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char32SummaryProvider, "char32_t summary provider", ConstString("char32_t"), widechar_flags);
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharSummaryProvider, "wchar_t summary provider", ConstString("wchar_t"), widechar_flags);
+
+ AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16SummaryProvider, "unichar summary provider", ConstString("unichar"), widechar_flags);
+#endif
+}
+
+lldb::TypeCategoryImplSP
+CPlusPlusLanguage::GetFormatters ()
+{
+ static std::once_flag g_initialize;
+ static TypeCategoryImplSP g_category;
+
+ std::call_once(g_initialize, [this] () -> void {
+ DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
+ if (g_category)
+ {
+ LoadLibCxxFormatters(g_category);
+ LoadLibStdcppFormatters(g_category);
+ LoadSystemFormatters(g_category);
+ }
+ });
+ return g_category;
+}
+
+HardcodedFormatters::HardcodedSummaryFinder
+CPlusPlusLanguage::GetHardcodedSummaries ()
+{
+ static std::once_flag g_initialize;
+ static ConstString g_vectortypes("VectorTypes");
+ static HardcodedFormatters::HardcodedSummaryFinder g_formatters;
+
+ std::call_once(g_initialize, [] () -> void {
+ g_formatters.push_back(
+ [](lldb_private::ValueObject& valobj,
+ lldb::DynamicValueType,
+ FormatManager&) -> TypeSummaryImpl::SharedPointer {
+ static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags(), lldb_private::formatters::CXXFunctionPointerSummaryProvider, "Function pointer summary provider"));
+ if (valobj.GetCompilerType().IsFunctionPointerType())
+ {
+ return formatter_sp;
+ }
+ return nullptr;
+ });
+ g_formatters.push_back(
+ [](lldb_private::ValueObject& valobj,
+ lldb::DynamicValueType,
+ FormatManager& fmt_mgr) -> TypeSummaryImpl::SharedPointer {
+ static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags()
+ .SetCascades(true)
+ .SetDontShowChildren(true)
+ .SetHideItemNames(true)
+ .SetShowMembersOneLiner(true)
+ .SetSkipPointers(true)
+ .SetSkipReferences(false),
+ lldb_private::formatters::VectorTypeSummaryProvider,
+ "vector_type pointer summary provider"));
+ if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr))
+ {
+ if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
+ return formatter_sp;
+ }
+ return nullptr;
+ });
+ });
+
+ return g_formatters;
+}
+
+HardcodedFormatters::HardcodedSyntheticFinder
+CPlusPlusLanguage::GetHardcodedSynthetics ()
+{
+ static std::once_flag g_initialize;
+ static ConstString g_vectortypes("VectorTypes");
+ static HardcodedFormatters::HardcodedSyntheticFinder g_formatters;
+
+ std::call_once(g_initialize, [] () -> void {
+ g_formatters.push_back(
+ [](lldb_private::ValueObject& valobj,
+ lldb::DynamicValueType,
+ FormatManager& fmt_mgr) -> SyntheticChildren::SharedPointer {
+ static CXXSyntheticChildren::SharedPointer formatter_sp(new CXXSyntheticChildren(SyntheticChildren::Flags().SetCascades(true).SetSkipPointers(true).SetSkipReferences(true).SetNonCacheable(true),
+ "vector_type synthetic children",
+ lldb_private::formatters::VectorTypeSyntheticFrontEndCreator));
+ if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr))
+ {
+ if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
+ return formatter_sp;
+ }
+ return nullptr;
+ });
+ });
+
+ return g_formatters;
+}
+
diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
new file mode 100644
index 000000000000..1a8c0f6938a5
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
@@ -0,0 +1,186 @@
+//===-- CPlusPlusLanguage.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CPlusPlusLanguage_h_
+#define liblldb_CPlusPlusLanguage_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+#include "llvm/ADT/StringRef.h"
+
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Target/Language.h"
+
+namespace lldb_private {
+
+class CPlusPlusLanguage :
+ public Language
+{
+public:
+ class MethodName
+ {
+ public:
+ enum Type
+ {
+ eTypeInvalid,
+ eTypeUnknownMethod,
+ eTypeClassMethod,
+ eTypeInstanceMethod
+ };
+
+ MethodName () :
+ m_full(),
+ m_basename(),
+ m_context(),
+ m_arguments(),
+ m_qualifiers(),
+ m_type (eTypeInvalid),
+ m_parsed (false),
+ m_parse_error (false)
+ {
+ }
+
+ MethodName (const ConstString &s) :
+ m_full(s),
+ m_basename(),
+ m_context(),
+ m_arguments(),
+ m_qualifiers(),
+ m_type (eTypeInvalid),
+ m_parsed (false),
+ m_parse_error (false)
+ {
+ }
+
+ void
+ Clear();
+
+ bool
+ IsValid ()
+ {
+ if (!m_parsed)
+ Parse();
+ if (m_parse_error)
+ return false;
+ if (m_type == eTypeInvalid)
+ return false;
+ return (bool)m_full;
+ }
+
+ Type
+ GetType () const
+ {
+ return m_type;
+ }
+
+ const ConstString &
+ GetFullName () const
+ {
+ return m_full;
+ }
+
+ llvm::StringRef
+ GetBasename ();
+
+ llvm::StringRef
+ GetContext ();
+
+ llvm::StringRef
+ GetArguments ();
+
+ llvm::StringRef
+ GetQualifiers ();
+
+ protected:
+ void
+ Parse();
+
+ ConstString m_full; // Full name: "lldb::SBTarget::GetBreakpointAtIndex(unsigned int) const"
+ llvm::StringRef m_basename; // Basename: "GetBreakpointAtIndex"
+ llvm::StringRef m_context; // Decl context: "lldb::SBTarget"
+ llvm::StringRef m_arguments; // Arguments: "(unsigned int)"
+ llvm::StringRef m_qualifiers; // Qualifiers: "const"
+ Type m_type;
+ bool m_parsed;
+ bool m_parse_error;
+ };
+
+ CPlusPlusLanguage() = default;
+
+ ~CPlusPlusLanguage() override = default;
+
+ lldb::LanguageType
+ GetLanguageType () const override
+ {
+ return lldb::eLanguageTypeC_plus_plus;
+ }
+
+ lldb::TypeCategoryImplSP
+ GetFormatters () override;
+
+ HardcodedFormatters::HardcodedSummaryFinder
+ GetHardcodedSummaries () override;
+
+ HardcodedFormatters::HardcodedSyntheticFinder
+ GetHardcodedSynthetics () override;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb_private::Language *
+ CreateInstance (lldb::LanguageType language);
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ static bool
+ IsCPPMangledName(const char *name);
+
+ // Extract C++ context and identifier from a string using heuristic matching (as opposed to
+ // CPlusPlusLanguage::MethodName which has to have a fully qualified C++ name with parens and arguments.
+ // If the name is a lone C identifier (e.g. C) or a qualified C identifier (e.g. A::B::C) it will return true,
+ // and identifier will be the identifier (C and C respectively) and the context will be "" and "A::B::" respectively.
+ // If the name fails the heuristic matching for a qualified or unqualified C/C++ identifier, then it will return false
+ // and identifier and context will be unchanged.
+
+ static bool
+ ExtractContextAndIdentifier (const char *name, llvm::StringRef &context, llvm::StringRef &identifier);
+
+ // in some cases, compilers will output different names for one same type. when that happens, it might be impossible
+ // to construct SBType objects for a valid type, because the name that is available is not the same as the name that
+ // can be used as a search key in FindTypes(). the equivalents map here is meant to return possible alternative names
+ // for a type through which a search can be conducted. Currently, this is only enabled for C++ but can be extended
+ // to ObjC or other languages if necessary
+ static uint32_t
+ FindEquivalentNames(ConstString type_name, std::vector<ConstString>& equivalents);
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CPlusPlusLanguage_h_
diff --git a/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp b/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp
new file mode 100644
index 000000000000..7e8d9582a2b5
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp
@@ -0,0 +1,204 @@
+//===-- CXXStringTypes.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CxxStringTypes.h"
+
+#include "llvm/Support/ConvertUTF.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/SectionLoadList.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Utility/ProcessStructReader.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+
+#include <algorithm>
+
+#if __ANDROID_NDK__
+#include <sys/types.h>
+#endif
+
+#include "lldb/Host/Time.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+bool
+lldb_private::formatters::Char16StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj);
+ if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+ options.SetLocation(valobj_addr);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetPrefixToken("u");
+
+ if (!StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16>(options))
+ {
+ stream.Printf("Summary Unavailable");
+ return true;
+ }
+
+ return true;
+}
+
+bool
+lldb_private::formatters::Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj);
+ if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+ options.SetLocation(valobj_addr);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetPrefixToken("U");
+
+ if (!StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF32>(options))
+ {
+ stream.Printf("Summary Unavailable");
+ return true;
+ }
+
+ return true;
+}
+
+bool
+lldb_private::formatters::WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ lldb::addr_t valobj_addr = GetArrayAddressOrPointerValue(valobj);
+ if (valobj_addr == 0 || valobj_addr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ // Get a wchar_t basic type from the current type system
+ CompilerType wchar_compiler_type = valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar);
+
+ if (!wchar_compiler_type)
+ return false;
+
+ const uint32_t wchar_size = wchar_compiler_type.GetBitSize(nullptr); // Safe to pass NULL for exe_scope here
+
+ StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+ options.SetLocation(valobj_addr);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetPrefixToken("L");
+
+ switch (wchar_size)
+ {
+ case 8:
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options);
+ case 16:
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16>(options);
+ case 32:
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF32>(options);
+ default:
+ stream.Printf("size for wchar_t is not valid");
+ return true;
+ }
+ return true;
+}
+
+bool
+lldb_private::formatters::Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
+{
+ DataExtractor data;
+ Error error;
+ valobj.GetData(data, error);
+
+ if (error.Fail())
+ return false;
+
+ std::string value;
+ valobj.GetValueAsCString(lldb::eFormatUnicode16, value);
+ if (!value.empty())
+ stream.Printf("%s ", value.c_str());
+
+ StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
+ options.SetData(data);
+ options.SetStream(&stream);
+ options.SetPrefixToken("u");
+ options.SetQuote('\'');
+ options.SetSourceSize(1);
+ options.SetBinaryZeroIsTerminator(false);
+
+ return StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::UTF16>(options);
+}
+
+bool
+lldb_private::formatters::Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
+{
+ DataExtractor data;
+ Error error;
+ valobj.GetData(data, error);
+
+ if (error.Fail())
+ return false;
+
+ std::string value;
+ valobj.GetValueAsCString(lldb::eFormatUnicode32, value);
+ if (!value.empty())
+ stream.Printf("%s ", value.c_str());
+
+ StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
+ options.SetData(data);
+ options.SetStream(&stream);
+ options.SetPrefixToken("U");
+ options.SetQuote('\'');
+ options.SetSourceSize(1);
+ options.SetBinaryZeroIsTerminator(false);
+
+ return StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::UTF32>(options);
+}
+
+bool
+lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions&)
+{
+ DataExtractor data;
+ Error error;
+ valobj.GetData(data, error);
+
+ if (error.Fail())
+ return false;
+
+ StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
+ options.SetData(data);
+ options.SetStream(&stream);
+ options.SetPrefixToken("L");
+ options.SetQuote('\'');
+ options.SetSourceSize(1);
+ options.SetBinaryZeroIsTerminator(false);
+
+ return StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::UTF16>(options);
+}
diff --git a/source/Plugins/Language/CPlusPlus/CxxStringTypes.h b/source/Plugins/Language/CPlusPlus/CxxStringTypes.h
new file mode 100644
index 000000000000..bfb03bda7ee0
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/CxxStringTypes.h
@@ -0,0 +1,41 @@
+//===-- CxxStringTypes.h ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CxxStringTypes_h_
+#define liblldb_CxxStringTypes_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+
+namespace lldb_private {
+ namespace formatters
+ {
+ bool
+ Char16StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char16_t* and unichar*
+
+ bool
+ Char32StringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char32_t*
+
+ bool
+ WCharStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // wchar_t*
+
+ bool
+ Char16SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char16_t and unichar
+
+ bool
+ Char32SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // char32_t
+
+ bool
+ WCharSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // wchar_t
+
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_CxxStringTypes_h_
diff --git a/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/source/Plugins/Language/CPlusPlus/LibCxx.cpp
new file mode 100644
index 000000000000..950bd62c5c9f
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -0,0 +1,653 @@
+//===-- LibCxx.cpp ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibCxx.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/FormatEntity.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/VectorIterator.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+bool
+lldb_private::formatters::LibcxxSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
+ if (!valobj_sp)
+ return false;
+ ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true));
+ ValueObjectSP count_sp(valobj_sp->GetChildAtNamePath( {ConstString("__cntrl_"),ConstString("__shared_owners_")} ));
+ ValueObjectSP weakcount_sp(valobj_sp->GetChildAtNamePath( {ConstString("__cntrl_"),ConstString("__shared_weak_owners_")} ));
+
+ if (!ptr_sp)
+ return false;
+
+ if (ptr_sp->GetValueAsUnsigned(0) == 0)
+ {
+ stream.Printf("nullptr");
+ return true;
+ }
+ else
+ {
+ bool print_pointee = false;
+ Error error;
+ ValueObjectSP pointee_sp = ptr_sp->Dereference(error);
+ if (pointee_sp && error.Success())
+ {
+ if (pointee_sp->DumpPrintableRepresentation(stream,
+ ValueObject::eValueObjectRepresentationStyleSummary,
+ lldb::eFormatInvalid,
+ ValueObject::ePrintableRepresentationSpecialCasesDisable,
+ false))
+ print_pointee = true;
+ }
+ if (!print_pointee)
+ stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0));
+ }
+
+ if (count_sp)
+ stream.Printf(" strong=%" PRIu64, 1+count_sp->GetValueAsUnsigned(0));
+
+ if (weakcount_sp)
+ stream.Printf(" weak=%" PRIu64, 1+weakcount_sp->GetValueAsUnsigned(0));
+
+ return true;
+}
+
+lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_bool_type(),
+m_exe_ctx_ref(),
+m_count(0),
+m_base_data_address(0),
+m_children()
+{
+ if (valobj_sp)
+ {
+ Update();
+ m_bool_type = valobj_sp->GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeBool);
+ }
+}
+
+size_t
+lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::CalculateNumChildren ()
+{
+ return m_count;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ auto iter = m_children.find(idx),
+ end = m_children.end();
+ if (iter != end)
+ return iter->second;
+ if (idx >= m_count)
+ return ValueObjectSP();
+ if (m_base_data_address == 0 || m_count == 0)
+ return ValueObjectSP();
+ if (!m_bool_type)
+ return ValueObjectSP();
+ size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
+ size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
+ lldb::addr_t byte_location = m_base_data_address + byte_idx;
+ ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
+ if (!process_sp)
+ return ValueObjectSP();
+ uint8_t byte = 0;
+ uint8_t mask = 0;
+ Error err;
+ size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
+ if (err.Fail() || bytes_read == 0)
+ return ValueObjectSP();
+ switch (bit_index)
+ {
+ case 0:
+ mask = 1; break;
+ case 1:
+ mask = 2; break;
+ case 2:
+ mask = 4; break;
+ case 3:
+ mask = 8; break;
+ case 4:
+ mask = 16; break;
+ case 5:
+ mask = 32; break;
+ case 6:
+ mask = 64; break;
+ case 7:
+ mask = 128; break;
+ default:
+ return ValueObjectSP();
+ }
+ bool bit_set = ((byte & mask) != 0);
+ DataBufferSP buffer_sp(new DataBufferHeap(m_bool_type.GetByteSize(nullptr),0));
+ if (bit_set && buffer_sp && buffer_sp->GetBytes())
+ *(buffer_sp->GetBytes()) = 1; // regardless of endianness, anything non-zero is true
+ StreamString name; name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ ValueObjectSP retval_sp(CreateValueObjectFromData(name.GetData(), DataExtractor(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()), m_exe_ctx_ref, m_bool_type));
+ if (retval_sp)
+ m_children[idx] = retval_sp;
+ return retval_sp;
+}
+
+/*(std::__1::vector<std::__1::allocator<bool> >) vBool = {
+ __begin_ = 0x00000001001000e0
+ __size_ = 56
+ __cap_alloc_ = {
+ std::__1::__libcpp_compressed_pair_imp<unsigned long, std::__1::allocator<unsigned long> > = {
+ __first_ = 1
+ }
+ }
+ }*/
+
+bool
+lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::Update()
+{
+ m_children.clear();
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ if (!valobj_sp)
+ return false;
+ m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+ ValueObjectSP size_sp(valobj_sp->GetChildMemberWithName(ConstString("__size_"), true));
+ if (!size_sp)
+ return false;
+ m_count = size_sp->GetValueAsUnsigned(0);
+ if (!m_count)
+ return true;
+ ValueObjectSP begin_sp(valobj_sp->GetChildMemberWithName(ConstString("__begin_"), true));
+ if (!begin_sp)
+ {
+ m_count = 0;
+ return false;
+ }
+ m_base_data_address = begin_sp->GetValueAsUnsigned(0);
+ if (!m_base_data_address)
+ {
+ m_count = 0;
+ return false;
+ }
+ return false;
+}
+
+bool
+lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+size_t
+lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ if (!m_count || !m_base_data_address)
+ return UINT32_MAX;
+ const char* item_name = name.GetCString();
+ uint32_t idx = ExtractIndexFromString(item_name);
+ if (idx < UINT32_MAX && idx >= CalculateNumChildren())
+ return UINT32_MAX;
+ return idx;
+}
+
+lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd ()
+{}
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ if (!valobj_sp)
+ return NULL;
+ return (new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp));
+}
+
+/*
+ (lldb) fr var ibeg --raw --ptr-depth 1
+ (std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::pair<int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::__tree_node<std::__1::pair<int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, void *> *, long> >) ibeg = {
+ __i_ = {
+ __ptr_ = 0x0000000100103870 {
+ std::__1::__tree_node_base<void *> = {
+ std::__1::__tree_end_node<std::__1::__tree_node_base<void *> *> = {
+ __left_ = 0x0000000000000000
+ }
+ __right_ = 0x0000000000000000
+ __parent_ = 0x00000001001038b0
+ __is_black_ = true
+ }
+ __value_ = {
+ first = 0
+ second = { std::string }
+ */
+
+lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_pair_ptr()
+{
+ if (valobj_sp)
+ Update();
+}
+
+bool
+lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update()
+{
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ if (!valobj_sp)
+ return false;
+
+ TargetSP target_sp(valobj_sp->GetTargetSP());
+
+ if (!target_sp)
+ return false;
+
+ if (!valobj_sp)
+ return false;
+
+ // this must be a ValueObject* because it is a child of the ValueObject we are producing children for
+ // it if were a ValueObjectSP, we would end up with a loop (iterator -> synthetic -> child -> parent == iterator)
+ // and that would in turn leak memory by never allowing the ValueObjects to die and free their memory
+ m_pair_ptr = valobj_sp->GetValueForExpressionPath(".__i_.__ptr_->__value_",
+ NULL,
+ NULL,
+ NULL,
+ ValueObject::GetValueForExpressionPathOptions().DontCheckDotVsArrowSyntax().SetSyntheticChildrenTraversal(ValueObject::GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None),
+ NULL).get();
+
+ return false;
+}
+
+size_t
+lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::CalculateNumChildren ()
+{
+ return 2;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ if (!m_pair_ptr)
+ return lldb::ValueObjectSP();
+ return m_pair_ptr->GetChildAtIndex(idx, true);
+}
+
+bool
+lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+size_t
+lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ if (name == ConstString("first"))
+ return 0;
+ if (name == ConstString("second"))
+ return 1;
+ return UINT32_MAX;
+}
+
+lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::~LibCxxMapIteratorSyntheticFrontEnd ()
+{
+ // this will be deleted when its parent dies (since it's a child object)
+ //delete m_pair_ptr;
+}
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ if (!valobj_sp)
+ return NULL;
+ return (new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp));
+}
+
+/*
+ (lldb) fr var ibeg --raw --ptr-depth 1 -T
+ (std::__1::__wrap_iter<int *>) ibeg = {
+ (std::__1::__wrap_iter<int *>::iterator_type) __i = 0x00000001001037a0 {
+ (int) *__i = 1
+ }
+ }
+*/
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ static ConstString g_item_name;
+ if (!g_item_name)
+ g_item_name.SetCString("__i");
+ if (!valobj_sp)
+ return NULL;
+ return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name));
+}
+
+lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::LibcxxSharedPtrSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_cntrl(NULL),
+m_count_sp(),
+m_weak_count_sp(),
+m_ptr_size(0),
+m_byte_order(lldb::eByteOrderInvalid)
+{
+ if (valobj_sp)
+ Update();
+}
+
+size_t
+lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::CalculateNumChildren ()
+{
+ return (m_cntrl ? 1 : 0);
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ if (!m_cntrl)
+ return lldb::ValueObjectSP();
+
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ if (!valobj_sp)
+ return lldb::ValueObjectSP();
+
+ if (idx == 0)
+ return valobj_sp->GetChildMemberWithName(ConstString("__ptr_"), true);
+
+ if (idx > 2)
+ return lldb::ValueObjectSP();
+
+ if (idx == 1)
+ {
+ if (!m_count_sp)
+ {
+ ValueObjectSP shared_owners_sp(m_cntrl->GetChildMemberWithName(ConstString("__shared_owners_"),true));
+ if (!shared_owners_sp)
+ return lldb::ValueObjectSP();
+ uint64_t count = 1 + shared_owners_sp->GetValueAsUnsigned(0);
+ DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
+ m_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_owners_sp->GetCompilerType());
+ }
+ return m_count_sp;
+ }
+ else /* if (idx == 2) */
+ {
+ if (!m_weak_count_sp)
+ {
+ ValueObjectSP shared_weak_owners_sp(m_cntrl->GetChildMemberWithName(ConstString("__shared_weak_owners_"),true));
+ if (!shared_weak_owners_sp)
+ return lldb::ValueObjectSP();
+ uint64_t count = 1 + shared_weak_owners_sp->GetValueAsUnsigned(0);
+ DataExtractor data(&count, 8, m_byte_order, m_ptr_size);
+ m_weak_count_sp = CreateValueObjectFromData("count", data, valobj_sp->GetExecutionContextRef(), shared_weak_owners_sp->GetCompilerType());
+ }
+ return m_weak_count_sp;
+ }
+}
+
+bool
+lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update()
+{
+ m_count_sp.reset();
+ m_weak_count_sp.reset();
+ m_cntrl = NULL;
+
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ if (!valobj_sp)
+ return false;
+
+ TargetSP target_sp(valobj_sp->GetTargetSP());
+ if (!target_sp)
+ return false;
+
+ m_byte_order = target_sp->GetArchitecture().GetByteOrder();
+ m_ptr_size = target_sp->GetArchitecture().GetAddressByteSize();
+
+ lldb::ValueObjectSP cntrl_sp(valobj_sp->GetChildMemberWithName(ConstString("__cntrl_"),true));
+
+ m_cntrl = cntrl_sp.get(); // need to store the raw pointer to avoid a circular dependency
+ return false;
+}
+
+bool
+lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+size_t
+lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ if (name == ConstString("__ptr_"))
+ return 0;
+ if (name == ConstString("count"))
+ return 1;
+ if (name == ConstString("weak_count"))
+ return 2;
+ return UINT32_MAX;
+}
+
+lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::~LibcxxSharedPtrSyntheticFrontEnd ()
+{}
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ if (!valobj_sp)
+ return NULL;
+ return (new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp));
+}
+
+bool
+lldb_private::formatters::LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ if (valobj.IsPointerType())
+ {
+ uint64_t value = valobj.GetValueAsUnsigned(0);
+ if (!value)
+ return false;
+ stream.Printf("0x%016" PRIx64 " ", value);
+ }
+ return FormatEntity::FormatStringRef("size=${svar%#}", stream, NULL, NULL, NULL, &valobj, false, false);
+}
+
+// the field layout in a libc++ string (cap, side, data or data, size, cap)
+enum LibcxxStringLayoutMode
+{
+ eLibcxxStringLayoutModeCSD = 0,
+ eLibcxxStringLayoutModeDSC = 1,
+ eLibcxxStringLayoutModeInvalid = 0xffff
+};
+
+// this function abstracts away the layout and mode details of a libc++ string
+// and returns the address of the data and the size ready for callers to consume
+static bool
+ExtractLibcxxStringInfo (ValueObject& valobj,
+ ValueObjectSP &location_sp,
+ uint64_t& size)
+{
+ ValueObjectSP D(valobj.GetChildAtIndexPath({0,0,0,0}));
+ if (!D)
+ return false;
+
+ ValueObjectSP layout_decider(D->GetChildAtIndexPath({0,0}));
+
+ // this child should exist
+ if (!layout_decider)
+ return false;
+
+ ConstString g_data_name("__data_");
+ ConstString g_size_name("__size_");
+ bool short_mode = false; // this means the string is in short-mode and the data is stored inline
+ LibcxxStringLayoutMode layout = (layout_decider->GetName() == g_data_name) ? eLibcxxStringLayoutModeDSC : eLibcxxStringLayoutModeCSD;
+ uint64_t size_mode_value = 0;
+
+ if (layout == eLibcxxStringLayoutModeDSC)
+ {
+ ValueObjectSP size_mode(D->GetChildAtIndexPath({1,1,0}));
+ if (!size_mode)
+ return false;
+
+ if (size_mode->GetName() != g_size_name)
+ {
+ // we are hitting the padding structure, move along
+ size_mode = D->GetChildAtIndexPath({1,1,1});
+ if (!size_mode)
+ return false;
+ }
+
+ size_mode_value = (size_mode->GetValueAsUnsigned(0));
+ short_mode = ((size_mode_value & 0x80) == 0);
+ }
+ else
+ {
+ ValueObjectSP size_mode(D->GetChildAtIndexPath({1,0,0}));
+ if (!size_mode)
+ return false;
+
+ size_mode_value = (size_mode->GetValueAsUnsigned(0));
+ short_mode = ((size_mode_value & 1) == 0);
+ }
+
+ if (short_mode)
+ {
+ ValueObjectSP s(D->GetChildAtIndex(1, true));
+ if (!s)
+ return false;
+ location_sp = s->GetChildAtIndex((layout == eLibcxxStringLayoutModeDSC) ? 0 : 1, true);
+ size = (layout == eLibcxxStringLayoutModeDSC) ? size_mode_value : ((size_mode_value >> 1) % 256);
+ return (location_sp.get() != nullptr);
+ }
+ else
+ {
+ ValueObjectSP l(D->GetChildAtIndex(0, true));
+ if (!l)
+ return false;
+ // we can use the layout_decider object as the data pointer
+ location_sp = (layout == eLibcxxStringLayoutModeDSC) ? layout_decider : l->GetChildAtIndex(2, true);
+ ValueObjectSP size_vo(l->GetChildAtIndex(1, true));
+ if (!size_vo || !location_sp)
+ return false;
+ size = size_vo->GetValueAsUnsigned(0);
+ return true;
+ }
+}
+
+bool
+lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
+{
+ uint64_t size = 0;
+ ValueObjectSP location_sp((ValueObject*)nullptr);
+ if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
+ return false;
+ if (size == 0)
+ {
+ stream.Printf("L\"\"");
+ return true;
+ }
+ if (!location_sp)
+ return false;
+
+ DataExtractor extractor;
+
+ StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
+
+ if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped)
+ {
+ const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
+ if (size > max_size)
+ {
+ size = max_size;
+ options.SetIsTruncated(true);
+ }
+ }
+ 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);
+
+ options.SetData(extractor);
+ options.SetStream(&stream);
+ options.SetPrefixToken("L");
+ options.SetQuote('"');
+ options.SetSourceSize(size);
+ options.SetBinaryZeroIsTerminator(false);
+
+ switch (wchar_t_size)
+ {
+ case 1:
+ StringPrinter::ReadBufferAndDumpToStream<lldb_private::formatters::StringPrinter::StringElementType::UTF8>(options);
+ break;
+
+ case 2:
+ lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStream<lldb_private::formatters::StringPrinter::StringElementType::UTF16>(options);
+ break;
+
+ case 4:
+ lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStream<lldb_private::formatters::StringPrinter::StringElementType::UTF32>(options);
+ break;
+
+ default:
+ stream.Printf("size for wchar_t is not valid");
+ return true;
+ }
+
+ return true;
+}
+
+bool
+lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
+{
+ uint64_t size = 0;
+ ValueObjectSP location_sp((ValueObject*)nullptr);
+
+ if (!ExtractLibcxxStringInfo(valobj, location_sp, size))
+ return false;
+
+ if (size == 0)
+ {
+ stream.Printf("\"\"");
+ return true;
+ }
+
+ if (!location_sp)
+ return false;
+
+ StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
+
+ DataExtractor extractor;
+ if (summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryCapped)
+ {
+ const auto max_size = valobj.GetTargetSP()->GetMaximumSizeOfStringSummary();
+ if (size > max_size)
+ {
+ size = max_size;
+ options.SetIsTruncated(true);
+ }
+ }
+ location_sp->GetPointeeData(extractor, 0, size);
+
+ options.SetData(extractor);
+ options.SetStream(&stream);
+ options.SetPrefixToken(0);
+ options.SetQuote('"');
+ options.SetSourceSize(size);
+ options.SetBinaryZeroIsTerminator(false);
+ StringPrinter::ReadBufferAndDumpToStream<StringPrinter::StringElementType::ASCII>(options);
+
+ return true;
+}
diff --git a/source/Plugins/Language/CPlusPlus/LibCxx.h b/source/Plugins/Language/CPlusPlus/LibCxx.h
new file mode 100644
index 000000000000..ae00bc0ade34
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -0,0 +1,141 @@
+//===-- LibCxx.h ---------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_LibCxx_h_
+#define liblldb_LibCxx_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+
+namespace lldb_private {
+ namespace formatters
+ {
+
+ bool
+ LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::string
+
+ bool
+ LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::wstring
+
+ bool
+ LibcxxSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libc++ std::shared_ptr<> and std::weak_ptr<>
+
+ class LibcxxVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ LibcxxVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ ~LibcxxVectorBoolSyntheticFrontEnd() override;
+
+ private:
+ CompilerType m_bool_type;
+ ExecutionContextRef m_exe_ctx_ref;
+ uint64_t m_count;
+ lldb::addr_t m_base_data_address;
+ std::map<size_t,lldb::ValueObjectSP> m_children;
+ };
+
+ SyntheticChildrenFrontEnd* LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ bool
+ LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ class LibCxxMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ ~LibCxxMapIteratorSyntheticFrontEnd() override;
+
+ private:
+ ValueObject *m_pair_ptr;
+ };
+
+ SyntheticChildrenFrontEnd* LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ SyntheticChildrenFrontEnd* LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ class LibcxxSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ LibcxxSharedPtrSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ ~LibcxxSharedPtrSyntheticFrontEnd() override;
+
+ private:
+ ValueObject* m_cntrl;
+ lldb::ValueObjectSP m_count_sp;
+ lldb::ValueObjectSP m_weak_count_sp;
+ uint8_t m_ptr_size;
+ lldb::ByteOrder m_byte_order;
+ };
+
+ SyntheticChildrenFrontEnd* LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ SyntheticChildrenFrontEnd* LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ SyntheticChildrenFrontEnd* LibcxxStdListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ SyntheticChildrenFrontEnd* LibcxxStdMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ SyntheticChildrenFrontEnd* LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ SyntheticChildrenFrontEnd* LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_LibCxx_h_
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp b/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp
new file mode 100644
index 000000000000..9970d49dac62
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp
@@ -0,0 +1,147 @@
+//===-- LibCxxInitializerList.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "LibCxx.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace lldb_private {
+ namespace formatters {
+ class LibcxxInitializerListSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ LibcxxInitializerListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~LibcxxInitializerListSyntheticFrontEnd() override;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ private:
+ ValueObject* m_start;
+ CompilerType m_element_type;
+ uint32_t m_element_size;
+ size_t m_num_elements;
+ std::map<size_t,lldb::ValueObjectSP> m_children;
+ };
+ } // namespace formatters
+} // namespace lldb_private
+
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::LibcxxInitializerListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_start(NULL),
+m_element_type(),
+m_element_size(0),
+m_num_elements(0),
+m_children()
+{
+ if (valobj_sp)
+ Update();
+}
+
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::~LibcxxInitializerListSyntheticFrontEnd()
+{
+ // this needs to stay around because it's a child object who will follow its parent's life cycle
+ // delete m_start;
+}
+
+size_t
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::CalculateNumChildren ()
+{
+ static ConstString g___size_("__size_");
+ m_num_elements = 0;
+ ValueObjectSP size_sp(m_backend.GetChildMemberWithName(g___size_, true));
+ if (size_sp)
+ m_num_elements = size_sp->GetValueAsUnsigned(0);
+ return m_num_elements;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ if (!m_start)
+ return lldb::ValueObjectSP();
+
+ auto cached = m_children.find(idx);
+ if (cached != m_children.end())
+ return cached->second;
+
+ uint64_t offset = idx * m_element_size;
+ offset = offset + m_start->GetValueAsUnsigned(0);
+ StreamString name;
+ name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ ValueObjectSP child_sp = CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type);
+ m_children[idx] = child_sp;
+ return child_sp;
+}
+
+bool
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::Update()
+{
+ static ConstString g___begin_("__begin_");
+
+ m_start = nullptr;
+ m_num_elements = 0;
+ m_children.clear();
+ lldb::TemplateArgumentKind kind;
+ m_element_type = m_backend.GetCompilerType().GetTemplateArgument(0, kind);
+ if (kind != lldb::eTemplateArgumentKindType || false == m_element_type.IsValid())
+ return false;
+
+ m_element_size = m_element_type.GetByteSize(nullptr);
+
+ if (m_element_size > 0)
+ m_start = m_backend.GetChildMemberWithName(g___begin_,true).get(); // store raw pointers or end up with a circular dependency
+
+ return false;
+}
+
+bool
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+size_t
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ if (!m_start)
+ return UINT32_MAX;
+ return ExtractIndexFromString(name.GetCString());
+}
+
+lldb_private::SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ if (!valobj_sp)
+ return NULL;
+ return (new LibcxxInitializerListSyntheticFrontEnd(valobj_sp));
+}
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxList.cpp b/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
new file mode 100644
index 000000000000..f86f968ea857
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
@@ -0,0 +1,414 @@
+//===-- LibCxxList.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "LibCxx.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace {
+
+ class ListEntry
+ {
+ public:
+ ListEntry() = default;
+ ListEntry (ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
+ ListEntry (const ListEntry& rhs) : m_entry_sp(rhs.m_entry_sp) {}
+ ListEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}
+
+ ListEntry
+ next ()
+ {
+ if (!m_entry_sp)
+ return ListEntry();
+ return ListEntry(m_entry_sp->GetChildAtIndexPath({0,1}));
+ }
+
+ ListEntry
+ prev ()
+ {
+ if (!m_entry_sp)
+ return ListEntry();
+ return ListEntry(m_entry_sp->GetChildAtIndexPath({0,0}));
+ }
+
+ uint64_t
+ value () const
+ {
+ if (!m_entry_sp)
+ return 0;
+ return m_entry_sp->GetValueAsUnsigned(0);
+ }
+
+ bool
+ null()
+ {
+ return (value() == 0);
+ }
+
+ explicit operator bool ()
+ {
+ return GetEntry().get() != nullptr && null() == false;
+ }
+
+ ValueObjectSP
+ GetEntry ()
+ {
+ return m_entry_sp;
+ }
+
+ void
+ SetEntry (ValueObjectSP entry)
+ {
+ m_entry_sp = entry;
+ }
+
+ bool
+ operator == (const ListEntry& rhs) const
+ {
+ return value() == rhs.value();
+ }
+
+ bool
+ operator != (const ListEntry& rhs) const
+ {
+ return !(*this == rhs);
+ }
+
+ private:
+ ValueObjectSP m_entry_sp;
+ };
+
+ class ListIterator
+ {
+ public:
+ ListIterator() = default;
+ ListIterator (ListEntry entry) : m_entry(entry) {}
+ ListIterator (ValueObjectSP entry) : m_entry(entry) {}
+ ListIterator (const ListIterator& rhs) : m_entry(rhs.m_entry) {}
+ ListIterator (ValueObject* entry) : m_entry(entry) {}
+
+ ValueObjectSP
+ value ()
+ {
+ return m_entry.GetEntry();
+ }
+
+ ValueObjectSP
+ advance (size_t count)
+ {
+ if (count == 0)
+ return m_entry.GetEntry();
+ if (count == 1)
+ {
+ next ();
+ return m_entry.GetEntry();
+ }
+ while (count > 0)
+ {
+ next ();
+ count--;
+ if (m_entry.null())
+ return lldb::ValueObjectSP();
+ }
+ return m_entry.GetEntry();
+ }
+
+ bool
+ operator == (const ListIterator& rhs) const
+ {
+ return (rhs.m_entry == m_entry);
+ }
+
+ protected:
+ void
+ next ()
+ {
+ m_entry = m_entry.next();
+ }
+
+ void
+ prev ()
+ {
+ m_entry = m_entry.prev();
+ }
+
+ private:
+ ListEntry m_entry;
+ };
+
+} // end anonymous namespace
+
+namespace lldb_private {
+ namespace formatters {
+ class LibcxxStdListSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~LibcxxStdListSyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ private:
+ bool
+ HasLoop(size_t count);
+
+ size_t m_list_capping_size;
+ static const bool g_use_loop_detect = true;
+
+ size_t m_loop_detected; // The number of elements that have had loop detection run over them.
+ ListEntry m_slow_runner; // Used for loop detection
+ ListEntry m_fast_runner; // Used for loop detection
+
+ lldb::addr_t m_node_address;
+ ValueObject* m_head;
+ ValueObject* m_tail;
+ CompilerType m_element_type;
+ size_t m_count;
+ std::map<size_t,lldb::ValueObjectSP> m_children;
+ std::map<size_t, ListIterator> m_iterators;
+ };
+ } // namespace formatters
+} // namespace lldb_private
+
+lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_list_capping_size(0),
+m_loop_detected(0),
+m_node_address(),
+m_head(NULL),
+m_tail(NULL),
+m_element_type(),
+m_count(UINT32_MAX),
+m_children(),
+m_iterators()
+{
+ if (valobj_sp)
+ Update();
+}
+
+bool
+lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop(size_t count)
+{
+ if (g_use_loop_detect == false)
+ return false;
+ // don't bother checking for a loop if we won't actually need to jump nodes
+ if (m_count < 2)
+ return false;
+
+ if (m_loop_detected == 0)
+ {
+ // This is the first time we are being run (after the last update). Set up the loop
+ // invariant for the first element.
+ m_slow_runner = ListEntry(m_head).next();
+ m_fast_runner = m_slow_runner.next();
+ m_loop_detected = 1;
+ }
+
+ // Loop invariant:
+ // Loop detection has been run over the first m_loop_detected elements. If m_slow_runner ==
+ // m_fast_runner then the loop has been detected after m_loop_detected elements.
+ const size_t steps_to_run = std::min(count,m_count);
+ while (m_loop_detected < steps_to_run
+ && m_slow_runner
+ && m_fast_runner
+ && m_slow_runner != m_fast_runner) {
+
+ m_slow_runner = m_slow_runner.next();
+ m_fast_runner = m_fast_runner.next().next();
+ m_loop_detected++;
+ }
+ if (count <= m_loop_detected)
+ return false; // No loop in the first m_loop_detected elements.
+ if (!m_slow_runner || !m_fast_runner)
+ return false; // Reached the end of the list. Definitely no loops.
+ return m_slow_runner == m_fast_runner;
+}
+
+size_t
+lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::CalculateNumChildren ()
+{
+ if (m_count != UINT32_MAX)
+ return m_count;
+ if (!m_head || !m_tail || m_node_address == 0)
+ return 0;
+ ValueObjectSP size_alloc(m_backend.GetChildMemberWithName(ConstString("__size_alloc_"), true));
+ if (size_alloc)
+ {
+ ValueObjectSP first(size_alloc->GetChildMemberWithName(ConstString("__first_"), true));
+ if (first)
+ {
+ m_count = first->GetValueAsUnsigned(UINT32_MAX);
+ }
+ }
+ if (m_count != UINT32_MAX)
+ {
+ return m_count;
+ }
+ else
+ {
+ uint64_t next_val = m_head->GetValueAsUnsigned(0);
+ uint64_t prev_val = m_tail->GetValueAsUnsigned(0);
+ if (next_val == 0 || prev_val == 0)
+ return 0;
+ if (next_val == m_node_address)
+ return 0;
+ if (next_val == prev_val)
+ return 1;
+ uint64_t size = 2;
+ ListEntry current(m_head);
+ while (current.next() && current.next().value() != m_node_address)
+ {
+ size++;
+ current = current.next();
+ if (size > m_list_capping_size)
+ break;
+ }
+ return m_count = (size-1);
+ }
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ if (idx >= CalculateNumChildren())
+ return lldb::ValueObjectSP();
+
+ if (!m_head || !m_tail || m_node_address == 0)
+ return lldb::ValueObjectSP();
+
+ auto cached = m_children.find(idx);
+ if (cached != m_children.end())
+ return cached->second;
+
+ if (HasLoop(idx+1))
+ return lldb::ValueObjectSP();
+
+ size_t actual_advance = idx;
+
+ ListIterator current(m_head);
+ if (idx > 0)
+ {
+ auto cached_iterator = m_iterators.find(idx-1);
+ if (cached_iterator != m_iterators.end())
+ {
+ current = cached_iterator->second;
+ actual_advance = 1;
+ }
+ }
+
+ ValueObjectSP current_sp(current.advance(actual_advance));
+ if (!current_sp)
+ return lldb::ValueObjectSP();
+
+ m_iterators[idx] = current;
+
+ current_sp = current_sp->GetChildAtIndex(1, true); // get the __value_ child
+ if (!current_sp)
+ return lldb::ValueObjectSP();
+ // we need to copy current_sp into a new object otherwise we will end up with all items named __value_
+ DataExtractor data;
+ Error error;
+ current_sp->GetData(data, error);
+ if (error.Fail())
+ return lldb::ValueObjectSP();
+
+ StreamString name;
+ name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ return (m_children[idx] = CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type));
+}
+
+bool
+lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::Update()
+{
+ m_children.clear();
+ m_iterators.clear();
+ m_head = m_tail = NULL;
+ m_node_address = 0;
+ m_count = UINT32_MAX;
+ m_loop_detected = 0;
+ m_slow_runner.SetEntry(nullptr);
+ m_fast_runner.SetEntry(nullptr);
+
+ Error err;
+ ValueObjectSP backend_addr(m_backend.AddressOf(err));
+ m_list_capping_size = 0;
+ if (m_backend.GetTargetSP())
+ m_list_capping_size = m_backend.GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
+ if (m_list_capping_size == 0)
+ m_list_capping_size = 255;
+ if (err.Fail() || backend_addr.get() == NULL)
+ return false;
+ m_node_address = backend_addr->GetValueAsUnsigned(0);
+ if (!m_node_address || m_node_address == LLDB_INVALID_ADDRESS)
+ return false;
+ ValueObjectSP impl_sp(m_backend.GetChildMemberWithName(ConstString("__end_"),true));
+ if (!impl_sp)
+ return false;
+ CompilerType list_type = m_backend.GetCompilerType();
+ if (list_type.IsReferenceType())
+ list_type = list_type.GetNonReferenceType();
+
+ if (list_type.GetNumTemplateArguments() == 0)
+ return false;
+ lldb::TemplateArgumentKind kind;
+ m_element_type = list_type.GetTemplateArgument(0, kind);
+ m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get();
+ m_tail = impl_sp->GetChildMemberWithName(ConstString("__prev_"), true).get();
+ return false;
+}
+
+bool
+lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+size_t
+lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ return ExtractIndexFromString(name.GetCString());
+}
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ if (!valobj_sp)
+ return NULL;
+ return (new LibcxxStdListSyntheticFrontEnd(valobj_sp));
+}
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
new file mode 100644
index 000000000000..aa82557edb02
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
@@ -0,0 +1,478 @@
+//===-- LibCxxList.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "LibCxx.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+class MapEntry
+{
+public:
+ MapEntry() = default;
+ explicit MapEntry (ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
+ MapEntry (const MapEntry& rhs) : m_entry_sp(rhs.m_entry_sp) {}
+ explicit MapEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}
+
+ ValueObjectSP
+ left () const
+ {
+ static ConstString g_left("__left_");
+ if (!m_entry_sp)
+ return m_entry_sp;
+ return m_entry_sp->GetChildMemberWithName(g_left, true);
+ }
+
+ ValueObjectSP
+ right () const
+ {
+ static ConstString g_right("__right_");
+ if (!m_entry_sp)
+ return m_entry_sp;
+ return m_entry_sp->GetChildMemberWithName(g_right, true);
+ }
+
+ ValueObjectSP
+ parent () const
+ {
+ static ConstString g_parent("__parent_");
+ if (!m_entry_sp)
+ return m_entry_sp;
+ return m_entry_sp->GetChildMemberWithName(g_parent, true);
+ }
+
+ uint64_t
+ value () const
+ {
+ if (!m_entry_sp)
+ return 0;
+ return m_entry_sp->GetValueAsUnsigned(0);
+ }
+
+ bool
+ error () const
+ {
+ if (!m_entry_sp)
+ return true;
+ return m_entry_sp->GetError().Fail();
+ }
+
+ bool
+ null() const
+ {
+ return (value() == 0);
+ }
+
+ ValueObjectSP
+ GetEntry () const
+ {
+ return m_entry_sp;
+ }
+
+ void
+ SetEntry (ValueObjectSP entry)
+ {
+ m_entry_sp = entry;
+ }
+
+ bool
+ operator == (const MapEntry& rhs) const
+ {
+ return (rhs.m_entry_sp.get() == m_entry_sp.get());
+ }
+
+private:
+ ValueObjectSP m_entry_sp;
+};
+
+class MapIterator
+{
+public:
+ MapIterator() = default;
+ MapIterator (MapEntry entry, size_t depth = 0) : m_entry(entry), m_max_depth(depth), m_error(false) {}
+ MapIterator (ValueObjectSP entry, size_t depth = 0) : m_entry(entry), m_max_depth(depth), m_error(false) {}
+ MapIterator (const MapIterator& rhs) : m_entry(rhs.m_entry),m_max_depth(rhs.m_max_depth), m_error(false) {}
+ MapIterator (ValueObject* entry, size_t depth = 0) : m_entry(entry), m_max_depth(depth), m_error(false) {}
+
+ ValueObjectSP
+ value ()
+ {
+ return m_entry.GetEntry();
+ }
+
+ ValueObjectSP
+ advance (size_t count)
+ {
+ ValueObjectSP fail(nullptr);
+ if (m_error)
+ return fail;
+ size_t steps = 0;
+ while (count > 0)
+ {
+ next();
+ count--, steps++;
+ if (m_error ||
+ m_entry.null() ||
+ (steps > m_max_depth))
+ return fail;
+ }
+ return m_entry.GetEntry();
+ }
+
+protected:
+ void
+ next ()
+ {
+ if (m_entry.null())
+ return;
+ MapEntry right(m_entry.right());
+ if (right.null() == false)
+ {
+ m_entry = tree_min(std::move(right));
+ return;
+ }
+ size_t steps = 0;
+ while (!is_left_child(m_entry))
+ {
+ if (m_entry.error())
+ {
+ m_error = true;
+ return;
+ }
+ m_entry.SetEntry(m_entry.parent());
+ steps++;
+ if (steps > m_max_depth)
+ {
+ m_entry = MapEntry();
+ return;
+ }
+ }
+ m_entry = MapEntry(m_entry.parent());
+ }
+
+private:
+ MapEntry
+ tree_min (MapEntry&& x)
+ {
+ if (x.null())
+ return MapEntry();
+ MapEntry left(x.left());
+ size_t steps = 0;
+ while (left.null() == false)
+ {
+ if (left.error())
+ {
+ m_error = true;
+ return MapEntry();
+ }
+ x = left;
+ left.SetEntry(x.left());
+ steps++;
+ if (steps > m_max_depth)
+ return MapEntry();
+ }
+ return x;
+ }
+
+ bool
+ is_left_child (const MapEntry& x)
+ {
+ if (x.null())
+ return false;
+ MapEntry rhs(x.parent());
+ rhs.SetEntry(rhs.left());
+ return x.value() == rhs.value();
+ }
+
+ MapEntry m_entry;
+ size_t m_max_depth;
+ bool m_error;
+};
+
+namespace lldb_private {
+ namespace formatters {
+ class LibcxxStdMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ LibcxxStdMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~LibcxxStdMapSyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ private:
+ bool
+ GetDataType();
+
+ void
+ GetValueOffset (const lldb::ValueObjectSP& node);
+
+ ValueObject* m_tree;
+ ValueObject* m_root_node;
+ CompilerType m_element_type;
+ uint32_t m_skip_size;
+ size_t m_count;
+ std::map<size_t, lldb::ValueObjectSP> m_children;
+ std::map<size_t, MapIterator> m_iterators;
+ };
+ } // namespace formatters
+} // namespace lldb_private
+
+lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::LibcxxStdMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_tree(NULL),
+m_root_node(NULL),
+m_element_type(),
+m_skip_size(UINT32_MAX),
+m_count(UINT32_MAX),
+m_children(),
+m_iterators()
+{
+ if (valobj_sp)
+ Update();
+}
+
+size_t
+lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::CalculateNumChildren ()
+{
+ static ConstString g___pair3_("__pair3_");
+ static ConstString g___first_("__first_");
+
+ if (m_count != UINT32_MAX)
+ return m_count;
+ if (m_tree == NULL)
+ return 0;
+ ValueObjectSP m_item(m_tree->GetChildMemberWithName(g___pair3_, true));
+ if (!m_item)
+ return 0;
+ m_item = m_item->GetChildMemberWithName(g___first_, true);
+ if (!m_item)
+ return 0;
+ m_count = m_item->GetValueAsUnsigned(0);
+ return m_count;
+}
+
+bool
+lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType()
+{
+ static ConstString g___value_("__value_");
+
+ if (m_element_type.GetOpaqueQualType() && m_element_type.GetTypeSystem())
+ return true;
+ m_element_type.Clear();
+ ValueObjectSP deref;
+ Error error;
+ deref = m_root_node->Dereference(error);
+ if (!deref || error.Fail())
+ return false;
+ deref = deref->GetChildMemberWithName(g___value_, true);
+ if (!deref)
+ return false;
+ m_element_type = deref->GetCompilerType();
+ return true;
+}
+
+void
+lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetValueOffset (const lldb::ValueObjectSP& node)
+{
+ if (m_skip_size != UINT32_MAX)
+ return;
+ if (!node)
+ return;
+ CompilerType node_type(node->GetCompilerType());
+ uint64_t bit_offset;
+ if (node_type.GetIndexOfFieldWithName("__value_", NULL, &bit_offset) == UINT32_MAX)
+ return;
+ m_skip_size = bit_offset / 8u;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ static ConstString g___cc("__cc");
+ static ConstString g___nc("__nc");
+ static ConstString g___value_("__value_");
+
+
+ if (idx >= CalculateNumChildren())
+ return lldb::ValueObjectSP();
+ if (m_tree == NULL || m_root_node == NULL)
+ return lldb::ValueObjectSP();
+
+ auto cached = m_children.find(idx);
+ if (cached != m_children.end())
+ return cached->second;
+
+ MapIterator iterator(m_root_node, CalculateNumChildren());
+
+ const bool need_to_skip = (idx > 0);
+ size_t actual_advancde = idx;
+ if (need_to_skip)
+ {
+ auto cached_iterator = m_iterators.find(idx-1);
+ if (cached_iterator != m_iterators.end())
+ {
+ iterator = cached_iterator->second;
+ actual_advancde = 1;
+ }
+ }
+
+ ValueObjectSP iterated_sp(iterator.advance(actual_advancde));
+ if (iterated_sp.get() == NULL)
+ {
+ // this tree is garbage - stop
+ m_tree = NULL; // this will stop all future searches until an Update() happens
+ return iterated_sp;
+ }
+ if (GetDataType())
+ {
+ if (!need_to_skip)
+ {
+ Error error;
+ iterated_sp = iterated_sp->Dereference(error);
+ if (!iterated_sp || error.Fail())
+ {
+ m_tree = NULL;
+ return lldb::ValueObjectSP();
+ }
+ GetValueOffset(iterated_sp);
+ iterated_sp = iterated_sp->GetChildMemberWithName(g___value_, true);
+ if (!iterated_sp)
+ {
+ m_tree = NULL;
+ return lldb::ValueObjectSP();
+ }
+ }
+ else
+ {
+ // because of the way our debug info is made, we need to read item 0 first
+ // so that we can cache information used to generate other elements
+ if (m_skip_size == UINT32_MAX)
+ GetChildAtIndex(0);
+ if (m_skip_size == UINT32_MAX)
+ {
+ m_tree = NULL;
+ return lldb::ValueObjectSP();
+ }
+ iterated_sp = iterated_sp->GetSyntheticChildAtOffset(m_skip_size, m_element_type, true);
+ if (!iterated_sp)
+ {
+ m_tree = NULL;
+ return lldb::ValueObjectSP();
+ }
+ }
+ }
+ else
+ {
+ m_tree = NULL;
+ return lldb::ValueObjectSP();
+ }
+ // at this point we have a valid
+ // we need to copy current_sp into a new object otherwise we will end up with all items named __value_
+ DataExtractor data;
+ Error error;
+ iterated_sp->GetData(data, error);
+ if (error.Fail())
+ {
+ m_tree = NULL;
+ return lldb::ValueObjectSP();
+ }
+ StreamString name;
+ name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ auto potential_child_sp = CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type);
+ if (potential_child_sp)
+ {
+ switch (potential_child_sp->GetNumChildren())
+ {
+ case 1:
+ {
+ auto child0_sp = potential_child_sp->GetChildAtIndex(0, true);
+ if (child0_sp && child0_sp->GetName() == g___cc)
+ potential_child_sp = child0_sp;
+ break;
+ }
+ case 2:
+ {
+ auto child0_sp = potential_child_sp->GetChildAtIndex(0, true);
+ auto child1_sp = potential_child_sp->GetChildAtIndex(1, true);
+ if (child0_sp && child0_sp->GetName() == g___cc &&
+ child1_sp && child1_sp->GetName() == g___nc)
+ potential_child_sp = child0_sp;
+ break;
+ }
+ }
+ potential_child_sp->SetName(ConstString(name.GetData()));
+ }
+ m_iterators[idx] = iterator;
+ return (m_children[idx] = potential_child_sp);
+}
+
+bool
+lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::Update()
+{
+ static ConstString g___tree_("__tree_");
+ static ConstString g___begin_node_("__begin_node_");
+ m_count = UINT32_MAX;
+ m_tree = m_root_node = NULL;
+ m_children.clear();
+ m_iterators.clear();
+ m_tree = m_backend.GetChildMemberWithName(g___tree_, true).get();
+ if (!m_tree)
+ return false;
+ m_root_node = m_tree->GetChildMemberWithName(g___begin_node_, true).get();
+ return false;
+}
+
+bool
+lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+size_t
+lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ return ExtractIndexFromString(name.GetCString());
+}
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ if (!valobj_sp)
+ return NULL;
+ return (new LibcxxStdMapSyntheticFrontEnd(valobj_sp));
+}
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp
new file mode 100644
index 000000000000..8ad806d52bce
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp
@@ -0,0 +1,172 @@
+//===-- LibCxxUnorderedMap.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "LibCxx.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace lldb_private {
+ namespace formatters {
+ class LibcxxStdUnorderedMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~LibcxxStdUnorderedMapSyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ private:
+ ValueObject* m_tree;
+ size_t m_num_elements;
+ ValueObject* m_next_element;
+ std::map<size_t,lldb::ValueObjectSP> m_children;
+ std::vector<std::pair<ValueObject*, uint64_t> > m_elements_cache;
+ };
+ } // namespace formatters
+} // namespace lldb_private
+
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_tree(NULL),
+m_num_elements(0),
+m_next_element(nullptr),
+m_children(),
+m_elements_cache()
+{
+ if (valobj_sp)
+ Update();
+}
+
+size_t
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::CalculateNumChildren ()
+{
+ if (m_num_elements != UINT32_MAX)
+ return m_num_elements;
+ return 0;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ if (idx >= CalculateNumChildren())
+ return lldb::ValueObjectSP();
+ if (m_tree == NULL)
+ return lldb::ValueObjectSP();
+
+ auto cached = m_children.find(idx);
+ if (cached != m_children.end())
+ return cached->second;
+
+ while (idx >= m_elements_cache.size())
+ {
+ if (m_next_element == nullptr)
+ return lldb::ValueObjectSP();
+
+ Error error;
+ ValueObjectSP node_sp = m_next_element->Dereference(error);
+ if (!node_sp || error.Fail())
+ return lldb::ValueObjectSP();
+
+ ValueObjectSP value_sp = node_sp->GetChildMemberWithName(ConstString("__value_"), true);
+ ValueObjectSP hash_sp = node_sp->GetChildMemberWithName(ConstString("__hash_"), true);
+ if (!hash_sp || !value_sp)
+ return lldb::ValueObjectSP();
+ m_elements_cache.push_back({value_sp.get(),hash_sp->GetValueAsUnsigned(0)});
+ m_next_element = node_sp->GetChildMemberWithName(ConstString("__next_"),true).get();
+ if (!m_next_element || m_next_element->GetValueAsUnsigned(0) == 0)
+ m_next_element = nullptr;
+ }
+
+ std::pair<ValueObject*, uint64_t> val_hash = m_elements_cache[idx];
+ if (!val_hash.first)
+ return lldb::ValueObjectSP();
+ StreamString stream;
+ stream.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ DataExtractor data;
+ Error error;
+ val_hash.first->GetData(data, error);
+ if (error.Fail())
+ return lldb::ValueObjectSP();
+ const bool thread_and_frame_only_if_stopped = true;
+ ExecutionContext exe_ctx = val_hash.first->GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped);
+ return val_hash.first->CreateValueObjectFromData(stream.GetData(),
+ data,
+ exe_ctx,
+ val_hash.first->GetCompilerType());
+}
+
+bool
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::Update()
+{
+ m_num_elements = UINT32_MAX;
+ m_next_element = nullptr;
+ m_elements_cache.clear();
+ m_children.clear();
+ ValueObjectSP table_sp = m_backend.GetChildMemberWithName(ConstString("__table_"), true);
+ if (!table_sp)
+ return false;
+ ValueObjectSP num_elements_sp = table_sp->GetChildAtNamePath({ConstString("__p2_"),ConstString("__first_")});
+ if (!num_elements_sp)
+ return false;
+ m_num_elements = num_elements_sp->GetValueAsUnsigned(0);
+ m_tree = table_sp->GetChildAtNamePath({ConstString("__p1_"),ConstString("__first_"),ConstString("__next_")}).get();
+ if (m_num_elements > 0)
+ m_next_element = table_sp->GetChildAtNamePath({ConstString("__p1_"),ConstString("__first_"),ConstString("__next_")}).get();
+ return false;
+}
+
+bool
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+size_t
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ return ExtractIndexFromString(name.GetCString());
+}
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ if (!valobj_sp)
+ return NULL;
+ return (new LibcxxStdUnorderedMapSyntheticFrontEnd(valobj_sp));
+}
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp b/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
new file mode 100644
index 000000000000..9fb4f48e9090
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
@@ -0,0 +1,159 @@
+//===-- LibCxxVector.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "LibCxx.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace lldb_private {
+ namespace formatters {
+ class LibcxxStdVectorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~LibcxxStdVectorSyntheticFrontEnd() override;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ private:
+ ValueObject* m_start;
+ ValueObject* m_finish;
+ CompilerType m_element_type;
+ uint32_t m_element_size;
+ std::map<size_t,lldb::ValueObjectSP> m_children;
+ };
+ } // namespace formatters
+} // namespace lldb_private
+
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_start(NULL),
+m_finish(NULL),
+m_element_type(),
+m_element_size(0),
+m_children()
+{
+ if (valobj_sp)
+ Update();
+}
+
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::~LibcxxStdVectorSyntheticFrontEnd()
+{
+ // these need to stay around because they are child objects who will follow their parent's life cycle
+ // delete m_start;
+ // delete m_finish;
+}
+
+size_t
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren ()
+{
+ if (!m_start || !m_finish)
+ return 0;
+ uint64_t start_val = m_start->GetValueAsUnsigned(0);
+ uint64_t finish_val = m_finish->GetValueAsUnsigned(0);
+
+ if (start_val == 0 || finish_val == 0)
+ return 0;
+
+ if (start_val >= finish_val)
+ return 0;
+
+ size_t num_children = (finish_val - start_val);
+ if (num_children % m_element_size)
+ return 0;
+ return num_children/m_element_size;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ if (!m_start || !m_finish)
+ return lldb::ValueObjectSP();
+
+ auto cached = m_children.find(idx);
+ if (cached != m_children.end())
+ return cached->second;
+
+ uint64_t offset = idx * m_element_size;
+ offset = offset + m_start->GetValueAsUnsigned(0);
+ StreamString name;
+ name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ ValueObjectSP child_sp = CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type);
+ m_children[idx] = child_sp;
+ return child_sp;
+}
+
+bool
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update()
+{
+ m_start = m_finish = NULL;
+ m_children.clear();
+ ValueObjectSP data_type_finder_sp(m_backend.GetChildMemberWithName(ConstString("__end_cap_"),true));
+ if (!data_type_finder_sp)
+ return false;
+ data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(ConstString("__first_"),true);
+ if (!data_type_finder_sp)
+ return false;
+ m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType();
+ m_element_size = m_element_type.GetByteSize(nullptr);
+
+ if (m_element_size > 0)
+ {
+ // store raw pointers or end up with a circular dependency
+ m_start = m_backend.GetChildMemberWithName(ConstString("__begin_"),true).get();
+ m_finish = m_backend.GetChildMemberWithName(ConstString("__end_"),true).get();
+ }
+ return false;
+}
+
+bool
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+size_t
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ if (!m_start || !m_finish)
+ return UINT32_MAX;
+ return ExtractIndexFromString(name.GetCString());
+}
+
+lldb_private::SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ if (!valobj_sp)
+ return NULL;
+ return (new LibcxxStdVectorSyntheticFrontEnd(valobj_sp));
+}
diff --git a/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
new file mode 100644
index 000000000000..ed89c5c84ea3
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
@@ -0,0 +1,373 @@
+//===-- LibStdcpp.cpp ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibStdcpp.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+#include "lldb/DataFormatters/VectorIterator.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+{
+public:
+ LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName (const ConstString &name) override;
+
+ ~LibstdcppMapIteratorSyntheticFrontEnd() override;
+
+private:
+ ExecutionContextRef m_exe_ctx_ref;
+ lldb::addr_t m_pair_address;
+ CompilerType m_pair_type;
+ EvaluateExpressionOptions m_options;
+ lldb::ValueObjectSP m_pair_sp;
+};
+
+/*
+ (std::_Rb_tree_iterator<std::pair<const int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >) ibeg = {
+ (_Base_ptr) _M_node = 0x0000000100103910 {
+ (std::_Rb_tree_color) _M_color = _S_black
+ (std::_Rb_tree_node_base::_Base_ptr) _M_parent = 0x00000001001038c0
+ (std::_Rb_tree_node_base::_Base_ptr) _M_left = 0x0000000000000000
+ (std::_Rb_tree_node_base::_Base_ptr) _M_right = 0x0000000000000000
+ }
+ }
+ */
+
+LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+ SyntheticChildrenFrontEnd(*valobj_sp.get()),
+ m_exe_ctx_ref(),
+ m_pair_address(0),
+ m_pair_type(),
+ m_options(),
+ m_pair_sp()
+{
+ if (valobj_sp)
+ Update();
+ m_options.SetCoerceToId(false);
+ m_options.SetUnwindOnError(true);
+ m_options.SetKeepInMemory(true);
+ m_options.SetUseDynamic(lldb::eDynamicCanRunTarget);
+}
+
+bool
+LibstdcppMapIteratorSyntheticFrontEnd::Update()
+{
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ if (!valobj_sp)
+ return false;
+
+ TargetSP target_sp(valobj_sp->GetTargetSP());
+
+ if (!target_sp)
+ return false;
+
+ bool is_64bit = (target_sp->GetArchitecture().GetAddressByteSize() == 8);
+
+ if (!valobj_sp)
+ return false;
+ m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+
+ ValueObjectSP _M_node_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_node"), true));
+ if (!_M_node_sp)
+ return false;
+
+ m_pair_address = _M_node_sp->GetValueAsUnsigned(0);
+ if (m_pair_address == 0)
+ return false;
+
+ m_pair_address += (is_64bit ? 32 : 16);
+
+ CompilerType my_type(valobj_sp->GetCompilerType());
+ if (my_type.GetNumTemplateArguments() >= 1)
+ {
+ TemplateArgumentKind kind;
+ CompilerType pair_type = my_type.GetTemplateArgument(0, kind);
+ if (kind != eTemplateArgumentKindType && kind != eTemplateArgumentKindTemplate && kind != eTemplateArgumentKindTemplateExpansion)
+ return false;
+ m_pair_type = pair_type;
+ }
+ else
+ return false;
+
+ return true;
+}
+
+size_t
+LibstdcppMapIteratorSyntheticFrontEnd::CalculateNumChildren ()
+{
+ return 2;
+}
+
+lldb::ValueObjectSP
+LibstdcppMapIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ if (m_pair_address != 0 && m_pair_type)
+ {
+ if (!m_pair_sp)
+ m_pair_sp = CreateValueObjectFromAddress("pair", m_pair_address, m_exe_ctx_ref, m_pair_type);
+ if (m_pair_sp)
+ return m_pair_sp->GetChildAtIndex(idx, true);
+ }
+ return lldb::ValueObjectSP();
+}
+
+bool
+LibstdcppMapIteratorSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+size_t
+LibstdcppMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ if (name == ConstString("first"))
+ return 0;
+ if (name == ConstString("second"))
+ return 1;
+ return UINT32_MAX;
+}
+
+LibstdcppMapIteratorSyntheticFrontEnd::~LibstdcppMapIteratorSyntheticFrontEnd ()
+{}
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ if (!valobj_sp)
+ return NULL;
+ return (new LibstdcppMapIteratorSyntheticFrontEnd(valobj_sp));
+}
+
+/*
+ (lldb) fr var ibeg --ptr-depth 1
+ (__gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > >) ibeg = {
+ _M_current = 0x00000001001037a0 {
+ *_M_current = 1
+ }
+ }
+ */
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ static ConstString g_item_name;
+ if (!g_item_name)
+ g_item_name.SetCString("_M_current");
+ if (!valobj_sp)
+ return NULL;
+ return (new VectorIteratorSyntheticFrontEnd(valobj_sp,g_item_name));
+}
+
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::VectorIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp,
+ ConstString item_name) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_exe_ctx_ref(),
+m_item_name(item_name),
+m_item_sp()
+{
+ if (valobj_sp)
+ Update();
+}
+
+bool
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update()
+{
+ m_item_sp.reset();
+
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ if (!valobj_sp)
+ return false;
+
+ if (!valobj_sp)
+ return false;
+
+ ValueObjectSP item_ptr(valobj_sp->GetChildMemberWithName(m_item_name,true));
+ if (!item_ptr)
+ return false;
+ if (item_ptr->GetValueAsUnsigned(0) == 0)
+ return false;
+ Error err;
+ m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+ m_item_sp = CreateValueObjectFromAddress("item", item_ptr->GetValueAsUnsigned(0), m_exe_ctx_ref, item_ptr->GetCompilerType().GetPointeeType());
+ if (err.Fail())
+ m_item_sp.reset();
+ return false;
+}
+
+size_t
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren ()
+{
+ return 1;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ if (idx == 0)
+ return m_item_sp;
+ return lldb::ValueObjectSP();
+}
+
+bool
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+size_t
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ if (name == ConstString("item"))
+ return 0;
+ return UINT32_MAX;
+}
+
+lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
+{
+}
+
+bool
+lldb_private::formatters::LibStdcppStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ const bool scalar_is_load_addr = true;
+ AddressType addr_type;
+ lldb::addr_t addr_of_string = valobj.GetAddressOf(scalar_is_load_addr, &addr_type);
+ if (addr_of_string != LLDB_INVALID_ADDRESS)
+ {
+ switch (addr_type)
+ {
+ case eAddressTypeLoad:
+ {
+ ProcessSP process_sp(valobj.GetProcessSP());
+ if (!process_sp)
+ return false;
+
+ StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+ Error error;
+ lldb::addr_t addr_of_data = process_sp->ReadPointerFromMemory(addr_of_string, error);
+ if (error.Fail() || addr_of_data == 0 || addr_of_data == LLDB_INVALID_ADDRESS)
+ return false;
+ options.SetLocation(addr_of_data);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetNeedsZeroTermination(false);
+ options.SetBinaryZeroIsTerminator(true);
+ lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(addr_of_string + process_sp->GetAddressByteSize(), error);
+ if (error.Fail())
+ return false;
+ options.SetSourceSize(size_of_data);
+
+ if (!StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options))
+ {
+ stream.Printf("Summary Unavailable");
+ return true;
+ }
+ else
+ return true;
+ }
+ break;
+ case eAddressTypeHost:
+ break;
+ case eAddressTypeInvalid:
+ case eAddressTypeFile:
+ break;
+ }
+ }
+ return false;
+}
+
+bool
+lldb_private::formatters::LibStdcppWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ const bool scalar_is_load_addr = true;
+ AddressType addr_type;
+ lldb::addr_t addr_of_string = valobj.GetAddressOf(scalar_is_load_addr, &addr_type);
+ if (addr_of_string != LLDB_INVALID_ADDRESS)
+ {
+ switch (addr_type)
+ {
+ case eAddressTypeLoad:
+ {
+ ProcessSP process_sp(valobj.GetProcessSP());
+ if (!process_sp)
+ return false;
+
+ CompilerType wchar_compiler_type = valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar);
+
+ if (!wchar_compiler_type)
+ return false;
+
+ const uint32_t wchar_size = wchar_compiler_type.GetBitSize(nullptr); // Safe to pass NULL for exe_scope here
+
+ StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+ Error error;
+ lldb::addr_t addr_of_data = process_sp->ReadPointerFromMemory(addr_of_string, error);
+ if (error.Fail() || addr_of_data == 0 || addr_of_data == LLDB_INVALID_ADDRESS)
+ return false;
+ options.SetLocation(addr_of_data);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetNeedsZeroTermination(false);
+ options.SetBinaryZeroIsTerminator(false);
+ lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(addr_of_string + process_sp->GetAddressByteSize(), error);
+ if (error.Fail())
+ return false;
+ options.SetSourceSize(size_of_data);
+ options.SetPrefixToken("L");
+
+ switch (wchar_size)
+ {
+ case 8:
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options);
+ case 16:
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16>(options);
+ case 32:
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF32>(options);
+ default:
+ stream.Printf("size for wchar_t is not valid");
+ return true;
+ }
+ return true;
+ }
+ break;
+ case eAddressTypeHost:
+ break;
+ case eAddressTypeInvalid:
+ case eAddressTypeFile:
+ break;
+ }
+ }
+ return false;
+}
diff --git a/source/Plugins/Language/CPlusPlus/LibStdcpp.h b/source/Plugins/Language/CPlusPlus/LibStdcpp.h
new file mode 100644
index 000000000000..347856a1695c
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/LibStdcpp.h
@@ -0,0 +1,33 @@
+//===-- LibStdCpp.h ---------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_LibStdCpp_h_
+#define liblldb_LibStdCpp_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+
+namespace lldb_private {
+ namespace formatters
+ {
+ bool
+ LibStdcppStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libcstdc++ c++11 std::string
+
+ bool
+ LibStdcppWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libcstdc++ c++11 std::wstring
+
+ SyntheticChildrenFrontEnd* LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ SyntheticChildrenFrontEnd* LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_LibStdCpp_h_
diff --git a/source/Plugins/Language/Go/GoFormatterFunctions.cpp b/source/Plugins/Language/Go/GoFormatterFunctions.cpp
new file mode 100644
index 000000000000..1d7cd76b9739
--- /dev/null
+++ b/source/Plugins/Language/Go/GoFormatterFunctions.cpp
@@ -0,0 +1,173 @@
+//===-- GoFormatterFunctions.cpp---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+#include <map>
+
+// Other libraries and framework includes
+// Project includes
+#include "GoFormatterFunctions.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace
+{
+class GoSliceSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+{
+ public:
+ GoSliceSyntheticFrontEnd(ValueObject &valobj)
+ : SyntheticChildrenFrontEnd(valobj)
+ {
+ Update();
+ }
+
+ ~GoSliceSyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override
+ {
+ return m_len;
+ }
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override
+ {
+ if (idx < m_len)
+ {
+ ValueObjectSP &cached = m_children[idx];
+ if (!cached)
+ {
+ StreamString idx_name;
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ lldb::addr_t object_at_idx = m_base_data_address;
+ object_at_idx += idx * m_type.GetByteSize(nullptr);
+ cached = CreateValueObjectFromAddress(idx_name.GetData(), object_at_idx,
+ m_backend.GetExecutionContextRef(), m_type);
+ }
+ return cached;
+ }
+ return ValueObjectSP();
+ }
+
+ bool
+ Update() override
+ {
+ size_t old_count = m_len;
+
+ ConstString array_const_str("array");
+ ValueObjectSP array_sp = m_backend.GetChildMemberWithName(array_const_str, true);
+ if (!array_sp)
+ {
+ m_children.clear();
+ return old_count == 0;
+ }
+ m_type = array_sp->GetCompilerType().GetPointeeType();
+ m_base_data_address = array_sp->GetPointerValue();
+
+ ConstString len_const_str("len");
+ ValueObjectSP len_sp = m_backend.GetChildMemberWithName(len_const_str, true);
+ if (len_sp)
+ {
+ m_len = len_sp->GetValueAsUnsigned(0);
+ m_children.clear();
+ }
+
+ return old_count == m_len;
+ }
+
+ bool
+ MightHaveChildren() override
+ {
+ return true;
+ }
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override
+ {
+ return ExtractIndexFromString(name.AsCString());
+ }
+
+ private:
+ CompilerType m_type;
+ lldb::addr_t m_base_data_address;
+ size_t m_len;
+ std::map<size_t, lldb::ValueObjectSP> m_children;
+};
+
+} // anonymous namespace
+
+bool
+lldb_private::formatters::GoStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &opts)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ if (valobj.IsPointerType())
+ {
+ Error err;
+ ValueObjectSP deref = valobj.Dereference(err);
+ if (!err.Success())
+ return false;
+ return GoStringSummaryProvider(*deref, stream, opts);
+ }
+
+ ConstString str_name("str");
+ ConstString len_name("len");
+
+ ValueObjectSP data_sp = valobj.GetChildMemberWithName(str_name, true);
+ ValueObjectSP len_sp = valobj.GetChildMemberWithName(len_name, true);
+ if (!data_sp || !len_sp)
+ return false;
+ bool success;
+ lldb::addr_t valobj_addr = data_sp->GetValueAsUnsigned(0, &success);
+
+ if (!success)
+ return false;
+
+ uint64_t length = len_sp->GetValueAsUnsigned(0);
+ if (length == 0)
+ {
+ stream.Printf("\"\"");
+ return true;
+ }
+
+ StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+ options.SetLocation(valobj_addr);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetSourceSize(length);
+ options.SetNeedsZeroTermination(false);
+ options.SetLanguage(eLanguageTypeGo);
+
+ if (!StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options))
+ {
+ stream.Printf("Summary Unavailable");
+ return true;
+ }
+
+ return true;
+}
+
+SyntheticChildrenFrontEnd *
+lldb_private::formatters::GoSliceSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp)
+{
+ if (!valobj_sp)
+ return nullptr;
+
+ lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return nullptr;
+ return new GoSliceSyntheticFrontEnd(*valobj_sp);
+}
diff --git a/source/Plugins/Language/Go/GoFormatterFunctions.h b/source/Plugins/Language/Go/GoFormatterFunctions.h
new file mode 100644
index 000000000000..ae1eda0f0c54
--- /dev/null
+++ b/source/Plugins/Language/Go/GoFormatterFunctions.h
@@ -0,0 +1,43 @@
+//===-- GoFormatterFunctions.h-----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GoFormatterFunctions_h_
+#define liblldb_GoFormatterFunctions_h_
+
+// C Includes
+#include <stdint.h>
+#include <time.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "clang/AST/ASTContext.h"
+
+// Project includes
+#include "lldb/lldb-forward.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/DataFormatters/FormatClasses.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Target.h"
+
+namespace lldb_private
+{
+namespace formatters
+{
+
+bool GoStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options);
+
+SyntheticChildrenFrontEnd *GoSliceSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP);
+
+} // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_GoFormatterFunctions_h_
diff --git a/source/Plugins/Language/Go/GoLanguage.cpp b/source/Plugins/Language/Go/GoLanguage.cpp
new file mode 100644
index 000000000000..ed010ffa4b2e
--- /dev/null
+++ b/source/Plugins/Language/Go/GoLanguage.cpp
@@ -0,0 +1,146 @@
+//===-- GoLanguage.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <string.h>
+// C++ Includes
+#include <functional>
+#include <mutex>
+
+// Other libraries and framework includes
+#include "llvm/ADT/StringRef.h"
+
+// Project includes
+#include "GoLanguage.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Symbol/GoASTContext.h"
+#include "Plugins/Language/Go/GoFormatterFunctions.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+void
+GoLanguage::Initialize()
+{
+ PluginManager::RegisterPlugin(GetPluginNameStatic(), "Go Language", CreateInstance);
+}
+
+void
+GoLanguage::Terminate()
+{
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+lldb_private::ConstString
+GoLanguage::GetPluginNameStatic()
+{
+ static ConstString g_name("Go");
+ return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+GoLanguage::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+GoLanguage::GetPluginVersion()
+{
+ return 1;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+Language *
+GoLanguage::CreateInstance(lldb::LanguageType language)
+{
+ if (language == eLanguageTypeGo)
+ return new GoLanguage();
+ return nullptr;
+}
+
+HardcodedFormatters::HardcodedSummaryFinder
+GoLanguage::GetHardcodedSummaries()
+{
+ static std::once_flag g_initialize;
+ static HardcodedFormatters::HardcodedSummaryFinder g_formatters;
+
+ std::call_once(g_initialize, []() -> void
+ {
+ g_formatters.push_back(
+ [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
+ FormatManager &) -> TypeSummaryImpl::SharedPointer
+ {
+ static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(
+ TypeSummaryImpl::Flags().SetDontShowChildren(true),
+ lldb_private::formatters::GoStringSummaryProvider, "Go string summary provider"));
+ if (GoASTContext::IsGoString(valobj.GetCompilerType()))
+ {
+ return formatter_sp;
+ }
+ if (GoASTContext::IsGoString(valobj.GetCompilerType().GetPointeeType()))
+ {
+ return formatter_sp;
+ }
+ return nullptr;
+ });
+ g_formatters.push_back(
+ [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
+ FormatManager &) -> TypeSummaryImpl::SharedPointer
+ {
+ static lldb::TypeSummaryImplSP formatter_sp(
+ new StringSummaryFormat(TypeSummaryImpl::Flags().SetHideItemNames(true),
+ "(len ${var.len}, cap ${var.cap})"));
+ if (GoASTContext::IsGoSlice(valobj.GetCompilerType()))
+ {
+ return formatter_sp;
+ }
+ if (GoASTContext::IsGoSlice(valobj.GetCompilerType().GetPointeeType()))
+ {
+ return formatter_sp;
+ }
+ return nullptr;
+ });
+ });
+ return g_formatters;
+}
+
+HardcodedFormatters::HardcodedSyntheticFinder
+GoLanguage::GetHardcodedSynthetics()
+{
+ static std::once_flag g_initialize;
+ static HardcodedFormatters::HardcodedSyntheticFinder g_formatters;
+
+ std::call_once(g_initialize, []() -> void
+ {
+ g_formatters.push_back(
+ [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
+ FormatManager &fmt_mgr) -> SyntheticChildren::SharedPointer
+ {
+ static CXXSyntheticChildren::SharedPointer formatter_sp(
+ new CXXSyntheticChildren(SyntheticChildren::Flags(), "slice synthetic children",
+ lldb_private::formatters::GoSliceSyntheticFrontEndCreator));
+ if (GoASTContext::IsGoSlice(valobj.GetCompilerType()))
+ {
+ return formatter_sp;
+ }
+ return nullptr;
+ });
+ });
+
+ return g_formatters;
+}
diff --git a/source/Plugins/Language/Go/GoLanguage.h b/source/Plugins/Language/Go/GoLanguage.h
new file mode 100644
index 000000000000..67dd04c2a22e
--- /dev/null
+++ b/source/Plugins/Language/Go/GoLanguage.h
@@ -0,0 +1,66 @@
+//===-- GoLanguage.h --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GoLanguage_h_
+#define liblldb_GoLanguage_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+#include "llvm/ADT/StringRef.h"
+
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Target/Language.h"
+
+namespace lldb_private
+{
+
+class GoLanguage : public Language
+{
+ public:
+ GoLanguage() = default;
+
+ ~GoLanguage() override = default;
+
+ lldb::LanguageType
+ GetLanguageType() const override
+ {
+ return lldb::eLanguageTypeGo;
+ }
+
+ HardcodedFormatters::HardcodedSummaryFinder GetHardcodedSummaries() override;
+
+ HardcodedFormatters::HardcodedSyntheticFinder GetHardcodedSynthetics() override;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void Initialize();
+
+ static void Terminate();
+
+ static lldb_private::Language *CreateInstance(lldb::LanguageType language);
+
+ static lldb_private::ConstString GetPluginNameStatic();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_GoLanguage_h_
diff --git a/source/Plugins/Language/ObjC/CF.cpp b/source/Plugins/Language/ObjC/CF.cpp
new file mode 100644
index 000000000000..614eb29a0f7a
--- /dev/null
+++ b/source/Plugins/Language/ObjC/CF.cpp
@@ -0,0 +1,334 @@
+//===-- CF.cpp ----------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CF.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Language.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+bool
+lldb_private::formatters::CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ time_t epoch = GetOSXEpoch();
+ epoch = epoch + (time_t)valobj.GetValueAsUnsigned(0);
+ tm *tm_date = localtime(&epoch);
+ if (!tm_date)
+ return false;
+ std::string buffer(1024,0);
+ if (strftime (&buffer[0], 1023, "%Z", tm_date) == 0)
+ return false;
+ stream.Printf("%04d-%02d-%02d %02d:%02d:%02d %s", tm_date->tm_year+1900, tm_date->tm_mon+1, tm_date->tm_mday, tm_date->tm_hour, tm_date->tm_min, tm_date->tm_sec, buffer.c_str());
+ return true;
+}
+
+bool
+lldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ static ConstString g_TypeHint("CFBag");
+
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+
+ if (!valobj_addr)
+ return false;
+
+ uint32_t count = 0;
+
+ bool is_type_ok = false; // check to see if this is a CFBag we know about
+ if (descriptor->IsCFType())
+ {
+ ConstString type_name(valobj.GetTypeName());
+ if (type_name == ConstString("__CFBag") || type_name == ConstString("const struct __CFBag"))
+ {
+ if (valobj.IsPointerType())
+ is_type_ok = true;
+ }
+ }
+
+ if (is_type_ok == false)
+ {
+ StackFrameSP frame_sp(valobj.GetFrameSP());
+ if (!frame_sp)
+ return false;
+ ValueObjectSP count_sp;
+ StreamString expr;
+ expr.Printf("(int)CFBagGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue());
+ EvaluateExpressionOptions options;
+ options.SetResultIsInternal(true);
+ if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp, options) != eExpressionCompleted)
+ return false;
+ if (!count_sp)
+ return false;
+ count = count_sp->GetValueAsUnsigned(0);
+ }
+ else
+ {
+ uint32_t offset = 2*ptr_size+4 + valobj_addr;
+ Error error;
+ count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error);
+ if (error.Fail())
+ return false;
+ }
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(options.GetLanguage()))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s\"%u value%s\"%s",
+ prefix.c_str(),
+ count,(count == 1 ? "" : "s"),
+ suffix.c_str());
+ return true;
+}
+
+bool
+lldb_private::formatters::CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+
+ if (!valobj_addr)
+ return false;
+
+ uint32_t count = 0;
+
+ bool is_type_ok = false; // check to see if this is a CFBag we know about
+ if (descriptor->IsCFType())
+ {
+ ConstString type_name(valobj.GetTypeName());
+ if (type_name == ConstString("__CFMutableBitVector") || type_name == ConstString("__CFBitVector") || type_name == ConstString("CFMutableBitVectorRef") || type_name == ConstString("CFBitVectorRef"))
+ {
+ if (valobj.IsPointerType())
+ is_type_ok = true;
+ }
+ }
+
+ if (is_type_ok == false)
+ return false;
+
+ Error error;
+ count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, ptr_size, 0, error);
+ if (error.Fail())
+ return false;
+ uint64_t num_bytes = count / 8 + ((count & 7) ? 1 : 0);
+ addr_t data_ptr = process_sp->ReadPointerFromMemory(valobj_addr+2*ptr_size+2*ptr_size, error);
+ if (error.Fail())
+ return false;
+ // make sure we do not try to read huge amounts of data
+ if (num_bytes > 1024)
+ num_bytes = 1024;
+ DataBufferSP buffer_sp(new DataBufferHeap(num_bytes,0));
+ num_bytes = process_sp->ReadMemory(data_ptr, buffer_sp->GetBytes(), num_bytes, error);
+ if (error.Fail() || num_bytes == 0)
+ return false;
+ uint8_t *bytes = buffer_sp->GetBytes();
+ for (uint64_t byte_idx = 0; byte_idx < num_bytes-1; byte_idx++)
+ {
+ uint8_t byte = bytes[byte_idx];
+ bool bit0 = (byte & 1) == 1;
+ bool bit1 = (byte & 2) == 2;
+ bool bit2 = (byte & 4) == 4;
+ bool bit3 = (byte & 8) == 8;
+ bool bit4 = (byte & 16) == 16;
+ bool bit5 = (byte & 32) == 32;
+ bool bit6 = (byte & 64) == 64;
+ bool bit7 = (byte & 128) == 128;
+ stream.Printf("%c%c%c%c %c%c%c%c ",
+ (bit7 ? '1' : '0'),
+ (bit6 ? '1' : '0'),
+ (bit5 ? '1' : '0'),
+ (bit4 ? '1' : '0'),
+ (bit3 ? '1' : '0'),
+ (bit2 ? '1' : '0'),
+ (bit1 ? '1' : '0'),
+ (bit0 ? '1' : '0'));
+ count -= 8;
+ }
+ {
+ // print the last byte ensuring we do not print spurious bits
+ uint8_t byte = bytes[num_bytes-1];
+ bool bit0 = (byte & 1) == 1;
+ bool bit1 = (byte & 2) == 2;
+ bool bit2 = (byte & 4) == 4;
+ bool bit3 = (byte & 8) == 8;
+ bool bit4 = (byte & 16) == 16;
+ bool bit5 = (byte & 32) == 32;
+ bool bit6 = (byte & 64) == 64;
+ bool bit7 = (byte & 128) == 128;
+ if (count)
+ {
+ stream.Printf("%c",bit7 ? '1' : '0');
+ count -= 1;
+ }
+ if (count)
+ {
+ stream.Printf("%c",bit6 ? '1' : '0');
+ count -= 1;
+ }
+ if (count)
+ {
+ stream.Printf("%c",bit5 ? '1' : '0');
+ count -= 1;
+ }
+ if (count)
+ {
+ stream.Printf("%c",bit4 ? '1' : '0');
+ count -= 1;
+ }
+ if (count)
+ {
+ stream.Printf("%c",bit3 ? '1' : '0');
+ count -= 1;
+ }
+ if (count)
+ {
+ stream.Printf("%c",bit2 ? '1' : '0');
+ count -= 1;
+ }
+ if (count)
+ {
+ stream.Printf("%c",bit1 ? '1' : '0');
+ count -= 1;
+ }
+ if (count)
+ stream.Printf("%c",bit0 ? '1' : '0');
+ }
+ return true;
+}
+
+bool
+lldb_private::formatters::CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ static ConstString g_TypeHint("CFBinaryHeap");
+
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+
+ if (!valobj_addr)
+ return false;
+
+ uint32_t count = 0;
+
+ bool is_type_ok = false; // check to see if this is a CFBinaryHeap we know about
+ if (descriptor->IsCFType())
+ {
+ ConstString type_name(valobj.GetTypeName());
+ if (type_name == ConstString("__CFBinaryHeap") || type_name == ConstString("const struct __CFBinaryHeap"))
+ {
+ if (valobj.IsPointerType())
+ is_type_ok = true;
+ }
+ }
+
+ if (is_type_ok == false)
+ {
+ StackFrameSP frame_sp(valobj.GetFrameSP());
+ if (!frame_sp)
+ return false;
+ ValueObjectSP count_sp;
+ StreamString expr;
+ expr.Printf("(int)CFBinaryHeapGetCount((void*)0x%" PRIx64 ")",valobj.GetPointerValue());
+ EvaluateExpressionOptions options;
+ options.SetResultIsInternal(true);
+ if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), count_sp, options) != eExpressionCompleted)
+ return false;
+ if (!count_sp)
+ return false;
+ count = count_sp->GetValueAsUnsigned(0);
+ }
+ else
+ {
+ uint32_t offset = 2*ptr_size;
+ Error error;
+ count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error);
+ if (error.Fail())
+ return false;
+ }
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(options.GetLanguage()))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s\"%u item%s\"%s",
+ prefix.c_str(),
+ count,(count == 1 ? "" : "s"),
+ suffix.c_str());
+ return true;
+}
diff --git a/source/Plugins/Language/ObjC/CF.h b/source/Plugins/Language/ObjC/CF.h
new file mode 100644
index 000000000000..4044f09f585e
--- /dev/null
+++ b/source/Plugins/Language/ObjC/CF.h
@@ -0,0 +1,34 @@
+//===-- CF.h ---------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CF_h_
+#define liblldb_CF_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+
+namespace lldb_private {
+ namespace formatters
+ {
+ bool
+ CFBagSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ CFBinaryHeapSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ CFBitVectorSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ CFAbsoluteTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_CF_h_
diff --git a/source/Plugins/Language/ObjC/Cocoa.cpp b/source/Plugins/Language/ObjC/Cocoa.cpp
new file mode 100644
index 000000000000..aa6e476b6131
--- /dev/null
+++ b/source/Plugins/Language/ObjC/Cocoa.cpp
@@ -0,0 +1,967 @@
+//===-- Cocoa.cpp -----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "Cocoa.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Mangled.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Language.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Utility/ProcessStructReader.h"
+
+#include "NSString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+bool
+lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+
+ if (!valobj_addr)
+ return false;
+
+ const char* class_name = descriptor->GetClassName().GetCString();
+
+ if (!class_name || !*class_name)
+ return false;
+
+ if (!strcmp(class_name,"NSBundle"))
+ {
+ uint64_t offset = 5 * ptr_size;
+ ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID), true));
+
+ StreamString summary_stream;
+ bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options);
+ if (was_nsstring_ok && summary_stream.GetSize() > 0)
+ {
+ stream.Printf("%s",summary_stream.GetData());
+ return true;
+ }
+ }
+ // this is either an unknown subclass or an NSBundle that comes from [NSBundle mainBundle]
+ // which is encoded differently and needs to be handled by running code
+ return ExtractSummaryFromObjCExpression(valobj, "NSString*", "bundlePath", stream, options.GetLanguage());
+}
+
+bool
+lldb_private::formatters::NSTimeZoneSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+
+ if (!valobj_addr)
+ return false;
+
+ const char* class_name = descriptor->GetClassName().GetCString();
+
+ if (!class_name || !*class_name)
+ return false;
+
+ if (!strcmp(class_name,"__NSTimeZone"))
+ {
+ uint64_t offset = ptr_size;
+ ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetCompilerType(), true));
+ StreamString summary_stream;
+ bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options);
+ if (was_nsstring_ok && summary_stream.GetSize() > 0)
+ {
+ stream.Printf("%s",summary_stream.GetData());
+ return true;
+ }
+ }
+ return ExtractSummaryFromObjCExpression(valobj, "NSString*", "name", stream, options.GetLanguage());
+}
+
+bool
+lldb_private::formatters::NSNotificationSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+
+ if (!valobj_addr)
+ return false;
+
+ const char* class_name = descriptor->GetClassName().GetCString();
+
+ if (!class_name || !*class_name)
+ return false;
+
+ if (!strcmp(class_name,"NSConcreteNotification"))
+ {
+ uint64_t offset = ptr_size;
+ ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetCompilerType(), true));
+ StreamString summary_stream;
+ bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options);
+ if (was_nsstring_ok && summary_stream.GetSize() > 0)
+ {
+ stream.Printf("%s",summary_stream.GetData());
+ return true;
+ }
+ }
+ // this is either an unknown subclass or an NSBundle that comes from [NSBundle mainBundle]
+ // which is encoded differently and needs to be handled by running code
+ return ExtractSummaryFromObjCExpression(valobj, "NSString*", "name", stream, options.GetLanguage());
+}
+
+bool
+lldb_private::formatters::NSMachPortSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+
+ if (!valobj_addr)
+ return false;
+
+ const char* class_name = descriptor->GetClassName().GetCString();
+
+ if (!class_name || !*class_name)
+ return false;
+
+ uint64_t port_number = 0;
+
+ do
+ {
+ if (!strcmp(class_name,"NSMachPort"))
+ {
+ uint64_t offset = (ptr_size == 4 ? 12 : 20);
+ Error error;
+ port_number = process_sp->ReadUnsignedIntegerFromMemory(offset+valobj_addr, 4, 0, error);
+ if (error.Success())
+ break;
+ }
+ if (!ExtractValueFromObjCExpression(valobj, "int", "machPort", port_number))
+ return false;
+ } while (false);
+
+ stream.Printf("mach port: %u",(uint32_t)(port_number & 0x00000000FFFFFFFF));
+ return true;
+}
+
+bool
+lldb_private::formatters::NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+
+ if (!valobj_addr)
+ return false;
+
+ const char* class_name = descriptor->GetClassName().GetCString();
+
+ if (!class_name || !*class_name)
+ return false;
+
+ uint64_t count = 0;
+
+ do {
+ if (!strcmp(class_name,"NSIndexSet") || !strcmp(class_name,"NSMutableIndexSet"))
+ {
+ Error error;
+ uint32_t mode = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+ptr_size, 4, 0, error);
+ if (error.Fail())
+ return false;
+ // this means the set is empty - count = 0
+ if ((mode & 1) == 1)
+ {
+ count = 0;
+ break;
+ }
+ if ((mode & 2) == 2)
+ mode = 1; // this means the set only has one range
+ else
+ mode = 2; // this means the set has multiple ranges
+ if (mode == 1)
+ {
+ count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+3*ptr_size, ptr_size, 0, error);
+ if (error.Fail())
+ return false;
+ }
+ else
+ {
+ // read a pointer to the data at 2*ptr_size
+ count = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, ptr_size, 0, error);
+ if (error.Fail())
+ return false;
+ // read the data at 2*ptr_size from the first location
+ count = process_sp->ReadUnsignedIntegerFromMemory(count+2*ptr_size, ptr_size, 0, error);
+ if (error.Fail())
+ return false;
+ }
+ }
+ else
+ {
+ if (!ExtractValueFromObjCExpression(valobj, "unsigned long long int", "count", count))
+ return false;
+ }
+ } while (false);
+ stream.Printf("%" PRIu64 " index%s",
+ count,
+ (count == 1 ? "" : "es"));
+ return true;
+}
+
+static void
+NSNumber_FormatChar (ValueObject& valobj,
+ Stream& stream,
+ char value,
+ lldb::LanguageType lang)
+{
+ static ConstString g_TypeHint("NSNumber:char");
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(lang))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s%hhd%s",
+ prefix.c_str(),
+ value,
+ suffix.c_str());
+}
+
+static void
+NSNumber_FormatShort (ValueObject& valobj,
+ Stream& stream,
+ short value,
+ lldb::LanguageType lang)
+{
+ static ConstString g_TypeHint("NSNumber:short");
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(lang))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s%hd%s",
+ prefix.c_str(),
+ value,
+ suffix.c_str());
+}
+
+static void
+NSNumber_FormatInt (ValueObject& valobj,
+ Stream& stream,
+ int value,
+ lldb::LanguageType lang)
+{
+ static ConstString g_TypeHint("NSNumber:int");
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(lang))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s%d%s",
+ prefix.c_str(),
+ value,
+ suffix.c_str());
+}
+
+static void
+NSNumber_FormatLong (ValueObject& valobj,
+ Stream& stream,
+ uint64_t value,
+ lldb::LanguageType lang)
+{
+ static ConstString g_TypeHint("NSNumber:long");
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(lang))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s%" PRId64 "%s",
+ prefix.c_str(),
+ value,
+ suffix.c_str());
+}
+
+static void
+NSNumber_FormatFloat (ValueObject& valobj,
+ Stream& stream,
+ float value,
+ lldb::LanguageType lang)
+{
+ static ConstString g_TypeHint("NSNumber:float");
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(lang))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s%f%s",
+ prefix.c_str(),
+ value,
+ suffix.c_str());
+}
+
+static void
+NSNumber_FormatDouble (ValueObject& valobj,
+ Stream& stream,
+ double value,
+ lldb::LanguageType lang)
+{
+ static ConstString g_TypeHint("NSNumber:double");
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(lang))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s%g%s",
+ prefix.c_str(),
+ value,
+ suffix.c_str());
+}
+
+bool
+lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+
+ if (!valobj_addr)
+ return false;
+
+ const char* class_name = descriptor->GetClassName().GetCString();
+
+ if (!class_name || !*class_name)
+ return false;
+
+ if (!strcmp(class_name,"NSNumber") || !strcmp(class_name,"__NSCFNumber"))
+ {
+ uint64_t value = 0;
+ uint64_t i_bits = 0;
+ if (descriptor->GetTaggedPointerInfo(&i_bits,&value))
+ {
+ switch (i_bits)
+ {
+ case 0:
+ NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage());
+ break;
+ case 1:
+ case 4:
+ NSNumber_FormatShort(valobj, stream, (short)value, options.GetLanguage());
+ break;
+ case 2:
+ case 8:
+ NSNumber_FormatInt(valobj, stream, (int)value, options.GetLanguage());
+ break;
+ case 3:
+ case 12:
+ NSNumber_FormatLong(valobj, stream, value, options.GetLanguage());
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+ else
+ {
+ Error error;
+ uint8_t data_type = (process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, 1, 0, error) & 0x1F);
+ uint64_t data_location = valobj_addr + 2*ptr_size;
+ uint64_t value = 0;
+ if (error.Fail())
+ return false;
+ switch (data_type)
+ {
+ case 1: // 0B00001
+ value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 1, 0, error);
+ if (error.Fail())
+ return false;
+ NSNumber_FormatChar(valobj, stream, (char)value, options.GetLanguage());
+ break;
+ case 2: // 0B0010
+ value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 2, 0, error);
+ if (error.Fail())
+ return false;
+ NSNumber_FormatShort(valobj, stream, (short)value, options.GetLanguage());
+ break;
+ case 3: // 0B0011
+ value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0, error);
+ if (error.Fail())
+ return false;
+ NSNumber_FormatInt(valobj, stream, (int)value, options.GetLanguage());
+ break;
+ case 17: // 0B10001
+ data_location += 8;
+ case 4: // 0B0100
+ value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, error);
+ if (error.Fail())
+ return false;
+ NSNumber_FormatLong(valobj, stream, value, options.GetLanguage());
+ break;
+ case 5: // 0B0101
+ {
+ uint32_t flt_as_int = process_sp->ReadUnsignedIntegerFromMemory(data_location, 4, 0, error);
+ if (error.Fail())
+ return false;
+ float flt_value = *((float*)&flt_as_int);
+ NSNumber_FormatFloat(valobj, stream, flt_value, options.GetLanguage());
+ break;
+ }
+ case 6: // 0B0110
+ {
+ uint64_t dbl_as_lng = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, error);
+ if (error.Fail())
+ return false;
+ double dbl_value = *((double*)&dbl_as_lng);
+ NSNumber_FormatDouble(valobj, stream, dbl_value, options.GetLanguage());
+ break;
+ }
+ default:
+ return false;
+ }
+ return true;
+ }
+ }
+ else
+ {
+ return ExtractSummaryFromObjCExpression(valobj, "NSString*", "stringValue", stream, options.GetLanguage());
+ }
+}
+
+bool
+lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+
+ if (!valobj_addr)
+ return false;
+
+ const char* class_name = descriptor->GetClassName().GetCString();
+
+ if (!class_name || !*class_name)
+ return false;
+
+ if (strcmp(class_name, "NSURL") == 0)
+ {
+ uint64_t offset_text = ptr_size + ptr_size + 8; // ISA + pointer + 8 bytes of data (even on 32bit)
+ uint64_t offset_base = offset_text + ptr_size;
+ 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)
+ return false;
+ StreamString summary;
+ if (!NSStringSummaryProvider(*text, summary, options))
+ return false;
+ if (base && base->GetValueAsUnsigned(0))
+ {
+ if (summary.GetSize() > 0)
+ summary.GetString().resize(summary.GetSize()-1);
+ summary.Printf(" -- ");
+ StreamString base_summary;
+ if (NSURLSummaryProvider(*base, base_summary, options) && base_summary.GetSize() > 0)
+ summary.Printf("%s",base_summary.GetSize() > 2 ? base_summary.GetData() + 2 : base_summary.GetData());
+ }
+ if (summary.GetSize())
+ {
+ stream.Printf("%s",summary.GetData());
+ return true;
+ }
+ }
+ else
+ {
+ return ExtractSummaryFromObjCExpression(valobj, "NSString*", "description", stream, options.GetLanguage());
+ }
+ return false;
+}
+
+bool
+lldb_private::formatters::NSDateSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+
+ if (!valobj_addr)
+ return false;
+
+ uint64_t date_value_bits = 0;
+ double date_value = 0.0;
+
+ const char* class_name = descriptor->GetClassName().GetCString();
+
+ if (!class_name || !*class_name)
+ return false;
+
+ if (strcmp(class_name,"NSDate") == 0 ||
+ strcmp(class_name,"__NSDate") == 0 ||
+ strcmp(class_name,"__NSTaggedDate") == 0)
+ {
+ uint64_t info_bits=0,value_bits = 0;
+ if (descriptor->GetTaggedPointerInfo(&info_bits,&value_bits))
+ {
+ date_value_bits = ((value_bits << 8) | (info_bits << 4));
+ date_value = *((double*)&date_value_bits);
+ }
+ else
+ {
+ Error error;
+ date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+ptr_size, 8, 0, error);
+ date_value = *((double*)&date_value_bits);
+ if (error.Fail())
+ return false;
+ }
+ }
+ else if (!strcmp(class_name,"NSCalendarDate"))
+ {
+ Error error;
+ date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, 8, 0, error);
+ date_value = *((double*)&date_value_bits);
+ if (error.Fail())
+ return false;
+ }
+ else
+ {
+ if (ExtractValueFromObjCExpression(valobj, "NSTimeInterval", "ExtractValueFromObjCExpression", date_value_bits) == false)
+ return false;
+ date_value = *((double*)&date_value_bits);
+ }
+ if (date_value == -63114076800)
+ {
+ stream.Printf("0001-12-30 00:00:00 +0000");
+ return true;
+ }
+ // this snippet of code assumes that time_t == seconds since Jan-1-1970
+ // this is generally true and POSIXly happy, but might break if a library
+ // vendor decides to get creative
+ time_t epoch = GetOSXEpoch();
+ epoch = epoch + (time_t)date_value;
+ tm *tm_date = gmtime(&epoch);
+ if (!tm_date)
+ return false;
+ std::string buffer(1024,0);
+ if (strftime (&buffer[0], 1023, "%Z", tm_date) == 0)
+ return false;
+ stream.Printf("%04d-%02d-%02d %02d:%02d:%02d %s", tm_date->tm_year+1900, tm_date->tm_mon+1, tm_date->tm_mday, tm_date->tm_hour, tm_date->tm_min, tm_date->tm_sec, buffer.c_str());
+ return true;
+}
+
+bool
+lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0)));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ ConstString class_name = descriptor->GetClassName();
+
+ if (class_name.IsEmpty())
+ return false;
+
+ if (ConstString cs = Mangled(class_name).GetDemangledName(lldb::eLanguageTypeUnknown))
+ class_name = cs;
+
+ stream.Printf("%s",class_name.AsCString("<unknown class>"));
+ return true;
+}
+
+class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd
+{
+public:
+ ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) :
+ SyntheticChildrenFrontEnd(*valobj_sp.get())
+ {
+ }
+
+ ~ObjCClassSyntheticChildrenFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override
+ {
+ return 0;
+ }
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override
+ {
+ return lldb::ValueObjectSP();
+ }
+
+ bool
+ Update() override
+ {
+ return false;
+ }
+
+ bool
+ MightHaveChildren() override
+ {
+ return false;
+ }
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override
+ {
+ return UINT32_MAX;
+ }
+};
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ return new ObjCClassSyntheticChildrenFrontEnd(valobj_sp);
+}
+
+template<bool needs_at>
+bool
+lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ bool is_64bit = (process_sp->GetAddressByteSize() == 8);
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+
+ if (!valobj_addr)
+ return false;
+
+ uint64_t value = 0;
+
+ const char* class_name = descriptor->GetClassName().GetCString();
+
+ if (!class_name || !*class_name)
+ return false;
+
+ if (!strcmp(class_name,"NSConcreteData") ||
+ !strcmp(class_name,"NSConcreteMutableData") ||
+ !strcmp(class_name,"__NSCFData"))
+ {
+ uint32_t offset = (is_64bit ? 16 : 8);
+ Error error;
+ value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, is_64bit ? 8 : 4, 0, error);
+ if (error.Fail())
+ return false;
+ }
+ else
+ {
+ if (!ExtractValueFromObjCExpression(valobj, "int", "length", value))
+ return false;
+ }
+
+ stream.Printf("%s%" PRIu64 " byte%s%s",
+ (needs_at ? "@\"" : ""),
+ value,
+ (value != 1 ? "s" : ""),
+ (needs_at ? "\"" : ""));
+
+ return true;
+}
+
+bool
+lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ const uint32_t type_info = valobj.GetCompilerType().GetTypeInfo();
+
+ ValueObjectSP real_guy_sp = valobj.GetSP();
+
+ if (type_info & eTypeIsPointer)
+ {
+ Error err;
+ real_guy_sp = valobj.Dereference(err);
+ if (err.Fail() || !real_guy_sp)
+ return false;
+ }
+ else if (type_info & eTypeIsReference)
+ {
+ real_guy_sp = valobj.GetChildAtIndex(0, true);
+ if (!real_guy_sp)
+ return false;
+ }
+ uint64_t value = real_guy_sp->GetValueAsUnsigned(0);
+ if (value == 0)
+ {
+ stream.Printf("NO");
+ return true;
+ }
+ stream.Printf("YES");
+ return true;
+}
+
+template <bool is_sel_ptr>
+bool
+lldb_private::formatters::ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ lldb::ValueObjectSP valobj_sp;
+
+ CompilerType charstar (valobj.GetCompilerType().GetBasicTypeFromAST(eBasicTypeChar).GetPointerType());
+
+ if (!charstar)
+ return false;
+
+ ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
+
+ if (is_sel_ptr)
+ {
+ lldb::addr_t data_address = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ if (data_address == LLDB_INVALID_ADDRESS)
+ return false;
+ valobj_sp = ValueObject::CreateValueObjectFromAddress("text", data_address, exe_ctx, charstar);
+ }
+ else
+ {
+ DataExtractor data;
+ Error error;
+ valobj.GetData(data, error);
+ if (error.Fail())
+ return false;
+ valobj_sp = ValueObject::CreateValueObjectFromData("text", data, exe_ctx, charstar);
+ }
+
+ if (!valobj_sp)
+ return false;
+
+ stream.Printf("%s",valobj_sp->GetSummaryAsCString());
+ return true;
+}
+
+// POSIX has an epoch on Jan-1-1970, but Cocoa prefers Jan-1-2001
+// this call gives the POSIX equivalent of the Cocoa epoch
+time_t
+lldb_private::formatters::GetOSXEpoch ()
+{
+ static time_t epoch = 0;
+ if (!epoch)
+ {
+#ifndef _WIN32
+ tzset();
+ tm tm_epoch;
+ tm_epoch.tm_sec = 0;
+ tm_epoch.tm_hour = 0;
+ tm_epoch.tm_min = 0;
+ tm_epoch.tm_mon = 0;
+ tm_epoch.tm_mday = 1;
+ tm_epoch.tm_year = 2001-1900; // for some reason, we need to subtract 1900 from this field. not sure why.
+ tm_epoch.tm_isdst = -1;
+ tm_epoch.tm_gmtoff = 0;
+ tm_epoch.tm_zone = NULL;
+ epoch = timegm(&tm_epoch);
+#endif
+ }
+ return epoch;
+}
+
+bool
+lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ if (const char* description = valobj.GetObjectDescription())
+ {
+ stream.Printf("%s", description);
+ return true;
+ }
+ else
+ return false;
+}
+
+template bool
+lldb_private::formatters::NSDataSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&);
+
+template bool
+lldb_private::formatters::NSDataSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&);
+
+template bool
+lldb_private::formatters::ObjCSELSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&);
+
+template bool
+lldb_private::formatters::ObjCSELSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&);
diff --git a/source/Plugins/Language/ObjC/Cocoa.h b/source/Plugins/Language/ObjC/Cocoa.h
new file mode 100644
index 000000000000..0caacf3453d4
--- /dev/null
+++ b/source/Plugins/Language/ObjC/Cocoa.h
@@ -0,0 +1,97 @@
+//===-- Cocoa.h ---------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Cocoa_h_
+#define liblldb_Cocoa_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+
+namespace lldb_private {
+ namespace formatters
+ {
+ bool
+ NSIndexSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSArraySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ template<bool needs_at>
+ bool
+ NSDataSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSNumberSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSNotificationSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSTimeZoneSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSMachPortSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSDateSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSBundleSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSURLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ extern template bool
+ NSDataSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
+
+ extern template bool
+ NSDataSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
+
+ SyntheticChildrenFrontEnd* NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ bool
+ ObjCClassSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ SyntheticChildrenFrontEnd* ObjCClassSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ bool
+ ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ template <bool is_sel_ptr>
+ bool
+ ObjCSELSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ extern template bool
+ ObjCSELSummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&);
+
+ extern template bool
+ ObjCSELSummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&);
+
+ bool
+ RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSError_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSException_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ SyntheticChildrenFrontEnd*
+ NSErrorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp);
+
+ SyntheticChildrenFrontEnd*
+ NSExceptionSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp);
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_Cocoa_h_
diff --git a/source/Plugins/Language/ObjC/CoreMedia.cpp b/source/Plugins/Language/ObjC/CoreMedia.cpp
new file mode 100644
index 000000000000..4103067b8d58
--- /dev/null
+++ b/source/Plugins/Language/ObjC/CoreMedia.cpp
@@ -0,0 +1,89 @@
+//===-- CoreMedia.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CoreMedia.h"
+
+#include "lldb/Core/Flags.h"
+#include "lldb/Symbol/TypeSystem.h"
+#include "lldb/Target/Target.h"
+#include <inttypes.h>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+bool
+lldb_private::formatters::CMTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ CompilerType type = valobj.GetCompilerType();
+ if (!type.IsValid())
+ return false;
+
+ TypeSystem *type_system = valobj.GetExecutionContextRef().GetTargetSP()->GetScratchTypeSystemForLanguage(nullptr, lldb::eLanguageTypeC);
+ if (!type_system)
+ return false;
+
+ // fetch children by offset to compensate for potential lack of debug info
+ auto int64_ty = type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 64);
+ auto int32_ty = type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, 32);
+
+ auto value_sp(valobj.GetSyntheticChildAtOffset(0, int64_ty, true));
+ auto timescale_sp(valobj.GetSyntheticChildAtOffset(8, int32_ty, true));
+ auto flags_sp(valobj.GetSyntheticChildAtOffset(12, int32_ty, true));
+
+ if (!value_sp || !timescale_sp || !flags_sp)
+ return false;
+
+ auto value = value_sp->GetValueAsUnsigned(0);
+ auto timescale = (int32_t)timescale_sp->GetValueAsUnsigned(0); // the timescale specifies the fraction of a second each unit in the numerator occupies
+ auto flags = Flags(flags_sp->GetValueAsUnsigned(0) & 0x00000000000000FF); // the flags I need sit in the LSB
+
+ const unsigned int FlagPositiveInf = 4;
+ const unsigned int FlagNegativeInf = 8;
+ const unsigned int FlagIndefinite = 16;
+
+ if (flags.AnySet(FlagIndefinite))
+ {
+ stream.Printf("indefinite");
+ return true;
+ }
+
+ if (flags.AnySet(FlagPositiveInf))
+ {
+ stream.Printf("+oo");
+ return true;
+ }
+
+ if (flags.AnySet(FlagNegativeInf))
+ {
+ stream.Printf("-oo");
+ return true;
+ }
+
+ if (timescale == 0)
+ return false;
+
+ switch (timescale)
+ {
+ case 0:
+ return false;
+ case 1:
+ stream.Printf("%" PRId64 " seconds", value);
+ return true;
+ case 2:
+ stream.Printf("%" PRId64 " half seconds", value);
+ return true;
+ case 3:
+ stream.Printf("%" PRId64 " third%sof a second", value, value == 1 ? " " : "s ");
+ return true;
+ default:
+ stream.Printf("%" PRId64 " %" PRId32 "th%sof a second", value, timescale, value == 1 ? " " : "s ");
+ return true;
+ }
+}
diff --git a/source/Plugins/Language/ObjC/CoreMedia.h b/source/Plugins/Language/ObjC/CoreMedia.h
new file mode 100644
index 000000000000..2ffabaadccf5
--- /dev/null
+++ b/source/Plugins/Language/ObjC/CoreMedia.h
@@ -0,0 +1,26 @@
+//===-- CoreMedia.h -----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CoreMedia_h_
+#define liblldb_CoreMedia_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+
+namespace lldb_private {
+ namespace formatters
+ {
+
+ bool
+ CMTimeSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_CF_h_
diff --git a/source/Plugins/Language/ObjC/NSArray.cpp b/source/Plugins/Language/ObjC/NSArray.cpp
new file mode 100644
index 000000000000..ccc82ab95ecc
--- /dev/null
+++ b/source/Plugins/Language/ObjC/NSArray.cpp
@@ -0,0 +1,792 @@
+//===-- NSArray.cpp ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "clang/AST/ASTContext.h"
+
+// Project includes
+#include "Cocoa.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Language.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace lldb_private {
+ namespace formatters {
+ class NSArrayMSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSArrayMSyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override = 0;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ protected:
+ virtual lldb::addr_t
+ GetDataAddress () = 0;
+
+ virtual uint64_t
+ GetUsedCount () = 0;
+
+ virtual uint64_t
+ GetOffset () = 0;
+
+ virtual uint64_t
+ GetSize () = 0;
+
+ ExecutionContextRef m_exe_ctx_ref;
+ uint8_t m_ptr_size;
+ CompilerType m_id_type;
+ std::vector<lldb::ValueObjectSP> m_children;
+ };
+
+ class NSArrayMSyntheticFrontEnd_109 : public NSArrayMSyntheticFrontEnd
+ {
+ public:
+ NSArrayMSyntheticFrontEnd_109 (lldb::ValueObjectSP valobj_sp);
+
+ ~NSArrayMSyntheticFrontEnd_109() override;
+
+ bool
+ Update() override;
+
+ protected:
+ lldb::addr_t
+ GetDataAddress() override;
+
+ uint64_t
+ GetUsedCount() override;
+
+ uint64_t
+ GetOffset() override;
+
+ uint64_t
+ GetSize() override;
+
+ private:
+ 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;
+ };
+
+ DataDescriptor_32 *m_data_32;
+ DataDescriptor_64 *m_data_64;
+ };
+
+ class NSArrayMSyntheticFrontEnd_1010 : public NSArrayMSyntheticFrontEnd
+ {
+ public:
+ NSArrayMSyntheticFrontEnd_1010 (lldb::ValueObjectSP valobj_sp);
+
+ ~NSArrayMSyntheticFrontEnd_1010() override;
+
+ bool
+ Update() override;
+
+ protected:
+ lldb::addr_t
+ GetDataAddress() override;
+
+ uint64_t
+ GetUsedCount() override;
+
+ uint64_t
+ GetOffset() override;
+
+ uint64_t
+ GetSize() override;
+
+ private:
+ struct DataDescriptor_32
+ {
+ uint32_t _used;
+ uint32_t _offset;
+ uint32_t _size : 28;
+ uint64_t _priv1 : 4;
+ uint32_t _priv2;
+ uint32_t _data;
+ };
+
+ struct DataDescriptor_64
+ {
+ uint64_t _used;
+ uint64_t _offset;
+ uint64_t _size : 60;
+ uint64_t _priv1 : 4;
+ uint32_t _priv2;
+ uint64_t _data;
+ };
+
+ DataDescriptor_32 *m_data_32;
+ DataDescriptor_64 *m_data_64;
+ };
+
+ class NSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSArrayISyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ private:
+ ExecutionContextRef m_exe_ctx_ref;
+ uint8_t m_ptr_size;
+ uint64_t m_items;
+ lldb::addr_t m_data_ptr;
+ CompilerType m_id_type;
+ std::vector<lldb::ValueObjectSP> m_children;
+ };
+
+ class NSArray0SyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ NSArray0SyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSArray0SyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+ };
+
+ class NSArrayCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSArrayCodeRunningSyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+ };
+ } // namespace formatters
+} // namespace lldb_private
+
+bool
+lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ static ConstString g_TypeHint("NSArray");
+
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+
+ if (!valobj_addr)
+ return false;
+
+ uint64_t value = 0;
+
+ const char* class_name = descriptor->GetClassName().GetCString();
+
+ if (!class_name || !*class_name)
+ return false;
+
+ if (!strcmp(class_name,"__NSArrayI"))
+ {
+ Error error;
+ value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
+ if (error.Fail())
+ return false;
+ }
+ else if (!strcmp(class_name,"__NSArrayM"))
+ {
+ Error error;
+ value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
+ if (error.Fail())
+ return false;
+ }
+ else if (!strcmp(class_name,"__NSArray0"))
+ {
+ value = 0;
+ }
+ else if (!strcmp(class_name,"__NSCFArray"))
+ {
+ Error error;
+ value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + 2 * ptr_size, ptr_size, 0, error);
+ if (error.Fail())
+ return false;
+ }
+ else
+ {
+ if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
+ return false;
+ }
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(options.GetLanguage()))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s%" PRIu64 " %s%s%s",
+ prefix.c_str(),
+ value,
+ "element",
+ value == 1 ? "" : "s",
+ suffix.c_str());
+ return true;
+}
+
+lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp),
+m_exe_ctx_ref(),
+m_ptr_size(8),
+m_id_type(),
+m_children()
+{
+ if (valobj_sp)
+ {
+ clang::ASTContext *ast = valobj_sp->GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext()->getASTContext();
+ if (ast)
+ m_id_type = CompilerType(ast, ast->ObjCBuiltinIdTy);
+ if (valobj_sp->GetProcessSP())
+ m_ptr_size = valobj_sp->GetProcessSP()->GetAddressByteSize();
+ }
+}
+
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::NSArrayMSyntheticFrontEnd_109 (lldb::ValueObjectSP valobj_sp) :
+NSArrayMSyntheticFrontEnd(valobj_sp),
+m_data_32(NULL),
+m_data_64(NULL)
+{
+}
+
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::NSArrayMSyntheticFrontEnd_1010 (lldb::ValueObjectSP valobj_sp) :
+NSArrayMSyntheticFrontEnd(valobj_sp),
+m_data_32(NULL),
+m_data_64(NULL)
+{
+}
+
+size_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd::CalculateNumChildren ()
+{
+ return GetUsedCount();
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ if (idx >= CalculateNumChildren())
+ return lldb::ValueObjectSP();
+ lldb::addr_t object_at_idx = GetDataAddress();
+ size_t pyhs_idx = idx;
+ pyhs_idx += GetOffset();
+ if (GetSize() <= pyhs_idx)
+ pyhs_idx -= GetSize();
+ object_at_idx += (pyhs_idx * m_ptr_size);
+ StreamString idx_name;
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ lldb::ValueObjectSP retval_sp = CreateValueObjectFromAddress(idx_name.GetData(),
+ object_at_idx,
+ m_exe_ctx_ref,
+ m_id_type);
+ m_children.push_back(retval_sp);
+ return retval_sp;
+}
+
+bool
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::Update()
+{
+ m_children.clear();
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ m_ptr_size = 0;
+ delete m_data_32;
+ m_data_32 = NULL;
+ delete m_data_64;
+ m_data_64 = NULL;
+ if (!valobj_sp)
+ return false;
+ m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+ Error error;
+ error.Clear();
+ lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return false;
+ m_ptr_size = process_sp->GetAddressByteSize();
+ uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
+ if (m_ptr_size == 4)
+ {
+ m_data_32 = new DataDescriptor_32();
+ process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
+ }
+ else
+ {
+ m_data_64 = new DataDescriptor_64();
+ process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
+ }
+ if (error.Fail())
+ return false;
+ return false;
+}
+
+bool
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::Update()
+{
+ m_children.clear();
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ m_ptr_size = 0;
+ delete m_data_32;
+ m_data_32 = NULL;
+ delete m_data_64;
+ m_data_64 = NULL;
+ if (!valobj_sp)
+ return false;
+ m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+ Error error;
+ error.Clear();
+ lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return false;
+ m_ptr_size = process_sp->GetAddressByteSize();
+ uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
+ if (m_ptr_size == 4)
+ {
+ m_data_32 = new DataDescriptor_32();
+ process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
+ }
+ else
+ {
+ m_data_64 = new DataDescriptor_64();
+ process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
+ }
+ if (error.Fail())
+ return false;
+ return false;
+}
+
+bool
+lldb_private::formatters::NSArrayMSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+size_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ const char* item_name = name.GetCString();
+ uint32_t idx = ExtractIndexFromString(item_name);
+ if (idx < UINT32_MAX && idx >= CalculateNumChildren())
+ return UINT32_MAX;
+ return idx;
+}
+
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::~NSArrayMSyntheticFrontEnd_109()
+{
+ delete m_data_32;
+ m_data_32 = NULL;
+ delete m_data_64;
+ m_data_64 = NULL;
+}
+
+lldb::addr_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetDataAddress ()
+{
+ if (!m_data_32 && !m_data_64)
+ return LLDB_INVALID_ADDRESS;
+ return m_data_32 ? m_data_32->_data :
+ m_data_64->_data;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetUsedCount ()
+{
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return m_data_32 ? m_data_32->_used :
+ m_data_64->_used;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetOffset ()
+{
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return m_data_32 ? m_data_32->_offset :
+ m_data_64->_offset;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetSize ()
+{
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return m_data_32 ? m_data_32->_size :
+ m_data_64->_size;
+}
+
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::~NSArrayMSyntheticFrontEnd_1010()
+{
+ delete m_data_32;
+ m_data_32 = NULL;
+ delete m_data_64;
+ m_data_64 = NULL;
+}
+
+lldb::addr_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetDataAddress ()
+{
+ if (!m_data_32 && !m_data_64)
+ return LLDB_INVALID_ADDRESS;
+ return m_data_32 ? m_data_32->_data :
+ m_data_64->_data;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetUsedCount ()
+{
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return m_data_32 ? m_data_32->_used :
+ m_data_64->_used;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetOffset ()
+{
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return m_data_32 ? m_data_32->_offset :
+ m_data_64->_offset;
+}
+
+uint64_t
+lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetSize ()
+{
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return m_data_32 ? m_data_32->_size :
+ m_data_64->_size;
+}
+
+lldb_private::formatters::NSArrayISyntheticFrontEnd::NSArrayISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd (*valobj_sp.get()),
+m_exe_ctx_ref (),
+m_ptr_size (8),
+m_items (0),
+m_data_ptr (0)
+{
+ if (valobj_sp)
+ {
+ CompilerType type = valobj_sp->GetCompilerType();
+ if (type)
+ {
+ ClangASTContext *ast = valobj_sp->GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext();
+ if (ast)
+ m_id_type = CompilerType(ast->getASTContext(), ast->getASTContext()->ObjCBuiltinIdTy);
+ }
+ }
+}
+
+size_t
+lldb_private::formatters::NSArrayISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ const char* item_name = name.GetCString();
+ uint32_t idx = ExtractIndexFromString(item_name);
+ if (idx < UINT32_MAX && idx >= CalculateNumChildren())
+ return UINT32_MAX;
+ return idx;
+}
+
+size_t
+lldb_private::formatters::NSArrayISyntheticFrontEnd::CalculateNumChildren ()
+{
+ return m_items;
+}
+
+bool
+lldb_private::formatters::NSArrayISyntheticFrontEnd::Update()
+{
+ m_ptr_size = 0;
+ m_items = 0;
+ m_data_ptr = 0;
+ m_children.clear();
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ if (!valobj_sp)
+ return false;
+ m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+ Error error;
+ error.Clear();
+ lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return false;
+ m_ptr_size = process_sp->GetAddressByteSize();
+ uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
+ m_items = process_sp->ReadPointerFromMemory(data_location, error);
+ if (error.Fail())
+ return false;
+ m_data_ptr = data_location+m_ptr_size;
+ return false;
+}
+
+bool
+lldb_private::formatters::NSArrayISyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ if (idx >= CalculateNumChildren())
+ return lldb::ValueObjectSP();
+ lldb::addr_t object_at_idx = m_data_ptr;
+ object_at_idx += (idx * m_ptr_size);
+ ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
+ if (!process_sp)
+ return lldb::ValueObjectSP();
+ Error error;
+ if (error.Fail())
+ return lldb::ValueObjectSP();
+ StreamString idx_name;
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ lldb::ValueObjectSP retval_sp = CreateValueObjectFromAddress(idx_name.GetData(),
+ object_at_idx,
+ m_exe_ctx_ref,
+ m_id_type);
+ m_children.push_back(retval_sp);
+ return retval_sp;
+}
+
+lldb_private::formatters::NSArray0SyntheticFrontEnd::NSArray0SyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd (*valobj_sp.get())
+{
+}
+
+size_t
+lldb_private::formatters::NSArray0SyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ return UINT32_MAX;
+}
+
+size_t
+lldb_private::formatters::NSArray0SyntheticFrontEnd::CalculateNumChildren ()
+{
+ return 0;
+}
+
+bool
+lldb_private::formatters::NSArray0SyntheticFrontEnd::Update()
+{
+ return false;
+}
+
+bool
+lldb_private::formatters::NSArray0SyntheticFrontEnd::MightHaveChildren ()
+{
+ return false;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSArray0SyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ return lldb::ValueObjectSP();
+}
+
+SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ if (!valobj_sp)
+ return nullptr;
+
+ lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return NULL;
+ AppleObjCRuntime *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(process_sp->GetObjCLanguageRuntime());
+ if (!runtime)
+ return NULL;
+
+ CompilerType valobj_type(valobj_sp->GetCompilerType());
+ Flags flags(valobj_type.GetTypeInfo());
+
+ if (flags.IsClear(eTypeIsPointer))
+ {
+ Error error;
+ valobj_sp = valobj_sp->AddressOf(error);
+ if (error.Fail() || !valobj_sp)
+ return NULL;
+ }
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return NULL;
+
+ const char* class_name = descriptor->GetClassName().GetCString();
+
+ if (!class_name || !*class_name)
+ return NULL;
+
+ if (!strcmp(class_name,"__NSArrayI"))
+ {
+ return (new NSArrayISyntheticFrontEnd(valobj_sp));
+ }
+ else if (!strcmp(class_name,"__NSArray0"))
+ {
+ return (new NSArray0SyntheticFrontEnd(valobj_sp));
+ }
+ else if (!strcmp(class_name,"__NSArrayM"))
+ {
+ if (runtime->GetFoundationVersion() >= 1100)
+ return (new NSArrayMSyntheticFrontEnd_1010(valobj_sp));
+ else
+ return (new NSArrayMSyntheticFrontEnd_109(valobj_sp));
+ }
+ else
+ {
+ return (new NSArrayCodeRunningSyntheticFrontEnd(valobj_sp));
+ }
+}
+
+lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get())
+{}
+
+size_t
+lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::CalculateNumChildren ()
+{
+ uint64_t count = 0;
+ if (ExtractValueFromObjCExpression(m_backend, "int", "count", count))
+ return count;
+ return 0;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ StreamString idx_name;
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ lldb::ValueObjectSP valobj_sp = CallSelectorOnObject(m_backend,"id","objectAtIndex:",idx);
+ if (valobj_sp)
+ {
+ valobj_sp->SetPreferredDisplayLanguage(m_backend.GetPreferredDisplayLanguage());
+ valobj_sp->SetName(ConstString(idx_name.GetData()));
+ }
+ return valobj_sp;
+}
+
+bool
+lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::Update()
+{
+ return false;
+}
+
+bool
+lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+size_t
+lldb_private::formatters::NSArrayCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ return 0;
+}
diff --git a/source/Plugins/Language/ObjC/NSDictionary.cpp b/source/Plugins/Language/ObjC/NSDictionary.cpp
new file mode 100644
index 000000000000..e4a7425329f5
--- /dev/null
+++ b/source/Plugins/Language/ObjC/NSDictionary.cpp
@@ -0,0 +1,749 @@
+//===-- NSDictionary.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+#include <mutex>
+
+// Other libraries and framework includes
+#include "clang/AST/DeclCXX.h"
+
+// Project includes
+#include "NSDictionary.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Language.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+std::map<ConstString, CXXFunctionSummaryFormat::Callback>&
+NSDictionary_Additionals::GetAdditionalSummaries ()
+{
+ static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map;
+ return g_map;
+}
+
+std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>&
+NSDictionary_Additionals::GetAdditionalSynthetics ()
+{
+ static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> g_map;
+ return g_map;
+}
+
+static CompilerType
+GetLLDBNSPairType (TargetSP target_sp)
+{
+ CompilerType compiler_type;
+
+ ClangASTContext *target_ast_context = target_sp->GetScratchClangASTContext();
+
+ if (target_ast_context)
+ {
+ ConstString g___lldb_autogen_nspair("__lldb_autogen_nspair");
+
+ compiler_type = target_ast_context->GetTypeForIdentifier<clang::CXXRecordDecl>(g___lldb_autogen_nspair);
+
+ if (!compiler_type)
+ {
+ compiler_type = target_ast_context->CreateRecordType(NULL, lldb::eAccessPublic, g___lldb_autogen_nspair.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC);
+
+ if (compiler_type)
+ {
+ ClangASTContext::StartTagDeclarationDefinition(compiler_type);
+ CompilerType id_compiler_type = target_ast_context->GetBasicType (eBasicTypeObjCID);
+ ClangASTContext::AddFieldToRecordType(compiler_type, "key", id_compiler_type, lldb::eAccessPublic, 0);
+ ClangASTContext::AddFieldToRecordType(compiler_type, "value", id_compiler_type, lldb::eAccessPublic, 0);
+ ClangASTContext::CompleteTagDeclarationDefinition(compiler_type);
+ }
+ }
+ }
+ return compiler_type;
+}
+
+namespace lldb_private {
+ namespace formatters {
+ class NSDictionaryISyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSDictionaryISyntheticFrontEnd() override;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ private:
+ struct DataDescriptor_32
+ {
+ uint32_t _used : 26;
+ uint32_t _szidx : 6;
+ };
+
+ struct DataDescriptor_64
+ {
+ uint64_t _used : 58;
+ uint32_t _szidx : 6;
+ };
+
+ struct DictionaryItemDescriptor
+ {
+ lldb::addr_t key_ptr;
+ lldb::addr_t val_ptr;
+ lldb::ValueObjectSP valobj_sp;
+ };
+
+ ExecutionContextRef m_exe_ctx_ref;
+ uint8_t m_ptr_size;
+ lldb::ByteOrder m_order;
+ DataDescriptor_32 *m_data_32;
+ DataDescriptor_64 *m_data_64;
+ lldb::addr_t m_data_ptr;
+ CompilerType m_pair_type;
+ std::vector<DictionaryItemDescriptor> m_children;
+ };
+
+ class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSDictionaryMSyntheticFrontEnd() override;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ private:
+ struct DataDescriptor_32
+ {
+ uint32_t _used : 26;
+ uint32_t _kvo : 1;
+ uint32_t _size;
+ uint32_t _mutations;
+ uint32_t _objs_addr;
+ uint32_t _keys_addr;
+ };
+
+ struct DataDescriptor_64
+ {
+ uint64_t _used : 58;
+ uint32_t _kvo : 1;
+ uint64_t _size;
+ uint64_t _mutations;
+ uint64_t _objs_addr;
+ uint64_t _keys_addr;
+ };
+
+ struct DictionaryItemDescriptor
+ {
+ lldb::addr_t key_ptr;
+ lldb::addr_t val_ptr;
+ lldb::ValueObjectSP valobj_sp;
+ };
+
+ ExecutionContextRef m_exe_ctx_ref;
+ uint8_t m_ptr_size;
+ lldb::ByteOrder m_order;
+ DataDescriptor_32 *m_data_32;
+ DataDescriptor_64 *m_data_64;
+ CompilerType m_pair_type;
+ std::vector<DictionaryItemDescriptor> m_children;
+ };
+
+ class NSDictionaryCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSDictionaryCodeRunningSyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+ };
+ } // namespace formatters
+} // namespace lldb_private
+
+template<bool name_entries>
+bool
+lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ static ConstString g_TypeHint("NSDictionary");
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+ bool is_64bit = (ptr_size == 8);
+
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+
+ if (!valobj_addr)
+ return false;
+
+ uint64_t value = 0;
+
+ ConstString class_name_cs = descriptor->GetClassName();
+ const char* class_name = class_name_cs.GetCString();
+
+ if (!class_name || !*class_name)
+ return false;
+
+ if (!strcmp(class_name,"__NSDictionaryI"))
+ {
+ Error error;
+ value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
+ if (error.Fail())
+ return false;
+ value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
+ }
+ else if (!strcmp(class_name,"__NSDictionaryM"))
+ {
+ Error error;
+ value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
+ if (error.Fail())
+ return false;
+ value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
+ }
+ /*else if (!strcmp(class_name,"__NSCFDictionary"))
+ {
+ Error error;
+ value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), 4, 0, error);
+ if (error.Fail())
+ return false;
+ if (is_64bit)
+ value &= ~0x0f1f000000000000UL;
+ }*/
+ else
+ {
+ auto& map(NSDictionary_Additionals::GetAdditionalSummaries());
+ auto iter = map.find(class_name_cs), end = map.end();
+ if (iter != end)
+ return iter->second(valobj, stream, options);
+ if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
+ return false;
+ }
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(options.GetLanguage()))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s%" PRIu64 " %s%s%s",
+ prefix.c_str(),
+ value,
+ "key/value pair",
+ value == 1 ? "" : "s",
+ suffix.c_str());
+ return true;
+}
+
+SyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren* synth, lldb::ValueObjectSP valobj_sp)
+{
+ lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return NULL;
+ ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+ if (!runtime)
+ return NULL;
+
+ CompilerType valobj_type(valobj_sp->GetCompilerType());
+ Flags flags(valobj_type.GetTypeInfo());
+
+ if (flags.IsClear(eTypeIsPointer))
+ {
+ Error error;
+ valobj_sp = valobj_sp->AddressOf(error);
+ if (error.Fail() || !valobj_sp)
+ return NULL;
+ }
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return NULL;
+
+ ConstString class_name_cs = descriptor->GetClassName();
+ const char* class_name = class_name_cs.GetCString();
+
+ if (!class_name || !*class_name)
+ return NULL;
+
+ if (!strcmp(class_name,"__NSDictionaryI"))
+ {
+ return (new NSDictionaryISyntheticFrontEnd(valobj_sp));
+ }
+ else if (!strcmp(class_name,"__NSDictionaryM"))
+ {
+ return (new NSDictionaryMSyntheticFrontEnd(valobj_sp));
+ }
+ else
+ {
+ auto& map(NSDictionary_Additionals::GetAdditionalSynthetics());
+ auto iter = map.find(class_name_cs), end = map.end();
+ if (iter != end)
+ return iter->second(synth, valobj_sp);
+ return (new NSDictionaryCodeRunningSyntheticFrontEnd(valobj_sp));
+ }
+}
+
+lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::NSDictionaryCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get())
+{}
+
+size_t
+lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::CalculateNumChildren ()
+{
+ uint64_t count = 0;
+ if (ExtractValueFromObjCExpression(m_backend, "int", "count", count))
+ return count;
+ return 0;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ StreamString idx_name;
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ StreamString key_fetcher_expr;
+ key_fetcher_expr.Printf("(id)[(NSArray*)[(id)0x%" PRIx64 " allKeys] objectAtIndex:%" PRIu64 "]", m_backend.GetPointerValue(), (uint64_t)idx);
+ StreamString value_fetcher_expr;
+ value_fetcher_expr.Printf("(id)[(id)0x%" PRIx64 " objectForKey:(%s)]",m_backend.GetPointerValue(),key_fetcher_expr.GetData());
+ StreamString object_fetcher_expr;
+ object_fetcher_expr.Printf("struct __lldb_autogen_nspair { id key; id value; } _lldb_valgen_item; _lldb_valgen_item.key = %s; _lldb_valgen_item.value = %s; _lldb_valgen_item;",key_fetcher_expr.GetData(),value_fetcher_expr.GetData());
+ lldb::ValueObjectSP child_sp;
+ EvaluateExpressionOptions options;
+ options.SetKeepInMemory(true);
+ options.SetLanguage(lldb::eLanguageTypeObjC_plus_plus);
+ options.SetResultIsInternal(true);
+ m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(),
+ GetViableFrame(m_backend.GetTargetSP().get()),
+ child_sp,
+ options);
+ if (child_sp)
+ child_sp->SetName(ConstString(idx_name.GetData()));
+ return child_sp;
+}
+
+bool
+lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::Update()
+{
+ return false;
+}
+
+bool
+lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+size_t
+lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ return 0;
+}
+
+lldb_private::formatters::NSDictionaryISyntheticFrontEnd::NSDictionaryISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_exe_ctx_ref(),
+m_ptr_size(8),
+m_order(lldb::eByteOrderInvalid),
+m_data_32(NULL),
+m_data_64(NULL),
+m_pair_type()
+{
+}
+
+lldb_private::formatters::NSDictionaryISyntheticFrontEnd::~NSDictionaryISyntheticFrontEnd ()
+{
+ delete m_data_32;
+ m_data_32 = NULL;
+ delete m_data_64;
+ m_data_64 = NULL;
+}
+
+size_t
+lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ const char* item_name = name.GetCString();
+ uint32_t idx = ExtractIndexFromString(item_name);
+ if (idx < UINT32_MAX && idx >= CalculateNumChildren())
+ return UINT32_MAX;
+ return idx;
+}
+
+size_t
+lldb_private::formatters::NSDictionaryISyntheticFrontEnd::CalculateNumChildren ()
+{
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return (m_data_32 ? m_data_32->_used : m_data_64->_used);
+}
+
+bool
+lldb_private::formatters::NSDictionaryISyntheticFrontEnd::Update()
+{
+ m_children.clear();
+ delete m_data_32;
+ m_data_32 = NULL;
+ delete m_data_64;
+ m_data_64 = NULL;
+ m_ptr_size = 0;
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ if (!valobj_sp)
+ return false;
+ m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+ Error error;
+ error.Clear();
+ lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return false;
+ m_ptr_size = process_sp->GetAddressByteSize();
+ m_order = process_sp->GetByteOrder();
+ uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
+ if (m_ptr_size == 4)
+ {
+ m_data_32 = new DataDescriptor_32();
+ process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
+ }
+ else
+ {
+ m_data_64 = new DataDescriptor_64();
+ process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
+ }
+ if (error.Fail())
+ return false;
+ m_data_ptr = data_location + m_ptr_size;
+ return false;
+}
+
+bool
+lldb_private::formatters::NSDictionaryISyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ uint32_t num_children = CalculateNumChildren();
+
+ if (idx >= num_children)
+ return lldb::ValueObjectSP();
+
+ if (m_children.empty())
+ {
+ // do the scan phase
+ lldb::addr_t key_at_idx = 0, val_at_idx = 0;
+
+ uint32_t tries = 0;
+ uint32_t test_idx = 0;
+
+ while(tries < num_children)
+ {
+ key_at_idx = m_data_ptr + (2*test_idx * m_ptr_size);
+ val_at_idx = key_at_idx + m_ptr_size;
+ ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
+ if (!process_sp)
+ return lldb::ValueObjectSP();
+ Error error;
+ key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
+ if (error.Fail())
+ return lldb::ValueObjectSP();
+ val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
+ if (error.Fail())
+ return lldb::ValueObjectSP();
+
+ test_idx++;
+
+ if (!key_at_idx || !val_at_idx)
+ continue;
+ tries++;
+
+ DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()};
+
+ m_children.push_back(descriptor);
+ }
+ }
+
+ if (idx >= m_children.size()) // should never happen
+ return lldb::ValueObjectSP();
+
+ DictionaryItemDescriptor &dict_item = m_children[idx];
+ if (!dict_item.valobj_sp)
+ {
+ if (!m_pair_type.IsValid())
+ {
+ TargetSP target_sp(m_backend.GetTargetSP());
+ if (!target_sp)
+ return ValueObjectSP();
+ m_pair_type = GetLLDBNSPairType(target_sp);
+ }
+ if (!m_pair_type.IsValid())
+ return ValueObjectSP();
+
+ DataBufferSP buffer_sp(new DataBufferHeap(2*m_ptr_size,0));
+
+ if (m_ptr_size == 8)
+ {
+ uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
+ *data_ptr = dict_item.key_ptr;
+ *(data_ptr+1) = dict_item.val_ptr;
+ }
+ else
+ {
+ uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
+ *data_ptr = dict_item.key_ptr;
+ *(data_ptr+1) = dict_item.val_ptr;
+ }
+
+ StreamString idx_name;
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ DataExtractor data(buffer_sp, m_order, m_ptr_size);
+ dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(),
+ data,
+ m_exe_ctx_ref,
+ m_pair_type);
+ }
+ return dict_item.valobj_sp;
+}
+
+lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_exe_ctx_ref(),
+m_ptr_size(8),
+m_order(lldb::eByteOrderInvalid),
+m_data_32(NULL),
+m_data_64(NULL),
+m_pair_type()
+{
+}
+
+lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::~NSDictionaryMSyntheticFrontEnd ()
+{
+ delete m_data_32;
+ m_data_32 = NULL;
+ delete m_data_64;
+ m_data_64 = NULL;
+}
+
+size_t
+lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ const char* item_name = name.GetCString();
+ uint32_t idx = ExtractIndexFromString(item_name);
+ if (idx < UINT32_MAX && idx >= CalculateNumChildren())
+ return UINT32_MAX;
+ return idx;
+}
+
+size_t
+lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::CalculateNumChildren ()
+{
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return (m_data_32 ? m_data_32->_used : m_data_64->_used);
+}
+
+bool
+lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update()
+{
+ m_children.clear();
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ m_ptr_size = 0;
+ delete m_data_32;
+ m_data_32 = NULL;
+ delete m_data_64;
+ m_data_64 = NULL;
+ if (!valobj_sp)
+ return false;
+ m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+ Error error;
+ error.Clear();
+ lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return false;
+ m_ptr_size = process_sp->GetAddressByteSize();
+ m_order = process_sp->GetByteOrder();
+ uint64_t data_location = valobj_sp->GetValueAsUnsigned(0) + m_ptr_size;
+ if (m_ptr_size == 4)
+ {
+ m_data_32 = new DataDescriptor_32();
+ process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
+ }
+ else
+ {
+ m_data_64 = new DataDescriptor_64();
+ process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
+ }
+ if (error.Fail())
+ return false;
+ return false;
+}
+
+bool
+lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ lldb::addr_t m_keys_ptr = (m_data_32 ? m_data_32->_keys_addr : m_data_64->_keys_addr);
+ lldb::addr_t m_values_ptr = (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr);
+
+ uint32_t num_children = CalculateNumChildren();
+
+ if (idx >= num_children)
+ return lldb::ValueObjectSP();
+
+ if (m_children.empty())
+ {
+ // do the scan phase
+ lldb::addr_t key_at_idx = 0, val_at_idx = 0;
+
+ uint32_t tries = 0;
+ uint32_t test_idx = 0;
+
+ while(tries < num_children)
+ {
+ key_at_idx = m_keys_ptr + (test_idx * m_ptr_size);
+ val_at_idx = m_values_ptr + (test_idx * m_ptr_size);;
+ ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
+ if (!process_sp)
+ return lldb::ValueObjectSP();
+ Error error;
+ key_at_idx = process_sp->ReadPointerFromMemory(key_at_idx, error);
+ if (error.Fail())
+ return lldb::ValueObjectSP();
+ val_at_idx = process_sp->ReadPointerFromMemory(val_at_idx, error);
+ if (error.Fail())
+ return lldb::ValueObjectSP();
+
+ test_idx++;
+
+ if (!key_at_idx || !val_at_idx)
+ continue;
+ tries++;
+
+ DictionaryItemDescriptor descriptor = {key_at_idx,val_at_idx,lldb::ValueObjectSP()};
+
+ m_children.push_back(descriptor);
+ }
+ }
+
+ if (idx >= m_children.size()) // should never happen
+ return lldb::ValueObjectSP();
+
+ DictionaryItemDescriptor &dict_item = m_children[idx];
+ if (!dict_item.valobj_sp)
+ {
+ if (!m_pair_type.IsValid())
+ {
+ TargetSP target_sp(m_backend.GetTargetSP());
+ if (!target_sp)
+ return ValueObjectSP();
+ m_pair_type = GetLLDBNSPairType(target_sp);
+ }
+ if (!m_pair_type.IsValid())
+ return ValueObjectSP();
+
+ DataBufferSP buffer_sp(new DataBufferHeap(2*m_ptr_size,0));
+
+ if (m_ptr_size == 8)
+ {
+ uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
+ *data_ptr = dict_item.key_ptr;
+ *(data_ptr+1) = dict_item.val_ptr;
+ }
+ else
+ {
+ uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
+ *data_ptr = dict_item.key_ptr;
+ *(data_ptr+1) = dict_item.val_ptr;
+ }
+
+ StreamString idx_name;
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ DataExtractor data(buffer_sp, m_order, m_ptr_size);
+ dict_item.valobj_sp = CreateValueObjectFromData(idx_name.GetData(),
+ data,
+ m_exe_ctx_ref,
+ m_pair_type);
+ }
+ return dict_item.valobj_sp;
+}
+
+template bool
+lldb_private::formatters::NSDictionarySummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&);
+
+template bool
+lldb_private::formatters::NSDictionarySummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&);
diff --git a/source/Plugins/Language/ObjC/NSDictionary.h b/source/Plugins/Language/ObjC/NSDictionary.h
new file mode 100644
index 000000000000..e96c25a97b2b
--- /dev/null
+++ b/source/Plugins/Language/ObjC/NSDictionary.h
@@ -0,0 +1,48 @@
+//===-- NSDictionary.h ---------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_NSDictionary_h_
+#define liblldb_NSDictionary_h_
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+
+#include <map>
+
+namespace lldb_private {
+ namespace formatters
+ {
+ template<bool name_entries>
+ bool
+ NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ extern template bool
+ NSDictionarySummaryProvider<true> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
+
+ extern template bool
+ NSDictionarySummaryProvider<false> (ValueObject&, Stream&, const TypeSummaryOptions&) ;
+
+ SyntheticChildrenFrontEnd* NSDictionarySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ class NSDictionary_Additionals
+ {
+ public:
+ static std::map<ConstString, CXXFunctionSummaryFormat::Callback>&
+ GetAdditionalSummaries ();
+
+ static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>&
+ GetAdditionalSynthetics ();
+ };
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_NSDictionary_h_
diff --git a/source/Plugins/Language/ObjC/NSError.cpp b/source/Plugins/Language/ObjC/NSError.cpp
new file mode 100644
index 000000000000..c627cd031926
--- /dev/null
+++ b/source/Plugins/Language/ObjC/NSError.cpp
@@ -0,0 +1,218 @@
+//===-- NSError.cpp ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "clang/AST/DeclCXX.h"
+
+// Project includes
+#include "Cocoa.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Target.h"
+
+#include "lldb/Utility/ProcessStructReader.h"
+
+#include "Plugins/Language/ObjC/NSString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+bool
+lldb_private::formatters::NSError_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ ProcessSP process_sp(valobj.GetProcessSP());
+ if (!process_sp)
+ return false;
+
+ lldb::addr_t ptr_value = LLDB_INVALID_ADDRESS;
+
+ CompilerType valobj_type(valobj.GetCompilerType());
+ Flags type_flags(valobj_type.GetTypeInfo());
+ if (type_flags.AllClear(eTypeHasValue))
+ {
+ if (valobj.IsBaseClass() && valobj.GetParent())
+ ptr_value = valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ }
+ else
+ ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+
+ if (ptr_value == LLDB_INVALID_ADDRESS)
+ return false;
+ size_t ptr_size = process_sp->GetAddressByteSize();
+ lldb::addr_t code_location = ptr_value + 2 * ptr_size;
+ lldb::addr_t domain_location = ptr_value + 3 * ptr_size;
+
+ Error error;
+ uint64_t code = process_sp->ReadUnsignedIntegerFromMemory(code_location, ptr_size, 0, error);
+ if (error.Fail())
+ return false;
+
+ lldb::addr_t domain_str_value = process_sp->ReadPointerFromMemory(domain_location, error);
+ if (error.Fail() || domain_str_value == LLDB_INVALID_ADDRESS)
+ return false;
+
+ if (!domain_str_value)
+ {
+ stream.Printf("domain: nil - code: %" PRIu64, code);
+ return true;
+ }
+
+ InferiorSizedWord isw(domain_str_value, *process_sp);
+
+ ValueObjectSP domain_str_sp = ValueObject::CreateValueObjectFromData("domain_str", isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeVoid).GetPointerType());
+
+ if (!domain_str_sp)
+ return false;
+
+ StreamString domain_str_summary;
+ if (NSStringSummaryProvider(*domain_str_sp, domain_str_summary, options) && !domain_str_summary.Empty())
+ {
+ stream.Printf("domain: %s - code: %" PRIu64, domain_str_summary.GetData(), code);
+ return true;
+ }
+ else
+ {
+ stream.Printf("domain: nil - code: %" PRIu64, code);
+ return true;
+ }
+}
+
+class NSErrorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+{
+public:
+ NSErrorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+ SyntheticChildrenFrontEnd(*valobj_sp)
+ {}
+
+ ~NSErrorSyntheticFrontEnd() override = default;
+ // no need to delete m_child_ptr - it's kept alive by the cluster manager on our behalf
+
+ size_t
+ CalculateNumChildren() override
+ {
+ if (m_child_ptr)
+ return 1;
+ if (m_child_sp)
+ return 1;
+ return 0;
+ }
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override
+ {
+ if (idx != 0)
+ return lldb::ValueObjectSP();
+
+ if (m_child_ptr)
+ return m_child_ptr->GetSP();
+ return m_child_sp;
+ }
+
+ bool
+ Update() override
+ {
+ m_child_ptr = nullptr;
+ m_child_sp.reset();
+
+ ProcessSP process_sp(m_backend.GetProcessSP());
+ if (!process_sp)
+ return false;
+
+ lldb::addr_t userinfo_location = LLDB_INVALID_ADDRESS;
+
+ CompilerType valobj_type(m_backend.GetCompilerType());
+ Flags type_flags(valobj_type.GetTypeInfo());
+ if (type_flags.AllClear(eTypeHasValue))
+ {
+ if (m_backend.IsBaseClass() && m_backend.GetParent())
+ userinfo_location = m_backend.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ }
+ else
+ userinfo_location = m_backend.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+
+ if (userinfo_location == LLDB_INVALID_ADDRESS)
+ return false;
+
+ size_t ptr_size = process_sp->GetAddressByteSize();
+
+ userinfo_location += 4 * ptr_size;
+ Error error;
+ lldb::addr_t userinfo = process_sp->ReadPointerFromMemory(userinfo_location, error);
+ if (userinfo == LLDB_INVALID_ADDRESS || error.Fail())
+ return false;
+ InferiorSizedWord isw(userinfo,*process_sp);
+ m_child_sp = ValueObject::CreateValueObjectFromData("_userInfo",
+ isw.GetAsData(process_sp->GetByteOrder()),
+ m_backend.GetExecutionContextRef(),
+ process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeObjCID));
+ return false;
+ }
+
+ bool
+ MightHaveChildren() override
+ {
+ return true;
+ }
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override
+ {
+ static ConstString g___userInfo("_userInfo");
+ if (name == g___userInfo)
+ return 0;
+ return UINT32_MAX;
+ }
+
+private:
+ // the child here can be "real" (i.e. an actual child of the root) or synthetized from raw memory
+ // if the former, I need to store a plain pointer to it - or else a loop of references will cause this entire hierarchy of values to leak
+ // if the latter, then I need to store a SharedPointer to it - so that it only goes away when everyone else in the cluster goes away
+ // oh joy!
+ ValueObject* m_child_ptr;
+ ValueObjectSP m_child_sp;
+};
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::NSErrorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return nullptr;
+ ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+ if (!runtime)
+ return nullptr;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return nullptr;
+
+ const char* class_name = descriptor->GetClassName().GetCString();
+
+ if (!class_name || !*class_name)
+ return nullptr;
+
+ if (!strcmp(class_name,"NSError"))
+ return (new NSErrorSyntheticFrontEnd(valobj_sp));
+ else if (!strcmp(class_name,"__NSCFError"))
+ return (new NSErrorSyntheticFrontEnd(valobj_sp));
+
+ return nullptr;
+}
diff --git a/source/Plugins/Language/ObjC/NSException.cpp b/source/Plugins/Language/ObjC/NSException.cpp
new file mode 100644
index 000000000000..e58223a4d461
--- /dev/null
+++ b/source/Plugins/Language/ObjC/NSException.cpp
@@ -0,0 +1,219 @@
+//===-- NSException.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "clang/AST/DeclCXX.h"
+
+// Project includes
+#include "Cocoa.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Target.h"
+
+#include "lldb/Utility/ProcessStructReader.h"
+
+#include "Plugins/Language/ObjC/NSString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+bool
+lldb_private::formatters::NSException_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ ProcessSP process_sp(valobj.GetProcessSP());
+ if (!process_sp)
+ return false;
+
+ lldb::addr_t ptr_value = LLDB_INVALID_ADDRESS;
+
+ CompilerType valobj_type(valobj.GetCompilerType());
+ Flags type_flags(valobj_type.GetTypeInfo());
+ if (type_flags.AllClear(eTypeHasValue))
+ {
+ if (valobj.IsBaseClass() && valobj.GetParent())
+ ptr_value = valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ }
+ else
+ ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+
+ if (ptr_value == LLDB_INVALID_ADDRESS)
+ return false;
+ size_t ptr_size = process_sp->GetAddressByteSize();
+ lldb::addr_t name_location = ptr_value + 1 * ptr_size;
+ lldb::addr_t reason_location = ptr_value + 2 * ptr_size;
+
+ Error error;
+ lldb::addr_t name = process_sp->ReadPointerFromMemory(name_location, error);
+ if (error.Fail() || name == LLDB_INVALID_ADDRESS)
+ return false;
+
+ lldb::addr_t reason = process_sp->ReadPointerFromMemory(reason_location, error);
+ if (error.Fail() || reason == LLDB_INVALID_ADDRESS)
+ return false;
+
+ InferiorSizedWord name_isw(name, *process_sp);
+ InferiorSizedWord reason_isw(reason, *process_sp);
+
+ CompilerType voidstar = process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
+
+ ValueObjectSP name_sp = ValueObject::CreateValueObjectFromData("name_str", name_isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), voidstar);
+ ValueObjectSP reason_sp = ValueObject::CreateValueObjectFromData("reason_str", reason_isw.GetAsData(process_sp->GetByteOrder()), valobj.GetExecutionContextRef(), voidstar);
+
+ if (!name_sp || !reason_sp)
+ 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());
+ return true;
+ }
+ else
+ return false;
+}
+
+class NSExceptionSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+{
+public:
+ NSExceptionSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+ SyntheticChildrenFrontEnd(*valobj_sp)
+ {}
+
+ ~NSExceptionSyntheticFrontEnd() override = default;
+ // no need to delete m_child_ptr - it's kept alive by the cluster manager on our behalf
+
+ size_t
+ CalculateNumChildren() override
+ {
+ if (m_child_ptr)
+ return 1;
+ if (m_child_sp)
+ return 1;
+ return 0;
+ }
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override
+ {
+ if (idx != 0)
+ return lldb::ValueObjectSP();
+
+ if (m_child_ptr)
+ return m_child_ptr->GetSP();
+ return m_child_sp;
+ }
+
+ bool
+ Update() override
+ {
+ m_child_ptr = nullptr;
+ m_child_sp.reset();
+
+ ProcessSP process_sp(m_backend.GetProcessSP());
+ if (!process_sp)
+ return false;
+
+ lldb::addr_t userinfo_location = LLDB_INVALID_ADDRESS;
+
+ CompilerType valobj_type(m_backend.GetCompilerType());
+ Flags type_flags(valobj_type.GetTypeInfo());
+ if (type_flags.AllClear(eTypeHasValue))
+ {
+ if (m_backend.IsBaseClass() && m_backend.GetParent())
+ userinfo_location = m_backend.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ }
+ else
+ userinfo_location = m_backend.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+
+ if (userinfo_location == LLDB_INVALID_ADDRESS)
+ return false;
+
+ size_t ptr_size = process_sp->GetAddressByteSize();
+
+ userinfo_location += 3 * ptr_size;
+ Error error;
+ lldb::addr_t userinfo = process_sp->ReadPointerFromMemory(userinfo_location, error);
+ if (userinfo == LLDB_INVALID_ADDRESS || error.Fail())
+ return false;
+ InferiorSizedWord isw(userinfo,*process_sp);
+ m_child_sp = ValueObject::CreateValueObjectFromData("userInfo",
+ isw.GetAsData(process_sp->GetByteOrder()),
+ m_backend.GetExecutionContextRef(),
+ process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeObjCID));
+ return false;
+ }
+
+ bool
+ MightHaveChildren() override
+ {
+ return true;
+ }
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override
+ {
+ static ConstString g___userInfo("userInfo");
+ if (name == g___userInfo)
+ return 0;
+ return UINT32_MAX;
+ }
+
+private:
+ // the child here can be "real" (i.e. an actual child of the root) or synthetized from raw memory
+ // if the former, I need to store a plain pointer to it - or else a loop of references will cause this entire hierarchy of values to leak
+ // if the latter, then I need to store a SharedPointer to it - so that it only goes away when everyone else in the cluster goes away
+ // oh joy!
+ ValueObject* m_child_ptr;
+ ValueObjectSP m_child_sp;
+};
+
+SyntheticChildrenFrontEnd*
+lldb_private::formatters::NSExceptionSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+{
+ lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return nullptr;
+ ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+ if (!runtime)
+ return nullptr;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return nullptr;
+
+ const char* class_name = descriptor->GetClassName().GetCString();
+
+ if (!class_name || !*class_name)
+ return nullptr;
+
+ if (!strcmp(class_name,"NSException"))
+ return (new NSExceptionSyntheticFrontEnd(valobj_sp));
+ else if (!strcmp(class_name,"NSCFException"))
+ return (new NSExceptionSyntheticFrontEnd(valobj_sp));
+ else if (!strcmp(class_name,"__NSCFException"))
+ return (new NSExceptionSyntheticFrontEnd(valobj_sp));
+
+ return nullptr;
+}
diff --git a/source/Plugins/Language/ObjC/NSIndexPath.cpp b/source/Plugins/Language/ObjC/NSIndexPath.cpp
new file mode 100644
index 000000000000..245f6da80c7f
--- /dev/null
+++ b/source/Plugins/Language/ObjC/NSIndexPath.cpp
@@ -0,0 +1,349 @@
+//===-- NSIndexPath.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "Cocoa.h"
+
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+class NSIndexPathSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+{
+public:
+ NSIndexPathSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+ SyntheticChildrenFrontEnd (*valobj_sp.get()),
+ m_ptr_size(0),
+ m_uint_star_type()
+ {
+ m_ptr_size = m_backend.GetTargetSP()->GetArchitecture().GetAddressByteSize();
+ }
+
+ ~NSIndexPathSyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override
+ {
+ return m_impl.GetNumIndexes();
+ }
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override
+ {
+ return m_impl.GetIndexAtIndex(idx, m_uint_star_type);
+ }
+
+ bool
+ Update() override
+ {
+ m_impl.Clear();
+
+ TypeSystem* type_system = m_backend.GetCompilerType().GetTypeSystem();
+ if (!type_system)
+ return false;
+
+ ClangASTContext *ast = m_backend.GetExecutionContextRef().GetTargetSP()->GetScratchClangASTContext();
+ if (!ast)
+ return false;
+
+ m_uint_star_type = ast->GetPointerSizedIntType(false);
+
+ static ConstString g__indexes("_indexes");
+ static ConstString g__length("_length");
+
+ ProcessSP process_sp = m_backend.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(m_backend));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ uint64_t info_bits(0),value_bits(0),payload(0);
+
+ if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits, &payload))
+ {
+ m_impl.m_inlined.SetIndexes(payload, *process_sp);
+ m_impl.m_mode = Mode::Inlined;
+ }
+ else
+ {
+ ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _indexes_id;
+ ObjCLanguageRuntime::ClassDescriptor::iVarDescriptor _length_id;
+
+ bool has_indexes(false),has_length(false);
+
+ for (size_t x = 0;
+ x < descriptor->GetNumIVars();
+ x++)
+ {
+ const auto& ivar = descriptor->GetIVarAtIndex(x);
+ if (ivar.m_name == g__indexes)
+ {
+ _indexes_id = ivar;
+ has_indexes = true;
+ }
+ else if (ivar.m_name == g__length)
+ {
+ _length_id = ivar;
+ has_length = true;
+ }
+
+ if (has_length && has_indexes)
+ break;
+ }
+
+ if (has_length && has_indexes)
+ {
+ m_impl.m_outsourced.m_indexes = m_backend.GetSyntheticChildAtOffset(_indexes_id.m_offset,
+ m_uint_star_type.GetPointerType(),
+ true).get();
+ ValueObjectSP length_sp(m_backend.GetSyntheticChildAtOffset(_length_id.m_offset,
+ m_uint_star_type,
+ true));
+ if (length_sp)
+ {
+ m_impl.m_outsourced.m_count = length_sp->GetValueAsUnsigned(0);
+ if (m_impl.m_outsourced.m_indexes)
+ m_impl.m_mode = Mode::Outsourced;
+ }
+ }
+ }
+ return false;
+ }
+
+ bool
+ MightHaveChildren() override
+ {
+ if (m_impl.m_mode == Mode::Invalid)
+ return false;
+ return true;
+ }
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override
+ {
+ const char* item_name = name.GetCString();
+ uint32_t idx = ExtractIndexFromString(item_name);
+ if (idx < UINT32_MAX && idx >= CalculateNumChildren())
+ return UINT32_MAX;
+ return idx;
+ }
+
+ lldb::ValueObjectSP
+ GetSyntheticValue() override
+ {
+ return nullptr;
+ }
+
+protected:
+ ObjCLanguageRuntime::ClassDescriptorSP m_descriptor_sp;
+
+ enum class Mode {
+ Inlined,
+ Outsourced,
+ Invalid
+ };
+
+ struct Impl {
+ Mode m_mode;
+
+ size_t
+ GetNumIndexes ()
+ {
+ switch (m_mode)
+ {
+ case Mode::Inlined:
+ return m_inlined.GetNumIndexes();
+ case Mode::Outsourced:
+ return m_outsourced.m_count;
+ default:
+ return 0;
+ }
+ }
+
+ lldb::ValueObjectSP
+ GetIndexAtIndex (size_t idx, const CompilerType& desired_type)
+ {
+ if (idx >= GetNumIndexes())
+ return nullptr;
+ switch (m_mode)
+ {
+ default: return nullptr;
+ case Mode::Inlined:
+ return m_inlined.GetIndexAtIndex (idx, desired_type);
+ case Mode::Outsourced:
+ return m_outsourced.GetIndexAtIndex (idx);
+ }
+ }
+
+ struct InlinedIndexes {
+ public:
+ void SetIndexes(uint64_t value, Process& p)
+ {
+ m_indexes = value;
+ _lengthForInlinePayload(p.GetAddressByteSize());
+ m_process = &p;
+ }
+
+ size_t
+ GetNumIndexes ()
+ {
+ return m_count;
+ }
+
+ lldb::ValueObjectSP
+ GetIndexAtIndex (size_t idx, const CompilerType& desired_type)
+ {
+ std::pair<uint64_t, bool> value(_indexAtPositionForInlinePayload(idx));
+ if (!value.second)
+ return nullptr;
+
+ Value v;
+ if (m_ptr_size == 8)
+ {
+ Scalar scalar( (unsigned long long)value.first );
+ v = Value(scalar);
+ }
+ else
+ {
+ Scalar scalar( (unsigned int)value.first );
+ v = Value(scalar);
+ }
+
+ v.SetCompilerType(desired_type);
+
+ StreamString idx_name;
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+
+ return ValueObjectConstResult::Create(m_process, v, ConstString(idx_name.GetData()));
+ }
+
+ void
+ Clear ()
+ {
+ m_indexes = 0;
+ m_count = 0;
+ m_ptr_size = 0;
+ m_process = nullptr;
+ }
+
+ private:
+ uint64_t m_indexes;
+ size_t m_count;
+ uint32_t m_ptr_size;
+ Process *m_process;
+
+ // cfr. Foundation for the details of this code
+ size_t _lengthForInlinePayload(uint32_t ptr_size) {
+ m_ptr_size = ptr_size;
+ if (m_ptr_size == 8)
+ m_count = ((m_indexes >> 3) & 0x7);
+ else
+ m_count = ((m_indexes >> 3) & 0x3);
+ return m_count;
+ }
+
+ std::pair<uint64_t, bool>
+ _indexAtPositionForInlinePayload(size_t pos)
+ {
+ if (m_ptr_size == 8)
+ {
+ switch (pos) {
+ case 5: return {((m_indexes >> 51) & 0x1ff),true};
+ case 4: return {((m_indexes >> 42) & 0x1ff),true};
+ case 3: return {((m_indexes >> 33) & 0x1ff),true};
+ case 2: return {((m_indexes >> 24) & 0x1ff),true};
+ case 1: return {((m_indexes >> 15) & 0x1ff),true};
+ case 0: return {((m_indexes >> 6) & 0x1ff),true};
+ }
+ }
+ else
+ {
+ switch (pos) {
+ case 2: return {((m_indexes >> 23) & 0x1ff),true};
+ case 1: return {((m_indexes >> 14) & 0x1ff),true};
+ case 0: return {((m_indexes >> 5) & 0x1ff),true};
+ }
+ }
+ return {0,false};
+ }
+
+ };
+ struct OutsourcedIndexes {
+ ValueObject *m_indexes;
+ size_t m_count;
+
+ lldb::ValueObjectSP
+ GetIndexAtIndex (size_t idx)
+ {
+ if (m_indexes)
+ {
+ ValueObjectSP index_sp(m_indexes->GetSyntheticArrayMember(idx, true));
+ return index_sp;
+ }
+ return nullptr;
+ }
+
+ void
+ Clear ()
+ {
+ m_indexes = nullptr;
+ m_count = 0;
+ }
+ };
+
+ union {
+ struct InlinedIndexes m_inlined;
+ struct OutsourcedIndexes m_outsourced;
+ };
+
+ void
+ Clear ()
+ {
+ m_mode = Mode::Invalid;
+ m_inlined.Clear();
+ m_outsourced.Clear();
+ }
+ } m_impl;
+
+ uint32_t m_ptr_size;
+ CompilerType m_uint_star_type;
+};
+
+namespace lldb_private {
+ namespace formatters {
+
+ SyntheticChildrenFrontEnd* NSIndexPathSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
+ {
+ if (valobj_sp)
+ return new NSIndexPathSyntheticFrontEnd(valobj_sp);
+ return nullptr;
+ }
+
+ } // namespace formatters
+} // namespace lldb_private
diff --git a/source/Plugins/Language/ObjC/NSSet.cpp b/source/Plugins/Language/ObjC/NSSet.cpp
new file mode 100644
index 000000000000..93115957e329
--- /dev/null
+++ b/source/Plugins/Language/ObjC/NSSet.cpp
@@ -0,0 +1,758 @@
+//===-- NSSet.cpp -----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "NSSet.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Language.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+std::map<ConstString, CXXFunctionSummaryFormat::Callback>&
+NSSet_Additionals::GetAdditionalSummaries ()
+{
+ static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map;
+ return g_map;
+}
+
+std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>&
+NSSet_Additionals::GetAdditionalSynthetics ()
+{
+ static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback> g_map;
+ return g_map;
+}
+
+namespace lldb_private {
+ namespace formatters {
+ class NSSetISyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ NSSetISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSSetISyntheticFrontEnd() override;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ private:
+ struct DataDescriptor_32
+ {
+ uint32_t _used : 26;
+ uint32_t _szidx : 6;
+ };
+
+ struct DataDescriptor_64
+ {
+ uint64_t _used : 58;
+ uint32_t _szidx : 6;
+ };
+
+ struct SetItemDescriptor
+ {
+ lldb::addr_t item_ptr;
+ lldb::ValueObjectSP valobj_sp;
+ };
+
+ ExecutionContextRef m_exe_ctx_ref;
+ uint8_t m_ptr_size;
+ DataDescriptor_32 *m_data_32;
+ DataDescriptor_64 *m_data_64;
+ lldb::addr_t m_data_ptr;
+ std::vector<SetItemDescriptor> m_children;
+ };
+
+ class NSOrderedSetSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ NSOrderedSetSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSOrderedSetSyntheticFrontEnd() override = default;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ private:
+ uint32_t m_count;
+ std::map<uint32_t,lldb::ValueObjectSP> m_children;
+ };
+
+ class NSSetMSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ NSSetMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSSetMSyntheticFrontEnd() override;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+
+ private:
+ struct DataDescriptor_32
+ {
+ uint32_t _used : 26;
+ uint32_t _size;
+ uint32_t _mutations;
+ uint32_t _objs_addr;
+ };
+
+ struct DataDescriptor_64
+ {
+ uint64_t _used : 58;
+ uint64_t _size;
+ uint64_t _mutations;
+ uint64_t _objs_addr;
+ };
+
+ struct SetItemDescriptor
+ {
+ lldb::addr_t item_ptr;
+ lldb::ValueObjectSP valobj_sp;
+ };
+
+ ExecutionContextRef m_exe_ctx_ref;
+ uint8_t m_ptr_size;
+ DataDescriptor_32 *m_data_32;
+ DataDescriptor_64 *m_data_64;
+ std::vector<SetItemDescriptor> m_children;
+ };
+
+ class NSSetCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd
+ {
+ public:
+ NSSetCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
+
+ ~NSSetCodeRunningSyntheticFrontEnd() override;
+
+ size_t
+ CalculateNumChildren() override;
+
+ lldb::ValueObjectSP
+ GetChildAtIndex(size_t idx) override;
+
+ bool
+ Update() override;
+
+ bool
+ MightHaveChildren() override;
+
+ size_t
+ GetIndexOfChildWithName(const ConstString &name) override;
+ };
+ } // namespace formatters
+} // namespace lldb_private
+
+template<bool cf_style>
+bool
+lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ static ConstString g_TypeHint("NSSet");
+
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+ bool is_64bit = (ptr_size == 8);
+
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+
+ if (!valobj_addr)
+ return false;
+
+ uint64_t value = 0;
+
+ ConstString class_name_cs = descriptor->GetClassName();
+ const char* class_name = class_name_cs.GetCString();
+
+ if (!class_name || !*class_name)
+ return false;
+
+ if (!strcmp(class_name,"__NSSetI"))
+ {
+ Error error;
+ value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
+ if (error.Fail())
+ return false;
+ value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
+ }
+ else if (!strcmp(class_name,"__NSSetM"))
+ {
+ Error error;
+ value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
+ if (error.Fail())
+ return false;
+ value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U);
+ }
+ /*else if (!strcmp(class_name,"__NSCFSet"))
+ {
+ Error error;
+ value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + (is_64bit ? 20 : 12), 4, 0, error);
+ if (error.Fail())
+ return false;
+ if (is_64bit)
+ value &= ~0x1fff000000000000UL;
+ }
+ else if (!strcmp(class_name,"NSCountedSet"))
+ {
+ Error error;
+ value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error);
+ if (error.Fail())
+ return false;
+ value = process_sp->ReadUnsignedIntegerFromMemory(value + (is_64bit ? 20 : 12), 4, 0, error);
+ if (error.Fail())
+ return false;
+ if (is_64bit)
+ value &= ~0x1fff000000000000UL;
+ }*/
+ else
+ {
+ auto& map(NSSet_Additionals::GetAdditionalSummaries());
+ auto iter = map.find(class_name_cs), end = map.end();
+ if (iter != end)
+ return iter->second(valobj, stream, options);
+ if (!ExtractValueFromObjCExpression(valobj, "int", "count", value))
+ return false;
+ }
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(options.GetLanguage()))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ stream.Printf("%s%" PRIu64 " %s%s%s",
+ prefix.c_str(),
+ value,
+ "element",
+ value == 1 ? "" : "s",
+ suffix.c_str());
+ return true;
+}
+
+SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreator (CXXSyntheticChildren* synth, lldb::ValueObjectSP valobj_sp)
+{
+ lldb::ProcessSP process_sp (valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return NULL;
+ ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+ if (!runtime)
+ return NULL;
+
+ CompilerType valobj_type(valobj_sp->GetCompilerType());
+ Flags flags(valobj_type.GetTypeInfo());
+
+ if (flags.IsClear(eTypeIsPointer))
+ {
+ Error error;
+ valobj_sp = valobj_sp->AddressOf(error);
+ if (error.Fail() || !valobj_sp)
+ return NULL;
+ }
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get()));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return NULL;
+
+ ConstString class_name_cs = descriptor->GetClassName();
+ const char* class_name = class_name_cs.GetCString();
+
+ if (!class_name || !*class_name)
+ return NULL;
+
+ if (!strcmp(class_name,"__NSSetI"))
+ {
+ return (new NSSetISyntheticFrontEnd(valobj_sp));
+ }
+ else if (!strcmp(class_name,"__NSSetM"))
+ {
+ return (new NSSetMSyntheticFrontEnd(valobj_sp));
+ }
+ else if ((!strcmp(class_name,"__NSOrderedSetI")) || (!strcmp(class_name,"__NSOrderedSetM")))
+ {
+ return new NSOrderedSetSyntheticFrontEnd(valobj_sp); // this runs code
+ }
+ else
+ {
+ auto& map(NSSet_Additionals::GetAdditionalSynthetics());
+ auto iter = map.find(class_name_cs), end = map.end();
+ if (iter != end)
+ return iter->second(synth, valobj_sp);
+ return /*(new NSSetCodeRunningSyntheticFrontEnd(valobj_sp))*/ NULL;
+ }
+}
+
+lldb_private::formatters::NSSetISyntheticFrontEnd::NSSetISyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_exe_ctx_ref(),
+m_ptr_size(8),
+m_data_32(NULL),
+m_data_64(NULL)
+{
+ if (valobj_sp)
+ Update();
+}
+
+lldb_private::formatters::NSSetISyntheticFrontEnd::~NSSetISyntheticFrontEnd ()
+{
+ delete m_data_32;
+ m_data_32 = NULL;
+ delete m_data_64;
+ m_data_64 = NULL;
+}
+
+size_t
+lldb_private::formatters::NSSetISyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ const char* item_name = name.GetCString();
+ uint32_t idx = ExtractIndexFromString(item_name);
+ if (idx < UINT32_MAX && idx >= CalculateNumChildren())
+ return UINT32_MAX;
+ return idx;
+}
+
+size_t
+lldb_private::formatters::NSSetISyntheticFrontEnd::CalculateNumChildren ()
+{
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return (m_data_32 ? m_data_32->_used : m_data_64->_used);
+}
+
+bool
+lldb_private::formatters::NSSetISyntheticFrontEnd::Update()
+{
+ m_children.clear();
+ delete m_data_32;
+ m_data_32 = NULL;
+ delete m_data_64;
+ m_data_64 = NULL;
+ m_ptr_size = 0;
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ if (!valobj_sp)
+ return false;
+ if (!valobj_sp)
+ return false;
+ m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+ Error error;
+ if (valobj_sp->IsPointerType())
+ {
+ valobj_sp = valobj_sp->Dereference(error);
+ if (error.Fail() || !valobj_sp)
+ return false;
+ }
+ error.Clear();
+ lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return false;
+ m_ptr_size = process_sp->GetAddressByteSize();
+ uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
+ if (m_ptr_size == 4)
+ {
+ m_data_32 = new DataDescriptor_32();
+ process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
+ }
+ else
+ {
+ m_data_64 = new DataDescriptor_64();
+ process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
+ }
+ if (error.Fail())
+ return false;
+ m_data_ptr = data_location + m_ptr_size;
+ return false;
+}
+
+bool
+lldb_private::formatters::NSSetISyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ uint32_t num_children = CalculateNumChildren();
+
+ if (idx >= num_children)
+ return lldb::ValueObjectSP();
+
+ ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
+ if (!process_sp)
+ return lldb::ValueObjectSP();
+
+ if (m_children.empty())
+ {
+ // do the scan phase
+ lldb::addr_t obj_at_idx = 0;
+
+ uint32_t tries = 0;
+ uint32_t test_idx = 0;
+
+ while(tries < num_children)
+ {
+ obj_at_idx = m_data_ptr + (test_idx * m_ptr_size);
+ if (!process_sp)
+ return lldb::ValueObjectSP();
+ Error error;
+ obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error);
+ if (error.Fail())
+ return lldb::ValueObjectSP();
+
+ test_idx++;
+
+ if (!obj_at_idx)
+ continue;
+ tries++;
+
+ SetItemDescriptor descriptor = {obj_at_idx,lldb::ValueObjectSP()};
+
+ m_children.push_back(descriptor);
+ }
+ }
+
+ if (idx >= m_children.size()) // should never happen
+ return lldb::ValueObjectSP();
+
+ SetItemDescriptor &set_item = m_children[idx];
+ if (!set_item.valobj_sp)
+ {
+ auto ptr_size = process_sp->GetAddressByteSize();
+ DataBufferHeap buffer(ptr_size,0);
+ switch (ptr_size)
+ {
+ case 0: // architecture has no clue?? - fail
+ return lldb::ValueObjectSP();
+ case 4:
+ *((uint32_t*)buffer.GetBytes()) = (uint32_t)set_item.item_ptr;
+ break;
+ case 8:
+ *((uint64_t*)buffer.GetBytes()) = (uint64_t)set_item.item_ptr;
+ break;
+ default:
+ assert(false && "pointer size is not 4 nor 8 - get out of here ASAP");
+ }
+ StreamString idx_name;
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+
+ DataExtractor data(buffer.GetBytes(),
+ buffer.GetByteSize(),
+ process_sp->GetByteOrder(),
+ process_sp->GetAddressByteSize());
+
+ set_item.valobj_sp =
+ CreateValueObjectFromData(idx_name.GetData(),
+ data,
+ m_exe_ctx_ref,
+ m_backend.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
+ }
+ return set_item.valobj_sp;
+}
+
+lldb_private::formatters::NSSetMSyntheticFrontEnd::NSSetMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_exe_ctx_ref(),
+m_ptr_size(8),
+m_data_32(NULL),
+m_data_64(NULL)
+{
+ if (valobj_sp)
+ Update ();
+}
+
+lldb_private::formatters::NSSetMSyntheticFrontEnd::~NSSetMSyntheticFrontEnd ()
+{
+ delete m_data_32;
+ m_data_32 = NULL;
+ delete m_data_64;
+ m_data_64 = NULL;
+}
+
+size_t
+lldb_private::formatters::NSSetMSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ const char* item_name = name.GetCString();
+ uint32_t idx = ExtractIndexFromString(item_name);
+ if (idx < UINT32_MAX && idx >= CalculateNumChildren())
+ return UINT32_MAX;
+ return idx;
+}
+
+size_t
+lldb_private::formatters::NSSetMSyntheticFrontEnd::CalculateNumChildren ()
+{
+ if (!m_data_32 && !m_data_64)
+ return 0;
+ return (m_data_32 ? m_data_32->_used : m_data_64->_used);
+}
+
+bool
+lldb_private::formatters::NSSetMSyntheticFrontEnd::Update()
+{
+ m_children.clear();
+ ValueObjectSP valobj_sp = m_backend.GetSP();
+ m_ptr_size = 0;
+ delete m_data_32;
+ m_data_32 = NULL;
+ delete m_data_64;
+ m_data_64 = NULL;
+ if (!valobj_sp)
+ return false;
+ if (!valobj_sp)
+ return false;
+ m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
+ Error error;
+ if (valobj_sp->IsPointerType())
+ {
+ valobj_sp = valobj_sp->Dereference(error);
+ if (error.Fail() || !valobj_sp)
+ return false;
+ }
+ error.Clear();
+ lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
+ if (!process_sp)
+ return false;
+ m_ptr_size = process_sp->GetAddressByteSize();
+ uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
+ if (m_ptr_size == 4)
+ {
+ m_data_32 = new DataDescriptor_32();
+ process_sp->ReadMemory (data_location, m_data_32, sizeof(DataDescriptor_32), error);
+ }
+ else
+ {
+ m_data_64 = new DataDescriptor_64();
+ process_sp->ReadMemory (data_location, m_data_64, sizeof(DataDescriptor_64), error);
+ }
+ if (error.Fail())
+ return false;
+ return false;
+}
+
+bool
+lldb_private::formatters::NSSetMSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ lldb::addr_t m_objs_addr = (m_data_32 ? m_data_32->_objs_addr : m_data_64->_objs_addr);
+
+ uint32_t num_children = CalculateNumChildren();
+
+ if (idx >= num_children)
+ return lldb::ValueObjectSP();
+
+ ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
+ if (!process_sp)
+ return lldb::ValueObjectSP();
+
+ if (m_children.empty())
+ {
+ // do the scan phase
+ lldb::addr_t obj_at_idx = 0;
+
+ uint32_t tries = 0;
+ uint32_t test_idx = 0;
+
+ while(tries < num_children)
+ {
+ obj_at_idx = m_objs_addr + (test_idx * m_ptr_size);
+ if (!process_sp)
+ return lldb::ValueObjectSP();
+ Error error;
+ obj_at_idx = process_sp->ReadPointerFromMemory(obj_at_idx, error);
+ if (error.Fail())
+ return lldb::ValueObjectSP();
+
+ test_idx++;
+
+ if (!obj_at_idx)
+ continue;
+ tries++;
+
+ SetItemDescriptor descriptor = {obj_at_idx,lldb::ValueObjectSP()};
+
+ m_children.push_back(descriptor);
+ }
+ }
+
+ if (idx >= m_children.size()) // should never happen
+ return lldb::ValueObjectSP();
+
+ SetItemDescriptor &set_item = m_children[idx];
+ if (!set_item.valobj_sp)
+ {
+ auto ptr_size = process_sp->GetAddressByteSize();
+ DataBufferHeap buffer(ptr_size,0);
+ switch (ptr_size)
+ {
+ case 0: // architecture has no clue?? - fail
+ return lldb::ValueObjectSP();
+ case 4:
+ *((uint32_t*)buffer.GetBytes()) = (uint32_t)set_item.item_ptr;
+ break;
+ case 8:
+ *((uint64_t*)buffer.GetBytes()) = (uint64_t)set_item.item_ptr;
+ break;
+ default:
+ assert(false && "pointer size is not 4 nor 8 - get out of here ASAP");
+ }
+ StreamString idx_name;
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+
+ DataExtractor data(buffer.GetBytes(),
+ buffer.GetByteSize(),
+ process_sp->GetByteOrder(),
+ process_sp->GetAddressByteSize());
+
+ set_item.valobj_sp =
+ CreateValueObjectFromData(idx_name.GetData(),
+ data,
+ m_exe_ctx_ref,
+ m_backend.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
+ }
+ return set_item.valobj_sp;
+}
+
+lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::NSOrderedSetSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
+SyntheticChildrenFrontEnd(*valobj_sp.get()),
+m_count(UINT32_MAX),
+m_children()
+{}
+
+size_t
+lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::CalculateNumChildren ()
+{
+ if (m_count != UINT32_MAX)
+ return m_count;
+ uint64_t count_temp;
+ if (ExtractValueFromObjCExpression(m_backend,"unsigned int","count",count_temp))
+ return (m_count = count_temp);
+ return (m_count = 0);
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::GetChildAtIndex (size_t idx)
+{
+ auto iter = m_children.find(idx);
+ if (iter == m_children.end())
+ {
+ lldb::ValueObjectSP retval_sp;
+ if (idx <= m_count)
+ {
+ retval_sp = CallSelectorOnObject(m_backend, "id", "objectAtIndex", idx);
+ if (retval_sp)
+ {
+ StreamString idx_name;
+ idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ retval_sp->SetName(ConstString(idx_name.GetData()));
+ }
+ m_children[idx] = retval_sp;
+ }
+ return retval_sp;
+ }
+ else
+ return iter->second;
+}
+
+bool
+lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::Update()
+{
+ return false;
+}
+
+bool
+lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::MightHaveChildren ()
+{
+ return true;
+}
+
+size_t
+lldb_private::formatters::NSOrderedSetSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
+{
+ const char* item_name = name.GetCString();
+ uint32_t idx = ExtractIndexFromString(item_name);
+ if (idx < UINT32_MAX && idx >= CalculateNumChildren())
+ return UINT32_MAX;
+ return idx;
+}
+
+template bool
+lldb_private::formatters::NSSetSummaryProvider<true> (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+template bool
+lldb_private::formatters::NSSetSummaryProvider<false> (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
diff --git a/source/Plugins/Language/ObjC/NSSet.h b/source/Plugins/Language/ObjC/NSSet.h
new file mode 100644
index 000000000000..c8622706e860
--- /dev/null
+++ b/source/Plugins/Language/ObjC/NSSet.h
@@ -0,0 +1,40 @@
+//===-- NSSet.h ---------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_NSSet_h_
+#define liblldb_NSSet_h_
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+
+namespace lldb_private {
+ namespace formatters
+ {
+ template<bool cf_style>
+ bool
+ NSSetSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ SyntheticChildrenFrontEnd* NSSetSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
+
+ class NSSet_Additionals
+ {
+ public:
+ static std::map<ConstString, CXXFunctionSummaryFormat::Callback>&
+ GetAdditionalSummaries ();
+
+ static std::map<ConstString, CXXSyntheticChildren::CreateFrontEndCallback>&
+ GetAdditionalSynthetics ();
+ };
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_NSSet_h_
diff --git a/source/Plugins/Language/ObjC/NSString.cpp b/source/Plugins/Language/ObjC/NSString.cpp
new file mode 100644
index 000000000000..80896631baf3
--- /dev/null
+++ b/source/Plugins/Language/ObjC/NSString.cpp
@@ -0,0 +1,405 @@
+//===-- NSString.cpp ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "NSString.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/DataFormatters/StringPrinter.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/Language.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/ProcessStructReader.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+std::map<ConstString, CXXFunctionSummaryFormat::Callback>&
+NSString_Additionals::GetAdditionalSummaries ()
+{
+ static std::map<ConstString, CXXFunctionSummaryFormat::Callback> g_map;
+ return g_map;
+}
+
+static CompilerType
+GetNSPathStore2Type (Target &target)
+{
+ static ConstString g_type_name("__lldb_autogen_nspathstore2");
+
+ ClangASTContext *ast_ctx = target.GetScratchClangASTContext();
+
+ if (!ast_ctx)
+ return CompilerType();
+
+ CompilerType voidstar = ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
+ CompilerType uint32 = ast_ctx->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
+
+ return ast_ctx->GetOrCreateStructForIdentifier(g_type_name, {
+ {"isa",voidstar},
+ {"lengthAndRef",uint32},
+ {"buffer",voidstar}
+ });
+}
+
+bool
+lldb_private::formatters::NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options)
+{
+ static ConstString g_TypeHint("NSString");
+
+ ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ return false;
+
+ ObjCLanguageRuntime* runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+
+ if (!runtime)
+ return false;
+
+ ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj));
+
+ if (!descriptor.get() || !descriptor->IsValid())
+ return false;
+
+ uint32_t ptr_size = process_sp->GetAddressByteSize();
+
+ lldb::addr_t valobj_addr = valobj.GetValueAsUnsigned(0);
+
+ if (!valobj_addr)
+ return false;
+
+ ConstString class_name_cs = descriptor->GetClassName();
+ const char* class_name = class_name_cs.GetCString();
+
+ if (!class_name || !*class_name)
+ return false;
+
+ bool is_tagged_ptr = (0 == strcmp(class_name,"NSTaggedPointerString")) && descriptor->GetTaggedPointerInfo();
+ // for a tagged pointer, the descriptor has everything we need
+ if (is_tagged_ptr)
+ return NSTaggedString_SummaryProvider(valobj, descriptor, stream, summary_options);
+
+ auto& additionals_map(NSString_Additionals::GetAdditionalSummaries());
+ auto iter = additionals_map.find(class_name_cs), end = additionals_map.end();
+ if (iter != end)
+ return iter->second(valobj, stream, summary_options);
+
+ // if not a tagged pointer that we know about, try the normal route
+ uint64_t info_bits_location = valobj_addr + ptr_size;
+ if (process_sp->GetByteOrder() != lldb::eByteOrderLittle)
+ info_bits_location += 3;
+
+ Error error;
+
+ uint8_t info_bits = process_sp->ReadUnsignedIntegerFromMemory(info_bits_location, 1, 0, error);
+ if (error.Fail())
+ return false;
+
+ bool is_mutable = (info_bits & 1) == 1;
+ bool is_inline = (info_bits & 0x60) == 0;
+ bool has_explicit_length = (info_bits & (1 | 4)) != 4;
+ bool is_unicode = (info_bits & 0x10) == 0x10;
+ bool is_path_store = strcmp(class_name,"NSPathStore2") == 0;
+ bool has_null = (info_bits & 8) == 8;
+
+ size_t explicit_length = 0;
+ if (!has_null && has_explicit_length && !is_path_store)
+ {
+ lldb::addr_t explicit_length_offset = 2*ptr_size;
+ if (is_mutable && !is_inline)
+ explicit_length_offset = explicit_length_offset + ptr_size; // notInlineMutable.length;
+ else if (is_inline)
+ explicit_length = explicit_length + 0; // inline1.length;
+ else if (!is_inline && !is_mutable)
+ explicit_length_offset = explicit_length_offset + ptr_size; // notInlineImmutable1.length;
+ else
+ explicit_length_offset = 0;
+
+ if (explicit_length_offset)
+ {
+ explicit_length_offset = valobj_addr + explicit_length_offset;
+ explicit_length = process_sp->ReadUnsignedIntegerFromMemory(explicit_length_offset, 4, 0, error);
+ }
+ }
+
+ if (strcmp(class_name,"NSString") &&
+ strcmp(class_name,"CFStringRef") &&
+ strcmp(class_name,"CFMutableStringRef") &&
+ strcmp(class_name,"__NSCFConstantString") &&
+ strcmp(class_name,"__NSCFString") &&
+ strcmp(class_name,"NSCFConstantString") &&
+ strcmp(class_name,"NSCFString") &&
+ strcmp(class_name,"NSPathStore2"))
+ {
+ // not one of us - but tell me class name
+ stream.Printf("class name = %s",class_name);
+ return true;
+ }
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(summary_options.GetLanguage()))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+ options.SetPrefixToken(prefix);
+ options.SetSuffixToken(suffix);
+
+ if (is_mutable)
+ {
+ uint64_t location = 2 * ptr_size + valobj_addr;
+ location = process_sp->ReadPointerFromMemory(location, error);
+ if (error.Fail())
+ return false;
+ if (has_explicit_length && is_unicode)
+ {
+ options.SetLocation(location);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetQuote('"');
+ options.SetSourceSize(explicit_length);
+ options.SetNeedsZeroTermination(false);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ options.SetBinaryZeroIsTerminator(false);
+ options.SetLanguage(summary_options.GetLanguage());
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16>(options);
+ }
+ else
+ {
+ options.SetLocation(location+1);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetSourceSize(explicit_length);
+ options.SetNeedsZeroTermination(false);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ options.SetBinaryZeroIsTerminator(false);
+ options.SetLanguage(summary_options.GetLanguage());
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII>(options);
+ }
+ }
+ else if (is_inline && has_explicit_length && !is_unicode && !is_path_store && !is_mutable)
+ {
+ uint64_t location = 3 * ptr_size + valobj_addr;
+
+ options.SetLocation(location);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetQuote('"');
+ options.SetSourceSize(explicit_length);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ options.SetLanguage(summary_options.GetLanguage());
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII> (options);
+ }
+ else if (is_unicode)
+ {
+ uint64_t location = valobj_addr + 2*ptr_size;
+ if (is_inline)
+ {
+ if (!has_explicit_length)
+ {
+ stream.Printf("found new combo");
+ return true;
+ }
+ else
+ location += ptr_size;
+ }
+ else
+ {
+ location = process_sp->ReadPointerFromMemory(location, error);
+ if (error.Fail())
+ return false;
+ }
+ options.SetLocation(location);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetQuote('"');
+ options.SetSourceSize(explicit_length);
+ options.SetNeedsZeroTermination(has_explicit_length == false);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ options.SetBinaryZeroIsTerminator(has_explicit_length == false);
+ options.SetLanguage(summary_options.GetLanguage());
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16> (options);
+ }
+ else if (is_path_store)
+ {
+ ProcessStructReader reader(valobj.GetProcessSP().get(), valobj.GetValueAsUnsigned(0), GetNSPathStore2Type(*valobj.GetTargetSP()));
+ explicit_length = reader.GetField<uint32_t>(ConstString("lengthAndRef")) >> 20;
+ lldb::addr_t location = valobj.GetValueAsUnsigned(0) + ptr_size + 4;
+
+ options.SetLocation(location);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetQuote('"');
+ options.SetSourceSize(explicit_length);
+ options.SetNeedsZeroTermination(has_explicit_length == false);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ options.SetBinaryZeroIsTerminator(has_explicit_length == false);
+ options.SetLanguage(summary_options.GetLanguage());
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16> (options);
+ }
+ else if (is_inline)
+ {
+ uint64_t location = valobj_addr + 2*ptr_size;
+ if (!has_explicit_length)
+ {
+ // in this kind of string, the byte before the string content is a length byte
+ // so let's try and use it to handle the embedded NUL case
+ Error error;
+ explicit_length = process_sp->ReadUnsignedIntegerFromMemory(location, 1, 0, error);
+ if (error.Fail() || explicit_length == 0)
+ has_explicit_length = false;
+ else
+ has_explicit_length = true;
+ location++;
+ }
+ options.SetLocation(location);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetSourceSize(explicit_length);
+ options.SetNeedsZeroTermination(!has_explicit_length);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ options.SetBinaryZeroIsTerminator(!has_explicit_length);
+ options.SetLanguage(summary_options.GetLanguage());
+ if (has_explicit_length)
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options);
+ else
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII>(options);
+ }
+ else
+ {
+ uint64_t location = valobj_addr + 2*ptr_size;
+ location = process_sp->ReadPointerFromMemory(location, error);
+ if (error.Fail())
+ return false;
+ if (has_explicit_length && !has_null)
+ explicit_length++; // account for the fact that there is no NULL and we need to have one added
+ options.SetLocation(location);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetSourceSize(explicit_length);
+ options.SetIgnoreMaxLength(summary_options.GetCapping() == TypeSummaryCapping::eTypeSummaryUncapped);
+ options.SetLanguage(summary_options.GetLanguage());
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::ASCII>(options);
+ }
+}
+
+bool
+lldb_private::formatters::NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ TargetSP target_sp(valobj.GetTargetSP());
+ if (!target_sp)
+ return false;
+ uint32_t addr_size = target_sp->GetArchitecture().GetAddressByteSize();
+ uint64_t pointer_value = valobj.GetValueAsUnsigned(0);
+ if (!pointer_value)
+ return false;
+ pointer_value += addr_size;
+ CompilerType type(valobj.GetCompilerType());
+ ExecutionContext exe_ctx(target_sp,false);
+ ValueObjectSP child_ptr_sp(valobj.CreateValueObjectFromAddress("string_ptr", pointer_value, exe_ctx, type));
+ if (!child_ptr_sp)
+ return false;
+ DataExtractor data;
+ Error error;
+ child_ptr_sp->GetData(data, error);
+ if (error.Fail())
+ return false;
+ ValueObjectSP child_sp(child_ptr_sp->CreateValueObjectFromData("string_data", data, exe_ctx, type));
+ child_sp->GetValueAsUnsigned(0);
+ if (child_sp)
+ return NSStringSummaryProvider(*child_sp, stream, options);
+ return false;
+}
+
+bool
+lldb_private::formatters::NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ return NSAttributedStringSummaryProvider(valobj, stream, options);
+}
+
+bool
+lldb_private::formatters::NSTaggedString_SummaryProvider (ValueObject& valobj, ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream, const TypeSummaryOptions& summary_options)
+{
+ static ConstString g_TypeHint("NSString");
+
+ if (!descriptor)
+ return false;
+ uint64_t len_bits = 0, data_bits = 0;
+ if (!descriptor->GetTaggedPointerInfo(&len_bits,&data_bits,nullptr))
+ return false;
+
+ static const int g_MaxNonBitmaskedLen = 7; //TAGGED_STRING_UNPACKED_MAXLEN
+ static const int g_SixbitMaxLen = 9;
+ static const int g_fiveBitMaxLen = 11;
+
+ static const char *sixBitToCharLookup = "eilotrm.apdnsIc ufkMShjTRxgC4013" "bDNvwyUL2O856P-B79AFKEWV_zGJ/HYX";
+
+ if (len_bits > g_fiveBitMaxLen)
+ return false;
+
+ std::string prefix,suffix;
+ if (Language* language = Language::FindPlugin(summary_options.GetLanguage()))
+ {
+ if (!language->GetFormatterPrefixSuffix(valobj, g_TypeHint, prefix, suffix))
+ {
+ prefix.clear();
+ suffix.clear();
+ }
+ }
+
+ // this is a fairly ugly trick - pretend that the numeric value is actually a char*
+ // this works under a few assumptions:
+ // little endian architecture
+ // sizeof(uint64_t) > g_MaxNonBitmaskedLen
+ if (len_bits <= g_MaxNonBitmaskedLen)
+ {
+ stream.Printf("%s",prefix.c_str());
+ stream.Printf("\"%s\"",(const char*)&data_bits);
+ stream.Printf("%s",suffix.c_str());
+ return true;
+ }
+
+ // if the data is bitmasked, we need to actually process the bytes
+ uint8_t bitmask = 0;
+ uint8_t shift_offset = 0;
+
+ if (len_bits <= g_SixbitMaxLen)
+ {
+ bitmask = 0x03f;
+ shift_offset = 6;
+ }
+ else
+ {
+ bitmask = 0x01f;
+ shift_offset = 5;
+ }
+
+ std::vector<uint8_t> bytes;
+ bytes.resize(len_bits);
+ for (; len_bits > 0; data_bits >>= shift_offset, --len_bits)
+ {
+ uint8_t packed = data_bits & bitmask;
+ bytes.insert(bytes.begin(), sixBitToCharLookup[packed]);
+ }
+
+ stream.Printf("%s",prefix.c_str());
+ stream.Printf("\"%s\"",&bytes[0]);
+ stream.Printf("%s",suffix.c_str());
+ return true;
+}
diff --git a/source/Plugins/Language/ObjC/NSString.h b/source/Plugins/Language/ObjC/NSString.h
new file mode 100644
index 000000000000..6a767a55e009
--- /dev/null
+++ b/source/Plugins/Language/ObjC/NSString.h
@@ -0,0 +1,42 @@
+//===-- NSString.h ---------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_NSString_h_
+#define liblldb_NSString_h_
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+
+namespace lldb_private {
+ namespace formatters
+ {
+ bool
+ NSStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSTaggedString_SummaryProvider (ValueObject& valobj, ObjCLanguageRuntime::ClassDescriptorSP descriptor, Stream& stream, const TypeSummaryOptions& summary_options);
+
+ bool
+ NSAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ bool
+ NSMutableAttributedStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
+
+ class NSString_Additionals
+ {
+ public:
+ static std::map<ConstString, CXXFunctionSummaryFormat::Callback>&
+ GetAdditionalSummaries ();
+ };
+ } // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_CF_h_
diff --git a/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/source/Plugins/Language/ObjC/ObjCLanguage.cpp
new file mode 100644
index 000000000000..91a3a0fb4299
--- /dev/null
+++ b/source/Plugins/Language/ObjC/ObjCLanguage.cpp
@@ -0,0 +1,877 @@
+//===-- ObjCLanguage.cpp ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+#include <mutex>
+
+// Other libraries and framework includes
+// Project includes
+#include "ObjCLanguage.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/DataVisualization.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Symbol/ClangASTContext.h"
+
+#include "CF.h"
+#include "Cocoa.h"
+#include "CoreMedia.h"
+#include "NSDictionary.h"
+#include "NSSet.h"
+#include "NSString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+void
+ObjCLanguage::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "Objective-C Language",
+ CreateInstance);
+}
+
+void
+ObjCLanguage::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+ObjCLanguage::GetPluginNameStatic()
+{
+ static ConstString g_name("objc");
+ return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ObjCLanguage::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ObjCLanguage::GetPluginVersion()
+{
+ return 1;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+Language *
+ObjCLanguage::CreateInstance (lldb::LanguageType language)
+{
+ switch (language)
+ {
+ case lldb::eLanguageTypeObjC:
+ return new ObjCLanguage();
+ default:
+ return nullptr;
+ }
+}
+
+void
+ObjCLanguage::MethodName::Clear()
+{
+ m_full.Clear();
+ m_class.Clear();
+ m_category.Clear();
+ m_selector.Clear();
+ m_type = eTypeUnspecified;
+ m_category_is_valid = false;
+}
+
+bool
+ObjCLanguage::MethodName::SetName (const char *name, bool strict)
+{
+ Clear();
+ if (name && name[0])
+ {
+ // If "strict" is true. then the method must be specified with a
+ // '+' or '-' at the beginning. If "strict" is false, then the '+'
+ // or '-' can be omitted
+ bool valid_prefix = false;
+
+ if (name[0] == '+' || name[0] == '-')
+ {
+ valid_prefix = name[1] == '[';
+ if (name[0] == '+')
+ m_type = eTypeClassMethod;
+ else
+ m_type = eTypeInstanceMethod;
+ }
+ else if (!strict)
+ {
+ // "strict" is false, the name just needs to start with '['
+ valid_prefix = name[0] == '[';
+ }
+
+ if (valid_prefix)
+ {
+ int name_len = strlen (name);
+ // Objective C methods must have at least:
+ // "-[" or "+[" prefix
+ // One character for a class name
+ // One character for the space between the class name
+ // One character for the method name
+ // "]" suffix
+ if (name_len >= (5 + (strict ? 1 : 0)) && name[name_len - 1] == ']')
+ {
+ m_full.SetCStringWithLength(name, name_len);
+ }
+ }
+ }
+ return IsValid(strict);
+}
+
+const ConstString &
+ObjCLanguage::MethodName::GetClassName ()
+{
+ if (!m_class)
+ {
+ if (IsValid(false))
+ {
+ const char *full = m_full.GetCString();
+ const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
+ const char *paren_pos = strchr (class_start, '(');
+ if (paren_pos)
+ {
+ m_class.SetCStringWithLength (class_start, paren_pos - class_start);
+ }
+ else
+ {
+ // No '(' was found in the full name, we can definitively say
+ // that our category was valid (and empty).
+ m_category_is_valid = true;
+ const char *space_pos = strchr (full, ' ');
+ if (space_pos)
+ {
+ m_class.SetCStringWithLength (class_start, space_pos - class_start);
+ if (!m_class_category)
+ {
+ // No category in name, so we can also fill in the m_class_category
+ m_class_category = m_class;
+ }
+ }
+ }
+ }
+ }
+ return m_class;
+}
+
+const ConstString &
+ObjCLanguage::MethodName::GetClassNameWithCategory ()
+{
+ if (!m_class_category)
+ {
+ if (IsValid(false))
+ {
+ const char *full = m_full.GetCString();
+ const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
+ const char *space_pos = strchr (full, ' ');
+ if (space_pos)
+ {
+ m_class_category.SetCStringWithLength (class_start, space_pos - class_start);
+ // If m_class hasn't been filled in and the class with category doesn't
+ // contain a '(', then we can also fill in the m_class
+ if (!m_class && strchr (m_class_category.GetCString(), '(') == NULL)
+ {
+ m_class = m_class_category;
+ // No '(' was found in the full name, we can definitively say
+ // that our category was valid (and empty).
+ m_category_is_valid = true;
+
+ }
+ }
+ }
+ }
+ return m_class_category;
+}
+
+const ConstString &
+ObjCLanguage::MethodName::GetSelector ()
+{
+ if (!m_selector)
+ {
+ if (IsValid(false))
+ {
+ const char *full = m_full.GetCString();
+ const char *space_pos = strchr (full, ' ');
+ if (space_pos)
+ {
+ ++space_pos; // skip the space
+ m_selector.SetCStringWithLength (space_pos, m_full.GetLength() - (space_pos - full) - 1);
+ }
+ }
+ }
+ return m_selector;
+}
+
+const ConstString &
+ObjCLanguage::MethodName::GetCategory ()
+{
+ if (!m_category_is_valid && !m_category)
+ {
+ if (IsValid(false))
+ {
+ m_category_is_valid = true;
+ const char *full = m_full.GetCString();
+ const char *class_start = (full[0] == '[' ? full + 1 : full + 2);
+ const char *open_paren_pos = strchr (class_start, '(');
+ if (open_paren_pos)
+ {
+ ++open_paren_pos; // Skip the open paren
+ const char *close_paren_pos = strchr (open_paren_pos, ')');
+ if (close_paren_pos)
+ m_category.SetCStringWithLength (open_paren_pos, close_paren_pos - open_paren_pos);
+ }
+ }
+ }
+ return m_category;
+}
+
+ConstString
+ObjCLanguage::MethodName::GetFullNameWithoutCategory (bool empty_if_no_category)
+{
+ if (IsValid(false))
+ {
+ if (HasCategory())
+ {
+ StreamString strm;
+ if (m_type == eTypeClassMethod)
+ strm.PutChar('+');
+ else if (m_type == eTypeInstanceMethod)
+ strm.PutChar('-');
+ strm.Printf("[%s %s]", GetClassName().GetCString(), GetSelector().GetCString());
+ return ConstString(strm.GetString().c_str());
+ }
+
+ if (!empty_if_no_category)
+ {
+ // Just return the full name since it doesn't have a category
+ return GetFullName();
+ }
+ }
+ return ConstString();
+}
+
+size_t
+ObjCLanguage::MethodName::GetFullNames (std::vector<ConstString> &names, bool append)
+{
+ if (!append)
+ names.clear();
+ if (IsValid(false))
+ {
+ StreamString strm;
+ const bool is_class_method = m_type == eTypeClassMethod;
+ const bool is_instance_method = m_type == eTypeInstanceMethod;
+ const ConstString &category = GetCategory();
+ if (is_class_method || is_instance_method)
+ {
+ names.push_back (m_full);
+ if (category)
+ {
+ strm.Printf("%c[%s %s]",
+ is_class_method ? '+' : '-',
+ GetClassName().GetCString(),
+ GetSelector().GetCString());
+ names.push_back(ConstString(strm.GetString().c_str()));
+ }
+ }
+ else
+ {
+ const ConstString &class_name = GetClassName();
+ const ConstString &selector = GetSelector();
+ strm.Printf("+[%s %s]", class_name.GetCString(), selector.GetCString());
+ names.push_back(ConstString(strm.GetString().c_str()));
+ strm.Clear();
+ strm.Printf("-[%s %s]", class_name.GetCString(), selector.GetCString());
+ names.push_back(ConstString(strm.GetString().c_str()));
+ strm.Clear();
+ if (category)
+ {
+ strm.Printf("+[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString());
+ names.push_back(ConstString(strm.GetString().c_str()));
+ strm.Clear();
+ strm.Printf("-[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString());
+ names.push_back(ConstString(strm.GetString().c_str()));
+ }
+ }
+ }
+ return names.size();
+}
+
+static void
+LoadObjCFormatters(TypeCategoryImplSP objc_category_sp)
+{
+ if (!objc_category_sp)
+ return;
+
+ TypeSummaryImpl::Flags objc_flags;
+ objc_flags.SetCascades(false)
+ .SetSkipPointers(true)
+ .SetSkipReferences(true)
+ .SetDontShowChildren(true)
+ .SetDontShowValue(true)
+ .SetShowMembersOneLiner(false)
+ .SetHideItemNames(false);
+
+ lldb::TypeSummaryImplSP ObjC_BOOL_summary(new CXXFunctionSummaryFormat(objc_flags, lldb_private::formatters::ObjCBOOLSummaryProvider,""));
+ objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL"),
+ ObjC_BOOL_summary);
+ objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL &"),
+ ObjC_BOOL_summary);
+ objc_category_sp->GetTypeSummariesContainer()->Add(ConstString("BOOL *"),
+ ObjC_BOOL_summary);
+
+#ifndef LLDB_DISABLE_PYTHON
+ // we need to skip pointers here since we are special casing a SEL* when retrieving its value
+ objc_flags.SetSkipPointers(true);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>, "SEL summary provider", ConstString("SEL"), objc_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>, "SEL summary provider", ConstString("struct objc_selector"), objc_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<false>, "SEL summary provider", ConstString("objc_selector"), objc_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<true>, "SEL summary provider", ConstString("objc_selector *"), objc_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCSELSummaryProvider<true>, "SEL summary provider", ConstString("SEL *"), objc_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::ObjCClassSummaryProvider, "Class summary provider", ConstString("Class"), objc_flags);
+
+ SyntheticChildren::Flags class_synth_flags;
+ class_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
+
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::ObjCClassSyntheticFrontEndCreator, "Class synthetic children", ConstString("Class"), class_synth_flags);
+#endif // LLDB_DISABLE_PYTHON
+
+ objc_flags.SetSkipPointers(false);
+ objc_flags.SetCascades(true);
+ objc_flags.SetSkipReferences(false);
+
+ AddStringSummary (objc_category_sp,
+ "${var.__FuncPtr%A}",
+ ConstString("__block_literal_generic"),
+ objc_flags);
+
+ AddStringSummary(objc_category_sp,
+ "${var.years} years, ${var.months} months, ${var.days} days, ${var.hours} hours, ${var.minutes} minutes ${var.seconds} seconds",
+ ConstString("CFGregorianUnits"),
+ objc_flags);
+ AddStringSummary(objc_category_sp,
+ "location=${var.location} length=${var.length}",
+ ConstString("CFRange"),
+ objc_flags);
+
+ AddStringSummary(objc_category_sp,
+ "location=${var.location}, length=${var.length}",
+ ConstString("NSRange"),
+ objc_flags);
+ AddStringSummary(objc_category_sp,
+ "(${var.origin}, ${var.size}), ...",
+ ConstString("NSRectArray"),
+ objc_flags);
+
+ AddOneLineSummary (objc_category_sp,
+ ConstString("NSPoint"),
+ objc_flags);
+ AddOneLineSummary (objc_category_sp,
+ ConstString("NSSize"),
+ objc_flags);
+ AddOneLineSummary (objc_category_sp,
+ ConstString("NSRect"),
+ objc_flags);
+
+ AddOneLineSummary (objc_category_sp,
+ ConstString("CGSize"),
+ objc_flags);
+ AddOneLineSummary (objc_category_sp,
+ ConstString("CGPoint"),
+ objc_flags);
+ AddOneLineSummary (objc_category_sp,
+ ConstString("CGRect"),
+ objc_flags);
+
+ AddStringSummary(objc_category_sp,
+ "red=${var.red} green=${var.green} blue=${var.blue}",
+ ConstString("RGBColor"),
+ objc_flags);
+ AddStringSummary(objc_category_sp,
+ "(t=${var.top}, l=${var.left}, b=${var.bottom}, r=${var.right})",
+ ConstString("Rect"),
+ objc_flags);
+ AddStringSummary(objc_category_sp,
+ "{(v=${var.v}, h=${var.h})}",
+ ConstString("Point"),
+ objc_flags);
+ AddStringSummary(objc_category_sp,
+ "${var.month}/${var.day}/${var.year} ${var.hour} :${var.minute} :${var.second} dayOfWeek:${var.dayOfWeek}",
+ ConstString("DateTimeRect *"),
+ objc_flags);
+ AddStringSummary(objc_category_sp,
+ "${var.ld.month}/${var.ld.day}/${var.ld.year} ${var.ld.hour} :${var.ld.minute} :${var.ld.second} dayOfWeek:${var.ld.dayOfWeek}",
+ ConstString("LongDateRect"),
+ objc_flags);
+ AddStringSummary(objc_category_sp,
+ "(x=${var.x}, y=${var.y})",
+ ConstString("HIPoint"),
+ objc_flags);
+ AddStringSummary(objc_category_sp,
+ "origin=${var.origin} size=${var.size}",
+ ConstString("HIRect"),
+ objc_flags);
+
+ TypeSummaryImpl::Flags appkit_flags;
+ appkit_flags.SetCascades(true)
+ .SetSkipPointers(false)
+ .SetSkipReferences(false)
+ .SetDontShowChildren(true)
+ .SetDontShowValue(false)
+ .SetShowMembersOneLiner(false)
+ .SetHideItemNames(false);
+
+ appkit_flags.SetDontShowChildren(false);
+
+#ifndef LLDB_DISABLE_PYTHON
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("NSArray"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("NSMutableArray"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSArrayI"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSArray0"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSArrayM"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("__NSCFArray"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("CFArrayRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSArraySummaryProvider, "NSArray summary provider", ConstString("CFMutableArrayRef"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("NSDictionary"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("NSMutableDictionary"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSCFDictionary"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSDictionaryI"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<false>, "NSDictionary summary provider", ConstString("__NSDictionaryM"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<true>, "NSDictionary summary provider", ConstString("CFDictionaryRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider<true>, "NSDictionary summary provider", ConstString("CFMutableDictionaryRef"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSSet summary", ConstString("NSSet"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>, "CFSetRef summary", ConstString("CFSetRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<true>, "CFMutableSetRef summary", ConstString("CFMutableSetRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSCFSet summary", ConstString("__NSCFSet"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSSetI summary", ConstString("__NSSetI"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSSetM summary", ConstString("__NSSetM"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSCountedSet summary", ConstString("NSCountedSet"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSMutableSet summary", ConstString("NSMutableSet"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "NSOrderedSet summary", ConstString("NSOrderedSet"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSOrderedSetI summary", ConstString("__NSOrderedSetI"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSSetSummaryProvider<false>, "__NSOrderedSetM summary", ConstString("__NSOrderedSetM"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSError_SummaryProvider, "NSError summary provider", ConstString("NSError"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSException_SummaryProvider, "NSException summary provider", ConstString("NSException"), appkit_flags);
+
+ // AddSummary(appkit_category_sp, "${var.key%@} -> ${var.value%@}", ConstString("$_lldb_typegen_nspair"), appkit_flags);
+
+ appkit_flags.SetDontShowChildren(true);
+
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSArrayM"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSArrayI"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSArray0"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("NSArray"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("NSMutableArray"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("__NSCFArray"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("CFMutableArrayRef"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSArraySyntheticFrontEndCreator, "NSArray synthetic children", ConstString("CFArrayRef"), ScriptedSyntheticChildren::Flags());
+
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSDictionaryM"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSDictionaryI"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("__NSCFDictionary"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("NSDictionary"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("NSMutableDictionary"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("CFDictionaryRef"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSDictionarySyntheticFrontEndCreator, "NSDictionary synthetic children", ConstString("CFMutableDictionaryRef"), ScriptedSyntheticChildren::Flags());
+
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSErrorSyntheticFrontEndCreator, "NSError synthetic children", ConstString("NSError"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSExceptionSyntheticFrontEndCreator, "NSException synthetic children", ConstString("NSException"), ScriptedSyntheticChildren::Flags());
+
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSSet synthetic children", ConstString("NSSet"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSSetI synthetic children", ConstString("__NSSetI"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSSetM synthetic children", ConstString("__NSSetM"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSMutableSet synthetic children", ConstString("NSMutableSet"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "NSOrderedSet synthetic children", ConstString("NSOrderedSet"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetI synthetic children", ConstString("__NSOrderedSetI"), ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSSetSyntheticFrontEndCreator, "__NSOrderedSetM synthetic children", ConstString("__NSOrderedSetM"), ScriptedSyntheticChildren::Flags());
+
+ AddCXXSynthetic(objc_category_sp, lldb_private::formatters::NSIndexPathSyntheticFrontEndCreator, "NSIndexPath synthetic children", ConstString("NSIndexPath"), ScriptedSyntheticChildren::Flags());
+
+ AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFBagRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("__CFBag"), appkit_flags);
+ AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("const struct __CFBag"), appkit_flags);
+ AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBagSummaryProvider, "CFBag summary provider", ConstString("CFMutableBagRef"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBinaryHeapSummaryProvider, "CFBinaryHeap summary provider", ConstString("CFBinaryHeapRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp,lldb_private::formatters::CFBinaryHeapSummaryProvider, "CFBinaryHeap summary provider", ConstString("__CFBinaryHeap"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSString"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("CFStringRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__CFString"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("CFMutableStringRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSMutableString"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__NSCFConstantString"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("__NSCFString"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSCFConstantString"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSCFString"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSStringSummaryProvider, "NSString summary provider", ConstString("NSPathStore2"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSAttributedStringSummaryProvider, "NSAttributedString summary provider", ConstString("NSAttributedString"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSMutableAttributedStringSummaryProvider, "NSMutableAttributedString summary provider", ConstString("NSMutableAttributedString"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSMutableAttributedStringSummaryProvider, "NSMutableAttributedString summary provider", ConstString("NSConcreteMutableAttributedString"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSBundleSummaryProvider, "NSBundle summary provider", ConstString("NSBundle"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSData"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSConcreteData"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSConcreteMutableData"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("NSMutableData"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<false>, "NSData summary provider", ConstString("__NSCFData"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>, "NSData summary provider", ConstString("CFDataRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider<true>, "NSData summary provider", ConstString("CFMutableDataRef"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSMachPortSummaryProvider, "NSMachPort summary provider", ConstString("NSMachPort"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNotificationSummaryProvider, "NSNotification summary provider", ConstString("NSNotification"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNotificationSummaryProvider, "NSNotification summary provider", ConstString("NSConcreteNotification"), appkit_flags);
+
+ AddStringSummary(objc_category_sp, "domain: ${var._domain} - code: ${var._code}", ConstString("NSError"), appkit_flags);
+ AddStringSummary(objc_category_sp,"name:${var.name%S} reason:${var.reason%S}",ConstString("NSException"),appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSNumber"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "CFNumberRef summary provider", ConstString("CFNumberRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("__NSCFBoolean"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("__NSCFNumber"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSCFBoolean"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSNumberSummaryProvider, "NSNumber summary provider", ConstString("NSCFNumber"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSDecimalNumber summary provider", ConstString("NSDecimalNumber"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSHost summary provider", ConstString("NSHost"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSTask summary provider", ConstString("NSTask"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::RuntimeSpecificDescriptionSummaryProvider, "NSValue summary provider", ConstString("NSValue"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSURLSummaryProvider, "NSURL summary provider", ConstString("NSURL"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSURLSummaryProvider, "NSURL summary provider", ConstString("CFURLRef"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("NSDate"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("__NSDate"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("__NSTaggedDate"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDateSummaryProvider, "NSDate summary provider", ConstString("NSCalendarDate"), appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("NSTimeZone"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("CFTimeZoneRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSTimeZoneSummaryProvider, "NSTimeZone summary provider", ConstString("__NSTimeZone"), appkit_flags);
+
+ // CFAbsoluteTime is actually a double rather than a pointer to an object
+ // we do not care about the numeric value, since it is probably meaningless to users
+ appkit_flags.SetDontShowValue(true);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::CFAbsoluteTimeSummaryProvider, "CFAbsoluteTime summary provider", ConstString("CFAbsoluteTime"), appkit_flags);
+ appkit_flags.SetDontShowValue(false);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider, "NSIndexSet summary provider", ConstString("NSIndexSet"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::NSIndexSetSummaryProvider, "NSIndexSet summary provider", ConstString("NSMutableIndexSet"), appkit_flags);
+
+ AddStringSummary(objc_category_sp,
+ "@\"${var.month%d}/${var.day%d}/${var.year%d} ${var.hour%d}:${var.minute%d}:${var.second}\"",
+ ConstString("CFGregorianDate"),
+ appkit_flags);
+
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("CFBitVectorRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("CFMutableBitVectorRef"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("__CFBitVector"), appkit_flags);
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::CFBitVectorSummaryProvider, "CFBitVector summary provider", ConstString("__CFMutableBitVector"), appkit_flags);
+#endif // LLDB_DISABLE_PYTHON
+}
+
+static void
+LoadCoreMediaFormatters(TypeCategoryImplSP objc_category_sp)
+{
+ if (!objc_category_sp)
+ return;
+
+ TypeSummaryImpl::Flags cm_flags;
+ cm_flags.SetCascades(true)
+ .SetDontShowChildren(false)
+ .SetDontShowValue(false)
+ .SetHideItemNames(false)
+ .SetShowMembersOneLiner(false)
+ .SetSkipPointers(false)
+ .SetSkipReferences(false);
+
+#ifndef LLDB_DISABLE_PYTHON
+ AddCXXSummary(objc_category_sp, lldb_private::formatters::CMTimeSummaryProvider, "CMTime summary provider", ConstString("CMTime"), cm_flags);
+#endif // LLDB_DISABLE_PYTHON
+}
+
+lldb::TypeCategoryImplSP
+ObjCLanguage::GetFormatters ()
+{
+ static std::once_flag g_initialize;
+ static TypeCategoryImplSP g_category;
+
+ std::call_once(g_initialize, [this] () -> void {
+ DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
+ if (g_category)
+ {
+ LoadCoreMediaFormatters(g_category);
+ LoadObjCFormatters(g_category);
+ }
+ });
+ return g_category;
+}
+
+std::vector<ConstString>
+ObjCLanguage::GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic)
+{
+ std::vector<ConstString> result;
+
+ if (use_dynamic == lldb::eNoDynamicValues)
+ return result;
+
+ CompilerType compiler_type(valobj.GetCompilerType());
+
+ const bool check_cpp = false;
+ const bool check_objc = true;
+ bool canBeObjCDynamic = compiler_type.IsPossibleDynamicType(nullptr, check_cpp, check_objc);
+
+ if (canBeObjCDynamic)
+ {
+ do {
+ lldb::ProcessSP process_sp = valobj.GetProcessSP();
+ if (!process_sp)
+ break;
+ ObjCLanguageRuntime* runtime = process_sp->GetObjCLanguageRuntime();
+ if (runtime == nullptr)
+ break;
+ ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetClassDescriptor(valobj));
+ if (!objc_class_sp)
+ break;
+ if (ConstString name = objc_class_sp->GetClassName())
+ result.push_back(name);
+ } while (false);
+ }
+
+ return result;
+}
+
+std::unique_ptr<Language::TypeScavenger>
+ObjCLanguage::GetTypeScavenger ()
+{
+ class ObjCTypeScavenger : public Language::TypeScavenger
+ {
+ private:
+ class ObjCScavengerResult : public Language::TypeScavenger::Result
+ {
+ public:
+ ObjCScavengerResult (CompilerType type) :
+ Language::TypeScavenger::Result(),
+ m_compiler_type(type)
+ {
+ }
+
+ bool
+ IsValid () override
+ {
+ return m_compiler_type.IsValid();
+ }
+
+ bool
+ DumpToStream (Stream& stream,
+ bool print_help_if_available) override
+ {
+ if (IsValid())
+ {
+ m_compiler_type.DumpTypeDescription(&stream);
+ stream.EOL();
+ return true;
+ }
+ return false;
+ }
+
+ ~ObjCScavengerResult() override = default;
+
+ private:
+ CompilerType m_compiler_type;
+ };
+
+ protected:
+ ObjCTypeScavenger() = default;
+
+ ~ObjCTypeScavenger() override = default;
+
+ bool
+ Find_Impl (ExecutionContextScope *exe_scope,
+ const char *key,
+ ResultSet &results) override
+ {
+ bool result = false;
+
+ Target* target = exe_scope->CalculateTarget().get();
+ if (target)
+ {
+ if (auto clang_modules_decl_vendor = target->GetClangModulesDeclVendor())
+ {
+ std::vector <clang::NamedDecl*> decls;
+ ConstString key_cs(key);
+
+ if (clang_modules_decl_vendor->FindDecls(key_cs, false, UINT32_MAX, decls) > 0 &&
+ decls.size() > 0)
+ {
+ CompilerType module_type = ClangASTContext::GetTypeForDecl(decls.front());
+ result = true;
+ std::unique_ptr<Language::TypeScavenger::Result> result(new ObjCScavengerResult(module_type));
+ results.insert(std::move(result));
+ }
+ }
+ }
+
+ if (!result)
+ {
+ Process* process = exe_scope->CalculateProcess().get();
+ if (process)
+ {
+ const bool create_on_demand = false;
+ auto objc_runtime = process->GetObjCLanguageRuntime(create_on_demand);
+ if (objc_runtime)
+ {
+ auto decl_vendor = objc_runtime->GetDeclVendor();
+ if (decl_vendor)
+ {
+ std::vector<clang::NamedDecl *> decls;
+ ConstString name(key);
+ decl_vendor->FindDecls(name, true, UINT32_MAX, decls);
+ for (auto decl : decls)
+ {
+ if (decl)
+ {
+ if (CompilerType candidate = ClangASTContext::GetTypeForDecl(decl))
+ {
+ result = true;
+ std::unique_ptr<Language::TypeScavenger::Result> result(new ObjCScavengerResult(candidate));
+ results.insert(std::move(result));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ friend class lldb_private::ObjCLanguage;
+ };
+
+ return std::unique_ptr<TypeScavenger>(new ObjCTypeScavenger());
+}
+
+bool
+ObjCLanguage::GetFormatterPrefixSuffix (ValueObject& valobj, ConstString type_hint,
+ std::string& prefix, std::string& suffix)
+{
+ static ConstString g_CFBag("CFBag");
+ static ConstString g_CFBinaryHeap("CFBinaryHeap");
+
+ static ConstString g_NSNumberChar("NSNumber:char");
+ static ConstString g_NSNumberShort("NSNumber:short");
+ static ConstString g_NSNumberInt("NSNumber:int");
+ static ConstString g_NSNumberLong("NSNumber:long");
+ static ConstString g_NSNumberFloat("NSNumber:float");
+ static ConstString g_NSNumberDouble("NSNumber:double");
+
+ static ConstString g_NSData("NSData");
+ static ConstString g_NSArray("NSArray");
+ static ConstString g_NSString("NSString");
+ static ConstString g_NSStringStar("NSString*");
+
+ if (type_hint.IsEmpty())
+ return false;
+
+ prefix.clear();
+ suffix.clear();
+
+ if (type_hint == g_CFBag ||
+ type_hint == g_CFBinaryHeap)
+ {
+ prefix = "@";
+ return true;
+ }
+
+ if (type_hint == g_NSNumberChar)
+ {
+ prefix = "(char)";
+ return true;
+ }
+ if (type_hint == g_NSNumberShort)
+ {
+ prefix = "(short)";
+ return true;
+ }
+ if (type_hint == g_NSNumberInt)
+ {
+ prefix = "(int)";
+ return true;
+ }
+ if (type_hint == g_NSNumberLong)
+ {
+ prefix = "(long)";
+ return true;
+ }
+ if (type_hint == g_NSNumberFloat)
+ {
+ prefix = "(float)";
+ return true;
+ }
+ if (type_hint == g_NSNumberDouble)
+ {
+ prefix = "(double)";
+ return true;
+ }
+
+ if (type_hint == g_NSData ||
+ type_hint == g_NSArray)
+ {
+ prefix = "@\"";
+ suffix = "\"";
+ return true;
+ }
+
+ if (type_hint == g_NSString ||
+ type_hint == g_NSStringStar)
+ {
+ prefix = "@";
+ return true;
+ }
+
+ return false;
+}
+
+bool
+ObjCLanguage::IsNilReference (ValueObject& valobj)
+{
+ const uint32_t mask = eTypeIsObjC | eTypeIsPointer;
+ bool isObjCpointer = (((valobj.GetCompilerType().GetTypeInfo(nullptr)) & mask) == mask);
+ if (!isObjCpointer)
+ return false;
+ bool canReadValue = true;
+ bool isZero = valobj.GetValueAsUnsigned(0,&canReadValue) == 0;
+ return canReadValue && isZero;
+}
diff --git a/source/Plugins/Language/ObjC/ObjCLanguage.h b/source/Plugins/Language/ObjC/ObjCLanguage.h
new file mode 100644
index 000000000000..e30aa18c0443
--- /dev/null
+++ b/source/Plugins/Language/ObjC/ObjCLanguage.h
@@ -0,0 +1,210 @@
+//===-- ObjCLanguage.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ObjCLanguage_h_
+#define liblldb_ObjCLanguage_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Target/Language.h"
+
+namespace lldb_private {
+
+class ObjCLanguage :
+ public Language
+{
+public:
+ class MethodName
+ {
+ public:
+ enum Type
+ {
+ eTypeUnspecified,
+ eTypeClassMethod,
+ eTypeInstanceMethod
+ };
+
+ MethodName () :
+ m_full(),
+ m_class(),
+ m_category(),
+ m_selector(),
+ m_type (eTypeUnspecified),
+ m_category_is_valid (false)
+ {
+ }
+
+ MethodName (const char *name, bool strict) :
+ m_full(),
+ m_class(),
+ m_category(),
+ m_selector(),
+ m_type (eTypeUnspecified),
+ m_category_is_valid (false)
+ {
+ SetName (name, strict);
+ }
+
+ void
+ Clear();
+
+ bool
+ IsValid (bool strict) const
+ {
+ // If "strict" is true, the name must have everything specified including
+ // the leading "+" or "-" on the method name
+ if (strict && m_type == eTypeUnspecified)
+ return false;
+ // Other than that, m_full will only be filled in if the objective C
+ // name is valid.
+ return (bool)m_full;
+ }
+
+ bool
+ HasCategory()
+ {
+ return !GetCategory().IsEmpty();
+ }
+
+ Type
+ GetType () const
+ {
+ return m_type;
+ }
+
+ const ConstString &
+ GetFullName () const
+ {
+ return m_full;
+ }
+
+ ConstString
+ GetFullNameWithoutCategory (bool empty_if_no_category);
+
+ bool
+ SetName (const char *name, bool strict);
+
+ const ConstString &
+ GetClassName ();
+
+ const ConstString &
+ GetClassNameWithCategory ();
+
+ const ConstString &
+ GetCategory ();
+
+ const ConstString &
+ GetSelector ();
+
+ // Get all possible names for a method. Examples:
+ // If name is "+[NSString(my_additions) myStringWithCString:]"
+ // names[0] => "+[NSString(my_additions) myStringWithCString:]"
+ // names[1] => "+[NSString myStringWithCString:]"
+ // If name is specified without the leading '+' or '-' like "[NSString(my_additions) myStringWithCString:]"
+ // names[0] => "+[NSString(my_additions) myStringWithCString:]"
+ // names[1] => "-[NSString(my_additions) myStringWithCString:]"
+ // names[2] => "+[NSString myStringWithCString:]"
+ // names[3] => "-[NSString myStringWithCString:]"
+ size_t
+ GetFullNames (std::vector<ConstString> &names, bool append);
+
+ protected:
+ ConstString m_full; // Full name: "+[NSString(my_additions) myStringWithCString:]"
+ ConstString m_class; // Class name: "NSString"
+ ConstString m_class_category; // Class with category: "NSString(my_additions)"
+ ConstString m_category; // Category: "my_additions"
+ ConstString m_selector; // Selector: "myStringWithCString:"
+ Type m_type;
+ bool m_category_is_valid;
+ };
+
+ ObjCLanguage() = default;
+
+ ~ObjCLanguage() override = default;
+
+ lldb::LanguageType
+ GetLanguageType () const override
+ {
+ return lldb::eLanguageTypeObjC;
+ }
+
+ lldb::TypeCategoryImplSP
+ GetFormatters () override;
+
+ std::vector<ConstString>
+ GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic) override;
+
+ std::unique_ptr<TypeScavenger>
+ GetTypeScavenger () override;
+
+ bool
+ GetFormatterPrefixSuffix (ValueObject& valobj, ConstString type_hint,
+ std::string& prefix, std::string& suffix) override;
+
+ bool
+ IsNilReference (ValueObject& valobj) override;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb_private::Language *
+ CreateInstance (lldb::LanguageType language);
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ static bool
+ IsPossibleObjCMethodName (const char *name)
+ {
+ if (!name)
+ return false;
+ bool starts_right = (name[0] == '+' || name[0] == '-') && name[1] == '[';
+ bool ends_right = (name[strlen(name) - 1] == ']');
+ return (starts_right && ends_right);
+ }
+
+ static bool
+ IsPossibleObjCSelector (const char *name)
+ {
+ if (!name)
+ return false;
+
+ if (strchr(name, ':') == NULL)
+ return true;
+ else if (name[strlen(name) - 1] == ':')
+ return true;
+ else
+ return false;
+ }
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ObjCLanguage_h_
diff --git a/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp b/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp
new file mode 100644
index 000000000000..62ddafefad97
--- /dev/null
+++ b/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp
@@ -0,0 +1,68 @@
+//===-- ObjCPlusPlusLanguage.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ObjCPlusPlusLanguage.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/PluginManager.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+ObjCPlusPlusLanguage::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "Objective-C++ Language",
+ CreateInstance);
+}
+
+void
+ObjCPlusPlusLanguage::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+ObjCPlusPlusLanguage::GetPluginNameStatic()
+{
+ static ConstString g_name("objcplusplus");
+ return g_name;
+}
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ObjCPlusPlusLanguage::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ObjCPlusPlusLanguage::GetPluginVersion()
+{
+ return 1;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+Language *
+ObjCPlusPlusLanguage::CreateInstance (lldb::LanguageType language)
+{
+ switch (language)
+ {
+ case lldb::eLanguageTypeObjC_plus_plus:
+ return new ObjCPlusPlusLanguage();
+ default:
+ return nullptr;
+ }
+}
diff --git a/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h b/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
new file mode 100644
index 000000000000..0e1db66b0899
--- /dev/null
+++ b/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
@@ -0,0 +1,63 @@
+//===-- ObjCPlusPlusLanguage.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ObjCPlusPlusLanguage_h_
+#define liblldb_ObjCPlusPlusLanguage_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/Language.h"
+
+namespace lldb_private {
+
+class ObjCPlusPlusLanguage :
+ public Language
+{
+public:
+ ObjCPlusPlusLanguage() = default;
+
+ ~ObjCPlusPlusLanguage() override = default;
+
+ lldb::LanguageType
+ GetLanguageType() const override
+ {
+ return lldb::eLanguageTypeObjC_plus_plus;
+ }
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb_private::Language *
+ CreateInstance (lldb::LanguageType language);
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CPlusPlusLanguage_h_
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index 3a3878ef09a1..a5fa004493a2 100644
--- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -40,14 +40,15 @@ ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)
{
const bool check_cxx = true;
const bool check_objc = false;
- return in_value.GetClangType().IsPossibleDynamicType (NULL, check_cxx, check_objc);
+ return in_value.GetCompilerType().IsPossibleDynamicType (NULL, check_cxx, check_objc);
}
bool
ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
lldb::DynamicValueType use_dynamic,
TypeAndOrName &class_type_or_name,
- Address &dynamic_address)
+ Address &dynamic_address,
+ Value::ValueType &value_type)
{
// For Itanium, if the type has a vtable pointer in the object, it will be at offset 0
// in the object. That will point to the "address point" within the vtable (not the beginning of the
@@ -58,6 +59,7 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
//
class_type_or_name.Clear();
+ value_type = Value::ValueType::eValueTypeScalar;
// Only a pointer or reference type can have a different dynamic and static type:
if (CouldHaveDynamicValue (in_value))
@@ -189,7 +191,7 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
type_sp = class_types.GetTypeAtIndex(i);
if (type_sp)
{
- if (type_sp->GetClangFullType().IsCXXClassType())
+ if (ClangASTContext::IsCXXClassType(type_sp->GetFullCompilerType ()))
{
if (log)
log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, picking this one: uid={0x%" PRIx64 "}, type-name='%s'\n",
@@ -221,8 +223,8 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
// the value we were handed.
if (type_sp)
{
- if (ClangASTContext::AreTypesSame (in_value.GetClangType(),
- type_sp->GetClangFullType()))
+ if (ClangASTContext::AreTypesSame (in_value.GetCompilerType(),
+ type_sp->GetFullCompilerType ()))
{
// The dynamic type we found was the same type,
// so we don't have a dynamic type here...
@@ -268,6 +270,42 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value,
return class_type_or_name.IsEmpty() == false;
}
+TypeAndOrName
+ItaniumABILanguageRuntime::FixUpDynamicType(const TypeAndOrName& type_and_or_name,
+ ValueObject& static_value)
+{
+ CompilerType static_type(static_value.GetCompilerType());
+ Flags static_type_flags(static_type.GetTypeInfo());
+
+ TypeAndOrName ret(type_and_or_name);
+ if (type_and_or_name.HasType())
+ {
+ // The type will always be the type of the dynamic object. If our parent's type was a pointer,
+ // then our type should be a pointer to the type of the dynamic object. If a reference, then the original type
+ // should be okay...
+ CompilerType orig_type = type_and_or_name.GetCompilerType();
+ CompilerType corrected_type = orig_type;
+ if (static_type_flags.AllSet(eTypeIsPointer))
+ corrected_type = orig_type.GetPointerType ();
+ else if (static_type_flags.AllSet(eTypeIsReference))
+ corrected_type = orig_type.GetLValueReferenceType();
+ ret.SetCompilerType(corrected_type);
+ }
+ else
+ {
+ // If we are here we need to adjust our dynamic type name to include the correct & or * symbol
+ std::string corrected_name (type_and_or_name.GetName().GetCString());
+ if (static_type_flags.AllSet(eTypeIsPointer))
+ corrected_name.append(" *");
+ else if (static_type_flags.AllSet(eTypeIsReference))
+ corrected_name.append(" &");
+ // the parent type should be a correctly pointer'ed or referenc'ed type
+ ret.SetCompilerType(static_type);
+ ret.SetName(corrected_name.c_str());
+ }
+ return ret;
+}
+
bool
ItaniumABILanguageRuntime::IsVTableName (const char *name)
{
@@ -420,6 +458,7 @@ ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch
exception_names.data(),
exception_names.size(),
eFunctionNameTypeBase,
+ eLanguageTypeUnknown,
eLazyBoolNo));
return resolver_sp;
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
index bc5d83be4bf5..519a3cee36d6 100644
--- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
+++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
@@ -1,4 +1,4 @@
-//===-- ItaniumABILanguageRuntime.h ----------------------------------------*- C++ -*-===//
+//===-- ItaniumABILanguageRuntime.h -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,6 +12,8 @@
// C Includes
// C++ Includes
+#include <vector>
+
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
@@ -20,28 +22,13 @@
#include "lldb/Target/CPPLanguageRuntime.h"
#include "lldb/Core/Value.h"
-#include <map>
-#include <vector>
-
namespace lldb_private {
class ItaniumABILanguageRuntime :
public lldb_private::CPPLanguageRuntime
{
public:
- ~ItaniumABILanguageRuntime() { }
-
- virtual bool
- IsVTableName (const char *name);
-
- virtual bool
- GetDynamicTypeAndAddress (ValueObject &in_value,
- lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name,
- Address &address);
-
- virtual bool
- CouldHaveDynamicValue (ValueObject &in_value);
+ ~ItaniumABILanguageRuntime() override = default;
//------------------------------------------------------------------
// Static Functions
@@ -58,38 +45,54 @@ namespace lldb_private {
static lldb_private::ConstString
GetPluginNameStatic();
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ bool
+ IsVTableName(const char *name) override;
- virtual uint32_t
- GetPluginVersion();
+ bool
+ GetDynamicTypeAndAddress(ValueObject &in_value,
+ lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name,
+ Address &address,
+ Value::ValueType &value_type) override;
- virtual void
- SetExceptionBreakpoints ();
+ TypeAndOrName
+ FixUpDynamicType(const TypeAndOrName& type_and_or_name,
+ ValueObject& static_value) override;
- virtual void
- ClearExceptionBreakpoints ();
+ bool
+ CouldHaveDynamicValue(ValueObject &in_value) override;
- virtual bool
- ExceptionBreakpointsAreSet ();
+ void
+ SetExceptionBreakpoints() override;
- virtual bool
- ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason);
+ void
+ ClearExceptionBreakpoints() override;
+
+ bool
+ ExceptionBreakpointsAreSet() override;
+
+ bool
+ ExceptionBreakpointsExplainStop(lldb::StopInfoSP stop_reason) override;
- virtual lldb::BreakpointResolverSP
- CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp);
+ lldb::BreakpointResolverSP
+ CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override;
- virtual lldb::SearchFilterSP
- CreateExceptionSearchFilter ();
+ lldb::SearchFilterSP
+ CreateExceptionSearchFilter() override;
- virtual size_t
- GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates);
+ size_t
+ GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates) override;
- protected:
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
+ protected:
lldb::BreakpointResolverSP
CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions);
@@ -107,4 +110,4 @@ namespace lldb_private {
} // namespace lldb_private
-#endif // liblldb_ItaniumABILanguageRuntime_h_
+#endif // liblldb_ItaniumABILanguageRuntime_h_
diff --git a/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp b/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp
new file mode 100644
index 000000000000..d59f292e7a08
--- /dev/null
+++ b/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp
@@ -0,0 +1,238 @@
+//===-- GoLanguageRuntime.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GoLanguageRuntime.h"
+
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectMemory.h"
+#include "lldb/Symbol/GoASTContext.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/TypeList.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/SectionLoadList.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "llvm/ADT/Twine.h"
+
+#include <vector>
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace {
+ValueObjectSP GetChild(ValueObject& obj, const char* name, bool dereference = true) {
+ ConstString name_const_str(name);
+ ValueObjectSP result = obj.GetChildMemberWithName(name_const_str, true);
+ if (dereference && result && result->IsPointerType()) {
+ Error err;
+ result = result->Dereference(err);
+ if (err.Fail())
+ result.reset();
+ }
+ return result;
+}
+
+ConstString ReadString(ValueObject& str, Process* process) {
+ ConstString result;
+ ValueObjectSP data = GetChild(str, "str", false);
+ ValueObjectSP len = GetChild(str, "len");
+ if (len && data)
+ {
+ Error err;
+ lldb::addr_t addr = data->GetPointerValue();
+ if (addr == LLDB_INVALID_ADDRESS)
+ return result;
+ uint64_t byte_size = len->GetValueAsUnsigned(0);
+ char* buf = new char[byte_size + 1];
+ buf[byte_size] = 0;
+ size_t bytes_read = process->ReadMemory (addr,
+ buf,
+ byte_size,
+ err);
+ if (!(err.Fail() || bytes_read != byte_size))
+ result = ConstString(buf, bytes_read);
+ delete[] buf;
+ }
+ return result;
+}
+
+ConstString
+ReadTypeName(ValueObjectSP type, Process* process)
+{
+ if (ValueObjectSP uncommon = GetChild(*type, "x"))
+ {
+ ValueObjectSP name = GetChild(*uncommon, "name");
+ ValueObjectSP package = GetChild(*uncommon, "pkgpath");
+ if (name && name->GetPointerValue() != 0 && package && package->GetPointerValue() != 0)
+ {
+ ConstString package_const_str = ReadString(*package, process);
+ ConstString name_const_str = ReadString(*name, process);
+ if (package_const_str.GetLength() == 0)
+ return name_const_str;
+ return ConstString((package_const_str.GetStringRef() + "." + name_const_str.GetStringRef()).str());
+ }
+ }
+ ValueObjectSP name = GetChild(*type, "_string");
+ if (name)
+ return ReadString(*name, process);
+ return ConstString("");
+}
+
+CompilerType
+LookupRuntimeType(ValueObjectSP type, ExecutionContext* exe_ctx, bool* is_direct)
+{
+ uint8_t kind = GetChild(*type, "kind")->GetValueAsUnsigned(0);
+ *is_direct = GoASTContext::IsDirectIface(kind);
+ if (GoASTContext::IsPointerKind(kind))
+ {
+ CompilerType type_ptr = type->GetCompilerType().GetPointerType();
+ Error err;
+ ValueObjectSP elem = type->CreateValueObjectFromAddress("elem", type->GetAddressOf() + type->GetByteSize(), *exe_ctx, type_ptr)->Dereference(err);
+ if (err.Fail())
+ return CompilerType();
+ bool tmp_direct;
+ return LookupRuntimeType(elem, exe_ctx, &tmp_direct).GetPointerType();
+ }
+ Target *target = exe_ctx->GetTargetPtr();
+ Process *process = exe_ctx->GetProcessPtr();
+
+ ConstString const_typename = ReadTypeName(type, process);
+ if (const_typename.GetLength() == 0)
+ return CompilerType();
+
+ SymbolContext sc;
+ TypeList type_list;
+ uint32_t num_matches = target->GetImages().FindTypes (sc,
+ const_typename,
+ false,
+ 2,
+ type_list);
+ if (num_matches > 0) {
+ return type_list.GetTypeAtIndex(0)->GetFullCompilerType();
+ }
+ return CompilerType();
+}
+
+}
+
+bool
+GoLanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)
+{
+ return GoASTContext::IsGoInterface(in_value.GetCompilerType());
+}
+
+bool
+GoLanguageRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name, Address &dynamic_address,
+ Value::ValueType &value_type)
+{
+ value_type = Value::eValueTypeScalar;
+ class_type_or_name.Clear();
+ if (CouldHaveDynamicValue (in_value))
+ {
+ Error err;
+ ValueObjectSP iface = in_value.GetStaticValue();
+ ValueObjectSP data_sp = GetChild(*iface, "data", false);
+ if (!data_sp)
+ return false;
+
+ if (ValueObjectSP tab = GetChild(*iface, "tab"))
+ iface = tab;
+ ValueObjectSP type = GetChild(*iface, "_type");
+ if (!type)
+ {
+ return false;
+ }
+
+ bool direct;
+ ExecutionContext exe_ctx (in_value.GetExecutionContextRef());
+ CompilerType final_type = LookupRuntimeType(type, &exe_ctx, &direct);
+ if (!final_type)
+ return false;
+ if (direct)
+ {
+ class_type_or_name.SetCompilerType(final_type);
+ }
+ else
+ {
+ // TODO: implement reference types or fix caller to support dynamic types that aren't pointers
+ // so we don't have to introduce this extra pointer.
+ class_type_or_name.SetCompilerType(final_type.GetPointerType());
+ }
+
+ dynamic_address.SetLoadAddress(data_sp->GetPointerValue(), exe_ctx.GetTargetPtr());
+
+ return true;
+ }
+ return false;
+}
+
+TypeAndOrName
+GoLanguageRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value)
+{
+ return type_and_or_name;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+LanguageRuntime *
+GoLanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language)
+{
+ if (language == eLanguageTypeGo)
+ return new GoLanguageRuntime (process);
+ else
+ return NULL;
+}
+
+void
+GoLanguageRuntime::Initialize()
+{
+ PluginManager::RegisterPlugin (GetPluginNameStatic(),
+ "Go Language Runtime",
+ CreateInstance);
+}
+
+void
+GoLanguageRuntime::Terminate()
+{
+ PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+GoLanguageRuntime::GetPluginNameStatic()
+{
+ static ConstString g_name("golang");
+ return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+GoLanguageRuntime::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+GoLanguageRuntime::GetPluginVersion()
+{
+ return 1;
+}
+
diff --git a/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h b/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h
new file mode 100644
index 000000000000..596d2888dc85
--- /dev/null
+++ b/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h
@@ -0,0 +1,93 @@
+//===-- GoLanguageRuntime.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GoLanguageRuntime_h_
+#define liblldb_GoLanguageRuntime_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Breakpoint/BreakpointResolver.h"
+#include "lldb/Target/LanguageRuntime.h"
+#include "lldb/Core/Value.h"
+
+namespace lldb_private {
+
+ class GoLanguageRuntime :
+ public lldb_private::LanguageRuntime
+ {
+ public:
+ ~GoLanguageRuntime() override = default;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb_private::LanguageRuntime *
+ CreateInstance(Process *process, lldb::LanguageType language);
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ lldb::LanguageType
+ GetLanguageType() const override
+ {
+ return lldb::eLanguageTypeGo;
+ }
+
+ bool
+ GetObjectDescription(Stream &str, ValueObject &object) override
+ {
+ // TODO(ribrdb): Maybe call String() method?
+ return false;
+ }
+
+ bool
+ GetObjectDescription(Stream &str, Value &value, ExecutionContextScope *exe_scope) override
+ {
+ return false;
+ }
+
+ bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name, Address &address,
+ Value::ValueType &value_type) override;
+
+ bool CouldHaveDynamicValue(ValueObject &in_value) override;
+
+ lldb::BreakpointResolverSP
+ CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override
+ {
+ return lldb::BreakpointResolverSP();
+ }
+
+ TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value) override;
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
+
+ private:
+ GoLanguageRuntime(Process *process) : lldb_private::LanguageRuntime(process) { } // Call CreateInstance instead.
+ };
+
+} // namespace lldb_private
+
+#endif // liblldb_GoLanguageRuntime_h_
diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
index 2490cf31409b..149244df30c2 100644
--- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
+++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
@@ -7,6 +7,10 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "RenderScriptRuntime.h"
#include "lldb/Core/ConstString.h"
@@ -14,10 +18,15 @@
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/DataFormatters/DumpValueObjectOptions.h"
+#include "lldb/Host/StringConvert.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -25,11 +34,350 @@
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Target/RegisterContext.h"
-
+#include "lldb/Expression/UserExpression.h"
#include "lldb/Symbol/VariableList.h"
using namespace lldb;
using namespace lldb_private;
+using namespace lldb_renderscript;
+
+namespace {
+
+// The empirical_type adds a basic level of validation to arbitrary data
+// allowing us to track if data has been discovered and stored or not.
+// An empirical_type will be marked as valid only if it has been explicitly assigned to.
+template <typename type_t>
+class empirical_type
+{
+public:
+ // Ctor. Contents is invalid when constructed.
+ empirical_type()
+ : valid(false)
+ {}
+
+ // Return true and copy contents to out if valid, else return false.
+ bool get(type_t& out) const
+ {
+ if (valid)
+ out = data;
+ return valid;
+ }
+
+ // Return a pointer to the contents or nullptr if it was not valid.
+ const type_t* get() const
+ {
+ return valid ? &data : nullptr;
+ }
+
+ // Assign data explicitly.
+ void set(const type_t in)
+ {
+ data = in;
+ valid = true;
+ }
+
+ // Mark contents as invalid.
+ void invalidate()
+ {
+ valid = false;
+ }
+
+ // Returns true if this type contains valid data.
+ bool isValid() const
+ {
+ return valid;
+ }
+
+ // Assignment operator.
+ empirical_type<type_t>& operator = (const type_t in)
+ {
+ set(in);
+ return *this;
+ }
+
+ // Dereference operator returns contents.
+ // Warning: Will assert if not valid so use only when you know data is valid.
+ const type_t& operator * () const
+ {
+ assert(valid);
+ return data;
+ }
+
+protected:
+ bool valid;
+ type_t data;
+};
+
+} // anonymous namespace
+
+// The ScriptDetails class collects data associated with a single script instance.
+struct RenderScriptRuntime::ScriptDetails
+{
+ ~ScriptDetails() = default;
+
+ enum ScriptType
+ {
+ eScript,
+ eScriptC
+ };
+
+ // The derived type of the script.
+ empirical_type<ScriptType> type;
+ // The name of the original source file.
+ empirical_type<std::string> resName;
+ // Path to script .so file on the device.
+ empirical_type<std::string> scriptDyLib;
+ // Directory where kernel objects are cached on device.
+ empirical_type<std::string> cacheDir;
+ // Pointer to the context which owns this script.
+ empirical_type<lldb::addr_t> context;
+ // Pointer to the script object itself.
+ empirical_type<lldb::addr_t> script;
+};
+
+// This Element class represents the Element object in RS,
+// defining the type associated with an Allocation.
+struct RenderScriptRuntime::Element
+{
+ // Taken from rsDefines.h
+ enum DataKind
+ {
+ RS_KIND_USER,
+ RS_KIND_PIXEL_L = 7,
+ RS_KIND_PIXEL_A,
+ RS_KIND_PIXEL_LA,
+ RS_KIND_PIXEL_RGB,
+ RS_KIND_PIXEL_RGBA,
+ RS_KIND_PIXEL_DEPTH,
+ RS_KIND_PIXEL_YUV,
+ RS_KIND_INVALID = 100
+ };
+
+ // Taken from rsDefines.h
+ enum DataType
+ {
+ RS_TYPE_NONE = 0,
+ RS_TYPE_FLOAT_16,
+ RS_TYPE_FLOAT_32,
+ RS_TYPE_FLOAT_64,
+ RS_TYPE_SIGNED_8,
+ RS_TYPE_SIGNED_16,
+ RS_TYPE_SIGNED_32,
+ RS_TYPE_SIGNED_64,
+ RS_TYPE_UNSIGNED_8,
+ RS_TYPE_UNSIGNED_16,
+ RS_TYPE_UNSIGNED_32,
+ RS_TYPE_UNSIGNED_64,
+ RS_TYPE_BOOLEAN,
+
+ RS_TYPE_UNSIGNED_5_6_5,
+ RS_TYPE_UNSIGNED_5_5_5_1,
+ RS_TYPE_UNSIGNED_4_4_4_4,
+
+ RS_TYPE_MATRIX_4X4,
+ RS_TYPE_MATRIX_3X3,
+ RS_TYPE_MATRIX_2X2,
+
+ RS_TYPE_ELEMENT = 1000,
+ RS_TYPE_TYPE,
+ RS_TYPE_ALLOCATION,
+ RS_TYPE_SAMPLER,
+ RS_TYPE_SCRIPT,
+ RS_TYPE_MESH,
+ RS_TYPE_PROGRAM_FRAGMENT,
+ RS_TYPE_PROGRAM_VERTEX,
+ RS_TYPE_PROGRAM_RASTER,
+ RS_TYPE_PROGRAM_STORE,
+ RS_TYPE_FONT,
+
+ RS_TYPE_INVALID = 10000
+ };
+
+ std::vector<Element> children; // Child Element fields for structs
+ empirical_type<lldb::addr_t> element_ptr; // Pointer to the RS Element of the Type
+ empirical_type<DataType> type; // Type of each data pointer stored by the allocation
+ empirical_type<DataKind> type_kind; // Defines pixel type if Allocation is created from an image
+ empirical_type<uint32_t> type_vec_size; // Vector size of each data point, e.g '4' for uchar4
+ empirical_type<uint32_t> field_count; // Number of Subelements
+ empirical_type<uint32_t> datum_size; // Size of a single Element with padding
+ empirical_type<uint32_t> padding; // Number of padding bytes
+ empirical_type<uint32_t> array_size; // Number of items in array, only needed for strucrs
+ ConstString type_name; // Name of type, only needed for structs
+
+ static const ConstString &GetFallbackStructName(); // Print this as the type name of a struct Element
+ // If we can't resolve the actual struct name
+
+ bool shouldRefresh() const
+ {
+ const bool valid_ptr = element_ptr.isValid() && *element_ptr.get() != 0x0;
+ const bool valid_type = type.isValid() && type_vec_size.isValid() && type_kind.isValid();
+ return !valid_ptr || !valid_type || !datum_size.isValid();
+ }
+};
+
+// This AllocationDetails class collects data associated with a single
+// allocation instance.
+struct RenderScriptRuntime::AllocationDetails
+{
+ struct Dimension
+ {
+ uint32_t dim_1;
+ uint32_t dim_2;
+ uint32_t dim_3;
+ uint32_t cubeMap;
+
+ Dimension()
+ {
+ dim_1 = 0;
+ dim_2 = 0;
+ dim_3 = 0;
+ cubeMap = 0;
+ }
+ };
+
+ // Header for reading and writing allocation contents
+ // to a binary file.
+ struct FileHeader
+ {
+ uint8_t ident[4]; // ASCII 'RSAD' identifying the file
+ uint16_t hdr_size; // Header size in bytes, for backwards compatability
+ uint16_t type; // DataType enum
+ uint32_t kind; // DataKind enum
+ uint32_t dims[3]; // Dimensions
+ uint32_t element_size; // Size of a single element, including padding
+ };
+
+ // Monotonically increasing from 1
+ static unsigned int ID;
+
+ // Maps Allocation DataType enum and vector size to printable strings
+ // using mapping from RenderScript numerical types summary documentation
+ static const char* RsDataTypeToString[][4];
+
+ // Maps Allocation DataKind enum to printable strings
+ static const char* RsDataKindToString[];
+
+ // Maps allocation types to format sizes for printing.
+ static const unsigned int RSTypeToFormat[][3];
+
+ // Give each allocation an ID as a way
+ // for commands to reference it.
+ const unsigned int id;
+
+ RenderScriptRuntime::Element element; // Allocation Element type
+ empirical_type<Dimension> dimension; // Dimensions of the Allocation
+ empirical_type<lldb::addr_t> address; // Pointer to address of the RS Allocation
+ empirical_type<lldb::addr_t> data_ptr; // Pointer to the data held by the Allocation
+ empirical_type<lldb::addr_t> type_ptr; // Pointer to the RS Type of the Allocation
+ empirical_type<lldb::addr_t> context; // Pointer to the RS Context of the Allocation
+ empirical_type<uint32_t> size; // Size of the allocation
+ empirical_type<uint32_t> stride; // Stride between rows of the allocation
+
+ // Give each allocation an id, so we can reference it in user commands.
+ AllocationDetails(): id(ID++)
+ {
+ }
+
+ bool shouldRefresh() const
+ {
+ bool valid_ptrs = data_ptr.isValid() && *data_ptr.get() != 0x0;
+ valid_ptrs = valid_ptrs && type_ptr.isValid() && *type_ptr.get() != 0x0;
+ return !valid_ptrs || !dimension.isValid() || !size.isValid() || element.shouldRefresh();
+ }
+};
+
+
+const ConstString &
+RenderScriptRuntime::Element::GetFallbackStructName()
+{
+ static const ConstString FallbackStructName("struct");
+ return FallbackStructName;
+}
+
+unsigned int RenderScriptRuntime::AllocationDetails::ID = 1;
+
+const char* RenderScriptRuntime::AllocationDetails::RsDataKindToString[] =
+{
+ "User",
+ "Undefined", "Undefined", "Undefined", // Enum jumps from 0 to 7
+ "Undefined", "Undefined", "Undefined",
+ "L Pixel",
+ "A Pixel",
+ "LA Pixel",
+ "RGB Pixel",
+ "RGBA Pixel",
+ "Pixel Depth",
+ "YUV Pixel"
+};
+
+const char* RenderScriptRuntime::AllocationDetails::RsDataTypeToString[][4] =
+{
+ {"None", "None", "None", "None"},
+ {"half", "half2", "half3", "half4"},
+ {"float", "float2", "float3", "float4"},
+ {"double", "double2", "double3", "double4"},
+ {"char", "char2", "char3", "char4"},
+ {"short", "short2", "short3", "short4"},
+ {"int", "int2", "int3", "int4"},
+ {"long", "long2", "long3", "long4"},
+ {"uchar", "uchar2", "uchar3", "uchar4"},
+ {"ushort", "ushort2", "ushort3", "ushort4"},
+ {"uint", "uint2", "uint3", "uint4"},
+ {"ulong", "ulong2", "ulong3", "ulong4"},
+ {"bool", "bool2", "bool3", "bool4"},
+ {"packed_565", "packed_565", "packed_565", "packed_565"},
+ {"packed_5551", "packed_5551", "packed_5551", "packed_5551"},
+ {"packed_4444", "packed_4444", "packed_4444", "packed_4444"},
+ {"rs_matrix4x4", "rs_matrix4x4", "rs_matrix4x4", "rs_matrix4x4"},
+ {"rs_matrix3x3", "rs_matrix3x3", "rs_matrix3x3", "rs_matrix3x3"},
+ {"rs_matrix2x2", "rs_matrix2x2", "rs_matrix2x2", "rs_matrix2x2"},
+
+ // Handlers
+ {"RS Element", "RS Element", "RS Element", "RS Element"},
+ {"RS Type", "RS Type", "RS Type", "RS Type"},
+ {"RS Allocation", "RS Allocation", "RS Allocation", "RS Allocation"},
+ {"RS Sampler", "RS Sampler", "RS Sampler", "RS Sampler"},
+ {"RS Script", "RS Script", "RS Script", "RS Script"},
+
+ // Deprecated
+ {"RS Mesh", "RS Mesh", "RS Mesh", "RS Mesh"},
+ {"RS Program Fragment", "RS Program Fragment", "RS Program Fragment", "RS Program Fragment"},
+ {"RS Program Vertex", "RS Program Vertex", "RS Program Vertex", "RS Program Vertex"},
+ {"RS Program Raster", "RS Program Raster", "RS Program Raster", "RS Program Raster"},
+ {"RS Program Store", "RS Program Store", "RS Program Store", "RS Program Store"},
+ {"RS Font", "RS Font", "RS Font", "RS Font"}
+};
+
+// Used as an index into the RSTypeToFormat array elements
+enum TypeToFormatIndex {
+ eFormatSingle = 0,
+ eFormatVector,
+ eElementSize
+};
+
+// { format enum of single element, format enum of element vector, size of element}
+const unsigned int RenderScriptRuntime::AllocationDetails::RSTypeToFormat[][3] =
+{
+ {eFormatHex, eFormatHex, 1}, // RS_TYPE_NONE
+ {eFormatFloat, eFormatVectorOfFloat16, 2}, // RS_TYPE_FLOAT_16
+ {eFormatFloat, eFormatVectorOfFloat32, sizeof(float)}, // RS_TYPE_FLOAT_32
+ {eFormatFloat, eFormatVectorOfFloat64, sizeof(double)}, // RS_TYPE_FLOAT_64
+ {eFormatDecimal, eFormatVectorOfSInt8, sizeof(int8_t)}, // RS_TYPE_SIGNED_8
+ {eFormatDecimal, eFormatVectorOfSInt16, sizeof(int16_t)}, // RS_TYPE_SIGNED_16
+ {eFormatDecimal, eFormatVectorOfSInt32, sizeof(int32_t)}, // RS_TYPE_SIGNED_32
+ {eFormatDecimal, eFormatVectorOfSInt64, sizeof(int64_t)}, // RS_TYPE_SIGNED_64
+ {eFormatDecimal, eFormatVectorOfUInt8, sizeof(uint8_t)}, // RS_TYPE_UNSIGNED_8
+ {eFormatDecimal, eFormatVectorOfUInt16, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_16
+ {eFormatDecimal, eFormatVectorOfUInt32, sizeof(uint32_t)}, // RS_TYPE_UNSIGNED_32
+ {eFormatDecimal, eFormatVectorOfUInt64, sizeof(uint64_t)}, // RS_TYPE_UNSIGNED_64
+ {eFormatBoolean, eFormatBoolean, 1}, // RS_TYPE_BOOL
+ {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_5_6_5
+ {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_5_5_5_1
+ {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_4_4_4_4
+ {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 16}, // RS_TYPE_MATRIX_4X4
+ {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 9}, // RS_TYPE_MATRIX_3X3
+ {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 4} // RS_TYPE_MATRIX_2X2
+};
//------------------------------------------------------------------
// Static Functions
@@ -44,6 +392,47 @@ RenderScriptRuntime::CreateInstance(Process *process, lldb::LanguageType languag
return NULL;
}
+// Callback with a module to search for matching symbols.
+// We first check that the module contains RS kernels.
+// Then look for a symbol which matches our kernel name.
+// The breakpoint address is finally set using the address of this symbol.
+Searcher::CallbackReturn
+RSBreakpointResolver::SearchCallback(SearchFilter &filter,
+ SymbolContext &context,
+ Address*,
+ bool)
+{
+ ModuleSP module = context.module_sp;
+
+ if (!module)
+ return Searcher::eCallbackReturnContinue;
+
+ // Is this a module containing renderscript kernels?
+ if (nullptr == module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData))
+ return Searcher::eCallbackReturnContinue;
+
+ // Attempt to set a breakpoint on the kernel name symbol within the module library.
+ // If it's not found, it's likely debug info is unavailable - try to set a
+ // breakpoint on <name>.expand.
+
+ const Symbol* kernel_sym = module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode);
+ if (!kernel_sym)
+ {
+ std::string kernel_name_expanded(m_kernel_name.AsCString());
+ kernel_name_expanded.append(".expand");
+ kernel_sym = module->FindFirstSymbolWithNameAndType(ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode);
+ }
+
+ if (kernel_sym)
+ {
+ Address bp_addr = kernel_sym->GetAddress();
+ if (filter.AddressPasses(bp_addr))
+ m_breakpoint->AddLocation(bp_addr);
+ }
+
+ return Searcher::eCallbackReturnContinue;
+}
+
void
RenderScriptRuntime::Initialize()
{
@@ -88,7 +477,7 @@ RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp)
return eModuleKindDriver;
}
- const ConstString rs_cpureflib("libRSCPURef.so");
+ const ConstString rs_cpureflib("libRSCpuRef.so");
if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib)
{
return eModuleKindImpl;
@@ -104,7 +493,6 @@ RenderScriptRuntime::IsRenderScriptModule(const lldb::ModuleSP &module_sp)
return GetModuleKind(module_sp) != eModuleKindIgnored;
}
-
void
RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list )
{
@@ -121,7 +509,6 @@ RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list )
}
}
-
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -145,11 +532,19 @@ RenderScriptRuntime::IsVTableName(const char *name)
bool
RenderScriptRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name, Address &address)
+ TypeAndOrName &class_type_or_name, Address &address,
+ Value::ValueType &value_type)
{
return false;
}
+TypeAndOrName
+RenderScriptRuntime::FixUpDynamicType (const TypeAndOrName& type_and_or_name,
+ ValueObject& static_value)
+{
+ return type_and_or_name;
+}
+
bool
RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value)
{
@@ -163,22 +558,78 @@ RenderScriptRuntime::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bo
return resolver_sp;
}
-
const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] =
{
//rsdScript
- {"rsdScriptInit", "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhjj", 0, RenderScriptRuntime::eModuleKindDriver, &lldb_private::RenderScriptRuntime::CaptureScriptInit1},
- {"rsdScriptInvokeForEach", "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvjPK12RsScriptCall", 0, RenderScriptRuntime::eModuleKindDriver, nullptr},
- {"rsdScriptInvokeForEachMulti", "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall", 0, RenderScriptRuntime::eModuleKindDriver, nullptr},
- {"rsdScriptInvokeFunction", "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvj", 0, RenderScriptRuntime::eModuleKindDriver, nullptr},
- {"rsdScriptSetGlobalVar", "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvj", 0, RenderScriptRuntime::eModuleKindDriver, &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar1},
+ {
+ "rsdScriptInit", //name
+ "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhjj", // symbol name 32 bit
+ "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhmj", // symbol name 64 bit
+ 0, // version
+ RenderScriptRuntime::eModuleKindDriver, // type
+ &lldb_private::RenderScriptRuntime::CaptureScriptInit1 // handler
+ },
+ {
+ "rsdScriptInvokeForEach", // name
+ "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvjPK12RsScriptCall", // symbol name 32bit
+ "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvmPK12RsScriptCall", // symbol name 64bit
+ 0, // version
+ RenderScriptRuntime::eModuleKindDriver, // type
+ nullptr // handler
+ },
+ {
+ "rsdScriptInvokeForEachMulti", // name
+ "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall", // symbol name 32bit
+ "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEmPS6_PKvmPK12RsScriptCall", // symbol name 64bit
+ 0, // version
+ RenderScriptRuntime::eModuleKindDriver, // type
+ nullptr // handler
+ },
+ {
+ "rsdScriptInvokeFunction", // name
+ "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvj", // symbol name 32bit
+ "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvm", // symbol name 64bit
+ 0, // version
+ RenderScriptRuntime::eModuleKindDriver, // type
+ nullptr // handler
+ },
+ {
+ "rsdScriptSetGlobalVar", // name
+ "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvj", // symbol name 32bit
+ "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvm", // symbol name 64bit
+ 0, // version
+ RenderScriptRuntime::eModuleKindDriver, // type
+ &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar1 // handler
+ },
//rsdAllocation
- {"rsdAllocationInit", "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", 0, RenderScriptRuntime::eModuleKindDriver, &lldb_private::RenderScriptRuntime::CaptureAllocationInit1},
- {"rsdAllocationRead2D", "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvjj", 0, RenderScriptRuntime::eModuleKindDriver, nullptr},
+ {
+ "rsdAllocationInit", // name
+ "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 32bit
+ "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 64bit
+ 0, // version
+ RenderScriptRuntime::eModuleKindDriver, // type
+ &lldb_private::RenderScriptRuntime::CaptureAllocationInit1 // handler
+ },
+ {
+ "rsdAllocationRead2D", //name
+ "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvjj", // symbol name 32bit
+ "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvmm", // symbol name 64bit
+ 0, // version
+ RenderScriptRuntime::eModuleKindDriver, // type
+ nullptr // handler
+ },
+ {
+ "rsdAllocationDestroy", // name
+ "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_10AllocationE", // symbol name 32bit
+ "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_10AllocationE", // symbol name 64bit
+ 0, // version
+ RenderScriptRuntime::eModuleKindDriver, // type
+ &lldb_private::RenderScriptRuntime::CaptureAllocationDestroy // handler
+ },
};
-const size_t RenderScriptRuntime::s_runtimeHookCount = sizeof(s_runtimeHookDefns)/sizeof(s_runtimeHookDefns[0]);
+const size_t RenderScriptRuntime::s_runtimeHookCount = sizeof(s_runtimeHookDefns)/sizeof(s_runtimeHookDefns[0]);
bool
RenderScriptRuntime::HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
@@ -193,13 +644,12 @@ RenderScriptRuntime::HookCallback(void *baton, StoppointCallbackContext *ctx, ll
return false;
}
-
void
RenderScriptRuntime::HookCallback(RuntimeHook* hook_info, ExecutionContext& context)
{
Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
- if(log)
+ if (log)
log->Printf ("RenderScriptRuntime::HookCallback - '%s' .", hook_info->defn->name);
if (hook_info->defn->grabber)
@@ -208,56 +658,241 @@ RenderScriptRuntime::HookCallback(RuntimeHook* hook_info, ExecutionContext& cont
}
}
-
bool
-RenderScriptRuntime::GetArg32Simple(ExecutionContext& context, uint32_t arg, uint32_t *data)
+RenderScriptRuntime::GetArgSimple(ExecutionContext &context, uint32_t arg, uint64_t *data)
{
- Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ // Get a positional integer argument.
+ // Given an ExecutionContext, ``context`` which should be a RenderScript
+ // frame, get the value of the positional argument ``arg`` and save its value
+ // to the address pointed to by ``data``.
+ // returns true on success, false otherwise.
+ // If unsuccessful, the value pointed to by ``data`` is undefined. Otherwise,
+ // ``data`` will be set to the value of the the given ``arg``.
+ // NOTE: only natural width integer arguments for the machine are supported.
+ // Behaviour with non primitive arguments is undefined.
if (!data)
return false;
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
Error error;
RegisterContext* reg_ctx = context.GetRegisterContext();
Process* process = context.GetProcessPtr();
+ bool success = false; // return value
- if (context.GetTargetPtr()->GetArchitecture().GetMachine() == llvm::Triple::ArchType::x86)
+ if (!context.GetTargetPtr())
{
- uint64_t sp = reg_ctx->GetSP();
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - Invalid target");
+
+ return false;
+ }
+
+ switch (context.GetTargetPtr()->GetArchitecture().GetMachine())
+ {
+ case llvm::Triple::ArchType::x86:
{
+ uint64_t sp = reg_ctx->GetSP();
uint32_t offset = (1 + arg) * sizeof(uint32_t);
- process->ReadMemory(sp + offset, data, sizeof(uint32_t), error);
- if(error.Fail())
+ uint32_t result = 0;
+ process->ReadMemory(sp + offset, &result, sizeof(uint32_t), error);
+ if (error.Fail())
{
- if(log)
- log->Printf ("RenderScriptRuntime:: GetArg32Simple - error reading X86 stack: %s.", error.AsCString());
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - error reading X86 stack: %s.", error.AsCString());
}
+ else
+ {
+ *data = result;
+ success = true;
+ }
+
+ break;
}
- }
- else if (context.GetTargetPtr()->GetArchitecture().GetMachine() == llvm::Triple::ArchType::arm)
- {
- if (arg < 4)
+ case llvm::Triple::ArchType::x86_64:
{
- const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg);
+ // amd64 has 6 integer registers, and 8 XMM registers for parameter passing.
+ // Surplus args are spilled onto the stack.
+ // rdi, rsi, rdx, rcx, r8, r9, (zmm0 - 7 for vectors)
+ // ref: AMD64 ABI Draft 0.99.6 – October 7, 2013 – 10:35; Figure 3.4. Retrieved from
+ // http://www.x86-64.org/documentation/abi.pdf
+ if (arg > 5)
+ {
+ if (log)
+ log->Warning("X86_64 register spill is not supported.");
+ break;
+ }
+ const char * regnames[] = {"rdi", "rsi", "rdx", "rcx", "r8", "r9"};
+ assert((sizeof(regnames) / sizeof(const char *)) > arg);
+ const RegisterInfo *rArg = reg_ctx->GetRegisterInfoByName(regnames[arg]);
RegisterValue rVal;
- reg_ctx->ReadRegister(rArg, rVal);
- (*data) = rVal.GetAsUInt32();
+ success = reg_ctx->ReadRegister(rArg, rVal);
+ if (success)
+ {
+ *data = rVal.GetAsUInt64(0u, &success);
+ }
+ else
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - error reading x86_64 register: %d.", arg);
+ }
+ break;
}
- else
+ case llvm::Triple::ArchType::arm:
{
- uint64_t sp = reg_ctx->GetSP();
+ // arm 32 bit
+ if (arg < 4)
{
+ const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg);
+ RegisterValue rVal;
+ success = reg_ctx->ReadRegister(rArg, rVal);
+ if (success)
+ {
+ (*data) = rVal.GetAsUInt32(0u, &success);
+ }
+ else
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - error reading ARM register: %d.", arg);
+ }
+ }
+ else
+ {
+ uint64_t sp = reg_ctx->GetSP();
uint32_t offset = (arg-4) * sizeof(uint32_t);
process->ReadMemory(sp + offset, &data, sizeof(uint32_t), error);
- if(error.Fail())
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - error reading ARM stack: %s.", error.AsCString());
+ }
+ else
{
- if(log)
- log->Printf ("RenderScriptRuntime:: GetArg32Simple - error reading ARM stack: %s.", error.AsCString());
+ success = true;
}
}
- }
+
+ break;
+ }
+ case llvm::Triple::ArchType::aarch64:
+ {
+ // arm 64 bit
+ // first 8 arguments are in the registers
+ if (arg < 8)
+ {
+ const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg);
+ RegisterValue rVal;
+ success = reg_ctx->ReadRegister(rArg, rVal);
+ if (success)
+ {
+ *data = rVal.GetAsUInt64(0u, &success);
+ }
+ else
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple() - AARCH64 - Error while reading the argument #%d", arg);
+ }
+ }
+ else
+ {
+ // @TODO: need to find the argument in the stack
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - AARCH64 - FOR #ARG >= 8 NOT IMPLEMENTED YET. Argument number: %d", arg);
+ }
+ break;
+ }
+ case llvm::Triple::ArchType::mipsel:
+ {
+
+ // read from the registers
+ if (arg < 4){
+ const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg + 4);
+ RegisterValue rVal;
+ success = reg_ctx->ReadRegister(rArg, rVal);
+ if (success)
+ {
+ *data = rVal.GetAsUInt64(0u, &success);
+ }
+ else
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple() - Mips - Error while reading the argument #%d", arg);
+ }
+
+ }
+
+ // read from the stack
+ else
+ {
+ uint64_t sp = reg_ctx->GetSP();
+ uint32_t offset = arg * sizeof(uint32_t);
+ process->ReadMemory(sp + offset, &data, sizeof(uint32_t), error);
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - error reading Mips stack: %s.", error.AsCString());
+ }
+ else
+ {
+ success = true;
+ }
+ }
+
+ break;
+ }
+ case llvm::Triple::ArchType::mips64el:
+ {
+ // read from the registers
+ if (arg < 8)
+ {
+ const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg + 4);
+ RegisterValue rVal;
+ success = reg_ctx->ReadRegister(rArg, rVal);
+ if (success)
+ {
+ (*data) = rVal.GetAsUInt64(0u, &success);
+ }
+ else
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - Mips64 - Error reading the argument #%d", arg);
+ }
+ }
+
+ // read from the stack
+ else
+ {
+ uint64_t sp = reg_ctx->GetSP();
+ uint32_t offset = (arg - 8) * sizeof(uint64_t);
+ process->ReadMemory(sp + offset, &data, sizeof(uint64_t), error);
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - Mips64 - Error reading Mips64 stack: %s.", error.AsCString());
+ }
+ else
+ {
+ success = true;
+ }
+ }
+
+ break;
+ }
+ default:
+ {
+ // invalid architecture
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - Architecture not supported");
+
+ }
}
- return true;
+
+ if (!success)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetArgSimple - failed to get argument at index %" PRIu32, arg);
+ }
+ return success;
}
void
@@ -267,35 +902,38 @@ RenderScriptRuntime::CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionConte
//Context, Script, int, data, length
- Error error;
-
- uint32_t rs_context_u32 = 0U;
- uint32_t rs_script_u32 = 0U;
- uint32_t rs_id_u32 = 0U;
- uint32_t rs_data_u32 = 0U;
- uint32_t rs_length_u32 = 0U;
+ uint64_t rs_context_u64 = 0U;
+ uint64_t rs_script_u64 = 0U;
+ uint64_t rs_id_u64 = 0U;
+ uint64_t rs_data_u64 = 0U;
+ uint64_t rs_length_u64 = 0U;
- std::string resname;
- std::string cachedir;
+ bool success =
+ GetArgSimple(context, 0, &rs_context_u64) &&
+ GetArgSimple(context, 1, &rs_script_u64) &&
+ GetArgSimple(context, 2, &rs_id_u64) &&
+ GetArgSimple(context, 3, &rs_data_u64) &&
+ GetArgSimple(context, 4, &rs_length_u64);
- GetArg32Simple(context, 0, &rs_context_u32);
- GetArg32Simple(context, 1, &rs_script_u32);
- GetArg32Simple(context, 2, &rs_id_u32);
- GetArg32Simple(context, 3, &rs_data_u32);
- GetArg32Simple(context, 4, &rs_length_u32);
+ if (!success)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::CaptureSetGlobalVar1 - Error while reading the function parameters");
+ return;
+ }
- if(log)
+ if (log)
{
log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 ":%" PRIu64 "bytes.",
- (uint64_t)rs_context_u32, (uint64_t)rs_script_u32, (uint64_t)rs_id_u32, (uint64_t)rs_data_u32, (uint64_t)rs_length_u32);
+ rs_context_u64, rs_script_u64, rs_id_u64, rs_data_u64, rs_length_u64);
- addr_t script_addr = (addr_t)rs_script_u32;
+ addr_t script_addr = (addr_t)rs_script_u64;
if (m_scriptMappings.find( script_addr ) != m_scriptMappings.end())
{
auto rsm = m_scriptMappings[script_addr];
- if (rs_id_u32 < rsm->m_globals.size())
+ if (rs_id_u64 < rsm->m_globals.size())
{
- auto rsg = rsm->m_globals[rs_id_u32];
+ auto rsg = rsm->m_globals[rs_id_u64];
log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - Setting of '%s' within '%s' inferred", rsg.m_name.AsCString(),
rsm->m_module->GetFileSpec().GetFilename().AsCString());
}
@@ -310,19 +948,65 @@ RenderScriptRuntime::CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionCon
//Context, Alloc, bool
- Error error;
-
- uint32_t rs_context_u32 = 0U;
- uint32_t rs_alloc_u32 = 0U;
- uint32_t rs_forceZero_u32 = 0U;
-
- GetArg32Simple(context, 0, &rs_context_u32);
- GetArg32Simple(context, 1, &rs_alloc_u32);
- GetArg32Simple(context, 2, &rs_forceZero_u32);
-
- if(log)
+ uint64_t rs_context_u64 = 0U;
+ uint64_t rs_alloc_u64 = 0U;
+ uint64_t rs_forceZero_u64 = 0U;
+
+ bool success =
+ GetArgSimple(context, 0, &rs_context_u64) &&
+ GetArgSimple(context, 1, &rs_alloc_u64) &&
+ GetArgSimple(context, 2, &rs_forceZero_u64);
+ if (!success) // error case
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::CaptureAllocationInit1 - Error while reading the function parameters");
+ return; // abort
+ }
+
+ if (log)
log->Printf ("RenderScriptRuntime::CaptureAllocationInit1 - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .",
- (uint64_t)rs_context_u32, (uint64_t)rs_alloc_u32, (uint64_t)rs_forceZero_u32);
+ rs_context_u64, rs_alloc_u64, rs_forceZero_u64);
+
+ AllocationDetails* alloc = LookUpAllocation(rs_alloc_u64, true);
+ if (alloc)
+ alloc->context = rs_context_u64;
+}
+
+void
+RenderScriptRuntime::CaptureAllocationDestroy(RuntimeHook* hook_info, ExecutionContext& context)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ // Context, Alloc
+ uint64_t rs_context_u64 = 0U;
+ uint64_t rs_alloc_u64 = 0U;
+
+ bool success = GetArgSimple(context, 0, &rs_context_u64) && GetArgSimple(context, 1, &rs_alloc_u64);
+ if (!success) // error case
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - Error while reading the function parameters");
+ return; // abort
+ }
+
+ if (log)
+ log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - 0x%" PRIx64 ", 0x%" PRIx64 ".",
+ rs_context_u64, rs_alloc_u64);
+
+ for (auto iter = m_allocations.begin(); iter != m_allocations.end(); ++iter)
+ {
+ auto& allocation_ap = *iter; // get the unique pointer
+ if (allocation_ap->address.isValid() && *allocation_ap->address.get() == rs_alloc_u64)
+ {
+ m_allocations.erase(iter);
+ if (log)
+ log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - Deleted allocation entry");
+ return;
+ }
+ }
+
+ if (log)
+ log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - Couldn't find destroyed allocation");
}
void
@@ -334,64 +1018,72 @@ RenderScriptRuntime::CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext
Error error;
Process* process = context.GetProcessPtr();
- uint32_t rs_context_u32 = 0U;
- uint32_t rs_script_u32 = 0U;
- uint32_t rs_resnameptr_u32 = 0U;
- uint32_t rs_cachedirptr_u32 = 0U;
+ uint64_t rs_context_u64 = 0U;
+ uint64_t rs_script_u64 = 0U;
+ uint64_t rs_resnameptr_u64 = 0U;
+ uint64_t rs_cachedirptr_u64 = 0U;
std::string resname;
std::string cachedir;
- GetArg32Simple(context, 0, &rs_context_u32);
- GetArg32Simple(context, 1, &rs_script_u32);
- GetArg32Simple(context, 2, &rs_resnameptr_u32);
- GetArg32Simple(context, 3, &rs_cachedirptr_u32);
+ // read the function parameters
+ bool success =
+ GetArgSimple(context, 0, &rs_context_u64) &&
+ GetArgSimple(context, 1, &rs_script_u64) &&
+ GetArgSimple(context, 2, &rs_resnameptr_u64) &&
+ GetArgSimple(context, 3, &rs_cachedirptr_u64);
- process->ReadCStringFromMemory((lldb::addr_t)rs_resnameptr_u32, resname, error);
+ if (!success)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::CaptureScriptInit1 - Error while reading the function parameters");
+ return;
+ }
+
+ process->ReadCStringFromMemory((lldb::addr_t)rs_resnameptr_u64, resname, error);
if (error.Fail())
{
- if(log)
+ if (log)
log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading resname: %s.", error.AsCString());
}
- process->ReadCStringFromMemory((lldb::addr_t)rs_cachedirptr_u32, cachedir, error);
+ process->ReadCStringFromMemory((lldb::addr_t)rs_cachedirptr_u64, cachedir, error);
if (error.Fail())
{
- if(log)
+ if (log)
log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading cachedir: %s.", error.AsCString());
}
if (log)
log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .",
- (uint64_t)rs_context_u32, (uint64_t)rs_script_u32, resname.c_str(), cachedir.c_str());
+ rs_context_u64, rs_script_u64, resname.c_str(), cachedir.c_str());
if (resname.size() > 0)
{
StreamString strm;
strm.Printf("librs.%s.so", resname.c_str());
- ScriptDetails script;
- script.cachedir = cachedir;
- script.resname = resname;
- script.scriptDyLib.assign(strm.GetData());
- script.script = rs_script_u32;
- script.context = rs_context_u32;
-
- m_scripts.push_back(script);
+ ScriptDetails* script = LookUpScript(rs_script_u64, true);
+ if (script)
+ {
+ script->type = ScriptDetails::eScriptC;
+ script->cacheDir = cachedir;
+ script->resName = resname;
+ script->scriptDyLib = strm.GetData();
+ script->context = addr_t(rs_context_u64);
+ }
if (log)
log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - '%s' tagged with context 0x%" PRIx64 " and script 0x%" PRIx64 ".",
- strm.GetData(), (uint64_t)rs_context_u32, (uint64_t)rs_script_u32);
+ strm.GetData(), rs_context_u64, rs_script_u64);
}
else if (log)
{
log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - resource name invalid, Script not tagged");
}
-
}
-
void
RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)
{
@@ -402,16 +1094,24 @@ RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)
return;
}
- if ((GetProcess()->GetTarget().GetArchitecture().GetMachine() != llvm::Triple::ArchType::x86)
- && (GetProcess()->GetTarget().GetArchitecture().GetMachine() != llvm::Triple::ArchType::arm))
+ Target &target = GetProcess()->GetTarget();
+ llvm::Triple::ArchType targetArchType = target.GetArchitecture().GetMachine();
+
+ if (targetArchType != llvm::Triple::ArchType::x86
+ && targetArchType != llvm::Triple::ArchType::arm
+ && targetArchType != llvm::Triple::ArchType::aarch64
+ && targetArchType != llvm::Triple::ArchType::mipsel
+ && targetArchType != llvm::Triple::ArchType::mips64el
+ && targetArchType != llvm::Triple::ArchType::x86_64
+ )
{
if (log)
- log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to hook runtime. Only X86, ARM supported currently.");
+ log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to hook runtime. Only X86, ARM, Mips supported currently.");
return;
}
- Target &target = GetProcess()->GetTarget();
+ uint32_t archByteSize = target.GetArchitecture().GetAddressByteSize();
for (size_t idx = 0; idx < s_runtimeHookCount; idx++)
{
@@ -420,16 +1120,29 @@ RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)
continue;
}
- const Symbol *sym = module->FindFirstSymbolWithNameAndType(ConstString(hook_defn->symbol_name), eSymbolTypeCode);
+ const char* symbol_name = (archByteSize == 4) ? hook_defn->symbol_name_m32 : hook_defn->symbol_name_m64;
+
+ const Symbol *sym = module->FindFirstSymbolWithNameAndType(ConstString(symbol_name), eSymbolTypeCode);
+ if (!sym){
+ if (log){
+ log->Printf("RenderScriptRuntime::LoadRuntimeHooks - ERROR: Symbol '%s' related to the function %s not found", symbol_name, hook_defn->name);
+ }
+ continue;
+ }
addr_t addr = sym->GetLoadAddress(&target);
if (addr == LLDB_INVALID_ADDRESS)
{
- if(log)
+ if (log)
log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to resolve the address of hook function '%s' with symbol '%s'.",
- hook_defn->name, hook_defn->symbol_name);
+ hook_defn->name, symbol_name);
continue;
}
+ else
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::LoadRuntimeHooks - Function %s, address resolved at 0x%" PRIx64, hook_defn->name, addr);
+ }
RuntimeHookSP hook(new RuntimeHook());
hook->address = addr;
@@ -455,35 +1168,1082 @@ RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp)
const ModuleSP module = rsmodule_sp->m_module;
const FileSpec& file = module->GetPlatformFileSpec();
-
- for (const auto &rs_script : m_scripts)
+
+ // Iterate over all of the scripts that we currently know of.
+ // Note: We cant push or pop to m_scripts here or it may invalidate rs_script.
+ for (const auto & rs_script : m_scripts)
+ {
+ // Extract the expected .so file path for this script.
+ std::string dylib;
+ if (!rs_script->scriptDyLib.get(dylib))
+ continue;
+
+ // Only proceed if the module that has loaded corresponds to this script.
+ if (file.GetFilename() != ConstString(dylib.c_str()))
+ continue;
+
+ // Obtain the script address which we use as a key.
+ lldb::addr_t script;
+ if (!rs_script->script.get(script))
+ continue;
+
+ // If we have a script mapping for the current script.
+ if (m_scriptMappings.find(script) != m_scriptMappings.end())
+ {
+ // if the module we have stored is different to the one we just received.
+ if (m_scriptMappings[script] != rsmodule_sp)
+ {
+ if (log)
+ log->Printf ("RenderScriptRuntime::FixupScriptDetails - Error: script %" PRIx64 " wants reassigned to new rsmodule '%s'.",
+ (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
+ }
+ }
+ // We don't have a script mapping for the current script.
+ else
+ {
+ // Obtain the script resource name.
+ std::string resName;
+ if (rs_script->resName.get(resName))
+ // Set the modules resource name.
+ rsmodule_sp->m_resname = resName;
+ // Add Script/Module pair to map.
+ m_scriptMappings[script] = rsmodule_sp;
+ if (log)
+ log->Printf ("RenderScriptRuntime::FixupScriptDetails - script %" PRIx64 " associated with rsmodule '%s'.",
+ (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
+ }
+ }
+}
+
+// Uses the Target API to evaluate the expression passed as a parameter to the function
+// The result of that expression is returned an unsigned 64 bit int, via the result* paramter.
+// Function returns true on success, and false on failure
+bool
+RenderScriptRuntime::EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ if (log)
+ log->Printf("RenderScriptRuntime::EvalRSExpression(%s)", expression);
+
+ ValueObjectSP expr_result;
+ // Perform the actual expression evaluation
+ GetProcess()->GetTarget().EvaluateExpression(expression, frame_ptr, expr_result);
+
+ if (!expr_result)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::EvalRSExpression - Error: Couldn't evaluate expression");
+ return false;
+ }
+
+ // The result of the expression is invalid
+ if (!expr_result->GetError().Success())
+ {
+ Error err = expr_result->GetError();
+ if (err.GetError() == UserExpression::kNoResult) // Expression returned void, so this is actually a success
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::EvalRSExpression - Expression returned void");
+
+ result = nullptr;
+ return true;
+ }
+
+ if (log)
+ log->Printf("RenderScriptRuntime::EvalRSExpression - Error evaluating expression result: %s", err.AsCString());
+ return false;
+ }
+
+ bool success = false;
+ *result = expr_result->GetValueAsUnsigned(0, &success); // We only read the result as an unsigned int.
+
+ if (!success)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::EvalRSExpression - Error: Couldn't convert expression result to unsigned int");
+ return false;
+ }
+
+ return true;
+}
+
+namespace // anonymous
+{
+ // max length of an expanded expression
+ const int jit_max_expr_size = 768;
+
+ // Format strings containing the expressions we may need to evaluate.
+ const char runtimeExpressions[][256] =
+ {
+ // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap)
+ "(int*)_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace(0x%lx, %u, %u, %u, 0, 0)",
+
+ // Type* rsaAllocationGetType(Context*, Allocation*)
+ "(void*)rsaAllocationGetType(0x%lx, 0x%lx)",
+
+ // rsaTypeGetNativeData(Context*, Type*, void* typeData, size)
+ // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ;
+ // mHal.state.lodCount; mHal.state.faces; mElement; into typeData
+ // Need to specify 32 or 64 bit for uint_t since this differs between devices
+ "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[0]", // X dim
+ "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[1]", // Y dim
+ "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[2]", // Z dim
+ "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[5]", // Element ptr
+
+ // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)
+ // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[0]", // Type
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[1]", // Kind
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[3]", // Vector Size
+ "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[4]", // Field Count
+
+ // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t *ids, const char **names,
+ // size_t *arraySizes, uint32_t dataSize)
+ // Needed for Allocations of structs to gather details about fields/Subelements
+ "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];"
+ "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); ids[%u]", // Element* of field
+
+ "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];"
+ "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); names[%u]", // Name of field
+
+ "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];"
+ "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); arr_size[%u]" // Array size of field
+ };
+
+
+ // Temporary workaround for MIPS, until the compiler emits the JAL instruction when invoking directly the function.
+ // At the moment, when evaluating an expression involving a function call, the LLVM codegen for Mips emits a JAL
+ // instruction, which is able to jump in the range +/- 128MB with respect to the current program counter ($pc). If
+ // the requested function happens to reside outside the above region, the function address will be truncated and the
+ // function invocation will fail. This is a problem in the RS plugin as we rely on the RS API to probe the number and
+ // the nature of allocations. A proper solution in the MIPS compiler is currently being investigated. As temporary
+ // work around for this context, we'll invoke the RS API through function pointers, which cause the compiler to emit a
+ // register based JALR instruction.
+ const char runtimeExpressions_mips[][512] =
+ {
+ // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap)
+ "int* (*f) (void*, int, int, int, int, int) = (int* (*) (void*, int, int, int, int, int)) "
+ "_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace; "
+ "(int*) f((void*) 0x%lx, %u, %u, %u, 0, 0)",
+
+ // Type* rsaAllocationGetType(Context*, Allocation*)
+ "void* (*f) (void*, void*) = (void* (*) (void*, void*)) rsaAllocationGetType; (void*) f((void*) 0x%lx, (void*) 0x%lx)",
+
+ // rsaTypeGetNativeData(Context*, Type*, void* typeData, size)
+ // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ;
+ // mHal.state.lodCount; mHal.state.faces; mElement; into typeData
+ // Need to specify 32 or 64 bit for uint_t since this differs between devices
+ "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) "
+ "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[0]",
+ "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) "
+ "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[1]",
+ "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) "
+ "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[2]",
+ "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) "
+ "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[5]",
+
+ // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)
+ // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData
+ "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) "
+ "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[0]", // Type
+ "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) "
+ "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[1]", // Kind
+ "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) "
+ "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[3]", // Vector size
+ "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) "
+ "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[4]", // Field count
+
+ // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t *ids, const char **names,
+ // size_t *arraySizes, uint32_t dataSize)
+ // Needed for Allocations of structs to gather details about fields/Subelements
+ "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];"
+ "void* (*f) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t) = "
+ "(void* (*) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t)) rsaElementGetSubElements;"
+ "(void*) f((void*) 0x%lx, (void*) 0x%lx, (uintptr_t*) ids, names, arr_size, (uint32_t) %u);"
+ "ids[%u]", // Element* of field
+ "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];"
+ "void* (*f) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t) = "
+ "(void* (*) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t)) rsaElementGetSubElements;"
+ "(void*) f((void*) 0x%lx, (void*) 0x%lx, (uintptr_t*) ids, names, arr_size, (uint32_t) %u);"
+ "names[%u]", // Name of field
+ "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];"
+ "void* (*f) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t) = "
+ "(void* (*) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t)) rsaElementGetSubElements;"
+ "(void*) f((void*) 0x%lx, (void*) 0x%lx, (uintptr_t*) ids, names, arr_size, (uint32_t) %u);"
+ "arr_size[%u]" // Array size of field
+ };
+
+} // end of the anonymous namespace
+
+
+// Retrieve the string to JIT for the given expression
+const char*
+RenderScriptRuntime::JITTemplate(ExpressionStrings e)
+{
+ // be nice to your Mips friend when adding new expression strings
+ static_assert(sizeof(runtimeExpressions)/sizeof(runtimeExpressions[0]) ==
+ sizeof(runtimeExpressions_mips)/sizeof(runtimeExpressions_mips[0]),
+ "#runtimeExpressions != #runtimeExpressions_mips");
+
+ assert((e >= eExprGetOffsetPtr && e <= eExprSubelementsArrSize) &&
+ "Expression string out of bounds");
+
+ llvm::Triple::ArchType arch = GetTargetRef().GetArchitecture().GetMachine();
+
+ // mips JAL workaround
+ if(arch == llvm::Triple::ArchType::mips64el || arch == llvm::Triple::ArchType::mipsel)
+ return runtimeExpressions_mips[e];
+ else
+ return runtimeExpressions[e];
+}
+
+
+// JITs the RS runtime for the internal data pointer of an allocation.
+// Is passed x,y,z coordinates for the pointer to a specific element.
+// Then sets the data_ptr member in Allocation with the result.
+// Returns true on success, false otherwise
+bool
+RenderScriptRuntime::JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr,
+ unsigned int x, unsigned int y, unsigned int z)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!allocation->address.isValid())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITDataPointer - Failed to find allocation details");
+ return false;
+ }
+
+ const char* expr_cstr = JITTemplate(eExprGetOffsetPtr);
+ char buffer[jit_max_expr_size];
+
+ int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(), x, y, z);
+ if (chars_written < 0)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
+ return false;
+ }
+ else if (chars_written >= jit_max_expr_size)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITDataPointer - Expression too long");
+ return false;
+ }
+
+ uint64_t result = 0;
+ if (!EvalRSExpression(buffer, frame_ptr, &result))
+ return false;
+
+ addr_t mem_ptr = static_cast<lldb::addr_t>(result);
+ allocation->data_ptr = mem_ptr;
+
+ return true;
+}
+
+// JITs the RS runtime for the internal pointer to the RS Type of an allocation
+// Then sets the type_ptr member in Allocation with the result.
+// Returns true on success, false otherwise
+bool
+RenderScriptRuntime::JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!allocation->address.isValid() || !allocation->context.isValid())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITTypePointer - Failed to find allocation details");
+ return false;
+ }
+
+ const char* expr_cstr = JITTemplate(eExprAllocGetType);
+ char buffer[jit_max_expr_size];
+
+ int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->context.get(), *allocation->address.get());
+ if (chars_written < 0)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
+ return false;
+ }
+ else if (chars_written >= jit_max_expr_size)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITTypePointer - Expression too long");
+ return false;
+ }
+
+ uint64_t result = 0;
+ if (!EvalRSExpression(buffer, frame_ptr, &result))
+ return false;
+
+ addr_t type_ptr = static_cast<lldb::addr_t>(result);
+ allocation->type_ptr = type_ptr;
+
+ return true;
+}
+
+// JITs the RS runtime for information about the dimensions and type of an allocation
+// Then sets dimension and element_ptr members in Allocation with the result.
+// Returns true on success, false otherwise
+bool
+RenderScriptRuntime::JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!allocation->type_ptr.isValid() || !allocation->context.isValid())
{
- if (file.GetFilename() == ConstString(rs_script.scriptDyLib.c_str()))
+ if (log)
+ log->Printf("RenderScriptRuntime::JITTypePacked - Failed to find allocation details");
+ return false;
+ }
+
+ // Expression is different depending on if device is 32 or 64 bit
+ uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
+ const unsigned int bits = archByteSize == 4 ? 32 : 64;
+
+ // We want 4 elements from packed data
+ const unsigned int num_exprs = 4;
+ assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1) && "Invalid number of expressions");
+
+ char buffer[num_exprs][jit_max_expr_size];
+ uint64_t results[num_exprs];
+
+ for (unsigned int i = 0; i < num_exprs; ++i)
+ {
+ const char* expr_cstr = JITTemplate((ExpressionStrings) (eExprTypeDimX + i));
+ int chars_written = snprintf(buffer[i], jit_max_expr_size, expr_cstr, bits,
+ *allocation->context.get(), *allocation->type_ptr.get());
+ if (chars_written < 0)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
+ return false;
+ }
+ else if (chars_written >= jit_max_expr_size)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITTypePacked - Expression too long");
+ return false;
+ }
+
+ // Perform expression evaluation
+ if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
+ return false;
+ }
+
+ // Assign results to allocation members
+ AllocationDetails::Dimension dims;
+ dims.dim_1 = static_cast<uint32_t>(results[0]);
+ dims.dim_2 = static_cast<uint32_t>(results[1]);
+ dims.dim_3 = static_cast<uint32_t>(results[2]);
+ allocation->dimension = dims;
+
+ addr_t elem_ptr = static_cast<lldb::addr_t>(results[3]);
+ allocation->element.element_ptr = elem_ptr;
+
+ if (log)
+ log->Printf("RenderScriptRuntime::JITTypePacked - dims (%u, %u, %u) Element*: 0x%" PRIx64,
+ dims.dim_1, dims.dim_2, dims.dim_3, elem_ptr);
+
+ return true;
+}
+
+// JITs the RS runtime for information about the Element of an allocation
+// Then sets type, type_vec_size, field_count and type_kind members in Element with the result.
+// Returns true on success, false otherwise
+bool
+RenderScriptRuntime::JITElementPacked(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!elem.element_ptr.isValid())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITElementPacked - Failed to find allocation details");
+ return false;
+ }
+
+ // We want 4 elements from packed data
+ const unsigned int num_exprs = 4;
+ assert(num_exprs == (eExprElementFieldCount - eExprElementType + 1) && "Invalid number of expressions");
+
+ char buffer[num_exprs][jit_max_expr_size];
+ uint64_t results[num_exprs];
+
+ for (unsigned int i = 0; i < num_exprs; i++)
+ {
+ const char* expr_cstr = JITTemplate((ExpressionStrings) (eExprElementType + i));
+ int chars_written = snprintf(buffer[i], jit_max_expr_size, expr_cstr, context, *elem.element_ptr.get());
+ if (chars_written < 0)
{
- if (m_scriptMappings.find( rs_script.script ) != m_scriptMappings.end())
+ if (log)
+ log->Printf("RenderScriptRuntime::JITElementPacked - Encoding error in snprintf()");
+ return false;
+ }
+ else if (chars_written >= jit_max_expr_size)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITElementPacked - Expression too long");
+ return false;
+ }
+
+ // Perform expression evaluation
+ if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
+ return false;
+ }
+
+ // Assign results to allocation members
+ elem.type = static_cast<RenderScriptRuntime::Element::DataType>(results[0]);
+ elem.type_kind = static_cast<RenderScriptRuntime::Element::DataKind>(results[1]);
+ elem.type_vec_size = static_cast<uint32_t>(results[2]);
+ elem.field_count = static_cast<uint32_t>(results[3]);
+
+ if (log)
+ log->Printf("RenderScriptRuntime::JITElementPacked - data type %u, pixel type %u, vector size %u, field count %u",
+ *elem.type.get(), *elem.type_kind.get(), *elem.type_vec_size.get(), *elem.field_count.get());
+
+ // If this Element has subelements then JIT rsaElementGetSubElements() for details about its fields
+ if (*elem.field_count.get() > 0 && !JITSubelements(elem, context, frame_ptr))
+ return false;
+
+ return true;
+}
+
+// JITs the RS runtime for information about the subelements/fields of a struct allocation
+// This is necessary for infering the struct type so we can pretty print the allocation's contents.
+// Returns true on success, false otherwise
+bool
+RenderScriptRuntime::JITSubelements(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!elem.element_ptr.isValid() || !elem.field_count.isValid())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITSubelements - Failed to find allocation details");
+ return false;
+ }
+
+ const short num_exprs = 3;
+ assert(num_exprs == (eExprSubelementsArrSize - eExprSubelementsId + 1) && "Invalid number of expressions");
+
+ char expr_buffer[jit_max_expr_size];
+ uint64_t results;
+
+ // Iterate over struct fields.
+ const uint32_t field_count = *elem.field_count.get();
+ for (unsigned int field_index = 0; field_index < field_count; ++field_index)
+ {
+ Element child;
+ for (unsigned int expr_index = 0; expr_index < num_exprs; ++expr_index)
+ {
+ const char* expr_cstr = JITTemplate((ExpressionStrings) (eExprSubelementsId + expr_index));
+ int chars_written = snprintf(expr_buffer, jit_max_expr_size, expr_cstr,
+ field_count, field_count, field_count,
+ context, *elem.element_ptr.get(), field_count, field_index);
+ if (chars_written < 0)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITSubelements - Encoding error in snprintf()");
+ return false;
+ }
+ else if (chars_written >= jit_max_expr_size)
{
- if (m_scriptMappings[rs_script.script] != rsmodule_sp)
+ if (log)
+ log->Printf("RenderScriptRuntime::JITSubelements - Expression too long");
+ return false;
+ }
+
+ // Perform expression evaluation
+ if (!EvalRSExpression(expr_buffer, frame_ptr, &results))
+ return false;
+
+ if (log)
+ log->Printf("RenderScriptRuntime::JITSubelements - Expr result 0x%" PRIx64, results);
+
+ switch(expr_index)
+ {
+ case 0: // Element* of child
+ child.element_ptr = static_cast<addr_t>(results);
+ break;
+ case 1: // Name of child
{
- if (log)
+ lldb::addr_t address = static_cast<addr_t>(results);
+ Error err;
+ std::string name;
+ GetProcess()->ReadCStringFromMemory(address, name, err);
+ if (!err.Fail())
+ child.type_name = ConstString(name);
+ else
{
- log->Printf ("RenderScriptRuntime::FixupScriptDetails - Error: script %" PRIx64 " wants reassigned to new rsmodule '%s'.",
- (uint64_t)rs_script.script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
+ if (log)
+ log->Printf("RenderScriptRuntime::JITSubelements - Warning: Couldn't read field name");
}
+ break;
}
+ case 2: // Array size of child
+ child.array_size = static_cast<uint32_t>(results);
+ break;
}
- else
+ }
+
+ // We need to recursively JIT each Element field of the struct since
+ // structs can be nested inside structs.
+ if (!JITElementPacked(child, context, frame_ptr))
+ return false;
+ elem.children.push_back(child);
+ }
+
+ // Try to infer the name of the struct type so we can pretty print the allocation contents.
+ FindStructTypeName(elem, frame_ptr);
+
+ return true;
+}
+
+// JITs the RS runtime for the address of the last element in the allocation.
+// The `elem_size` paramter represents the size of a single element, including padding.
+// Which is needed as an offset from the last element pointer.
+// Using this offset minus the starting address we can calculate the size of the allocation.
+// Returns true on success, false otherwise
+bool
+RenderScriptRuntime::JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!allocation->address.isValid() || !allocation->dimension.isValid()
+ || !allocation->data_ptr.isValid() || !allocation->element.datum_size.isValid())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITAllocationSize - Failed to find allocation details");
+ return false;
+ }
+
+ // Find dimensions
+ unsigned int dim_x = allocation->dimension.get()->dim_1;
+ unsigned int dim_y = allocation->dimension.get()->dim_2;
+ unsigned int dim_z = allocation->dimension.get()->dim_3;
+
+ // Our plan of jitting the last element address doesn't seem to work for struct Allocations
+ // Instead try to infer the size ourselves without any inter element padding.
+ if (allocation->element.children.size() > 0)
+ {
+ if (dim_x == 0) dim_x = 1;
+ if (dim_y == 0) dim_y = 1;
+ if (dim_z == 0) dim_z = 1;
+
+ allocation->size = dim_x * dim_y * dim_z * *allocation->element.datum_size.get();
+
+ if (log)
+ log->Printf("RenderScriptRuntime::JITAllocationSize - Infered size of struct allocation %u", *allocation->size.get());
+
+ return true;
+ }
+
+ const char* expr_cstr = JITTemplate(eExprGetOffsetPtr);
+ char buffer[jit_max_expr_size];
+
+ // Calculate last element
+ dim_x = dim_x == 0 ? 0 : dim_x - 1;
+ dim_y = dim_y == 0 ? 0 : dim_y - 1;
+ dim_z = dim_z == 0 ? 0 : dim_z - 1;
+
+ int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(),
+ dim_x, dim_y, dim_z);
+ if (chars_written < 0)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITAllocationSize - Encoding error in snprintf()");
+ return false;
+ }
+ else if (chars_written >= jit_max_expr_size)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITAllocationSize - Expression too long");
+ return false;
+ }
+
+ uint64_t result = 0;
+ if (!EvalRSExpression(buffer, frame_ptr, &result))
+ return false;
+
+ addr_t mem_ptr = static_cast<lldb::addr_t>(result);
+ // Find pointer to last element and add on size of an element
+ allocation->size = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()) + *allocation->element.datum_size.get();
+
+ return true;
+}
+
+// JITs the RS runtime for information about the stride between rows in the allocation.
+// This is done to detect padding, since allocated memory is 16-byte aligned.
+// Returns true on success, false otherwise
+bool
+RenderScriptRuntime::JITAllocationStride(AllocationDetails* allocation, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!allocation->address.isValid() || !allocation->data_ptr.isValid())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITAllocationStride - Failed to find allocation details");
+ return false;
+ }
+
+ const char* expr_cstr = JITTemplate(eExprGetOffsetPtr);
+ char buffer[jit_max_expr_size];
+
+ int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(),
+ 0, 1, 0);
+ if (chars_written < 0)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITAllocationStride - Encoding error in snprintf()");
+ return false;
+ }
+ else if (chars_written >= jit_max_expr_size)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::JITAllocationStride - Expression too long");
+ return false;
+ }
+
+ uint64_t result = 0;
+ if (!EvalRSExpression(buffer, frame_ptr, &result))
+ return false;
+
+ addr_t mem_ptr = static_cast<lldb::addr_t>(result);
+ allocation->stride = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get());
+
+ return true;
+}
+
+// JIT all the current runtime info regarding an allocation
+bool
+RenderScriptRuntime::RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr)
+{
+ // GetOffsetPointer()
+ if (!JITDataPointer(allocation, frame_ptr))
+ return false;
+
+ // rsaAllocationGetType()
+ if (!JITTypePointer(allocation, frame_ptr))
+ return false;
+
+ // rsaTypeGetNativeData()
+ if (!JITTypePacked(allocation, frame_ptr))
+ return false;
+
+ // rsaElementGetNativeData()
+ if (!JITElementPacked(allocation->element, *allocation->context.get(), frame_ptr))
+ return false;
+
+ // Sets the datum_size member in Element
+ SetElementSize(allocation->element);
+
+ // Use GetOffsetPointer() to infer size of the allocation
+ if (!JITAllocationSize(allocation, frame_ptr))
+ return false;
+
+ return true;
+}
+
+// Function attempts to set the type_name member of the paramaterised Element object.
+// This string should be the name of the struct type the Element represents.
+// We need this string for pretty printing the Element to users.
+void
+RenderScriptRuntime::FindStructTypeName(Element& elem, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ if (!elem.type_name.IsEmpty()) // Name already set
+ return;
+ else
+ elem.type_name = Element::GetFallbackStructName(); // Default type name if we don't succeed
+
+ // Find all the global variables from the script rs modules
+ VariableList variable_list;
+ for (auto module_sp : m_rsmodules)
+ module_sp->m_module->FindGlobalVariables(RegularExpression("."), true, UINT32_MAX, variable_list);
+
+ // 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 var_index = 0; var_index < variable_list.GetSize(); ++var_index)
+ {
+ const VariableSP var_sp(variable_list.GetVariableAtIndex(var_index));
+ if (!var_sp)
+ continue;
+
+ ValueObjectSP valobj_sp = ValueObjectVariable::Create(frame_ptr, var_sp);
+ if (!valobj_sp)
+ continue;
+
+ // Find the number of variable fields.
+ // If it has no fields, or more fields than our Element, then it can't be the struct we're looking for.
+ // Don't check for equality since RS can add extra struct members for padding.
+ size_t num_children = valobj_sp->GetNumChildren();
+ if (num_children > elem.children.size() || num_children == 0)
+ continue;
+
+ // Iterate over children looking for members with matching field names.
+ // If all the field names match, this is likely the struct we want.
+ //
+ // TODO: This could be made more robust by also checking children data sizes, or array size
+ bool found = true;
+ for (size_t child_index = 0; child_index < num_children; ++child_index)
+ {
+ ValueObjectSP child = valobj_sp->GetChildAtIndex(child_index, true);
+ if (!child || (child->GetName() != elem.children[child_index].type_name))
{
- m_scriptMappings[rs_script.script] = rsmodule_sp;
- rsmodule_sp->m_resname = rs_script.resname;
- if (log)
- {
- log->Printf ("RenderScriptRuntime::FixupScriptDetails - script %" PRIx64 " associated with rsmodule '%s'.",
- (uint64_t)rs_script.script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
- }
+ found = false;
+ break;
+ }
+ }
+
+ // RS can add extra struct members for padding in the format '#rs_padding_[0-9]+'
+ if (found && num_children < elem.children.size())
+ {
+ const unsigned int size_diff = elem.children.size() - num_children;
+ if (log)
+ log->Printf("RenderScriptRuntime::FindStructTypeName - %u padding struct entries", size_diff);
+
+ for (unsigned int padding_index = 0; padding_index < size_diff; ++padding_index)
+ {
+ const ConstString& name = elem.children[num_children + padding_index].type_name;
+ if (strcmp(name.AsCString(), "#rs_padding") < 0)
+ found = false;
}
}
+
+ // We've found a global var with matching type
+ if (found)
+ {
+ // Dereference since our Element type isn't a pointer.
+ if (valobj_sp->IsPointerType())
+ {
+ Error err;
+ ValueObjectSP deref_valobj = valobj_sp->Dereference(err);
+ if (!err.Fail())
+ valobj_sp = deref_valobj;
+ }
+
+ // Save name of variable in Element.
+ elem.type_name = valobj_sp->GetTypeName();
+ if (log)
+ log->Printf("RenderScriptRuntime::FindStructTypeName - Element name set to %s", elem.type_name.AsCString());
+
+ return;
+ }
}
-
+}
+
+// Function sets the datum_size member of Element. Representing the size of a single instance including padding.
+// Assumes the relevant allocation information has already been jitted.
+void
+RenderScriptRuntime::SetElementSize(Element& elem)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ const Element::DataType type = *elem.type.get();
+ assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT
+ && "Invalid allocation type");
+
+ const unsigned int vec_size = *elem.type_vec_size.get();
+ unsigned int data_size = 0;
+ unsigned int padding = 0;
+
+ // Element is of a struct type, calculate size recursively.
+ if ((type == Element::RS_TYPE_NONE) && (elem.children.size() > 0))
+ {
+ for (Element& child : elem.children)
+ {
+ SetElementSize(child);
+ const unsigned int array_size = child.array_size.isValid() ? *child.array_size.get() : 1;
+ data_size += *child.datum_size.get() * array_size;
+ }
+ }
+ else if (type == Element::RS_TYPE_UNSIGNED_5_6_5 || type == Element::RS_TYPE_UNSIGNED_5_5_5_1 ||
+ type == Element::RS_TYPE_UNSIGNED_4_4_4_4) // These have been packed already
+ {
+ data_size = AllocationDetails::RSTypeToFormat[type][eElementSize];
+ }
+ else if (type < Element::RS_TYPE_ELEMENT)
+ {
+ data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];
+ if (vec_size == 3)
+ padding = AllocationDetails::RSTypeToFormat[type][eElementSize];
+ }
+ else
+ data_size = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
+
+ elem.padding = padding;
+ elem.datum_size = data_size + padding;
+ if (log)
+ log->Printf("RenderScriptRuntime::SetElementSize - element size set to %u", data_size + padding);
+}
+
+// Given an allocation, this function copies the allocation contents from device into a buffer on the heap.
+// Returning a shared pointer to the buffer containing the data.
+std::shared_ptr<uint8_t>
+RenderScriptRuntime::GetAllocationData(AllocationDetails* allocation, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ // JIT all the allocation details
+ if (allocation->shouldRefresh())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetAllocationData - Allocation details not calculated yet, jitting info");
+
+ if (!RefreshAllocation(allocation, frame_ptr))
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't JIT allocation details");
+ return nullptr;
+ }
+ }
+
+ assert(allocation->data_ptr.isValid() && allocation->element.type.isValid() && allocation->element.type_vec_size.isValid()
+ && allocation->size.isValid() && "Allocation information not available");
+
+ // Allocate a buffer to copy data into
+ const unsigned int size = *allocation->size.get();
+ std::shared_ptr<uint8_t> buffer(new uint8_t[size]);
+ if (!buffer)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't allocate a %u byte buffer", size);
+ return nullptr;
+ }
+
+ // Read the inferior memory
+ Error error;
+ lldb::addr_t data_ptr = *allocation->data_ptr.get();
+ GetProcess()->ReadMemory(data_ptr, buffer.get(), size, error);
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetAllocationData - '%s' Couldn't read %u bytes of allocation data from 0x%" PRIx64,
+ error.AsCString(), size, data_ptr);
+ return nullptr;
+ }
+
+ return buffer;
+}
+
+// Function copies data from a binary file into an allocation.
+// There is a header at the start of the file, FileHeader, before the data content itself.
+// Information from this header is used to display warnings to the user about incompatabilities
+bool
+RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ // Find allocation with the given id
+ AllocationDetails* alloc = FindAllocByID(strm, alloc_id);
+ if (!alloc)
+ return false;
+
+ if (log)
+ log->Printf("RenderScriptRuntime::LoadAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());
+
+ // JIT all the allocation details
+ if (alloc->shouldRefresh())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::LoadAllocation - Allocation details not calculated yet, jitting info");
+
+ if (!RefreshAllocation(alloc, frame_ptr))
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::LoadAllocation - Couldn't JIT allocation details");
+ return false;
+ }
+ }
+
+ assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && alloc->element.type_vec_size.isValid()
+ && alloc->size.isValid() && alloc->element.datum_size.isValid() && "Allocation information not available");
+
+ // Check we can read from file
+ FileSpec file(filename, true);
+ if (!file.Exists())
+ {
+ strm.Printf("Error: File %s does not exist", filename);
+ strm.EOL();
+ return false;
+ }
+
+ if (!file.Readable())
+ {
+ strm.Printf("Error: File %s does not have readable permissions", filename);
+ strm.EOL();
+ return false;
+ }
+
+ // Read file into data buffer
+ DataBufferSP data_sp(file.ReadFileContents());
+
+ // Cast start of buffer to FileHeader and use pointer to read metadata
+ void* file_buffer = data_sp->GetBytes();
+ const AllocationDetails::FileHeader* head = static_cast<AllocationDetails::FileHeader*>(file_buffer);
+
+ // Advance buffer past header
+ file_buffer = static_cast<uint8_t*>(file_buffer) + head->hdr_size;
+
+ if (log)
+ log->Printf("RenderScriptRuntime::LoadAllocation - header type %u, element size %u",
+ head->type, head->element_size);
+
+ // Check if the target allocation and file both have the same number of bytes for an Element
+ if (*alloc->element.datum_size.get() != head->element_size)
+ {
+ strm.Printf("Warning: Mismatched Element sizes - file %u bytes, allocation %u bytes",
+ head->element_size, *alloc->element.datum_size.get());
+ strm.EOL();
+ }
+
+ // Check if the target allocation and file both have the same integral type
+ const unsigned int type = static_cast<unsigned int>(*alloc->element.type.get());
+ if (type != head->type)
+ {
+ // Enum value isn't monotonous, so doesn't always index RsDataTypeToString array
+ unsigned int printable_target_type_index = type;
+ unsigned int printable_head_type_index = head->type;
+ if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT)
+ printable_target_type_index = static_cast<Element::DataType>(
+ (type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1);
+
+ if (head->type >= Element::RS_TYPE_ELEMENT && head->type <= Element::RS_TYPE_FONT)
+ printable_head_type_index = static_cast<Element::DataType>(
+ (head->type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1);
+
+ const char* file_type_cstr = AllocationDetails::RsDataTypeToString[printable_head_type_index][0];
+ const char* target_type_cstr = AllocationDetails::RsDataTypeToString[printable_target_type_index][0];
+
+ strm.Printf("Warning: Mismatched Types - file '%s' type, allocation '%s' type",
+ file_type_cstr, target_type_cstr);
+ strm.EOL();
+ }
+
+ // Calculate size of allocation data in file
+ size_t length = data_sp->GetByteSize() - head->hdr_size;
+
+ // Check if the target allocation and file both have the same total data size.
+ const unsigned int alloc_size = *alloc->size.get();
+ if (alloc_size != length)
+ {
+ strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64 " bytes, allocation 0x%x bytes",
+ (uint64_t) length, alloc_size);
+ strm.EOL();
+ length = alloc_size < length ? alloc_size : length; // Set length to copy to minimum
+ }
+
+ // Copy file data from our buffer into the target allocation.
+ lldb::addr_t alloc_data = *alloc->data_ptr.get();
+ Error error;
+ size_t bytes_written = GetProcess()->WriteMemory(alloc_data, file_buffer, length, error);
+ if (!error.Success() || bytes_written != length)
+ {
+ strm.Printf("Error: Couldn't write data to allocation %s", error.AsCString());
+ strm.EOL();
+ return false;
+ }
+
+ strm.Printf("Contents of file '%s' read into allocation %u", filename, alloc->id);
+ strm.EOL();
+
+ return true;
+}
+
+// Function copies allocation contents into a binary file.
+// This file can then be loaded later into a different allocation.
+// There is a header, FileHeader, before the allocation data containing meta-data.
+bool
+RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ // Find allocation with the given id
+ AllocationDetails* alloc = FindAllocByID(strm, alloc_id);
+ if (!alloc)
+ return false;
+
+ if (log)
+ log->Printf("RenderScriptRuntime::SaveAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());
+
+ // JIT all the allocation details
+ if (alloc->shouldRefresh())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::SaveAllocation - Allocation details not calculated yet, jitting info");
+
+ if (!RefreshAllocation(alloc, frame_ptr))
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::SaveAllocation - Couldn't JIT allocation details");
+ return false;
+ }
+ }
+
+ assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && alloc->element.type_vec_size.isValid() && alloc->element.datum_size.get()
+ && alloc->element.type_kind.isValid() && alloc->dimension.isValid() && "Allocation information not available");
+
+ // Check we can create writable file
+ FileSpec file_spec(filename, true);
+ File file(file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionTruncate);
+ if (!file)
+ {
+ strm.Printf("Error: Failed to open '%s' for writing", filename);
+ strm.EOL();
+ return false;
+ }
+
+ // Read allocation into buffer of heap memory
+ const std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
+ if (!buffer)
+ {
+ strm.Printf("Error: Couldn't read allocation data into buffer");
+ strm.EOL();
+ return false;
+ }
+
+ // Create the file header
+ AllocationDetails::FileHeader head;
+ head.ident[0] = 'R'; head.ident[1] = 'S'; head.ident[2] = 'A'; head.ident[3] = 'D';
+ head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader));
+ head.type = static_cast<uint16_t>(*alloc->element.type.get());
+ head.kind = static_cast<uint32_t>(*alloc->element.type_kind.get());
+ head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1);
+ head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2);
+ head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3);
+ head.element_size = static_cast<uint32_t>(*alloc->element.datum_size.get());
+
+ // Write the file header
+ size_t num_bytes = sizeof(AllocationDetails::FileHeader);
+ Error err = file.Write(static_cast<const void*>(&head), num_bytes);
+ if (!err.Success())
+ {
+ strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
+ strm.EOL();
+ return false;
+ }
+
+ // Write allocation data to file
+ num_bytes = static_cast<size_t>(*alloc->size.get());
+ if (log)
+ log->Printf("RenderScriptRuntime::SaveAllocation - Writing 0x%" PRIx64 " bytes from %p", (uint64_t) num_bytes, buffer.get());
+
+ err = file.Write(buffer.get(), num_bytes);
+ if (!err.Success())
+ {
+ strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
+ strm.EOL();
+ return false;
+ }
+
+ strm.Printf("Allocation written to file '%s'", filename);
+ strm.EOL();
+ return true;
}
bool
@@ -496,7 +2256,14 @@ RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp)
for (const auto &rs_module : m_rsmodules)
{
if (rs_module->m_module == module_sp)
+ {
+ // Check if the user has enabled automatically breaking on
+ // all RS kernels.
+ if (m_breakAllKernels)
+ BreakOnModuleKernels(rs_module);
+
return false;
+ }
}
bool module_loaded = false;
switch (GetModuleKind(module_sp))
@@ -585,7 +2352,6 @@ RenderScriptRuntime::Update()
}
}
-
// The maximum line length of an .rs.info packet
#define MAXLINE 500
@@ -609,12 +2375,12 @@ RSModuleDescriptor::ParseRSInfo()
std::string info((const char *)buffer->GetBytes());
std::vector<std::string> info_lines;
- size_t lpos = info.find_first_of("\n");
+ size_t lpos = info.find('\n');
while (lpos != std::string::npos)
{
info_lines.push_back(info.substr(0, lpos));
info = info.substr(lpos + 1);
- lpos = info.find_first_of("\n");
+ lpos = info.find('\n');
}
size_t offset = 0;
while (offset < info_lines.size())
@@ -710,7 +2476,6 @@ RenderScriptRuntime::Status(Stream &strm) const
strm.Indent(b.second->defn->name);
strm.EOL();
}
- strm.EOL();
}
else
{
@@ -728,15 +2493,21 @@ RenderScriptRuntime::DumpContexts(Stream &strm) const
std::map<addr_t, uint64_t> contextReferences;
- for (const auto &script : m_scripts)
+ // Iterate over all of the currently discovered scripts.
+ // Note: We cant push or pop from m_scripts inside this loop or it may invalidate script.
+ for (const auto & script : m_scripts)
{
- if (contextReferences.find(script.context) != contextReferences.end())
+ if (!script->context.isValid())
+ continue;
+ lldb::addr_t context = *script->context;
+
+ if (contextReferences.find(context) != contextReferences.end())
{
- contextReferences[script.context]++;
+ contextReferences[context]++;
}
else
{
- contextReferences[script.context] = 1;
+ contextReferences[context] = 1;
}
}
@@ -767,69 +2538,502 @@ RenderScriptRuntime::DumpKernels(Stream &strm) const
strm.IndentLess();
}
-void
-RenderScriptRuntime::AttemptBreakpointAtKernelName(Stream &strm, const char* name, Error& error)
+RenderScriptRuntime::AllocationDetails*
+RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id)
{
- if (!name)
+ AllocationDetails* alloc = nullptr;
+
+ // See if we can find allocation using id as an index;
+ if (alloc_id <= m_allocations.size() && alloc_id != 0
+ && m_allocations[alloc_id-1]->id == alloc_id)
{
- error.SetErrorString("invalid kernel name");
- return;
+ alloc = m_allocations[alloc_id-1].get();
+ return alloc;
}
- bool kernels_found;
- ConstString kernel_name(name);
- for (const auto &module : m_rsmodules)
+ // Fallback to searching
+ for (const auto & a : m_allocations)
{
- for (const auto &kernel : module->m_kernels)
+ if (a->id == alloc_id)
+ {
+ alloc = a.get();
+ break;
+ }
+ }
+
+ if (alloc == nullptr)
+ {
+ strm.Printf("Error: Couldn't find allocation with id matching %u", alloc_id);
+ strm.EOL();
+ }
+
+ return alloc;
+}
+
+// Prints the contents of an allocation to the output stream, which may be a file
+bool
+RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame* frame_ptr, const uint32_t id)
+{
+ Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+
+ // Check we can find the desired allocation
+ AllocationDetails* alloc = FindAllocByID(strm, id);
+ if (!alloc)
+ return false; // FindAllocByID() will print error message for us here
+
+ if (log)
+ log->Printf("RenderScriptRuntime::DumpAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());
+
+ // Check we have information about the allocation, if not calculate it
+ if (alloc->shouldRefresh())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::DumpAllocation - Allocation details not calculated yet, jitting info");
+
+ // JIT all the allocation information
+ if (!RefreshAllocation(alloc, frame_ptr))
{
- if (kernel.m_name == kernel_name)
- {
- //Attempt to set a breakpoint on this symbol, within the module library
- //If it's not found, it's likely debug info is unavailable - set a
- //breakpoint on <name>.expand and emit a warning.
+ strm.Printf("Error: Couldn't JIT allocation details");
+ strm.EOL();
+ return false;
+ }
+ }
+
+ // Establish format and size of each data element
+ const unsigned int vec_size = *alloc->element.type_vec_size.get();
+ const Element::DataType type = *alloc->element.type.get();
+
+ assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT
+ && "Invalid allocation type");
+
+ lldb::Format format;
+ if (type >= Element::RS_TYPE_ELEMENT)
+ format = eFormatHex;
+ else
+ format = vec_size == 1 ? static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatSingle])
+ : static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatVector]);
+
+ const unsigned int data_size = *alloc->element.datum_size.get();
+
+ if (log)
+ log->Printf("RenderScriptRuntime::DumpAllocation - Element size %u bytes, including padding", data_size);
+
+ // Allocate a buffer to copy data into
+ std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
+ if (!buffer)
+ {
+ strm.Printf("Error: Couldn't read allocation data");
+ strm.EOL();
+ return false;
+ }
+
+ // Calculate stride between rows as there may be padding at end of rows since
+ // allocated memory is 16-byte aligned
+ if (!alloc->stride.isValid())
+ {
+ if (alloc->dimension.get()->dim_2 == 0) // We only have one dimension
+ alloc->stride = 0;
+ else if (!JITAllocationStride(alloc, frame_ptr))
+ {
+ strm.Printf("Error: Couldn't calculate allocation row stride");
+ strm.EOL();
+ return false;
+ }
+ }
+ const unsigned int stride = *alloc->stride.get();
+ const unsigned int size = *alloc->size.get(); // Size of whole allocation
+ const unsigned int padding = alloc->element.padding.isValid() ? *alloc->element.padding.get() : 0;
+ if (log)
+ log->Printf("RenderScriptRuntime::DumpAllocation - stride %u bytes, size %u bytes, padding %u", stride, size, padding);
+
+ // Find dimensions used to index loops, so need to be non-zero
+ unsigned int dim_x = alloc->dimension.get()->dim_1;
+ dim_x = dim_x == 0 ? 1 : dim_x;
- const Symbol* kernel_sym = module->m_module->FindFirstSymbolWithNameAndType(kernel_name, eSymbolTypeCode);
+ unsigned int dim_y = alloc->dimension.get()->dim_2;
+ dim_y = dim_y == 0 ? 1 : dim_y;
- if (!kernel_sym)
+ unsigned int dim_z = alloc->dimension.get()->dim_3;
+ dim_z = dim_z == 0 ? 1 : dim_z;
+
+ // Use data extractor to format output
+ const uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
+ DataExtractor alloc_data(buffer.get(), size, GetProcess()->GetByteOrder(), archByteSize);
+
+ unsigned int offset = 0; // Offset in buffer to next element to be printed
+ unsigned int prev_row = 0; // Offset to the start of the previous row
+
+ // Iterate over allocation dimensions, printing results to user
+ strm.Printf("Data (X, Y, Z):");
+ for (unsigned int z = 0; z < dim_z; ++z)
+ {
+ for (unsigned int y = 0; y < dim_y; ++y)
+ {
+ // Use stride to index start of next row.
+ if (!(y==0 && z==0))
+ offset = prev_row + stride;
+ prev_row = offset;
+
+ // Print each element in the row individually
+ for (unsigned int x = 0; x < dim_x; ++x)
+ {
+ strm.Printf("\n(%u, %u, %u) = ", x, y, z);
+ if ((type == Element::RS_TYPE_NONE) && (alloc->element.children.size() > 0) &&
+ (alloc->element.type_name != Element::GetFallbackStructName()))
{
- std::string kernel_name_expanded(name);
- kernel_name_expanded.append(".expand");
- kernel_sym = module->m_module->FindFirstSymbolWithNameAndType(ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode);
+ // Here we are dumping an Element of struct type.
+ // This is done using expression evaluation with the name of the struct type and pointer to element.
- if (kernel_sym)
- {
- strm.Printf("Kernel '%s' could not be found, but expansion exists. ", name);
- strm.Printf("Breakpoint placed on expanded kernel. Have you compiled in debug mode?");
- strm.EOL();
- }
- else
+ // Don't print the name of the resulting expression, since this will be '$[0-9]+'
+ DumpValueObjectOptions expr_options;
+ expr_options.SetHideName(true);
+
+ // Setup expression as derefrencing a pointer cast to element address.
+ char expr_char_buffer[jit_max_expr_size];
+ int chars_written = snprintf(expr_char_buffer, jit_max_expr_size, "*(%s*) 0x%" PRIx64,
+ alloc->element.type_name.AsCString(), *alloc->data_ptr.get() + offset);
+
+ if (chars_written < 0 || chars_written >= jit_max_expr_size)
{
- error.SetErrorStringWithFormat("Could not locate symbols for loaded kernel '%s'.", name);
- return;
+ if (log)
+ log->Printf("RenderScriptRuntime::DumpAllocation- Error in snprintf()");
+ continue;
}
- }
- addr_t bp_addr = kernel_sym->GetLoadAddress(&GetProcess()->GetTarget());
- if (bp_addr == LLDB_INVALID_ADDRESS)
+ // Evaluate expression
+ ValueObjectSP expr_result;
+ GetProcess()->GetTarget().EvaluateExpression(expr_char_buffer, frame_ptr, expr_result);
+
+ // Print the results to our stream.
+ expr_result->Dump(strm, expr_options);
+ }
+ else
{
- error.SetErrorStringWithFormat("Could not locate load address for symbols of kernel '%s'.", name);
- return;
+ alloc_data.Dump(&strm, offset, format, data_size - padding, 1, 1, LLDB_INVALID_ADDRESS, 0, 0);
}
+ offset += data_size;
+ }
+ }
+ }
+ strm.EOL();
+
+ return true;
+}
+
+// Prints infomation regarding all the currently loaded allocations.
+// These details are gathered by jitting the runtime, which has as latency.
+void
+RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute)
+{
+ strm.Printf("RenderScript Allocations:");
+ strm.EOL();
+ strm.IndentMore();
+
+ for (auto &alloc : m_allocations)
+ {
+ // JIT the allocation info if we haven't done it, or the user forces us to.
+ bool do_refresh = alloc->shouldRefresh() || recompute;
+
+ // JIT current allocation information
+ if (do_refresh && !RefreshAllocation(alloc.get(), frame_ptr))
+ {
+ strm.Printf("Error: Couldn't evaluate details for allocation %u\n", alloc->id);
+ continue;
+ }
- BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(bp_addr, false, false);
- strm.Printf("Breakpoint %" PRIu64 ": kernel '%s' within script '%s'", (uint64_t)bp->GetID(), name, module->m_resname.c_str());
- strm.EOL();
+ strm.Printf("%u:\n",alloc->id);
+ strm.IndentMore();
- kernels_found = true;
+ strm.Indent("Context: ");
+ if (!alloc->context.isValid())
+ strm.Printf("unknown\n");
+ else
+ strm.Printf("0x%" PRIx64 "\n", *alloc->context.get());
+
+ strm.Indent("Address: ");
+ if (!alloc->address.isValid())
+ strm.Printf("unknown\n");
+ else
+ strm.Printf("0x%" PRIx64 "\n", *alloc->address.get());
+
+ strm.Indent("Data pointer: ");
+ if (!alloc->data_ptr.isValid())
+ strm.Printf("unknown\n");
+ else
+ strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get());
+
+ strm.Indent("Dimensions: ");
+ if (!alloc->dimension.isValid())
+ strm.Printf("unknown\n");
+ else
+ strm.Printf("(%d, %d, %d)\n", alloc->dimension.get()->dim_1,
+ alloc->dimension.get()->dim_2,
+ alloc->dimension.get()->dim_3);
+
+ strm.Indent("Data Type: ");
+ if (!alloc->element.type.isValid() || !alloc->element.type_vec_size.isValid())
+ strm.Printf("unknown\n");
+ else
+ {
+ const int vector_size = *alloc->element.type_vec_size.get();
+ Element::DataType type = *alloc->element.type.get();
+
+ if (!alloc->element.type_name.IsEmpty())
+ strm.Printf("%s\n", alloc->element.type_name.AsCString());
+ else
+ {
+ // Enum value isn't monotonous, so doesn't always index RsDataTypeToString array
+ if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT)
+ type = static_cast<Element::DataType>((type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1);
+
+ if (type >= (sizeof(AllocationDetails::RsDataTypeToString) / sizeof(AllocationDetails::RsDataTypeToString[0]))
+ || vector_size > 4 || vector_size < 1)
+ strm.Printf("invalid type\n");
+ else
+ strm.Printf("%s\n", AllocationDetails::RsDataTypeToString[static_cast<unsigned int>(type)][vector_size-1]);
}
}
+
+ strm.Indent("Data Kind: ");
+ if (!alloc->element.type_kind.isValid())
+ strm.Printf("unknown\n");
+ else
+ {
+ const Element::DataKind kind = *alloc->element.type_kind.get();
+ if (kind < Element::RS_KIND_USER || kind > Element::RS_KIND_PIXEL_YUV)
+ strm.Printf("invalid kind\n");
+ else
+ strm.Printf("%s\n", AllocationDetails::RsDataKindToString[static_cast<unsigned int>(kind)]);
+ }
+
+ strm.EOL();
+ strm.IndentLess();
}
+ strm.IndentLess();
+}
- if (!kernels_found)
+// Set breakpoints on every kernel found in RS module
+void
+RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp)
+{
+ for (const auto &kernel : rsmodule_sp->m_kernels)
{
- error.SetErrorString("kernel name not found");
+ // Don't set breakpoint on 'root' kernel
+ if (strcmp(kernel.m_name.AsCString(), "root") == 0)
+ continue;
+
+ CreateKernelBreakpoint(kernel.m_name);
}
- return;
+}
+
+// Method is internally called by the 'kernel breakpoint all' command to
+// enable or disable breaking on all kernels.
+//
+// When do_break is true we want to enable this functionality.
+// When do_break is false we want to disable it.
+void
+RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target)
+{
+ Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
+
+ InitSearchFilter(target);
+
+ // Set breakpoints on all the kernels
+ if (do_break && !m_breakAllKernels)
+ {
+ m_breakAllKernels = true;
+
+ for (const auto &module : m_rsmodules)
+ BreakOnModuleKernels(module);
+
+ if (log)
+ log->Printf("RenderScriptRuntime::SetBreakAllKernels(True)"
+ "- breakpoints set on all currently loaded kernels");
+ }
+ else if (!do_break && m_breakAllKernels) // Breakpoints won't be set on any new kernels.
+ {
+ m_breakAllKernels = false;
+
+ if (log)
+ log->Printf("RenderScriptRuntime::SetBreakAllKernels(False) - breakpoints no longer automatically set");
+ }
+}
+
+// Given the name of a kernel this function creates a breakpoint using our
+// own breakpoint resolver, and returns the Breakpoint shared pointer.
+BreakpointSP
+RenderScriptRuntime::CreateKernelBreakpoint(const ConstString& name)
+{
+ Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
+
+ if (!m_filtersp)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::CreateKernelBreakpoint - Error: No breakpoint search filter set");
+ return nullptr;
+ }
+
+ BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name));
+ BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(m_filtersp, resolver_sp, false, false, false);
+
+ // Give RS breakpoints a specific name, so the user can manipulate them as a group.
+ Error err;
+ if (!bp->AddName("RenderScriptKernel", err) && log)
+ log->Printf("RenderScriptRuntime::CreateKernelBreakpoint: Error setting break name, %s", err.AsCString());
+
+ return bp;
+}
+
+// Given an expression for a variable this function tries to calculate the variable's value.
+// If this is possible it returns true and sets the uint64_t parameter to the variables unsigned value.
+// Otherwise function returns false.
+bool
+RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp, const char* var_name, uint64_t& val)
+{
+ Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
+ Error error;
+ VariableSP var_sp;
+
+ // Find variable in stack frame
+ ValueObjectSP value_sp(frame_sp->GetValueForVariableExpressionPath(var_name,
+ eNoDynamicValues,
+ StackFrame::eExpressionPathOptionCheckPtrVsMember |
+ StackFrame::eExpressionPathOptionsAllowDirectIVarAccess,
+ var_sp,
+ error));
+ if (!error.Success())
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetFrameVarAsUnsigned - Error, couldn't find '%s' in frame", var_name);
+
+ return false;
+ }
+
+ // Find the unsigned int value for the variable
+ bool success = false;
+ val = value_sp->GetValueAsUnsigned(0, &success);
+ if (!success)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::GetFrameVarAsUnsigned - Error, couldn't parse '%s' as an unsigned int", var_name);
+
+ return false;
+ }
+
+ return true;
+}
+
+// Callback when a kernel breakpoint hits and we're looking for a specific coordinate.
+// Baton parameter contains a pointer to the target coordinate we want to break on.
+// Function then checks the .expand frame for the current coordinate and breaks to user if it matches.
+// Parameter 'break_id' is the id of the Breakpoint which made the callback.
+// Parameter 'break_loc_id' is the id for the BreakpointLocation which was hit,
+// a single logical breakpoint can have multiple addresses.
+bool
+RenderScriptRuntime::KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx,
+ user_id_t break_id, user_id_t break_loc_id)
+{
+ Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
+
+ assert(baton && "Error: null baton in conditional kernel breakpoint callback");
+
+ // Coordinate we want to stop on
+ const int* target_coord = static_cast<const int*>(baton);
+
+ if (log)
+ log->Printf("RenderScriptRuntime::KernelBreakpointHit - Break ID %" PRIu64 ", target coord (%d, %d, %d)",
+ break_id, target_coord[0], target_coord[1], target_coord[2]);
+
+ // Go up one stack frame to .expand kernel
+ ExecutionContext context(ctx->exe_ctx_ref);
+ ThreadSP thread_sp = context.GetThreadSP();
+ if (!thread_sp->SetSelectedFrameByIndex(1))
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::KernelBreakpointHit - Error, couldn't go up stack frame");
+
+ return false;
+ }
+
+ StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
+ if (!frame_sp)
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::KernelBreakpointHit - Error, couldn't select .expand stack frame");
+
+ return false;
+ }
+
+ // Get values for variables in .expand frame that tell us the current kernel invocation
+ const char* coord_expressions[] = {"rsIndex", "p->current.y", "p->current.z"};
+ uint64_t current_coord[3] = {0, 0, 0};
+
+ for(int i = 0; i < 3; ++i)
+ {
+ if (!GetFrameVarAsUnsigned(frame_sp, coord_expressions[i], current_coord[i]))
+ return false;
+
+ if (log)
+ log->Printf("RenderScriptRuntime::KernelBreakpointHit, %s = %" PRIu64, coord_expressions[i], current_coord[i]);
+ }
+
+ // Check if the current kernel invocation coordinate matches our target coordinate
+ if (current_coord[0] == static_cast<uint64_t>(target_coord[0]) &&
+ current_coord[1] == static_cast<uint64_t>(target_coord[1]) &&
+ current_coord[2] == static_cast<uint64_t>(target_coord[2]))
+ {
+ if (log)
+ log->Printf("RenderScriptRuntime::KernelBreakpointHit, BREAKING %" PRIu64 ", %" PRIu64 ", %" PRIu64,
+ current_coord[0], current_coord[1], current_coord[2]);
+
+ BreakpointSP breakpoint_sp = context.GetTargetPtr()->GetBreakpointByID(break_id);
+ assert(breakpoint_sp != nullptr && "Error: Couldn't find breakpoint matching break id for callback");
+ breakpoint_sp->SetEnabled(false); // Optimise since conditional breakpoint should only be hit once.
+ return true;
+ }
+
+ // No match on coordinate
+ return false;
+}
+
+// Tries to set a breakpoint on the start of a kernel, resolved using the kernel name.
+// Argument 'coords', represents a three dimensional coordinate which can be used to specify
+// a single kernel instance to break on. If this is set then we add a callback to the breakpoint.
+void
+RenderScriptRuntime::PlaceBreakpointOnKernel(Stream &strm, const char* name, const std::array<int,3> coords,
+ Error& error, TargetSP target)
+{
+ if (!name)
+ {
+ error.SetErrorString("invalid kernel name");
+ return;
+ }
+
+ InitSearchFilter(target);
+
+ ConstString kernel_name(name);
+ BreakpointSP bp = CreateKernelBreakpoint(kernel_name);
+
+ // We have a conditional breakpoint on a specific coordinate
+ if (coords[0] != -1)
+ {
+ strm.Printf("Conditional kernel breakpoint on coordinate %d, %d, %d", coords[0], coords[1], coords[2]);
+ strm.EOL();
+
+ // Allocate memory for the baton, and copy over coordinate
+ int* baton = new int[3];
+ baton[0] = coords[0]; baton[1] = coords[1]; baton[2] = coords[2];
+
+ // Create a callback that will be invoked everytime the breakpoint is hit.
+ // The baton object passed to the handler is the target coordinate we want to break on.
+ bp->SetCallback(KernelBreakpointHit, baton, true);
+
+ // Store a shared pointer to the baton, so the memory will eventually be cleaned up after destruction
+ m_conditional_breaks[bp->GetID()] = std::shared_ptr<int>(baton);
+ }
+
+ if (bp)
+ bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);
}
void
@@ -845,12 +3049,49 @@ RenderScriptRuntime::DumpModules(Stream &strm) const
strm.IndentLess();
}
+RenderScriptRuntime::ScriptDetails*
+RenderScriptRuntime::LookUpScript(addr_t address, bool create)
+{
+ for (const auto & s : m_scripts)
+ {
+ if (s->script.isValid())
+ if (*s->script == address)
+ return s.get();
+ }
+ if (create)
+ {
+ std::unique_ptr<ScriptDetails> s(new ScriptDetails);
+ s->script = address;
+ m_scripts.push_back(std::move(s));
+ return m_scripts.back().get();
+ }
+ return nullptr;
+}
+
+RenderScriptRuntime::AllocationDetails*
+RenderScriptRuntime::LookUpAllocation(addr_t address, bool create)
+{
+ for (const auto & a : m_allocations)
+ {
+ if (a->address.isValid())
+ if (*a->address == address)
+ return a.get();
+ }
+ if (create)
+ {
+ std::unique_ptr<AllocationDetails> a(new AllocationDetails);
+ a->address = address;
+ m_allocations.push_back(std::move(a));
+ return m_allocations.back().get();
+ }
+ return nullptr;
+}
+
void
RSModuleDescriptor::Dump(Stream &strm) const
{
strm.Indent();
m_module->GetFileSpec().Dump(&strm);
- m_module->ParseAllDebugSymbols();
if(m_module->GetNumCompileUnits())
{
strm.Indent("Debug info loaded.");
@@ -931,8 +3172,7 @@ RSKernelDescriptor::Dump(Stream &strm) const
class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed
{
- private:
- public:
+public:
CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "renderscript module probe",
"Initiates a Probe of all loaded modules for kernels and other renderscript objects.",
@@ -941,10 +3181,10 @@ class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed
{
}
- ~CommandObjectRenderScriptRuntimeModuleProbe() {}
+ ~CommandObjectRenderScriptRuntimeModuleProbe() override = default;
bool
- DoExecute(Args &command, CommandReturnObject &result)
+ DoExecute(Args &command, CommandReturnObject &result) override
{
const size_t argc = command.GetArgumentCount();
if (argc == 0)
@@ -970,8 +3210,7 @@ class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed
class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed
{
- private:
- public:
+public:
CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "renderscript module dump",
"Dumps renderscript specific information for all modules.", "renderscript module dump",
@@ -979,10 +3218,10 @@ class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed
{
}
- ~CommandObjectRenderScriptRuntimeModuleDump() {}
+ ~CommandObjectRenderScriptRuntimeModuleDump() override = default;
bool
- DoExecute(Args &command, CommandReturnObject &result)
+ DoExecute(Args &command, CommandReturnObject &result) override
{
RenderScriptRuntime *runtime =
(RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
@@ -994,8 +3233,7 @@ class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed
class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword
{
- private:
- public:
+public:
CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
: CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.",
NULL)
@@ -1004,13 +3242,12 @@ class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword
LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter)));
}
- ~CommandObjectRenderScriptRuntimeModule() {}
+ ~CommandObjectRenderScriptRuntimeModule() override = default;
};
class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed
{
- private:
- public:
+public:
CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "renderscript kernel list",
"Lists renderscript kernel names and associated script resources.", "renderscript kernel list",
@@ -1018,10 +3255,10 @@ class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed
{
}
- ~CommandObjectRenderScriptRuntimeKernelList() {}
+ ~CommandObjectRenderScriptRuntimeKernelList() override = default;
bool
- DoExecute(Args &command, CommandReturnObject &result)
+ DoExecute(Args &command, CommandReturnObject &result) override
{
RenderScriptRuntime *runtime =
(RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
@@ -1031,52 +3268,213 @@ class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed
}
};
-class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectParsed
+class CommandObjectRenderScriptRuntimeKernelBreakpointSet : public CommandObjectParsed
{
- private:
- public:
- CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter)
- : CommandObjectParsed(interpreter, "renderscript kernel breakpoint",
- "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint",
- eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
+public:
+ CommandObjectRenderScriptRuntimeKernelBreakpointSet(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript kernel breakpoint set",
+ "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint set <kernel_name> [-c x,y,z]",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), m_options(interpreter)
{
}
- ~CommandObjectRenderScriptRuntimeKernelBreakpoint() {}
+ ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() override = default;
- bool
- DoExecute(Args &command, CommandReturnObject &result)
+ Options*
+ GetOptions() override
{
- const size_t argc = command.GetArgumentCount();
- if (argc == 1)
+ return &m_options;
+ }
+
+ class CommandOptions : public Options
+ {
+ public:
+ CommandOptions(CommandInterpreter &interpreter) : Options(interpreter)
{
- RenderScriptRuntime *runtime =
- (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
+ }
+
+ ~CommandOptions() override = default;
+ Error
+ SetOptionValue(uint32_t option_idx, const char *option_arg) override
+ {
Error error;
- runtime->AttemptBreakpointAtKernelName(result.GetOutputStream(), command.GetArgumentAtIndex(0), error);
+ const int short_option = m_getopt_table[option_idx].val;
- if (error.Success())
+ switch (short_option)
{
- result.AppendMessage("Breakpoint(s) created");
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return true;
+ case 'c':
+ if (!ParseCoordinate(option_arg))
+ error.SetErrorStringWithFormat("Couldn't parse coordinate '%s', should be in format 'x,y,z'.", option_arg);
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
+ break;
}
+ return error;
+ }
+
+ // -c takes an argument of the form 'num[,num][,num]'.
+ // Where 'id_cstr' is this argument with the whitespace trimmed.
+ // Missing coordinates are defaulted to zero.
+ bool
+ ParseCoordinate(const char* id_cstr)
+ {
+ RegularExpression regex;
+ RegularExpression::Match regex_match(3);
+
+ bool matched = false;
+ if(regex.Compile("^([0-9]+),([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, &regex_match))
+ matched = true;
+ else if(regex.Compile("^([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, &regex_match))
+ matched = true;
+ else if(regex.Compile("^([0-9]+)$") && regex.Execute(id_cstr, &regex_match))
+ matched = true;
+ for(uint32_t i = 0; i < 3; i++)
+ {
+ std::string group;
+ if(regex_match.GetMatchAtIndex(id_cstr, i + 1, group))
+ m_coord[i] = (uint32_t)strtoul(group.c_str(), NULL, 0);
+ else
+ m_coord[i] = 0;
+ }
+ return matched;
+ }
+
+ void
+ OptionParsingStarting() override
+ {
+ // -1 means the -c option hasn't been set
+ m_coord[0] = -1;
+ m_coord[1] = -1;
+ m_coord[2] = -1;
+ }
+
+ const OptionDefinition*
+ GetDefinitions() override
+ {
+ return g_option_table;
+ }
+
+ static OptionDefinition g_option_table[];
+ std::array<int,3> m_coord;
+ };
+
+ bool
+ DoExecute(Args &command, CommandReturnObject &result) override
+ {
+ const size_t argc = command.GetArgumentCount();
+ if (argc < 1)
+ {
+ result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name, and an optional coordinate.", m_cmd_name.c_str());
result.SetStatus(eReturnStatusFailed);
- result.AppendErrorWithFormat("Error: %s", error.AsCString());
return false;
}
- result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name", m_cmd_name.c_str());
+ RenderScriptRuntime *runtime =
+ (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
+
+ Error error;
+ runtime->PlaceBreakpointOnKernel(result.GetOutputStream(), command.GetArgumentAtIndex(0), m_options.m_coord,
+ error, m_exe_ctx.GetTargetSP());
+
+ if (error.Success())
+ {
+ result.AppendMessage("Breakpoint(s) created");
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
result.SetStatus(eReturnStatusFailed);
+ result.AppendErrorWithFormat("Error: %s", error.AsCString());
return false;
}
+
+private:
+ CommandOptions m_options;
+};
+
+OptionDefinition
+CommandObjectRenderScriptRuntimeKernelBreakpointSet::CommandOptions::g_option_table[] =
+{
+ { LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeValue,
+ "Set a breakpoint on a single invocation of the kernel with specified coordinate.\n"
+ "Coordinate takes the form 'x[,y][,z] where x,y,z are positive integers representing kernel dimensions. "
+ "Any unset dimensions will be defaulted to zero."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+};
+
+class CommandObjectRenderScriptRuntimeKernelBreakpointAll : public CommandObjectParsed
+{
+public:
+ CommandObjectRenderScriptRuntimeKernelBreakpointAll(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript kernel breakpoint all",
+ "Automatically sets a breakpoint on all renderscript kernels that are or will be loaded.\n"
+ "Disabling option means breakpoints will no longer be set on any kernels loaded in the future, "
+ "but does not remove currently set breakpoints.",
+ "renderscript kernel breakpoint all <enable/disable>",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
+ {
+ }
+
+ ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() override = default;
+
+ bool
+ DoExecute(Args &command, CommandReturnObject &result) override
+ {
+ const size_t argc = command.GetArgumentCount();
+ if (argc != 1)
+ {
+ result.AppendErrorWithFormat("'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ RenderScriptRuntime *runtime =
+ static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
+
+ bool do_break = false;
+ const char* argument = command.GetArgumentAtIndex(0);
+ if (strcmp(argument, "enable") == 0)
+ {
+ do_break = true;
+ result.AppendMessage("Breakpoints will be set on all kernels.");
+ }
+ else if (strcmp(argument, "disable") == 0)
+ {
+ do_break = false;
+ result.AppendMessage("Breakpoints will not be set on any new kernels.");
+ }
+ else
+ {
+ result.AppendErrorWithFormat("Argument must be either 'enable' or 'disable'");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP());
+
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+};
+
+class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectMultiword
+{
+public:
+ CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that generate breakpoints on renderscript kernels.",
+ nullptr)
+ {
+ LoadSubCommand("set", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(interpreter)));
+ LoadSubCommand("all", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(interpreter)));
+ }
+
+ ~CommandObjectRenderScriptRuntimeKernelBreakpoint() override = default;
};
class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword
{
- private:
- public:
+public:
CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter)
: CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with renderscript kernels.",
NULL)
@@ -1085,13 +3483,12 @@ class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword
LoadSubCommand("breakpoint", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter)));
}
- ~CommandObjectRenderScriptRuntimeKernel() {}
+ ~CommandObjectRenderScriptRuntimeKernel() override = default;
};
class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed
{
- private:
- public:
+public:
CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "renderscript context dump",
"Dumps renderscript context information.", "renderscript context dump",
@@ -1099,10 +3496,10 @@ class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed
{
}
- ~CommandObjectRenderScriptRuntimeContextDump() {}
+ ~CommandObjectRenderScriptRuntimeContextDump() override = default;
bool
- DoExecute(Args &command, CommandReturnObject &result)
+ DoExecute(Args &command, CommandReturnObject &result) override
{
RenderScriptRuntime *runtime =
(RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
@@ -1114,8 +3511,7 @@ class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed
class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword
{
- private:
- public:
+public:
CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter)
: CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with renderscript contexts.",
NULL)
@@ -1123,13 +3519,345 @@ class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword
LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(interpreter)));
}
- ~CommandObjectRenderScriptRuntimeContext() {}
+ ~CommandObjectRenderScriptRuntimeContext() override = default;
+};
+
+class CommandObjectRenderScriptRuntimeAllocationDump : public CommandObjectParsed
+{
+public:
+ CommandObjectRenderScriptRuntimeAllocationDump(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript allocation dump",
+ "Displays the contents of a particular allocation", "renderscript allocation dump <ID>",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter)
+ {
+ }
+
+ ~CommandObjectRenderScriptRuntimeAllocationDump() override = default;
+
+ Options*
+ GetOptions() override
+ {
+ return &m_options;
+ }
+
+ class CommandOptions : public Options
+ {
+ public:
+ CommandOptions(CommandInterpreter &interpreter) : Options(interpreter)
+ {
+ }
+
+ ~CommandOptions() override = default;
+
+ Error
+ SetOptionValue(uint32_t option_idx, const char *option_arg) override
+ {
+ Error error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'f':
+ m_outfile.SetFile(option_arg, true);
+ if (m_outfile.Exists())
+ {
+ m_outfile.Clear();
+ error.SetErrorStringWithFormat("file already exists: '%s'", option_arg);
+ }
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
+ break;
+ }
+ return error;
+ }
+
+ void
+ OptionParsingStarting() override
+ {
+ m_outfile.Clear();
+ }
+
+ const OptionDefinition*
+ GetDefinitions() override
+ {
+ return g_option_table;
+ }
+
+ static OptionDefinition g_option_table[];
+ FileSpec m_outfile;
+ };
+
+ bool
+ DoExecute(Args &command, CommandReturnObject &result) override
+ {
+ const size_t argc = command.GetArgumentCount();
+ if (argc < 1)
+ {
+ result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. As well as an optional -f argument",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ RenderScriptRuntime *runtime =
+ static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
+
+ const char* id_cstr = command.GetArgumentAtIndex(0);
+ bool convert_complete = false;
+ const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
+ if (!convert_complete)
+ {
+ result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ Stream* output_strm = nullptr;
+ StreamFile outfile_stream;
+ const FileSpec &outfile_spec = m_options.m_outfile; // Dump allocation to file instead
+ if (outfile_spec)
+ {
+ // Open output file
+ char path[256];
+ outfile_spec.GetPath(path, sizeof(path));
+ if (outfile_stream.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success())
+ {
+ output_strm = &outfile_stream;
+ result.GetOutputStream().Printf("Results written to '%s'", path);
+ result.GetOutputStream().EOL();
+ }
+ else
+ {
+ result.AppendErrorWithFormat("Couldn't open file '%s'", path);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ output_strm = &result.GetOutputStream();
+
+ assert(output_strm != nullptr);
+ bool success = runtime->DumpAllocation(*output_strm, m_exe_ctx.GetFramePtr(), id);
+
+ if (success)
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
+
+ return true;
+ }
+
+private:
+ CommandOptions m_options;
+};
+
+OptionDefinition
+CommandObjectRenderScriptRuntimeAllocationDump::CommandOptions::g_option_table[] =
+{
+ { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename,
+ "Print results to specified file instead of command line."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+};
+
+class CommandObjectRenderScriptRuntimeAllocationList : public CommandObjectParsed
+{
+public:
+ CommandObjectRenderScriptRuntimeAllocationList(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript allocation list",
+ "List renderscript allocations and their information.", "renderscript allocation list",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter)
+ {
+ }
+
+ ~CommandObjectRenderScriptRuntimeAllocationList() override = default;
+
+ Options*
+ GetOptions() override
+ {
+ return &m_options;
+ }
+
+ class CommandOptions : public Options
+ {
+ public:
+ CommandOptions(CommandInterpreter &interpreter) : Options(interpreter), m_refresh(false)
+ {
+ }
+
+ ~CommandOptions() override = default;
+
+ Error
+ SetOptionValue(uint32_t option_idx, const char *option_arg) override
+ {
+ Error error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'r':
+ m_refresh = true;
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
+ break;
+ }
+ return error;
+ }
+
+ void
+ OptionParsingStarting() override
+ {
+ m_refresh = false;
+ }
+
+ const OptionDefinition*
+ GetDefinitions() override
+ {
+ return g_option_table;
+ }
+
+ static OptionDefinition g_option_table[];
+ bool m_refresh;
+ };
+
+ bool
+ DoExecute(Args &command, CommandReturnObject &result) override
+ {
+ RenderScriptRuntime *runtime =
+ static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
+ runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), m_options.m_refresh);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+
+private:
+ CommandOptions m_options;
+};
+
+OptionDefinition
+CommandObjectRenderScriptRuntimeAllocationList::CommandOptions::g_option_table[] =
+{
+ { LLDB_OPT_SET_1, false, "refresh", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
+ "Recompute allocation details."},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+};
+
+class CommandObjectRenderScriptRuntimeAllocationLoad : public CommandObjectParsed
+{
+public:
+ CommandObjectRenderScriptRuntimeAllocationLoad(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript allocation load",
+ "Loads renderscript allocation contents from a file.", "renderscript allocation load <ID> <filename>",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched)
+ {
+ }
+
+ ~CommandObjectRenderScriptRuntimeAllocationLoad() override = default;
+
+ bool
+ DoExecute(Args &command, CommandReturnObject &result) override
+ {
+ const size_t argc = command.GetArgumentCount();
+ if (argc != 2)
+ {
+ result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ RenderScriptRuntime *runtime =
+ static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
+
+ const char* id_cstr = command.GetArgumentAtIndex(0);
+ bool convert_complete = false;
+ const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
+ if (!convert_complete)
+ {
+ result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ const char* filename = command.GetArgumentAtIndex(1);
+ bool success = runtime->LoadAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr());
+
+ if (success)
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
+
+ return true;
+ }
+};
+
+class CommandObjectRenderScriptRuntimeAllocationSave : public CommandObjectParsed
+{
+public:
+ CommandObjectRenderScriptRuntimeAllocationSave(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "renderscript allocation save",
+ "Write renderscript allocation contents to a file.", "renderscript allocation save <ID> <filename>",
+ eCommandRequiresProcess | eCommandProcessMustBeLaunched)
+ {
+ }
+
+ ~CommandObjectRenderScriptRuntimeAllocationSave() override = default;
+
+ bool
+ DoExecute(Args &command, CommandReturnObject &result) override
+ {
+ const size_t argc = command.GetArgumentCount();
+ if (argc != 2)
+ {
+ result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ RenderScriptRuntime *runtime =
+ static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
+
+ const char* id_cstr = command.GetArgumentAtIndex(0);
+ bool convert_complete = false;
+ const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
+ if (!convert_complete)
+ {
+ result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ const char* filename = command.GetArgumentAtIndex(1);
+ bool success = runtime->SaveAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr());
+
+ if (success)
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ else
+ result.SetStatus(eReturnStatusFailed);
+
+ return true;
+ }
+};
+
+class CommandObjectRenderScriptRuntimeAllocation : public CommandObjectMultiword
+{
+public:
+ CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(interpreter, "renderscript allocation", "Commands that deal with renderscript allocations.",
+ NULL)
+ {
+ LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationList(interpreter)));
+ LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationDump(interpreter)));
+ LoadSubCommand("save", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationSave(interpreter)));
+ LoadSubCommand("load", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationLoad(interpreter)));
+ }
+
+ ~CommandObjectRenderScriptRuntimeAllocation() override = default;
};
class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed
{
- private:
- public:
+public:
CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "renderscript status",
"Displays current renderscript runtime status.", "renderscript status",
@@ -1137,10 +3865,10 @@ class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed
{
}
- ~CommandObjectRenderScriptRuntimeStatus() {}
+ ~CommandObjectRenderScriptRuntimeStatus() override = default;
bool
- DoExecute(Args &command, CommandReturnObject &result)
+ DoExecute(Args &command, CommandReturnObject &result) override
{
RenderScriptRuntime *runtime =
(RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
@@ -1152,7 +3880,7 @@ class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed
class CommandObjectRenderScriptRuntime : public CommandObjectMultiword
{
- public:
+public:
CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)
: CommandObjectMultiword(interpreter, "renderscript", "A set of commands for operating on renderscript.",
"renderscript <subcommand> [<subcommand-options>]")
@@ -1161,9 +3889,10 @@ class CommandObjectRenderScriptRuntime : public CommandObjectMultiword
LoadSubCommand("status", CommandObjectSP(new CommandObjectRenderScriptRuntimeStatus(interpreter)));
LoadSubCommand("kernel", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernel(interpreter)));
LoadSubCommand("context", CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(interpreter)));
+ LoadSubCommand("allocation", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocation(interpreter)));
}
- ~CommandObjectRenderScriptRuntime() {}
+ ~CommandObjectRenderScriptRuntime() override = default;
};
void
@@ -1173,7 +3902,8 @@ RenderScriptRuntime::Initiate()
}
RenderScriptRuntime::RenderScriptRuntime(Process *process)
- : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false)
+ : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false),
+ m_breakAllKernels(false)
{
ModulesDidLoad(process->GetTarget().GetImages());
}
@@ -1189,3 +3919,4 @@ RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter& interpre
return command_object;
}
+RenderScriptRuntime::~RenderScriptRuntime() = default;
diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
index 2a01e744e976..0ca268c93b00 100644
--- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
+++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
@@ -12,6 +12,12 @@
// C Includes
// C++ Includes
+#include <array>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
@@ -19,8 +25,8 @@
#include "lldb/Target/CPPLanguageRuntime.h"
#include "lldb/Core/Module.h"
-namespace lldb_private
-{
+namespace lldb_private {
+namespace lldb_renderscript {
typedef uint32_t RSSlot;
class RSModuleDescriptor;
@@ -31,11 +37,56 @@ typedef std::shared_ptr<RSModuleDescriptor> RSModuleDescriptorSP;
typedef std::shared_ptr<RSGlobalDescriptor> RSGlobalDescriptorSP;
typedef std::shared_ptr<RSKernelDescriptor> RSKernelDescriptorSP;
+// Breakpoint Resolvers decide where a breakpoint is placed,
+// so having our own allows us to limit the search scope to RS kernel modules.
+// As well as check for .expand kernels as a fallback.
+class RSBreakpointResolver : public BreakpointResolver
+{
+public:
+ RSBreakpointResolver(Breakpoint *bkpt, ConstString name):
+ BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
+ m_kernel_name(name)
+ {
+ }
+
+ void
+ GetDescription(Stream *strm) override
+ {
+ if (strm)
+ strm->Printf("RenderScript kernel breakpoint for '%s'", m_kernel_name.AsCString());
+ }
+
+ void
+ Dump(Stream *s) const override
+ {
+ }
+
+ Searcher::CallbackReturn
+ SearchCallback(SearchFilter &filter,
+ SymbolContext &context,
+ Address *addr,
+ bool containing) override;
+
+ Searcher::Depth
+ GetDepth() override
+ {
+ return Searcher::eDepthModule;
+ }
+
+ lldb::BreakpointResolverSP
+ CopyForBreakpoint(Breakpoint &breakpoint) override
+ {
+ lldb::BreakpointResolverSP ret_sp(new RSBreakpointResolver(&breakpoint, m_kernel_name));
+ return ret_sp;
+ }
+protected:
+ ConstString m_kernel_name;
+};
struct RSKernelDescriptor
{
- public:
+public:
RSKernelDescriptor(const RSModuleDescriptor *module, const char *name, uint32_t slot)
: m_module(module)
, m_name(name)
@@ -52,7 +103,7 @@ struct RSKernelDescriptor
struct RSGlobalDescriptor
{
- public:
+public:
RSGlobalDescriptor(const RSModuleDescriptor *module, const char *name )
: m_module(module)
, m_name(name)
@@ -67,13 +118,13 @@ struct RSGlobalDescriptor
class RSModuleDescriptor
{
- public:
+public:
RSModuleDescriptor(const lldb::ModuleSP &module)
: m_module(module)
{
}
- ~RSModuleDescriptor() {}
+ ~RSModuleDescriptor() = default;
bool ParseRSInfo();
@@ -86,10 +137,11 @@ class RSModuleDescriptor
std::string m_resname;
};
+} // namespace lldb_renderscript
+
class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
{
- public:
-
+public:
enum ModuleKind
{
eModuleKindIgnored,
@@ -99,8 +151,7 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
eModuleKindKernelObj
};
-
- ~RenderScriptRuntime() {}
+ ~RenderScriptRuntime() override;
//------------------------------------------------------------------
// Static Functions
@@ -121,21 +172,19 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
static void ModulesDidLoad(const lldb::ProcessSP& process_sp, const ModuleList &module_list );
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- virtual lldb_private::ConstString GetPluginName();
-
- virtual uint32_t GetPluginVersion();
+ bool IsVTableName(const char *name) override;
- virtual bool IsVTableName(const char *name);
-
- virtual bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name, Address &address);
+ bool GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
+ TypeAndOrName &class_type_or_name, Address &address,
+ Value::ValueType &value_type) override;
+
+ TypeAndOrName
+ FixUpDynamicType(const TypeAndOrName& type_and_or_name,
+ ValueObject& static_value) override;
- virtual bool CouldHaveDynamicValue(ValueObject &in_value);
+ bool CouldHaveDynamicValue(ValueObject &in_value) override;
- virtual lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp);
+ lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override;
bool LoadModule(const lldb::ModuleSP &module_sp);
@@ -147,25 +196,60 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
void DumpKernels(Stream &strm) const;
- void AttemptBreakpointAtKernelName(Stream &strm, const char *name, Error &error);
+ bool DumpAllocation(Stream &strm, StackFrame* frame_ptr, const uint32_t id);
+
+ void ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute);
+
+ void PlaceBreakpointOnKernel(Stream &strm, const char *name, const std::array<int,3> coords,
+ Error &error, lldb::TargetSP target);
+
+ void SetBreakAllKernels(bool do_break, lldb::TargetSP target);
void Status(Stream &strm) const;
- virtual size_t GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates) {
+ size_t GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates) override {
return static_cast<size_t>(0);
}
- virtual void ModulesDidLoad(const ModuleList &module_list );
+ void ModulesDidLoad(const ModuleList &module_list) override;
+
+ bool LoadAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr);
+
+ bool SaveAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr);
void Update();
void Initiate();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+
+protected:
+ struct ScriptDetails;
+ struct AllocationDetails;
+ struct Element;
+
+ void InitSearchFilter(lldb::TargetSP target)
+ {
+ if (!m_filtersp)
+ m_filtersp.reset(new SearchFilterForUnconstrainedSearches(target));
+ }
- protected:
-
- void FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp);
+ void FixupScriptDetails(lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
void LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind);
+
+ bool RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr);
+
+ bool EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result);
+
+ lldb::BreakpointSP CreateKernelBreakpoint(const ConstString& name);
+
+ void BreakOnModuleKernels(const lldb_renderscript::RSModuleDescriptorSP rsmodule_sp);
struct RuntimeHook;
typedef void (RenderScriptRuntime::*CaptureStateFn)(RuntimeHook* hook_info, ExecutionContext &context); // Please do this!
@@ -173,7 +257,8 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
struct HookDefn
{
const char * name;
- const char * symbol_name;
+ const char * symbol_name_m32; // mangled name for the 32 bit architectures
+ const char * symbol_name_m64; // mangled name for the 64 bit archs
uint32_t version;
ModuleKind kind;
CaptureStateFn grabber;
@@ -185,46 +270,102 @@ class RenderScriptRuntime : public lldb_private::CPPLanguageRuntime
const HookDefn *defn;
lldb::BreakpointSP bp_sp;
};
-
- typedef std::shared_ptr<RuntimeHook> RuntimeHookSP;
- struct ScriptDetails
- {
- std::string resname;
- std::string scriptDyLib;
- std::string cachedir;
- lldb::addr_t context;
- lldb::addr_t script;
- };
+ typedef std::shared_ptr<RuntimeHook> RuntimeHookSP;
lldb::ModuleSP m_libRS;
lldb::ModuleSP m_libRSDriver;
lldb::ModuleSP m_libRSCpuRef;
- std::vector<RSModuleDescriptorSP> m_rsmodules;
- std::vector<ScriptDetails> m_scripts;
+ std::vector<lldb_renderscript::RSModuleDescriptorSP> m_rsmodules;
+
+ std::vector<std::unique_ptr<ScriptDetails>> m_scripts;
+ std::vector<std::unique_ptr<AllocationDetails>> m_allocations;
- std::map<lldb::addr_t, RSModuleDescriptorSP> m_scriptMappings;
+ std::map<lldb::addr_t, lldb_renderscript::RSModuleDescriptorSP> m_scriptMappings;
std::map<lldb::addr_t, RuntimeHookSP> m_runtimeHooks;
+ std::map<lldb::user_id_t, std::shared_ptr<int>> m_conditional_breaks;
+
+ lldb::SearchFilterSP m_filtersp; // Needed to create breakpoints through Target API
bool m_initiated;
bool m_debuggerPresentFlagged;
+ bool m_breakAllKernels;
static const HookDefn s_runtimeHookDefns[];
static const size_t s_runtimeHookCount;
- private:
+private:
+ // Used to index expression format strings
+ enum ExpressionStrings
+ {
+ eExprGetOffsetPtr = 0,
+ eExprAllocGetType,
+ eExprTypeDimX,
+ eExprTypeDimY,
+ eExprTypeDimZ,
+ eExprTypeElemPtr,
+ eExprElementType,
+ eExprElementKind,
+ eExprElementVec,
+ eExprElementFieldCount,
+ eExprSubelementsId,
+ eExprSubelementsName,
+ eExprSubelementsArrSize
+ };
+
RenderScriptRuntime(Process *process); // Call CreateInstance instead.
static bool HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id,
lldb::user_id_t break_loc_id);
+ static bool KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx,
+ lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
+
void HookCallback(RuntimeHook* hook_info, ExecutionContext& context);
- bool GetArg32Simple(ExecutionContext& context, uint32_t arg, uint32_t *data);
+ bool GetArgSimple(ExecutionContext& context, uint32_t arg, uint64_t* data);
void CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext& context);
void CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context);
+ void CaptureAllocationDestroy(RuntimeHook* hook_info, ExecutionContext& context);
void CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context);
+ AllocationDetails* FindAllocByID(Stream &strm, const uint32_t alloc_id);
+ std::shared_ptr<uint8_t> GetAllocationData(AllocationDetails* allocation, StackFrame* frame_ptr);
+ void SetElementSize(Element& elem);
+ static bool GetFrameVarAsUnsigned(const lldb::StackFrameSP, const char* var_name, uint64_t& val);
+ void FindStructTypeName(Element& elem, StackFrame* frame_ptr);
+
+ //
+ // Helper functions for jitting the runtime
+ //
+ const char* JITTemplate(ExpressionStrings e);
+
+ bool JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr,
+ unsigned int x = 0, unsigned int y = 0, unsigned int z = 0);
+
+ bool JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr);
+
+ bool JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr);
+
+ bool JITElementPacked(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr);
+
+ bool JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr);
+
+ bool JITSubelements(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr);
+
+ bool JITAllocationStride(AllocationDetails* allocation, StackFrame* frame_ptr);
+
+ // Search for a script detail object using a target address.
+ // If a script does not currently exist this function will return nullptr.
+ // If 'create' is true and there is no previous script with this address,
+ // then a new Script detail object will be created for this address and returned.
+ ScriptDetails* LookUpScript(lldb::addr_t address, bool create);
+
+ // Search for a previously saved allocation detail object using a target address.
+ // If an allocation does not exist for this address then nullptr will be returned.
+ // If 'create' is true and there is no previous allocation then a new allocation
+ // detail object will be created for this address and returned.
+ AllocationDetails* LookUpAllocation(lldb::addr_t address, bool create);
};
} // namespace lldb_private
diff --git a/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
index c7c64ed54d87..c57519871624 100644
--- a/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
+++ b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp
@@ -30,36 +30,25 @@ MemoryHistoryASan::CreateInstance (const ProcessSP &process_sp)
{
if (!process_sp.get())
return NULL;
-
+
Target & target = process_sp->GetTarget();
-
- bool found_asan_runtime = false;
-
+
const ModuleList &target_modules = target.GetImages();
Mutex::Locker modules_locker(target_modules.GetMutex());
const size_t num_modules = target_modules.GetSize();
for (size_t i = 0; i < num_modules; ++i)
{
Module *module_pointer = target_modules.GetModulePointerAtIndexUnlocked(i);
-
- SymbolContextList sc_list;
- const bool include_symbols = true;
- const bool append = true;
- const bool include_inlines = true;
- size_t num_matches = module_pointer->FindFunctions(ConstString("__asan_get_alloc_stack"), NULL, eFunctionNameTypeAuto, include_symbols, include_inlines, append, sc_list);
-
- if (num_matches)
- {
- found_asan_runtime = true;
- break;
- }
+ const Symbol* symbol = module_pointer->FindFirstSymbolWithNameAndType(
+ ConstString("__asan_get_alloc_stack"),
+ lldb::eSymbolTypeAny);
+
+ if (symbol != nullptr)
+ return MemoryHistorySP(new MemoryHistoryASan(process_sp));
}
-
- if (! found_asan_runtime)
- return MemoryHistorySP();
- return MemoryHistorySP(new MemoryHistoryASan(process_sp));
+ return MemoryHistorySP();
}
void
@@ -86,7 +75,8 @@ MemoryHistoryASan::GetPluginNameStatic()
MemoryHistoryASan::MemoryHistoryASan(const ProcessSP &process_sp)
{
- this->m_process_sp = process_sp;
+ if (process_sp)
+ m_process_wp = process_sp;
}
const char *
@@ -112,14 +102,23 @@ static void CreateHistoryThreadFromValueObject(ProcessSP process_sp, ValueObject
std::string count_path = "." + std::string(type) + "_count";
std::string tid_path = "." + std::string(type) + "_tid";
std::string trace_path = "." + std::string(type) + "_trace";
+
+ ValueObjectSP count_sp = return_value_sp->GetValueForExpressionPath(count_path.c_str());
+ ValueObjectSP tid_sp = return_value_sp->GetValueForExpressionPath(tid_path.c_str());
+
+ if (!count_sp || !tid_sp)
+ return;
- int count = return_value_sp->GetValueForExpressionPath(count_path.c_str())->GetValueAsUnsigned(0);
- tid_t tid = return_value_sp->GetValueForExpressionPath(tid_path.c_str())->GetValueAsUnsigned(0);
+ int count = count_sp->GetValueAsUnsigned(0);
+ tid_t tid = tid_sp->GetValueAsUnsigned(0);
if (count <= 0)
return;
ValueObjectSP trace_sp = return_value_sp->GetValueForExpressionPath(trace_path.c_str());
+
+ if (!trace_sp)
+ return;
std::vector<lldb::addr_t> pcs;
for (int i = 0; i < count; i++)
@@ -144,40 +143,41 @@ static void CreateHistoryThreadFromValueObject(ProcessSP process_sp, ValueObject
HistoryThreads
MemoryHistoryASan::GetHistoryThreads(lldb::addr_t address)
{
- ProcessSP process_sp = m_process_sp;
- ThreadSP thread_sp = m_process_sp->GetThreadList().GetSelectedThread();
- StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
+ HistoryThreads result;
- if (!frame_sp)
+ ProcessSP process_sp = m_process_wp.lock();
+ if (process_sp)
{
- return HistoryThreads();
- }
+ ThreadSP thread_sp = process_sp->GetThreadList().GetSelectedThread();
- ExecutionContext exe_ctx (frame_sp);
- ValueObjectSP return_value_sp;
- StreamString expr;
- expr.Printf(memory_history_asan_command_format, address, address);
-
- EvaluateExpressionOptions options;
- options.SetUnwindOnError(true);
- options.SetTryAllThreads(true);
- options.SetStopOthers(true);
- options.SetIgnoreBreakpoints(true);
- options.SetTimeoutUsec(GET_STACK_FUNCTION_TIMEOUT_USEC);
-
- if (m_process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), return_value_sp, options) != eExpressionCompleted)
- {
- return HistoryThreads();
- }
- if (!return_value_sp)
- {
- return HistoryThreads();
+ if (thread_sp)
+ {
+ StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
+
+ if (frame_sp)
+ {
+ ExecutionContext exe_ctx (frame_sp);
+ ValueObjectSP return_value_sp;
+ StreamString expr;
+ expr.Printf(memory_history_asan_command_format, address, address);
+
+ EvaluateExpressionOptions options;
+ options.SetUnwindOnError(true);
+ options.SetTryAllThreads(true);
+ options.SetStopOthers(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetTimeoutUsec(GET_STACK_FUNCTION_TIMEOUT_USEC);
+
+ if (process_sp->GetTarget().EvaluateExpression(expr.GetData(), frame_sp.get(), return_value_sp, options) == eExpressionCompleted)
+ {
+ if (return_value_sp)
+ {
+ CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "free", "Memory deallocated at", result);
+ CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "alloc", "Memory allocated at", result);
+ }
+ }
+ }
+ }
}
-
- HistoryThreads result;
-
- CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "alloc", "Memory allocated at", result);
- CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "free", "Memory deallocated at", result);
-
return result;
}
diff --git a/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h
index 5307e0b34081..b38f95ed744e 100644
--- a/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h
+++ b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h
@@ -1,4 +1,4 @@
-//===-- MemoryHistoryASan.h ----------------------------------------*- C++ -*-===//
+//===-- MemoryHistoryASan.h -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -24,7 +24,8 @@ namespace lldb_private {
class MemoryHistoryASan : public lldb_private::MemoryHistory
{
public:
-
+ ~MemoryHistoryASan() override = default;
+
static lldb::MemoryHistorySP
CreateInstance (const lldb::ProcessSP &process_sp);
@@ -36,27 +37,28 @@ public:
static lldb_private::ConstString
GetPluginNameStatic();
+
+ lldb_private::ConstString
+ GetPluginName() override
+ {
+ return GetPluginNameStatic();
+ }
- virtual
- ~MemoryHistoryASan () {}
-
- virtual lldb_private::ConstString
- GetPluginName() { return GetPluginNameStatic(); }
-
- virtual uint32_t
- GetPluginVersion() { return 1; }
+ uint32_t
+ GetPluginVersion() override
+ {
+ return 1;
+ }
- virtual lldb_private::HistoryThreads
- GetHistoryThreads(lldb::addr_t address);
+ lldb_private::HistoryThreads
+ GetHistoryThreads(lldb::addr_t address) override;
private:
-
MemoryHistoryASan(const lldb::ProcessSP &process_sp);
- lldb::ProcessSP m_process_sp;
-
+ lldb::ProcessWP m_process_wp;
};
} // namespace lldb_private
-#endif // liblldb_MemoryHistoryASan_h_
+#endif // liblldb_MemoryHistoryASan_h_
diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
index 8209d23c0aee..f2a74b05fe26 100644
--- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
+++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
@@ -103,9 +103,13 @@ ObjectContainerBSDArchive::Object::Extract (const DataExtractor& data, lldb::off
}
else
{
- // Strip off any spaces (if the object file name contains spaces it
- // will use the extended format above).
- str.erase (str.find(' '));
+ // Strip off any trailing spaces.
+ const size_t last_pos = str.find_last_not_of(' ');
+ if (last_pos != std::string::npos)
+ {
+ if (last_pos + 1 < 16)
+ str.erase (last_pos + 1);
+ }
ar_name.SetCString(str.c_str());
}
diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
index 8093c580ff97..cbb3848dc7cd 100644
--- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
+++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
@@ -10,8 +10,11 @@
#ifndef liblldb_ObjectContainerBSDArchive_h_
#define liblldb_ObjectContainerBSDArchive_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Symbol/ObjectContainer.h"
-
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Host/FileSpec.h"
@@ -22,6 +25,14 @@ class ObjectContainerBSDArchive :
public lldb_private::ObjectContainer
{
public:
+ ObjectContainerBSDArchive(const lldb::ModuleSP &module_sp,
+ lldb::DataBufferSP& data_sp,
+ lldb::offset_t data_offset,
+ const lldb_private::FileSpec *file,
+ lldb::offset_t offset,
+ lldb::offset_t length);
+
+ ~ObjectContainerBSDArchive() override;
//------------------------------------------------------------------
// Static Functions
@@ -60,43 +71,33 @@ public:
//------------------------------------------------------------------
// Member Functions
//------------------------------------------------------------------
- ObjectContainerBSDArchive (const lldb::ModuleSP &module_sp,
- lldb::DataBufferSP& data_sp,
- lldb::offset_t data_offset,
- const lldb_private::FileSpec *file,
- lldb::offset_t offset,
- lldb::offset_t length);
-
- virtual
- ~ObjectContainerBSDArchive();
+ bool
+ ParseHeader() override;
- virtual bool
- ParseHeader ();
-
- virtual size_t
- GetNumObjects () const
+ size_t
+ GetNumObjects() const override
{
if (m_archive_sp)
return m_archive_sp->GetNumObjects();
return 0;
}
- virtual void
- Dump (lldb_private::Stream *s) const;
- virtual lldb::ObjectFileSP
- GetObjectFile (const lldb_private::FileSpec *file);
+ void
+ Dump(lldb_private::Stream *s) const override;
+
+ lldb::ObjectFileSP
+ GetObjectFile(const lldb_private::FileSpec *file) override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
protected:
-
struct Object
{
Object();
@@ -127,6 +128,13 @@ protected:
typedef std::shared_ptr<Archive> shared_ptr;
typedef std::multimap<lldb_private::FileSpec, shared_ptr> Map;
+ Archive(const lldb_private::ArchSpec &arch,
+ const lldb_private::TimeValue &mod_time,
+ lldb::offset_t file_offset,
+ lldb_private::DataExtractor &data);
+
+ ~Archive();
+
static Map &
GetArchiveCache ();
@@ -146,13 +154,6 @@ protected:
lldb::offset_t file_offset,
lldb_private::DataExtractor &data);
- Archive (const lldb_private::ArchSpec &arch,
- const lldb_private::TimeValue &mod_time,
- lldb::offset_t file_offset,
- lldb_private::DataExtractor &data);
-
- ~Archive ();
-
size_t
GetNumObjects () const
{
@@ -226,4 +227,4 @@ protected:
Archive::shared_ptr m_archive_sp;
};
-#endif // liblldb_ObjectContainerBSDArchive_h_
+#endif // liblldb_ObjectContainerBSDArchive_h_
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 789fd4913301..44fe6615a361 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -11,6 +11,7 @@
#include <cassert>
#include <algorithm>
+#include <unordered_map>
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/DataBuffer.h"
@@ -48,6 +49,8 @@ const char *const LLDB_NT_OWNER_GNU = "GNU";
const char *const LLDB_NT_OWNER_NETBSD = "NetBSD";
const char *const LLDB_NT_OWNER_CSR = "csr";
const char *const LLDB_NT_OWNER_ANDROID = "Android";
+const char *const LLDB_NT_OWNER_CORE = "CORE";
+const char *const LLDB_NT_OWNER_LINUX = "LINUX";
// ELF note type definitions
const elf_word LLDB_NT_FREEBSD_ABI_TAG = 0x01;
@@ -66,6 +69,41 @@ const elf_word LLDB_NT_GNU_ABI_OS_LINUX = 0x00;
const elf_word LLDB_NT_GNU_ABI_OS_HURD = 0x01;
const elf_word LLDB_NT_GNU_ABI_OS_SOLARIS = 0x02;
+// LLDB_NT_OWNER_CORE and LLDB_NT_OWNER_LINUX note contants
+#define NT_PRSTATUS 1
+#define NT_PRFPREG 2
+#define NT_PRPSINFO 3
+#define NT_TASKSTRUCT 4
+#define NT_AUXV 6
+#define NT_SIGINFO 0x53494749
+#define NT_FILE 0x46494c45
+#define NT_PRXFPREG 0x46e62b7f
+#define NT_PPC_VMX 0x100
+#define NT_PPC_SPE 0x101
+#define NT_PPC_VSX 0x102
+#define NT_386_TLS 0x200
+#define NT_386_IOPERM 0x201
+#define NT_X86_XSTATE 0x202
+#define NT_S390_HIGH_GPRS 0x300
+#define NT_S390_TIMER 0x301
+#define NT_S390_TODCMP 0x302
+#define NT_S390_TODPREG 0x303
+#define NT_S390_CTRS 0x304
+#define NT_S390_PREFIX 0x305
+#define NT_S390_LAST_BREAK 0x306
+#define NT_S390_SYSTEM_CALL 0x307
+#define NT_S390_TDB 0x308
+#define NT_S390_VXRS_LOW 0x309
+#define NT_S390_VXRS_HIGH 0x30a
+#define NT_ARM_VFP 0x400
+#define NT_ARM_TLS 0x401
+#define NT_ARM_HW_BREAK 0x402
+#define NT_ARM_HW_WATCH 0x403
+#define NT_ARM_SYSTEM_CALL 0x404
+#define NT_METAG_CBUF 0x500
+#define NT_METAG_RPIPE 0x501
+#define NT_METAG_TLS 0x502
+
//===----------------------------------------------------------------------===//
/// @class ELFRelocation
/// @brief Generic wrapper for ELFRel and ELFRela.
@@ -290,6 +328,11 @@ mipsVariantFromElfFlags(const elf::elf_word e_flags, uint32_t endian)
switch (mips_arch)
{
+ case llvm::ELF::EF_MIPS_ARCH_1:
+ case llvm::ELF::EF_MIPS_ARCH_2:
+ case llvm::ELF::EF_MIPS_ARCH_3:
+ case llvm::ELF::EF_MIPS_ARCH_4:
+ case llvm::ELF::EF_MIPS_ARCH_5:
case llvm::ELF::EF_MIPS_ARCH_32:
return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32el : ArchSpec::eMIPSSubType_mips32;
case llvm::ELF::EF_MIPS_ARCH_32R2:
@@ -847,40 +890,52 @@ ObjectFileELF::SetLoadAddress (Target &target,
SectionList *section_list = GetSectionList ();
if (section_list)
{
- if (value_is_offset)
+ if (!value_is_offset)
{
- const size_t num_sections = section_list->GetSize();
- size_t sect_idx = 0;
-
- for (sect_idx = 0; sect_idx < num_sections; ++sect_idx)
+ bool found_offset = false;
+ for (size_t i = 0, count = GetProgramHeaderCount(); i < count; ++i)
{
- // Iterate through the object file sections to find all
- // of the sections that have SHF_ALLOC in their flag bits.
- SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx));
- // if (section_sp && !section_sp->IsThreadSpecific())
- if (section_sp && section_sp->Test(SHF_ALLOC))
- {
- lldb::addr_t load_addr = section_sp->GetFileAddress() + value;
-
- // On 32-bit systems the load address have to fit into 4 bytes. The rest of
- // the bytes are the overflow from the addition.
- if (GetAddressByteSize() == 4)
- load_addr &= 0xFFFFFFFF;
-
- if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, load_addr))
- ++num_loaded_sections;
- }
+ const elf::ELFProgramHeader* header = GetProgramHeaderByIndex(i);
+ if (header == nullptr)
+ continue;
+
+ if (header->p_type != PT_LOAD || header->p_offset != 0)
+ continue;
+
+ value = value - header->p_vaddr;
+ found_offset = true;
+ break;
}
- return num_loaded_sections > 0;
+ if (!found_offset)
+ return false;
}
- else
+
+ const size_t num_sections = section_list->GetSize();
+ size_t sect_idx = 0;
+
+ for (sect_idx = 0; sect_idx < num_sections; ++sect_idx)
{
- // Not sure how to slide an ELF file given the base address
- // of the ELF file in memory
+ // Iterate through the object file sections to find all
+ // of the sections that have SHF_ALLOC in their flag bits.
+ SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx));
+ // if (section_sp && !section_sp->IsThreadSpecific())
+ if (section_sp && section_sp->Test(SHF_ALLOC))
+ {
+ lldb::addr_t load_addr = section_sp->GetFileAddress() + value;
+
+ // On 32-bit systems the load address have to fit into 4 bytes. The rest of
+ // the bytes are the overflow from the addition.
+ if (GetAddressByteSize() == 4)
+ load_addr &= 0xFFFFFFFF;
+
+ if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, load_addr))
+ ++num_loaded_sections;
+ }
}
+ return num_loaded_sections > 0;
}
}
- return false; // If it changed
+ return false;
}
ByteOrder
@@ -905,8 +960,17 @@ ObjectFileELF::GetAddressByteSize() const
AddressClass
ObjectFileELF::GetAddressClass (addr_t file_addr)
{
- auto res = ObjectFile::GetAddressClass (file_addr);
+ Symtab* symtab = GetSymtab();
+ if (!symtab)
+ return eAddressClassUnknown;
+
+ // The address class is determined based on the symtab. Ask it from the object file what
+ // contains the symtab information.
+ ObjectFile* symtab_objfile = symtab->GetObjectFile();
+ if (symtab_objfile != nullptr && symtab_objfile != this)
+ return symtab_objfile->GetAddressClass(file_addr);
+ auto res = ObjectFile::GetAddressClass (file_addr);
if (res != eAddressClassCode)
return res;
@@ -1076,16 +1140,35 @@ ObjectFileELF::GetImageInfoAddress(Target *target)
addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();
return Address(dynsym_section_sp, offset);
}
- else if (symbol.d_tag == DT_MIPS_RLD_MAP && target)
+ // MIPS executables uses DT_MIPS_RLD_MAP_REL to support PIE. DT_MIPS_RLD_MAP exists in non-PIE.
+ else if ((symbol.d_tag == DT_MIPS_RLD_MAP || symbol.d_tag == DT_MIPS_RLD_MAP_REL) && target)
{
addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();
addr_t dyn_base = dynsym_section_sp->GetLoadBaseAddress(target);
if (dyn_base == LLDB_INVALID_ADDRESS)
return Address();
- Address addr;
+
Error error;
- if (target->ReadPointerFromMemory(dyn_base + offset, false, error, addr))
- return addr;
+ if (symbol.d_tag == DT_MIPS_RLD_MAP)
+ {
+ // DT_MIPS_RLD_MAP tag stores an absolute address of the debug pointer.
+ Address addr;
+ if (target->ReadPointerFromMemory(dyn_base + offset, false, error, addr))
+ return addr;
+ }
+ if (symbol.d_tag == DT_MIPS_RLD_MAP_REL)
+ {
+ // DT_MIPS_RLD_MAP_REL tag stores the offset to the debug pointer, relative to the address of the tag.
+ uint64_t rel_offset;
+ rel_offset = target->ReadUnsignedIntegerFromMemory(dyn_base + offset, false, GetAddressByteSize(), UINT64_MAX, error);
+ if (error.Success() && rel_offset != UINT64_MAX)
+ {
+ Address addr;
+ addr_t debug_ptr_address = dyn_base + (offset - GetAddressByteSize()) + rel_offset;
+ addr.SetOffset (debug_ptr_address);
+ return addr;
+ }
+ }
}
}
@@ -1232,6 +1315,7 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
while (true)
{
// Parse the note header. If this fails, bail out.
+ const lldb::offset_t note_offset = offset;
ELFNote note = ELFNote();
if (!note.Parse(data, &offset))
{
@@ -1239,11 +1323,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
return error;
}
- // If a tag processor handles the tag, it should set processed to true, and
- // the loop will assume the tag processing has moved entirely past the note's payload.
- // Otherwise, leave it false and the end of the loop will handle the offset properly.
- bool processed = false;
-
if (log)
log->Printf ("ObjectFileELF::%s parsing note name='%s', type=%" PRIu32, __FUNCTION__, note.n_name.c_str (), note.n_type);
@@ -1252,9 +1331,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
(note.n_type == LLDB_NT_FREEBSD_ABI_TAG) &&
(note.n_descsz == LLDB_NT_FREEBSD_ABI_SIZE))
{
- // We'll consume the payload below.
- processed = true;
-
// Pull out the min version info.
uint32_t version_info;
if (data.GetU32 (&offset, &version_info, 1) == nullptr)
@@ -1285,9 +1361,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
case LLDB_NT_GNU_ABI_TAG:
if (note.n_descsz == LLDB_NT_GNU_ABI_SIZE)
{
- // We'll consume the payload below.
- processed = true;
-
// Pull out the min OS version supporting the ABI.
uint32_t version_info[4];
if (data.GetU32 (&offset, &version_info[0], note.n_descsz / 4) == nullptr)
@@ -1330,9 +1403,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
// Only bother processing this if we don't already have the uuid set.
if (!uuid.IsValid())
{
- // We'll consume the payload below.
- processed = true;
-
// 16 bytes is UUID|MD5, 20 bytes is SHA1
if ((note.n_descsz == 16 || note.n_descsz == 20))
{
@@ -1355,10 +1425,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
(note.n_type == LLDB_NT_NETBSD_ABI_TAG) &&
(note.n_descsz == LLDB_NT_NETBSD_ABI_SIZE))
{
-
- // We'll consume the payload below.
- processed = true;
-
// Pull out the min version info.
uint32_t version_info;
if (data.GetU32 (&offset, &version_info, 1) == nullptr)
@@ -1378,8 +1444,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
else if ((note.n_type == LLDB_NT_GNU_ABI_TAG) &&
(note.n_name == LLDB_NT_OWNER_CSR))
{
- // We'll consume the payload below.
- processed = true;
arch_spec.GetTriple().setOS(llvm::Triple::OSType::UnknownOS);
arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::CSR);
@@ -1397,9 +1461,48 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
arch_spec.GetTriple().setEnvironment(llvm::Triple::EnvironmentType::Android);
}
+ else if (note.n_name == LLDB_NT_OWNER_LINUX)
+ {
+ // This is sometimes found in core files and usually contains extended register info
+ arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
+ }
+ else if (note.n_name == LLDB_NT_OWNER_CORE)
+ {
+ // Parse the NT_FILE to look for stuff in paths to shared libraries
+ // As the contents look like:
+ // count = 0x000000000000000a (10)
+ // page_size = 0x0000000000001000 (4096)
+ // Index start end file_ofs path
+ // ===== ------------------ ------------------ ------------------ -------------------------------------
+ // [ 0] 0x0000000000400000 0x0000000000401000 0x0000000000000000 /tmp/a.out
+ // [ 1] 0x0000000000600000 0x0000000000601000 0x0000000000000000 /tmp/a.out
+ // [ 2] 0x0000000000601000 0x0000000000602000 0x0000000000000001 /tmp/a.out
+ // [ 3] 0x00007fa79c9ed000 0x00007fa79cba8000 0x0000000000000000 /lib/x86_64-linux-gnu/libc-2.19.so
+ // [ 4] 0x00007fa79cba8000 0x00007fa79cda7000 0x00000000000001bb /lib/x86_64-linux-gnu/libc-2.19.so
+ // [ 5] 0x00007fa79cda7000 0x00007fa79cdab000 0x00000000000001ba /lib/x86_64-linux-gnu/libc-2.19.so
+ // [ 6] 0x00007fa79cdab000 0x00007fa79cdad000 0x00000000000001be /lib/x86_64-linux-gnu/libc-2.19.so
+ // [ 7] 0x00007fa79cdb2000 0x00007fa79cdd5000 0x0000000000000000 /lib/x86_64-linux-gnu/ld-2.19.so
+ // [ 8] 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022 /lib/x86_64-linux-gnu/ld-2.19.so
+ // [ 9] 0x00007fa79cfd5000 0x00007fa79cfd6000 0x0000000000000023 /lib/x86_64-linux-gnu/ld-2.19.so
+ if (note.n_type == NT_FILE)
+ {
+ uint64_t count = data.GetU64(&offset);
+ offset += 8 + 3*8*count; // Skip page size and all start/end/file_ofs
+ for (size_t i=0; i<count; ++i)
+ {
+ llvm::StringRef path(data.GetCStr(&offset));
+ if (path.startswith("/lib/x86_64-linux-gnu"))
+ {
+ arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
+ break;
+ }
+ }
+ }
+ }
- if (!processed)
- offset += llvm::RoundUpToAlignment(note.n_descsz, 4);
+ // Calculate the offset of the next note just in case "offset" has been used
+ // to poke at the contents of the note data
+ offset = note_offset + note.GetByteSize();
}
return error;
@@ -1496,8 +1599,8 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
I != section_headers.end(); ++I)
{
static ConstString g_sect_name_gnu_debuglink (".gnu_debuglink");
- const ELFSectionHeaderInfo &header = *I;
- const uint64_t section_size = header.sh_type == SHT_NOBITS ? 0 : header.sh_size;
+ const ELFSectionHeaderInfo &sheader = *I;
+ const uint64_t section_size = sheader.sh_type == SHT_NOBITS ? 0 : sheader.sh_size;
ConstString name(shstr_data.PeekCStr(I->sh_name));
I->section_name = name;
@@ -1505,23 +1608,33 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
if (arch_spec.GetMachine() == llvm::Triple::mips || arch_spec.GetMachine() == llvm::Triple::mipsel
|| arch_spec.GetMachine() == llvm::Triple::mips64 || arch_spec.GetMachine() == llvm::Triple::mips64el)
{
- if (header.sh_type == SHT_MIPS_ABIFLAGS)
+ uint32_t arch_flags = arch_spec.GetFlags ();
+ DataExtractor data;
+ if (sheader.sh_type == SHT_MIPS_ABIFLAGS)
{
- DataExtractor data;
- if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size))
+
+ if (section_size && (data.SetData (object_data, sheader.sh_offset, section_size) == section_size))
{
lldb::offset_t ase_offset = 12; // MIPS ABI Flags Version: 0
- uint32_t arch_flags = arch_spec.GetFlags ();
arch_flags |= data.GetU32 (&ase_offset);
- arch_spec.SetFlags (arch_flags);
}
}
+ // Settings appropriate ArchSpec ABI Flags
+ if (header.e_flags & llvm::ELF::EF_MIPS_ABI2)
+ {
+ arch_flags |= lldb_private::ArchSpec::eMIPSABI_N32;
+ }
+ else if (header.e_flags & llvm::ELF::EF_MIPS_ABI_O32)
+ {
+ arch_flags |= lldb_private::ArchSpec::eMIPSABI_O32;
+ }
+ arch_spec.SetFlags (arch_flags);
}
if (name == g_sect_name_gnu_debuglink)
{
DataExtractor data;
- if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size))
+ if (section_size && (data.SetData (object_data, sheader.sh_offset, section_size) == section_size))
{
lldb::offset_t gnu_debuglink_offset = 0;
gnu_debuglink_file = data.GetCStr (&gnu_debuglink_offset);
@@ -1531,7 +1644,7 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
}
// Process ELF note section entries.
- bool is_note_header = (header.sh_type == SHT_NOTE);
+ bool is_note_header = (sheader.sh_type == SHT_NOTE);
// The section header ".note.android.ident" is stored as a
// PROGBITS type header but it is actually a note header.
@@ -1543,7 +1656,7 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
{
// Allow notes to refine module info.
DataExtractor data;
- if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size))
+ if (section_size && (data.SetData (object_data, sheader.sh_offset, section_size) == section_size))
{
Error error = RefineModuleDetailsFromNote (data, arch_spec, uuid);
if (error.Fail ())
@@ -1555,6 +1668,12 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
}
}
+ // Make any unknown triple components to be unspecified unknowns.
+ if (arch_spec.GetTriple().getVendor() == llvm::Triple::UnknownVendor)
+ arch_spec.GetTriple().setVendorName (llvm::StringRef());
+ if (arch_spec.GetTriple().getOS() == llvm::Triple::UnknownOS)
+ arch_spec.GetTriple().setOSName (llvm::StringRef());
+
return section_headers.size();
}
}
@@ -1651,17 +1770,30 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)
static ConstString g_sect_name_tdata (".tdata");
static ConstString g_sect_name_tbss (".tbss");
static ConstString g_sect_name_dwarf_debug_abbrev (".debug_abbrev");
+ static ConstString g_sect_name_dwarf_debug_addr (".debug_addr");
static ConstString g_sect_name_dwarf_debug_aranges (".debug_aranges");
static ConstString g_sect_name_dwarf_debug_frame (".debug_frame");
static ConstString g_sect_name_dwarf_debug_info (".debug_info");
static ConstString g_sect_name_dwarf_debug_line (".debug_line");
static ConstString g_sect_name_dwarf_debug_loc (".debug_loc");
static ConstString g_sect_name_dwarf_debug_macinfo (".debug_macinfo");
+ static ConstString g_sect_name_dwarf_debug_macro (".debug_macro");
static ConstString g_sect_name_dwarf_debug_pubnames (".debug_pubnames");
static ConstString g_sect_name_dwarf_debug_pubtypes (".debug_pubtypes");
static ConstString g_sect_name_dwarf_debug_ranges (".debug_ranges");
static ConstString g_sect_name_dwarf_debug_str (".debug_str");
+ static ConstString g_sect_name_dwarf_debug_str_offsets (".debug_str_offsets");
+ static ConstString g_sect_name_dwarf_debug_abbrev_dwo (".debug_abbrev.dwo");
+ static ConstString g_sect_name_dwarf_debug_info_dwo (".debug_info.dwo");
+ static ConstString g_sect_name_dwarf_debug_line_dwo (".debug_line.dwo");
+ static ConstString g_sect_name_dwarf_debug_macro_dwo (".debug_macro.dwo");
+ static ConstString g_sect_name_dwarf_debug_loc_dwo (".debug_loc.dwo");
+ static ConstString g_sect_name_dwarf_debug_str_dwo (".debug_str.dwo");
+ static ConstString g_sect_name_dwarf_debug_str_offsets_dwo (".debug_str_offsets.dwo");
static ConstString g_sect_name_eh_frame (".eh_frame");
+ static ConstString g_sect_name_arm_exidx (".ARM.exidx");
+ static ConstString g_sect_name_arm_extab (".ARM.extab");
+ static ConstString g_sect_name_go_symtab (".gosymtab");
SectionType sect_type = eSectionTypeOther;
@@ -1694,18 +1826,31 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)
// MISSING? .gnu_debugdata - "mini debuginfo / MiniDebugInfo" section, http://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html
// MISSING? .debug-index - http://src.chromium.org/viewvc/chrome/trunk/src/build/gdb-add-index?pathrev=144644
// MISSING? .debug_types - Type descriptions from DWARF 4? See http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo
- else if (name == g_sect_name_dwarf_debug_abbrev) sect_type = eSectionTypeDWARFDebugAbbrev;
- else if (name == g_sect_name_dwarf_debug_aranges) sect_type = eSectionTypeDWARFDebugAranges;
- else if (name == g_sect_name_dwarf_debug_frame) sect_type = eSectionTypeDWARFDebugFrame;
- else if (name == g_sect_name_dwarf_debug_info) sect_type = eSectionTypeDWARFDebugInfo;
- else if (name == g_sect_name_dwarf_debug_line) sect_type = eSectionTypeDWARFDebugLine;
- else if (name == g_sect_name_dwarf_debug_loc) sect_type = eSectionTypeDWARFDebugLoc;
- else if (name == g_sect_name_dwarf_debug_macinfo) sect_type = eSectionTypeDWARFDebugMacInfo;
- else if (name == g_sect_name_dwarf_debug_pubnames) sect_type = eSectionTypeDWARFDebugPubNames;
- else if (name == g_sect_name_dwarf_debug_pubtypes) sect_type = eSectionTypeDWARFDebugPubTypes;
- else if (name == g_sect_name_dwarf_debug_ranges) sect_type = eSectionTypeDWARFDebugRanges;
- else if (name == g_sect_name_dwarf_debug_str) sect_type = eSectionTypeDWARFDebugStr;
- else if (name == g_sect_name_eh_frame) sect_type = eSectionTypeEHFrame;
+ else if (name == g_sect_name_dwarf_debug_abbrev) sect_type = eSectionTypeDWARFDebugAbbrev;
+ else if (name == g_sect_name_dwarf_debug_addr) sect_type = eSectionTypeDWARFDebugAddr;
+ else if (name == g_sect_name_dwarf_debug_aranges) sect_type = eSectionTypeDWARFDebugAranges;
+ else if (name == g_sect_name_dwarf_debug_frame) sect_type = eSectionTypeDWARFDebugFrame;
+ else if (name == g_sect_name_dwarf_debug_info) sect_type = eSectionTypeDWARFDebugInfo;
+ else if (name == g_sect_name_dwarf_debug_line) sect_type = eSectionTypeDWARFDebugLine;
+ else if (name == g_sect_name_dwarf_debug_loc) sect_type = eSectionTypeDWARFDebugLoc;
+ else if (name == g_sect_name_dwarf_debug_macinfo) sect_type = eSectionTypeDWARFDebugMacInfo;
+ else if (name == g_sect_name_dwarf_debug_macro) sect_type = eSectionTypeDWARFDebugMacro;
+ else if (name == g_sect_name_dwarf_debug_pubnames) sect_type = eSectionTypeDWARFDebugPubNames;
+ else if (name == g_sect_name_dwarf_debug_pubtypes) sect_type = eSectionTypeDWARFDebugPubTypes;
+ else if (name == g_sect_name_dwarf_debug_ranges) sect_type = eSectionTypeDWARFDebugRanges;
+ else if (name == g_sect_name_dwarf_debug_str) sect_type = eSectionTypeDWARFDebugStr;
+ else if (name == g_sect_name_dwarf_debug_str_offsets) sect_type = eSectionTypeDWARFDebugStrOffsets;
+ else if (name == g_sect_name_dwarf_debug_abbrev_dwo) sect_type = eSectionTypeDWARFDebugAbbrev;
+ else if (name == g_sect_name_dwarf_debug_info_dwo) sect_type = eSectionTypeDWARFDebugInfo;
+ else if (name == g_sect_name_dwarf_debug_line_dwo) sect_type = eSectionTypeDWARFDebugLine;
+ else if (name == g_sect_name_dwarf_debug_macro_dwo) sect_type = eSectionTypeDWARFDebugMacro;
+ else if (name == g_sect_name_dwarf_debug_loc_dwo) sect_type = eSectionTypeDWARFDebugLoc;
+ else if (name == g_sect_name_dwarf_debug_str_dwo) sect_type = eSectionTypeDWARFDebugStr;
+ else if (name == g_sect_name_dwarf_debug_str_offsets_dwo) sect_type = eSectionTypeDWARFDebugStrOffsets;
+ else if (name == g_sect_name_eh_frame) sect_type = eSectionTypeEHFrame;
+ else if (name == g_sect_name_arm_exidx) sect_type = eSectionTypeARMexidx;
+ else if (name == g_sect_name_arm_extab) sect_type = eSectionTypeARMextab;
+ else if (name == g_sect_name_go_symtab) sect_type = eSectionTypeGoSymtab;
switch (header.sh_type)
{
@@ -1731,7 +1876,7 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)
if (eSectionTypeOther == sect_type)
{
// the kalimba toolchain assumes that ELF section names are free-form. It does
- // supports linkscripts which (can) give rise to various arbitarily named
+ // support linkscripts which (can) give rise to various arbitrarily named
// sections being "Code" or "Data".
sect_type = kalimbaSectionType(m_header, header);
}
@@ -1770,17 +1915,19 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)
{
static const SectionType g_sections[] =
{
- eSectionTypeDWARFDebugAranges,
- eSectionTypeDWARFDebugInfo,
eSectionTypeDWARFDebugAbbrev,
+ eSectionTypeDWARFDebugAddr,
+ eSectionTypeDWARFDebugAranges,
eSectionTypeDWARFDebugFrame,
+ eSectionTypeDWARFDebugInfo,
eSectionTypeDWARFDebugLine,
- eSectionTypeDWARFDebugStr,
eSectionTypeDWARFDebugLoc,
eSectionTypeDWARFDebugMacInfo,
eSectionTypeDWARFDebugPubNames,
eSectionTypeDWARFDebugPubTypes,
eSectionTypeDWARFDebugRanges,
+ eSectionTypeDWARFDebugStr,
+ eSectionTypeDWARFDebugStrOffsets,
eSectionTypeELFSymbolTable,
};
SectionList *elf_section_list = m_sections_ap.get();
@@ -1805,6 +1952,29 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list)
}
}
+// Find the arm/aarch64 mapping symbol character in the given symbol name. Mapping symbols have the
+// form of "$<char>[.<any>]*". Additionally we recognize cases when the mapping symbol prefixed by
+// an arbitrary string because if a symbol prefix added to each symbol in the object file with
+// objcopy then the mapping symbols are also prefixed.
+static char
+FindArmAarch64MappingSymbol(const char* symbol_name)
+{
+ if (!symbol_name)
+ return '\0';
+
+ const char* dollar_pos = ::strchr(symbol_name, '$');
+ if (!dollar_pos || dollar_pos[1] == '\0')
+ return '\0';
+
+ if (dollar_pos[2] == '\0' || dollar_pos[2] == '.')
+ return dollar_pos[1];
+ return '\0';
+}
+
+#define STO_MIPS_ISA (3 << 6)
+#define STO_MICROMIPS (2 << 6)
+#define IS_MICROMIPS(ST_OTHER) (((ST_OTHER) & STO_MIPS_ISA) == STO_MICROMIPS)
+
// private
unsigned
ObjectFileELF::ParseSymbols (Symtab *symtab,
@@ -1840,6 +2010,13 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
// makes it highly unlikely that this will collide with anything else.
bool skip_oatdata_oatexec = m_file.GetFilename() == ConstString("system@framework@boot.oat");
+ ArchSpec arch;
+ GetArchitecture(arch);
+
+ // Local cache to avoid doing a FindSectionByName for each symbol. The "const char*" key must
+ // came from a ConstString object so they can be compared by pointer
+ std::unordered_map<const char*, lldb::SectionSP> section_name_to_section;
+
unsigned i;
for (i = 0; i < num_symbols; ++i)
{
@@ -1945,64 +2122,58 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
int64_t symbol_value_offset = 0;
uint32_t additional_flags = 0;
- ArchSpec arch;
- if (GetArchitecture(arch))
+ if (arch.IsValid())
{
if (arch.GetMachine() == llvm::Triple::arm)
{
- if (symbol.getBinding() == STB_LOCAL && symbol_name && symbol_name[0] == '$')
+ if (symbol.getBinding() == STB_LOCAL)
{
- // These are reserved for the specification (e.g.: mapping
- // symbols). We don't want to add them to the symbol table.
-
+ char mapping_symbol = FindArmAarch64MappingSymbol(symbol_name);
if (symbol_type == eSymbolTypeCode)
{
- llvm::StringRef symbol_name_ref(symbol_name);
- if (symbol_name_ref == "$a" || symbol_name_ref.startswith("$a."))
- {
- // $a[.<any>]* - marks an ARM instruction sequence
- m_address_class_map[symbol.st_value] = eAddressClassCode;
- }
- else if (symbol_name_ref == "$b" || symbol_name_ref.startswith("$b.") ||
- symbol_name_ref == "$t" || symbol_name_ref.startswith("$t."))
+ switch (mapping_symbol)
{
- // $b[.<any>]* - marks a THUMB BL instruction sequence
- // $t[.<any>]* - marks a THUMB instruction sequence
- m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
- }
- else if (symbol_name_ref == "$d" || symbol_name_ref.startswith("$d."))
- {
- // $d[.<any>]* - marks a data item sequence (e.g. lit pool)
- m_address_class_map[symbol.st_value] = eAddressClassData;
+ case 'a':
+ // $a[.<any>]* - marks an ARM instruction sequence
+ m_address_class_map[symbol.st_value] = eAddressClassCode;
+ break;
+ case 'b':
+ case 't':
+ // $b[.<any>]* - marks a THUMB BL instruction sequence
+ // $t[.<any>]* - marks a THUMB instruction sequence
+ m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
+ break;
+ case 'd':
+ // $d[.<any>]* - marks a data item sequence (e.g. lit pool)
+ m_address_class_map[symbol.st_value] = eAddressClassData;
+ break;
}
}
-
- continue;
+ if (mapping_symbol)
+ continue;
}
}
else if (arch.GetMachine() == llvm::Triple::aarch64)
{
- if (symbol.getBinding() == STB_LOCAL && symbol_name && symbol_name[0] == '$')
+ if (symbol.getBinding() == STB_LOCAL)
{
- // These are reserved for the specification (e.g.: mapping
- // symbols). We don't want to add them to the symbol table.
-
+ char mapping_symbol = FindArmAarch64MappingSymbol(symbol_name);
if (symbol_type == eSymbolTypeCode)
{
- llvm::StringRef symbol_name_ref(symbol_name);
- if (symbol_name_ref == "$x" || symbol_name_ref.startswith("$x."))
+ switch (mapping_symbol)
{
- // $x[.<any>]* - marks an A64 instruction sequence
- m_address_class_map[symbol.st_value] = eAddressClassCode;
- }
- else if (symbol_name_ref == "$d" || symbol_name_ref.startswith("$d."))
- {
- // $d[.<any>]* - marks a data item sequence (e.g. lit pool)
- m_address_class_map[symbol.st_value] = eAddressClassData;
+ case 'x':
+ // $x[.<any>]* - marks an A64 instruction sequence
+ m_address_class_map[symbol.st_value] = eAddressClassCode;
+ break;
+ case 'd':
+ // $d[.<any>]* - marks a data item sequence (e.g. lit pool)
+ m_address_class_map[symbol.st_value] = eAddressClassData;
+ break;
}
}
-
- continue;
+ if (mapping_symbol)
+ continue;
}
}
@@ -2029,11 +2200,46 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
}
}
}
+
+ /*
+ * MIPS:
+ * The bit #0 of an address is used for ISA mode (1 for microMIPS, 0 for MIPS).
+ * This allows processer to switch between microMIPS and MIPS without any need
+ * for special mode-control register. However, apart from .debug_line, none of
+ * the ELF/DWARF sections set the ISA bit (for symbol or section). Use st_other
+ * flag to check whether the symbol is microMIPS and then set the address class
+ * accordingly.
+ */
+ const llvm::Triple::ArchType llvm_arch = arch.GetMachine();
+ if (llvm_arch == llvm::Triple::mips || llvm_arch == llvm::Triple::mipsel
+ || llvm_arch == llvm::Triple::mips64 || llvm_arch == llvm::Triple::mips64el)
+ {
+ if (IS_MICROMIPS(symbol.st_other))
+ m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
+ else if ((symbol.st_value & 1) && (symbol_type == eSymbolTypeCode))
+ {
+ symbol.st_value = symbol.st_value & (~1ull);
+ m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
+ }
+ else
+ {
+ if (symbol_type == eSymbolTypeCode)
+ m_address_class_map[symbol.st_value] = eAddressClassCode;
+ else if (symbol_type == eSymbolTypeData)
+ m_address_class_map[symbol.st_value] = eAddressClassData;
+ else
+ m_address_class_map[symbol.st_value] = eAddressClassUnknown;
+ }
+ }
}
- // If the symbol section we've found has no data (SHT_NOBITS), then check the module section
- // list. This can happen if we're parsing the debug file and it has no .text section, for example.
- if (symbol_section_sp && (symbol_section_sp->GetFileSize() == 0))
+ // symbol_value_offset may contain 0 for ARM symbols or -1 for
+ // THUMB symbols. See above for more details.
+ uint64_t symbol_value = symbol.st_value + symbol_value_offset;
+ if (symbol_section_sp && CalculateType() != ObjectFile::Type::eTypeObjectFile)
+ symbol_value -= symbol_section_sp->GetFileAddress();
+
+ if (symbol_section_sp)
{
ModuleSP module_sp(GetModule());
if (module_sp)
@@ -2042,20 +2248,17 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
if (module_section_list && module_section_list != section_list)
{
const ConstString &sect_name = symbol_section_sp->GetName();
- lldb::SectionSP section_sp (module_section_list->FindSectionByName (sect_name));
- if (section_sp && section_sp->GetFileSize())
- {
- symbol_section_sp = section_sp;
- }
+ auto section_it = section_name_to_section.find(sect_name.GetCString());
+ if (section_it == section_name_to_section.end())
+ section_it = section_name_to_section.emplace(
+ sect_name.GetCString(),
+ module_section_list->FindSectionByName (sect_name)).first;
+ if (section_it->second && section_it->second->GetFileSize())
+ symbol_section_sp = section_it->second;
}
}
}
- // symbol_value_offset may contain 0 for ARM symbols or -1 for
- // THUMB symbols. See above for more details.
- uint64_t symbol_value = symbol.st_value + symbol_value_offset;
- if (symbol_section_sp && CalculateType() != ObjectFile::Type::eTypeObjectFile)
- symbol_value -= symbol_section_sp->GetFileAddress();
bool is_global = symbol.getBinding() == STB_GLOBAL;
uint32_t flags = symbol.st_other << 8 | symbol.st_info | additional_flags;
bool is_mangled = symbol_name ? (symbol_name[0] == '_' && symbol_name[1] == 'Z') : false;
@@ -2069,7 +2272,7 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
Mangled mangled(ConstString(symbol_bare), is_mangled);
// Now append the suffix back to mangled and unmangled names. Only do it if the
- // demangling was sucessful (string is not empty).
+ // demangling was successful (string is not empty).
if (has_suffix)
{
llvm::StringRef suffix = symbol_ref.substr(version_pos);
@@ -2221,7 +2424,7 @@ ObjectFileELF::PLTRelocationType()
}
// Returns the size of the normal plt entries and the offset of the first normal plt entry. The
-// 0th entry in the plt table is ususally a resolution entry which have different size in some
+// 0th entry in the plt table is usually a resolution entry which have different size in some
// architectures then the rest of the plt entries.
static std::pair<uint64_t, uint64_t>
GetPltEntrySizeAndOffset(const ELFSectionHeader* rel_hdr, const ELFSectionHeader* plt_hdr)
@@ -2237,8 +2440,8 @@ GetPltEntrySizeAndOffset(const ELFSectionHeader* rel_hdr, const ELFSectionHeader
{
// The linker haven't set the plt_hdr->sh_entsize field. Try to guess the size of the plt
// entries based on the number of entries and the size of the plt section with the
- // asumption that the size of the 0th entry is at least as big as the size of the normal
- // entries and it isn't mutch bigger then that.
+ // assumption that the size of the 0th entry is at least as big as the size of the normal
+ // entries and it isn't much bigger then that.
if (plt_hdr->sh_addralign)
plt_entsize = plt_hdr->sh_size / plt_hdr->sh_addralign / (num_relocations + 1) * plt_hdr->sh_addralign;
else
@@ -2563,8 +2766,6 @@ ObjectFileELF::GetSymtab()
uint64_t symbol_id = 0;
lldb_private::Mutex::Locker locker(module_sp->GetMutex());
- m_symtab_ap.reset(new Symtab(this));
-
// Sharable objects and dynamic executables usually have 2 distinct symbol
// tables, one named ".symtab", and the other ".dynsym". The dynsym is a smaller
// version of the symtab that only contains global symbols. The information found
@@ -2578,7 +2779,10 @@ ObjectFileELF::GetSymtab()
symtab = section_list->FindSectionByType (eSectionTypeELFDynamicSymbols, true).get();
}
if (symtab)
+ {
+ m_symtab_ap.reset(new Symtab(symtab->GetObjectFile()));
symbol_id += ParseSymbolTable (m_symtab_ap.get(), symbol_id, symtab);
+ }
// DT_JMPREL
// If present, this entry's d_ptr member holds the address of relocation
@@ -2598,10 +2802,19 @@ ObjectFileELF::GetSymtab()
user_id_t reloc_id = reloc_section->GetID();
const ELFSectionHeaderInfo *reloc_header = GetSectionHeaderByIndex(reloc_id);
assert(reloc_header);
+
+ if (m_symtab_ap == nullptr)
+ m_symtab_ap.reset(new Symtab(reloc_section->GetObjectFile()));
ParseTrampolineSymbols (m_symtab_ap.get(), symbol_id, reloc_header, reloc_id);
}
}
+
+ // If we still don't have any symtab then create an empty instance to avoid do the section
+ // lookup next time.
+ if (m_symtab_ap == nullptr)
+ m_symtab_ap.reset(new Symtab(this));
+
m_symtab_ap->CalculateSymbolSizes();
}
@@ -3000,6 +3213,27 @@ ObjectFileELF::GetArchitecture (ArchSpec &arch)
ParseSectionHeaders();
}
+ if (CalculateType() == eTypeCoreFile && m_arch_spec.TripleOSIsUnspecifiedUnknown())
+ {
+ // Core files don't have section headers yet they have PT_NOTE program headers
+ // that might shed more light on the architecture
+ if (ParseProgramHeaders())
+ {
+ for (size_t i = 0, count = GetProgramHeaderCount(); i < count; ++i)
+ {
+ const elf::ELFProgramHeader* header = GetProgramHeaderByIndex(i);
+ if (header && header->p_type == PT_NOTE && header->p_offset != 0 && header->p_filesz > 0)
+ {
+ DataExtractor data;
+ if (data.SetData (m_data, header->p_offset, header->p_filesz) == header->p_filesz)
+ {
+ lldb_private::UUID uuid;
+ RefineModuleDetailsFromNote (data, m_arch_spec, uuid);
+ }
+ }
+ }
+ }
+ }
arch = m_arch_spec;
return true;
}
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index 99088d166b12..4b97f92c6c5c 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -10,9 +10,14 @@
#ifndef liblldb_ObjectFileELF_h_
#define liblldb_ObjectFileELF_h_
+// C Includes
#include <stdint.h>
+
+// C++ Includes
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -47,6 +52,12 @@ struct ELFNote
/// True if the ELFRel entry was successfully read and false otherwise.
bool
Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+
+ size_t
+ GetByteSize() const
+ {
+ return 12 + llvm::RoundUpToAlignment (n_namesz, 4) + llvm::RoundUpToAlignment (n_descsz, 4);
+ }
};
//------------------------------------------------------------------------------
@@ -59,6 +70,8 @@ class ObjectFileELF :
public lldb_private::ObjectFile
{
public:
+ ~ObjectFileELF() override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
@@ -113,9 +126,6 @@ public:
//------------------------------------------------------------------
// ObjectFile Protocol.
//------------------------------------------------------------------
- virtual
- ~ObjectFileELF();
-
bool
ParseHeader() override;
@@ -211,6 +221,7 @@ private:
{
lldb_private::ConstString section_name;
};
+
typedef std::vector<ELFSectionHeaderInfo> SectionHeaderColl;
typedef SectionHeaderColl::iterator SectionHeaderCollIter;
typedef SectionHeaderColl::const_iterator SectionHeaderCollConstIter;
@@ -428,4 +439,4 @@ private:
RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, lldb_private::ArchSpec &arch_spec, lldb_private::UUID &uuid);
};
-#endif // #ifndef liblldb_ObjectFileELF_h_
+#endif // liblldb_ObjectFileELF_h_
diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
index 47140f5bcaff..39dbb3fb047b 100644
--- a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
+++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
@@ -10,10 +10,13 @@
#ifndef liblldb_ObjectFileJIT_h_
#define liblldb_ObjectFileJIT_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/Address.h"
#include "lldb/Symbol/ObjectFile.h"
-
//----------------------------------------------------------------------
// This class needs to be hidden as eventually belongs in a plugin that
// will export the ObjectFile protocol
@@ -22,6 +25,11 @@ class ObjectFileJIT :
public lldb_private::ObjectFile
{
public:
+ ObjectFileJIT(const lldb::ModuleSP &module_sp,
+ const lldb::ObjectFileJITDelegateSP &delegate_sp);
+
+ ~ObjectFileJIT() override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
@@ -62,81 +70,77 @@ public:
//------------------------------------------------------------------
// Member Functions
//------------------------------------------------------------------
- ObjectFileJIT (const lldb::ModuleSP &module_sp,
- const lldb::ObjectFileJITDelegateSP &delegate_sp);
-
- virtual
- ~ObjectFileJIT();
-
- virtual bool
- ParseHeader ();
+ bool
+ ParseHeader() override;
- virtual bool
+ bool
SetLoadAddress(lldb_private::Target &target,
lldb::addr_t value,
- bool value_is_offset);
+ bool value_is_offset) override;
- virtual lldb::ByteOrder
- GetByteOrder () const;
+ lldb::ByteOrder
+ GetByteOrder() const override;
- virtual bool
- IsExecutable () const;
+ bool
+ IsExecutable() const override;
- virtual uint32_t
- GetAddressByteSize () const;
+ uint32_t
+ GetAddressByteSize() const override;
- virtual lldb_private::Symtab *
- GetSymtab();
+ lldb_private::Symtab *
+ GetSymtab() override;
- virtual bool
- IsStripped ();
+ bool
+ IsStripped() override;
- virtual void
- CreateSections (lldb_private::SectionList &unified_section_list);
+ void
+ CreateSections(lldb_private::SectionList &unified_section_list) override;
- virtual void
- Dump (lldb_private::Stream *s);
+ void
+ Dump(lldb_private::Stream *s) override;
- virtual bool
- GetArchitecture (lldb_private::ArchSpec &arch);
+ bool
+ GetArchitecture(lldb_private::ArchSpec &arch) override;
- virtual bool
- GetUUID (lldb_private::UUID* uuid);
+ bool
+ GetUUID(lldb_private::UUID* uuid) override;
- virtual uint32_t
- GetDependentModules (lldb_private::FileSpecList& files);
+ uint32_t
+ GetDependentModules(lldb_private::FileSpecList& files) override;
+
+ size_t
+ ReadSectionData(const lldb_private::Section *section,
+ lldb::offset_t section_offset,
+ void *dst,
+ size_t dst_len) const override;
+
+ size_t
+ ReadSectionData(const lldb_private::Section *section,
+ lldb_private::DataExtractor& section_data) const override;
- virtual size_t
- ReadSectionData (const lldb_private::Section *section,
- lldb::offset_t section_offset,
- void *dst,
- size_t dst_len) const;
- virtual size_t
- ReadSectionData (const lldb_private::Section *section,
- lldb_private::DataExtractor& section_data) const;
+ lldb_private::Address
+ GetEntryPointAddress() override;
+ lldb_private::Address
+ GetHeaderAddress() override;
+
+ ObjectFile::Type
+ CalculateType() override;
+
+ ObjectFile::Strata
+ CalculateStrata() override;
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
- virtual lldb_private::Address
- GetEntryPointAddress ();
-
- virtual lldb_private::Address
- GetHeaderAddress ();
-
- virtual ObjectFile::Type
- CalculateType();
-
- virtual ObjectFile::Strata
- CalculateStrata();
protected:
lldb::ObjectFileJITDelegateWP m_delegate_wp;
};
-#endif // liblldb_ObjectFileJIT_h_
+#endif // liblldb_ObjectFileJIT_h_
diff --git a/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp b/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp
new file mode 100644
index 000000000000..86c574f2776c
--- /dev/null
+++ b/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp
@@ -0,0 +1,559 @@
+//===-- OperatingSystemGo.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+#include <unordered_map>
+
+// Other libraries and framework includes
+// Project includes
+#include "OperatingSystemGo.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/OptionValueProperties.h"
+#include "lldb/Interpreter/Options.h"
+#include "lldb/Interpreter/OptionGroupBoolean.h"
+#include "lldb/Interpreter/OptionGroupUInt64.h"
+#include "lldb/Interpreter/Property.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadList.h"
+#include "lldb/Target/Thread.h"
+#include "Plugins/Process/Utility/DynamicRegisterInfo.h"
+#include "Plugins/Process/Utility/RegisterContextMemory.h"
+#include "Plugins/Process/Utility/ThreadMemory.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace
+{
+
+static PropertyDefinition g_properties[] = {{"enable", OptionValue::eTypeBoolean, true, true, nullptr, nullptr,
+ "Specify whether goroutines should be treated as threads."},
+ {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}};
+
+enum
+{
+ ePropertyEnableGoroutines,
+};
+
+class PluginProperties : public Properties
+{
+public:
+ PluginProperties()
+ : Properties()
+ {
+ m_collection_sp.reset(new OptionValueProperties(GetSettingName()));
+ m_collection_sp->Initialize(g_properties);
+ }
+
+ ~PluginProperties() override = default;
+
+ static ConstString
+ GetSettingName()
+ {
+ return OperatingSystemGo::GetPluginNameStatic();
+ }
+
+ bool
+ GetEnableGoroutines()
+ {
+ const uint32_t idx = ePropertyEnableGoroutines;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(NULL, idx, g_properties[idx].default_uint_value);
+ }
+
+ bool
+ SetEnableGoroutines(bool enable)
+ {
+ const uint32_t idx = ePropertyEnableGoroutines;
+ return m_collection_sp->SetPropertyAtIndexAsUInt64(NULL, idx, enable);
+ }
+};
+
+typedef std::shared_ptr<PluginProperties> OperatingSystemGoPropertiesSP;
+
+static const OperatingSystemGoPropertiesSP &
+GetGlobalPluginProperties()
+{
+ static OperatingSystemGoPropertiesSP g_settings_sp;
+ if (!g_settings_sp)
+ g_settings_sp.reset(new PluginProperties());
+ return g_settings_sp;
+}
+
+class RegisterContextGo : public RegisterContextMemory
+{
+public:
+ RegisterContextGo(lldb_private::Thread &thread, uint32_t concrete_frame_idx, DynamicRegisterInfo &reg_info,
+ lldb::addr_t reg_data_addr)
+ : RegisterContextMemory(thread, concrete_frame_idx, reg_info, reg_data_addr)
+ {
+ const RegisterInfo *sp = reg_info.GetRegisterInfoAtIndex(
+ reg_info.ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP));
+ const RegisterInfo *pc = reg_info.GetRegisterInfoAtIndex(
+ reg_info.ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC));
+ size_t byte_size = std::max(sp->byte_offset + sp->byte_size, pc->byte_offset + pc->byte_size);
+
+ DataBufferSP reg_data_sp(new DataBufferHeap(byte_size, 0));
+ m_reg_data.SetData(reg_data_sp);
+ }
+
+ ~RegisterContextGo() override = default;
+
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &reg_value) override
+ {
+ switch (reg_info->kinds[eRegisterKindGeneric])
+ {
+ case LLDB_REGNUM_GENERIC_SP:
+ case LLDB_REGNUM_GENERIC_PC:
+ return RegisterContextMemory::ReadRegister(reg_info, reg_value);
+ default:
+ reg_value.SetValueToInvalid();
+ return true;
+ }
+ }
+
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &reg_value) override
+ {
+ switch (reg_info->kinds[eRegisterKindGeneric])
+ {
+ case LLDB_REGNUM_GENERIC_SP:
+ case LLDB_REGNUM_GENERIC_PC:
+ return RegisterContextMemory::WriteRegister(reg_info, reg_value);
+ default:
+ return false;
+ }
+ }
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(RegisterContextGo);
+};
+
+} // anonymous namespace
+
+struct OperatingSystemGo::Goroutine
+{
+ uint64_t m_lostack;
+ uint64_t m_histack;
+ uint64_t m_goid;
+ addr_t m_gobuf;
+ uint32_t m_status;
+};
+
+void
+OperatingSystemGo::Initialize()
+{
+ PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
+ DebuggerInitialize);
+}
+
+void
+OperatingSystemGo::DebuggerInitialize(Debugger &debugger)
+{
+ if (!PluginManager::GetSettingForOperatingSystemPlugin(debugger, PluginProperties::GetSettingName()))
+ {
+ const bool is_global_setting = true;
+ PluginManager::CreateSettingForOperatingSystemPlugin(
+ debugger, GetGlobalPluginProperties()->GetValueProperties(),
+ ConstString("Properties for the goroutine thread plug-in."), is_global_setting);
+ }
+}
+
+void
+OperatingSystemGo::Terminate()
+{
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+OperatingSystem *
+OperatingSystemGo::CreateInstance(Process *process, bool force)
+{
+ if (!force)
+ {
+ TargetSP target_sp = process->CalculateTarget();
+ if (!target_sp)
+ return nullptr;
+ ModuleList &module_list = target_sp->GetImages();
+ Mutex::Locker modules_locker(module_list.GetMutex());
+ const size_t num_modules = module_list.GetSize();
+ bool found_go_runtime = false;
+ for (size_t i = 0; i < num_modules; ++i)
+ {
+ Module *module = module_list.GetModulePointerAtIndexUnlocked(i);
+ const SectionList *section_list = module->GetSectionList();
+ if (section_list)
+ {
+ SectionSP section_sp(section_list->FindSectionByType(eSectionTypeGoSymtab, true));
+ if (section_sp)
+ {
+ found_go_runtime = true;
+ break;
+ }
+ }
+ }
+ if (!found_go_runtime)
+ return nullptr;
+ }
+ return new OperatingSystemGo(process);
+}
+
+OperatingSystemGo::OperatingSystemGo(lldb_private::Process *process)
+ : OperatingSystem(process)
+ , m_reginfo(new DynamicRegisterInfo)
+{
+}
+
+OperatingSystemGo::~OperatingSystemGo() = default;
+
+ConstString
+OperatingSystemGo::GetPluginNameStatic()
+{
+ static ConstString g_name("goroutines");
+ return g_name;
+}
+
+const char *
+OperatingSystemGo::GetPluginDescriptionStatic()
+{
+ return "Operating system plug-in that reads runtime data-structures for goroutines.";
+}
+
+bool
+OperatingSystemGo::Init(ThreadList &threads)
+{
+ if (threads.GetSize(false) < 1)
+ return false;
+ TargetSP target_sp = m_process->CalculateTarget();
+ if (!target_sp)
+ return false;
+ m_allg_sp = FindGlobal(target_sp, "runtime.allg");
+ m_allglen_sp = FindGlobal(target_sp, "runtime.allglen");
+
+ if (m_allg_sp && !m_allglen_sp)
+ {
+ StreamSP error_sp = target_sp->GetDebugger().GetAsyncErrorStream();
+ error_sp->Printf("Unsupported Go runtime version detected.");
+ return false;
+ }
+
+ if (!m_allg_sp)
+ return false;
+
+ RegisterContextSP real_registers_sp = threads.GetThreadAtIndex(0, false)->GetRegisterContext();
+
+ std::unordered_map<size_t, ConstString> register_sets;
+ for (size_t set_idx = 0; set_idx < real_registers_sp->GetRegisterSetCount(); ++set_idx)
+ {
+ const RegisterSet *set = real_registers_sp->GetRegisterSet(set_idx);
+ ConstString name(set->name);
+ for (size_t reg_idx = 0; reg_idx < set->num_registers; ++reg_idx)
+ {
+ register_sets[reg_idx] = name;
+ }
+ }
+ TypeSP gobuf_sp = FindType(target_sp, "runtime.gobuf");
+ if (!gobuf_sp)
+ {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
+
+ if (log)
+ log->Printf("OperatingSystemGo unable to find struct Gobuf");
+ return false;
+ }
+ CompilerType gobuf_type(gobuf_sp->GetLayoutCompilerType());
+ for (size_t idx = 0; idx < real_registers_sp->GetRegisterCount(); ++idx)
+ {
+ RegisterInfo reg = *real_registers_sp->GetRegisterInfoAtIndex(idx);
+ int field_index = -1;
+ if (reg.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_SP)
+ {
+ field_index = 0;
+ }
+ else if (reg.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_PC)
+ {
+ field_index = 1;
+ }
+ if (field_index == -1)
+ {
+ reg.byte_offset = ~0;
+ }
+ else
+ {
+ std::string field_name;
+ uint64_t bit_offset = 0;
+ CompilerType field_type =
+ gobuf_type.GetFieldAtIndex(field_index, field_name, &bit_offset, nullptr, nullptr);
+ reg.byte_size = field_type.GetByteSize(nullptr);
+ reg.byte_offset = bit_offset / 8;
+ }
+ ConstString name(reg.name);
+ ConstString alt_name(reg.alt_name);
+ m_reginfo->AddRegister(reg, name, alt_name, register_sets[idx]);
+ }
+ return true;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+ConstString
+OperatingSystemGo::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+OperatingSystemGo::GetPluginVersion()
+{
+ return 1;
+}
+
+bool
+OperatingSystemGo::UpdateThreadList(ThreadList &old_thread_list, ThreadList &real_thread_list,
+ ThreadList &new_thread_list)
+{
+ new_thread_list = real_thread_list;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
+
+ if (!(m_allg_sp || Init(real_thread_list)) || (m_allg_sp && !m_allglen_sp) ||
+ !GetGlobalPluginProperties()->GetEnableGoroutines())
+ {
+ return new_thread_list.GetSize(false) > 0;
+ }
+
+ if (log)
+ log->Printf("OperatingSystemGo::UpdateThreadList(%d, %d, %d) fetching thread data from Go for pid %" PRIu64,
+ old_thread_list.GetSize(false), real_thread_list.GetSize(false), new_thread_list.GetSize(0),
+ m_process->GetID());
+ uint64_t allglen = m_allglen_sp->GetValueAsUnsigned(0);
+ if (allglen == 0)
+ {
+ return new_thread_list.GetSize(false) > 0;
+ }
+ std::vector<Goroutine> goroutines;
+ // The threads that are in "new_thread_list" upon entry are the threads from the
+ // lldb_private::Process subclass, no memory threads will be in this list.
+
+ Error err;
+ for (uint64_t i = 0; i < allglen; ++i)
+ {
+ goroutines.push_back(CreateGoroutineAtIndex(i, err));
+ if (err.Fail())
+ {
+ err.PutToLog(log, "OperatingSystemGo::UpdateThreadList");
+ return new_thread_list.GetSize(false) > 0;
+ }
+ }
+ // Make a map so we can match goroutines with backing threads.
+ std::map<uint64_t, ThreadSP> stack_map;
+ for (uint32_t i = 0; i < real_thread_list.GetSize(false); ++i)
+ {
+ ThreadSP thread = real_thread_list.GetThreadAtIndex(i, false);
+ stack_map[thread->GetRegisterContext()->GetSP()] = thread;
+ }
+ for (const Goroutine &goroutine : goroutines)
+ {
+ if (0 /* Gidle */ == goroutine.m_status || 6 /* Gdead */ == goroutine.m_status)
+ {
+ continue;
+ }
+ ThreadSP memory_thread = old_thread_list.FindThreadByID(goroutine.m_goid, false);
+ if (memory_thread && IsOperatingSystemPluginThread(memory_thread) && memory_thread->IsValid())
+ {
+ memory_thread->ClearBackingThread();
+ }
+ else
+ {
+ memory_thread.reset(new ThreadMemory(*m_process, goroutine.m_goid, nullptr, nullptr, goroutine.m_gobuf));
+ }
+ // Search for the backing thread if the goroutine is running.
+ if (2 == (goroutine.m_status & 0xfff))
+ {
+ auto backing_it = stack_map.lower_bound(goroutine.m_lostack);
+ if (backing_it != stack_map.end())
+ {
+ if (goroutine.m_histack >= backing_it->first)
+ {
+ if (log)
+ log->Printf("OperatingSystemGo::UpdateThreadList found backing thread %" PRIx64 " (%" PRIx64
+ ") for thread %" PRIx64 "",
+ backing_it->second->GetID(), backing_it->second->GetProtocolID(),
+ memory_thread->GetID());
+ memory_thread->SetBackingThread(backing_it->second);
+ new_thread_list.RemoveThreadByID(backing_it->second->GetID(), false);
+ }
+ }
+ }
+ new_thread_list.AddThread(memory_thread);
+ }
+
+ return new_thread_list.GetSize(false) > 0;
+}
+
+void
+OperatingSystemGo::ThreadWasSelected(Thread *thread)
+{
+}
+
+RegisterContextSP
+OperatingSystemGo::CreateRegisterContextForThread(Thread *thread, addr_t reg_data_addr)
+{
+ RegisterContextSP reg_ctx_sp;
+ if (!thread)
+ return reg_ctx_sp;
+
+ if (!IsOperatingSystemPluginThread(thread->shared_from_this()))
+ return reg_ctx_sp;
+
+ reg_ctx_sp.reset(new RegisterContextGo(*thread, 0, *m_reginfo, reg_data_addr));
+ return reg_ctx_sp;
+}
+
+StopInfoSP
+OperatingSystemGo::CreateThreadStopReason(lldb_private::Thread *thread)
+{
+ StopInfoSP stop_info_sp;
+ return stop_info_sp;
+}
+
+lldb::ThreadSP
+OperatingSystemGo::CreateThread(lldb::tid_t tid, addr_t context)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
+
+ if (log)
+ log->Printf("OperatingSystemGo::CreateThread (tid = 0x%" PRIx64 ", context = 0x%" PRIx64 ") not implemented",
+ tid, context);
+
+ return ThreadSP();
+}
+
+ValueObjectSP
+OperatingSystemGo::FindGlobal(TargetSP target, const char *name)
+{
+ VariableList variable_list;
+ const bool append = true;
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
+
+ if (log)
+ {
+ log->Printf("exe: %s", target->GetExecutableModule()->GetSpecificationDescription().c_str());
+ log->Printf("modules: %zu", target->GetImages().GetSize());
+ }
+
+ uint32_t match_count = target->GetImages().FindGlobalVariables(ConstString(name), append, 1, variable_list);
+ if (match_count > 0)
+ {
+ ExecutionContextScope *exe_scope = target->GetProcessSP().get();
+ if (exe_scope == NULL)
+ exe_scope = target.get();
+ return ValueObjectVariable::Create(exe_scope, variable_list.GetVariableAtIndex(0));
+ }
+ return ValueObjectSP();
+}
+
+TypeSP
+OperatingSystemGo::FindType(TargetSP target_sp, const char *name)
+{
+ ConstString const_typename(name);
+ SymbolContext sc;
+ const bool exact_match = false;
+
+ const ModuleList &module_list = target_sp->GetImages();
+ size_t count = module_list.GetSize();
+ for (size_t idx = 0; idx < count; idx++)
+ {
+ ModuleSP module_sp(module_list.GetModuleAtIndex(idx));
+ if (module_sp)
+ {
+ TypeSP type_sp(module_sp->FindFirstType(sc, const_typename, exact_match));
+ if (type_sp)
+ return type_sp;
+ }
+ }
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
+
+ if (log)
+ log->Printf("OperatingSystemGo::FindType(%s): not found", name);
+ return TypeSP();
+}
+
+OperatingSystemGo::Goroutine
+OperatingSystemGo::CreateGoroutineAtIndex(uint64_t idx, Error &err)
+{
+ err.Clear();
+ Goroutine result;
+ ValueObjectSP g = m_allg_sp->GetSyntheticArrayMember(idx, true)->Dereference(err);
+ if (err.Fail())
+ {
+ return result;
+ }
+
+ ConstString name("goid");
+ ValueObjectSP val = g->GetChildMemberWithName(name, true);
+ bool success = false;
+ result.m_goid = val->GetValueAsUnsigned(0, &success);
+ if (!success)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("unable to read goid");
+ return result;
+ }
+ name.SetCString("atomicstatus");
+ val = g->GetChildMemberWithName(name, true);
+ result.m_status = (uint32_t)val->GetValueAsUnsigned(0, &success);
+ if (!success)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("unable to read atomicstatus");
+ return result;
+ }
+ name.SetCString("sched");
+ val = g->GetChildMemberWithName(name, true);
+ result.m_gobuf = val->GetAddressOf(false);
+ name.SetCString("stack");
+ val = g->GetChildMemberWithName(name, true);
+ name.SetCString("lo");
+ ValueObjectSP child = val->GetChildMemberWithName(name, true);
+ result.m_lostack = child->GetValueAsUnsigned(0, &success);
+ if (!success)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("unable to read stack.lo");
+ return result;
+ }
+ name.SetCString("hi");
+ child = val->GetChildMemberWithName(name, true);
+ result.m_histack = child->GetValueAsUnsigned(0, &success);
+ if (!success)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("unable to read stack.hi");
+ return result;
+ }
+ return result;
+}
diff --git a/source/Plugins/OperatingSystem/Go/OperatingSystemGo.h b/source/Plugins/OperatingSystem/Go/OperatingSystemGo.h
new file mode 100644
index 000000000000..d3391d907dfe
--- /dev/null
+++ b/source/Plugins/OperatingSystem/Go/OperatingSystemGo.h
@@ -0,0 +1,87 @@
+//===-- OperatingSystemGo.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _liblldb_OperatingSystemGo_h_
+#define _liblldb_OperatingSystemGo_h_
+
+// C Includes
+// C++ Includes
+#include <memory>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/OperatingSystem.h"
+
+class DynamicRegisterInfo;
+
+class OperatingSystemGo : public lldb_private::OperatingSystem
+{
+public:
+ OperatingSystemGo(lldb_private::Process *process);
+
+ ~OperatingSystemGo() override;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static lldb_private::OperatingSystem *CreateInstance(lldb_private::Process *process, bool force);
+
+ static void Initialize();
+
+ static void DebuggerInitialize(lldb_private::Debugger &debugger);
+
+ static void Terminate();
+
+ static lldb_private::ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic();
+
+ //------------------------------------------------------------------
+ // lldb_private::PluginInterface Methods
+ //------------------------------------------------------------------
+ lldb_private::ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+
+ //------------------------------------------------------------------
+ // lldb_private::OperatingSystem Methods
+ //------------------------------------------------------------------
+ bool UpdateThreadList(lldb_private::ThreadList &old_thread_list,
+ lldb_private::ThreadList &real_thread_list,
+ lldb_private::ThreadList &new_thread_list) override;
+
+ void ThreadWasSelected(lldb_private::Thread *thread) override;
+
+ lldb::RegisterContextSP CreateRegisterContextForThread(lldb_private::Thread *thread,
+ lldb::addr_t reg_data_addr) override;
+
+ lldb::StopInfoSP CreateThreadStopReason(lldb_private::Thread *thread) override;
+
+ //------------------------------------------------------------------
+ // Method for lazy creation of threads on demand
+ //------------------------------------------------------------------
+ lldb::ThreadSP CreateThread(lldb::tid_t tid, lldb::addr_t context) override;
+
+private:
+ struct Goroutine;
+
+ static lldb::ValueObjectSP FindGlobal(lldb::TargetSP target, const char *name);
+
+ static lldb::TypeSP FindType(lldb::TargetSP target_sp, const char *name);
+
+ bool Init(lldb_private::ThreadList &threads);
+
+ Goroutine CreateGoroutineAtIndex(uint64_t idx, lldb_private::Error &err);
+
+ std::unique_ptr<DynamicRegisterInfo> m_reginfo;
+ lldb::ValueObjectSP m_allg_sp;
+ lldb::ValueObjectSP m_allglen_sp;
+};
+
+#endif // liblldb_OperatingSystemGo_h_
diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
index e744d13deec1..a556b0e84e83 100644
--- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -24,7 +24,6 @@
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
-#include "lldb/Symbol/ClangNamespaceDecl.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Process.h"
@@ -43,9 +42,7 @@ using namespace lldb_private;
void
OperatingSystemPython::Initialize()
{
- PluginManager::RegisterPlugin (GetPluginNameStatic(),
- GetPluginDescriptionStatic(),
- CreateInstance);
+ PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, nullptr);
}
void
diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
index e29bf8054f6c..1b33c42cf0fe 100644
--- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
+++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
@@ -1,4 +1,4 @@
-//===-- OperatingSystemPython.h ---------------------------*- C++ -*-===//
+//===-- OperatingSystemPython.h ---------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,14 +6,16 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#ifndef LLDB_DISABLE_PYTHON
#ifndef liblldb_OperatingSystemPython_h_
#define liblldb_OperatingSystemPython_h_
+#ifndef LLDB_DISABLE_PYTHON
+
// C Includes
// C++ Includes
// Other libraries and framework includes
+// Project includes
#include "lldb/Core/StructuredData.h"
#include "lldb/Target/OperatingSystem.h"
@@ -27,6 +29,11 @@ class ScriptInterpreter;
class OperatingSystemPython : public lldb_private::OperatingSystem
{
public:
+ OperatingSystemPython(lldb_private::Process *process,
+ const lldb_private::FileSpec &python_module_path);
+
+ ~OperatingSystemPython() override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
@@ -46,49 +53,39 @@ public:
GetPluginDescriptionStatic();
//------------------------------------------------------------------
- // Class Methods
- //------------------------------------------------------------------
- OperatingSystemPython (lldb_private::Process *process,
- const lldb_private::FileSpec &python_module_path);
-
- virtual
- ~OperatingSystemPython ();
-
- //------------------------------------------------------------------
// lldb_private::PluginInterface Methods
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
//------------------------------------------------------------------
// lldb_private::OperatingSystem Methods
//------------------------------------------------------------------
- virtual bool
- UpdateThreadList (lldb_private::ThreadList &old_thread_list,
- lldb_private::ThreadList &real_thread_list,
- lldb_private::ThreadList &new_thread_list);
+ bool
+ UpdateThreadList(lldb_private::ThreadList &old_thread_list,
+ lldb_private::ThreadList &real_thread_list,
+ lldb_private::ThreadList &new_thread_list) override;
- virtual void
- ThreadWasSelected (lldb_private::Thread *thread);
+ void
+ ThreadWasSelected(lldb_private::Thread *thread) override;
- virtual lldb::RegisterContextSP
- CreateRegisterContextForThread (lldb_private::Thread *thread,
- lldb::addr_t reg_data_addr);
+ lldb::RegisterContextSP
+ CreateRegisterContextForThread(lldb_private::Thread *thread,
+ lldb::addr_t reg_data_addr) override;
- virtual lldb::StopInfoSP
- CreateThreadStopReason (lldb_private::Thread *thread);
+ lldb::StopInfoSP
+ CreateThreadStopReason(lldb_private::Thread *thread) override;
//------------------------------------------------------------------
// Method for lazy creation of threads on demand
//------------------------------------------------------------------
- virtual lldb::ThreadSP
- CreateThread (lldb::tid_t tid, lldb::addr_t context);
+ lldb::ThreadSP
+ CreateThread(lldb::tid_t tid, lldb::addr_t context) override;
protected:
-
bool IsValid() const
{
return m_python_object_sp && m_python_object_sp->IsValid();
@@ -107,5 +104,6 @@ protected:
lldb_private::StructuredData::ObjectSP m_python_object_sp;
};
-#endif // #ifndef liblldb_OperatingSystemPython_h_
-#endif // #ifndef LLDB_DISABLE_PYTHON
+#endif // LLDB_DISABLE_PYTHON
+
+#endif // liblldb_OperatingSystemPython_h_
diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
index 67156e6ae37b..d1bfc438a341 100644
--- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
+++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
@@ -22,6 +22,9 @@ namespace platform_freebsd {
class PlatformFreeBSD : public Platform
{
public:
+ PlatformFreeBSD(bool is_host);
+
+ ~PlatformFreeBSD() override;
//------------------------------------------------------------
// Class functions
@@ -42,14 +45,6 @@ namespace platform_freebsd {
GetDescriptionStatic (bool is_host);
//------------------------------------------------------------
- // Class Methods
- //------------------------------------------------------------
- PlatformFreeBSD (bool is_host);
-
- virtual
- ~PlatformFreeBSD();
-
- //------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
ConstString
@@ -179,4 +174,4 @@ namespace platform_freebsd {
} // namespace platform_freebsd
} // namespace lldb_private
-#endif // liblldb_PlatformFreeBSD_h_
+#endif // liblldb_PlatformFreeBSD_h_
diff --git a/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp b/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
new file mode 100644
index 000000000000..2979d1e438b7
--- /dev/null
+++ b/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
@@ -0,0 +1,685 @@
+//===-- PlatformNetBSD.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PlatformNetBSD.h"
+#include "lldb/Host/Config.h"
+
+// C Includes
+#include <stdio.h>
+#ifndef LLDB_DISABLE_POSIX
+#include <sys/utsname.h>
+#endif
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/BreakpointSite.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::platform_netbsd;
+
+PlatformSP
+PlatformNetBSD::CreateInstance(bool force, const ArchSpec *arch)
+{
+ // The only time we create an instance is when we are creating a remote
+ // netbsd platform
+ const bool is_host = false;
+
+ bool create = force;
+ if (create == false && arch && arch->IsValid())
+ {
+ const llvm::Triple &triple = arch->GetTriple();
+ switch (triple.getOS())
+ {
+ case llvm::Triple::NetBSD:
+ create = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+ if (create)
+ return PlatformSP(new PlatformNetBSD (is_host));
+ return PlatformSP();
+
+}
+
+ConstString
+PlatformNetBSD::GetPluginNameStatic(bool is_host)
+{
+ if (is_host)
+ {
+ static ConstString g_host_name(Platform::GetHostPlatformName ());
+ return g_host_name;
+ }
+ else
+ {
+ static ConstString g_remote_name("remote-netbsd");
+ return g_remote_name;
+ }
+}
+
+const char *
+PlatformNetBSD::GetDescriptionStatic (bool is_host)
+{
+ if (is_host)
+ return "Local NetBSD user platform plug-in.";
+ else
+ return "Remote NetBSD user platform plug-in.";
+}
+
+static uint32_t g_initialize_count = 0;
+
+void
+PlatformNetBSD::Initialize ()
+{
+ Platform::Initialize ();
+
+ if (g_initialize_count++ == 0)
+ {
+#if defined(__NetBSD__)
+ // Force a host flag to true for the default platform object.
+ PlatformSP default_platform_sp (new PlatformNetBSD(true));
+ default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
+ Platform::SetHostPlatform (default_platform_sp);
+#endif
+ PluginManager::RegisterPlugin(PlatformNetBSD::GetPluginNameStatic(false),
+ PlatformNetBSD::GetDescriptionStatic(false),
+ PlatformNetBSD::CreateInstance);
+ }
+}
+
+void
+PlatformNetBSD::Terminate ()
+{
+ if (g_initialize_count > 0 && --g_initialize_count == 0)
+ PluginManager::UnregisterPlugin (PlatformNetBSD::CreateInstance);
+
+ Platform::Terminate ();
+}
+
+bool
+PlatformNetBSD::GetModuleSpec (const FileSpec& module_file_spec,
+ const ArchSpec& arch,
+ ModuleSpec &module_spec)
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetModuleSpec (module_file_spec, arch, module_spec);
+
+ return Platform::GetModuleSpec (module_file_spec, arch, module_spec);
+}
+
+Error
+PlatformNetBSD::RunShellCommand(const char *command,
+ const FileSpec &working_dir,
+ int *status_ptr,
+ int *signo_ptr,
+ std::string *command_output,
+ uint32_t timeout_sec)
+{
+ if (IsHost())
+ return Host::RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
+ else
+ {
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->RunShellCommand(command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
+ else
+ return Error("unable to run a remote command without a platform");
+ }
+}
+
+Error
+PlatformNetBSD::ResolveExecutable (const ModuleSpec &module_spec,
+ lldb::ModuleSP &exe_module_sp,
+ const FileSpecList *module_search_paths_ptr)
+{
+ Error error;
+ // Nothing special to do here, just use the actual file and architecture
+
+ char exe_path[PATH_MAX];
+ ModuleSpec resolved_module_spec(module_spec);
+
+ if (IsHost())
+ {
+ // If we have "ls" as the module_spec's file, resolve the executable location based on
+ // the current path variables
+ if (!resolved_module_spec.GetFileSpec().Exists())
+ {
+ module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
+ resolved_module_spec.GetFileSpec().SetFile(exe_path, true);
+ }
+
+ if (!resolved_module_spec.GetFileSpec().Exists())
+ resolved_module_spec.GetFileSpec().ResolveExecutableLocation ();
+
+ if (resolved_module_spec.GetFileSpec().Exists())
+ error.Clear();
+ else
+ {
+ error.SetErrorStringWithFormat("unable to find executable for '%s'", resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ {
+ error = GetCachedExecutable (resolved_module_spec, exe_module_sp, module_search_paths_ptr, *m_remote_platform_sp);
+ }
+ else
+ {
+ // We may connect to a process and use the provided executable (Don't use local $PATH).
+
+ // Resolve any executable within a bundle on MacOSX
+ Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());
+
+ if (resolved_module_spec.GetFileSpec().Exists())
+ {
+ error.Clear();
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+ }
+ }
+
+ if (error.Success())
+ {
+ if (resolved_module_spec.GetArchitecture().IsValid())
+ {
+ error = ModuleList::GetSharedModule (resolved_module_spec,
+ exe_module_sp,
+ module_search_paths_ptr,
+ NULL,
+ NULL);
+
+ if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
+ {
+ exe_module_sp.reset();
+ error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
+ resolved_module_spec.GetArchitecture().GetArchitectureName());
+ }
+ }
+ else
+ {
+ // No valid architecture was specified, ask the platform for
+ // the architectures that we should be using (in the correct order)
+ // and see if we can find a match that way
+ StreamString arch_names;
+ for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, resolved_module_spec.GetArchitecture()); ++idx)
+ {
+ error = ModuleList::GetSharedModule (resolved_module_spec,
+ exe_module_sp,
+ module_search_paths_ptr,
+ NULL,
+ NULL);
+ // Did we find an executable using one of the
+ if (error.Success())
+ {
+ if (exe_module_sp && exe_module_sp->GetObjectFile())
+ break;
+ else
+ error.SetErrorToGenericError();
+ }
+
+ if (idx > 0)
+ arch_names.PutCString (", ");
+ arch_names.PutCString (resolved_module_spec.GetArchitecture().GetArchitectureName());
+ }
+
+ if (error.Fail() || !exe_module_sp)
+ {
+ if (resolved_module_spec.GetFileSpec().Readable())
+ {
+ error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+ resolved_module_spec.GetFileSpec().GetPath().c_str(),
+ GetPluginName().GetCString(),
+ arch_names.GetString().c_str());
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("'%s' is not readable", resolved_module_spec.GetFileSpec().GetPath().c_str());
+ }
+ }
+ }
+ }
+
+ return error;
+}
+
+// From PlatformMacOSX only
+Error
+PlatformNetBSD::GetFileWithUUID (const FileSpec &platform_file,
+ const UUID *uuid_ptr,
+ FileSpec &local_file)
+{
+ if (IsRemote())
+ {
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetFileWithUUID (platform_file, uuid_ptr, local_file);
+ }
+
+ // Default to the local case
+ local_file = platform_file;
+ return Error();
+}
+
+
+//------------------------------------------------------------------
+/// Default Constructor
+//------------------------------------------------------------------
+PlatformNetBSD::PlatformNetBSD (bool is_host) :
+ Platform(is_host),
+ m_remote_platform_sp()
+{
+}
+
+bool
+PlatformNetBSD::GetRemoteOSVersion ()
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetOSVersion (m_major_os_version,
+ m_minor_os_version,
+ m_update_os_version);
+ return false;
+}
+
+bool
+PlatformNetBSD::GetRemoteOSBuildString (std::string &s)
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetRemoteOSBuildString (s);
+ s.clear();
+ return false;
+}
+
+bool
+PlatformNetBSD::GetRemoteOSKernelDescription (std::string &s)
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetRemoteOSKernelDescription (s);
+ s.clear();
+ return false;
+}
+
+// Remote Platform subclasses need to override this function
+ArchSpec
+PlatformNetBSD::GetRemoteSystemArchitecture ()
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetRemoteSystemArchitecture ();
+ return ArchSpec();
+}
+
+
+const char *
+PlatformNetBSD::GetHostname ()
+{
+ if (IsHost())
+ return Platform::GetHostname();
+
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetHostname ();
+ return NULL;
+}
+
+bool
+PlatformNetBSD::IsConnected () const
+{
+ if (IsHost())
+ return true;
+ else if (m_remote_platform_sp)
+ return m_remote_platform_sp->IsConnected();
+ return false;
+}
+
+Error
+PlatformNetBSD::ConnectRemote (Args& args)
+{
+ Error error;
+ if (IsHost())
+ {
+ error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
+ }
+ else
+ {
+ if (!m_remote_platform_sp)
+ m_remote_platform_sp = Platform::Create (ConstString("remote-gdb-server"), error);
+
+ if (m_remote_platform_sp)
+ {
+ if (error.Success())
+ {
+ if (m_remote_platform_sp)
+ {
+ error = m_remote_platform_sp->ConnectRemote (args);
+ }
+ else
+ {
+ error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
+ }
+ }
+ }
+ else
+ error.SetErrorString ("failed to create a 'remote-gdb-server' platform");
+
+ if (error.Fail())
+ m_remote_platform_sp.reset();
+ }
+
+ return error;
+}
+
+Error
+PlatformNetBSD::DisconnectRemote ()
+{
+ Error error;
+
+ if (IsHost())
+ {
+ error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString());
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ error = m_remote_platform_sp->DisconnectRemote ();
+ else
+ error.SetErrorString ("the platform is not currently connected");
+ }
+ return error;
+}
+
+bool
+PlatformNetBSD::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
+{
+ bool success = false;
+ if (IsHost())
+ {
+ success = Platform::GetProcessInfo (pid, process_info);
+ }
+ else if (m_remote_platform_sp)
+ {
+ success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
+ }
+ return success;
+}
+
+uint32_t
+PlatformNetBSD::FindProcesses (const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &process_infos)
+{
+ uint32_t match_count = 0;
+ if (IsHost())
+ {
+ // Let the base class figure out the host details
+ match_count = Platform::FindProcesses (match_info, process_infos);
+ }
+ else
+ {
+ // If we are remote, we can only return results if we are connected
+ if (m_remote_platform_sp)
+ match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
+ }
+ return match_count;
+}
+
+const char *
+PlatformNetBSD::GetUserName (uint32_t uid)
+{
+ // Check the cache in Platform in case we have already looked this uid up
+ const char *user_name = Platform::GetUserName(uid);
+ if (user_name)
+ return user_name;
+
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->GetUserName(uid);
+ return NULL;
+}
+
+const char *
+PlatformNetBSD::GetGroupName (uint32_t gid)
+{
+ const char *group_name = Platform::GetGroupName(gid);
+ if (group_name)
+ return group_name;
+
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->GetGroupName(gid);
+ return NULL;
+}
+
+
+Error
+PlatformNetBSD::GetSharedModule (const ModuleSpec &module_spec,
+ Process* process,
+ ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr,
+ ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr)
+{
+ Error error;
+ module_sp.reset();
+
+ if (IsRemote())
+ {
+ // If we have a remote platform always, let it try and locate
+ // the shared module first.
+ if (m_remote_platform_sp)
+ {
+ error = m_remote_platform_sp->GetSharedModule (module_spec,
+ process,
+ module_sp,
+ module_search_paths_ptr,
+ old_module_sp_ptr,
+ did_create_ptr);
+ }
+ }
+
+ if (!module_sp)
+ {
+ // Fall back to the local platform and find the file locally
+ error = Platform::GetSharedModule (module_spec,
+ process,
+ module_sp,
+ module_search_paths_ptr,
+ old_module_sp_ptr,
+ did_create_ptr);
+ }
+ if (module_sp)
+ module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
+ return error;
+}
+
+
+bool
+PlatformNetBSD::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
+{
+ if (IsHost())
+ {
+ ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
+ if (hostArch.GetTriple().isOSNetBSD())
+ {
+ if (idx == 0)
+ {
+ arch = hostArch;
+ return arch.IsValid();
+ }
+ else if (idx == 1)
+ {
+ // If the default host architecture is 64-bit, look for a 32-bit variant
+ if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit())
+ {
+ arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
+ return arch.IsValid();
+ }
+ }
+ }
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch);
+
+ llvm::Triple triple;
+ // Set the OS to NetBSD
+ triple.setOS(llvm::Triple::NetBSD);
+ // Set the architecture
+ switch (idx)
+ {
+ case 0: triple.setArchName("x86_64"); break;
+ case 1: triple.setArchName("i386"); break;
+ default: return false;
+ }
+ // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the vendor by
+ // calling triple.SetVendorName("unknown") so that it is a "unspecified unknown".
+ // This means when someone calls triple.GetVendorName() it will return an empty string
+ // which indicates that the vendor can be set when two architectures are merged
+
+ // Now set the triple into "arch" and return true
+ arch.SetTriple(triple);
+ return true;
+ }
+ return false;
+}
+
+void
+PlatformNetBSD::GetStatus (Stream &strm)
+{
+#ifndef LLDB_DISABLE_POSIX
+ struct ::utsname un;
+
+ strm << " Host: ";
+
+ ::memset(&un, 0, sizeof(utsname));
+ if (::uname(&un) == -1) {
+ strm << "NetBSD" << '\n';
+ } else {
+ strm << un.sysname << ' ' << un.release;
+ if (un.nodename[0] != '\0')
+ strm << " (" << un.nodename << ')';
+ strm << '\n';
+
+ // Dump a common information about the platform status.
+ strm << "Host: " << un.sysname << ' ' << un.release << ' ' << un.version << '\n';
+ }
+#endif
+
+ Platform::GetStatus(strm);
+}
+
+size_t
+PlatformNetBSD::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
+{
+ ArchSpec arch = target.GetArchitecture();
+ const uint8_t *trap_opcode = NULL;
+ size_t trap_opcode_size = 0;
+
+ switch (arch.GetMachine())
+ {
+ default:
+ assert(false && "Unhandled architecture in PlatformNetBSD::GetSoftwareBreakpointTrapOpcode()");
+ break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ {
+ static const uint8_t g_i386_opcode[] = { 0xCC };
+ trap_opcode = g_i386_opcode;
+ trap_opcode_size = sizeof(g_i386_opcode);
+ }
+ break;
+ }
+
+ if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
+ return trap_opcode_size;
+ return 0;
+}
+
+
+void
+PlatformNetBSD::CalculateTrapHandlerSymbolNames ()
+{
+ m_trap_handlers.push_back (ConstString ("_sigtramp"));
+}
+
+Error
+PlatformNetBSD::LaunchProcess (ProcessLaunchInfo &launch_info)
+{
+ Error error;
+ if (IsHost())
+ {
+ error = Platform::LaunchProcess (launch_info);
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ error = m_remote_platform_sp->LaunchProcess (launch_info);
+ else
+ error.SetErrorString ("the platform is not currently connected");
+ }
+ return error;
+}
+
+lldb::ProcessSP
+PlatformNetBSD::Attach(ProcessAttachInfo &attach_info,
+ Debugger &debugger,
+ Target *target,
+ Error &error)
+{
+ lldb::ProcessSP process_sp;
+ if (IsHost())
+ {
+ if (target == NULL)
+ {
+ TargetSP new_target_sp;
+ ArchSpec emptyArchSpec;
+
+ error = debugger.GetTargetList().CreateTarget (debugger,
+ NULL,
+ emptyArchSpec,
+ false,
+ m_remote_platform_sp,
+ new_target_sp);
+ target = new_target_sp.get();
+ }
+ else
+ error.Clear();
+
+ if (target && error.Success())
+ {
+ debugger.GetTargetList().SetSelectedTarget(target);
+ // The netbsd always currently uses the GDB remote debugger plug-in
+ // so even when debugging locally we are debugging remotely!
+ // Just like the darwin plugin.
+ process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
+
+ if (process_sp)
+ error = process_sp->Attach (attach_info);
+ }
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, error);
+ else
+ error.SetErrorString ("the platform is not currently connected");
+ }
+ return process_sp;
+}
diff --git a/source/Plugins/Platform/NetBSD/PlatformNetBSD.h b/source/Plugins/Platform/NetBSD/PlatformNetBSD.h
new file mode 100644
index 000000000000..b0187be99b05
--- /dev/null
+++ b/source/Plugins/Platform/NetBSD/PlatformNetBSD.h
@@ -0,0 +1,177 @@
+//===-- PlatformNetBSD.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_PlatformNetBSD_h_
+#define liblldb_PlatformNetBSD_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/Platform.h"
+
+namespace lldb_private {
+namespace platform_netbsd {
+
+ class PlatformNetBSD : public Platform
+ {
+ public:
+ PlatformNetBSD (bool is_host);
+
+ ~PlatformNetBSD() override = default;
+
+ //------------------------------------------------------------
+ // Class functions
+ //------------------------------------------------------------
+ static lldb::PlatformSP
+ CreateInstance(bool force, const ArchSpec *arch);
+
+ static void
+ Initialize ();
+
+ static void
+ Terminate ();
+
+ static ConstString
+ GetPluginNameStatic (bool is_host);
+
+ static const char *
+ GetDescriptionStatic (bool is_host);
+
+ //------------------------------------------------------------
+ // lldb_private::PluginInterface functions
+ //------------------------------------------------------------
+ ConstString
+ GetPluginName() override
+ {
+ return GetPluginNameStatic (IsHost());
+ }
+
+ uint32_t
+ GetPluginVersion() override
+ {
+ return 1;
+ }
+
+ const char *
+ GetDescription () override
+ {
+ return GetDescriptionStatic(IsHost());
+ }
+
+ //------------------------------------------------------------
+ // lldb_private::Platform functions
+ //------------------------------------------------------------
+ bool
+ GetModuleSpec(const FileSpec& module_file_spec,
+ const ArchSpec& arch,
+ ModuleSpec &module_spec) override;
+
+ Error
+ RunShellCommand(const char *command,
+ const FileSpec &working_dir,
+ int *status_ptr,
+ int *signo_ptr,
+ std::string *command_output,
+ uint32_t timeout_sec) override;
+
+ Error
+ ResolveExecutable(const ModuleSpec &module_spec,
+ lldb::ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr) override;
+
+ size_t
+ GetSoftwareBreakpointTrapOpcode(Target &target,
+ BreakpointSite *bp_site) override;
+
+ bool
+ GetRemoteOSVersion () override;
+
+ bool
+ GetRemoteOSBuildString (std::string &s) override;
+
+ bool
+ GetRemoteOSKernelDescription (std::string &s) override;
+
+ // Remote Platform subclasses need to override this function
+ ArchSpec
+ GetRemoteSystemArchitecture() override;
+
+ bool
+ IsConnected () const override;
+
+ Error
+ ConnectRemote(Args& args) override;
+
+ Error
+ DisconnectRemote() override;
+
+ const char *
+ GetHostname () override;
+
+ const char *
+ GetUserName (uint32_t uid) override;
+
+ const char *
+ GetGroupName (uint32_t gid) override;
+
+ bool
+ GetProcessInfo(lldb::pid_t pid,
+ ProcessInstanceInfo &proc_info) override;
+
+ uint32_t
+ FindProcesses(const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &process_infos) override;
+
+ Error
+ LaunchProcess(ProcessLaunchInfo &launch_info) override;
+
+ lldb::ProcessSP
+ Attach(ProcessAttachInfo &attach_info,
+ Debugger &debugger,
+ Target *target,
+ Error &error) override;
+
+ // NetBSD processes can not be launched by spawning and attaching.
+ bool
+ CanDebugProcess () override { return false; }
+
+ // Only on PlatformMacOSX:
+ Error
+ GetFileWithUUID(const FileSpec &platform_file,
+ const UUID* uuid, FileSpec &local_file) override;
+
+ Error
+ GetSharedModule(const ModuleSpec &module_spec,
+ Process* process,
+ lldb::ModuleSP &module_sp,
+ const FileSpecList *module_search_paths_ptr,
+ lldb::ModuleSP *old_module_sp_ptr,
+ bool *did_create_ptr) override;
+
+ bool
+ GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) override;
+
+ void
+ GetStatus(Stream &strm) override;
+
+ void
+ CalculateTrapHandlerSymbolNames () override;
+
+ protected:
+ lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote netbsd OS
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN (PlatformNetBSD);
+ };
+
+} // namespace platform_netbsd
+} // namespace lldb_private
+
+#endif // liblldb_PlatformNetBSD_h_
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index b4f841a16dec..c7564655a11b 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -19,13 +19,18 @@
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Expression/UserExpression.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileCache.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/ProcessLaunchInfo.h"
+#include "lldb/Target/Thread.h"
using namespace lldb;
using namespace lldb_private;
@@ -673,9 +678,12 @@ PlatformPOSIX::ConnectRemote (Args& args)
if (m_options.get())
{
OptionGroupOptions* options = m_options.get();
- const OptionGroupPlatformRSync* m_rsync_options = (OptionGroupPlatformRSync*)options->GetGroupWithOption('r');
- const OptionGroupPlatformSSH* m_ssh_options = (OptionGroupPlatformSSH*)options->GetGroupWithOption('s');
- const OptionGroupPlatformCaching* m_cache_options = (OptionGroupPlatformCaching*)options->GetGroupWithOption('c');
+ const OptionGroupPlatformRSync *m_rsync_options =
+ static_cast<const OptionGroupPlatformRSync *>(options->GetGroupWithOption('r'));
+ const OptionGroupPlatformSSH *m_ssh_options =
+ static_cast<const OptionGroupPlatformSSH *>(options->GetGroupWithOption('s'));
+ const OptionGroupPlatformCaching *m_cache_options =
+ static_cast<const OptionGroupPlatformCaching *>(options->GetGroupWithOption('c'));
if (m_rsync_options->m_rsync)
{
@@ -843,6 +851,175 @@ PlatformPOSIX::DebugProcess (ProcessLaunchInfo &launch_info,
void
PlatformPOSIX::CalculateTrapHandlerSymbolNames ()
-{
+{
m_trap_handlers.push_back (ConstString ("_sigtramp"));
+}
+
+Error
+PlatformPOSIX::EvaluateLibdlExpression(lldb_private::Process* process,
+ const char* expr_cstr,
+ const char* expr_prefix,
+ lldb::ValueObjectSP& result_valobj_sp)
+{
+ DynamicLoader *loader = process->GetDynamicLoader();
+ if (loader)
+ {
+ Error error = loader->CanLoadImage();
+ if (error.Fail())
+ return error;
+ }
+
+ ThreadSP thread_sp(process->GetThreadList().GetSelectedThread());
+ if (!thread_sp)
+ return Error("Selected thread isn't valid");
+
+ StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0));
+ if (!frame_sp)
+ return Error("Frame 0 isn't valid");
+
+ ExecutionContext exe_ctx;
+ frame_sp->CalculateExecutionContext(exe_ctx);
+ EvaluateExpressionOptions expr_options;
+ expr_options.SetUnwindOnError(true);
+ expr_options.SetIgnoreBreakpoints(true);
+ expr_options.SetExecutionPolicy(eExecutionPolicyAlways);
+ expr_options.SetLanguage(eLanguageTypeC_plus_plus);
+
+ Error expr_error;
+ UserExpression::Evaluate(exe_ctx,
+ expr_options,
+ expr_cstr,
+ expr_prefix,
+ result_valobj_sp,
+ expr_error);
+ if (result_valobj_sp->GetError().Fail())
+ return result_valobj_sp->GetError();
+ return Error();
+}
+
+uint32_t
+PlatformPOSIX::DoLoadImage(lldb_private::Process* process,
+ const lldb_private::FileSpec& remote_file,
+ lldb_private::Error& error)
+{
+ char path[PATH_MAX];
+ remote_file.GetPath(path, sizeof(path));
+
+ StreamString expr;
+ expr.Printf(R"(
+ struct __lldb_dlopen_result { void *image_ptr; const char *error_str; } the_result;
+ the_result.image_ptr = dlopen ("%s", 2);
+ if (the_result.image_ptr == (void *) 0x0)
+ {
+ the_result.error_str = dlerror();
+ }
+ else
+ {
+ the_result.error_str = (const char *) 0x0;
+ }
+ the_result;
+ )",
+ path);
+ const char *prefix = GetLibdlFunctionDeclarations();
+ lldb::ValueObjectSP result_valobj_sp;
+ error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp);
+ if (error.Fail())
+ return LLDB_INVALID_IMAGE_TOKEN;
+
+ error = result_valobj_sp->GetError();
+ if (error.Fail())
+ return LLDB_INVALID_IMAGE_TOKEN;
+
+ Scalar scalar;
+ ValueObjectSP image_ptr_sp = result_valobj_sp->GetChildAtIndex(0, true);
+ if (!image_ptr_sp || !image_ptr_sp->ResolveValue(scalar))
+ {
+ error.SetErrorStringWithFormat("unable to load '%s'", path);
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+
+ addr_t image_ptr = scalar.ULongLong(LLDB_INVALID_ADDRESS);
+ if (image_ptr != 0 && image_ptr != LLDB_INVALID_ADDRESS)
+ return process->AddImageToken(image_ptr);
+
+ if (image_ptr == 0)
+ {
+ ValueObjectSP error_str_sp = result_valobj_sp->GetChildAtIndex(1, true);
+ if (error_str_sp && error_str_sp->IsCStringContainer(true))
+ {
+ DataBufferSP buffer_sp(new DataBufferHeap(10240,0));
+ size_t num_chars = error_str_sp->ReadPointedString (buffer_sp, error, 10240).first;
+ if (error.Success() && num_chars > 0)
+ error.SetErrorStringWithFormat("dlopen error: %s", buffer_sp->GetBytes());
+ else
+ error.SetErrorStringWithFormat("dlopen failed for unknown reasons.");
+ return LLDB_INVALID_IMAGE_TOKEN;
+ }
+ }
+ error.SetErrorStringWithFormat("unable to load '%s'", path);
+ return LLDB_INVALID_IMAGE_TOKEN;
+}
+
+Error
+PlatformPOSIX::UnloadImage (lldb_private::Process* process, uint32_t image_token)
+{
+ const addr_t image_addr = process->GetImagePtrFromToken(image_token);
+ if (image_addr == LLDB_INVALID_ADDRESS)
+ return Error("Invalid image token");
+
+ StreamString expr;
+ expr.Printf("dlclose((void *)0x%" PRIx64 ")", image_addr);
+ const char *prefix = GetLibdlFunctionDeclarations();
+ lldb::ValueObjectSP result_valobj_sp;
+ Error error = EvaluateLibdlExpression(process, expr.GetData(), prefix, result_valobj_sp);
+ if (error.Fail())
+ return error;
+
+ if (result_valobj_sp->GetError().Fail())
+ return result_valobj_sp->GetError();
+
+ Scalar scalar;
+ if (result_valobj_sp->ResolveValue(scalar))
+ {
+ if (scalar.UInt(1))
+ return Error("expression failed: \"%s\"", expr.GetData());
+ process->ResetImageToken(image_token);
+ }
+ return Error();
}
+
+lldb::ProcessSP
+PlatformPOSIX::ConnectProcess (const char* connect_url,
+ const char* plugin_name,
+ lldb_private::Debugger &debugger,
+ lldb_private::Target *target,
+ lldb_private::Error &error)
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->ConnectProcess(connect_url,
+ plugin_name,
+ debugger,
+ target,
+ error);
+
+ return Platform::ConnectProcess(connect_url, plugin_name, debugger, target, error);
+}
+
+const char*
+PlatformPOSIX::GetLibdlFunctionDeclarations() const
+{
+ return R"(
+ extern "C" void* dlopen(const char*, int);
+ extern "C" void* dlsym(void*, const char*);
+ extern "C" int dlclose(void*);
+ extern "C" char* dlerror(void);
+ )";
+}
+
+size_t
+PlatformPOSIX::ConnectToWaitingProcesses(Debugger& debugger, Error& error)
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->ConnectToWaitingProcesses(debugger, error);
+ return Platform::ConnectToWaitingProcesses(debugger, error);
+}
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
index 82686dcef6b0..60f6207d140b 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.h
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
@@ -12,7 +12,6 @@
// C Includes
// C++ Includes
-
#include <memory>
// Other libraries and framework includes
@@ -23,11 +22,10 @@
class PlatformPOSIX : public lldb_private::Platform
{
public:
- PlatformPOSIX (bool is_host);
-
- virtual
- ~PlatformPOSIX();
-
+ PlatformPOSIX(bool is_host);
+
+ ~PlatformPOSIX() override;
+
//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
@@ -37,9 +35,8 @@ public:
const lldb_private::ArchSpec& arch,
lldb_private::ModuleSpec &module_spec) override;
- lldb_private::OptionGroupOptions
- *GetConnectionOptions(
- lldb_private::CommandInterpreter &interpreter) override;
+ lldb_private::OptionGroupOptions*
+ GetConnectionOptions(lldb_private::CommandInterpreter &interpreter) override;
const char *
GetHostname () override;
@@ -119,11 +116,11 @@ public:
IsConnected () const override;
lldb_private::Error
- RunShellCommand(const char *command, // Shouldn't be NULL
+ RunShellCommand(const char *command, // Shouldn't be nullptr
const lldb_private::FileSpec &working_dir, // Pass empty FileSpec to use the current working directory
- int *status_ptr, // Pass NULL if you don't want the process exit status
- int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
- std::string *command_output, // Pass NULL if you don't want the command output
+ int *status_ptr, // Pass nullptr if you don't want the process exit status
+ int *signo_ptr, // Pass nullptr if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass nullptr if you don't want the command output
uint32_t timeout_sec) override; // Timeout in seconds to wait for shell program to finish
lldb_private::Error
@@ -150,13 +147,13 @@ public:
lldb::ProcessSP
Attach (lldb_private::ProcessAttachInfo &attach_info,
lldb_private::Debugger &debugger,
- lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one
+ lldb_private::Target *target, // Can be nullptr, if nullptr create a new target, else use existing one
lldb_private::Error &error) override;
lldb::ProcessSP
DebugProcess (lldb_private::ProcessLaunchInfo &launch_info,
lldb_private::Debugger &debugger,
- lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one
+ lldb_private::Target *target, // Can be nullptr, if nullptr create a new target, else use existing one
lldb_private::Error &error) override;
std::string
@@ -176,14 +173,39 @@ public:
lldb_private::Error
DisconnectRemote () override;
+ uint32_t
+ DoLoadImage (lldb_private::Process* process,
+ const lldb_private::FileSpec& remote_file,
+ lldb_private::Error& error) override;
+
+ lldb_private::Error
+ UnloadImage (lldb_private::Process* process, uint32_t image_token) override;
+
+ lldb::ProcessSP
+ ConnectProcess (const char* connect_url,
+ const char* plugin_name,
+ lldb_private::Debugger &debugger,
+ lldb_private::Target *target,
+ lldb_private::Error &error) override;
+
+ size_t
+ ConnectToWaitingProcesses(lldb_private::Debugger& debugger, lldb_private::Error& error) override;
+
protected:
std::unique_ptr<lldb_private::OptionGroupOptions> m_options;
-
lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote POSIX-compliant OS
-
+
+ lldb_private::Error
+ EvaluateLibdlExpression(lldb_private::Process* process,
+ const char *expr_cstr,
+ const char *expr_prefix,
+ lldb::ValueObjectSP& result_valobj_sp);
+
+ virtual const char*
+ GetLibdlFunctionDeclarations() const;
+
private:
DISALLOW_COPY_AND_ASSIGN (PlatformPOSIX);
-
};
-#endif // liblldb_PlatformPOSIX_h_
+#endif // liblldb_PlatformPOSIX_h_
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index b0e75d4f3457..f16ea017676f 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -21,6 +21,7 @@
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/FileSpec.h"
@@ -40,23 +41,6 @@ using namespace lldb_private::platform_gdb_server;
static bool g_initialized = false;
-static std::string MakeGdbServerUrl(
- const std::string &platform_scheme,
- const std::string &platform_hostname,
- uint16_t port)
-{
- const char *override_scheme = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_SCHEME");
- const char *override_hostname = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME");
- const char *port_offset_c_str = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET");
- int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0;
- StreamString result;
- result.Printf("%s://%s:%u",
- override_scheme ? override_scheme : platform_scheme.c_str(),
- override_hostname ? override_hostname : platform_hostname.c_str(),
- port + port_offset);
- return result.GetString();
-}
-
void
PlatformRemoteGDBServer::Initialize ()
{
@@ -590,9 +574,8 @@ PlatformRemoteGDBServer::DebugProcess (ProcessLaunchInfo &launch_info,
if (IsConnected())
{
lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
- uint16_t port = LaunchGDBserverAndGetPort(debugserver_pid);
-
- if (port == 0)
+ std::string connect_url;
+ if (!LaunchGDBServer(debugserver_pid, connect_url))
{
error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ());
}
@@ -623,8 +606,6 @@ PlatformRemoteGDBServer::DebugProcess (ProcessLaunchInfo &launch_info,
if (process_sp)
{
- std::string connect_url =
- MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, port);
error = process_sp->ConnectRemote (nullptr, connect_url.c_str());
// Retry the connect remote one time...
if (error.Fail())
@@ -649,23 +630,36 @@ PlatformRemoteGDBServer::DebugProcess (ProcessLaunchInfo &launch_info,
}
-uint16_t
-PlatformRemoteGDBServer::LaunchGDBserverAndGetPort (lldb::pid_t &pid)
+bool
+PlatformRemoteGDBServer::LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url)
{
ArchSpec remote_arch = GetRemoteSystemArchitecture ();
llvm::Triple &remote_triple = remote_arch.GetTriple ();
+
+ uint16_t port = 0;
+ std::string socket_name;
+ bool launch_result = false;
if (remote_triple.getVendor () == llvm::Triple::Apple && remote_triple.getOS () == llvm::Triple::IOS)
{
// When remote debugging to iOS, we use a USB mux that always talks
// to localhost, so we will need the remote debugserver to accept connections
// only from localhost, no matter what our current hostname is
- return m_gdb_client.LaunchGDBserverAndGetPort (pid, "127.0.0.1");
+ launch_result = m_gdb_client.LaunchGDBServer ("127.0.0.1", pid, port, socket_name);
}
else
{
// All other hosts should use their actual hostname
- return m_gdb_client.LaunchGDBserverAndGetPort (pid, NULL);
+ launch_result = m_gdb_client.LaunchGDBServer (nullptr, pid, port, socket_name);
}
+
+ if (!launch_result)
+ return false;
+
+ connect_url = MakeGdbServerUrl(m_platform_scheme,
+ m_platform_hostname,
+ port,
+ (socket_name.empty()) ? nullptr : socket_name.c_str());
+ return true;
}
bool
@@ -686,9 +680,8 @@ PlatformRemoteGDBServer::Attach (ProcessAttachInfo &attach_info,
if (IsConnected())
{
lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
- uint16_t port = LaunchGDBserverAndGetPort(debugserver_pid);
-
- if (port == 0)
+ std::string connect_url;
+ if (!LaunchGDBServer(debugserver_pid, connect_url))
{
error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ());
}
@@ -716,11 +709,8 @@ PlatformRemoteGDBServer::Attach (ProcessAttachInfo &attach_info,
// The darwin always currently uses the GDB remote debugger plug-in
// so even when debugging locally we are debugging remotely!
process_sp = target->CreateProcess (attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
-
if (process_sp)
{
- std::string connect_url =
- MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, port);
error = process_sp->ConnectRemote(nullptr, connect_url.c_str());
if (error.Success())
{
@@ -931,13 +921,8 @@ PlatformRemoteGDBServer::GetRemoteUnixSignals()
return false;
// We can live without short_name, description, etc.
- std::string short_name{""};
- auto object_sp = dict->GetValueForKey("short_name");
- if (object_sp && object_sp->IsValid())
- short_name = object_sp->GetStringValue();
-
bool suppress{false};
- object_sp = dict->GetValueForKey("suppress");
+ auto object_sp = dict->GetValueForKey("suppress");
if (object_sp && object_sp->IsValid())
suppress = object_sp->GetBooleanValue();
@@ -958,7 +943,6 @@ PlatformRemoteGDBServer::GetRemoteUnixSignals()
remote_signals_sp->AddSignal(signo,
name.c_str(),
- short_name.c_str(),
suppress, stop, notify,
description.c_str());
return true;
@@ -969,3 +953,66 @@ PlatformRemoteGDBServer::GetRemoteUnixSignals()
return m_remote_signals_sp;
}
+
+std::string
+PlatformRemoteGDBServer::MakeGdbServerUrl(const std::string &platform_scheme,
+ const std::string &platform_hostname,
+ uint16_t port,
+ const char* socket_name)
+{
+ const char *override_scheme = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_SCHEME");
+ const char *override_hostname = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME");
+ const char *port_offset_c_str = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET");
+ int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0;
+
+ return MakeUrl(override_scheme ? override_scheme : platform_scheme.c_str(),
+ override_hostname ? override_hostname : platform_hostname.c_str(),
+ port + port_offset,
+ socket_name);
+}
+
+std::string
+PlatformRemoteGDBServer::MakeUrl(const char* scheme,
+ const char* hostname,
+ uint16_t port,
+ const char* path)
+{
+ StreamString result;
+ result.Printf("%s://%s", scheme, hostname);
+ if (port != 0)
+ result.Printf(":%u", port);
+ if (path)
+ result.Write(path, strlen(path));
+ return result.GetString();
+}
+
+lldb::ProcessSP
+PlatformRemoteGDBServer::ConnectProcess(const char* connect_url,
+ const char* plugin_name,
+ lldb_private::Debugger &debugger,
+ lldb_private::Target *target,
+ lldb_private::Error &error)
+{
+ if (!IsRemote() || !IsConnected())
+ {
+ error.SetErrorString("Not connected to remote gdb server");
+ return nullptr;
+ }
+ return Platform::ConnectProcess(connect_url, plugin_name, debugger, target, error);
+}
+
+size_t
+PlatformRemoteGDBServer::GetPendingGdbServerList(std::vector<std::string>& connection_urls)
+{
+ std::vector<std::pair<uint16_t, std::string>> remote_servers;
+ m_gdb_client.QueryGDBServer(remote_servers);
+ for (const auto& gdbserver : remote_servers)
+ {
+ const char* socket_name_cstr = gdbserver.second.empty() ? nullptr : gdbserver.second.c_str();
+ connection_urls.emplace_back(MakeGdbServerUrl(m_platform_scheme,
+ m_platform_hostname,
+ gdbserver.first,
+ socket_name_cstr));
+ }
+ return connection_urls.size();
+}
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
index 0bf013fdfb68..61136f1185e6 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
@@ -217,6 +217,16 @@ public:
const lldb::UnixSignalsSP &
GetRemoteUnixSignals() override;
+ lldb::ProcessSP
+ ConnectProcess (const char* connect_url,
+ const char* plugin_name,
+ lldb_private::Debugger &debugger,
+ lldb_private::Target *target,
+ lldb_private::Error &error) override;
+
+ virtual size_t
+ GetPendingGdbServerList(std::vector<std::string>& connection_urls);
+
protected:
process_gdb_remote::GDBRemoteCommunicationClient m_gdb_client;
std::string m_platform_description; // After we connect we can get a more complete description of what we are connected to
@@ -225,16 +235,29 @@ protected:
lldb::UnixSignalsSP m_remote_signals_sp;
- // Launch the lldb-gdbserver on the remote host and return the port it is listening on or 0 on
- // failure. Subclasses should override this method if they want to do extra actions before or
- // after launching the lldb-gdbserver.
- virtual uint16_t
- LaunchGDBserverAndGetPort (lldb::pid_t &pid);
+ // Launch the debug server on the remote host - caller connects to launched
+ // debug server using connect_url.
+ // Subclasses should override this method if they want to do extra actions before or
+ // after launching the debug server.
+ virtual bool
+ LaunchGDBServer (lldb::pid_t &pid, std::string &connect_url);
virtual bool
KillSpawnedProcess (lldb::pid_t pid);
+ virtual std::string
+ MakeUrl(const char* scheme,
+ const char* hostname,
+ uint16_t port,
+ const char* path);
+
private:
+ std::string
+ MakeGdbServerUrl(const std::string &platform_scheme,
+ const std::string &platform_hostname,
+ uint16_t port,
+ const char* socket_name);
+
DISALLOW_COPY_AND_ASSIGN (PlatformRemoteGDBServer);
};
diff --git a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
index 5e46c836beac..2b292442399f 100644
--- a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
+++ b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
@@ -8,33 +8,288 @@
//===----------------------------------------------------------------------===//
// C Includes
+#include <errno.h>
+
// C++ Includes
// Other libraries and framework includes
#include "lldb/Core/State.h"
#include "lldb/Target/UnixSignals.h"
// Project includes
+#include "lldb/Breakpoint/Watchpoint.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/State.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/HostNativeThread.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadSpec.h"
+#include "llvm/ADT/SmallString.h"
+#include "POSIXStopInfo.h"
#include "FreeBSDThread.h"
#include "ProcessFreeBSD.h"
#include "ProcessPOSIXLog.h"
+#include "ProcessMonitor.h"
+#include "RegisterContextPOSIXProcessMonitor_arm.h"
+#include "RegisterContextPOSIXProcessMonitor_arm64.h"
+#include "RegisterContextPOSIXProcessMonitor_mips64.h"
+#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
+#include "RegisterContextPOSIXProcessMonitor_x86.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
+#include "Plugins/Process/Utility/UnwindLLDB.h"
using namespace lldb;
using namespace lldb_private;
-//------------------------------------------------------------------------------
-// Constructors and destructors.
-
FreeBSDThread::FreeBSDThread(Process &process, lldb::tid_t tid)
- : POSIXThread(process, tid)
+ : Thread(process, tid),
+ m_frame_ap (),
+ m_breakpoint (),
+ m_thread_name_valid (false),
+ m_thread_name (),
+ m_posix_thread(NULL)
{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("FreeBSDThread::%s (tid = %" PRIi64 ")", __FUNCTION__, tid);
+
+ // Set the current watchpoints for this thread.
+ Target &target = GetProcess()->GetTarget();
+ const WatchpointList &wp_list = target.GetWatchpointList();
+ size_t wp_size = wp_list.GetSize();
+
+ for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++)
+ {
+ lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx);
+ if (wp.get() && wp->IsEnabled())
+ {
+ // This watchpoint as been enabled; obviously this "new" thread
+ // has been created since that watchpoint was enabled. Since
+ // the POSIXBreakpointProtocol has yet to be initialized, its
+ // m_watchpoints_initialized member will be FALSE. Attempting to
+ // read the debug status register to determine if a watchpoint
+ // has been hit would result in the zeroing of that register.
+ // Since the active debug registers would have been cloned when
+ // this thread was created, simply force the m_watchpoints_initized
+ // member to TRUE and avoid resetting dr6 and dr7.
+ GetPOSIXBreakpointProtocol()->ForceWatchpointsInitialized();
+ }
+ }
}
FreeBSDThread::~FreeBSDThread()
{
+ DestroyThread();
+}
+
+ProcessMonitor &
+FreeBSDThread::GetMonitor()
+{
+ ProcessSP base = GetProcess();
+ ProcessFreeBSD &process = static_cast<ProcessFreeBSD&>(*base);
+ return process.GetMonitor();
+}
+
+void
+FreeBSDThread::RefreshStateAfterStop()
+{
+ // Invalidate all registers in our register context. We don't set "force" to
+ // true because the stop reply packet might have had some register values
+ // that were expedited and these will already be copied into the register
+ // context by the time this function gets called. The KDPRegisterContext
+ // class has been made smart enough to detect when it needs to invalidate
+ // which registers are valid by putting hooks in the register read and
+ // register supply functions where they check the process stop ID and do
+ // the right thing.
+ //if (StateIsStoppedState(GetState())
+ {
+ const bool force = false;
+ GetRegisterContext()->InvalidateIfNeeded (force);
+ }
}
-//------------------------------------------------------------------------------
-// ProcessInterface protocol.
+const char *
+FreeBSDThread::GetInfo()
+{
+ return NULL;
+}
+
+void
+FreeBSDThread::SetName (const char *name)
+{
+ m_thread_name_valid = (name && name[0]);
+ if (m_thread_name_valid)
+ m_thread_name.assign (name);
+ else
+ m_thread_name.clear();
+}
+
+const char *
+FreeBSDThread::GetName ()
+{
+ if (!m_thread_name_valid)
+ {
+ llvm::SmallString<32> thread_name;
+ HostNativeThread::GetName(GetID(), thread_name);
+ m_thread_name = thread_name.c_str();
+ m_thread_name_valid = true;
+ }
+
+ if (m_thread_name.empty())
+ return NULL;
+ return m_thread_name.c_str();
+}
+
+lldb::RegisterContextSP
+FreeBSDThread::GetRegisterContext()
+{
+ if (!m_reg_context_sp)
+ {
+ m_posix_thread = NULL;
+
+ RegisterInfoInterface *reg_interface = NULL;
+ const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture();
+
+ assert(target_arch.GetTriple().getOS() == llvm::Triple::FreeBSD);
+ switch (target_arch.GetMachine())
+ {
+ case llvm::Triple::aarch64:
+ reg_interface = new RegisterContextFreeBSD_arm64(target_arch);
+ break;
+ case llvm::Triple::arm:
+ reg_interface = new RegisterContextFreeBSD_arm(target_arch);
+ break;
+ case llvm::Triple::ppc:
+#ifndef __powerpc64__
+ reg_interface = new RegisterContextFreeBSD_powerpc32(target_arch);
+ break;
+#endif
+ case llvm::Triple::ppc64:
+ reg_interface = new RegisterContextFreeBSD_powerpc64(target_arch);
+ break;
+ case llvm::Triple::mips64:
+ reg_interface = new RegisterContextFreeBSD_mips64(target_arch);
+ break;
+ case llvm::Triple::x86:
+ reg_interface = new RegisterContextFreeBSD_i386(target_arch);
+ break;
+ case llvm::Triple::x86_64:
+ reg_interface = new RegisterContextFreeBSD_x86_64(target_arch);
+ break;
+ default:
+ llvm_unreachable("CPU not supported");
+ }
+
+ switch (target_arch.GetMachine())
+ {
+ case llvm::Triple::aarch64:
+ {
+ RegisterContextPOSIXProcessMonitor_arm64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm64(*this, 0, reg_interface);
+ m_posix_thread = reg_ctx;
+ m_reg_context_sp.reset(reg_ctx);
+ break;
+ }
+ case llvm::Triple::arm:
+ {
+ RegisterContextPOSIXProcessMonitor_arm *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm(*this, 0, reg_interface);
+ m_posix_thread = reg_ctx;
+ m_reg_context_sp.reset(reg_ctx);
+ break;
+ }
+ case llvm::Triple::mips64:
+ {
+ RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface);
+ m_posix_thread = reg_ctx;
+ m_reg_context_sp.reset(reg_ctx);
+ break;
+ }
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ {
+ RegisterContextPOSIXProcessMonitor_powerpc *reg_ctx = new RegisterContextPOSIXProcessMonitor_powerpc(*this, 0, reg_interface);
+ m_posix_thread = reg_ctx;
+ m_reg_context_sp.reset(reg_ctx);
+ break;
+ }
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ {
+ RegisterContextPOSIXProcessMonitor_x86_64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_x86_64(*this, 0, reg_interface);
+ m_posix_thread = reg_ctx;
+ m_reg_context_sp.reset(reg_ctx);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return m_reg_context_sp;
+}
+
+lldb::RegisterContextSP
+FreeBSDThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)
+{
+ lldb::RegisterContextSP reg_ctx_sp;
+ uint32_t concrete_frame_idx = 0;
+
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("FreeBSDThread::%s ()", __FUNCTION__);
+
+ if (frame)
+ concrete_frame_idx = frame->GetConcreteFrameIndex();
+
+ if (concrete_frame_idx == 0)
+ reg_ctx_sp = GetRegisterContext();
+ else
+ {
+ assert(GetUnwinder());
+ reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame);
+ }
+
+ return reg_ctx_sp;
+}
+
+lldb::addr_t
+FreeBSDThread::GetThreadPointer ()
+{
+ ProcessMonitor &monitor = GetMonitor();
+ addr_t addr;
+ if (monitor.ReadThreadPointer (GetID(), addr))
+ return addr;
+ else
+ return LLDB_INVALID_ADDRESS;
+}
+
+bool
+FreeBSDThread::CalculateStopInfo()
+{
+ SetStopInfo (m_stop_info_sp);
+ return true;
+}
+
+Unwind *
+FreeBSDThread::GetUnwinder()
+{
+ if (m_unwinder_ap.get() == NULL)
+ m_unwinder_ap.reset(new UnwindLLDB(*this));
+
+ return m_unwinder_ap.get();
+}
+
+void
+FreeBSDThread::DidStop()
+{
+ // Don't set the thread state to stopped unless we really stopped.
+}
void
FreeBSDThread::WillResume(lldb::StateType resume_state)
@@ -68,3 +323,359 @@ FreeBSDThread::WillResume(lldb::StateType resume_state)
break;
}
}
+
+bool
+FreeBSDThread::Resume()
+{
+ lldb::StateType resume_state = GetResumeState();
+ ProcessMonitor &monitor = GetMonitor();
+ bool status;
+
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log)
+ log->Printf ("FreeBSDThread::%s (), resume_state = %s", __FUNCTION__,
+ StateAsCString(resume_state));
+
+ switch (resume_state)
+ {
+ default:
+ assert(false && "Unexpected state for resume!");
+ status = false;
+ break;
+
+ case lldb::eStateRunning:
+ SetState(resume_state);
+ status = monitor.Resume(GetID(), GetResumeSignal());
+ break;
+
+ case lldb::eStateStepping:
+ SetState(resume_state);
+ status = monitor.SingleStep(GetID(), GetResumeSignal());
+ break;
+ case lldb::eStateStopped:
+ case lldb::eStateSuspended:
+ status = true;
+ break;
+ }
+
+ return status;
+}
+
+void
+FreeBSDThread::Notify(const ProcessMessage &message)
+{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log)
+ log->Printf ("FreeBSDThread::%s () message kind = '%s' for tid %" PRIu64,
+ __FUNCTION__, message.PrintKind(), GetID());
+
+ switch (message.GetKind())
+ {
+ default:
+ assert(false && "Unexpected message kind!");
+ break;
+
+ case ProcessMessage::eExitMessage:
+ // Nothing to be done.
+ break;
+
+ case ProcessMessage::eLimboMessage:
+ LimboNotify(message);
+ break;
+
+ case ProcessMessage::eSignalMessage:
+ SignalNotify(message);
+ break;
+
+ case ProcessMessage::eSignalDeliveredMessage:
+ SignalDeliveredNotify(message);
+ break;
+
+ case ProcessMessage::eTraceMessage:
+ TraceNotify(message);
+ break;
+
+ case ProcessMessage::eBreakpointMessage:
+ BreakNotify(message);
+ break;
+
+ case ProcessMessage::eWatchpointMessage:
+ WatchNotify(message);
+ break;
+
+ case ProcessMessage::eCrashMessage:
+ CrashNotify(message);
+ break;
+
+ case ProcessMessage::eExecMessage:
+ ExecNotify(message);
+ break;
+ }
+}
+
+bool
+FreeBSDThread::EnableHardwareWatchpoint(Watchpoint *wp)
+{
+ bool wp_set = false;
+ if (wp)
+ {
+ addr_t wp_addr = wp->GetLoadAddress();
+ size_t wp_size = wp->GetByteSize();
+ bool wp_read = wp->WatchpointRead();
+ bool wp_write = wp->WatchpointWrite();
+ uint32_t wp_hw_index = wp->GetHardwareIndex();
+ POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
+ if (reg_ctx)
+ wp_set = reg_ctx->SetHardwareWatchpointWithIndex(wp_addr, wp_size,
+ wp_read, wp_write,
+ wp_hw_index);
+ }
+ return wp_set;
+}
+
+bool
+FreeBSDThread::DisableHardwareWatchpoint(Watchpoint *wp)
+{
+ bool result = false;
+ if (wp)
+ {
+ lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
+ if (reg_ctx_sp.get())
+ result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex());
+ }
+ return result;
+}
+
+uint32_t
+FreeBSDThread::NumSupportedHardwareWatchpoints()
+{
+ lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
+ if (reg_ctx_sp.get())
+ return reg_ctx_sp->NumSupportedHardwareWatchpoints();
+ return 0;
+}
+
+uint32_t
+FreeBSDThread::FindVacantWatchpointIndex()
+{
+ uint32_t hw_index = LLDB_INVALID_INDEX32;
+ uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
+ uint32_t wp_idx;
+ POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
+ if (reg_ctx)
+ {
+ for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
+ {
+ if (reg_ctx->IsWatchpointVacant(wp_idx))
+ {
+ hw_index = wp_idx;
+ break;
+ }
+ }
+ }
+ return hw_index;
+}
+
+void
+FreeBSDThread::BreakNotify(const ProcessMessage &message)
+{
+ bool status;
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+
+ assert(GetRegisterContext());
+ status = GetPOSIXBreakpointProtocol()->UpdateAfterBreakpoint();
+ assert(status && "Breakpoint update failed!");
+
+ // With our register state restored, resolve the breakpoint object
+ // corresponding to our current PC.
+ assert(GetRegisterContext());
+ lldb::addr_t pc = GetRegisterContext()->GetPC();
+ if (log)
+ log->Printf ("FreeBSDThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc);
+ lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
+
+ // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
+ // we create a stop reason with should_stop=false. If there is no breakpoint location, then report
+ // an invalid stop reason. We don't need to worry about stepping over the breakpoint here, that will
+ // be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
+ if (bp_site)
+ {
+ lldb::break_id_t bp_id = bp_site->GetID();
+ // If we have an operating system plug-in, we might have set a thread specific breakpoint using the
+ // operating system thread ID, so we can't make any assumptions about the thread ID so we must always
+ // report the breakpoint regardless of the thread.
+ if (bp_site->ValidForThisThread(this) || GetProcess()->GetOperatingSystem () != NULL)
+ SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id));
+ else
+ {
+ const bool should_stop = false;
+ SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id, should_stop));
+ }
+ }
+ else
+ SetStopInfo(StopInfoSP());
+}
+
+void
+FreeBSDThread::WatchNotify(const ProcessMessage &message)
+{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+
+ lldb::addr_t halt_addr = message.GetHWAddress();
+ if (log)
+ log->Printf ("FreeBSDThread::%s () Hardware Watchpoint Address = 0x%8.8"
+ PRIx64, __FUNCTION__, halt_addr);
+
+ POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
+ if (reg_ctx)
+ {
+ uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
+ uint32_t wp_idx;
+ for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
+ {
+ if (reg_ctx->IsWatchpointHit(wp_idx))
+ {
+ // Clear the watchpoint hit here
+ reg_ctx->ClearWatchpointHits();
+ break;
+ }
+ }
+
+ if (wp_idx == num_hw_wps)
+ return;
+
+ Target &target = GetProcess()->GetTarget();
+ lldb::addr_t wp_monitor_addr = reg_ctx->GetWatchpointAddress(wp_idx);
+ const WatchpointList &wp_list = target.GetWatchpointList();
+ lldb::WatchpointSP wp_sp = wp_list.FindByAddress(wp_monitor_addr);
+
+ assert(wp_sp.get() && "No watchpoint found");
+ SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID(*this,
+ wp_sp->GetID()));
+ }
+}
+
+void
+FreeBSDThread::TraceNotify(const ProcessMessage &message)
+{
+ POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
+ if (reg_ctx)
+ {
+ uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
+ uint32_t wp_idx;
+ for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
+ {
+ if (reg_ctx->IsWatchpointHit(wp_idx))
+ {
+ WatchNotify(message);
+ return;
+ }
+ }
+ }
+
+ SetStopInfo (StopInfo::CreateStopReasonToTrace(*this));
+}
+
+void
+FreeBSDThread::LimboNotify(const ProcessMessage &message)
+{
+ SetStopInfo (lldb::StopInfoSP(new POSIXLimboStopInfo(*this)));
+}
+
+void
+FreeBSDThread::SignalNotify(const ProcessMessage &message)
+{
+ int signo = message.GetSignal();
+ SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo));
+}
+
+void
+FreeBSDThread::SignalDeliveredNotify(const ProcessMessage &message)
+{
+ int signo = message.GetSignal();
+ SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo));
+}
+
+void
+FreeBSDThread::CrashNotify(const ProcessMessage &message)
+{
+ // FIXME: Update stop reason as per bugzilla 14598
+ int signo = message.GetSignal();
+
+ assert(message.GetKind() == ProcessMessage::eCrashMessage);
+
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log)
+ log->Printf ("FreeBSDThread::%s () signo = %i, reason = '%s'",
+ __FUNCTION__, signo, message.PrintCrashReason());
+
+ SetStopInfo (lldb::StopInfoSP(new POSIXCrashStopInfo(*this, signo,
+ message.GetCrashReason(),
+ message.GetFaultAddress())));
+}
+
+unsigned
+FreeBSDThread::GetRegisterIndexFromOffset(unsigned offset)
+{
+ unsigned reg = LLDB_INVALID_REGNUM;
+ ArchSpec arch = HostInfo::GetArchitecture();
+
+ switch (arch.GetMachine())
+ {
+ default:
+ llvm_unreachable("CPU type not supported!");
+ break;
+
+ case llvm::Triple::aarch64:
+ case llvm::Triple::arm:
+ case llvm::Triple::mips64:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ {
+ POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
+ reg = reg_ctx->GetRegisterIndexFromOffset(offset);
+ }
+ break;
+ }
+ return reg;
+}
+
+void
+FreeBSDThread::ExecNotify(const ProcessMessage &message)
+{
+ SetStopInfo (StopInfo::CreateStopReasonWithExec(*this));
+}
+
+const char *
+FreeBSDThread::GetRegisterName(unsigned reg)
+{
+ const char * name = nullptr;
+ ArchSpec arch = HostInfo::GetArchitecture();
+
+ switch (arch.GetMachine())
+ {
+ default:
+ assert(false && "CPU type not supported!");
+ break;
+
+ case llvm::Triple::aarch64:
+ case llvm::Triple::arm:
+ case llvm::Triple::mips64:
+ case llvm::Triple::ppc:
+ case llvm::Triple::ppc64:
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ name = GetRegisterContext()->GetRegisterName(reg);
+ break;
+ }
+ return name;
+}
+
+const char *
+FreeBSDThread::GetRegisterNameFromOffset(unsigned offset)
+{
+ return GetRegisterName(GetRegisterIndexFromOffset(offset));
+}
+
diff --git a/source/Plugins/Process/FreeBSD/FreeBSDThread.h b/source/Plugins/Process/FreeBSD/FreeBSDThread.h
index 8741075cb60b..90c11dbefcb0 100644
--- a/source/Plugins/Process/FreeBSD/FreeBSDThread.h
+++ b/source/Plugins/Process/FreeBSD/FreeBSDThread.h
@@ -10,14 +10,23 @@
#ifndef liblldb_FreeBSDThread_H_
#define liblldb_FreeBSDThread_H_
+// C++ Includes
+#include <memory>
+#include <string>
+
// Other libraries and framework includes
-#include "POSIXThread.h"
+#include "lldb/Target/Thread.h"
+#include "RegisterContextPOSIX.h"
+
+class ProcessMessage;
+class ProcessMonitor;
+class POSIXBreakpointProtocol;
//------------------------------------------------------------------------------
// @class FreeBSDThread
// @brief Abstraction of a FreeBSD thread.
class FreeBSDThread
- : public POSIXThread
+ : public lldb_private::Thread
{
public:
@@ -28,12 +37,106 @@ public:
virtual ~FreeBSDThread();
+ // POSIXThread
+ void
+ RefreshStateAfterStop() override;
+
+ // This notifies the thread when a private stop occurs.
+ void
+ DidStop () override;
+
+ const char *
+ GetInfo() override;
+
+ void
+ SetName (const char *name) override;
+
+ const char *
+ GetName () override;
+
+ lldb::RegisterContextSP
+ GetRegisterContext() override;
+
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame (lldb_private::StackFrame *frame) override;
+
+ lldb::addr_t
+ GetThreadPointer () override;
+
+ //--------------------------------------------------------------------------
+ // These functions provide a mapping from the register offset
+ // back to the register index or name for use in debugging or log
+ // output.
+
+ unsigned
+ GetRegisterIndexFromOffset(unsigned offset);
+
+ const char *
+ GetRegisterName(unsigned reg);
+
+ const char *
+ GetRegisterNameFromOffset(unsigned offset);
+
+ //--------------------------------------------------------------------------
+ // These methods form a specialized interface to POSIX threads.
+ //
+ bool Resume();
+
+ void Notify(const ProcessMessage &message);
+
+ //--------------------------------------------------------------------------
+ // These methods provide an interface to watchpoints
+ //
+ bool EnableHardwareWatchpoint(lldb_private::Watchpoint *wp);
+
+ bool DisableHardwareWatchpoint(lldb_private::Watchpoint *wp);
+
+ uint32_t NumSupportedHardwareWatchpoints();
+
+ uint32_t FindVacantWatchpointIndex();
+
+protected:
+ POSIXBreakpointProtocol *
+ GetPOSIXBreakpointProtocol ()
+ {
+ if (!m_reg_context_sp)
+ m_reg_context_sp = GetRegisterContext();
+ return m_posix_thread;
+ }
+
+ std::unique_ptr<lldb_private::StackFrame> m_frame_ap;
+
+ lldb::BreakpointSiteSP m_breakpoint;
+
+ bool m_thread_name_valid;
+ std::string m_thread_name;
+ POSIXBreakpointProtocol *m_posix_thread;
+
+ ProcessMonitor &
+ GetMonitor();
+
+ bool
+ CalculateStopInfo() override;
+
+ void BreakNotify(const ProcessMessage &message);
+ void WatchNotify(const ProcessMessage &message);
+ virtual void TraceNotify(const ProcessMessage &message);
+ void LimboNotify(const ProcessMessage &message);
+ void SignalNotify(const ProcessMessage &message);
+ void SignalDeliveredNotify(const ProcessMessage &message);
+ void CrashNotify(const ProcessMessage &message);
+ void ExitNotify(const ProcessMessage &message);
+ void ExecNotify(const ProcessMessage &message);
+
+ lldb_private::Unwind *
+ GetUnwinder() override;
+
//--------------------------------------------------------------------------
// FreeBSDThread internal API.
// POSIXThread override
virtual void
- WillResume(lldb::StateType resume_state);
+ WillResume(lldb::StateType resume_state) override;
};
#endif // #ifndef liblldb_FreeBSDThread_H_
diff --git a/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp b/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp
index 3b8cea737bcb..409cf8c46b03 100644
--- a/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp
+++ b/source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp
@@ -45,7 +45,7 @@ POSIXLimboStopInfo::ShouldNotify(Event *event_ptr)
//===----------------------------------------------------------------------===//
// POSIXCrashStopInfo
-POSIXCrashStopInfo::POSIXCrashStopInfo(POSIXThread &thread,
+POSIXCrashStopInfo::POSIXCrashStopInfo(FreeBSDThread &thread,
uint32_t status,
CrashReason reason,
lldb::addr_t fault_addr)
diff --git a/source/Plugins/Process/FreeBSD/POSIXStopInfo.h b/source/Plugins/Process/FreeBSD/POSIXStopInfo.h
index a1ee2ea68524..ace6c98017b7 100644
--- a/source/Plugins/Process/FreeBSD/POSIXStopInfo.h
+++ b/source/Plugins/Process/FreeBSD/POSIXStopInfo.h
@@ -17,7 +17,7 @@
#include "lldb/Target/StopInfo.h"
#include "CrashReason.h"
-#include "POSIXThread.h"
+#include "FreeBSDThread.h"
#include <string>
@@ -42,7 +42,7 @@ class POSIXLimboStopInfo
: public POSIXStopInfo
{
public:
- POSIXLimboStopInfo(POSIXThread &thread)
+ POSIXLimboStopInfo(FreeBSDThread &thread)
: POSIXStopInfo(thread, 0)
{ }
@@ -70,7 +70,7 @@ class POSIXCrashStopInfo
: public POSIXStopInfo
{
public:
- POSIXCrashStopInfo(POSIXThread &thread, uint32_t status,
+ POSIXCrashStopInfo(FreeBSDThread &thread, uint32_t status,
CrashReason reason,
lldb::addr_t fault_addr);
~POSIXCrashStopInfo();
@@ -88,7 +88,7 @@ class POSIXNewThreadStopInfo
: public POSIXStopInfo
{
public:
- POSIXNewThreadStopInfo (POSIXThread &thread)
+ POSIXNewThreadStopInfo (FreeBSDThread &thread)
: POSIXStopInfo (thread, 0)
{ }
diff --git a/source/Plugins/Process/FreeBSD/POSIXThread.cpp b/source/Plugins/Process/FreeBSD/POSIXThread.cpp
deleted file mode 100644
index 854796fb7448..000000000000
--- a/source/Plugins/Process/FreeBSD/POSIXThread.cpp
+++ /dev/null
@@ -1,661 +0,0 @@
-//===-- POSIXThread.cpp -----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-#include <errno.h>
-
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Breakpoint/Watchpoint.h"
-#include "lldb/Breakpoint/BreakpointLocation.h"
-#include "lldb/Core/Debugger.h"
-#include "lldb/Core/State.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Host/HostNativeThread.h"
-#include "lldb/Host/HostInfo.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/StopInfo.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Target/ThreadSpec.h"
-#include "llvm/ADT/SmallString.h"
-#include "POSIXStopInfo.h"
-#include "POSIXThread.h"
-#include "ProcessPOSIX.h"
-#include "ProcessPOSIXLog.h"
-#include "ProcessMonitor.h"
-#include "RegisterContextPOSIXProcessMonitor_arm.h"
-#include "RegisterContextPOSIXProcessMonitor_arm64.h"
-#include "RegisterContextPOSIXProcessMonitor_mips64.h"
-#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
-#include "RegisterContextPOSIXProcessMonitor_x86.h"
-#include "Plugins/Process/Utility/RegisterContextFreeBSD_arm.h"
-#include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
-#include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
-#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
-#include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
-#include "Plugins/Process/Utility/UnwindLLDB.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-
-POSIXThread::POSIXThread(Process &process, lldb::tid_t tid)
- : Thread(process, tid),
- m_frame_ap (),
- m_breakpoint (),
- m_thread_name_valid (false),
- m_thread_name (),
- m_posix_thread(NULL)
-{
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("POSIXThread::%s (tid = %" PRIi64 ")", __FUNCTION__, tid);
-
- // Set the current watchpoints for this thread.
- Target &target = GetProcess()->GetTarget();
- const WatchpointList &wp_list = target.GetWatchpointList();
- size_t wp_size = wp_list.GetSize();
-
- for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++)
- {
- lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx);
- if (wp.get() && wp->IsEnabled())
- {
- // This watchpoint as been enabled; obviously this "new" thread
- // has been created since that watchpoint was enabled. Since
- // the POSIXBreakpointProtocol has yet to be initialized, its
- // m_watchpoints_initialized member will be FALSE. Attempting to
- // read the debug status register to determine if a watchpoint
- // has been hit would result in the zeroing of that register.
- // Since the active debug registers would have been cloned when
- // this thread was created, simply force the m_watchpoints_initized
- // member to TRUE and avoid resetting dr6 and dr7.
- GetPOSIXBreakpointProtocol()->ForceWatchpointsInitialized();
- }
- }
-}
-
-POSIXThread::~POSIXThread()
-{
- DestroyThread();
-}
-
-ProcessMonitor &
-POSIXThread::GetMonitor()
-{
- ProcessSP base = GetProcess();
- ProcessPOSIX &process = static_cast<ProcessPOSIX&>(*base);
- return process.GetMonitor();
-}
-
-void
-POSIXThread::RefreshStateAfterStop()
-{
- // Invalidate all registers in our register context. We don't set "force" to
- // true because the stop reply packet might have had some register values
- // that were expedited and these will already be copied into the register
- // context by the time this function gets called. The KDPRegisterContext
- // class has been made smart enough to detect when it needs to invalidate
- // which registers are valid by putting hooks in the register read and
- // register supply functions where they check the process stop ID and do
- // the right thing.
- //if (StateIsStoppedState(GetState())
- {
- const bool force = false;
- GetRegisterContext()->InvalidateIfNeeded (force);
- }
-}
-
-const char *
-POSIXThread::GetInfo()
-{
- return NULL;
-}
-
-void
-POSIXThread::SetName (const char *name)
-{
- m_thread_name_valid = (name && name[0]);
- if (m_thread_name_valid)
- m_thread_name.assign (name);
- else
- m_thread_name.clear();
-}
-
-const char *
-POSIXThread::GetName ()
-{
- if (!m_thread_name_valid)
- {
- llvm::SmallString<32> thread_name;
- HostNativeThread::GetName(GetID(), thread_name);
- m_thread_name = thread_name.c_str();
- m_thread_name_valid = true;
- }
-
- if (m_thread_name.empty())
- return NULL;
- return m_thread_name.c_str();
-}
-
-lldb::RegisterContextSP
-POSIXThread::GetRegisterContext()
-{
- if (!m_reg_context_sp)
- {
- m_posix_thread = NULL;
-
- RegisterInfoInterface *reg_interface = NULL;
- const ArchSpec &target_arch = GetProcess()->GetTarget().GetArchitecture();
-
- switch (target_arch.GetTriple().getOS())
- {
- case llvm::Triple::FreeBSD:
- switch (target_arch.GetMachine())
- {
- case llvm::Triple::arm:
- reg_interface = new RegisterContextFreeBSD_arm(target_arch);
- break;
- case llvm::Triple::ppc:
-#ifndef __powerpc64__
- reg_interface = new RegisterContextFreeBSD_powerpc32(target_arch);
- break;
-#endif
- case llvm::Triple::ppc64:
- reg_interface = new RegisterContextFreeBSD_powerpc64(target_arch);
- break;
- case llvm::Triple::mips64:
- reg_interface = new RegisterContextFreeBSD_mips64(target_arch);
- break;
- case llvm::Triple::x86:
- reg_interface = new RegisterContextFreeBSD_i386(target_arch);
- break;
- case llvm::Triple::x86_64:
- reg_interface = new RegisterContextFreeBSD_x86_64(target_arch);
- break;
- default:
- break;
- }
- break;
-
- default:
- break;
- }
-
- assert(reg_interface && "OS or CPU not supported!");
-
- switch (target_arch.GetMachine())
- {
- case llvm::Triple::aarch64:
- {
- RegisterContextPOSIXProcessMonitor_arm64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm64(*this, 0, reg_interface);
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- case llvm::Triple::arm:
- {
- RegisterContextPOSIXProcessMonitor_arm *reg_ctx = new RegisterContextPOSIXProcessMonitor_arm(*this, 0, reg_interface);
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- case llvm::Triple::mips64:
- {
- RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface);
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- {
- RegisterContextPOSIXProcessMonitor_powerpc *reg_ctx = new RegisterContextPOSIXProcessMonitor_powerpc(*this, 0, reg_interface);
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- {
- RegisterContextPOSIXProcessMonitor_x86_64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_x86_64(*this, 0, reg_interface);
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
- default:
- break;
- }
- }
- return m_reg_context_sp;
-}
-
-lldb::RegisterContextSP
-POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)
-{
- lldb::RegisterContextSP reg_ctx_sp;
- uint32_t concrete_frame_idx = 0;
-
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("POSIXThread::%s ()", __FUNCTION__);
-
- if (frame)
- concrete_frame_idx = frame->GetConcreteFrameIndex();
-
- if (concrete_frame_idx == 0)
- reg_ctx_sp = GetRegisterContext();
- else
- {
- assert(GetUnwinder());
- reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame);
- }
-
- return reg_ctx_sp;
-}
-
-lldb::addr_t
-POSIXThread::GetThreadPointer ()
-{
- ProcessMonitor &monitor = GetMonitor();
- addr_t addr;
- if (monitor.ReadThreadPointer (GetID(), addr))
- return addr;
- else
- return LLDB_INVALID_ADDRESS;
-}
-
-bool
-POSIXThread::CalculateStopInfo()
-{
- SetStopInfo (m_stop_info_sp);
- return true;
-}
-
-Unwind *
-POSIXThread::GetUnwinder()
-{
- if (m_unwinder_ap.get() == NULL)
- m_unwinder_ap.reset(new UnwindLLDB(*this));
-
- return m_unwinder_ap.get();
-}
-
-void
-POSIXThread::DidStop()
-{
- // Don't set the thread state to stopped unless we really stopped.
-}
-
-bool
-POSIXThread::Resume()
-{
- lldb::StateType resume_state = GetResumeState();
- ProcessMonitor &monitor = GetMonitor();
- bool status;
-
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
- if (log)
- log->Printf ("POSIXThread::%s (), resume_state = %s", __FUNCTION__,
- StateAsCString(resume_state));
-
- switch (resume_state)
- {
- default:
- assert(false && "Unexpected state for resume!");
- status = false;
- break;
-
- case lldb::eStateRunning:
- SetState(resume_state);
- status = monitor.Resume(GetID(), GetResumeSignal());
- break;
-
- case lldb::eStateStepping:
- SetState(resume_state);
- status = monitor.SingleStep(GetID(), GetResumeSignal());
- break;
- case lldb::eStateStopped:
- case lldb::eStateSuspended:
- status = true;
- break;
- }
-
- return status;
-}
-
-void
-POSIXThread::Notify(const ProcessMessage &message)
-{
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
- if (log)
- log->Printf ("POSIXThread::%s () message kind = '%s' for tid %" PRIu64,
- __FUNCTION__, message.PrintKind(), GetID());
-
- switch (message.GetKind())
- {
- default:
- assert(false && "Unexpected message kind!");
- break;
-
- case ProcessMessage::eExitMessage:
- // Nothing to be done.
- break;
-
- case ProcessMessage::eLimboMessage:
- LimboNotify(message);
- break;
-
- case ProcessMessage::eSignalMessage:
- SignalNotify(message);
- break;
-
- case ProcessMessage::eSignalDeliveredMessage:
- SignalDeliveredNotify(message);
- break;
-
- case ProcessMessage::eTraceMessage:
- TraceNotify(message);
- break;
-
- case ProcessMessage::eBreakpointMessage:
- BreakNotify(message);
- break;
-
- case ProcessMessage::eWatchpointMessage:
- WatchNotify(message);
- break;
-
- case ProcessMessage::eCrashMessage:
- CrashNotify(message);
- break;
-
- case ProcessMessage::eNewThreadMessage:
- ThreadNotify(message);
- break;
-
- case ProcessMessage::eExecMessage:
- ExecNotify(message);
- break;
- }
-}
-
-bool
-POSIXThread::EnableHardwareWatchpoint(Watchpoint *wp)
-{
- bool wp_set = false;
- if (wp)
- {
- addr_t wp_addr = wp->GetLoadAddress();
- size_t wp_size = wp->GetByteSize();
- bool wp_read = wp->WatchpointRead();
- bool wp_write = wp->WatchpointWrite();
- uint32_t wp_hw_index = wp->GetHardwareIndex();
- POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
- if (reg_ctx)
- wp_set = reg_ctx->SetHardwareWatchpointWithIndex(wp_addr, wp_size,
- wp_read, wp_write,
- wp_hw_index);
- }
- return wp_set;
-}
-
-bool
-POSIXThread::DisableHardwareWatchpoint(Watchpoint *wp)
-{
- bool result = false;
- if (wp)
- {
- lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
- if (reg_ctx_sp.get())
- result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex());
- }
- return result;
-}
-
-uint32_t
-POSIXThread::NumSupportedHardwareWatchpoints()
-{
- lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
- if (reg_ctx_sp.get())
- return reg_ctx_sp->NumSupportedHardwareWatchpoints();
- return 0;
-}
-
-uint32_t
-POSIXThread::FindVacantWatchpointIndex()
-{
- uint32_t hw_index = LLDB_INVALID_INDEX32;
- uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
- uint32_t wp_idx;
- POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
- if (reg_ctx)
- {
- for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
- {
- if (reg_ctx->IsWatchpointVacant(wp_idx))
- {
- hw_index = wp_idx;
- break;
- }
- }
- }
- return hw_index;
-}
-
-void
-POSIXThread::BreakNotify(const ProcessMessage &message)
-{
- bool status;
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
-
- assert(GetRegisterContext());
- status = GetPOSIXBreakpointProtocol()->UpdateAfterBreakpoint();
- assert(status && "Breakpoint update failed!");
-
- // With our register state restored, resolve the breakpoint object
- // corresponding to our current PC.
- assert(GetRegisterContext());
- lldb::addr_t pc = GetRegisterContext()->GetPC();
- if (log)
- log->Printf ("POSIXThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc);
- lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
-
- // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
- // we create a stop reason with should_stop=false. If there is no breakpoint location, then report
- // an invalid stop reason. We don't need to worry about stepping over the breakpoint here, that will
- // be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
- if (bp_site)
- {
- lldb::break_id_t bp_id = bp_site->GetID();
- // If we have an operating system plug-in, we might have set a thread specific breakpoint using the
- // operating system thread ID, so we can't make any assumptions about the thread ID so we must always
- // report the breakpoint regardless of the thread.
- if (bp_site->ValidForThisThread(this) || GetProcess()->GetOperatingSystem () != NULL)
- SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id));
- else
- {
- const bool should_stop = false;
- SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id, should_stop));
- }
- }
- else
- SetStopInfo(StopInfoSP());
-}
-
-void
-POSIXThread::WatchNotify(const ProcessMessage &message)
-{
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
-
- lldb::addr_t halt_addr = message.GetHWAddress();
- if (log)
- log->Printf ("POSIXThread::%s () Hardware Watchpoint Address = 0x%8.8"
- PRIx64, __FUNCTION__, halt_addr);
-
- POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
- if (reg_ctx)
- {
- uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
- uint32_t wp_idx;
- for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
- {
- if (reg_ctx->IsWatchpointHit(wp_idx))
- {
- // Clear the watchpoint hit here
- reg_ctx->ClearWatchpointHits();
- break;
- }
- }
-
- if (wp_idx == num_hw_wps)
- return;
-
- Target &target = GetProcess()->GetTarget();
- lldb::addr_t wp_monitor_addr = reg_ctx->GetWatchpointAddress(wp_idx);
- const WatchpointList &wp_list = target.GetWatchpointList();
- lldb::WatchpointSP wp_sp = wp_list.FindByAddress(wp_monitor_addr);
-
- assert(wp_sp.get() && "No watchpoint found");
- SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID(*this,
- wp_sp->GetID()));
- }
-}
-
-void
-POSIXThread::TraceNotify(const ProcessMessage &message)
-{
- POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
- if (reg_ctx)
- {
- uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
- uint32_t wp_idx;
- for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
- {
- if (reg_ctx->IsWatchpointHit(wp_idx))
- {
- WatchNotify(message);
- return;
- }
- }
- }
-
- SetStopInfo (StopInfo::CreateStopReasonToTrace(*this));
-}
-
-void
-POSIXThread::LimboNotify(const ProcessMessage &message)
-{
- SetStopInfo (lldb::StopInfoSP(new POSIXLimboStopInfo(*this)));
-}
-
-void
-POSIXThread::SignalNotify(const ProcessMessage &message)
-{
- int signo = message.GetSignal();
- SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo));
-}
-
-void
-POSIXThread::SignalDeliveredNotify(const ProcessMessage &message)
-{
- int signo = message.GetSignal();
- SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo));
-}
-
-void
-POSIXThread::CrashNotify(const ProcessMessage &message)
-{
- // FIXME: Update stop reason as per bugzilla 14598
- int signo = message.GetSignal();
-
- assert(message.GetKind() == ProcessMessage::eCrashMessage);
-
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
- if (log)
- log->Printf ("POSIXThread::%s () signo = %i, reason = '%s'",
- __FUNCTION__, signo, message.PrintCrashReason());
-
- SetStopInfo (lldb::StopInfoSP(new POSIXCrashStopInfo(*this, signo,
- message.GetCrashReason(),
- message.GetFaultAddress())));
-}
-
-void
-POSIXThread::ThreadNotify(const ProcessMessage &message)
-{
- SetStopInfo (lldb::StopInfoSP(new POSIXNewThreadStopInfo(*this)));
-}
-
-unsigned
-POSIXThread::GetRegisterIndexFromOffset(unsigned offset)
-{
- unsigned reg = LLDB_INVALID_REGNUM;
- ArchSpec arch = HostInfo::GetArchitecture();
-
- switch (arch.GetMachine())
- {
- default:
- llvm_unreachable("CPU type not supported!");
- break;
-
- case llvm::Triple::aarch64:
- case llvm::Triple::arm:
- case llvm::Triple::mips64:
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- {
- POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
- reg = reg_ctx->GetRegisterIndexFromOffset(offset);
- }
- break;
- }
- return reg;
-}
-
-void
-POSIXThread::ExecNotify(const ProcessMessage &message)
-{
- SetStopInfo (StopInfo::CreateStopReasonWithExec(*this));
-}
-
-const char *
-POSIXThread::GetRegisterName(unsigned reg)
-{
- const char * name = nullptr;
- ArchSpec arch = HostInfo::GetArchitecture();
-
- switch (arch.GetMachine())
- {
- default:
- assert(false && "CPU type not supported!");
- break;
-
- case llvm::Triple::aarch64:
- case llvm::Triple::arm:
- case llvm::Triple::mips64:
- case llvm::Triple::ppc:
- case llvm::Triple::ppc64:
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- name = GetRegisterContext()->GetRegisterName(reg);
- break;
- }
- return name;
-}
-
-const char *
-POSIXThread::GetRegisterNameFromOffset(unsigned offset)
-{
- return GetRegisterName(GetRegisterIndexFromOffset(offset));
-}
-
diff --git a/source/Plugins/Process/FreeBSD/POSIXThread.h b/source/Plugins/Process/FreeBSD/POSIXThread.h
deleted file mode 100644
index c38d194dbd19..000000000000
--- a/source/Plugins/Process/FreeBSD/POSIXThread.h
+++ /dev/null
@@ -1,132 +0,0 @@
-//===-- POSIXThread.h -------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_POSIXThread_H_
-#define liblldb_POSIXThread_H_
-
-// C Includes
-// C++ Includes
-#include <memory>
-#include <string>
-
-// Other libraries and framework includes
-#include "lldb/Target/Thread.h"
-#include "Plugins/Process/Utility/RegisterContextPOSIX.h"
-
-class ProcessMessage;
-class ProcessMonitor;
-class POSIXBreakpointProtocol;
-
-//------------------------------------------------------------------------------
-// @class POSIXThread
-// @brief Abstraction of a POSIX thread.
-class POSIXThread
- : public lldb_private::Thread
-{
-public:
- POSIXThread(lldb_private::Process &process, lldb::tid_t tid);
-
- virtual ~POSIXThread();
-
- void
- RefreshStateAfterStop() override;
-
- // This notifies the thread when a private stop occurs.
- void
- DidStop () override;
-
- const char *
- GetInfo() override;
-
- void
- SetName (const char *name) override;
-
- const char *
- GetName () override;
-
- lldb::RegisterContextSP
- GetRegisterContext() override;
-
- lldb::RegisterContextSP
- CreateRegisterContextForFrame (lldb_private::StackFrame *frame) override;
-
- lldb::addr_t
- GetThreadPointer () override;
-
- //--------------------------------------------------------------------------
- // These functions provide a mapping from the register offset
- // back to the register index or name for use in debugging or log
- // output.
-
- unsigned
- GetRegisterIndexFromOffset(unsigned offset);
-
- const char *
- GetRegisterName(unsigned reg);
-
- const char *
- GetRegisterNameFromOffset(unsigned offset);
-
- //--------------------------------------------------------------------------
- // These methods form a specialized interface to POSIX threads.
- //
- bool Resume();
-
- void Notify(const ProcessMessage &message);
-
- //--------------------------------------------------------------------------
- // These methods provide an interface to watchpoints
- //
- bool EnableHardwareWatchpoint(lldb_private::Watchpoint *wp);
-
- bool DisableHardwareWatchpoint(lldb_private::Watchpoint *wp);
-
- uint32_t NumSupportedHardwareWatchpoints();
-
- uint32_t FindVacantWatchpointIndex();
-
-protected:
- POSIXBreakpointProtocol *
- GetPOSIXBreakpointProtocol ()
- {
- if (!m_reg_context_sp)
- m_reg_context_sp = GetRegisterContext();
- return m_posix_thread;
- }
-
- std::unique_ptr<lldb_private::StackFrame> m_frame_ap;
-
- lldb::BreakpointSiteSP m_breakpoint;
-
- bool m_thread_name_valid;
- std::string m_thread_name;
- POSIXBreakpointProtocol *m_posix_thread;
-
- ProcessMonitor &
- GetMonitor();
-
- bool
- CalculateStopInfo() override;
-
- void BreakNotify(const ProcessMessage &message);
- void WatchNotify(const ProcessMessage &message);
- virtual void TraceNotify(const ProcessMessage &message);
- void LimboNotify(const ProcessMessage &message);
- void SignalNotify(const ProcessMessage &message);
- void SignalDeliveredNotify(const ProcessMessage &message);
- void CrashNotify(const ProcessMessage &message);
- void ThreadNotify(const ProcessMessage &message);
- void ExitNotify(const ProcessMessage &message);
- void ExecNotify(const ProcessMessage &message);
-
- lldb_private::Unwind *
- GetUnwinder() override;
-};
-
-#endif // #ifndef liblldb_POSIXThread_H_
diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
index a0458f16e558..769ccd7248ac 100644
--- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
@@ -28,6 +28,23 @@
#include "ProcessMonitor.h"
#include "FreeBSDThread.h"
+// Other libraries and framework includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/Watchpoint.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/State.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/Platform.h"
+#include "lldb/Target/Target.h"
+
+#include "lldb/Host/posix/Fcntl.h"
+
+
using namespace lldb;
using namespace lldb_private;
@@ -45,13 +62,13 @@ namespace
// Static functions.
lldb::ProcessSP
-ProcessFreeBSD::CreateInstance(Target& target,
+ProcessFreeBSD::CreateInstance(lldb::TargetSP target_sp,
Listener &listener,
const FileSpec *crash_file_path)
{
lldb::ProcessSP process_sp;
if (crash_file_path == NULL)
- process_sp.reset(new ProcessFreeBSD (target, listener));
+ process_sp.reset(new ProcessFreeBSD (target_sp, listener, GetFreeBSDSignals()));
return process_sp;
}
@@ -97,32 +114,6 @@ ProcessFreeBSD::GetPluginVersion()
}
void
-ProcessFreeBSD::GetPluginCommandHelp(const char *command, Stream *strm)
-{
-}
-
-Error
-ProcessFreeBSD::ExecutePluginCommand(Args &command, Stream *strm)
-{
- return Error(1, eErrorTypeGeneric);
-}
-
-Log *
-ProcessFreeBSD::EnablePluginLogging(Stream *strm, Args &command)
-{
- return NULL;
-}
-
-//------------------------------------------------------------------------------
-// Constructors and destructors.
-
-ProcessFreeBSD::ProcessFreeBSD(Target& target, Listener &listener)
- : ProcessPOSIX(target, listener, GetFreeBSDSignals ()),
- m_resume_signo(0)
-{
-}
-
-void
ProcessFreeBSD::Terminate()
{
}
@@ -232,7 +223,7 @@ ProcessFreeBSD::WillResume()
m_suspend_tids.clear();
m_run_tids.clear();
m_step_tids.clear();
- return ProcessPOSIX::WillResume();
+ return Process::WillResume();
}
void
@@ -264,7 +255,7 @@ ProcessFreeBSD::SendMessage(const ProcessMessage &message)
break;
case ProcessMessage::eNewThreadMessage:
- assert(0 && "eNewThreadMessage unexpected on FreeBSD");
+ llvm_unreachable("eNewThreadMessage unexpected on FreeBSD");
break;
case ProcessMessage::eExecMessage:
@@ -274,3 +265,781 @@ ProcessFreeBSD::SendMessage(const ProcessMessage &message)
m_message_queue.push(message);
}
+
+//------------------------------------------------------------------------------
+// Constructors and destructors.
+
+ProcessFreeBSD::ProcessFreeBSD(lldb::TargetSP target_sp, Listener &listener, UnixSignalsSP &unix_signals_sp)
+ : Process(target_sp, listener, unix_signals_sp),
+ m_byte_order(endian::InlHostByteOrder()),
+ m_monitor(NULL),
+ m_module(NULL),
+ m_message_mutex (Mutex::eMutexTypeRecursive),
+ m_exit_now(false),
+ m_seen_initial_stop(),
+ m_resume_signo(0)
+{
+ // FIXME: Putting this code in the ctor and saving the byte order in a
+ // member variable is a hack to avoid const qual issues in GetByteOrder.
+ lldb::ModuleSP module = GetTarget().GetExecutableModule();
+ if (module && module->GetObjectFile())
+ m_byte_order = module->GetObjectFile()->GetByteOrder();
+}
+
+ProcessFreeBSD::~ProcessFreeBSD()
+{
+ delete m_monitor;
+}
+
+//------------------------------------------------------------------------------
+// Process protocol.
+void
+ProcessFreeBSD::Finalize()
+{
+ Process::Finalize();
+
+ if (m_monitor)
+ m_monitor->StopMonitor();
+}
+
+bool
+ProcessFreeBSD::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name)
+{
+ // For now we are just making sure the file exists for a given module
+ ModuleSP exe_module_sp(target_sp->GetExecutableModule());
+ if (exe_module_sp.get())
+ return exe_module_sp->GetFileSpec().Exists();
+ // If there is no executable module, we return true since we might be preparing to attach.
+ return true;
+}
+
+Error
+ProcessFreeBSD::DoAttachToProcessWithID (lldb::pid_t pid, const ProcessAttachInfo &attach_info)
+{
+ Error error;
+ assert(m_monitor == NULL);
+
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("ProcessFreeBSD::%s(pid = %" PRIi64 ")", __FUNCTION__, GetID());
+
+ m_monitor = new ProcessMonitor(this, pid, error);
+
+ if (!error.Success())
+ return error;
+
+ PlatformSP platform_sp (GetTarget().GetPlatform ());
+ assert (platform_sp.get());
+ if (!platform_sp)
+ return error; // FIXME: Detatch?
+
+ // Find out what we can about this process
+ ProcessInstanceInfo process_info;
+ platform_sp->GetProcessInfo (pid, process_info);
+
+ // Resolve the executable module
+ ModuleSP exe_module_sp;
+ FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
+ ModuleSpec exe_module_spec(process_info.GetExecutableFile(), GetTarget().GetArchitecture());
+ error = platform_sp->ResolveExecutable(exe_module_spec,
+ exe_module_sp,
+ executable_search_paths.GetSize() ? &executable_search_paths : NULL);
+ if (!error.Success())
+ return error;
+
+ // Fix the target architecture if necessary
+ const ArchSpec &module_arch = exe_module_sp->GetArchitecture();
+ if (module_arch.IsValid() && !GetTarget().GetArchitecture().IsExactMatch(module_arch))
+ GetTarget().SetArchitecture(module_arch);
+
+ // Initialize the target module list
+ GetTarget().SetExecutableModule (exe_module_sp, true);
+
+ SetSTDIOFileDescriptor(m_monitor->GetTerminalFD());
+
+ SetID(pid);
+
+ return error;
+}
+
+Error
+ProcessFreeBSD::WillLaunch(Module* module)
+{
+ Error error;
+ return error;
+}
+
+FileSpec
+ProcessFreeBSD::GetFileSpec(const lldb_private::FileAction *file_action,
+ const FileSpec &default_file_spec,
+ const FileSpec &dbg_pts_file_spec)
+{
+ FileSpec file_spec{};
+
+ if (file_action && file_action->GetAction() == FileAction::eFileActionOpen)
+ {
+ file_spec = file_action->GetFileSpec();
+ // By default the stdio paths passed in will be pseudo-terminal
+ // (/dev/pts). If so, convert to using a different default path
+ // instead to redirect I/O to the debugger console. This should
+ // also handle user overrides to /dev/null or a different file.
+ if (!file_spec || file_spec == dbg_pts_file_spec)
+ file_spec = default_file_spec;
+ }
+ return file_spec;
+}
+
+Error
+ProcessFreeBSD::DoLaunch (Module *module,
+ ProcessLaunchInfo &launch_info)
+{
+ Error error;
+ assert(m_monitor == NULL);
+
+ FileSpec working_dir = launch_info.GetWorkingDirectory();
+ if (working_dir &&
+ (!working_dir.ResolvePath() ||
+ working_dir.GetFileType() != FileSpec::eFileTypeDirectory))
+ {
+ error.SetErrorStringWithFormat("No such file or directory: %s",
+ working_dir.GetCString());
+ return error;
+ }
+
+ SetPrivateState(eStateLaunching);
+
+ const lldb_private::FileAction *file_action;
+
+ // Default of empty will mean to use existing open file descriptors
+ FileSpec stdin_file_spec{};
+ FileSpec stdout_file_spec{};
+ FileSpec stderr_file_spec{};
+
+ const FileSpec dbg_pts_file_spec{launch_info.GetPTY().GetSlaveName(NULL,0), false};
+
+ file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
+ stdin_file_spec = GetFileSpec(file_action, stdin_file_spec, dbg_pts_file_spec);
+
+ file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
+ stdout_file_spec = GetFileSpec(file_action, stdout_file_spec, dbg_pts_file_spec);
+
+ file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
+ stderr_file_spec = GetFileSpec(file_action, stderr_file_spec, dbg_pts_file_spec);
+
+ m_monitor = new ProcessMonitor(this,
+ module,
+ launch_info.GetArguments().GetConstArgumentVector(),
+ launch_info.GetEnvironmentEntries().GetConstArgumentVector(),
+ stdin_file_spec,
+ stdout_file_spec,
+ stderr_file_spec,
+ working_dir,
+ launch_info,
+ error);
+
+ m_module = module;
+
+ if (!error.Success())
+ return error;
+
+ int terminal = m_monitor->GetTerminalFD();
+ if (terminal >= 0) {
+ // The reader thread will close the file descriptor when done, so we pass it a copy.
+#ifdef F_DUPFD_CLOEXEC
+ int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0);
+ if (stdio == -1) {
+ error.SetErrorToErrno();
+ return error;
+ }
+#else
+ // Special case when F_DUPFD_CLOEXEC does not exist (Debian kFreeBSD)
+ int stdio = fcntl(terminal, F_DUPFD, 0);
+ if (stdio == -1) {
+ error.SetErrorToErrno();
+ return error;
+ }
+ stdio = fcntl(terminal, F_SETFD, FD_CLOEXEC);
+ if (stdio == -1) {
+ error.SetErrorToErrno();
+ return error;
+ }
+#endif
+ SetSTDIOFileDescriptor(stdio);
+ }
+
+ SetID(m_monitor->GetPID());
+ return error;
+}
+
+void
+ProcessFreeBSD::DidLaunch()
+{
+}
+
+addr_t
+ProcessFreeBSD::GetImageInfoAddress()
+{
+ Target *target = &GetTarget();
+ ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
+ Address addr = obj_file->GetImageInfoAddress(target);
+
+ if (addr.IsValid())
+ return addr.GetLoadAddress(target);
+ return LLDB_INVALID_ADDRESS;
+}
+
+Error
+ProcessFreeBSD::DoHalt(bool &caused_stop)
+{
+ Error error;
+
+ if (IsStopped())
+ {
+ caused_stop = false;
+ }
+ else if (kill(GetID(), SIGSTOP))
+ {
+ caused_stop = false;
+ error.SetErrorToErrno();
+ }
+ else
+ {
+ caused_stop = true;
+ }
+ return error;
+}
+
+Error
+ProcessFreeBSD::DoSignal(int signal)
+{
+ Error error;
+
+ if (kill(GetID(), signal))
+ error.SetErrorToErrno();
+
+ return error;
+}
+
+Error
+ProcessFreeBSD::DoDestroy()
+{
+ Error error;
+
+ if (!HasExited())
+ {
+ assert(m_monitor);
+ m_exit_now = true;
+ if (GetID() == LLDB_INVALID_PROCESS_ID)
+ {
+ error.SetErrorString("invalid process id");
+ return error;
+ }
+ if (!m_monitor->Kill())
+ {
+ error.SetErrorToErrno();
+ return error;
+ }
+
+ SetPrivateState(eStateExited);
+ }
+
+ return error;
+}
+
+void
+ProcessFreeBSD::DoDidExec()
+{
+ Target *target = &GetTarget();
+ if (target)
+ {
+ PlatformSP platform_sp (target->GetPlatform());
+ assert (platform_sp.get());
+ if (platform_sp)
+ {
+ ProcessInstanceInfo process_info;
+ platform_sp->GetProcessInfo(GetID(), process_info);
+ ModuleSP exe_module_sp;
+ ModuleSpec exe_module_spec(process_info.GetExecutableFile(), target->GetArchitecture());
+ FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
+ Error error = platform_sp->ResolveExecutable(exe_module_spec,
+ exe_module_sp,
+ executable_search_paths.GetSize() ? &executable_search_paths : NULL);
+ if (!error.Success())
+ return;
+ target->SetExecutableModule(exe_module_sp, true);
+ }
+ }
+}
+
+bool
+ProcessFreeBSD::AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid)
+{
+ bool added_to_set = false;
+ ThreadStopSet::iterator it = m_seen_initial_stop.find(stop_tid);
+ if (it == m_seen_initial_stop.end())
+ {
+ m_seen_initial_stop.insert(stop_tid);
+ added_to_set = true;
+ }
+ return added_to_set;
+}
+
+bool
+ProcessFreeBSD::WaitingForInitialStop(lldb::tid_t stop_tid)
+{
+ return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end());
+}
+
+FreeBSDThread *
+ProcessFreeBSD::CreateNewFreeBSDThread(lldb_private::Process &process, lldb::tid_t tid)
+{
+ return new FreeBSDThread(process, tid);
+}
+
+void
+ProcessFreeBSD::RefreshStateAfterStop()
+{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("ProcessFreeBSD::%s(), message_queue size = %d", __FUNCTION__, (int)m_message_queue.size());
+
+ Mutex::Locker lock(m_message_mutex);
+
+ // This method used to only handle one message. Changing it to loop allows
+ // it to handle the case where we hit a breakpoint while handling a different
+ // breakpoint.
+ while (!m_message_queue.empty())
+ {
+ ProcessMessage &message = m_message_queue.front();
+
+ // Resolve the thread this message corresponds to and pass it along.
+ lldb::tid_t tid = message.GetTID();
+ if (log)
+ log->Printf ("ProcessFreeBSD::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid);
+
+ m_thread_list.RefreshStateAfterStop();
+
+ FreeBSDThread *thread = static_cast<FreeBSDThread*>(
+ GetThreadList().FindThreadByID(tid, false).get());
+ if (thread)
+ thread->Notify(message);
+
+ if (message.GetKind() == ProcessMessage::eExitMessage)
+ {
+ // FIXME: We should tell the user about this, but the limbo message is probably better for that.
+ if (log)
+ log->Printf ("ProcessFreeBSD::%s() removing thread, tid = %" PRIi64, __FUNCTION__, tid);
+
+ Mutex::Locker lock(m_thread_list.GetMutex());
+
+ ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false);
+ thread_sp.reset();
+ m_seen_initial_stop.erase(tid);
+ }
+
+ m_message_queue.pop();
+ }
+}
+
+bool
+ProcessFreeBSD::IsAlive()
+{
+ StateType state = GetPrivateState();
+ return state != eStateDetached
+ && state != eStateExited
+ && state != eStateInvalid
+ && state != eStateUnloaded;
+}
+
+size_t
+ProcessFreeBSD::DoReadMemory(addr_t vm_addr,
+ void *buf, size_t size, Error &error)
+{
+ assert(m_monitor);
+ return m_monitor->ReadMemory(vm_addr, buf, size, error);
+}
+
+size_t
+ProcessFreeBSD::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size,
+ Error &error)
+{
+ assert(m_monitor);
+ return m_monitor->WriteMemory(vm_addr, buf, size, error);
+}
+
+addr_t
+ProcessFreeBSD::DoAllocateMemory(size_t size, uint32_t permissions,
+ Error &error)
+{
+ addr_t allocated_addr = LLDB_INVALID_ADDRESS;
+
+ unsigned prot = 0;
+ if (permissions & lldb::ePermissionsReadable)
+ prot |= eMmapProtRead;
+ if (permissions & lldb::ePermissionsWritable)
+ prot |= eMmapProtWrite;
+ if (permissions & lldb::ePermissionsExecutable)
+ prot |= eMmapProtExec;
+
+ if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
+ eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {
+ m_addr_to_mmap_size[allocated_addr] = size;
+ error.Clear();
+ } else {
+ allocated_addr = LLDB_INVALID_ADDRESS;
+ error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions));
+ }
+
+ return allocated_addr;
+}
+
+Error
+ProcessFreeBSD::DoDeallocateMemory(lldb::addr_t addr)
+{
+ Error error;
+ MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
+ if (pos != m_addr_to_mmap_size.end() &&
+ InferiorCallMunmap(this, addr, pos->second))
+ m_addr_to_mmap_size.erase (pos);
+ else
+ error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr);
+
+ return error;
+}
+
+size_t
+ProcessFreeBSD::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
+{
+ static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xD4 };
+ static const uint8_t g_i386_opcode[] = { 0xCC };
+
+ ArchSpec arch = GetTarget().GetArchitecture();
+ const uint8_t *opcode = NULL;
+ size_t opcode_size = 0;
+
+ switch (arch.GetMachine())
+ {
+ default:
+ assert(false && "CPU type not supported!");
+ break;
+
+ case llvm::Triple::arm:
+ {
+ // The ARM reference recommends the use of 0xe7fddefe and 0xdefe
+ // but the linux kernel does otherwise.
+ static const uint8_t g_arm_breakpoint_opcode[] = { 0xf0, 0x01, 0xf0, 0xe7 };
+ static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde };
+
+ lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0));
+ AddressClass addr_class = eAddressClassUnknown;
+
+ if (bp_loc_sp)
+ addr_class = bp_loc_sp->GetAddress ().GetAddressClass ();
+
+ if (addr_class == eAddressClassCodeAlternateISA
+ || (addr_class == eAddressClassUnknown
+ && bp_loc_sp->GetAddress().GetOffset() & 1))
+ {
+ opcode = g_thumb_breakpoint_opcode;
+ opcode_size = sizeof(g_thumb_breakpoint_opcode);
+ }
+ else
+ {
+ opcode = g_arm_breakpoint_opcode;
+ opcode_size = sizeof(g_arm_breakpoint_opcode);
+ }
+ }
+ break;
+ case llvm::Triple::aarch64:
+ opcode = g_aarch64_opcode;
+ opcode_size = sizeof(g_aarch64_opcode);
+ break;
+
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ opcode = g_i386_opcode;
+ opcode_size = sizeof(g_i386_opcode);
+ break;
+ }
+
+ bp_site->SetTrapOpcode(opcode, opcode_size);
+ return opcode_size;
+}
+
+Error
+ProcessFreeBSD::EnableBreakpointSite(BreakpointSite *bp_site)
+{
+ return EnableSoftwareBreakpoint(bp_site);
+}
+
+Error
+ProcessFreeBSD::DisableBreakpointSite(BreakpointSite *bp_site)
+{
+ return DisableSoftwareBreakpoint(bp_site);
+}
+
+Error
+ProcessFreeBSD::EnableWatchpoint(Watchpoint *wp, bool notify)
+{
+ Error error;
+ if (wp)
+ {
+ user_id_t watchID = wp->GetID();
+ addr_t addr = wp->GetLoadAddress();
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ if (log)
+ log->Printf ("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64 ")",
+ watchID);
+ if (wp->IsEnabled())
+ {
+ if (log)
+ log->Printf("ProcessFreeBSD::EnableWatchpoint(watchID = %" PRIu64
+ ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.",
+ watchID, (uint64_t)addr);
+ return error;
+ }
+
+ // Try to find a vacant watchpoint slot in the inferiors' main thread
+ uint32_t wp_hw_index = LLDB_INVALID_INDEX32;
+ Mutex::Locker lock(m_thread_list.GetMutex());
+ FreeBSDThread *thread = static_cast<FreeBSDThread*>(
+ m_thread_list.GetThreadAtIndex(0, false).get());
+
+ if (thread)
+ wp_hw_index = thread->FindVacantWatchpointIndex();
+
+ if (wp_hw_index == LLDB_INVALID_INDEX32)
+ {
+ error.SetErrorString("Setting hardware watchpoint failed.");
+ }
+ else
+ {
+ wp->SetHardwareIndex(wp_hw_index);
+ bool wp_enabled = true;
+ uint32_t thread_count = m_thread_list.GetSize(false);
+ for (uint32_t i = 0; i < thread_count; ++i)
+ {
+ thread = static_cast<FreeBSDThread*>(
+ m_thread_list.GetThreadAtIndex(i, false).get());
+ if (thread)
+ wp_enabled &= thread->EnableHardwareWatchpoint(wp);
+ else
+ wp_enabled = false;
+ }
+ if (wp_enabled)
+ {
+ wp->SetEnabled(true, notify);
+ return error;
+ }
+ else
+ {
+ // Watchpoint enabling failed on at least one
+ // of the threads so roll back all of them
+ DisableWatchpoint(wp, false);
+ error.SetErrorString("Setting hardware watchpoint failed");
+ }
+ }
+ }
+ else
+ error.SetErrorString("Watchpoint argument was NULL.");
+ return error;
+}
+
+Error
+ProcessFreeBSD::DisableWatchpoint(Watchpoint *wp, bool notify)
+{
+ Error error;
+ if (wp)
+ {
+ user_id_t watchID = wp->GetID();
+ addr_t addr = wp->GetLoadAddress();
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+ if (log)
+ log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64 ")",
+ watchID);
+ if (!wp->IsEnabled())
+ {
+ if (log)
+ log->Printf("ProcessFreeBSD::DisableWatchpoint(watchID = %" PRIu64
+ ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.",
+ watchID, (uint64_t)addr);
+ // This is needed (for now) to keep watchpoints disabled correctly
+ wp->SetEnabled(false, notify);
+ return error;
+ }
+
+ if (wp->IsHardware())
+ {
+ bool wp_disabled = true;
+ Mutex::Locker lock(m_thread_list.GetMutex());
+ uint32_t thread_count = m_thread_list.GetSize(false);
+ for (uint32_t i = 0; i < thread_count; ++i)
+ {
+ FreeBSDThread *thread = static_cast<FreeBSDThread*>(
+ m_thread_list.GetThreadAtIndex(i, false).get());
+ if (thread)
+ wp_disabled &= thread->DisableHardwareWatchpoint(wp);
+ else
+ wp_disabled = false;
+ }
+ if (wp_disabled)
+ {
+ wp->SetHardwareIndex(LLDB_INVALID_INDEX32);
+ wp->SetEnabled(false, notify);
+ return error;
+ }
+ else
+ error.SetErrorString("Disabling hardware watchpoint failed");
+ }
+ }
+ else
+ error.SetErrorString("Watchpoint argument was NULL.");
+ return error;
+}
+
+Error
+ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num)
+{
+ Error error;
+ Mutex::Locker lock(m_thread_list.GetMutex());
+ FreeBSDThread *thread = static_cast<FreeBSDThread*>(
+ m_thread_list.GetThreadAtIndex(0, false).get());
+ if (thread)
+ num = thread->NumSupportedHardwareWatchpoints();
+ else
+ error.SetErrorString("Process does not exist.");
+ return error;
+}
+
+Error
+ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num, bool &after)
+{
+ Error error = GetWatchpointSupportInfo(num);
+ // Watchpoints trigger and halt the inferior after
+ // the corresponding instruction has been executed.
+ after = true;
+ return error;
+}
+
+uint32_t
+ProcessFreeBSD::UpdateThreadListIfNeeded()
+{
+ Mutex::Locker lock(m_thread_list.GetMutex());
+ // Do not allow recursive updates.
+ return m_thread_list.GetSize(false);
+}
+
+#if 0
+bool
+ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
+{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("ProcessFreeBSD::%s() (pid = %" PRIi64 ")", __FUNCTION__, GetID());
+
+ bool has_updated = false;
+ // Update the process thread list with this new thread.
+ // FIXME: We should be using tid, not pid.
+ assert(m_monitor);
+ ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));
+ if (!thread_sp) {
+ thread_sp.reset(CreateNewFreeBSDThread(*this, GetID()));
+ has_updated = true;
+ }
+
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("ProcessFreeBSD::%s() updated pid = %" PRIi64, __FUNCTION__, GetID());
+ new_thread_list.AddThread(thread_sp);
+
+ return has_updated; // the list has been updated
+}
+#endif
+
+ByteOrder
+ProcessFreeBSD::GetByteOrder() const
+{
+ // FIXME: We should be able to extract this value directly. See comment in
+ // ProcessFreeBSD().
+ return m_byte_order;
+}
+
+size_t
+ProcessFreeBSD::PutSTDIN(const char *buf, size_t len, Error &error)
+{
+ ssize_t status;
+ if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0)
+ {
+ error.SetErrorToErrno();
+ return 0;
+ }
+ return status;
+}
+
+//------------------------------------------------------------------------------
+// Utility functions.
+
+bool
+ProcessFreeBSD::HasExited()
+{
+ switch (GetPrivateState())
+ {
+ default:
+ break;
+
+ case eStateDetached:
+ case eStateExited:
+ return true;
+ }
+
+ return false;
+}
+
+bool
+ProcessFreeBSD::IsStopped()
+{
+ switch (GetPrivateState())
+ {
+ default:
+ break;
+
+ case eStateStopped:
+ case eStateCrashed:
+ case eStateSuspended:
+ return true;
+ }
+
+ return false;
+}
+
+bool
+ProcessFreeBSD::IsAThreadRunning()
+{
+ bool is_running = false;
+ Mutex::Locker lock(m_thread_list.GetMutex());
+ uint32_t thread_count = m_thread_list.GetSize(false);
+ for (uint32_t i = 0; i < thread_count; ++i)
+ {
+ FreeBSDThread *thread = static_cast<FreeBSDThread*>(
+ m_thread_list.GetThreadAtIndex(i, false).get());
+ StateType thread_state = thread->GetState();
+ if (thread_state == eStateRunning || thread_state == eStateStepping)
+ {
+ is_running = true;
+ break;
+ }
+ }
+ return is_running;
+}
+
+const DataBufferSP
+ProcessFreeBSD::GetAuxvData ()
+{
+ // If we're the local platform, we can ask the host for auxv data.
+ PlatformSP platform_sp = GetTarget().GetPlatform ();
+ if (platform_sp && platform_sp->IsHost ())
+ return lldb_private::Host::GetAuxvData(this);
+
+ // Somewhat unexpected - the process is not running locally or we don't have a platform.
+ assert (false && "no platform or not the host - how did we get here with ProcessFreeBSD?");
+ return DataBufferSP ();
+}
diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
index d6ae3462c73b..3cc46f489875 100644
--- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
+++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
@@ -13,18 +13,20 @@
// C Includes
// C++ Includes
+#include <set>
#include <queue>
// Other libraries and framework includes
#include "lldb/Target/Process.h"
#include "lldb/Target/ThreadList.h"
#include "ProcessMessage.h"
-#include "ProcessPOSIX.h"
+#include "ProcessFreeBSD.h"
class ProcessMonitor;
+class FreeBSDThread;
class ProcessFreeBSD :
- public ProcessPOSIX
+ public lldb_private::Process
{
public:
@@ -32,7 +34,7 @@ public:
// Static functions.
//------------------------------------------------------------------
static lldb::ProcessSP
- CreateInstance(lldb_private::Target& target,
+ CreateInstance(lldb::TargetSP target_sp,
lldb_private::Listener &listener,
const lldb_private::FileSpec *crash_file_path);
@@ -51,45 +53,188 @@ public:
//------------------------------------------------------------------
// Constructors and destructors
//------------------------------------------------------------------
- ProcessFreeBSD(lldb_private::Target& target,
- lldb_private::Listener &listener);
-
- virtual lldb_private::Error
- DoDetach(bool keep_stopped);
-
- virtual bool
- UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list);
+ ProcessFreeBSD(lldb::TargetSP target_sp,
+ lldb_private::Listener &listener,
+ lldb::UnixSignalsSP &unix_signals_sp);
- virtual lldb_private::Error
- DoResume();
+ ~ProcessFreeBSD();
virtual lldb_private::Error
- WillResume();
-
- virtual void
- SendMessage(const ProcessMessage &message);
+ WillResume() override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
virtual lldb_private::ConstString
- GetPluginName();
+ GetPluginName() override;
virtual uint32_t
- GetPluginVersion();
+ GetPluginVersion() override;
+
+public:
+ //------------------------------------------------------------------
+ // Process protocol.
+ //------------------------------------------------------------------
+ void
+ Finalize() override;
+
+ bool
+ CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override;
+
+ lldb_private::Error
+ WillLaunch(lldb_private::Module *module) override;
+
+ lldb_private::Error
+ DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info) override;
+
+ lldb_private::Error
+ DoLaunch (lldb_private::Module *exe_module,
+ lldb_private::ProcessLaunchInfo &launch_info) override;
+
+ void
+ DidLaunch() override;
+
+ lldb_private::Error
+ DoResume() override;
+
+ lldb_private::Error
+ DoHalt(bool &caused_stop) override;
+
+ lldb_private::Error
+ DoDetach(bool keep_stopped) override;
+
+ lldb_private::Error
+ DoSignal(int signal) override;
+
+ lldb_private::Error
+ DoDestroy() override;
+
+ void
+ DoDidExec() override;
+
+ void
+ RefreshStateAfterStop() override;
+
+ bool
+ IsAlive() override;
+
+ size_t
+ DoReadMemory(lldb::addr_t vm_addr,
+ void *buf,
+ size_t size,
+ lldb_private::Error &error) override;
+
+ size_t
+ DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
+ lldb_private::Error &error) override;
+
+ lldb::addr_t
+ DoAllocateMemory(size_t size, uint32_t permissions,
+ lldb_private::Error &error) override;
+
+ lldb_private::Error
+ DoDeallocateMemory(lldb::addr_t ptr) override;
+
+ virtual size_t
+ GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site);
+ lldb_private::Error
+ EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
+
+ lldb_private::Error
+ DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
+
+ lldb_private::Error
+ EnableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override;
+
+ lldb_private::Error
+ DisableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override;
+
+ lldb_private::Error
+ GetWatchpointSupportInfo(uint32_t &num) override;
+
+ lldb_private::Error
+ GetWatchpointSupportInfo(uint32_t &num, bool &after) override;
+
+ virtual uint32_t
+ UpdateThreadListIfNeeded();
+
+ bool
+ UpdateThreadList(lldb_private::ThreadList &old_thread_list,
+ lldb_private::ThreadList &new_thread_list) override;
+
+ virtual lldb::ByteOrder
+ GetByteOrder() const;
+
+ lldb::addr_t
+ GetImageInfoAddress() override;
+
+ size_t
+ PutSTDIN(const char *buf, size_t len, lldb_private::Error &error) override;
+
+ const lldb::DataBufferSP
+ GetAuxvData () override;
+
+ //--------------------------------------------------------------------------
+ // ProcessFreeBSD internal API.
+
+ /// Registers the given message with this process.
virtual void
- GetPluginCommandHelp(const char *command, lldb_private::Stream *strm);
+ SendMessage(const ProcessMessage &message);
- virtual lldb_private::Error
- ExecutePluginCommand(lldb_private::Args &command,
- lldb_private::Stream *strm);
+ ProcessMonitor &
+ GetMonitor() { assert(m_monitor); return *m_monitor; }
+
+ lldb_private::FileSpec
+ GetFileSpec(const lldb_private::FileAction *file_action,
+ const lldb_private::FileSpec &default_file_spec,
+ const lldb_private::FileSpec &dbg_pts_file_spec);
+
+ /// Adds the thread to the list of threads for which we have received the initial stopping signal.
+ /// The \p stop_tid parameter indicates the thread which the stop happened for.
+ bool
+ AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid);
+
+ bool
+ WaitingForInitialStop(lldb::tid_t stop_tid);
- virtual lldb_private::Log *
- EnablePluginLogging(lldb_private::Stream *strm,
- lldb_private::Args &command);
+ virtual FreeBSDThread *
+ CreateNewFreeBSDThread(lldb_private::Process &process, lldb::tid_t tid);
protected:
+ /// Target byte order.
+ lldb::ByteOrder m_byte_order;
+
+ /// Process monitor;
+ ProcessMonitor *m_monitor;
+
+ /// The module we are executing.
+ lldb_private::Module *m_module;
+
+ /// Message queue notifying this instance of inferior process state changes.
+ lldb_private::Mutex m_message_mutex;
+ std::queue<ProcessMessage> m_message_queue;
+
+ /// Drive any exit events to completion.
+ bool m_exit_now;
+
+ /// Returns true if the process has exited.
+ bool HasExited();
+
+ /// Returns true if the process is stopped.
+ bool IsStopped();
+
+ /// Returns true if at least one running is currently running
+ bool IsAThreadRunning();
+
+ typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
+ MMapMap m_addr_to_mmap_size;
+
+ typedef std::set<lldb::tid_t> ThreadStopSet;
+ /// Every thread begins with a stop signal. This keeps track
+ /// of the threads for which we have received the stop signal.
+ ThreadStopSet m_seen_initial_stop;
+
friend class FreeBSDThread;
typedef std::vector<lldb::tid_t> tid_collection;
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
index 427c66ce3e6b..ceb527b61d80 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -32,7 +32,7 @@
#include "lldb/Utility/PseudoTerminal.h"
#include "Plugins/Process/POSIX/CrashReason.h"
-#include "POSIXThread.h"
+#include "FreeBSDThread.h"
#include "ProcessFreeBSD.h"
#include "ProcessPOSIXLog.h"
#include "ProcessMonitor.h"
@@ -804,7 +804,7 @@ ProcessMonitor::AttachArgs::~AttachArgs()
/// launching or attaching to the inferior process, and then 2) servicing
/// operations such as register reads/writes, stepping, etc. See the comments
/// on the Operation class for more info as to why this is needed.
-ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
+ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process,
Module *module,
const char *argv[],
const char *envp[],
@@ -865,7 +865,7 @@ WAIT_AGAIN:
}
}
-ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
+ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process,
lldb::pid_t pid,
lldb_private::Error &error)
: m_process(static_cast<ProcessFreeBSD *>(process)),
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
index 20ce582d973e..07fa6b7869ad 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
@@ -49,7 +49,7 @@ public:
/// Launches an inferior process ready for debugging. Forms the
/// implementation of Process::DoLaunch.
- ProcessMonitor(ProcessPOSIX *process,
+ ProcessMonitor(ProcessFreeBSD *process,
lldb_private::Module *module,
char const *argv[],
char const *envp[],
@@ -60,7 +60,7 @@ public:
const lldb_private::ProcessLaunchInfo &launch_info,
lldb_private::Error &error);
- ProcessMonitor(ProcessPOSIX *process,
+ ProcessMonitor(ProcessFreeBSD *process,
lldb::pid_t pid,
lldb_private::Error &error);
diff --git a/source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp b/source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp
deleted file mode 100644
index 360382e2e63a..000000000000
--- a/source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp
+++ /dev/null
@@ -1,939 +0,0 @@
-//===-- ProcessPOSIX.cpp ----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-#include <errno.h>
-
-// C++ Includes
-// Other libraries and framework includes
-#include "lldb/Breakpoint/BreakpointLocation.h"
-#include "lldb/Breakpoint/Watchpoint.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/State.h"
-#include "lldb/Host/FileSpec.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Target/DynamicLoader.h"
-#include "lldb/Target/Platform.h"
-#include "lldb/Target/Target.h"
-
-#include "ProcessPOSIX.h"
-#include "ProcessPOSIXLog.h"
-#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
-#include "POSIXThread.h"
-#include "ProcessMonitor.h"
-
-#include "lldb/Host/posix/Fcntl.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-//------------------------------------------------------------------------------
-// Constructors and destructors.
-
-ProcessPOSIX::ProcessPOSIX(Target& target, Listener &listener, UnixSignalsSP &unix_signals_sp)
- : Process(target, listener, unix_signals_sp),
- m_byte_order(lldb::endian::InlHostByteOrder()),
- m_monitor(NULL),
- m_module(NULL),
- m_message_mutex (Mutex::eMutexTypeRecursive),
- m_exit_now(false),
- m_seen_initial_stop()
-{
- // FIXME: Putting this code in the ctor and saving the byte order in a
- // member variable is a hack to avoid const qual issues in GetByteOrder.
- lldb::ModuleSP module = GetTarget().GetExecutableModule();
- if (module && module->GetObjectFile())
- m_byte_order = module->GetObjectFile()->GetByteOrder();
-}
-
-ProcessPOSIX::~ProcessPOSIX()
-{
- delete m_monitor;
-}
-
-//------------------------------------------------------------------------------
-// Process protocol.
-void
-ProcessPOSIX::Finalize()
-{
- Process::Finalize();
-
- if (m_monitor)
- m_monitor->StopMonitor();
-}
-
-bool
-ProcessPOSIX::CanDebug(Target &target, bool plugin_specified_by_name)
-{
- // For now we are just making sure the file exists for a given module
- ModuleSP exe_module_sp(target.GetExecutableModule());
- if (exe_module_sp.get())
- return exe_module_sp->GetFileSpec().Exists();
- // If there is no executable module, we return true since we might be preparing to attach.
- return true;
-}
-
-Error
-ProcessPOSIX::DoAttachToProcessWithID (lldb::pid_t pid, const ProcessAttachInfo &attach_info)
-{
- Error error;
- assert(m_monitor == NULL);
-
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("ProcessPOSIX::%s(pid = %" PRIi64 ")", __FUNCTION__, GetID());
-
- m_monitor = new ProcessMonitor(this, pid, error);
-
- if (!error.Success())
- return error;
-
- PlatformSP platform_sp (m_target.GetPlatform ());
- assert (platform_sp.get());
- if (!platform_sp)
- return error; // FIXME: Detatch?
-
- // Find out what we can about this process
- ProcessInstanceInfo process_info;
- platform_sp->GetProcessInfo (pid, process_info);
-
- // Resolve the executable module
- ModuleSP exe_module_sp;
- FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
- ModuleSpec exe_module_spec(process_info.GetExecutableFile(), m_target.GetArchitecture());
- error = platform_sp->ResolveExecutable(exe_module_spec,
- exe_module_sp,
- executable_search_paths.GetSize() ? &executable_search_paths : NULL);
- if (!error.Success())
- return error;
-
- // Fix the target architecture if necessary
- const ArchSpec &module_arch = exe_module_sp->GetArchitecture();
- if (module_arch.IsValid() && !m_target.GetArchitecture().IsExactMatch(module_arch))
- m_target.SetArchitecture(module_arch);
-
- // Initialize the target module list
- m_target.SetExecutableModule (exe_module_sp, true);
-
- SetSTDIOFileDescriptor(m_monitor->GetTerminalFD());
-
- SetID(pid);
-
- return error;
-}
-
-Error
-ProcessPOSIX::WillLaunch(Module* module)
-{
- Error error;
- return error;
-}
-
-FileSpec
-ProcessPOSIX::GetFileSpec(const lldb_private::FileAction *file_action,
- const FileSpec &default_file_spec,
- const FileSpec &dbg_pts_file_spec)
-{
- FileSpec file_spec{};
-
- if (file_action && file_action->GetAction() == FileAction::eFileActionOpen)
- {
- file_spec = file_action->GetFileSpec();
- // By default the stdio paths passed in will be pseudo-terminal
- // (/dev/pts). If so, convert to using a different default path
- // instead to redirect I/O to the debugger console. This should
- // also handle user overrides to /dev/null or a different file.
- if (!file_spec || file_spec == dbg_pts_file_spec)
- file_spec = default_file_spec;
- }
- return file_spec;
-}
-
-Error
-ProcessPOSIX::DoLaunch (Module *module,
- ProcessLaunchInfo &launch_info)
-{
- Error error;
- assert(m_monitor == NULL);
-
- FileSpec working_dir = launch_info.GetWorkingDirectory();
- if (working_dir &&
- (!working_dir.ResolvePath() ||
- working_dir.GetFileType() != FileSpec::eFileTypeDirectory))
- {
- error.SetErrorStringWithFormat("No such file or directory: %s",
- working_dir.GetCString());
- return error;
- }
-
- SetPrivateState(eStateLaunching);
-
- const lldb_private::FileAction *file_action;
-
- // Default of empty will mean to use existing open file descriptors
- FileSpec stdin_file_spec{};
- FileSpec stdout_file_spec{};
- FileSpec stderr_file_spec{};
-
- const FileSpec dbg_pts_file_spec{launch_info.GetPTY().GetSlaveName(NULL,0), false};
-
- file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
- stdin_file_spec = GetFileSpec(file_action, stdin_file_spec, dbg_pts_file_spec);
-
- file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
- stdout_file_spec = GetFileSpec(file_action, stdout_file_spec, dbg_pts_file_spec);
-
- file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
- stderr_file_spec = GetFileSpec(file_action, stderr_file_spec, dbg_pts_file_spec);
-
- m_monitor = new ProcessMonitor(this,
- module,
- launch_info.GetArguments().GetConstArgumentVector(),
- launch_info.GetEnvironmentEntries().GetConstArgumentVector(),
- stdin_file_spec,
- stdout_file_spec,
- stderr_file_spec,
- working_dir,
- launch_info,
- error);
-
- m_module = module;
-
- if (!error.Success())
- return error;
-
- int terminal = m_monitor->GetTerminalFD();
- if (terminal >= 0) {
- // The reader thread will close the file descriptor when done, so we pass it a copy.
- int stdio = fcntl(terminal, F_DUPFD_CLOEXEC, 0);
- if (stdio == -1) {
- error.SetErrorToErrno();
- return error;
- }
- SetSTDIOFileDescriptor(stdio);
- }
-
- SetID(m_monitor->GetPID());
- return error;
-}
-
-void
-ProcessPOSIX::DidLaunch()
-{
-}
-
-Error
-ProcessPOSIX::DoResume()
-{
- StateType state = GetPrivateState();
-
- assert(state == eStateStopped);
-
- SetPrivateState(eStateRunning);
-
- bool did_resume = false;
-
- Mutex::Locker lock(m_thread_list.GetMutex());
-
- uint32_t thread_count = m_thread_list.GetSize(false);
- for (uint32_t i = 0; i < thread_count; ++i)
- {
- POSIXThread *thread = static_cast<POSIXThread*>(
- m_thread_list.GetThreadAtIndex(i, false).get());
- did_resume = thread->Resume() || did_resume;
- }
- assert(did_resume && "Process resume failed!");
-
- return Error();
-}
-
-addr_t
-ProcessPOSIX::GetImageInfoAddress()
-{
- Target *target = &GetTarget();
- ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
- Address addr = obj_file->GetImageInfoAddress(target);
-
- if (addr.IsValid())
- return addr.GetLoadAddress(target);
- return LLDB_INVALID_ADDRESS;
-}
-
-Error
-ProcessPOSIX::DoHalt(bool &caused_stop)
-{
- Error error;
-
- if (IsStopped())
- {
- caused_stop = false;
- }
- else if (kill(GetID(), SIGSTOP))
- {
- caused_stop = false;
- error.SetErrorToErrno();
- }
- else
- {
- caused_stop = true;
- }
- return error;
-}
-
-Error
-ProcessPOSIX::DoSignal(int signal)
-{
- Error error;
-
- if (kill(GetID(), signal))
- error.SetErrorToErrno();
-
- return error;
-}
-
-Error
-ProcessPOSIX::DoDestroy()
-{
- Error error;
-
- if (!HasExited())
- {
- assert(m_monitor);
- m_exit_now = true;
- if (GetID() == LLDB_INVALID_PROCESS_ID)
- {
- error.SetErrorString("invalid process id");
- return error;
- }
- if (!m_monitor->Kill())
- {
- error.SetErrorToErrno();
- return error;
- }
-
- SetPrivateState(eStateExited);
- }
-
- return error;
-}
-
-void
-ProcessPOSIX::DoDidExec()
-{
- Target *target = &GetTarget();
- if (target)
- {
- PlatformSP platform_sp (target->GetPlatform());
- assert (platform_sp.get());
- if (platform_sp)
- {
- ProcessInstanceInfo process_info;
- platform_sp->GetProcessInfo(GetID(), process_info);
- ModuleSP exe_module_sp;
- ModuleSpec exe_module_spec(process_info.GetExecutableFile(), target->GetArchitecture());
- FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
- Error error = platform_sp->ResolveExecutable(exe_module_spec,
- exe_module_sp,
- executable_search_paths.GetSize() ? &executable_search_paths : NULL);
- if (!error.Success())
- return;
- target->SetExecutableModule(exe_module_sp, true);
- }
- }
-}
-
-void
-ProcessPOSIX::SendMessage(const ProcessMessage &message)
-{
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
-
- Mutex::Locker lock(m_message_mutex);
-
- Mutex::Locker thread_lock(m_thread_list.GetMutex());
-
- POSIXThread *thread = static_cast<POSIXThread*>(
- m_thread_list.FindThreadByID(message.GetTID(), false).get());
-
- switch (message.GetKind())
- {
- case ProcessMessage::eInvalidMessage:
- return;
-
- case ProcessMessage::eAttachMessage:
- SetPrivateState(eStateStopped);
- return;
-
- case ProcessMessage::eLimboMessage:
- assert(thread);
- thread->SetState(eStateStopped);
- if (message.GetTID() == GetID())
- {
- m_exit_status = message.GetExitStatus();
- if (m_exit_now)
- {
- SetPrivateState(eStateExited);
- m_monitor->Detach(GetID());
- }
- else
- {
- SetPrivateState(eStateStopped);
- }
- }
- else
- {
- SetPrivateState(eStateStopped);
- }
- break;
-
- case ProcessMessage::eExitMessage:
- if (thread != nullptr)
- thread->SetState(eStateExited);
- else
- {
- if (log)
- log->Warning ("ProcessPOSIX::%s eExitMessage for TID %" PRIu64 " failed to find a thread to mark as eStateExited, ignoring", __FUNCTION__, message.GetTID ());
- }
-
- // FIXME: I'm not sure we need to do this.
- if (message.GetTID() == GetID())
- {
- SetExitStatus(message.GetExitStatus(), NULL);
- }
- else if (!IsAThreadRunning())
- SetPrivateState(eStateStopped);
- break;
-
- case ProcessMessage::eSignalMessage:
- case ProcessMessage::eSignalDeliveredMessage:
- if (message.GetSignal() == SIGSTOP &&
- AddThreadForInitialStopIfNeeded(message.GetTID()))
- return;
- // Intentional fall-through
-
- case ProcessMessage::eBreakpointMessage:
- case ProcessMessage::eTraceMessage:
- case ProcessMessage::eWatchpointMessage:
- case ProcessMessage::eCrashMessage:
- assert(thread);
- thread->SetState(eStateStopped);
- SetPrivateState(eStateStopped);
- break;
-
- case ProcessMessage::eNewThreadMessage:
- {
- lldb::tid_t new_tid = message.GetChildTID();
- if (WaitingForInitialStop(new_tid))
- {
- m_monitor->WaitForInitialTIDStop(new_tid);
- }
- assert(thread);
- thread->SetState(eStateStopped);
- SetPrivateState(eStateStopped);
- break;
- }
-
- case ProcessMessage::eExecMessage:
- {
- assert(thread);
- thread->SetState(eStateStopped);
- SetPrivateState(eStateStopped);
- break;
- }
- }
-
-
- m_message_queue.push(message);
-}
-
-bool
-ProcessPOSIX::AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid)
-{
- bool added_to_set = false;
- ThreadStopSet::iterator it = m_seen_initial_stop.find(stop_tid);
- if (it == m_seen_initial_stop.end())
- {
- m_seen_initial_stop.insert(stop_tid);
- added_to_set = true;
- }
- return added_to_set;
-}
-
-bool
-ProcessPOSIX::WaitingForInitialStop(lldb::tid_t stop_tid)
-{
- return (m_seen_initial_stop.find(stop_tid) == m_seen_initial_stop.end());
-}
-
-POSIXThread *
-ProcessPOSIX::CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid)
-{
- return new POSIXThread(process, tid);
-}
-
-void
-ProcessPOSIX::RefreshStateAfterStop()
-{
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("ProcessPOSIX::%s(), message_queue size = %d", __FUNCTION__, (int)m_message_queue.size());
-
- Mutex::Locker lock(m_message_mutex);
-
- // This method used to only handle one message. Changing it to loop allows
- // it to handle the case where we hit a breakpoint while handling a different
- // breakpoint.
- while (!m_message_queue.empty())
- {
- ProcessMessage &message = m_message_queue.front();
-
- // Resolve the thread this message corresponds to and pass it along.
- lldb::tid_t tid = message.GetTID();
- if (log)
- log->Printf ("ProcessPOSIX::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid);
-
- if (message.GetKind() == ProcessMessage::eNewThreadMessage)
- {
- if (log)
- log->Printf ("ProcessPOSIX::%s() adding thread, tid = %" PRIi64, __FUNCTION__, message.GetChildTID());
- lldb::tid_t child_tid = message.GetChildTID();
- ThreadSP thread_sp;
- thread_sp.reset(CreateNewPOSIXThread(*this, child_tid));
-
- Mutex::Locker lock(m_thread_list.GetMutex());
-
- m_thread_list.AddThread(thread_sp);
- }
-
- m_thread_list.RefreshStateAfterStop();
-
- POSIXThread *thread = static_cast<POSIXThread*>(
- GetThreadList().FindThreadByID(tid, false).get());
- if (thread)
- thread->Notify(message);
-
- if (message.GetKind() == ProcessMessage::eExitMessage)
- {
- // FIXME: We should tell the user about this, but the limbo message is probably better for that.
- if (log)
- log->Printf ("ProcessPOSIX::%s() removing thread, tid = %" PRIi64, __FUNCTION__, tid);
-
- Mutex::Locker lock(m_thread_list.GetMutex());
-
- ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false);
- thread_sp.reset();
- m_seen_initial_stop.erase(tid);
- }
-
- m_message_queue.pop();
- }
-}
-
-bool
-ProcessPOSIX::IsAlive()
-{
- StateType state = GetPrivateState();
- return state != eStateDetached
- && state != eStateExited
- && state != eStateInvalid
- && state != eStateUnloaded;
-}
-
-size_t
-ProcessPOSIX::DoReadMemory(addr_t vm_addr,
- void *buf, size_t size, Error &error)
-{
- assert(m_monitor);
- return m_monitor->ReadMemory(vm_addr, buf, size, error);
-}
-
-size_t
-ProcessPOSIX::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size,
- Error &error)
-{
- assert(m_monitor);
- return m_monitor->WriteMemory(vm_addr, buf, size, error);
-}
-
-addr_t
-ProcessPOSIX::DoAllocateMemory(size_t size, uint32_t permissions,
- Error &error)
-{
- addr_t allocated_addr = LLDB_INVALID_ADDRESS;
-
- unsigned prot = 0;
- if (permissions & lldb::ePermissionsReadable)
- prot |= eMmapProtRead;
- if (permissions & lldb::ePermissionsWritable)
- prot |= eMmapProtWrite;
- if (permissions & lldb::ePermissionsExecutable)
- prot |= eMmapProtExec;
-
- if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
- eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {
- m_addr_to_mmap_size[allocated_addr] = size;
- error.Clear();
- } else {
- allocated_addr = LLDB_INVALID_ADDRESS;
- error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions));
- }
-
- return allocated_addr;
-}
-
-Error
-ProcessPOSIX::DoDeallocateMemory(lldb::addr_t addr)
-{
- Error error;
- MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
- if (pos != m_addr_to_mmap_size.end() &&
- InferiorCallMunmap(this, addr, pos->second))
- m_addr_to_mmap_size.erase (pos);
- else
- error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr);
-
- return error;
-}
-
-size_t
-ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
-{
- static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xD4 };
- static const uint8_t g_i386_opcode[] = { 0xCC };
-
- ArchSpec arch = GetTarget().GetArchitecture();
- const uint8_t *opcode = NULL;
- size_t opcode_size = 0;
-
- switch (arch.GetMachine())
- {
- default:
- assert(false && "CPU type not supported!");
- break;
-
- case llvm::Triple::arm:
- {
- // The ARM reference recommends the use of 0xe7fddefe and 0xdefe
- // but the linux kernel does otherwise.
- static const uint8_t g_arm_breakpoint_opcode[] = { 0xf0, 0x01, 0xf0, 0xe7 };
- static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde };
-
- lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0));
- AddressClass addr_class = eAddressClassUnknown;
-
- if (bp_loc_sp)
- addr_class = bp_loc_sp->GetAddress ().GetAddressClass ();
-
- if (addr_class == eAddressClassCodeAlternateISA
- || (addr_class == eAddressClassUnknown
- && bp_loc_sp->GetAddress().GetOffset() & 1))
- {
- opcode = g_thumb_breakpoint_opcode;
- opcode_size = sizeof(g_thumb_breakpoint_opcode);
- }
- else
- {
- opcode = g_arm_breakpoint_opcode;
- opcode_size = sizeof(g_arm_breakpoint_opcode);
- }
- }
- break;
- case llvm::Triple::aarch64:
- opcode = g_aarch64_opcode;
- opcode_size = sizeof(g_aarch64_opcode);
- break;
-
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- opcode = g_i386_opcode;
- opcode_size = sizeof(g_i386_opcode);
- break;
- }
-
- bp_site->SetTrapOpcode(opcode, opcode_size);
- return opcode_size;
-}
-
-Error
-ProcessPOSIX::EnableBreakpointSite(BreakpointSite *bp_site)
-{
- return EnableSoftwareBreakpoint(bp_site);
-}
-
-Error
-ProcessPOSIX::DisableBreakpointSite(BreakpointSite *bp_site)
-{
- return DisableSoftwareBreakpoint(bp_site);
-}
-
-Error
-ProcessPOSIX::EnableWatchpoint(Watchpoint *wp, bool notify)
-{
- Error error;
- if (wp)
- {
- user_id_t watchID = wp->GetID();
- addr_t addr = wp->GetLoadAddress();
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- if (log)
- log->Printf ("ProcessPOSIX::EnableWatchpoint(watchID = %" PRIu64 ")",
- watchID);
- if (wp->IsEnabled())
- {
- if (log)
- log->Printf("ProcessPOSIX::EnableWatchpoint(watchID = %" PRIu64
- ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.",
- watchID, (uint64_t)addr);
- return error;
- }
-
- // Try to find a vacant watchpoint slot in the inferiors' main thread
- uint32_t wp_hw_index = LLDB_INVALID_INDEX32;
- Mutex::Locker lock(m_thread_list.GetMutex());
- POSIXThread *thread = static_cast<POSIXThread*>(
- m_thread_list.GetThreadAtIndex(0, false).get());
-
- if (thread)
- wp_hw_index = thread->FindVacantWatchpointIndex();
-
- if (wp_hw_index == LLDB_INVALID_INDEX32)
- {
- error.SetErrorString("Setting hardware watchpoint failed.");
- }
- else
- {
- wp->SetHardwareIndex(wp_hw_index);
- bool wp_enabled = true;
- uint32_t thread_count = m_thread_list.GetSize(false);
- for (uint32_t i = 0; i < thread_count; ++i)
- {
- thread = static_cast<POSIXThread*>(
- m_thread_list.GetThreadAtIndex(i, false).get());
- if (thread)
- wp_enabled &= thread->EnableHardwareWatchpoint(wp);
- else
- wp_enabled = false;
- }
- if (wp_enabled)
- {
- wp->SetEnabled(true, notify);
- return error;
- }
- else
- {
- // Watchpoint enabling failed on at least one
- // of the threads so roll back all of them
- DisableWatchpoint(wp, false);
- error.SetErrorString("Setting hardware watchpoint failed");
- }
- }
- }
- else
- error.SetErrorString("Watchpoint argument was NULL.");
- return error;
-}
-
-Error
-ProcessPOSIX::DisableWatchpoint(Watchpoint *wp, bool notify)
-{
- Error error;
- if (wp)
- {
- user_id_t watchID = wp->GetID();
- addr_t addr = wp->GetLoadAddress();
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
- if (log)
- log->Printf("ProcessPOSIX::DisableWatchpoint(watchID = %" PRIu64 ")",
- watchID);
- if (!wp->IsEnabled())
- {
- if (log)
- log->Printf("ProcessPOSIX::DisableWatchpoint(watchID = %" PRIu64
- ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.",
- watchID, (uint64_t)addr);
- // This is needed (for now) to keep watchpoints disabled correctly
- wp->SetEnabled(false, notify);
- return error;
- }
-
- if (wp->IsHardware())
- {
- bool wp_disabled = true;
- Mutex::Locker lock(m_thread_list.GetMutex());
- uint32_t thread_count = m_thread_list.GetSize(false);
- for (uint32_t i = 0; i < thread_count; ++i)
- {
- POSIXThread *thread = static_cast<POSIXThread*>(
- m_thread_list.GetThreadAtIndex(i, false).get());
- if (thread)
- wp_disabled &= thread->DisableHardwareWatchpoint(wp);
- else
- wp_disabled = false;
- }
- if (wp_disabled)
- {
- wp->SetHardwareIndex(LLDB_INVALID_INDEX32);
- wp->SetEnabled(false, notify);
- return error;
- }
- else
- error.SetErrorString("Disabling hardware watchpoint failed");
- }
- }
- else
- error.SetErrorString("Watchpoint argument was NULL.");
- return error;
-}
-
-Error
-ProcessPOSIX::GetWatchpointSupportInfo(uint32_t &num)
-{
- Error error;
- Mutex::Locker lock(m_thread_list.GetMutex());
- POSIXThread *thread = static_cast<POSIXThread*>(
- m_thread_list.GetThreadAtIndex(0, false).get());
- if (thread)
- num = thread->NumSupportedHardwareWatchpoints();
- else
- error.SetErrorString("Process does not exist.");
- return error;
-}
-
-Error
-ProcessPOSIX::GetWatchpointSupportInfo(uint32_t &num, bool &after)
-{
- Error error = GetWatchpointSupportInfo(num);
- // Watchpoints trigger and halt the inferior after
- // the corresponding instruction has been executed.
- after = true;
- return error;
-}
-
-uint32_t
-ProcessPOSIX::UpdateThreadListIfNeeded()
-{
- Mutex::Locker lock(m_thread_list.GetMutex());
- // Do not allow recursive updates.
- return m_thread_list.GetSize(false);
-}
-
-bool
-ProcessPOSIX::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
-{
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("ProcessPOSIX::%s() (pid = %" PRIi64 ")", __FUNCTION__, GetID());
-
- bool has_updated = false;
- // Update the process thread list with this new thread.
- // FIXME: We should be using tid, not pid.
- assert(m_monitor);
- ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));
- if (!thread_sp) {
- thread_sp.reset(CreateNewPOSIXThread(*this, GetID()));
- has_updated = true;
- }
-
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("ProcessPOSIX::%s() updated pid = %" PRIi64, __FUNCTION__, GetID());
- new_thread_list.AddThread(thread_sp);
-
- return has_updated; // the list has been updated
-}
-
-ByteOrder
-ProcessPOSIX::GetByteOrder() const
-{
- // FIXME: We should be able to extract this value directly. See comment in
- // ProcessPOSIX().
- return m_byte_order;
-}
-
-size_t
-ProcessPOSIX::PutSTDIN(const char *buf, size_t len, Error &error)
-{
- ssize_t status;
- if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0)
- {
- error.SetErrorToErrno();
- return 0;
- }
- return status;
-}
-
-//------------------------------------------------------------------------------
-// Utility functions.
-
-bool
-ProcessPOSIX::HasExited()
-{
- switch (GetPrivateState())
- {
- default:
- break;
-
- case eStateDetached:
- case eStateExited:
- return true;
- }
-
- return false;
-}
-
-bool
-ProcessPOSIX::IsStopped()
-{
- switch (GetPrivateState())
- {
- default:
- break;
-
- case eStateStopped:
- case eStateCrashed:
- case eStateSuspended:
- return true;
- }
-
- return false;
-}
-
-bool
-ProcessPOSIX::IsAThreadRunning()
-{
- bool is_running = false;
- Mutex::Locker lock(m_thread_list.GetMutex());
- uint32_t thread_count = m_thread_list.GetSize(false);
- for (uint32_t i = 0; i < thread_count; ++i)
- {
- POSIXThread *thread = static_cast<POSIXThread*>(
- m_thread_list.GetThreadAtIndex(i, false).get());
- StateType thread_state = thread->GetState();
- if (thread_state == eStateRunning || thread_state == eStateStepping)
- {
- is_running = true;
- break;
- }
- }
- return is_running;
-}
-
-const DataBufferSP
-ProcessPOSIX::GetAuxvData ()
-{
- // If we're the local platform, we can ask the host for auxv data.
- PlatformSP platform_sp = m_target.GetPlatform ();
- if (platform_sp && platform_sp->IsHost ())
- return lldb_private::Host::GetAuxvData(this);
-
- // Somewhat unexpected - the process is not running locally or we don't have a platform.
- assert (false && "no platform or not the host - how did we get here with ProcessPOSIX?");
- return DataBufferSP ();
-}
diff --git a/source/Plugins/Process/FreeBSD/ProcessPOSIX.h b/source/Plugins/Process/FreeBSD/ProcessPOSIX.h
deleted file mode 100644
index 627017c547dc..000000000000
--- a/source/Plugins/Process/FreeBSD/ProcessPOSIX.h
+++ /dev/null
@@ -1,205 +0,0 @@
-//===-- ProcessPOSIX.h ------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_ProcessPOSIX_H_
-#define liblldb_ProcessPOSIX_H_
-
-// C Includes
-
-// C++ Includes
-#include <queue>
-#include <set>
-
-// Other libraries and framework includes
-#include "lldb/Target/Process.h"
-#include "ProcessMessage.h"
-
-class ProcessMonitor;
-class POSIXThread;
-
-class ProcessPOSIX :
- public lldb_private::Process
-{
-public:
-
- //------------------------------------------------------------------
- // Constructors and destructors
- //------------------------------------------------------------------
- ProcessPOSIX(lldb_private::Target& target,
- lldb_private::Listener &listener,
- lldb::UnixSignalsSP &unix_signals_sp);
-
- virtual
- ~ProcessPOSIX();
-
- //------------------------------------------------------------------
- // Process protocol.
- //------------------------------------------------------------------
- void
- Finalize() override;
-
- bool
- CanDebug(lldb_private::Target &target, bool plugin_specified_by_name) override;
-
- lldb_private::Error
- WillLaunch(lldb_private::Module *module) override;
-
- lldb_private::Error
- DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info) override;
-
- lldb_private::Error
- DoLaunch (lldb_private::Module *exe_module,
- lldb_private::ProcessLaunchInfo &launch_info) override;
-
- void
- DidLaunch() override;
-
- lldb_private::Error
- DoResume() override;
-
- lldb_private::Error
- DoHalt(bool &caused_stop) override;
-
- lldb_private::Error
- DoDetach(bool keep_stopped) override = 0;
-
- lldb_private::Error
- DoSignal(int signal) override;
-
- lldb_private::Error
- DoDestroy() override;
-
- void
- DoDidExec() override;
-
- void
- RefreshStateAfterStop() override;
-
- bool
- IsAlive() override;
-
- size_t
- DoReadMemory(lldb::addr_t vm_addr,
- void *buf,
- size_t size,
- lldb_private::Error &error) override;
-
- size_t
- DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
- lldb_private::Error &error) override;
-
- lldb::addr_t
- DoAllocateMemory(size_t size, uint32_t permissions,
- lldb_private::Error &error) override;
-
- lldb_private::Error
- DoDeallocateMemory(lldb::addr_t ptr) override;
-
- virtual size_t
- GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site);
-
- lldb_private::Error
- EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
-
- lldb_private::Error
- DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
-
- lldb_private::Error
- EnableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override;
-
- lldb_private::Error
- DisableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true) override;
-
- lldb_private::Error
- GetWatchpointSupportInfo(uint32_t &num) override;
-
- lldb_private::Error
- GetWatchpointSupportInfo(uint32_t &num, bool &after) override;
-
- virtual uint32_t
- UpdateThreadListIfNeeded();
-
- bool
- UpdateThreadList(lldb_private::ThreadList &old_thread_list,
- lldb_private::ThreadList &new_thread_list) override = 0;
-
- virtual lldb::ByteOrder
- GetByteOrder() const;
-
- lldb::addr_t
- GetImageInfoAddress() override;
-
- size_t
- PutSTDIN(const char *buf, size_t len, lldb_private::Error &error) override;
-
- const lldb::DataBufferSP
- GetAuxvData () override;
-
- //--------------------------------------------------------------------------
- // ProcessPOSIX internal API.
-
- /// Registers the given message with this process.
- virtual void
- SendMessage(const ProcessMessage &message);
-
- ProcessMonitor &
- GetMonitor() { assert(m_monitor); return *m_monitor; }
-
- lldb_private::FileSpec
- GetFileSpec(const lldb_private::FileAction *file_action,
- const lldb_private::FileSpec &default_file_spec,
- const lldb_private::FileSpec &dbg_pts_file_spec);
-
- /// Adds the thread to the list of threads for which we have received the initial stopping signal.
- /// The \p stop_tid parameter indicates the thread which the stop happened for.
- bool
- AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid);
-
- bool
- WaitingForInitialStop(lldb::tid_t stop_tid);
-
- virtual POSIXThread *
- CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid);
-
-protected:
- /// Target byte order.
- lldb::ByteOrder m_byte_order;
-
- /// Process monitor;
- ProcessMonitor *m_monitor;
-
- /// The module we are executing.
- lldb_private::Module *m_module;
-
- /// Message queue notifying this instance of inferior process state changes.
- lldb_private::Mutex m_message_mutex;
- std::queue<ProcessMessage> m_message_queue;
-
- /// Drive any exit events to completion.
- bool m_exit_now;
-
- /// Returns true if the process has exited.
- bool HasExited();
-
- /// Returns true if the process is stopped.
- bool IsStopped();
-
- /// Returns true if at least one running is currently running
- bool IsAThreadRunning();
-
- typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
- MMapMap m_addr_to_mmap_size;
-
- typedef std::set<lldb::tid_t> ThreadStopSet;
- /// Every thread begins with a stop signal. This keeps track
- /// of the threads for which we have received the stop signal.
- ThreadStopSet m_seen_initial_stop;
-};
-
-#endif // liblldb_MacOSXProcess_H_
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX.h b/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h
index 6ddd9cfe4c21..6ddd9cfe4c21 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX.h
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp
index ac2f81d53929..9922311fd9db 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp
@@ -12,7 +12,7 @@
#include "lldb/Target/Thread.h"
#include "RegisterContextPOSIX_arm.h"
-#include "ProcessPOSIX.h"
+#include "ProcessFreeBSD.h"
#include "RegisterContextPOSIXProcessMonitor_arm.h"
#include "ProcessMonitor.h"
@@ -32,7 +32,7 @@ ProcessMonitor &
RegisterContextPOSIXProcessMonitor_arm::GetMonitor()
{
ProcessSP base = CalculateProcess();
- ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+ ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get());
return process->GetMonitor();
}
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h
index 12a43c77837c..3787502a390c 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.h
@@ -10,6 +10,7 @@
#ifndef liblldb_RegisterContextPOSIXProcessMonitor_arm_H_
#define liblldb_RegisterContextPOSIXProcessMonitor_arm_H_
+#include "RegisterContextPOSIX.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h"
class RegisterContextPOSIXProcessMonitor_arm:
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp
index d79def52499f..012f4b6e1555 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp
@@ -12,7 +12,7 @@
#include "lldb/Target/Thread.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
-#include "ProcessPOSIX.h"
+#include "ProcessFreeBSD.h"
#include "ProcessMonitor.h"
#include "RegisterContextPOSIXProcessMonitor_arm64.h"
@@ -32,7 +32,7 @@ ProcessMonitor &
RegisterContextPOSIXProcessMonitor_arm64::GetMonitor()
{
lldb::ProcessSP base = CalculateProcess();
- ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+ ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get());
return process->GetMonitor();
}
@@ -260,13 +260,11 @@ RegisterContextPOSIXProcessMonitor_arm64::HardwareSingleStep(bool enable)
bool
RegisterContextPOSIXProcessMonitor_arm64::UpdateAfterBreakpoint()
{
- // PC points one byte past the int3 responsible for the breakpoint.
lldb::addr_t pc;
if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
return false;
- SetPC(pc - 1);
return true;
}
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h
index eb24d4852ab8..729385c4a76e 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.h
@@ -10,6 +10,7 @@
#ifndef liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_
#define liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_
+#include "RegisterContextPOSIX.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
class RegisterContextPOSIXProcessMonitor_arm64:
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp
index 893a0f22b6f8..eeada4b16337 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp
@@ -12,7 +12,7 @@
#include "lldb/Target/Thread.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h"
-#include "ProcessPOSIX.h"
+#include "ProcessFreeBSD.h"
#include "ProcessMonitor.h"
#include "RegisterContextPOSIXProcessMonitor_mips64.h"
@@ -32,7 +32,7 @@ ProcessMonitor &
RegisterContextPOSIXProcessMonitor_mips64::GetMonitor()
{
ProcessSP base = CalculateProcess();
- ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+ ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get());
return process->GetMonitor();
}
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h
index 79e4468b1adf..e61621bec197 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.h
@@ -10,6 +10,7 @@
#ifndef liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_
#define liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_
+#include "RegisterContextPOSIX.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h"
class RegisterContextPOSIXProcessMonitor_mips64:
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp
index 8c12b62a202f..321e6ea262ce 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp
@@ -12,7 +12,7 @@
#include "lldb/Target/Thread.h"
#include "RegisterContextPOSIX_powerpc.h"
-#include "ProcessPOSIX.h"
+#include "ProcessFreeBSD.h"
#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
#include "ProcessMonitor.h"
@@ -32,7 +32,7 @@ ProcessMonitor &
RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor()
{
ProcessSP base = CalculateProcess();
- ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+ ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get());
return process->GetMonitor();
}
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h
index 5c686df4836f..ff1d0f36171b 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.h
@@ -10,6 +10,7 @@
#ifndef liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_
#define liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_
+#include "RegisterContextPOSIX.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
class RegisterContextPOSIXProcessMonitor_powerpc:
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
index 9245441f659f..31b9e7a38b21 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
@@ -11,7 +11,7 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
-#include "Plugins/Process/FreeBSD/ProcessPOSIX.h"
+#include "Plugins/Process/FreeBSD/ProcessFreeBSD.h"
#include "RegisterContextPOSIXProcessMonitor_x86.h"
#include "Plugins/Process/FreeBSD/ProcessMonitor.h"
@@ -58,13 +58,16 @@ RegisterContextPOSIXProcessMonitor_x86_64::RegisterContextPOSIXProcessMonitor_x8
lldb_private::RegisterInfoInterface *register_info)
: RegisterContextPOSIX_x86(thread, concrete_frame_idx, register_info)
{
+ // Store byte offset of fctrl (i.e. first register of FPR) wrt 'UserArea'
+ const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("fctrl");
+ m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset;
}
ProcessMonitor &
RegisterContextPOSIXProcessMonitor_x86_64::GetMonitor()
{
ProcessSP base = CalculateProcess();
- ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+ ProcessFreeBSD *process = static_cast<ProcessFreeBSD*>(base.get());
return process->GetMonitor();
}
@@ -254,10 +257,20 @@ RegisterContextPOSIXProcessMonitor_x86_64::ReadRegister(const RegisterInfo *reg_
}
// Get pointer to m_fpr.xstate.fxsave variable and set the data from it.
- assert (reg_info->byte_offset < sizeof(m_fpr));
- uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset;
+ // Byte offsets of all registers are calculated wrt 'UserArea' structure.
+ // However, ReadFPR() reads fpu registers {using ptrace(PT_GETFPREGS,..)}
+ // and stores them in 'm_fpr' (of type FPR structure). To extract values of fpu
+ // registers, m_fpr should be read at byte offsets calculated wrt to FPR structure.
+
+ // Since, FPR structure is also one of the member of UserArea structure.
+ // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - byte_offset(fctrl wrt UserArea)
+ assert ( (reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr));
+ uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea;
switch (reg_info->byte_size)
{
+ case 1:
+ value.SetUInt8(*(uint8_t *)src);
+ return true;
case 2:
value.SetUInt16(*(uint16_t *)src);
return true;
@@ -308,10 +321,20 @@ RegisterContextPOSIXProcessMonitor_x86_64::WriteRegister(const RegisterInfo *reg
else
{
// Get pointer to m_fpr.xstate.fxsave variable and set the data to it.
- assert (reg_info->byte_offset < sizeof(m_fpr));
- uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset;
+ // Byte offsets of all registers are calculated wrt 'UserArea' structure.
+ // However, WriteFPR() takes m_fpr (of type FPR structure) and writes only fpu
+ // registers using ptrace(PT_SETFPREGS,..) API. Hence fpu registers should
+ // be written in m_fpr at byte offsets calculated wrt FPR structure.
+
+ // Since, FPR structure is also one of the member of UserArea structure.
+ // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) - byte_offset(fctrl wrt UserArea)
+ assert ( (reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(m_fpr));
+ uint8_t *dst = (uint8_t *)&m_fpr + reg_info->byte_offset - m_fctrl_offset_in_userarea;
switch (reg_info->byte_size)
{
+ case 1:
+ *(uint8_t *)dst = value.GetAsUInt8();
+ break;
case 2:
*(uint16_t *)dst = value.GetAsUInt16();
break;
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h
index 2afb195c4c36..f55d917ee75d 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.h
@@ -10,6 +10,7 @@
#ifndef liblldb_RegisterContextPOSIXProcessMonitor_x86_H_
#define liblldb_RegisterContextPOSIXProcessMonitor_x86_H_
+#include "RegisterContextPOSIX.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h"
class RegisterContextPOSIXProcessMonitor_x86_64:
@@ -90,6 +91,7 @@ protected:
private:
ProcessMonitor &
GetMonitor();
+ uint32_t m_fctrl_offset_in_userarea; // Offset of 'fctrl' in 'UserArea' Structure
};
#endif
diff --git a/source/Plugins/Process/POSIX/CrashReason.cpp b/source/Plugins/Process/POSIX/CrashReason.cpp
index 6de13f470c5e..44409a4ce552 100644
--- a/source/Plugins/Process/POSIX/CrashReason.cpp
+++ b/source/Plugins/Process/POSIX/CrashReason.cpp
@@ -28,11 +28,12 @@ GetCrashReasonForSIGSEGV(const siginfo_t& info)
switch (info.si_code)
{
+#ifdef SI_KERNEL
case SI_KERNEL:
- // Linux will occasionally send spurious SI_KERNEL codes.
- // (this is poorly documented in sigaction)
+ // Some platforms will occasionally send nonstandard spurious SI_KERNEL codes.
// One way to get this is via unaligned SIMD loads.
return CrashReason::eInvalidAddress; // for lack of anything better
+#endif
case SEGV_MAPERR:
return CrashReason::eInvalidAddress;
case SEGV_ACCERR:
diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
index 4eff442c1a0d..26de4b549c9f 100644
--- a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
+++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -99,7 +99,7 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, con
return 0;
}
- // { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'gcc' : 2,
+ // { 'name':'rcx' , 'bitsize' : 64, 'offset' : 16, 'encoding':'uint' , 'format':'hex' , 'set': 0, 'ehframe' : 2,
// 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },
RegisterInfo reg_info;
std::vector<uint32_t> value_regs;
@@ -325,8 +325,12 @@ DynamicRegisterInfo::SetRegisterInfo(const StructuredData::Dictionary &dict, con
// Fill in the register numbers
reg_info.kinds[lldb::eRegisterKindLLDB] = i;
- reg_info.kinds[lldb::eRegisterKindGDB] = i;
- reg_info_dict->GetValueForKeyAsInteger("gcc", reg_info.kinds[lldb::eRegisterKindGCC], LLDB_INVALID_REGNUM);
+ reg_info.kinds[lldb::eRegisterKindProcessPlugin] = i;
+ uint32_t eh_frame_regno = LLDB_INVALID_REGNUM;
+ reg_info_dict->GetValueForKeyAsInteger("gcc", eh_frame_regno, LLDB_INVALID_REGNUM);
+ if (eh_frame_regno == LLDB_INVALID_REGNUM)
+ reg_info_dict->GetValueForKeyAsInteger("ehframe", eh_frame_regno, LLDB_INVALID_REGNUM);
+ reg_info.kinds[lldb::eRegisterKindEHFrame] = eh_frame_regno;
reg_info_dict->GetValueForKeyAsInteger("dwarf", reg_info.kinds[lldb::eRegisterKindDWARF], LLDB_INVALID_REGNUM);
std::string generic_str;
if (reg_info_dict->GetValueForKeyAsString("generic", generic_str))
@@ -703,12 +707,12 @@ DynamicRegisterInfo::Dump () const
m_regs[i].byte_offset,
m_regs[i].encoding,
FormatManager::GetFormatAsCString (m_regs[i].format));
- if (m_regs[i].kinds[eRegisterKindGDB] != LLDB_INVALID_REGNUM)
- s.Printf(", gdb = %3u", m_regs[i].kinds[eRegisterKindGDB]);
+ if (m_regs[i].kinds[eRegisterKindProcessPlugin] != LLDB_INVALID_REGNUM)
+ s.Printf(", process plugin = %3u", m_regs[i].kinds[eRegisterKindProcessPlugin]);
if (m_regs[i].kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
s.Printf(", dwarf = %3u", m_regs[i].kinds[eRegisterKindDWARF]);
- if (m_regs[i].kinds[eRegisterKindGCC] != LLDB_INVALID_REGNUM)
- s.Printf(", gcc = %3u", m_regs[i].kinds[eRegisterKindGCC]);
+ if (m_regs[i].kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM)
+ s.Printf(", ehframe = %3u", m_regs[i].kinds[eRegisterKindEHFrame]);
if (m_regs[i].kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM)
s.Printf(", generic = %3u", m_regs[i].kinds[eRegisterKindGeneric]);
if (m_regs[i].alt_name)
diff --git a/source/Plugins/Process/Utility/FreeBSDSignals.cpp b/source/Plugins/Process/Utility/FreeBSDSignals.cpp
index c143d36e87c7..e575e2c6a496 100644
--- a/source/Plugins/Process/Utility/FreeBSDSignals.cpp
+++ b/source/Plugins/Process/Utility/FreeBSDSignals.cpp
@@ -26,70 +26,70 @@ FreeBSDSignals::Reset()
{
UnixSignals::Reset();
- // SIGNO NAME SHORT NAME SUPPRESS STOP NOTIFY DESCRIPTION
- // ====== ============ ========== ======== ====== ====== ===================================================
- AddSignal (32, "SIGTHR", "THR", false, true , true , "thread interrupt");
- AddSignal (33, "SIGLIBRT", "LIBRT", false, true , true , "reserved by real-time library");
- AddSignal (65, "SIGRTMIN", "RTMIN", false, true , true , "real time signal 0");
- AddSignal (66, "SIGRTMIN+1", "RTMIN+1", false, true , true , "real time signal 1");
- AddSignal (67, "SIGRTMIN+2", "RTMIN+2", false, true , true , "real time signal 2");
- AddSignal (68, "SIGRTMIN+3", "RTMIN+3", false, true , true , "real time signal 3");
- AddSignal (69, "SIGRTMIN+4", "RTMIN+4", false, true , true , "real time signal 4");
- AddSignal (70, "SIGRTMIN+5", "RTMIN+5", false, true , true , "real time signal 5");
- AddSignal (71, "SIGRTMIN+6", "RTMIN+6", false, true , true , "real time signal 6");
- AddSignal (72, "SIGRTMIN+7", "RTMIN+7", false, true , true , "real time signal 7");
- AddSignal (73, "SIGRTMIN+8", "RTMIN+8", false, true , true , "real time signal 8");
- AddSignal (74, "SIGRTMIN+9", "RTMIN+9", false, true , true , "real time signal 9");
- AddSignal (75, "SIGRTMIN+10", "RTMIN+10", false, true , true , "real time signal 10");
- AddSignal (76, "SIGRTMIN+11", "RTMIN+11", false, true , true , "real time signal 11");
- AddSignal (77, "SIGRTMIN+12", "RTMIN+12", false, true , true , "real time signal 12");
- AddSignal (78, "SIGRTMIN+13", "RTMIN+13", false, true , true , "real time signal 13");
- AddSignal (79, "SIGRTMIN+14", "RTMIN+14", false, true , true , "real time signal 14");
- AddSignal (80, "SIGRTMIN+15", "RTMIN+15", false, true , true , "real time signal 15");
- AddSignal (81, "SIGRTMIN+16", "RTMIN+16", false, true , true , "real time signal 16");
- AddSignal (82, "SIGRTMIN+17", "RTMIN+17", false, true , true , "real time signal 17");
- AddSignal (83, "SIGRTMIN+18", "RTMIN+18", false, true , true , "real time signal 18");
- AddSignal (84, "SIGRTMIN+19", "RTMIN+19", false, true , true , "real time signal 19");
- AddSignal (85, "SIGRTMIN+20", "RTMIN+20", false, true , true , "real time signal 20");
- AddSignal (86, "SIGRTMIN+21", "RTMIN+21", false, true , true , "real time signal 21");
- AddSignal (87, "SIGRTMIN+22", "RTMIN+22", false, true , true , "real time signal 22");
- AddSignal (88, "SIGRTMIN+23", "RTMIN+23", false, true , true , "real time signal 23");
- AddSignal (89, "SIGRTMIN+24", "RTMIN+24", false, true , true , "real time signal 24");
- AddSignal (90, "SIGRTMIN+25", "RTMIN+25", false, true , true , "real time signal 25");
- AddSignal (91, "SIGRTMIN+26", "RTMIN+26", false, true , true , "real time signal 26");
- AddSignal (92, "SIGRTMIN+27", "RTMIN+27", false, true , true , "real time signal 27");
- AddSignal (93, "SIGRTMIN+28", "RTMIN+28", false, true , true , "real time signal 28");
- AddSignal (94, "SIGRTMIN+29", "RTMIN+29", false, true , true , "real time signal 29");
- AddSignal (95, "SIGRTMIN+30", "RTMIN+30", false, true , true , "real time signal 30");
- AddSignal (96, "SIGRTMAX-30", "RTMAX-30", false, true , true , "real time signal 31");
- AddSignal (97, "SIGRTMAX-29", "RTMAX-29", false, true , true , "real time signal 32");
- AddSignal (98, "SIGRTMAX-28", "RTMAX-28", false, true , true , "real time signal 33");
- AddSignal (99, "SIGRTMAX-27", "RTMAX-27", false, true , true , "real time signal 34");
- AddSignal (100, "SIGRTMAX-26", "RTMAX-26", false, true , true , "real time signal 35");
- AddSignal (101, "SIGRTMAX-25", "RTMAX-25", false, true , true , "real time signal 36");
- AddSignal (102, "SIGRTMAX-24", "RTMAX-24", false, true , true , "real time signal 37");
- AddSignal (103, "SIGRTMAX-23", "RTMAX-23", false, true , true , "real time signal 38");
- AddSignal (104, "SIGRTMAX-22", "RTMAX-22", false, true , true , "real time signal 39");
- AddSignal (105, "SIGRTMAX-21", "RTMAX-21", false, true , true , "real time signal 40");
- AddSignal (106, "SIGRTMAX-20", "RTMAX-20", false, true , true , "real time signal 41");
- AddSignal (107, "SIGRTMAX-19", "RTMAX-19", false, true , true , "real time signal 42");
- AddSignal (108, "SIGRTMAX-18", "RTMAX-18", false, true , true , "real time signal 43");
- AddSignal (109, "SIGRTMAX-17", "RTMAX-17", false, true , true , "real time signal 44");
- AddSignal (110, "SIGRTMAX-16", "RTMAX-16", false, true , true , "real time signal 45");
- AddSignal (111, "SIGRTMAX-15", "RTMAX-15", false, true , true , "real time signal 46");
- AddSignal (112, "SIGRTMAX-14", "RTMAX-14", false, true , true , "real time signal 47");
- AddSignal (113, "SIGRTMAX-13", "RTMAX-13", false, true , true , "real time signal 48");
- AddSignal (114, "SIGRTMAX-12", "RTMAX-12", false, true , true , "real time signal 49");
- AddSignal (115, "SIGRTMAX-11", "RTMAX-11", false, true , true , "real time signal 50");
- AddSignal (116, "SIGRTMAX-10", "RTMAX-10", false, true , true , "real time signal 51");
- AddSignal (117, "SIGRTMAX-9", "RTMAX-9", false, true , true , "real time signal 52");
- AddSignal (118, "SIGRTMAX-8", "RTMAX-8", false, true , true , "real time signal 53");
- AddSignal (119, "SIGRTMAX-7", "RTMAX-7", false, true , true , "real time signal 54");
- AddSignal (120, "SIGRTMAX-6", "RTMAX-6", false, true , true , "real time signal 55");
- AddSignal (121, "SIGRTMAX-5", "RTMAX-5", false, true , true , "real time signal 56");
- AddSignal (122, "SIGRTMAX-4", "RTMAX-4", false, true , true , "real time signal 57");
- AddSignal (123, "SIGRTMAX-3", "RTMAX-3", false, true , true , "real time signal 58");
- AddSignal (124, "SIGRTMAX-2", "RTMAX-2", false, true , true , "real time signal 59");
- AddSignal (125, "SIGRTMAX-1", "RTMAX-1", false, true , true , "real time signal 60");
- AddSignal (126, "SIGRTMAX", "RTMAX", false, true , true , "real time signal 61");
+ // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION
+ // ====== ============ ======== ====== ====== ===================================================
+ AddSignal (32, "SIGTHR", false, false, false, "thread interrupt");
+ AddSignal (33, "SIGLIBRT", false, false, false, "reserved by real-time library");
+ AddSignal (65, "SIGRTMIN", false, false, false, "real time signal 0");
+ AddSignal (66, "SIGRTMIN+1", false, false, false, "real time signal 1");
+ AddSignal (67, "SIGRTMIN+2", false, false, false, "real time signal 2");
+ AddSignal (68, "SIGRTMIN+3", false, false, false, "real time signal 3");
+ AddSignal (69, "SIGRTMIN+4", false, false, false, "real time signal 4");
+ AddSignal (70, "SIGRTMIN+5", false, false, false, "real time signal 5");
+ AddSignal (71, "SIGRTMIN+6", false, false, false, "real time signal 6");
+ AddSignal (72, "SIGRTMIN+7", false, false, false, "real time signal 7");
+ AddSignal (73, "SIGRTMIN+8", false, false, false, "real time signal 8");
+ AddSignal (74, "SIGRTMIN+9", false, false, false, "real time signal 9");
+ AddSignal (75, "SIGRTMIN+10", false, false, false, "real time signal 10");
+ AddSignal (76, "SIGRTMIN+11", false, false, false, "real time signal 11");
+ AddSignal (77, "SIGRTMIN+12", false, false, false, "real time signal 12");
+ AddSignal (78, "SIGRTMIN+13", false, false, false, "real time signal 13");
+ AddSignal (79, "SIGRTMIN+14", false, false, false, "real time signal 14");
+ AddSignal (80, "SIGRTMIN+15", false, false, false, "real time signal 15");
+ AddSignal (81, "SIGRTMIN+16", false, false, false, "real time signal 16");
+ AddSignal (82, "SIGRTMIN+17", false, false, false, "real time signal 17");
+ AddSignal (83, "SIGRTMIN+18", false, false, false, "real time signal 18");
+ AddSignal (84, "SIGRTMIN+19", false, false, false, "real time signal 19");
+ AddSignal (85, "SIGRTMIN+20", false, false, false, "real time signal 20");
+ AddSignal (86, "SIGRTMIN+21", false, false, false, "real time signal 21");
+ AddSignal (87, "SIGRTMIN+22", false, false, false, "real time signal 22");
+ AddSignal (88, "SIGRTMIN+23", false, false, false, "real time signal 23");
+ AddSignal (89, "SIGRTMIN+24", false, false, false, "real time signal 24");
+ AddSignal (90, "SIGRTMIN+25", false, false, false, "real time signal 25");
+ AddSignal (91, "SIGRTMIN+26", false, false, false, "real time signal 26");
+ AddSignal (92, "SIGRTMIN+27", false, false, false, "real time signal 27");
+ AddSignal (93, "SIGRTMIN+28", false, false, false, "real time signal 28");
+ AddSignal (94, "SIGRTMIN+29", false, false, false, "real time signal 29");
+ AddSignal (95, "SIGRTMIN+30", false, false, false, "real time signal 30");
+ AddSignal (96, "SIGRTMAX-30", false, false, false, "real time signal 31");
+ AddSignal (97, "SIGRTMAX-29", false, false, false, "real time signal 32");
+ AddSignal (98, "SIGRTMAX-28", false, false, false, "real time signal 33");
+ AddSignal (99, "SIGRTMAX-27", false, false, false, "real time signal 34");
+ AddSignal (100, "SIGRTMAX-26", false, false, false, "real time signal 35");
+ AddSignal (101, "SIGRTMAX-25", false, false, false, "real time signal 36");
+ AddSignal (102, "SIGRTMAX-24", false, false, false, "real time signal 37");
+ AddSignal (103, "SIGRTMAX-23", false, false, false, "real time signal 38");
+ AddSignal (104, "SIGRTMAX-22", false, false, false, "real time signal 39");
+ AddSignal (105, "SIGRTMAX-21", false, false, false, "real time signal 40");
+ AddSignal (106, "SIGRTMAX-20", false, false, false, "real time signal 41");
+ AddSignal (107, "SIGRTMAX-19", false, false, false, "real time signal 42");
+ AddSignal (108, "SIGRTMAX-18", false, false, false, "real time signal 43");
+ AddSignal (109, "SIGRTMAX-17", false, false, false, "real time signal 44");
+ AddSignal (110, "SIGRTMAX-16", false, false, false, "real time signal 45");
+ AddSignal (111, "SIGRTMAX-15", false, false, false, "real time signal 46");
+ AddSignal (112, "SIGRTMAX-14", false, false, false, "real time signal 47");
+ AddSignal (113, "SIGRTMAX-13", false, false, false, "real time signal 48");
+ AddSignal (114, "SIGRTMAX-12", false, false, false, "real time signal 49");
+ AddSignal (115, "SIGRTMAX-11", false, false, false, "real time signal 50");
+ AddSignal (116, "SIGRTMAX-10", false, false, false, "real time signal 51");
+ AddSignal (117, "SIGRTMAX-9", false, false, false, "real time signal 52");
+ AddSignal (118, "SIGRTMAX-8", false, false, false, "real time signal 53");
+ AddSignal (119, "SIGRTMAX-7", false, false, false, "real time signal 54");
+ AddSignal (120, "SIGRTMAX-6", false, false, false, "real time signal 55");
+ AddSignal (121, "SIGRTMAX-5", false, false, false, "real time signal 56");
+ AddSignal (122, "SIGRTMAX-4", false, false, false, "real time signal 57");
+ AddSignal (123, "SIGRTMAX-3", false, false, false, "real time signal 58");
+ AddSignal (124, "SIGRTMAX-2", false, false, false, "real time signal 59");
+ AddSignal (125, "SIGRTMAX-1", false, false, false, "real time signal 60");
+ AddSignal (126, "SIGRTMAX", false, false, false, "real time signal 61");
}
diff --git a/source/Plugins/Process/Utility/HistoryThread.h b/source/Plugins/Process/Utility/HistoryThread.h
index 51173c626d71..e87f6496134b 100644
--- a/source/Plugins/Process/Utility/HistoryThread.h
+++ b/source/Plugins/Process/Utility/HistoryThread.h
@@ -10,6 +10,10 @@
#ifndef liblldb_HistoryThread_h_
#define liblldb_HistoryThread_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Core/Broadcaster.h"
@@ -37,52 +41,55 @@ class HistoryThread : public lldb_private::Thread
public:
HistoryThread (lldb_private::Process &process, lldb::tid_t tid, std::vector<lldb::addr_t> pcs, uint32_t stop_id, bool stop_id_is_valid);
- virtual ~HistoryThread ();
+ ~HistoryThread() override;
- virtual lldb::RegisterContextSP
- GetRegisterContext ();
+ lldb::RegisterContextSP
+ GetRegisterContext() override;
- virtual lldb::RegisterContextSP
- CreateRegisterContextForFrame (StackFrame *frame);
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame(StackFrame *frame) override;
- virtual void
- RefreshStateAfterStop() { }
+ void
+ RefreshStateAfterStop() override { }
bool
- CalculateStopInfo () { return false; }
+ CalculateStopInfo() override
+ {
+ return false;
+ }
void
- SetExtendedBacktraceToken (uint64_t token)
+ SetExtendedBacktraceToken(uint64_t token) override
{
m_extended_unwind_token = token;
}
uint64_t
- GetExtendedBacktraceToken ()
+ GetExtendedBacktraceToken() override
{
return m_extended_unwind_token;
}
const char *
- GetQueueName ()
+ GetQueueName() override
{
return m_queue_name.c_str();
}
void
- SetQueueName (const char *name)
+ SetQueueName(const char *name) override
{
m_queue_name = name;
}
lldb::queue_id_t
- GetQueueID ()
+ GetQueueID() override
{
return m_queue_id;
}
void
- SetQueueID (lldb::queue_id_t queue)
+ SetQueueID(lldb::queue_id_t queue) override
{
m_queue_id = queue;
}
@@ -94,7 +101,7 @@ public:
}
uint32_t
- GetExtendedBacktraceOriginatingIndexID ();
+ GetExtendedBacktraceOriginatingIndexID() override;
void
SetThreadName (const char *name)
@@ -102,14 +109,14 @@ public:
m_thread_name = name;
}
- virtual const char *
- GetName ()
+ const char *
+ GetName() override
{
return m_thread_name.c_str();
}
- virtual void
- SetName(const char *name)
+ void
+ SetName(const char *name) override
{
m_thread_name = name;
}
@@ -133,4 +140,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_HistoryThread_h_
+#endif // liblldb_HistoryThread_h_
diff --git a/source/Plugins/Process/Utility/HistoryUnwind.h b/source/Plugins/Process/Utility/HistoryUnwind.h
index 733f93e1ff87..2cb78bc1dc63 100644
--- a/source/Plugins/Process/Utility/HistoryUnwind.h
+++ b/source/Plugins/Process/Utility/HistoryUnwind.h
@@ -10,8 +10,12 @@
#ifndef liblldb_HistoryUnwind_h_
#define liblldb_HistoryUnwind_h_
+// C Includes
+// C++ Includes
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Target/Unwind.h"
@@ -23,21 +27,21 @@ class HistoryUnwind : public lldb_private::Unwind
public:
HistoryUnwind (Thread &thread, std::vector<lldb::addr_t> pcs, bool stop_id_is_valid);
- virtual ~HistoryUnwind ();
+ ~HistoryUnwind() override;
protected:
void
- DoClear();
+ DoClear() override;
lldb::RegisterContextSP
- DoCreateRegisterContextForFrame (StackFrame *frame);
+ DoCreateRegisterContextForFrame(StackFrame *frame) override;
bool
- DoGetFrameInfoAtIndex (uint32_t frame_idx,
- lldb::addr_t& cfa,
- lldb::addr_t& pc);
+ DoGetFrameInfoAtIndex(uint32_t frame_idx,
+ lldb::addr_t& cfa,
+ lldb::addr_t& pc) override;
uint32_t
- DoGetFrameCount ();
+ DoGetFrameCount() override;
private:
@@ -47,4 +51,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_HistoryUnwind_h_
+#endif // liblldb_HistoryUnwind_h_
diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index 3923c5433406..bd3978cc0ab4 100644
--- a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -93,7 +93,7 @@ lldb_private::InferiorCallMmap (Process *process,
if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range))
{
ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
- ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+ CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
lldb::addr_t args[] = { addr, length, prot_arg, flags_arg, fd, offset };
lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
mmap_range.GetBaseAddress(),
@@ -103,9 +103,6 @@ lldb_private::InferiorCallMmap (Process *process,
if (call_plan_sp)
{
StreamFile error_strm;
- // This plan is a utility plan, so set it to discard itself when done.
- call_plan_sp->SetIsMasterPlan (true);
- call_plan_sp->SetOkayToDiscard(true);
StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
if (frame)
@@ -182,15 +179,12 @@ lldb_private::InferiorCallMunmap (Process *process,
lldb::addr_t args[] = { addr, length };
lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
munmap_range.GetBaseAddress(),
- ClangASTType(),
+ CompilerType(),
args,
options));
if (call_plan_sp)
{
StreamFile error_strm;
- // This plan is a utility plan, so set it to discard itself when done.
- call_plan_sp->SetIsMasterPlan (true);
- call_plan_sp->SetOkayToDiscard(true);
StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
if (frame)
@@ -235,7 +229,7 @@ lldb_private::InferiorCall (Process *process,
options.SetTimeoutUsec(500000);
ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
- ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+ CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
*address,
clang_void_ptr_type,
@@ -244,9 +238,6 @@ lldb_private::InferiorCall (Process *process,
if (call_plan_sp)
{
StreamString error_strm;
- // This plan is a utility plan, so set it to discard itself when done.
- call_plan_sp->SetIsMasterPlan (true);
- call_plan_sp->SetOkayToDiscard(true);
StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
if (frame)
diff --git a/source/Plugins/Process/Utility/LinuxSignals.cpp b/source/Plugins/Process/Utility/LinuxSignals.cpp
index cd1fc8165eb9..5687577f9d16 100644
--- a/source/Plugins/Process/Utility/LinuxSignals.cpp
+++ b/source/Plugins/Process/Utility/LinuxSignals.cpp
@@ -24,72 +24,70 @@ void
LinuxSignals::Reset()
{
m_signals.clear();
-
- AddSignal (1, "SIGHUP", "HUP", false, true , true , "hangup");
- AddSignal (2, "SIGINT", "INT", true , true , true , "interrupt");
- AddSignal (3, "SIGQUIT", "QUIT", false, true , true , "quit");
- AddSignal (4, "SIGILL", "ILL", false, true , true , "illegal instruction");
- AddSignal (5, "SIGTRAP", "TRAP", true , true , true , "trace trap (not reset when caught)");
- AddSignal (6, "SIGABRT", "ABRT", false, true , true , "abort()");
- AddSignal (6, "SIGIOT", "IOT", false, true , true , "IOT trap");
- AddSignal (7, "SIGBUS", "BUS", false, true , true , "bus error");
- AddSignal (8, "SIGFPE", "FPE", false, true , true , "floating point exception");
- AddSignal (9, "SIGKILL", "KILL", false, true , true , "kill");
- AddSignal (10, "SIGUSR1", "USR1", false, true , true , "user defined signal 1");
- AddSignal (11, "SIGSEGV", "SEGV", false, true , true , "segmentation violation");
- AddSignal (12, "SIGUSR2", "USR2", false, true , true , "user defined signal 2");
- AddSignal (13, "SIGPIPE", "PIPE", false, true , true , "write to pipe with reading end closed");
- AddSignal (14, "SIGALRM", "ALRM", false, false, false, "alarm");
- AddSignal (15, "SIGTERM", "TERM", false, true , true , "termination requested");
- AddSignal (16, "SIGSTKFLT", "STKFLT", false, true , true , "stack fault");
- AddSignal (16, "SIGCLD", "CLD", false, false, true , "same as SIGCHLD");
- AddSignal (17, "SIGCHLD", "CHLD", false, false, true , "child status has changed");
- AddSignal (18, "SIGCONT", "CONT", false, true , true , "process continue");
- AddSignal (19, "SIGSTOP", "STOP", true , true , true , "process stop");
- AddSignal (20, "SIGTSTP", "TSTP", false, true , true , "tty stop");
- AddSignal (21, "SIGTTIN", "TTIN", false, true , true , "background tty read");
- AddSignal (22, "SIGTTOU", "TTOU", false, true , true , "background tty write");
- AddSignal (23, "SIGURG", "URG", false, true , true , "urgent data on socket");
- AddSignal (24, "SIGXCPU", "XCPU", false, true , true , "CPU resource exceeded");
- AddSignal (25, "SIGXFSZ", "XFSZ", false, true , true , "file size limit exceeded");
- AddSignal (26, "SIGVTALRM", "VTALRM", false, true , true , "virtual time alarm");
- AddSignal (27, "SIGPROF", "PROF", false, false, false, "profiling time alarm");
- AddSignal (28, "SIGWINCH", "WINCH", false, true , true , "window size changes");
- AddSignal (29, "SIGPOLL", "POLL", false, true , true , "pollable event");
- AddSignal (29, "SIGIO", "IO", false, true , true , "input/output ready");
- AddSignal (30, "SIGPWR", "PWR", false, true , true , "power failure");
- AddSignal (31, "SIGSYS", "SYS", false, true , true , "invalid system call");
- AddSignal (32, "SIG32", "SIG32", false, true , true , "threading library internal signal 1");
- AddSignal (33, "SIG33", "SIG33", false, true , true , "threading library internal signal 2");
- AddSignal (34, "SIGRTMIN", "RTMIN", false, true , true , "real time signal 0");
- AddSignal (35, "SIGRTMIN+1", "RTMIN+1", false, true , true , "real time signal 1");
- AddSignal (36, "SIGRTMIN+2", "RTMIN+2", false, true , true , "real time signal 2");
- AddSignal (37, "SIGRTMIN+3", "RTMIN+3", false, true , true , "real time signal 3");
- AddSignal (38, "SIGRTMIN+4", "RTMIN+4", false, true , true , "real time signal 4");
- AddSignal (39, "SIGRTMIN+5", "RTMIN+5", false, true , true , "real time signal 5");
- AddSignal (40, "SIGRTMIN+6", "RTMIN+6", false, true , true , "real time signal 6");
- AddSignal (41, "SIGRTMIN+7", "RTMIN+7", false, true , true , "real time signal 7");
- AddSignal (42, "SIGRTMIN+8", "RTMIN+8", false, true , true , "real time signal 8");
- AddSignal (43, "SIGRTMIN+9", "RTMIN+9", false, true , true , "real time signal 9");
- AddSignal (44, "SIGRTMIN+10", "RTMIN+10", false, true , true , "real time signal 10");
- AddSignal (45, "SIGRTMIN+11", "RTMIN+11", false, true , true , "real time signal 11");
- AddSignal (46, "SIGRTMIN+12", "RTMIN+12", false, true , true , "real time signal 12");
- AddSignal (47, "SIGRTMIN+13", "RTMIN+13", false, true , true , "real time signal 13");
- AddSignal (48, "SIGRTMIN+14", "RTMIN+14", false, true , true , "real time signal 14");
- AddSignal (49, "SIGRTMIN+15", "RTMIN+15", false, true , true , "real time signal 15");
- AddSignal (50, "SIGRTMAX-14", "RTMAX-14", false, true , true , "real time signal 16"); // switching to SIGRTMAX-xxx to match "kill -l" output
- AddSignal (51, "SIGRTMAX-13", "RTMAX-13", false, true , true , "real time signal 17");
- AddSignal (52, "SIGRTMAX-12", "RTMAX-12", false, true , true , "real time signal 18");
- AddSignal (53, "SIGRTMAX-11", "RTMAX-11", false, true , true , "real time signal 19");
- AddSignal (54, "SIGRTMAX-10", "RTMAX-10", false, true , true , "real time signal 20");
- AddSignal (55, "SIGRTMAX-9", "RTMAX-9", false, true , true , "real time signal 21");
- AddSignal (56, "SIGRTMAX-8", "RTMAX-8", false, true , true , "real time signal 22");
- AddSignal (57, "SIGRTMAX-7", "RTMAX-7", false, true , true , "real time signal 23");
- AddSignal (58, "SIGRTMAX-6", "RTMAX-6", false, true , true , "real time signal 24");
- AddSignal (59, "SIGRTMAX-5", "RTMAX-5", false, true , true , "real time signal 25");
- AddSignal (60, "SIGRTMAX-4", "RTMAX-4", false, true , true , "real time signal 26");
- AddSignal (61, "SIGRTMAX-3", "RTMAX-3", false, true , true , "real time signal 27");
- AddSignal (62, "SIGRTMAX-2", "RTMAX-2", false, true , true , "real time signal 28");
- AddSignal (63, "SIGRTMAX-1", "RTMAX-1", false, true , true , "real time signal 29");
- AddSignal (64, "SIGRTMAX", "RTMAX", false, true , true , "real time signal 30");
+ // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION ALIAS
+ // ===== =========== ======== ===== ====== ====================================== ======
+ AddSignal (1, "SIGHUP", false, true , true , "hangup" );
+ AddSignal (2, "SIGINT", true , true , true , "interrupt" );
+ AddSignal (3, "SIGQUIT", false, true , true , "quit" );
+ AddSignal (4, "SIGILL", false, true , true , "illegal instruction" );
+ AddSignal (5, "SIGTRAP", true , true , true , "trace trap (not reset when caught)" );
+ AddSignal (6, "SIGABRT", false, true , true , "abort()/IOT trap", "SIGIOT");
+ AddSignal (7, "SIGBUS", false, true , true , "bus error" );
+ AddSignal (8, "SIGFPE", false, true , true , "floating point exception" );
+ AddSignal (9, "SIGKILL", false, true , true , "kill" );
+ AddSignal (10, "SIGUSR1", false, true , true , "user defined signal 1" );
+ AddSignal (11, "SIGSEGV", false, true , true , "segmentation violation" );
+ AddSignal (12, "SIGUSR2", false, true , true , "user defined signal 2" );
+ AddSignal (13, "SIGPIPE", false, true , true , "write to pipe with reading end closed" );
+ AddSignal (14, "SIGALRM", false, false, false, "alarm" );
+ AddSignal (15, "SIGTERM", false, true , true , "termination requested" );
+ AddSignal (16, "SIGSTKFLT", false, true , true , "stack fault" );
+ AddSignal (17, "SIGCHLD", false, false, true , "child status has changed", "SIGCLD");
+ AddSignal (18, "SIGCONT", false, true , true , "process continue" );
+ AddSignal (19, "SIGSTOP", true , true , true , "process stop" );
+ AddSignal (20, "SIGTSTP", false, true , true , "tty stop" );
+ AddSignal (21, "SIGTTIN", false, true , true , "background tty read" );
+ AddSignal (22, "SIGTTOU", false, true , true , "background tty write" );
+ AddSignal (23, "SIGURG", false, true , true , "urgent data on socket" );
+ AddSignal (24, "SIGXCPU", false, true , true , "CPU resource exceeded" );
+ AddSignal (25, "SIGXFSZ", false, true , true , "file size limit exceeded" );
+ AddSignal (26, "SIGVTALRM", false, true , true , "virtual time alarm" );
+ AddSignal (27, "SIGPROF", false, false, false, "profiling time alarm" );
+ AddSignal (28, "SIGWINCH", false, true , true , "window size changes" );
+ AddSignal (29, "SIGIO", false, true , true , "input/output ready/Pollable event", "SIGPOLL");
+ AddSignal (30, "SIGPWR", false, true , true , "power failure" );
+ AddSignal (31, "SIGSYS", false, true , true , "invalid system call" );
+ AddSignal (32, "SIG32", false, false, false, "threading library internal signal 1" );
+ AddSignal (33, "SIG33", false, false, false, "threading library internal signal 2" );
+ AddSignal (34, "SIGRTMIN", false, false, false, "real time signal 0" );
+ AddSignal (35, "SIGRTMIN+1", false, false, false, "real time signal 1" );
+ AddSignal (36, "SIGRTMIN+2", false, false, false, "real time signal 2" );
+ AddSignal (37, "SIGRTMIN+3", false, false, false, "real time signal 3" );
+ AddSignal (38, "SIGRTMIN+4", false, false, false, "real time signal 4" );
+ AddSignal (39, "SIGRTMIN+5", false, false, false, "real time signal 5" );
+ AddSignal (40, "SIGRTMIN+6", false, false, false, "real time signal 6" );
+ AddSignal (41, "SIGRTMIN+7", false, false, false, "real time signal 7" );
+ AddSignal (42, "SIGRTMIN+8", false, false, false, "real time signal 8" );
+ AddSignal (43, "SIGRTMIN+9", false, false, false, "real time signal 9" );
+ AddSignal (44, "SIGRTMIN+10", false, false, false, "real time signal 10" );
+ AddSignal (45, "SIGRTMIN+11", false, false, false, "real time signal 11" );
+ AddSignal (46, "SIGRTMIN+12", false, false, false, "real time signal 12" );
+ AddSignal (47, "SIGRTMIN+13", false, false, false, "real time signal 13" );
+ AddSignal (48, "SIGRTMIN+14", false, false, false, "real time signal 14" );
+ AddSignal (49, "SIGRTMIN+15", false, false, false, "real time signal 15" );
+ AddSignal (50, "SIGRTMAX-14", false, false, false, "real time signal 16" ); // switching to SIGRTMAX-xxx to match "kill -l" output
+ AddSignal (51, "SIGRTMAX-13", false, false, false, "real time signal 17" );
+ AddSignal (52, "SIGRTMAX-12", false, false, false, "real time signal 18" );
+ AddSignal (53, "SIGRTMAX-11", false, false, false, "real time signal 19" );
+ AddSignal (54, "SIGRTMAX-10", false, false, false, "real time signal 20" );
+ AddSignal (55, "SIGRTMAX-9", false, false, false, "real time signal 21" );
+ AddSignal (56, "SIGRTMAX-8", false, false, false, "real time signal 22" );
+ AddSignal (57, "SIGRTMAX-7", false, false, false, "real time signal 23" );
+ AddSignal (58, "SIGRTMAX-6", false, false, false, "real time signal 24" );
+ AddSignal (59, "SIGRTMAX-5", false, false, false, "real time signal 25" );
+ AddSignal (60, "SIGRTMAX-4", false, false, false, "real time signal 26" );
+ AddSignal (61, "SIGRTMAX-3", false, false, false, "real time signal 27" );
+ AddSignal (62, "SIGRTMAX-2", false, false, false, "real time signal 28" );
+ AddSignal (63, "SIGRTMAX-1", false, false, false, "real time signal 29" );
+ AddSignal (64, "SIGRTMAX", false, false, false, "real time signal 30" );
}
diff --git a/source/Plugins/Process/Utility/MipsLinuxSignals.cpp b/source/Plugins/Process/Utility/MipsLinuxSignals.cpp
index 1dc0be81c0ae..422fc9b642d0 100644
--- a/source/Plugins/Process/Utility/MipsLinuxSignals.cpp
+++ b/source/Plugins/Process/Utility/MipsLinuxSignals.cpp
@@ -24,72 +24,70 @@ void
MipsLinuxSignals::Reset()
{
m_signals.clear();
-
- AddSignal (1, "SIGHUP", "HUP", false, true , true , "hangup");
- AddSignal (2, "SIGINT", "INT", true , true , true , "interrupt");
- AddSignal (3, "SIGQUIT", "QUIT", false, true , true , "quit");
- AddSignal (4, "SIGILL", "ILL", false, true , true , "illegal instruction");
- AddSignal (5, "SIGTRAP", "TRAP", true , true , true , "trace trap (not reset when caught)");
- AddSignal (6, "SIGABRT", "ABRT", false, true , true , "abort()");
- AddSignal (6, "SIGIOT", "IOT", false, true , true , "IOT trap");
- AddSignal (7, "SIGEMT", "EMT", false, true , true , "terminate process with core dump");
- AddSignal (8, "SIGFPE", "FPE", false, true , true , "floating point exception");
- AddSignal (9, "SIGKILL", "KILL", false, true , true , "kill");
- AddSignal (10, "SIGBUS", "BUS", false, true , true , "bus error");
- AddSignal (11, "SIGSEGV", "SEGV", false, true , true , "segmentation violation");
- AddSignal (12, "SIGSYS", "SYS", false, true , true , "invalid system call");
- AddSignal (13, "SIGPIPE", "PIPE", false, true , true , "write to pipe with reading end closed");
- AddSignal (14, "SIGALRM", "ALRM", false, false, false, "alarm");
- AddSignal (15, "SIGTERM", "TERM", false, true , true , "termination requested");
- AddSignal (16, "SIGUSR1", "USR1", false, true , true , "user defined signal 1");
- AddSignal (17, "SIGUSR2", "USR2", false, true , true , "user defined signal 2");
- AddSignal (18, "SIGCLD", "CLD", false, false, true , "same as SIGCHLD");
- AddSignal (18, "SIGCHLD", "CHLD", false, false, true , "child status has changed");
- AddSignal (19, "SIGPWR", "PWR", false, true , true , "power failure");
- AddSignal (20, "SIGWINCH", "WINCH", false, true , true , "window size changes");
- AddSignal (21, "SIGURG", "URG", false, true , true , "urgent data on socket");
- AddSignal (22, "SIGIO", "IO", false, true , true , "input/output ready");
- AddSignal (22, "SIGPOLL", "POLL", false, true , true , "pollable event");
- AddSignal (23, "SIGSTOP", "STOP", true , true , true , "process stop");
- AddSignal (24, "SIGTSTP", "TSTP", false, true , true , "tty stop");
- AddSignal (25, "SIGCONT", "CONT", false, true , true , "process continue");
- AddSignal (26, "SIGTTIN", "TTIN", false, true , true , "background tty read");
- AddSignal (27, "SIGTTOU", "TTOU", false, true , true , "background tty write");
- AddSignal (28, "SIGVTALRM", "VTALRM", false, true , true , "virtual time alarm");
- AddSignal (29, "SIGPROF", "PROF", false, false, false, "profiling time alarm");
- AddSignal (30, "SIGXCPU", "XCPU", false, true , true , "CPU resource exceeded");
- AddSignal (31, "SIGXFSZ", "XFSZ", false, true , true , "file size limit exceeded");
- AddSignal (32, "SIG32", "SIG32", false, true , true , "threading library internal signal 1");
- AddSignal (33, "SIG33", "SIG33", false, true , true , "threading library internal signal 2");
- AddSignal (34, "SIGRTMIN", "RTMIN", false, true , true , "real time signal 0");
- AddSignal (35, "SIGRTMIN+1", "RTMIN+1", false, true , true , "real time signal 1");
- AddSignal (36, "SIGRTMIN+2", "RTMIN+2", false, true , true , "real time signal 2");
- AddSignal (37, "SIGRTMIN+3", "RTMIN+3", false, true , true , "real time signal 3");
- AddSignal (38, "SIGRTMIN+4", "RTMIN+4", false, true , true , "real time signal 4");
- AddSignal (39, "SIGRTMIN+5", "RTMIN+5", false, true , true , "real time signal 5");
- AddSignal (40, "SIGRTMIN+6", "RTMIN+6", false, true , true , "real time signal 6");
- AddSignal (41, "SIGRTMIN+7", "RTMIN+7", false, true , true , "real time signal 7");
- AddSignal (42, "SIGRTMIN+8", "RTMIN+8", false, true , true , "real time signal 8");
- AddSignal (43, "SIGRTMIN+9", "RTMIN+9", false, true , true , "real time signal 9");
- AddSignal (44, "SIGRTMIN+10", "RTMIN+10", false, true , true , "real time signal 10");
- AddSignal (45, "SIGRTMIN+11", "RTMIN+11", false, true , true , "real time signal 11");
- AddSignal (46, "SIGRTMIN+12", "RTMIN+12", false, true , true , "real time signal 12");
- AddSignal (47, "SIGRTMIN+13", "RTMIN+13", false, true , true , "real time signal 13");
- AddSignal (48, "SIGRTMIN+14", "RTMIN+14", false, true , true , "real time signal 14");
- AddSignal (49, "SIGRTMIN+15", "RTMIN+15", false, true , true , "real time signal 15");
- AddSignal (50, "SIGRTMAX-14", "RTMAX-14", false, true , true , "real time signal 16"); // switching to SIGRTMAX-xxx to match "kill -l" output
- AddSignal (51, "SIGRTMAX-13", "RTMAX-13", false, true , true , "real time signal 17");
- AddSignal (52, "SIGRTMAX-12", "RTMAX-12", false, true , true , "real time signal 18");
- AddSignal (53, "SIGRTMAX-11", "RTMAX-11", false, true , true , "real time signal 19");
- AddSignal (54, "SIGRTMAX-10", "RTMAX-10", false, true , true , "real time signal 20");
- AddSignal (55, "SIGRTMAX-9", "RTMAX-9", false, true , true , "real time signal 21");
- AddSignal (56, "SIGRTMAX-8", "RTMAX-8", false, true , true , "real time signal 22");
- AddSignal (57, "SIGRTMAX-7", "RTMAX-7", false, true , true , "real time signal 23");
- AddSignal (58, "SIGRTMAX-6", "RTMAX-6", false, true , true , "real time signal 24");
- AddSignal (59, "SIGRTMAX-5", "RTMAX-5", false, true , true , "real time signal 25");
- AddSignal (60, "SIGRTMAX-4", "RTMAX-4", false, true , true , "real time signal 26");
- AddSignal (61, "SIGRTMAX-3", "RTMAX-3", false, true , true , "real time signal 27");
- AddSignal (62, "SIGRTMAX-2", "RTMAX-2", false, true , true , "real time signal 28");
- AddSignal (63, "SIGRTMAX-1", "RTMAX-1", false, true , true , "real time signal 29");
- AddSignal (64, "SIGRTMAX", "RTMAX", false, true , true , "real time signal 30");
+ // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION ALIAS
+ // ===== =========== ======== ===== ====== ====================================== ========
+ AddSignal (1, "SIGHUP", false, true , true , "hangup" );
+ AddSignal (2, "SIGINT", true , true , true , "interrupt" );
+ AddSignal (3, "SIGQUIT", false, true , true , "quit" );
+ AddSignal (4, "SIGILL", false, true , true , "illegal instruction" );
+ AddSignal (5, "SIGTRAP", true , true , true , "trace trap (not reset when caught)" );
+ AddSignal (6, "SIGABRT", false, true , true , "abort()/IOT trap", "SIGIOT");
+ AddSignal (7, "SIGEMT", false, true , true , "terminate process with core dump" );
+ AddSignal (8, "SIGFPE", false, true , true , "floating point exception" );
+ AddSignal (9, "SIGKILL", false, true , true , "kill" );
+ AddSignal (10, "SIGBUS", false, true , true , "bus error" );
+ AddSignal (11, "SIGSEGV", false, true , true , "segmentation violation" );
+ AddSignal (12, "SIGSYS", false, true , true , "invalid system call" );
+ AddSignal (13, "SIGPIPE", false, true , true , "write to pipe with reading end closed" );
+ AddSignal (14, "SIGALRM", false, false, false, "alarm" );
+ AddSignal (15, "SIGTERM", false, true , true , "termination requested" );
+ AddSignal (16, "SIGUSR1", false, true , true , "user defined signal 1" );
+ AddSignal (17, "SIGUSR2", false, true , true , "user defined signal 2" );
+ AddSignal (18, "SIGCHLD", false, false, true , "child status has changed", "SIGCLD");
+ AddSignal (19, "SIGPWR", false, true , true , "power failure" );
+ AddSignal (20, "SIGWINCH", false, true , true , "window size changes" );
+ AddSignal (21, "SIGURG", false, true , true , "urgent data on socket" );
+ AddSignal (22, "SIGIO", false, true , true , "input/output ready/Pollable event", "SIGPOLL");
+ AddSignal (23, "SIGSTOP", true , true , true , "process stop" );
+ AddSignal (24, "SIGTSTP", false, true , true , "tty stop" );
+ AddSignal (25, "SIGCONT", false, true , true , "process continue" );
+ AddSignal (26, "SIGTTIN", false, true , true , "background tty read" );
+ AddSignal (27, "SIGTTOU", false, true , true , "background tty write" );
+ AddSignal (28, "SIGVTALRM", false, true , true , "virtual time alarm" );
+ AddSignal (29, "SIGPROF", false, false, false, "profiling time alarm" );
+ AddSignal (30, "SIGXCPU", false, true , true , "CPU resource exceeded" );
+ AddSignal (31, "SIGXFSZ", false, true , true , "file size limit exceeded" );
+ AddSignal (32, "SIG32", false, false, false, "threading library internal signal 1" );
+ AddSignal (33, "SIG33", false, false, false, "threading library internal signal 2" );
+ AddSignal (34, "SIGRTMIN", false, false, false, "real time signal 0" );
+ AddSignal (35, "SIGRTMIN+1", false, false, false, "real time signal 1" );
+ AddSignal (36, "SIGRTMIN+2", false, false, false, "real time signal 2" );
+ AddSignal (37, "SIGRTMIN+3", false, false, false, "real time signal 3" );
+ AddSignal (38, "SIGRTMIN+4", false, false, false, "real time signal 4" );
+ AddSignal (39, "SIGRTMIN+5", false, false, false, "real time signal 5" );
+ AddSignal (40, "SIGRTMIN+6", false, false, false, "real time signal 6" );
+ AddSignal (41, "SIGRTMIN+7", false, false, false, "real time signal 7" );
+ AddSignal (42, "SIGRTMIN+8", false, false, false, "real time signal 8" );
+ AddSignal (43, "SIGRTMIN+9", false, false, false, "real time signal 9" );
+ AddSignal (44, "SIGRTMIN+10", false, false, false, "real time signal 10" );
+ AddSignal (45, "SIGRTMIN+11", false, false, false, "real time signal 11" );
+ AddSignal (46, "SIGRTMIN+12", false, false, false, "real time signal 12" );
+ AddSignal (47, "SIGRTMIN+13", false, false, false, "real time signal 13" );
+ AddSignal (48, "SIGRTMIN+14", false, false, false, "real time signal 14" );
+ AddSignal (49, "SIGRTMIN+15", false, false, false, "real time signal 15" );
+ AddSignal (50, "SIGRTMAX-14", false, false, false, "real time signal 16" ); // switching to SIGRTMAX-xxx to match "kill -l" output
+ AddSignal (51, "SIGRTMAX-13", false, false, false, "real time signal 17" );
+ AddSignal (52, "SIGRTMAX-12", false, false, false, "real time signal 18" );
+ AddSignal (53, "SIGRTMAX-11", false, false, false, "real time signal 19" );
+ AddSignal (54, "SIGRTMAX-10", false, false, false, "real time signal 20" );
+ AddSignal (55, "SIGRTMAX-9", false, false, false, "real time signal 21" );
+ AddSignal (56, "SIGRTMAX-8", false, false, false, "real time signal 22" );
+ AddSignal (57, "SIGRTMAX-7", false, false, false, "real time signal 23" );
+ AddSignal (58, "SIGRTMAX-6", false, false, false, "real time signal 24" );
+ AddSignal (59, "SIGRTMAX-5", false, false, false, "real time signal 25" );
+ AddSignal (60, "SIGRTMAX-4", false, false, false, "real time signal 26" );
+ AddSignal (61, "SIGRTMAX-3", false, false, false, "real time signal 27" );
+ AddSignal (62, "SIGRTMAX-2", false, false, false, "real time signal 28" );
+ AddSignal (63, "SIGRTMAX-1", false, false, false, "real time signal 29" );
+ AddSignal (64, "SIGRTMAX", false, false, false, "real time signal 30" );
}
diff --git a/source/Plugins/Process/Utility/NetBSDSignals.cpp b/source/Plugins/Process/Utility/NetBSDSignals.cpp
new file mode 100644
index 000000000000..5dce51616c4e
--- /dev/null
+++ b/source/Plugins/Process/Utility/NetBSDSignals.cpp
@@ -0,0 +1,34 @@
+//===-- NetBSDSignals.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "NetBSDSignals.h"
+
+using namespace lldb_private;
+
+NetBSDSignals::NetBSDSignals()
+ : UnixSignals()
+{
+ Reset();
+}
+
+void
+NetBSDSignals::Reset()
+{
+ UnixSignals::Reset();
+ // SIGNO NAME SUPPRESS STOP NOTIFY DESCRIPTION
+ // ====== ============ ======== ====== ====== ===================================================
+ AddSignal (32, "SIGPWR", false, true , true , "power fail/restart (not reset when caught)");
+#ifdef SIGRTMIN /* SIGRTMAX */
+ /* Kernel only; not exposed to userland yet */
+#endif
+}
diff --git a/source/Plugins/Process/Utility/NetBSDSignals.h b/source/Plugins/Process/Utility/NetBSDSignals.h
new file mode 100644
index 000000000000..441402b056db
--- /dev/null
+++ b/source/Plugins/Process/Utility/NetBSDSignals.h
@@ -0,0 +1,31 @@
+//===-- NetBSDSignals.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_NetBSDSignals_H_
+#define liblldb_NetBSDSignals_H_
+
+// Project includes
+#include "lldb/Target/UnixSignals.h"
+
+namespace lldb_private {
+
+/// NetBSD specific set of Unix signals.
+class NetBSDSignals : public UnixSignals
+{
+public:
+ NetBSDSignals();
+
+private:
+ void
+ Reset() override;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_NetBSDSignals_H_
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
index 4138a6aaa2aa..452fb47ebc8a 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
@@ -34,8 +34,8 @@
#endif
// Project includes
-#include "ARM_GCC_Registers.h"
#include "ARM_DWARF_Registers.h"
+#include "Utility/ARM_ehframe_Registers.h"
#include "llvm/ADT/STLExtras.h"
@@ -172,89 +172,69 @@ enum
};
-RegisterContextDarwin_arm::RegisterContextDarwin_arm(Thread &thread, uint32_t concrete_frame_idx) :
- RegisterContext(thread, concrete_frame_idx),
- gpr(),
- fpu(),
- exc()
-{
- uint32_t i;
- for (i=0; i<kNumErrors; i++)
- {
- gpr_errs[i] = -1;
- fpu_errs[i] = -1;
- exc_errs[i] = -1;
- }
-}
-
-RegisterContextDarwin_arm::~RegisterContextDarwin_arm()
-{
-}
-
-
#define GPR_OFFSET(idx) ((idx) * 4)
#define FPU_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextDarwin_arm::GPR))
#define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU))
#define DBG_OFFSET(reg) ((LLVM_EXTENSION offsetof (RegisterContextDarwin_arm::DBG, reg) + sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU) + sizeof (RegisterContextDarwin_arm::EXC)))
-#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextDarwin_arm::DBG *)NULL)->reg[i]), DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i }, NULL, NULL
+#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextDarwin_arm::DBG *)NULL)->reg[i]), DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL
#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU) + sizeof (RegisterContextDarwin_arm::EXC))
static RegisterInfo g_register_infos[] = {
// General purpose registers
-// NAME ALT SZ OFFSET ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
+// NAME ALT SZ OFFSET ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS
// ====== ======= == ============= ============= ============ =============== =============== ========================= ===================== ============= ========== ===============
-{ "r0", NULL, 4, GPR_OFFSET(0), eEncodingUint, eFormatHex, { gcc_r0, dwarf_r0, LLDB_INVALID_REGNUM, gdb_arm_r0, gpr_r0 }, NULL, NULL},
-{ "r1", NULL, 4, GPR_OFFSET(1), eEncodingUint, eFormatHex, { gcc_r1, dwarf_r1, LLDB_INVALID_REGNUM, gdb_arm_r1, gpr_r1 }, NULL, NULL},
-{ "r2", NULL, 4, GPR_OFFSET(2), eEncodingUint, eFormatHex, { gcc_r2, dwarf_r2, LLDB_INVALID_REGNUM, gdb_arm_r2, gpr_r2 }, NULL, NULL},
-{ "r3", NULL, 4, GPR_OFFSET(3), eEncodingUint, eFormatHex, { gcc_r3, dwarf_r3, LLDB_INVALID_REGNUM, gdb_arm_r3, gpr_r3 }, NULL, NULL},
-{ "r4", NULL, 4, GPR_OFFSET(4), eEncodingUint, eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, gdb_arm_r4, gpr_r4 }, NULL, NULL},
-{ "r5", NULL, 4, GPR_OFFSET(5), eEncodingUint, eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, gdb_arm_r5, gpr_r5 }, NULL, NULL},
-{ "r6", NULL, 4, GPR_OFFSET(6), eEncodingUint, eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, gdb_arm_r6, gpr_r6 }, NULL, NULL},
-{ "r7", NULL, 4, GPR_OFFSET(7), eEncodingUint, eFormatHex, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, gdb_arm_r7, gpr_r7 }, NULL, NULL},
-{ "r8", NULL, 4, GPR_OFFSET(8), eEncodingUint, eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, gdb_arm_r8, gpr_r8 }, NULL, NULL},
-{ "r9", NULL, 4, GPR_OFFSET(9), eEncodingUint, eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, gdb_arm_r9, gpr_r9 }, NULL, NULL},
-{ "r10", NULL, 4, GPR_OFFSET(10), eEncodingUint, eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, gdb_arm_r10, gpr_r10 }, NULL, NULL},
-{ "r11", NULL, 4, GPR_OFFSET(11), eEncodingUint, eFormatHex, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM, gdb_arm_r11, gpr_r11 }, NULL, NULL},
-{ "r12", NULL, 4, GPR_OFFSET(12), eEncodingUint, eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, gdb_arm_r12, gpr_r12 }, NULL, NULL},
-{ "sp", "r13", 4, GPR_OFFSET(13), eEncodingUint, eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, gdb_arm_sp, gpr_sp }, NULL, NULL},
-{ "lr", "r14", 4, GPR_OFFSET(14), eEncodingUint, eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_arm_lr, gpr_lr }, NULL, NULL},
-{ "pc", "r15", 4, GPR_OFFSET(15), eEncodingUint, eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_arm_pc, gpr_pc }, NULL, NULL},
-{ "cpsr", "psr", 4, GPR_OFFSET(16), eEncodingUint, eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, gdb_arm_cpsr, gpr_cpsr }, NULL, NULL},
-
-{ "s0", NULL, 4, FPU_OFFSET(0), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, gdb_arm_s0, fpu_s0 }, NULL, NULL},
-{ "s1", NULL, 4, FPU_OFFSET(1), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, gdb_arm_s1, fpu_s1 }, NULL, NULL},
-{ "s2", NULL, 4, FPU_OFFSET(2), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, gdb_arm_s2, fpu_s2 }, NULL, NULL},
-{ "s3", NULL, 4, FPU_OFFSET(3), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, gdb_arm_s3, fpu_s3 }, NULL, NULL},
-{ "s4", NULL, 4, FPU_OFFSET(4), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, gdb_arm_s4, fpu_s4 }, NULL, NULL},
-{ "s5", NULL, 4, FPU_OFFSET(5), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, gdb_arm_s5, fpu_s5 }, NULL, NULL},
-{ "s6", NULL, 4, FPU_OFFSET(6), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, gdb_arm_s6, fpu_s6 }, NULL, NULL},
-{ "s7", NULL, 4, FPU_OFFSET(7), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, gdb_arm_s7, fpu_s7 }, NULL, NULL},
-{ "s8", NULL, 4, FPU_OFFSET(8), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, gdb_arm_s8, fpu_s8 }, NULL, NULL},
-{ "s9", NULL, 4, FPU_OFFSET(9), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, gdb_arm_s9, fpu_s9 }, NULL, NULL},
-{ "s10", NULL, 4, FPU_OFFSET(10), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, gdb_arm_s10, fpu_s10 }, NULL, NULL},
-{ "s11", NULL, 4, FPU_OFFSET(11), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, gdb_arm_s11, fpu_s11 }, NULL, NULL},
-{ "s12", NULL, 4, FPU_OFFSET(12), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, gdb_arm_s12, fpu_s12 }, NULL, NULL},
-{ "s13", NULL, 4, FPU_OFFSET(13), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, gdb_arm_s13, fpu_s13 }, NULL, NULL},
-{ "s14", NULL, 4, FPU_OFFSET(14), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, gdb_arm_s14, fpu_s14 }, NULL, NULL},
-{ "s15", NULL, 4, FPU_OFFSET(15), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, gdb_arm_s15, fpu_s15 }, NULL, NULL},
-{ "s16", NULL, 4, FPU_OFFSET(16), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, gdb_arm_s16, fpu_s16 }, NULL, NULL},
-{ "s17", NULL, 4, FPU_OFFSET(17), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, gdb_arm_s17, fpu_s17 }, NULL, NULL},
-{ "s18", NULL, 4, FPU_OFFSET(18), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, gdb_arm_s18, fpu_s18 }, NULL, NULL},
-{ "s19", NULL, 4, FPU_OFFSET(19), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, gdb_arm_s19, fpu_s19 }, NULL, NULL},
-{ "s20", NULL, 4, FPU_OFFSET(20), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, gdb_arm_s20, fpu_s20 }, NULL, NULL},
-{ "s21", NULL, 4, FPU_OFFSET(21), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, gdb_arm_s21, fpu_s21 }, NULL, NULL},
-{ "s22", NULL, 4, FPU_OFFSET(22), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, gdb_arm_s22, fpu_s22 }, NULL, NULL},
-{ "s23", NULL, 4, FPU_OFFSET(23), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, gdb_arm_s23, fpu_s23 }, NULL, NULL},
-{ "s24", NULL, 4, FPU_OFFSET(24), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, gdb_arm_s24, fpu_s24 }, NULL, NULL},
-{ "s25", NULL, 4, FPU_OFFSET(25), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, gdb_arm_s25, fpu_s25 }, NULL, NULL},
-{ "s26", NULL, 4, FPU_OFFSET(26), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, gdb_arm_s26, fpu_s26 }, NULL, NULL},
-{ "s27", NULL, 4, FPU_OFFSET(27), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, gdb_arm_s27, fpu_s27 }, NULL, NULL},
-{ "s28", NULL, 4, FPU_OFFSET(28), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, gdb_arm_s28, fpu_s28 }, NULL, NULL},
-{ "s29", NULL, 4, FPU_OFFSET(29), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, gdb_arm_s29, fpu_s29 }, NULL, NULL},
-{ "s30", NULL, 4, FPU_OFFSET(30), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, gdb_arm_s30, fpu_s30 }, NULL, NULL},
-{ "s31", NULL, 4, FPU_OFFSET(31), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, gdb_arm_s31, fpu_s31 }, NULL, NULL},
-{ "fpscr", NULL, 4, FPU_OFFSET(32), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, gdb_arm_fpscr, fpu_fpscr }, NULL, NULL},
+{ "r0", NULL, 4, GPR_OFFSET(0), eEncodingUint, eFormatHex, { ehframe_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r0 }, NULL, NULL},
+{ "r1", NULL, 4, GPR_OFFSET(1), eEncodingUint, eFormatHex, { ehframe_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r1 }, NULL, NULL},
+{ "r2", NULL, 4, GPR_OFFSET(2), eEncodingUint, eFormatHex, { ehframe_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r2 }, NULL, NULL},
+{ "r3", NULL, 4, GPR_OFFSET(3), eEncodingUint, eFormatHex, { ehframe_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r3 }, NULL, NULL},
+{ "r4", NULL, 4, GPR_OFFSET(4), eEncodingUint, eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r4 }, NULL, NULL},
+{ "r5", NULL, 4, GPR_OFFSET(5), eEncodingUint, eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r5 }, NULL, NULL},
+{ "r6", NULL, 4, GPR_OFFSET(6), eEncodingUint, eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r6 }, NULL, NULL},
+{ "r7", NULL, 4, GPR_OFFSET(7), eEncodingUint, eFormatHex, { ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, gpr_r7 }, NULL, NULL},
+{ "r8", NULL, 4, GPR_OFFSET(8), eEncodingUint, eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r8 }, NULL, NULL},
+{ "r9", NULL, 4, GPR_OFFSET(9), eEncodingUint, eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r9 }, NULL, NULL},
+{ "r10", NULL, 4, GPR_OFFSET(10), eEncodingUint, eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r10 }, NULL, NULL},
+{ "r11", NULL, 4, GPR_OFFSET(11), eEncodingUint, eFormatHex, { ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r11 }, NULL, NULL},
+{ "r12", NULL, 4, GPR_OFFSET(12), eEncodingUint, eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r12 }, NULL, NULL},
+{ "sp", "r13", 4, GPR_OFFSET(13), eEncodingUint, eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, gpr_sp }, NULL, NULL},
+{ "lr", "r14", 4, GPR_OFFSET(14), eEncodingUint, eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, gpr_lr }, NULL, NULL},
+{ "pc", "r15", 4, GPR_OFFSET(15), eEncodingUint, eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, gpr_pc }, NULL, NULL},
+{ "cpsr", "psr", 4, GPR_OFFSET(16), eEncodingUint, eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, gpr_cpsr }, NULL, NULL},
+
+{ "s0", NULL, 4, FPU_OFFSET(0), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s0 }, NULL, NULL},
+{ "s1", NULL, 4, FPU_OFFSET(1), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s1 }, NULL, NULL},
+{ "s2", NULL, 4, FPU_OFFSET(2), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s2 }, NULL, NULL},
+{ "s3", NULL, 4, FPU_OFFSET(3), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s3 }, NULL, NULL},
+{ "s4", NULL, 4, FPU_OFFSET(4), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s4 }, NULL, NULL},
+{ "s5", NULL, 4, FPU_OFFSET(5), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s5 }, NULL, NULL},
+{ "s6", NULL, 4, FPU_OFFSET(6), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s6 }, NULL, NULL},
+{ "s7", NULL, 4, FPU_OFFSET(7), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s7 }, NULL, NULL},
+{ "s8", NULL, 4, FPU_OFFSET(8), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s8 }, NULL, NULL},
+{ "s9", NULL, 4, FPU_OFFSET(9), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s9 }, NULL, NULL},
+{ "s10", NULL, 4, FPU_OFFSET(10), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s10 }, NULL, NULL},
+{ "s11", NULL, 4, FPU_OFFSET(11), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s11 }, NULL, NULL},
+{ "s12", NULL, 4, FPU_OFFSET(12), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s12 }, NULL, NULL},
+{ "s13", NULL, 4, FPU_OFFSET(13), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s13 }, NULL, NULL},
+{ "s14", NULL, 4, FPU_OFFSET(14), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s14 }, NULL, NULL},
+{ "s15", NULL, 4, FPU_OFFSET(15), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s15 }, NULL, NULL},
+{ "s16", NULL, 4, FPU_OFFSET(16), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s16 }, NULL, NULL},
+{ "s17", NULL, 4, FPU_OFFSET(17), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s17 }, NULL, NULL},
+{ "s18", NULL, 4, FPU_OFFSET(18), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s18 }, NULL, NULL},
+{ "s19", NULL, 4, FPU_OFFSET(19), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s19 }, NULL, NULL},
+{ "s20", NULL, 4, FPU_OFFSET(20), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s20 }, NULL, NULL},
+{ "s21", NULL, 4, FPU_OFFSET(21), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s21 }, NULL, NULL},
+{ "s22", NULL, 4, FPU_OFFSET(22), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s22 }, NULL, NULL},
+{ "s23", NULL, 4, FPU_OFFSET(23), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s23 }, NULL, NULL},
+{ "s24", NULL, 4, FPU_OFFSET(24), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s24 }, NULL, NULL},
+{ "s25", NULL, 4, FPU_OFFSET(25), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s25 }, NULL, NULL},
+{ "s26", NULL, 4, FPU_OFFSET(26), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s26 }, NULL, NULL},
+{ "s27", NULL, 4, FPU_OFFSET(27), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s27 }, NULL, NULL},
+{ "s28", NULL, 4, FPU_OFFSET(28), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s28 }, NULL, NULL},
+{ "s29", NULL, 4, FPU_OFFSET(29), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s29 }, NULL, NULL},
+{ "s30", NULL, 4, FPU_OFFSET(30), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s30 }, NULL, NULL},
+{ "s31", NULL, 4, FPU_OFFSET(31), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s31 }, NULL, NULL},
+{ "fpscr", NULL, 4, FPU_OFFSET(32), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpscr }, NULL, NULL},
{ "exception",NULL, 4, EXC_OFFSET(0), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception }, NULL, NULL},
{ "fsr", NULL, 4, EXC_OFFSET(1), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_fsr }, NULL, NULL},
@@ -403,6 +383,26 @@ g_exc_regnums[] =
static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
+RegisterContextDarwin_arm::RegisterContextDarwin_arm(Thread &thread, uint32_t concrete_frame_idx) :
+ RegisterContext(thread, concrete_frame_idx),
+ gpr(),
+ fpu(),
+ exc()
+{
+ uint32_t i;
+ for (i=0; i<kNumErrors; i++)
+ {
+ gpr_errs[i] = -1;
+ fpu_errs[i] = -1;
+ exc_errs[i] = -1;
+ }
+}
+
+RegisterContextDarwin_arm::~RegisterContextDarwin_arm()
+{
+}
+
+
void
RegisterContextDarwin_arm::InvalidateAllRegisters ()
{
@@ -940,27 +940,27 @@ RegisterContextDarwin_arm::ConvertRegisterKindToRegisterNumber (lldb::RegisterKi
break;
}
}
- else if (kind == eRegisterKindGCC)
+ else if (kind == eRegisterKindEHFrame)
{
switch (reg)
{
- case gcc_r0: return gpr_r0;
- case gcc_r1: return gpr_r1;
- case gcc_r2: return gpr_r2;
- case gcc_r3: return gpr_r3;
- case gcc_r4: return gpr_r4;
- case gcc_r5: return gpr_r5;
- case gcc_r6: return gpr_r6;
- case gcc_r7: return gpr_r7;
- case gcc_r8: return gpr_r8;
- case gcc_r9: return gpr_r9;
- case gcc_r10: return gpr_r10;
- case gcc_r11: return gpr_r11;
- case gcc_r12: return gpr_r12;
- case gcc_sp: return gpr_sp;
- case gcc_lr: return gpr_lr;
- case gcc_pc: return gpr_pc;
- case gcc_cpsr: return gpr_cpsr;
+ case ehframe_r0: return gpr_r0;
+ case ehframe_r1: return gpr_r1;
+ case ehframe_r2: return gpr_r2;
+ case ehframe_r3: return gpr_r3;
+ case ehframe_r4: return gpr_r4;
+ case ehframe_r5: return gpr_r5;
+ case ehframe_r6: return gpr_r6;
+ case ehframe_r7: return gpr_r7;
+ case ehframe_r8: return gpr_r8;
+ case ehframe_r9: return gpr_r9;
+ case ehframe_r10: return gpr_r10;
+ case ehframe_r11: return gpr_r11;
+ case ehframe_r12: return gpr_r12;
+ case ehframe_sp: return gpr_sp;
+ case ehframe_lr: return gpr_lr;
+ case ehframe_pc: return gpr_pc;
+ case ehframe_cpsr: return gpr_cpsr;
}
}
else if (kind == eRegisterKindLLDB)
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
index 23134efd43e6..f4d82259f9df 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
@@ -51,61 +51,59 @@
class RegisterContextDarwin_arm : public lldb_private::RegisterContext
{
public:
-
RegisterContextDarwin_arm(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
- virtual
- ~RegisterContextDarwin_arm();
+ ~RegisterContextDarwin_arm() override;
- virtual void
- InvalidateAllRegisters ();
+ void
+ InvalidateAllRegisters() override;
- virtual size_t
- GetRegisterCount ();
+ size_t
+ GetRegisterCount() override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual size_t
- GetRegisterSetCount ();
+ size_t
+ GetRegisterSetCount() override;
- virtual const lldb_private::RegisterSet *
- GetRegisterSet (size_t set);
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t set) override;
- virtual bool
- ReadRegister (const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &reg_value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &reg_value) override;
- virtual bool
- WriteRegister (const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &reg_value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &reg_value) override;
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
- virtual uint32_t
- NumSupportedHardwareBreakpoints ();
+ uint32_t
+ NumSupportedHardwareBreakpoints() override;
- virtual uint32_t
- SetHardwareBreakpoint (lldb::addr_t addr, size_t size);
+ uint32_t
+ SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override;
- virtual bool
- ClearHardwareBreakpoint (uint32_t hw_idx);
+ bool
+ ClearHardwareBreakpoint(uint32_t hw_idx) override;
- virtual uint32_t
- NumSupportedHardwareWatchpoints ();
+ uint32_t
+ NumSupportedHardwareWatchpoints() override;
- virtual uint32_t
- SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write);
+ uint32_t
+ SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) override;
- virtual bool
- ClearHardwareWatchpoint (uint32_t hw_index);
+ bool
+ ClearHardwareWatchpoint(uint32_t hw_index) override;
struct GPR
{
@@ -113,7 +111,6 @@ public:
uint32_t cpsr; // CPSR
};
-
struct QReg
{
uint8_t bytes[16];
@@ -163,7 +160,6 @@ public:
LogDBGRegisters (lldb_private::Log *log, const DBG& dbg);
protected:
-
enum
{
GPRRegSet = 1, // ARM_THREAD_STATE
@@ -330,4 +326,4 @@ protected:
GetRegisterInfos ();
};
-#endif // liblldb_RegisterContextDarwin_arm_h_
+#endif // liblldb_RegisterContextDarwin_arm_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
index e08a87369e4d..7de042dd11a9 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
@@ -36,31 +36,11 @@
#endif
// Project includes
-#include "ARM64_GCC_Registers.h"
#include "ARM64_DWARF_Registers.h"
using namespace lldb;
using namespace lldb_private;
-RegisterContextDarwin_arm64::RegisterContextDarwin_arm64(Thread &thread, uint32_t concrete_frame_idx) :
- RegisterContext(thread, concrete_frame_idx),
- gpr(),
- fpu(),
- exc()
-{
- uint32_t i;
- for (i=0; i<kNumErrors; i++)
- {
- gpr_errs[i] = -1;
- fpu_errs[i] = -1;
- exc_errs[i] = -1;
- }
-}
-
-RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64()
-{
-}
-
#define GPR_OFFSET(idx) ((idx) * 8)
#define GPR_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::GPR, reg))
@@ -71,7 +51,7 @@ RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64()
#define EXC_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::EXC, reg) + sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU))
#define DBG_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_arm64::DBG, reg) + sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU) + sizeof (RegisterContextDarwin_arm64::EXC))
-#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextDarwin_arm64::DBG *)NULL)->reg[i]), DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i }, NULL, NULL
+#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextDarwin_arm64::DBG *)NULL)->reg[i]), DBG_OFFSET_NAME(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL
#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_arm64::GPR) + sizeof (RegisterContextDarwin_arm64::FPU) + sizeof (RegisterContextDarwin_arm64::EXC))
//-----------------------------------------------------------------------------
@@ -173,6 +153,26 @@ g_exc_regnums[] =
static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos_arm64);
+RegisterContextDarwin_arm64::RegisterContextDarwin_arm64(Thread &thread, uint32_t concrete_frame_idx) :
+ RegisterContext(thread, concrete_frame_idx),
+ gpr(),
+ fpu(),
+ exc()
+{
+ uint32_t i;
+ for (i=0; i<kNumErrors; i++)
+ {
+ gpr_errs[i] = -1;
+ fpu_errs[i] = -1;
+ exc_errs[i] = -1;
+ }
+}
+
+RegisterContextDarwin_arm64::~RegisterContextDarwin_arm64()
+{
+}
+
+
void
RegisterContextDarwin_arm64::InvalidateAllRegisters ()
{
@@ -488,7 +488,7 @@ RegisterContextDarwin_arm64::ReadRegister (const RegisterInfo *reg_info, Registe
case fpu_v29:
case fpu_v30:
case fpu_v31:
- value.SetBytes(fpu.v[reg].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder());
+ value.SetBytes(fpu.v[reg].bytes, reg_info->byte_size, endian::InlHostByteOrder());
break;
case fpu_fpsr:
@@ -770,44 +770,44 @@ RegisterContextDarwin_arm64::ConvertRegisterKindToRegisterNumber (RegisterKind k
break;
}
}
- else if (kind == eRegisterKindGCC)
+ else if (kind == eRegisterKindEHFrame)
{
switch (reg)
{
- case arm64_gcc::x0: return gpr_x0;
- case arm64_gcc::x1: return gpr_x1;
- case arm64_gcc::x2: return gpr_x2;
- case arm64_gcc::x3: return gpr_x3;
- case arm64_gcc::x4: return gpr_x4;
- case arm64_gcc::x5: return gpr_x5;
- case arm64_gcc::x6: return gpr_x6;
- case arm64_gcc::x7: return gpr_x7;
- case arm64_gcc::x8: return gpr_x8;
- case arm64_gcc::x9: return gpr_x9;
- case arm64_gcc::x10: return gpr_x10;
- case arm64_gcc::x11: return gpr_x11;
- case arm64_gcc::x12: return gpr_x12;
- case arm64_gcc::x13: return gpr_x13;
- case arm64_gcc::x14: return gpr_x14;
- case arm64_gcc::x15: return gpr_x15;
- case arm64_gcc::x16: return gpr_x16;
- case arm64_gcc::x17: return gpr_x17;
- case arm64_gcc::x18: return gpr_x18;
- case arm64_gcc::x19: return gpr_x19;
- case arm64_gcc::x20: return gpr_x20;
- case arm64_gcc::x21: return gpr_x21;
- case arm64_gcc::x22: return gpr_x22;
- case arm64_gcc::x23: return gpr_x23;
- case arm64_gcc::x24: return gpr_x24;
- case arm64_gcc::x25: return gpr_x25;
- case arm64_gcc::x26: return gpr_x26;
- case arm64_gcc::x27: return gpr_x27;
- case arm64_gcc::x28: return gpr_x28;
- case arm64_gcc::fp: return gpr_fp;
- case arm64_gcc::sp: return gpr_sp;
- case arm64_gcc::lr: return gpr_lr;
- case arm64_gcc::pc: return gpr_pc;
- case arm64_gcc::cpsr: return gpr_cpsr;
+ case arm64_ehframe::x0: return gpr_x0;
+ case arm64_ehframe::x1: return gpr_x1;
+ case arm64_ehframe::x2: return gpr_x2;
+ case arm64_ehframe::x3: return gpr_x3;
+ case arm64_ehframe::x4: return gpr_x4;
+ case arm64_ehframe::x5: return gpr_x5;
+ case arm64_ehframe::x6: return gpr_x6;
+ case arm64_ehframe::x7: return gpr_x7;
+ case arm64_ehframe::x8: return gpr_x8;
+ case arm64_ehframe::x9: return gpr_x9;
+ case arm64_ehframe::x10: return gpr_x10;
+ case arm64_ehframe::x11: return gpr_x11;
+ case arm64_ehframe::x12: return gpr_x12;
+ case arm64_ehframe::x13: return gpr_x13;
+ case arm64_ehframe::x14: return gpr_x14;
+ case arm64_ehframe::x15: return gpr_x15;
+ case arm64_ehframe::x16: return gpr_x16;
+ case arm64_ehframe::x17: return gpr_x17;
+ case arm64_ehframe::x18: return gpr_x18;
+ case arm64_ehframe::x19: return gpr_x19;
+ case arm64_ehframe::x20: return gpr_x20;
+ case arm64_ehframe::x21: return gpr_x21;
+ case arm64_ehframe::x22: return gpr_x22;
+ case arm64_ehframe::x23: return gpr_x23;
+ case arm64_ehframe::x24: return gpr_x24;
+ case arm64_ehframe::x25: return gpr_x25;
+ case arm64_ehframe::x26: return gpr_x26;
+ case arm64_ehframe::x27: return gpr_x27;
+ case arm64_ehframe::x28: return gpr_x28;
+ case arm64_ehframe::fp: return gpr_fp;
+ case arm64_ehframe::sp: return gpr_sp;
+ case arm64_ehframe::lr: return gpr_lr;
+ case arm64_ehframe::pc: return gpr_pc;
+ case arm64_ehframe::cpsr: return gpr_cpsr;
}
}
else if (kind == eRegisterKindLLDB)
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h
index aeac15e9b09a..b228c42ade53 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h
@@ -32,52 +32,50 @@
class RegisterContextDarwin_arm64 : public lldb_private::RegisterContext
{
public:
-
RegisterContextDarwin_arm64(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
- virtual
- ~RegisterContextDarwin_arm64();
+ ~RegisterContextDarwin_arm64() override;
- virtual void
- InvalidateAllRegisters ();
+ void
+ InvalidateAllRegisters() override;
- virtual size_t
- GetRegisterCount ();
+ size_t
+ GetRegisterCount() override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual size_t
- GetRegisterSetCount ();
+ size_t
+ GetRegisterSetCount() override;
- virtual const lldb_private::RegisterSet *
- GetRegisterSet (size_t set);
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t set) override;
- virtual bool
- ReadRegister (const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &reg_value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &reg_value) override;
- virtual bool
- WriteRegister (const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &reg_value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &reg_value) override;
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
- virtual uint32_t
- NumSupportedHardwareWatchpoints ();
+ uint32_t
+ NumSupportedHardwareWatchpoints() override;
- virtual uint32_t
- SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write);
+ uint32_t
+ SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) override;
- virtual bool
- ClearHardwareWatchpoint (uint32_t hw_index);
+ bool
+ ClearHardwareWatchpoint(uint32_t hw_index) override;
// mirrors <mach/arm/thread_status.h> arm_thread_state64_t
struct GPR
@@ -90,7 +88,6 @@ public:
uint32_t cpsr; // cpsr
};
-
struct VReg
{
uint8_t bytes[16];
@@ -126,7 +123,6 @@ public:
LogDBGRegisters (lldb_private::Log *log, const DBG& dbg);
protected:
-
enum
{
GPRRegSet = 6, // ARM_THREAD_STATE64
@@ -293,4 +289,4 @@ protected:
GetRegisterInfos ();
};
-#endif // liblldb_RegisterContextDarwin_arm64_h_
+#endif // liblldb_RegisterContextDarwin_arm64_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
index 08144bf7ec26..1b01c28b5d96 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
@@ -98,16 +98,16 @@ enum
enum
{
- gcc_eax = 0,
- gcc_ecx,
- gcc_edx,
- gcc_ebx,
- gcc_ebp,
- gcc_esp,
- gcc_esi,
- gcc_edi,
- gcc_eip,
- gcc_eflags
+ ehframe_eax = 0,
+ ehframe_ecx,
+ ehframe_edx,
+ ehframe_ebx,
+ ehframe_ebp,
+ ehframe_esp,
+ ehframe_esi,
+ ehframe_edi,
+ ehframe_eip,
+ ehframe_eflags
};
enum
@@ -140,79 +140,6 @@ enum
dwarf_xmm7
};
-enum
-{
- gdb_eax = 0,
- gdb_ecx = 1,
- gdb_edx = 2,
- gdb_ebx = 3,
- gdb_esp = 4,
- gdb_ebp = 5,
- gdb_esi = 6,
- gdb_edi = 7,
- gdb_eip = 8,
- gdb_eflags = 9,
- gdb_cs = 10,
- gdb_ss = 11,
- gdb_ds = 12,
- gdb_es = 13,
- gdb_fs = 14,
- gdb_gs = 15,
- gdb_stmm0 = 16,
- gdb_stmm1 = 17,
- gdb_stmm2 = 18,
- gdb_stmm3 = 19,
- gdb_stmm4 = 20,
- gdb_stmm5 = 21,
- gdb_stmm6 = 22,
- gdb_stmm7 = 23,
- gdb_fctrl = 24, gdb_fcw = gdb_fctrl,
- gdb_fstat = 25, gdb_fsw = gdb_fstat,
- gdb_ftag = 26, gdb_ftw = gdb_ftag,
- gdb_fiseg = 27, gdb_fpu_cs = gdb_fiseg,
- gdb_fioff = 28, gdb_ip = gdb_fioff,
- gdb_foseg = 29, gdb_fpu_ds = gdb_foseg,
- gdb_fooff = 30, gdb_dp = gdb_fooff,
- gdb_fop = 31,
- gdb_xmm0 = 32,
- gdb_xmm1 = 33,
- gdb_xmm2 = 34,
- gdb_xmm3 = 35,
- gdb_xmm4 = 36,
- gdb_xmm5 = 37,
- gdb_xmm6 = 38,
- gdb_xmm7 = 39,
- gdb_mxcsr = 40,
- gdb_mm0 = 41,
- gdb_mm1 = 42,
- gdb_mm2 = 43,
- gdb_mm3 = 44,
- gdb_mm4 = 45,
- gdb_mm5 = 46,
- gdb_mm6 = 47,
- gdb_mm7 = 48
-};
-
-RegisterContextDarwin_i386::RegisterContextDarwin_i386 (Thread &thread, uint32_t concrete_frame_idx) :
- RegisterContext(thread, concrete_frame_idx),
- gpr(),
- fpu(),
- exc()
-{
- uint32_t i;
- for (i=0; i<kNumErrors; i++)
- {
- gpr_errs[i] = -1;
- fpu_errs[i] = -1;
- exc_errs[i] = -1;
- }
-}
-
-RegisterContextDarwin_i386::~RegisterContextDarwin_i386()
-{
-}
-
-
#define GPR_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_i386::GPR, reg))
#define FPU_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_i386::FPU, reg) + sizeof (RegisterContextDarwin_i386::GPR))
@@ -224,42 +151,42 @@ RegisterContextDarwin_i386::~RegisterContextDarwin_i386()
// sizes and offsets.
#define DEFINE_GPR(reg, alt) #reg, alt, sizeof(((RegisterContextDarwin_i386::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex
#define DEFINE_FPU_UINT(reg) #reg, NULL, sizeof(((RegisterContextDarwin_i386::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex
-#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextDarwin_i386::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_##reg##i, LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i }, NULL, NULL
+#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextDarwin_i386::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_##reg##i, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_##reg##i }, NULL, NULL
#define DEFINE_EXC(reg) #reg, NULL, sizeof(((RegisterContextDarwin_i386::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex
#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_i386::GPR) + sizeof (RegisterContextDarwin_i386::FPU) + sizeof (RegisterContextDarwin_i386::EXC))
static RegisterInfo g_register_infos[] =
{
-// Macro auto defines most stuff GCC DWARF GENERIC GDB LLDB VALUE REGS INVALIDATE REGS
+// Macro auto defines most stuff eh_frame DWARF GENERIC PROCESS PLUGIN LLDB VALUE REGS INVALIDATE REGS
// =============================== ======================= =================== ========================= ================== ================= ========== ===============
- { DEFINE_GPR(eax , NULL) , { gcc_eax , dwarf_eax , LLDB_INVALID_REGNUM , gdb_eax , gpr_eax }, NULL, NULL},
- { DEFINE_GPR(ebx , NULL) , { gcc_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , gdb_ebx , gpr_ebx }, NULL, NULL},
- { DEFINE_GPR(ecx , NULL) , { gcc_ecx , dwarf_ecx , LLDB_INVALID_REGNUM , gdb_ecx , gpr_ecx }, NULL, NULL},
- { DEFINE_GPR(edx , NULL) , { gcc_edx , dwarf_edx , LLDB_INVALID_REGNUM , gdb_edx , gpr_edx }, NULL, NULL},
- { DEFINE_GPR(edi , NULL) , { gcc_edi , dwarf_edi , LLDB_INVALID_REGNUM , gdb_edi , gpr_edi }, NULL, NULL},
- { DEFINE_GPR(esi , NULL) , { gcc_esi , dwarf_esi , LLDB_INVALID_REGNUM , gdb_esi , gpr_esi }, NULL, NULL},
- { DEFINE_GPR(ebp , "fp") , { gcc_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , gdb_ebp , gpr_ebp }, NULL, NULL},
- { DEFINE_GPR(esp , "sp") , { gcc_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , gdb_esp , gpr_esp }, NULL, NULL},
- { DEFINE_GPR(ss , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_ss , gpr_ss }, NULL, NULL},
- { DEFINE_GPR(eflags , "flags") , { gcc_eflags , dwarf_eflags , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags , gpr_eflags }, NULL, NULL},
- { DEFINE_GPR(eip , "pc") , { gcc_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , gdb_eip , gpr_eip }, NULL, NULL},
- { DEFINE_GPR(cs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_cs , gpr_cs }, NULL, NULL},
- { DEFINE_GPR(ds , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_ds , gpr_ds }, NULL, NULL},
- { DEFINE_GPR(es , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_es , gpr_es }, NULL, NULL},
- { DEFINE_GPR(fs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fs , gpr_fs }, NULL, NULL},
- { DEFINE_GPR(gs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_gs , gpr_gs }, NULL, NULL},
-
- { DEFINE_FPU_UINT(fcw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fcw , fpu_fcw }, NULL, NULL},
- { DEFINE_FPU_UINT(fsw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fsw , fpu_fsw }, NULL, NULL},
- { DEFINE_FPU_UINT(ftw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_ftw , fpu_ftw }, NULL, NULL},
- { DEFINE_FPU_UINT(fop) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fop , fpu_fop }, NULL, NULL},
- { DEFINE_FPU_UINT(ip) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_ip , fpu_ip }, NULL, NULL},
- { DEFINE_FPU_UINT(cs) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_cs , fpu_cs }, NULL, NULL},
- { DEFINE_FPU_UINT(dp) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_dp , fpu_dp }, NULL, NULL},
- { DEFINE_FPU_UINT(ds) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_ds , fpu_ds }, NULL, NULL},
- { DEFINE_FPU_UINT(mxcsr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_mxcsr , fpu_mxcsr }, NULL, NULL},
- { DEFINE_FPU_UINT(mxcsrmask) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_mxcsrmask}, NULL, NULL},
+ { DEFINE_GPR(eax , NULL) , { ehframe_eax , dwarf_eax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_eax }, NULL, NULL},
+ { DEFINE_GPR(ebx , NULL) , { ehframe_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_ebx }, NULL, NULL},
+ { DEFINE_GPR(ecx , NULL) , { ehframe_ecx , dwarf_ecx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_ecx }, NULL, NULL},
+ { DEFINE_GPR(edx , NULL) , { ehframe_edx , dwarf_edx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_edx }, NULL, NULL},
+ { DEFINE_GPR(edi , NULL) , { ehframe_edi , dwarf_edi , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_edi }, NULL, NULL},
+ { DEFINE_GPR(esi , NULL) , { ehframe_esi , dwarf_esi , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_esi }, NULL, NULL},
+ { DEFINE_GPR(ebp , "fp") , { ehframe_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, gpr_ebp }, NULL, NULL},
+ { DEFINE_GPR(esp , "sp") , { ehframe_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, gpr_esp }, NULL, NULL},
+ { DEFINE_GPR(ss , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_ss }, NULL, NULL},
+ { DEFINE_GPR(eflags , "flags") , { ehframe_eflags , dwarf_eflags , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, gpr_eflags }, NULL, NULL},
+ { DEFINE_GPR(eip , "pc") , { ehframe_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, gpr_eip }, NULL, NULL},
+ { DEFINE_GPR(cs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_cs }, NULL, NULL},
+ { DEFINE_GPR(ds , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_ds }, NULL, NULL},
+ { DEFINE_GPR(es , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_es }, NULL, NULL},
+ { DEFINE_GPR(fs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_fs }, NULL, NULL},
+ { DEFINE_GPR(gs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_gs }, NULL, NULL},
+
+ { DEFINE_FPU_UINT(fcw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_fcw }, NULL, NULL},
+ { DEFINE_FPU_UINT(fsw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_fsw }, NULL, NULL},
+ { DEFINE_FPU_UINT(ftw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_ftw }, NULL, NULL},
+ { DEFINE_FPU_UINT(fop) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_fop }, NULL, NULL},
+ { DEFINE_FPU_UINT(ip) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_ip }, NULL, NULL},
+ { DEFINE_FPU_UINT(cs) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_cs }, NULL, NULL},
+ { DEFINE_FPU_UINT(dp) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_dp }, NULL, NULL},
+ { DEFINE_FPU_UINT(ds) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_ds }, NULL, NULL},
+ { DEFINE_FPU_UINT(mxcsr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_mxcsr }, NULL, NULL},
+ { DEFINE_FPU_UINT(mxcsrmask) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_mxcsrmask}, NULL, NULL},
{ DEFINE_FPU_VECT(stmm,0) },
{ DEFINE_FPU_VECT(stmm,1) },
{ DEFINE_FPU_VECT(stmm,2) },
@@ -277,13 +204,33 @@ static RegisterInfo g_register_infos[] =
{ DEFINE_FPU_VECT(xmm,6) },
{ DEFINE_FPU_VECT(xmm,7) },
- { DEFINE_EXC(trapno) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_trapno }, NULL, NULL},
- { DEFINE_EXC(err) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_err }, NULL, NULL},
- { DEFINE_EXC(faultvaddr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_faultvaddr }, NULL, NULL}
+ { DEFINE_EXC(trapno) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_trapno }, NULL, NULL},
+ { DEFINE_EXC(err) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_err }, NULL, NULL},
+ { DEFINE_EXC(faultvaddr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, exc_faultvaddr }, NULL, NULL}
};
static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
+RegisterContextDarwin_i386::RegisterContextDarwin_i386 (Thread &thread, uint32_t concrete_frame_idx) :
+ RegisterContext(thread, concrete_frame_idx),
+ gpr(),
+ fpu(),
+ exc()
+{
+ uint32_t i;
+ for (i=0; i<kNumErrors; i++)
+ {
+ gpr_errs[i] = -1;
+ fpu_errs[i] = -1;
+ exc_errs[i] = -1;
+ }
+}
+
+RegisterContextDarwin_i386::~RegisterContextDarwin_i386()
+{
+}
+
+
void
RegisterContextDarwin_i386::InvalidateAllRegisters ()
{
@@ -859,7 +806,7 @@ RegisterContextDarwin_i386::ConvertRegisterKindToRegisterNumber (lldb::RegisterK
break;
}
}
- else if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
+ else if (kind == eRegisterKindEHFrame || kind == eRegisterKindDWARF)
{
switch (reg)
{
@@ -893,55 +840,6 @@ RegisterContextDarwin_i386::ConvertRegisterKindToRegisterNumber (lldb::RegisterK
break;
}
}
- else if (kind == eRegisterKindGDB)
- {
- switch (reg)
- {
- case gdb_eax : return gpr_eax;
- case gdb_ebx : return gpr_ebx;
- case gdb_ecx : return gpr_ecx;
- case gdb_edx : return gpr_edx;
- case gdb_esi : return gpr_esi;
- case gdb_edi : return gpr_edi;
- case gdb_ebp : return gpr_ebp;
- case gdb_esp : return gpr_esp;
- case gdb_eip : return gpr_eip;
- case gdb_eflags : return gpr_eflags;
- case gdb_cs : return gpr_cs;
- case gdb_ss : return gpr_ss;
- case gdb_ds : return gpr_ds;
- case gdb_es : return gpr_es;
- case gdb_fs : return gpr_fs;
- case gdb_gs : return gpr_gs;
- case gdb_stmm0 : return fpu_stmm0;
- case gdb_stmm1 : return fpu_stmm1;
- case gdb_stmm2 : return fpu_stmm2;
- case gdb_stmm3 : return fpu_stmm3;
- case gdb_stmm4 : return fpu_stmm4;
- case gdb_stmm5 : return fpu_stmm5;
- case gdb_stmm6 : return fpu_stmm6;
- case gdb_stmm7 : return fpu_stmm7;
- case gdb_fctrl : return fpu_fctrl;
- case gdb_fstat : return fpu_fstat;
- case gdb_ftag : return fpu_ftag;
- case gdb_fiseg : return fpu_fiseg;
- case gdb_fioff : return fpu_fioff;
- case gdb_foseg : return fpu_foseg;
- case gdb_fooff : return fpu_fooff;
- case gdb_fop : return fpu_fop;
- case gdb_xmm0 : return fpu_xmm0;
- case gdb_xmm1 : return fpu_xmm1;
- case gdb_xmm2 : return fpu_xmm2;
- case gdb_xmm3 : return fpu_xmm3;
- case gdb_xmm4 : return fpu_xmm4;
- case gdb_xmm5 : return fpu_xmm5;
- case gdb_xmm6 : return fpu_xmm6;
- case gdb_xmm7 : return fpu_xmm7;
- case gdb_mxcsr : return fpu_mxcsr;
- default:
- break;
- }
- }
else if (kind == eRegisterKindLLDB)
{
return reg;
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
index 1d03feb9f3dd..9568b0332b4c 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
@@ -20,45 +20,45 @@
class RegisterContextDarwin_i386 : public lldb_private::RegisterContext
{
public:
-
RegisterContextDarwin_i386(lldb_private::Thread &thread,
- uint32_t concrete_frame_idx);
+ uint32_t concrete_frame_idx);
- virtual
- ~RegisterContextDarwin_i386();
+ ~RegisterContextDarwin_i386() override;
- virtual void
- InvalidateAllRegisters ();
+ void
+ InvalidateAllRegisters() override;
- virtual size_t
- GetRegisterCount ();
+ size_t
+ GetRegisterCount() override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual size_t
- GetRegisterSetCount ();
+ size_t
+ GetRegisterSetCount() override;
- virtual const lldb_private::RegisterSet *
- GetRegisterSet (size_t set);
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t set) override;
- virtual bool
- ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
- virtual bool
- HardwareSingleStep (bool enable);
+ bool
+ HardwareSingleStep(bool enable) override;
struct GPR
{
@@ -121,7 +121,6 @@ public:
};
protected:
-
enum
{
GPRRegSet = 1,
@@ -266,4 +265,4 @@ protected:
GetRegisterInfos ();
};
-#endif // liblldb_RegisterContextDarwin_i386_h_
+#endif // liblldb_RegisterContextDarwin_i386_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
index 54124d187d54..aee6e1228d2a 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
@@ -111,132 +111,52 @@ enum
fpu_fooff = fpu_dp
};
-enum gcc_dwarf_regnums
-{
- gcc_dwarf_gpr_rax = 0,
- gcc_dwarf_gpr_rdx,
- gcc_dwarf_gpr_rcx,
- gcc_dwarf_gpr_rbx,
- gcc_dwarf_gpr_rsi,
- gcc_dwarf_gpr_rdi,
- gcc_dwarf_gpr_rbp,
- gcc_dwarf_gpr_rsp,
- gcc_dwarf_gpr_r8,
- gcc_dwarf_gpr_r9,
- gcc_dwarf_gpr_r10,
- gcc_dwarf_gpr_r11,
- gcc_dwarf_gpr_r12,
- gcc_dwarf_gpr_r13,
- gcc_dwarf_gpr_r14,
- gcc_dwarf_gpr_r15,
- gcc_dwarf_gpr_rip,
- gcc_dwarf_fpu_xmm0,
- gcc_dwarf_fpu_xmm1,
- gcc_dwarf_fpu_xmm2,
- gcc_dwarf_fpu_xmm3,
- gcc_dwarf_fpu_xmm4,
- gcc_dwarf_fpu_xmm5,
- gcc_dwarf_fpu_xmm6,
- gcc_dwarf_fpu_xmm7,
- gcc_dwarf_fpu_xmm8,
- gcc_dwarf_fpu_xmm9,
- gcc_dwarf_fpu_xmm10,
- gcc_dwarf_fpu_xmm11,
- gcc_dwarf_fpu_xmm12,
- gcc_dwarf_fpu_xmm13,
- gcc_dwarf_fpu_xmm14,
- gcc_dwarf_fpu_xmm15,
- gcc_dwarf_fpu_stmm0,
- gcc_dwarf_fpu_stmm1,
- gcc_dwarf_fpu_stmm2,
- gcc_dwarf_fpu_stmm3,
- gcc_dwarf_fpu_stmm4,
- gcc_dwarf_fpu_stmm5,
- gcc_dwarf_fpu_stmm6,
- gcc_dwarf_fpu_stmm7
-
-};
+enum ehframe_dwarf_regnums
+{
+ ehframe_dwarf_gpr_rax = 0,
+ ehframe_dwarf_gpr_rdx,
+ ehframe_dwarf_gpr_rcx,
+ ehframe_dwarf_gpr_rbx,
+ ehframe_dwarf_gpr_rsi,
+ ehframe_dwarf_gpr_rdi,
+ ehframe_dwarf_gpr_rbp,
+ ehframe_dwarf_gpr_rsp,
+ ehframe_dwarf_gpr_r8,
+ ehframe_dwarf_gpr_r9,
+ ehframe_dwarf_gpr_r10,
+ ehframe_dwarf_gpr_r11,
+ ehframe_dwarf_gpr_r12,
+ ehframe_dwarf_gpr_r13,
+ ehframe_dwarf_gpr_r14,
+ ehframe_dwarf_gpr_r15,
+ ehframe_dwarf_gpr_rip,
+ ehframe_dwarf_fpu_xmm0,
+ ehframe_dwarf_fpu_xmm1,
+ ehframe_dwarf_fpu_xmm2,
+ ehframe_dwarf_fpu_xmm3,
+ ehframe_dwarf_fpu_xmm4,
+ ehframe_dwarf_fpu_xmm5,
+ ehframe_dwarf_fpu_xmm6,
+ ehframe_dwarf_fpu_xmm7,
+ ehframe_dwarf_fpu_xmm8,
+ ehframe_dwarf_fpu_xmm9,
+ ehframe_dwarf_fpu_xmm10,
+ ehframe_dwarf_fpu_xmm11,
+ ehframe_dwarf_fpu_xmm12,
+ ehframe_dwarf_fpu_xmm13,
+ ehframe_dwarf_fpu_xmm14,
+ ehframe_dwarf_fpu_xmm15,
+ ehframe_dwarf_fpu_stmm0,
+ ehframe_dwarf_fpu_stmm1,
+ ehframe_dwarf_fpu_stmm2,
+ ehframe_dwarf_fpu_stmm3,
+ ehframe_dwarf_fpu_stmm4,
+ ehframe_dwarf_fpu_stmm5,
+ ehframe_dwarf_fpu_stmm6,
+ ehframe_dwarf_fpu_stmm7
-enum gdb_regnums
-{
- gdb_gpr_rax = 0,
- gdb_gpr_rbx = 1,
- gdb_gpr_rcx = 2,
- gdb_gpr_rdx = 3,
- gdb_gpr_rsi = 4,
- gdb_gpr_rdi = 5,
- gdb_gpr_rbp = 6,
- gdb_gpr_rsp = 7,
- gdb_gpr_r8 = 8,
- gdb_gpr_r9 = 9,
- gdb_gpr_r10 = 10,
- gdb_gpr_r11 = 11,
- gdb_gpr_r12 = 12,
- gdb_gpr_r13 = 13,
- gdb_gpr_r14 = 14,
- gdb_gpr_r15 = 15,
- gdb_gpr_rip = 16,
- gdb_gpr_rflags = 17,
- gdb_gpr_cs = 18,
- gdb_gpr_ss = 19,
- gdb_gpr_ds = 20,
- gdb_gpr_es = 21,
- gdb_gpr_fs = 22,
- gdb_gpr_gs = 23,
- gdb_fpu_stmm0 = 24,
- gdb_fpu_stmm1 = 25,
- gdb_fpu_stmm2 = 26,
- gdb_fpu_stmm3 = 27,
- gdb_fpu_stmm4 = 28,
- gdb_fpu_stmm5 = 29,
- gdb_fpu_stmm6 = 30,
- gdb_fpu_stmm7 = 31,
- gdb_fpu_fctrl = 32, gdb_fpu_fcw = gdb_fpu_fctrl,
- gdb_fpu_fstat = 33, gdb_fpu_fsw = gdb_fpu_fstat,
- gdb_fpu_ftag = 34, gdb_fpu_ftw = gdb_fpu_ftag,
- gdb_fpu_fiseg = 35, gdb_fpu_cs = gdb_fpu_fiseg,
- gdb_fpu_fioff = 36, gdb_fpu_ip = gdb_fpu_fioff,
- gdb_fpu_foseg = 37, gdb_fpu_ds = gdb_fpu_foseg,
- gdb_fpu_fooff = 38, gdb_fpu_dp = gdb_fpu_fooff,
- gdb_fpu_fop = 39,
- gdb_fpu_xmm0 = 40,
- gdb_fpu_xmm1 = 41,
- gdb_fpu_xmm2 = 42,
- gdb_fpu_xmm3 = 43,
- gdb_fpu_xmm4 = 44,
- gdb_fpu_xmm5 = 45,
- gdb_fpu_xmm6 = 46,
- gdb_fpu_xmm7 = 47,
- gdb_fpu_xmm8 = 48,
- gdb_fpu_xmm9 = 49,
- gdb_fpu_xmm10 = 50,
- gdb_fpu_xmm11 = 51,
- gdb_fpu_xmm12 = 52,
- gdb_fpu_xmm13 = 53,
- gdb_fpu_xmm14 = 54,
- gdb_fpu_xmm15 = 55,
- gdb_fpu_mxcsr = 56
};
-RegisterContextDarwin_x86_64::RegisterContextDarwin_x86_64 (Thread &thread, uint32_t concrete_frame_idx) :
- RegisterContext (thread, concrete_frame_idx),
- gpr(),
- fpu(),
- exc()
-{
- uint32_t i;
- for (i=0; i<kNumErrors; i++)
- {
- gpr_errs[i] = -1;
- fpu_errs[i] = -1;
- exc_errs[i] = -1;
- }
-}
-
-RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64()
-{
-}
-
#define GPR_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_x86_64::GPR, reg))
#define FPU_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_x86_64::FPU, reg) + sizeof (RegisterContextDarwin_x86_64::GPR))
#define EXC_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_x86_64::EXC, reg) + sizeof (RegisterContextDarwin_x86_64::GPR) + sizeof (RegisterContextDarwin_x86_64::FPU))
@@ -247,7 +167,7 @@ RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64()
// sizes and offsets.
#define DEFINE_GPR(reg, alt) #reg, alt, sizeof(((RegisterContextDarwin_x86_64::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex
#define DEFINE_FPU_UINT(reg) #reg, NULL, sizeof(((RegisterContextDarwin_x86_64::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex
-#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextDarwin_x86_64::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i }, NULL, NULL
+#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextDarwin_x86_64::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { ehframe_dwarf_fpu_##reg##i, ehframe_dwarf_fpu_##reg##i, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_##reg##i }, NULL, NULL
#define DEFINE_EXC(reg) #reg, NULL, sizeof(((RegisterContextDarwin_x86_64::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex
#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_x86_64::GPR) + sizeof (RegisterContextDarwin_x86_64::FPU) + sizeof (RegisterContextDarwin_x86_64::EXC))
@@ -255,39 +175,39 @@ RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64()
// General purpose registers for 64 bit
static RegisterInfo g_register_infos[] =
{
-// Macro auto defines most stuff GCC DWARF GENERIC GDB LLDB VALUE REGS INVALIDATE REGS
-// =============================== ====================== =================== ========================== ==================== =================== ========== ===============
- { DEFINE_GPR (rax , NULL) , { gcc_dwarf_gpr_rax , gcc_dwarf_gpr_rax , LLDB_INVALID_REGNUM , gdb_gpr_rax , gpr_rax }, NULL, NULL},
- { DEFINE_GPR (rbx , NULL) , { gcc_dwarf_gpr_rbx , gcc_dwarf_gpr_rbx , LLDB_INVALID_REGNUM , gdb_gpr_rbx , gpr_rbx }, NULL, NULL},
- { DEFINE_GPR (rcx , NULL) , { gcc_dwarf_gpr_rcx , gcc_dwarf_gpr_rcx , LLDB_INVALID_REGNUM , gdb_gpr_rcx , gpr_rcx }, NULL, NULL},
- { DEFINE_GPR (rdx , NULL) , { gcc_dwarf_gpr_rdx , gcc_dwarf_gpr_rdx , LLDB_INVALID_REGNUM , gdb_gpr_rdx , gpr_rdx }, NULL, NULL},
- { DEFINE_GPR (rdi , NULL) , { gcc_dwarf_gpr_rdi , gcc_dwarf_gpr_rdi , LLDB_INVALID_REGNUM , gdb_gpr_rdi , gpr_rdi }, NULL, NULL},
- { DEFINE_GPR (rsi , NULL) , { gcc_dwarf_gpr_rsi , gcc_dwarf_gpr_rsi , LLDB_INVALID_REGNUM , gdb_gpr_rsi , gpr_rsi }, NULL, NULL},
- { DEFINE_GPR (rbp , "fp") , { gcc_dwarf_gpr_rbp , gcc_dwarf_gpr_rbp , LLDB_REGNUM_GENERIC_FP , gdb_gpr_rbp , gpr_rbp }, NULL, NULL},
- { DEFINE_GPR (rsp , "sp") , { gcc_dwarf_gpr_rsp , gcc_dwarf_gpr_rsp , LLDB_REGNUM_GENERIC_SP , gdb_gpr_rsp , gpr_rsp }, NULL, NULL},
- { DEFINE_GPR (r8 , NULL) , { gcc_dwarf_gpr_r8 , gcc_dwarf_gpr_r8 , LLDB_INVALID_REGNUM , gdb_gpr_r8 , gpr_r8 }, NULL, NULL},
- { DEFINE_GPR (r9 , NULL) , { gcc_dwarf_gpr_r9 , gcc_dwarf_gpr_r9 , LLDB_INVALID_REGNUM , gdb_gpr_r9 , gpr_r9 }, NULL, NULL},
- { DEFINE_GPR (r10 , NULL) , { gcc_dwarf_gpr_r10 , gcc_dwarf_gpr_r10 , LLDB_INVALID_REGNUM , gdb_gpr_r10 , gpr_r10 }, NULL, NULL},
- { DEFINE_GPR (r11 , NULL) , { gcc_dwarf_gpr_r11 , gcc_dwarf_gpr_r11 , LLDB_INVALID_REGNUM , gdb_gpr_r11 , gpr_r11 }, NULL, NULL},
- { DEFINE_GPR (r12 , NULL) , { gcc_dwarf_gpr_r12 , gcc_dwarf_gpr_r12 , LLDB_INVALID_REGNUM , gdb_gpr_r12 , gpr_r12 }, NULL, NULL},
- { DEFINE_GPR (r13 , NULL) , { gcc_dwarf_gpr_r13 , gcc_dwarf_gpr_r13 , LLDB_INVALID_REGNUM , gdb_gpr_r13 , gpr_r13 }, NULL, NULL},
- { DEFINE_GPR (r14 , NULL) , { gcc_dwarf_gpr_r14 , gcc_dwarf_gpr_r14 , LLDB_INVALID_REGNUM , gdb_gpr_r14 , gpr_r14 }, NULL, NULL},
- { DEFINE_GPR (r15 , NULL) , { gcc_dwarf_gpr_r15 , gcc_dwarf_gpr_r15 , LLDB_INVALID_REGNUM , gdb_gpr_r15 , gpr_r15 }, NULL, NULL},
- { DEFINE_GPR (rip , "pc") , { gcc_dwarf_gpr_rip , gcc_dwarf_gpr_rip , LLDB_REGNUM_GENERIC_PC , gdb_gpr_rip , gpr_rip }, NULL, NULL},
- { DEFINE_GPR (rflags, "flags") , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags , gpr_rflags }, NULL, NULL},
- { DEFINE_GPR (cs , NULL) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_gpr_cs , gpr_cs }, NULL, NULL},
- { DEFINE_GPR (fs , NULL) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_gpr_fs , gpr_fs }, NULL, NULL},
- { DEFINE_GPR (gs , NULL) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_gpr_gs , gpr_gs }, NULL, NULL},
-
- { DEFINE_FPU_UINT(fcw) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_fcw , fpu_fcw }, NULL, NULL},
- { DEFINE_FPU_UINT(fsw) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_fsw , fpu_fsw }, NULL, NULL},
- { DEFINE_FPU_UINT(ftw) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_ftw , fpu_ftw }, NULL, NULL},
- { DEFINE_FPU_UINT(fop) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_fop , fpu_fop }, NULL, NULL},
- { DEFINE_FPU_UINT(ip) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_ip , fpu_ip }, NULL, NULL},
- { DEFINE_FPU_UINT(cs) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_cs , fpu_cs }, NULL, NULL},
- { DEFINE_FPU_UINT(dp) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_dp , fpu_dp }, NULL, NULL},
- { DEFINE_FPU_UINT(ds) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_ds , fpu_ds }, NULL, NULL},
- { DEFINE_FPU_UINT(mxcsr) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , gdb_fpu_mxcsr , fpu_mxcsr }, NULL, NULL},
+// Macro auto defines most stuff EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB VALUE REGS INVALIDATE REGS
+// =============================== ====================== =================== ========================== ==================== =================== ========== ===============
+ { DEFINE_GPR (rax , NULL) , { ehframe_dwarf_gpr_rax , ehframe_dwarf_gpr_rax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_rax }, NULL, NULL},
+ { DEFINE_GPR (rbx , NULL) , { ehframe_dwarf_gpr_rbx , ehframe_dwarf_gpr_rbx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_rbx }, NULL, NULL},
+ { DEFINE_GPR (rcx , NULL) , { ehframe_dwarf_gpr_rcx , ehframe_dwarf_gpr_rcx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_rcx }, NULL, NULL},
+ { DEFINE_GPR (rdx , NULL) , { ehframe_dwarf_gpr_rdx , ehframe_dwarf_gpr_rdx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_rdx }, NULL, NULL},
+ { DEFINE_GPR (rdi , NULL) , { ehframe_dwarf_gpr_rdi , ehframe_dwarf_gpr_rdi , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_rdi }, NULL, NULL},
+ { DEFINE_GPR (rsi , NULL) , { ehframe_dwarf_gpr_rsi , ehframe_dwarf_gpr_rsi , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_rsi }, NULL, NULL},
+ { DEFINE_GPR (rbp , "fp") , { ehframe_dwarf_gpr_rbp , ehframe_dwarf_gpr_rbp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, gpr_rbp }, NULL, NULL},
+ { DEFINE_GPR (rsp , "sp") , { ehframe_dwarf_gpr_rsp , ehframe_dwarf_gpr_rsp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, gpr_rsp }, NULL, NULL},
+ { DEFINE_GPR (r8 , NULL) , { ehframe_dwarf_gpr_r8 , ehframe_dwarf_gpr_r8 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r8 }, NULL, NULL},
+ { DEFINE_GPR (r9 , NULL) , { ehframe_dwarf_gpr_r9 , ehframe_dwarf_gpr_r9 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r9 }, NULL, NULL},
+ { DEFINE_GPR (r10 , NULL) , { ehframe_dwarf_gpr_r10 , ehframe_dwarf_gpr_r10 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r10 }, NULL, NULL},
+ { DEFINE_GPR (r11 , NULL) , { ehframe_dwarf_gpr_r11 , ehframe_dwarf_gpr_r11 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r11 }, NULL, NULL},
+ { DEFINE_GPR (r12 , NULL) , { ehframe_dwarf_gpr_r12 , ehframe_dwarf_gpr_r12 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r12 }, NULL, NULL},
+ { DEFINE_GPR (r13 , NULL) , { ehframe_dwarf_gpr_r13 , ehframe_dwarf_gpr_r13 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r13 }, NULL, NULL},
+ { DEFINE_GPR (r14 , NULL) , { ehframe_dwarf_gpr_r14 , ehframe_dwarf_gpr_r14 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r14 }, NULL, NULL},
+ { DEFINE_GPR (r15 , NULL) , { ehframe_dwarf_gpr_r15 , ehframe_dwarf_gpr_r15 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_r15 }, NULL, NULL},
+ { DEFINE_GPR (rip , "pc") , { ehframe_dwarf_gpr_rip , ehframe_dwarf_gpr_rip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, gpr_rip }, NULL, NULL},
+ { DEFINE_GPR (rflags, "flags") , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, gpr_rflags }, NULL, NULL},
+ { DEFINE_GPR (cs , NULL) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_cs }, NULL, NULL},
+ { DEFINE_GPR (fs , NULL) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_fs }, NULL, NULL},
+ { DEFINE_GPR (gs , NULL) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, gpr_gs }, NULL, NULL},
+
+ { DEFINE_FPU_UINT(fcw) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_fcw }, NULL, NULL},
+ { DEFINE_FPU_UINT(fsw) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_fsw }, NULL, NULL},
+ { DEFINE_FPU_UINT(ftw) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_ftw }, NULL, NULL},
+ { DEFINE_FPU_UINT(fop) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_fop }, NULL, NULL},
+ { DEFINE_FPU_UINT(ip) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_ip }, NULL, NULL},
+ { DEFINE_FPU_UINT(cs) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_cs }, NULL, NULL},
+ { DEFINE_FPU_UINT(dp) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_dp }, NULL, NULL},
+ { DEFINE_FPU_UINT(ds) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_ds }, NULL, NULL},
+ { DEFINE_FPU_UINT(mxcsr) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_mxcsr }, NULL, NULL},
{ DEFINE_FPU_UINT(mxcsrmask) , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, fpu_mxcsrmask }, NULL, NULL},
{ DEFINE_FPU_VECT(stmm,0) },
{ DEFINE_FPU_VECT(stmm,1) },
@@ -321,6 +241,25 @@ static RegisterInfo g_register_infos[] =
static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
+RegisterContextDarwin_x86_64::RegisterContextDarwin_x86_64 (Thread &thread, uint32_t concrete_frame_idx) :
+ RegisterContext (thread, concrete_frame_idx),
+ gpr(),
+ fpu(),
+ exc()
+{
+ uint32_t i;
+ for (i=0; i<kNumErrors; i++)
+ {
+ gpr_errs[i] = -1;
+ fpu_errs[i] = -1;
+ exc_errs[i] = -1;
+ }
+}
+
+RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64()
+{
+}
+
void
RegisterContextDarwin_x86_64::InvalidateAllRegisters ()
@@ -687,7 +626,7 @@ RegisterContextDarwin_x86_64::ReadRegister (const RegisterInfo *reg_info,
case fpu_stmm5:
case fpu_stmm6:
case fpu_stmm7:
- value.SetBytes(fpu.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder());
+ value.SetBytes(fpu.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, endian::InlHostByteOrder());
break;
case fpu_xmm0:
@@ -706,7 +645,7 @@ RegisterContextDarwin_x86_64::ReadRegister (const RegisterInfo *reg_info,
case fpu_xmm13:
case fpu_xmm14:
case fpu_xmm15:
- value.SetBytes(fpu.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder());
+ value.SetBytes(fpu.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, endian::InlHostByteOrder());
break;
case exc_trapno:
@@ -919,116 +858,51 @@ RegisterContextDarwin_x86_64::ConvertRegisterKindToRegisterNumber (lldb::Registe
break;
}
}
- else if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
- {
- switch (reg)
- {
- case gcc_dwarf_gpr_rax: return gpr_rax;
- case gcc_dwarf_gpr_rdx: return gpr_rdx;
- case gcc_dwarf_gpr_rcx: return gpr_rcx;
- case gcc_dwarf_gpr_rbx: return gpr_rbx;
- case gcc_dwarf_gpr_rsi: return gpr_rsi;
- case gcc_dwarf_gpr_rdi: return gpr_rdi;
- case gcc_dwarf_gpr_rbp: return gpr_rbp;
- case gcc_dwarf_gpr_rsp: return gpr_rsp;
- case gcc_dwarf_gpr_r8: return gpr_r8;
- case gcc_dwarf_gpr_r9: return gpr_r9;
- case gcc_dwarf_gpr_r10: return gpr_r10;
- case gcc_dwarf_gpr_r11: return gpr_r11;
- case gcc_dwarf_gpr_r12: return gpr_r12;
- case gcc_dwarf_gpr_r13: return gpr_r13;
- case gcc_dwarf_gpr_r14: return gpr_r14;
- case gcc_dwarf_gpr_r15: return gpr_r15;
- case gcc_dwarf_gpr_rip: return gpr_rip;
- case gcc_dwarf_fpu_xmm0: return fpu_xmm0;
- case gcc_dwarf_fpu_xmm1: return fpu_xmm1;
- case gcc_dwarf_fpu_xmm2: return fpu_xmm2;
- case gcc_dwarf_fpu_xmm3: return fpu_xmm3;
- case gcc_dwarf_fpu_xmm4: return fpu_xmm4;
- case gcc_dwarf_fpu_xmm5: return fpu_xmm5;
- case gcc_dwarf_fpu_xmm6: return fpu_xmm6;
- case gcc_dwarf_fpu_xmm7: return fpu_xmm7;
- case gcc_dwarf_fpu_xmm8: return fpu_xmm8;
- case gcc_dwarf_fpu_xmm9: return fpu_xmm9;
- case gcc_dwarf_fpu_xmm10: return fpu_xmm10;
- case gcc_dwarf_fpu_xmm11: return fpu_xmm11;
- case gcc_dwarf_fpu_xmm12: return fpu_xmm12;
- case gcc_dwarf_fpu_xmm13: return fpu_xmm13;
- case gcc_dwarf_fpu_xmm14: return fpu_xmm14;
- case gcc_dwarf_fpu_xmm15: return fpu_xmm15;
- case gcc_dwarf_fpu_stmm0: return fpu_stmm0;
- case gcc_dwarf_fpu_stmm1: return fpu_stmm1;
- case gcc_dwarf_fpu_stmm2: return fpu_stmm2;
- case gcc_dwarf_fpu_stmm3: return fpu_stmm3;
- case gcc_dwarf_fpu_stmm4: return fpu_stmm4;
- case gcc_dwarf_fpu_stmm5: return fpu_stmm5;
- case gcc_dwarf_fpu_stmm6: return fpu_stmm6;
- case gcc_dwarf_fpu_stmm7: return fpu_stmm7;
- default:
- break;
- }
- }
- else if (kind == eRegisterKindGDB)
+ else if (kind == eRegisterKindEHFrame || kind == eRegisterKindDWARF)
{
switch (reg)
{
- case gdb_gpr_rax : return gpr_rax;
- case gdb_gpr_rbx : return gpr_rbx;
- case gdb_gpr_rcx : return gpr_rcx;
- case gdb_gpr_rdx : return gpr_rdx;
- case gdb_gpr_rsi : return gpr_rsi;
- case gdb_gpr_rdi : return gpr_rdi;
- case gdb_gpr_rbp : return gpr_rbp;
- case gdb_gpr_rsp : return gpr_rsp;
- case gdb_gpr_r8 : return gpr_r8;
- case gdb_gpr_r9 : return gpr_r9;
- case gdb_gpr_r10 : return gpr_r10;
- case gdb_gpr_r11 : return gpr_r11;
- case gdb_gpr_r12 : return gpr_r12;
- case gdb_gpr_r13 : return gpr_r13;
- case gdb_gpr_r14 : return gpr_r14;
- case gdb_gpr_r15 : return gpr_r15;
- case gdb_gpr_rip : return gpr_rip;
- case gdb_gpr_rflags : return gpr_rflags;
- case gdb_gpr_cs : return gpr_cs;
- case gdb_gpr_ss : return gpr_gs; // HACK: For now for "ss", just copy what is in "gs"
- case gdb_gpr_ds : return gpr_gs; // HACK: For now for "ds", just copy what is in "gs"
- case gdb_gpr_es : return gpr_gs; // HACK: For now for "es", just copy what is in "gs"
- case gdb_gpr_fs : return gpr_fs;
- case gdb_gpr_gs : return gpr_gs;
- case gdb_fpu_stmm0 : return fpu_stmm0;
- case gdb_fpu_stmm1 : return fpu_stmm1;
- case gdb_fpu_stmm2 : return fpu_stmm2;
- case gdb_fpu_stmm3 : return fpu_stmm3;
- case gdb_fpu_stmm4 : return fpu_stmm4;
- case gdb_fpu_stmm5 : return fpu_stmm5;
- case gdb_fpu_stmm6 : return fpu_stmm6;
- case gdb_fpu_stmm7 : return fpu_stmm7;
- case gdb_fpu_fctrl : return fpu_fctrl;
- case gdb_fpu_fstat : return fpu_fstat;
- case gdb_fpu_ftag : return fpu_ftag;
- case gdb_fpu_fiseg : return fpu_fiseg;
- case gdb_fpu_fioff : return fpu_fioff;
- case gdb_fpu_foseg : return fpu_foseg;
- case gdb_fpu_fooff : return fpu_fooff;
- case gdb_fpu_fop : return fpu_fop;
- case gdb_fpu_xmm0 : return fpu_xmm0;
- case gdb_fpu_xmm1 : return fpu_xmm1;
- case gdb_fpu_xmm2 : return fpu_xmm2;
- case gdb_fpu_xmm3 : return fpu_xmm3;
- case gdb_fpu_xmm4 : return fpu_xmm4;
- case gdb_fpu_xmm5 : return fpu_xmm5;
- case gdb_fpu_xmm6 : return fpu_xmm6;
- case gdb_fpu_xmm7 : return fpu_xmm7;
- case gdb_fpu_xmm8 : return fpu_xmm8;
- case gdb_fpu_xmm9 : return fpu_xmm9;
- case gdb_fpu_xmm10 : return fpu_xmm10;
- case gdb_fpu_xmm11 : return fpu_xmm11;
- case gdb_fpu_xmm12 : return fpu_xmm12;
- case gdb_fpu_xmm13 : return fpu_xmm13;
- case gdb_fpu_xmm14 : return fpu_xmm14;
- case gdb_fpu_xmm15 : return fpu_xmm15;
- case gdb_fpu_mxcsr : return fpu_mxcsr;
+ case ehframe_dwarf_gpr_rax: return gpr_rax;
+ case ehframe_dwarf_gpr_rdx: return gpr_rdx;
+ case ehframe_dwarf_gpr_rcx: return gpr_rcx;
+ case ehframe_dwarf_gpr_rbx: return gpr_rbx;
+ case ehframe_dwarf_gpr_rsi: return gpr_rsi;
+ case ehframe_dwarf_gpr_rdi: return gpr_rdi;
+ case ehframe_dwarf_gpr_rbp: return gpr_rbp;
+ case ehframe_dwarf_gpr_rsp: return gpr_rsp;
+ case ehframe_dwarf_gpr_r8: return gpr_r8;
+ case ehframe_dwarf_gpr_r9: return gpr_r9;
+ case ehframe_dwarf_gpr_r10: return gpr_r10;
+ case ehframe_dwarf_gpr_r11: return gpr_r11;
+ case ehframe_dwarf_gpr_r12: return gpr_r12;
+ case ehframe_dwarf_gpr_r13: return gpr_r13;
+ case ehframe_dwarf_gpr_r14: return gpr_r14;
+ case ehframe_dwarf_gpr_r15: return gpr_r15;
+ case ehframe_dwarf_gpr_rip: return gpr_rip;
+ case ehframe_dwarf_fpu_xmm0: return fpu_xmm0;
+ case ehframe_dwarf_fpu_xmm1: return fpu_xmm1;
+ case ehframe_dwarf_fpu_xmm2: return fpu_xmm2;
+ case ehframe_dwarf_fpu_xmm3: return fpu_xmm3;
+ case ehframe_dwarf_fpu_xmm4: return fpu_xmm4;
+ case ehframe_dwarf_fpu_xmm5: return fpu_xmm5;
+ case ehframe_dwarf_fpu_xmm6: return fpu_xmm6;
+ case ehframe_dwarf_fpu_xmm7: return fpu_xmm7;
+ case ehframe_dwarf_fpu_xmm8: return fpu_xmm8;
+ case ehframe_dwarf_fpu_xmm9: return fpu_xmm9;
+ case ehframe_dwarf_fpu_xmm10: return fpu_xmm10;
+ case ehframe_dwarf_fpu_xmm11: return fpu_xmm11;
+ case ehframe_dwarf_fpu_xmm12: return fpu_xmm12;
+ case ehframe_dwarf_fpu_xmm13: return fpu_xmm13;
+ case ehframe_dwarf_fpu_xmm14: return fpu_xmm14;
+ case ehframe_dwarf_fpu_xmm15: return fpu_xmm15;
+ case ehframe_dwarf_fpu_stmm0: return fpu_stmm0;
+ case ehframe_dwarf_fpu_stmm1: return fpu_stmm1;
+ case ehframe_dwarf_fpu_stmm2: return fpu_stmm2;
+ case ehframe_dwarf_fpu_stmm3: return fpu_stmm3;
+ case ehframe_dwarf_fpu_stmm4: return fpu_stmm4;
+ case ehframe_dwarf_fpu_stmm5: return fpu_stmm5;
+ case ehframe_dwarf_fpu_stmm6: return fpu_stmm6;
+ case ehframe_dwarf_fpu_stmm7: return fpu_stmm7;
default:
break;
}
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
index 09e35e9c423e..ed627e194a26 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
@@ -23,41 +23,42 @@ public:
RegisterContextDarwin_x86_64 (lldb_private::Thread &thread,
uint32_t concrete_frame_idx);
- virtual
- ~RegisterContextDarwin_x86_64();
+ ~RegisterContextDarwin_x86_64() override;
- virtual void
- InvalidateAllRegisters ();
+ void
+ InvalidateAllRegisters() override;
- virtual size_t
- GetRegisterCount ();
+ size_t
+ GetRegisterCount() override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual size_t
- GetRegisterSetCount ();
+ size_t
+ GetRegisterSetCount() override;
- virtual const lldb_private::RegisterSet *
- GetRegisterSet (size_t set);
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t set) override;
- virtual bool
- ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
- virtual bool
- HardwareSingleStep (bool enable);
+ bool
+ HardwareSingleStep(bool enable) override;
struct GPR
{
@@ -268,7 +269,6 @@ protected:
static const lldb_private::RegisterInfo *
GetRegisterInfos ();
-
};
-#endif // liblldb_RegisterContextDarwin_x86_64_h_
+#endif // liblldb_RegisterContextDarwin_x86_64_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextDummy.cpp b/source/Plugins/Process/Utility/RegisterContextDummy.cpp
index 329b0a7968a2..0859e4e9419c 100644
--- a/source/Plugins/Process/Utility/RegisterContextDummy.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextDummy.cpp
@@ -51,10 +51,10 @@ RegisterContext (thread, concrete_frame_idx)
m_pc_reg_info.format = eFormatPointer;
m_pc_reg_info.invalidate_regs = NULL;
m_pc_reg_info.value_regs = NULL;
- m_pc_reg_info.kinds[eRegisterKindGCC] = LLDB_INVALID_REGNUM;
+ m_pc_reg_info.kinds[eRegisterKindEHFrame] = LLDB_INVALID_REGNUM;
m_pc_reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM;
m_pc_reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
- m_pc_reg_info.kinds[eRegisterKindGDB] = LLDB_INVALID_REGNUM;
+ m_pc_reg_info.kinds[eRegisterKindProcessPlugin] = LLDB_INVALID_REGNUM;
m_pc_reg_info.kinds[eRegisterKindLLDB] = LLDB_INVALID_REGNUM;
}
diff --git a/source/Plugins/Process/Utility/RegisterContextDummy.h b/source/Plugins/Process/Utility/RegisterContextDummy.h
index ddf466713048..9f6a8dc347b5 100644
--- a/source/Plugins/Process/Utility/RegisterContextDummy.h
+++ b/source/Plugins/Process/Utility/RegisterContextDummy.h
@@ -10,8 +10,12 @@
#ifndef lldb_RegisterContextDummy_h_
#define lldb_RegisterContextDummy_h_
+// C Includes
+// C++ Includes
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -25,42 +29,39 @@ public:
RegisterContextDummy (Thread &thread, uint32_t concrete_frame_idx, uint32_t address_byte_size);
- ///
- // pure virtual functions from the base class that we must implement
- ///
+ ~RegisterContextDummy() override;
- virtual
- ~RegisterContextDummy ();
+ void
+ InvalidateAllRegisters() override;
- virtual void
- InvalidateAllRegisters ();
+ size_t
+ GetRegisterCount() override;
- virtual size_t
- GetRegisterCount ();
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ size_t
+ GetRegisterSetCount() override;
- virtual size_t
- GetRegisterSetCount ();
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t reg_set) override;
- virtual const lldb_private::RegisterSet *
- GetRegisterSet (size_t reg_set);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
-
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
private:
//------------------------------------------------------------------
@@ -72,6 +73,7 @@ private:
DISALLOW_COPY_AND_ASSIGN (RegisterContextDummy);
};
+
} // namespace lldb_private
-#endif // lldb_RegisterContextDummy_h_
+#endif // lldb_RegisterContextDummy_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp b/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp
index 8005a6339f6d..a507dad69f60 100644
--- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.cpp
@@ -23,6 +23,7 @@ using namespace lldb_private;
// http://svnweb.freebsd.org/base/head/sys/arm/include/reg.h
#define GPR_OFFSET(idx) ((idx) * 4)
#define FPU_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextFreeBSD_arm::GPR))
+#define FPSCR_OFFSET (LLVM_EXTENSION offsetof (RegisterContextFreeBSD_arm::FPU, fpscr) + sizeof (RegisterContextFreeBSD_arm::GPR))
#define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextFreeBSD_arm::GPR) + sizeof (RegisterContextFreeBSD_arm::FPU))
#define DBG_OFFSET(reg) ((LLVM_EXTENSION offsetof (RegisterContextFreeBSD_arm::DBG, reg) + sizeof (RegisterContextFreeBSD_arm::GPR) + sizeof (RegisterContextFreeBSD_arm::FPU) + sizeof (RegisterContextFreeBSD_arm::EXC)))
diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h b/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h
index c4287e9f0a47..f2d9364b3ce6 100644
--- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h
+++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm.h
@@ -12,7 +12,6 @@
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
-#include "RegisterContextPOSIX.h"
#include "RegisterInfoInterface.h"
class RegisterContextFreeBSD_arm
diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h b/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h
index 249027aaa76c..cfdae4d2b557 100644
--- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h
+++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h
@@ -10,7 +10,7 @@
#ifndef liblldb_RegisterContextFreeBSD_arm64_H_
#define liblldb_RegisterContextFreeBSD_arm64_H_
-#include "RegisterContextPOSIX.h"
+#include "RegisterInfoInterface.h"
class RegisterContextFreeBSD_arm64:
public lldb_private::RegisterInfoInterface
diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h b/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h
index 62792c02e2b9..9527fc03f728 100644
--- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h
+++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_i386.h
@@ -10,7 +10,7 @@
#ifndef liblldb_RegisterContextFreeBSD_i386_H_
#define liblldb_RegisterContextFreeBSD_i386_H_
-#include "RegisterContextPOSIX.h"
+#include "RegisterInfoInterface.h"
class RegisterContextFreeBSD_i386
: public lldb_private::RegisterInfoInterface
diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h b/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h
index f9a3ce09c5b1..5c042af20eac 100644
--- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h
+++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h
@@ -10,7 +10,7 @@
#ifndef liblldb_RegisterContextFreeBSD_mips64_H_
#define liblldb_RegisterContextFreeBSD_mips64_H_
-#include "RegisterContextPOSIX.h"
+#include "RegisterInfoInterface.h"
class RegisterContextFreeBSD_mips64:
public lldb_private::RegisterInfoInterface
diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h
index b907fe99b5e0..930683f8a870 100644
--- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h
+++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h
@@ -7,17 +7,21 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextFreeBSD_powerpc_H_
-#define liblldb_RegisterContextFreeBSD_powerpc_H_
+#ifndef liblldb_RegisterContextFreeBSD_powerpc_h_
+#define liblldb_RegisterContextFreeBSD_powerpc_h_
-#include "RegisterContextPOSIX.h"
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "RegisterInfoInterface.h"
class RegisterContextFreeBSD_powerpc:
public lldb_private::RegisterInfoInterface
{
public:
RegisterContextFreeBSD_powerpc(const lldb_private::ArchSpec &target_arch);
- virtual ~RegisterContextFreeBSD_powerpc();
+ ~RegisterContextFreeBSD_powerpc() override;
size_t
GetGPRSize() const override;
@@ -34,7 +38,7 @@ class RegisterContextFreeBSD_powerpc32:
{
public:
RegisterContextFreeBSD_powerpc32(const lldb_private::ArchSpec &target_arch);
- virtual ~RegisterContextFreeBSD_powerpc32();
+ ~RegisterContextFreeBSD_powerpc32() override;
size_t
GetGPRSize() const override;
@@ -51,7 +55,7 @@ class RegisterContextFreeBSD_powerpc64:
{
public:
RegisterContextFreeBSD_powerpc64(const lldb_private::ArchSpec &target_arch);
- virtual ~RegisterContextFreeBSD_powerpc64();
+ ~RegisterContextFreeBSD_powerpc64() override;
size_t
GetGPRSize() const override;
@@ -63,4 +67,4 @@ public:
GetRegisterCount() const override;
};
-#endif
+#endif // liblldb_RegisterContextFreeBSD_powerpc_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h b/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h
index 21fbdb4681b3..e739fa50ed6c 100644
--- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h
+++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h
@@ -10,7 +10,7 @@
#ifndef liblldb_RegisterContextFreeBSD_x86_64_H_
#define liblldb_RegisterContextFreeBSD_x86_64_H_
-#include "RegisterContextPOSIX.h"
+#include "RegisterInfoInterface.h"
class RegisterContextFreeBSD_x86_64:
public lldb_private::RegisterInfoInterface
diff --git a/source/Plugins/Process/Utility/RegisterContextHistory.cpp b/source/Plugins/Process/Utility/RegisterContextHistory.cpp
index 3c370103629e..9d2181376e09 100644
--- a/source/Plugins/Process/Utility/RegisterContextHistory.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextHistory.cpp
@@ -52,10 +52,10 @@ RegisterContext (thread, concrete_frame_idx),
m_pc_reg_info.format = eFormatPointer;
m_pc_reg_info.invalidate_regs = NULL;
m_pc_reg_info.value_regs = NULL;
- m_pc_reg_info.kinds[eRegisterKindGCC] = LLDB_INVALID_REGNUM;
+ m_pc_reg_info.kinds[eRegisterKindEHFrame] = LLDB_INVALID_REGNUM;
m_pc_reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM;
m_pc_reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
- m_pc_reg_info.kinds[eRegisterKindGDB] = LLDB_INVALID_REGNUM;
+ m_pc_reg_info.kinds[eRegisterKindProcessPlugin] = LLDB_INVALID_REGNUM;
m_pc_reg_info.kinds[eRegisterKindLLDB] = LLDB_INVALID_REGNUM;
}
diff --git a/source/Plugins/Process/Utility/RegisterContextHistory.h b/source/Plugins/Process/Utility/RegisterContextHistory.h
index 04842c62aff1..3f44a1fde68b 100644
--- a/source/Plugins/Process/Utility/RegisterContextHistory.h
+++ b/source/Plugins/Process/Utility/RegisterContextHistory.h
@@ -10,8 +10,12 @@
#ifndef lldb_RegisterContextHistory_h_
#define lldb_RegisterContextHistory_h_
+// C Includes
+// C++ Includes
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -25,42 +29,39 @@ public:
RegisterContextHistory (Thread &thread, uint32_t concrete_frame_idx, uint32_t address_byte_size, lldb::addr_t pc_value);
- ///
- // pure virtual functions from the base class that we must implement
- ///
+ ~RegisterContextHistory() override;
- virtual
- ~RegisterContextHistory ();
+ void
+ InvalidateAllRegisters() override;
- virtual void
- InvalidateAllRegisters ();
+ size_t
+ GetRegisterCount() override;
- virtual size_t
- GetRegisterCount ();
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ size_t
+ GetRegisterSetCount() override;
- virtual size_t
- GetRegisterSetCount ();
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t reg_set) override;
- virtual const lldb_private::RegisterSet *
- GetRegisterSet (size_t reg_set);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
-
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
private:
//------------------------------------------------------------------
@@ -76,4 +77,4 @@ private:
};
} // namespace lldb_private
-#endif // lldb_RegisterContextHistory_h_
+#endif // lldb_RegisterContextHistory_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index 37b007cfffcf..278a1d5dabf6 100644
--- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -17,6 +17,7 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Symbol/ArmUnwindInfo.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/Function.h"
@@ -634,28 +635,30 @@ bool
RegisterContextLLDB::CheckIfLoopingStack ()
{
// If we have a bad stack setup, we can get the same CFA value multiple times -- or even
- // more devious, we can actually oscillate between two CFA values. Detect that here and
+ // more devious, we can actually oscillate between two CFA values. Detect that here and
// break out to avoid a possible infinite loop in lldb trying to unwind the stack.
- addr_t next_frame_cfa;
- addr_t next_next_frame_cfa = LLDB_INVALID_ADDRESS;
- if (GetNextFrame().get() && GetNextFrame()->GetCFA(next_frame_cfa))
+ // To detect when we have the same CFA value multiple times, we compare the CFA of the current
+ // frame with the 2nd next frame because in some specail case (e.g. signal hanlders, hand
+ // written assembly without ABI compiance) we can have 2 frames with the same CFA (in theory we
+ // can have arbitrary number of frames with the same CFA, but more then 2 is very very unlikely)
+
+ RegisterContextLLDB::SharedPtr next_frame = GetNextFrame();
+ if (next_frame)
{
- if (next_frame_cfa == m_cfa)
+ RegisterContextLLDB::SharedPtr next_next_frame = next_frame->GetNextFrame();
+ addr_t next_next_frame_cfa = LLDB_INVALID_ADDRESS;
+ if (next_next_frame && next_next_frame->GetCFA(next_next_frame_cfa))
{
- // We have a loop in the stack unwind
- return true;
- }
- if (GetNextFrame()->GetNextFrame().get() && GetNextFrame()->GetNextFrame()->GetCFA(next_next_frame_cfa)
- && next_next_frame_cfa == m_cfa)
- {
- // We have a loop in the stack unwind
- return true;
+ if (next_next_frame_cfa == m_cfa)
+ {
+ // We have a loop in the stack unwind
+ return true;
+ }
}
}
return false;
}
-
bool
RegisterContextLLDB::IsFrameZero () const
{
@@ -792,24 +795,38 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
func_unwinders_sp = pc_module_sp->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);
}
- // No FuncUnwinders available for this pc (i.e. a stripped function symbol and -fomit-frame-pointer).
- // Try using the eh_frame information relative to the current PC,
- // and finally fall back on the architectural default unwind.
+ // No FuncUnwinders available for this pc (stripped function symbols, lldb could not augment its
+ // function table with another source, like LC_FUNCTION_STARTS or eh_frame in ObjectFileMachO).
+ // See if eh_frame or the .ARM.exidx tables have unwind information for this address, else fall
+ // back to the architectural default unwind.
if (!func_unwinders_sp)
{
- DWARFCallFrameInfo *eh_frame = pc_module_sp && pc_module_sp->GetObjectFile() ?
- pc_module_sp->GetObjectFile()->GetUnwindTable().GetEHFrameInfo() : nullptr;
-
m_frame_type = eNormalFrame;
- if (eh_frame && m_current_pc.IsValid())
+
+ if (!pc_module_sp || !pc_module_sp->GetObjectFile() || !m_current_pc.IsValid())
+ return arch_default_unwind_plan_sp;
+
+ // Even with -fomit-frame-pointer, we can try eh_frame to get back on track.
+ DWARFCallFrameInfo *eh_frame = pc_module_sp->GetObjectFile()->GetUnwindTable().GetEHFrameInfo();
+ if (eh_frame)
{
unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
- // Even with -fomit-frame-pointer, we can try eh_frame to get back on track.
if (eh_frame->GetUnwindPlan (m_current_pc, *unwind_plan_sp))
return unwind_plan_sp;
else
unwind_plan_sp.reset();
}
+
+ ArmUnwindInfo *arm_exidx = pc_module_sp->GetObjectFile()->GetUnwindTable().GetArmUnwindInfo();
+ if (arm_exidx)
+ {
+ unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+ if (arm_exidx->GetUnwindPlan (exe_ctx.GetTargetRef(), m_current_pc, *unwind_plan_sp))
+ return unwind_plan_sp;
+ else
+ unwind_plan_sp.reset();
+ }
+
return arch_default_unwind_plan_sp;
}
@@ -864,12 +881,12 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
// then the architecture default plan and for hand written assembly code it is often
// written in a way that it valid at all location what helps in the most common
// cases when the instruction emulation fails.
- UnwindPlanSP eh_frame_unwind_plan = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one);
- if (eh_frame_unwind_plan &&
- eh_frame_unwind_plan.get() != unwind_plan_sp.get() &&
- eh_frame_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName())
+ UnwindPlanSP call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), m_current_offset_backed_up_one);
+ if (call_site_unwind_plan &&
+ call_site_unwind_plan.get() != unwind_plan_sp.get() &&
+ call_site_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName())
{
- m_fallback_unwind_plan_sp = eh_frame_unwind_plan;
+ m_fallback_unwind_plan_sp = call_site_unwind_plan;
}
else
{
@@ -909,12 +926,12 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
// more reliable even on non call sites then the architecture default plan and for hand
// written assembly code it is often written in a way that it valid at all location what
// helps in the most common cases when the instruction emulation fails.
- UnwindPlanSP eh_frame_unwind_plan = func_unwinders_sp->GetEHFrameUnwindPlan (process->GetTarget(), m_current_offset_backed_up_one);
- if (eh_frame_unwind_plan &&
- eh_frame_unwind_plan.get() != unwind_plan_sp.get() &&
- eh_frame_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName())
+ UnwindPlanSP call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), m_current_offset_backed_up_one);
+ if (call_site_unwind_plan &&
+ call_site_unwind_plan.get() != unwind_plan_sp.get() &&
+ call_site_unwind_plan->GetSourceName() != unwind_plan_sp->GetSourceName())
{
- m_fallback_unwind_plan_sp = eh_frame_unwind_plan;
+ m_fallback_unwind_plan_sp = call_site_unwind_plan;
}
else
{
@@ -1488,7 +1505,11 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
unwindplan_regloc.GetDWARFExpressionLength(),
process->GetByteOrder(), process->GetAddressByteSize());
ModuleSP opcode_ctx;
- DWARFExpression dwarfexpr (opcode_ctx, dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength());
+ DWARFExpression dwarfexpr (opcode_ctx,
+ dwarfdata,
+ nullptr,
+ 0,
+ unwindplan_regloc.GetDWARFExpressionLength());
dwarfexpr.SetRegisterKind (unwindplan_registerkind);
Value result;
Error error;
@@ -1784,7 +1805,11 @@ RegisterContextLLDB::ReadCFAValueForRow (lldb::RegisterKind row_register_kind,
row->GetCFAValue().GetDWARFExpressionLength(),
process->GetByteOrder(), process->GetAddressByteSize());
ModuleSP opcode_ctx;
- DWARFExpression dwarfexpr (opcode_ctx, dwarfdata, 0, row->GetCFAValue().GetDWARFExpressionLength());
+ DWARFExpression dwarfexpr (opcode_ctx,
+ dwarfdata,
+ nullptr,
+ 0,
+ row->GetCFAValue().GetDWARFExpressionLength());
dwarfexpr.SetRegisterKind (row_register_kind);
Value result;
Error error;
diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.h b/source/Plugins/Process/Utility/RegisterContextLLDB.h
index 5f94a977448d..68dca3d4965f 100644
--- a/source/Plugins/Process/Utility/RegisterContextLLDB.h
+++ b/source/Plugins/Process/Utility/RegisterContextLLDB.h
@@ -10,8 +10,12 @@
#ifndef lldb_RegisterContextLLDB_h_
#define lldb_RegisterContextLLDB_h_
+// C Includes
+// C++ Includes
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Symbol/UnwindPlan.h"
@@ -33,42 +37,39 @@ public:
lldb_private::SymbolContext& sym_ctx,
uint32_t frame_number, lldb_private::UnwindLLDB& unwind_lldb);
- ///
- // pure virtual functions from the base class that we must implement
- ///
-
- virtual
- ~RegisterContextLLDB () { }
+ ~RegisterContextLLDB() override = default;
- virtual void
- InvalidateAllRegisters ();
+ void
+ InvalidateAllRegisters() override;
- virtual size_t
- GetRegisterCount ();
+ size_t
+ GetRegisterCount() override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual size_t
- GetRegisterSetCount ();
+ size_t
+ GetRegisterSetCount() override;
- virtual const lldb_private::RegisterSet *
- GetRegisterSet (size_t reg_set);
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t reg_set) override;
- virtual bool
- ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
bool
IsValid () const;
@@ -99,7 +100,6 @@ private:
// UnwindLLDB needs to pass around references to RegisterLocations
friend class UnwindLLDB;
-
// Returns true if we have an unwind loop -- the same stack frame unwinding
// multiple times.
bool
@@ -130,7 +130,6 @@ private:
bool
IsSkipFrame () const;
-
//------------------------------------------------------------------
/// Determines if a SymbolContext is a trap handler or not
///
@@ -221,7 +220,6 @@ private:
bool
IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp, int &valid_pc_offset);
-
lldb_private::Thread& m_thread;
///
@@ -269,4 +267,4 @@ private:
} // namespace lldb_private
-#endif // lldb_RegisterContextLLDB_h_
+#endif // lldb_RegisterContextLLDB_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp
index e7784b1712c3..f8d97aa3482c 100644
--- a/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextLinux_arm.cpp
@@ -22,6 +22,7 @@ using namespace lldb_private;
// Based on RegisterContextDarwin_arm.cpp
#define GPR_OFFSET(idx) ((idx) * 4)
#define FPU_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextLinux_arm::GPR))
+#define FPSCR_OFFSET (LLVM_EXTENSION offsetof (RegisterContextLinux_arm::FPU, fpscr) + sizeof (RegisterContextLinux_arm::GPR))
#define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextLinux_arm::GPR) + sizeof (RegisterContextLinux_arm::FPU))
#define DBG_OFFSET(reg) ((LLVM_EXTENSION offsetof (RegisterContextLinux_arm::DBG, reg) + sizeof (RegisterContextLinux_arm::GPR) + sizeof (RegisterContextLinux_arm::FPU) + sizeof (RegisterContextLinux_arm::EXC)))
diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_arm.h b/source/Plugins/Process/Utility/RegisterContextLinux_arm.h
index 7087eb4c3dcc..c3d41f686dcd 100644
--- a/source/Plugins/Process/Utility/RegisterContextLinux_arm.h
+++ b/source/Plugins/Process/Utility/RegisterContextLinux_arm.h
@@ -12,7 +12,6 @@
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
-#include "RegisterContextPOSIX.h"
#include "RegisterInfoInterface.h"
class RegisterContextLinux_arm
diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp
index 8c23e39ff013..a4ab083995f6 100644
--- a/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextLinux_arm64.cpp
@@ -21,7 +21,7 @@
#define GPR_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::GPR, reg))
#define FPU_OFFSET(idx) ((idx) * 16 + sizeof (RegisterContextLinux_arm64::GPR))
-#define FPU_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::FPU, reg))
+#define FPU_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::FPU, reg) + sizeof (RegisterContextLinux_arm64::GPR))
#define EXC_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::EXC, reg) + sizeof (RegisterContextLinux_arm64::GPR) + sizeof (RegisterContextLinux_arm64::FPU))
#define DBG_OFFSET_NAME(reg) (LLVM_EXTENSION offsetof (RegisterContextLinux_arm64::DBG, reg) + sizeof (RegisterContextLinux_arm64::GPR) + sizeof (RegisterContextLinux_arm64::FPU) + sizeof (RegisterContextLinux_arm64::EXC))
diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h b/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h
index a9a5a0985f25..3de94b862583 100644
--- a/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h
+++ b/source/Plugins/Process/Utility/RegisterContextLinux_arm64.h
@@ -12,7 +12,6 @@
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
-#include "RegisterContextPOSIX.h"
#include "RegisterInfoInterface.h"
class RegisterContextLinux_arm64
diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp
index 4f6bbc8f8ab8..e39beef42888 100644
--- a/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextLinux_i386.cpp
@@ -26,7 +26,7 @@ struct GPR
uint32_t es;
uint32_t fs;
uint32_t gs;
- uint32_t orig_ax;
+ uint32_t orig_eax;
uint32_t eip;
uint32_t cs;
uint32_t eflags;
@@ -38,7 +38,8 @@ struct FPR_i386
{
uint16_t fctrl; // FPU Control Word (fcw)
uint16_t fstat; // FPU Status Word (fsw)
- uint16_t ftag; // FPU Tag Word (ftw)
+ uint8_t ftag; // FPU Tag Word (ftw)
+ uint8_t reserved_1; // Reserved
uint16_t fop; // Last Instruction Opcode (fop)
union
{
@@ -98,6 +99,9 @@ struct UserArea
RegisterContextLinux_i386::RegisterContextLinux_i386(const ArchSpec &target_arch) :
RegisterInfoInterface(target_arch)
{
+ RegisterInfo orig_ax = { "orig_eax", NULL, sizeof(((GPR*)NULL)->orig_eax), (LLVM_EXTENSION offsetof(GPR, orig_eax)), eEncodingUint, \
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL };
+ d_register_infos.push_back(orig_ax);
}
size_t
@@ -131,3 +135,9 @@ RegisterContextLinux_i386::GetUserRegisterCount () const
{
return static_cast<uint32_t> (k_num_user_registers_i386);
}
+
+const std::vector<lldb_private::RegisterInfo> *
+RegisterContextLinux_i386::GetDynamicRegisterInfoP() const
+{
+ return &d_register_infos;
+}
diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_i386.h b/source/Plugins/Process/Utility/RegisterContextLinux_i386.h
index cb71d7993e17..6c4768f49ac1 100644
--- a/source/Plugins/Process/Utility/RegisterContextLinux_i386.h
+++ b/source/Plugins/Process/Utility/RegisterContextLinux_i386.h
@@ -10,7 +10,7 @@
#ifndef liblldb_RegisterContextLinux_i386_H_
#define liblldb_RegisterContextLinux_i386_H_
-#include "RegisterContextPOSIX.h"
+#include "RegisterInfoInterface.h"
class RegisterContextLinux_i386
: public lldb_private::RegisterInfoInterface
@@ -29,6 +29,12 @@ public:
uint32_t
GetUserRegisterCount () const override;
+
+ const std::vector<lldb_private::RegisterInfo> *
+ GetDynamicRegisterInfoP() const override;
+
+private:
+ std::vector<lldb_private::RegisterInfo> d_register_infos;
};
#endif
diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp
index 4d58b85b5665..1b2281004d26 100644
--- a/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextLinux_mips.cpp
@@ -10,7 +10,7 @@
#include <vector>
#include <stddef.h>
-// For GDB, GCC and DWARF Register numbers
+// For eh_frame and DWARF Register numbers
#include "RegisterContextLinux_mips.h"
// Internal codes for mips registers
@@ -29,8 +29,17 @@ using namespace lldb;
#include "RegisterInfos_mips.h"
#undef DECLARE_REGISTER_INFOS_MIPS_STRUCT
-RegisterContextLinux_mips::RegisterContextLinux_mips(const ArchSpec &target_arch) :
- RegisterInfoInterface(target_arch)
+uint32_t
+GetUserRegisterInfoCount (bool msa_present)
+{
+ if (msa_present)
+ return static_cast<uint32_t> (k_num_user_registers_mips);
+ return static_cast<uint32_t> (k_num_user_registers_mips - k_num_msa_registers_mips);
+}
+
+RegisterContextLinux_mips::RegisterContextLinux_mips(const ArchSpec &target_arch, bool msa_present) :
+ RegisterInfoInterface(target_arch),
+ m_user_register_count (GetUserRegisterInfoCount (msa_present))
{
}
@@ -63,5 +72,5 @@ RegisterContextLinux_mips::GetRegisterCount () const
uint32_t
RegisterContextLinux_mips::GetUserRegisterCount () const
{
- return static_cast<uint32_t> (k_num_user_registers_mips);
+ return static_cast<uint32_t> (m_user_register_count);
}
diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_mips.h b/source/Plugins/Process/Utility/RegisterContextLinux_mips.h
index bcc2d002c854..c0bd5ad4f4f9 100644
--- a/source/Plugins/Process/Utility/RegisterContextLinux_mips.h
+++ b/source/Plugins/Process/Utility/RegisterContextLinux_mips.h
@@ -17,7 +17,7 @@ class RegisterContextLinux_mips
: public lldb_private::RegisterInfoInterface
{
public:
- RegisterContextLinux_mips(const lldb_private::ArchSpec &target_arch);
+ RegisterContextLinux_mips(const lldb_private::ArchSpec &target_arch, bool msa_present = true);
size_t
GetGPRSize() const override;
@@ -30,6 +30,9 @@ public:
uint32_t
GetUserRegisterCount () const override;
+
+private:
+ uint32_t m_user_register_count;
};
#endif
diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp
index 7f512f82be80..f2871e3b7352 100644
--- a/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextLinux_mips64.cpp
@@ -12,7 +12,7 @@
#include <vector>
#include <stddef.h>
-// For GDB, GCC and DWARF Register numbers
+// For eh_frame and DWARF Register numbers
#include "RegisterContextLinux_mips64.h"
// For GP and FP buffers
@@ -75,27 +75,31 @@ GetRegisterInfoCount (const ArchSpec &target_arch)
}
uint32_t
-GetUserRegisterInfoCount (const ArchSpec &target_arch)
+GetUserRegisterInfoCount (const ArchSpec &target_arch, bool msa_present)
{
switch (target_arch.GetMachine())
{
case llvm::Triple::mips:
case llvm::Triple::mipsel:
- return static_cast<uint32_t> (k_num_user_registers_mips);
+ if (msa_present)
+ return static_cast<uint32_t> (k_num_user_registers_mips);
+ return static_cast<uint32_t> (k_num_user_registers_mips - k_num_msa_registers_mips);
case llvm::Triple::mips64el:
case llvm::Triple::mips64:
- return static_cast<uint32_t> (k_num_user_registers_mips64);
+ if (msa_present)
+ return static_cast<uint32_t> (k_num_user_registers_mips64);
+ return static_cast<uint32_t> (k_num_user_registers_mips64 - k_num_msa_registers_mips64);
default:
assert(false && "Unhandled target architecture.");
return 0;
}
}
-RegisterContextLinux_mips64::RegisterContextLinux_mips64(const ArchSpec &target_arch) :
+RegisterContextLinux_mips64::RegisterContextLinux_mips64(const ArchSpec &target_arch, bool msa_present) :
lldb_private::RegisterInfoInterface(target_arch),
m_register_info_p (GetRegisterInfoPtr (target_arch)),
m_register_info_count (GetRegisterInfoCount (target_arch)),
- m_user_register_count (GetUserRegisterInfoCount (target_arch))
+ m_user_register_count (GetUserRegisterInfoCount (target_arch, msa_present))
{
}
diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h b/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h
index 86c662c52cea..843328c92e43 100644
--- a/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h
+++ b/source/Plugins/Process/Utility/RegisterContextLinux_mips64.h
@@ -19,7 +19,7 @@ class RegisterContextLinux_mips64
: public lldb_private::RegisterInfoInterface
{
public:
- RegisterContextLinux_mips64(const lldb_private::ArchSpec &target_arch);
+ RegisterContextLinux_mips64(const lldb_private::ArchSpec &target_arch, bool msa_present = true);
size_t
GetGPRSize() const override;
diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp
index c0993b47a126..78afe72fcfa9 100644
--- a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.cpp
@@ -32,7 +32,7 @@ typedef struct _GPR
uint64_t rdx;
uint64_t rsi;
uint64_t rdi;
- uint64_t orig_ax;
+ uint64_t orig_rax;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
@@ -171,6 +171,9 @@ RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(const ArchSpec &target_
m_register_info_count (GetRegisterInfoCount (target_arch)),
m_user_register_count (GetUserRegisterInfoCount (target_arch))
{
+ RegisterInfo orig_ax = { "orig_rax", NULL, sizeof(((GPR*)NULL)->orig_rax), (LLVM_EXTENSION offsetof(GPR, orig_rax)), eEncodingUint, \
+ eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL };
+ d_register_infos.push_back(orig_ax);
}
size_t
@@ -179,6 +182,12 @@ RegisterContextLinux_x86_64::GetGPRSize() const
return sizeof(GPR);
}
+const std::vector<lldb_private::RegisterInfo> *
+RegisterContextLinux_x86_64::GetDynamicRegisterInfoP() const
+{
+ return &d_register_infos;
+}
+
const RegisterInfo *
RegisterContextLinux_x86_64::GetRegisterInfo() const
{
diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h
index 0cdfae9ac943..ed0b7de9aae8 100644
--- a/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h
+++ b/source/Plugins/Process/Utility/RegisterContextLinux_x86_64.h
@@ -10,7 +10,7 @@
#ifndef liblldb_RegisterContextLinux_x86_64_H_
#define liblldb_RegisterContextLinux_x86_64_H_
-#include "RegisterContextPOSIX.h"
+#include "RegisterInfoInterface.h"
class RegisterContextLinux_x86_64
: public lldb_private::RegisterInfoInterface
@@ -30,10 +30,15 @@ public:
uint32_t
GetUserRegisterCount () const override;
+ const std::vector<lldb_private::RegisterInfo> *
+ GetDynamicRegisterInfoP() const override;
+
private:
const lldb_private::RegisterInfo *m_register_info_p;
uint32_t m_register_info_count;
uint32_t m_user_register_count;
+ std::vector<lldb_private::RegisterInfo> d_register_infos;
+
};
#endif
diff --git a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h
index 505b8d44a27a..0ddadbed01e0 100644
--- a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h
+++ b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h
@@ -22,56 +22,49 @@
class RegisterContextMacOSXFrameBackchain : public lldb_private::RegisterContext
{
public:
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
RegisterContextMacOSXFrameBackchain (lldb_private::Thread &thread,
uint32_t concrete_frame_idx,
const UnwindMacOSXFrameBackchain::Cursor &cursor);
- virtual
- ~RegisterContextMacOSXFrameBackchain ();
+ ~RegisterContextMacOSXFrameBackchain() override;
- //------------------------------------------------------------------
- // Subclasses must override these functions
- //------------------------------------------------------------------
- virtual void
- InvalidateAllRegisters ();
+ void
+ InvalidateAllRegisters() override;
- virtual size_t
- GetRegisterCount ();
+ size_t
+ GetRegisterCount() override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual size_t
- GetRegisterSetCount ();
+ size_t
+ GetRegisterSetCount() override;
- virtual const lldb_private::RegisterSet *
- GetRegisterSet (size_t reg_set);
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t reg_set) override;
- virtual bool
- ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
private:
UnwindMacOSXFrameBackchain::Cursor m_cursor;
bool m_cursor_is_valid;
- //------------------------------------------------------------------
- // For RegisterContextMacOSXFrameBackchain only
- //------------------------------------------------------------------
+
DISALLOW_COPY_AND_ASSIGN (RegisterContextMacOSXFrameBackchain);
};
-#endif // lldb_RegisterContextMacOSXFrameBackchain_h_
+#endif // lldb_RegisterContextMacOSXFrameBackchain_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextMemory.h b/source/Plugins/Process/Utility/RegisterContextMemory.h
index 9d97dfa723be..d61aba9543d4 100644
--- a/source/Plugins/Process/Utility/RegisterContextMemory.h
+++ b/source/Plugins/Process/Utility/RegisterContextMemory.h
@@ -25,39 +25,31 @@ class DynamicRegisterInfo;
class RegisterContextMemory : public lldb_private::RegisterContext
{
public:
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
RegisterContextMemory (lldb_private::Thread &thread,
uint32_t concrete_frame_idx,
DynamicRegisterInfo &reg_info,
lldb::addr_t reg_data_addr);
- virtual
- ~RegisterContextMemory ();
+ ~RegisterContextMemory() override;
- //------------------------------------------------------------------
- // Subclasses must override these functions
- //------------------------------------------------------------------
- virtual void
- InvalidateAllRegisters ();
+ void
+ InvalidateAllRegisters() override;
- virtual size_t
- GetRegisterCount ();
+ size_t
+ GetRegisterCount() override;
- virtual const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual size_t
- GetRegisterSetCount ();
+ size_t
+ GetRegisterSetCount() override;
- virtual const lldb_private::RegisterSet *
- GetRegisterSet (size_t reg_set);
+ const lldb_private::RegisterSet *
+ GetRegisterSet(size_t reg_set) override;
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
-
//------------------------------------------------------------------
// If all of the thread register are in a contiguous buffer in
// memory, then the default ReadRegister/WriteRegister and
@@ -66,24 +58,24 @@ public:
// class and modify the read/write functions as needed.
//------------------------------------------------------------------
- virtual bool
- ReadRegister (const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &reg_value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &reg_value) override;
- virtual bool
- WriteRegister (const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &reg_value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &reg_value) override;
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
void
SetAllRegisterData (const lldb::DataBufferSP &data_sp);
+
protected:
-
void
SetAllRegisterValid (bool b);
@@ -93,10 +85,7 @@ protected:
lldb::addr_t m_reg_data_addr; // If this is valid, then we have a register context that is stored in memmory
private:
- //------------------------------------------------------------------
- // For RegisterContextMemory only
- //------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (RegisterContextMemory);
};
-#endif // lldb_RegisterContextMemory_h_
+#endif // lldb_RegisterContextMemory_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
index d306f86256bc..029a0e7352ec 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
@@ -88,6 +88,54 @@ static const uint32_t g_fpu_regnums_arm[] =
fpu_s30_arm,
fpu_s31_arm,
fpu_fpscr_arm,
+ fpu_d0_arm,
+ fpu_d1_arm,
+ fpu_d2_arm,
+ fpu_d3_arm,
+ fpu_d4_arm,
+ fpu_d5_arm,
+ fpu_d6_arm,
+ fpu_d7_arm,
+ fpu_d8_arm,
+ fpu_d9_arm,
+ fpu_d10_arm,
+ fpu_d11_arm,
+ fpu_d12_arm,
+ fpu_d13_arm,
+ fpu_d14_arm,
+ fpu_d15_arm,
+ fpu_d16_arm,
+ fpu_d17_arm,
+ fpu_d18_arm,
+ fpu_d19_arm,
+ fpu_d20_arm,
+ fpu_d21_arm,
+ fpu_d22_arm,
+ fpu_d23_arm,
+ fpu_d24_arm,
+ fpu_d25_arm,
+ fpu_d26_arm,
+ fpu_d27_arm,
+ fpu_d28_arm,
+ fpu_d29_arm,
+ fpu_d30_arm,
+ fpu_d31_arm,
+ fpu_q0_arm,
+ fpu_q1_arm,
+ fpu_q2_arm,
+ fpu_q3_arm,
+ fpu_q4_arm,
+ fpu_q5_arm,
+ fpu_q6_arm,
+ fpu_q7_arm,
+ fpu_q8_arm,
+ fpu_q9_arm,
+ fpu_q10_arm,
+ fpu_q11_arm,
+ fpu_q12_arm,
+ fpu_q13_arm,
+ fpu_q14_arm,
+ fpu_q15_arm,
LLDB_INVALID_REGNUM // register sets need to end with this flag
};
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h
index a3a2926262f7..fbbcb9402911 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h
@@ -1,4 +1,4 @@
-//===-- RegisterContextPOSIX_arm.h ----------------------------*- C++ -*-===//
+//===-- RegisterContextPOSIX_arm.h ------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,12 +7,17 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextPOSIX_arm_H_
-#define liblldb_RegisterContextPOSIX_arm_H_
+#ifndef liblldb_RegisterContextPOSIX_arm_h_
+#define liblldb_RegisterContextPOSIX_arm_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/Log.h"
+#include "lldb/Target/RegisterContext.h"
+#include "RegisterInfoInterface.h"
#include "lldb-arm-register-enums.h"
-#include "RegisterContextPOSIX.h"
class ProcessMonitor;
@@ -24,16 +29,16 @@ public:
uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info);
- ~RegisterContextPOSIX_arm();
+ ~RegisterContextPOSIX_arm() override;
void
Invalidate();
void
- InvalidateAllRegisters();
+ InvalidateAllRegisters() override;
size_t
- GetRegisterCount();
+ GetRegisterCount() override;
virtual size_t
GetGPRSize();
@@ -45,19 +50,19 @@ public:
GetRegisterOffset(unsigned reg);
const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex(size_t reg);
+ GetRegisterInfoAtIndex(size_t reg) override;
size_t
- GetRegisterSetCount();
+ GetRegisterSetCount() override;
const lldb_private::RegisterSet *
- GetRegisterSet(size_t set);
+ GetRegisterSet(size_t set) override;
const char *
GetRegisterName(unsigned reg);
uint32_t
- ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
protected:
struct RegInfo
@@ -117,5 +122,4 @@ protected:
virtual bool WriteFPR() = 0;
};
-#endif // #ifndef liblldb_RegisterContextPOSIX_arm_H_
-
+#endif // liblldb_RegisterContextPOSIX_arm_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
index 29e7a7d21e02..225d4f25168e 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
@@ -7,12 +7,17 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextPOSIX_arm64_H_
-#define liblldb_RegisterContextPOSIX_arm64_H_
+#ifndef liblldb_RegisterContextPOSIX_arm64_h_
+#define liblldb_RegisterContextPOSIX_arm64_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/Log.h"
+#include "lldb/Target/RegisterContext.h"
+#include "RegisterInfoInterface.h"
#include "lldb-arm64-register-enums.h"
-#include "RegisterContextPOSIX.h"
class ProcessMonitor;
@@ -24,16 +29,16 @@ public:
uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info);
- ~RegisterContextPOSIX_arm64();
+ ~RegisterContextPOSIX_arm64() override;
void
Invalidate();
void
- InvalidateAllRegisters();
+ InvalidateAllRegisters() override;
size_t
- GetRegisterCount();
+ GetRegisterCount() override;
virtual size_t
GetGPRSize();
@@ -45,19 +50,19 @@ public:
GetRegisterOffset(unsigned reg);
const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex(size_t reg);
+ GetRegisterInfoAtIndex(size_t reg) override;
size_t
- GetRegisterSetCount();
+ GetRegisterSetCount() override;
const lldb_private::RegisterSet *
- GetRegisterSet(size_t set);
+ GetRegisterSet(size_t set) override;
const char *
GetRegisterName(unsigned reg);
uint32_t
- ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
protected:
struct RegInfo
@@ -116,4 +121,4 @@ protected:
virtual bool WriteFPR() = 0;
};
-#endif // #ifndef liblldb_RegisterContextPOSIX_arm64_H_
+#endif // liblldb_RegisterContextPOSIX_arm64_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h
index 612a03466983..07552d8d681d 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h
@@ -7,11 +7,16 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextPOSIX_mips64_H_
-#define liblldb_RegisterContextPOSIX_mips64_H_
+#ifndef liblldb_RegisterContextPOSIX_mips64_h_
+#define liblldb_RegisterContextPOSIX_mips64_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/Log.h"
-#include "RegisterContextPOSIX.h"
+#include "lldb/Target/RegisterContext.h"
+#include "RegisterInfoInterface.h"
#include "RegisterContext_mips.h"
#include "lldb-mips-freebsd-register-enums.h"
@@ -27,16 +32,16 @@ public:
uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info);
- ~RegisterContextPOSIX_mips64();
+ ~RegisterContextPOSIX_mips64() override;
void
Invalidate();
void
- InvalidateAllRegisters();
+ InvalidateAllRegisters() override;
size_t
- GetRegisterCount();
+ GetRegisterCount() override;
virtual size_t
GetGPRSize();
@@ -48,19 +53,19 @@ public:
GetRegisterOffset(unsigned reg);
const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex(size_t reg);
+ GetRegisterInfoAtIndex(size_t reg) override;
size_t
- GetRegisterSetCount();
+ GetRegisterSetCount() override;
const lldb_private::RegisterSet *
- GetRegisterSet(size_t set);
+ GetRegisterSet(size_t set) override;
const char *
GetRegisterName(unsigned reg);
uint32_t
- ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
protected:
uint64_t m_gpr_mips64[k_num_gpr_registers_mips64]; // general purpose registers.
@@ -87,4 +92,4 @@ protected:
virtual bool WriteFPR() = 0;
};
-#endif // #ifndef liblldb_RegisterContextPOSIX_mips64_H_
+#endif // liblldb_RegisterContextPOSIX_mips64_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h
index c7a2451d7811..4168e46ebd9a 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h
@@ -1,4 +1,4 @@
-//===-- RegisterContextPOSIX_powerpc.h ---------------------------*- C++ -*-===//
+//===-- RegisterContextPOSIX_powerpc.h --------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,11 +7,16 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextPOSIX_powerpc_H_
-#define liblldb_RegisterContextPOSIX_powerpc_H_
+#ifndef liblldb_RegisterContextPOSIX_powerpc_h_
+#define liblldb_RegisterContextPOSIX_powerpc_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/Log.h"
-#include "RegisterContextPOSIX.h"
+#include "lldb/Target/RegisterContext.h"
+#include "RegisterInfoInterface.h"
#include "RegisterContext_powerpc.h"
class ProcessMonitor;
@@ -148,16 +153,16 @@ public:
uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info);
- ~RegisterContextPOSIX_powerpc();
+ ~RegisterContextPOSIX_powerpc() override;
void
Invalidate();
void
- InvalidateAllRegisters();
+ InvalidateAllRegisters() override;
size_t
- GetRegisterCount();
+ GetRegisterCount() override;
virtual size_t
GetGPRSize();
@@ -169,19 +174,19 @@ public:
GetRegisterOffset(unsigned reg);
const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex(size_t reg);
+ GetRegisterInfoAtIndex(size_t reg) override;
size_t
- GetRegisterSetCount();
+ GetRegisterSetCount() override;
const lldb_private::RegisterSet *
- GetRegisterSet(size_t set);
+ GetRegisterSet(size_t set) override;
const char *
GetRegisterName(unsigned reg);
uint32_t
- ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
protected:
uint64_t m_gpr_powerpc[k_num_gpr_registers_powerpc]; // general purpose registers.
@@ -215,4 +220,4 @@ protected:
virtual bool WriteVMX() = 0;
};
-#endif // #ifndef liblldb_RegisterContextPOSIX_powerpc_H_
+#endif // liblldb_RegisterContextPOSIX_powerpc_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
index 0eec1d909c1a..b4708255a566 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
@@ -7,13 +7,18 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextPOSIX_x86_H_
-#define liblldb_RegisterContextPOSIX_x86_H_
+#ifndef liblldb_RegisterContextPOSIX_x86_h_
+#define liblldb_RegisterContextPOSIX_x86_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/Log.h"
-#include "lldb-x86-register-enums.h"
-#include "RegisterContextPOSIX.h"
+#include "lldb/Target/RegisterContext.h"
+#include "RegisterInfoInterface.h"
#include "RegisterContext_x86.h"
+#include "lldb-x86-register-enums.h"
class ProcessMonitor;
@@ -25,16 +30,16 @@ public:
uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info);
- ~RegisterContextPOSIX_x86();
+ ~RegisterContextPOSIX_x86() override;
void
Invalidate();
void
- InvalidateAllRegisters();
+ InvalidateAllRegisters() override;
size_t
- GetRegisterCount();
+ GetRegisterCount() override;
virtual size_t
GetGPRSize();
@@ -46,19 +51,19 @@ public:
GetRegisterOffset(unsigned reg);
const lldb_private::RegisterInfo *
- GetRegisterInfoAtIndex(size_t reg);
+ GetRegisterInfoAtIndex(size_t reg) override;
size_t
- GetRegisterSetCount();
+ GetRegisterSetCount() override;
const lldb_private::RegisterSet *
- GetRegisterSet(size_t set);
+ GetRegisterSet(size_t set) override;
const char *
GetRegisterName(unsigned reg);
uint32_t
- ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num);
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
//---------------------------------------------------------------------------
// Note: prefer kernel definitions over user-land
@@ -186,4 +191,4 @@ protected:
virtual bool WriteFPR() = 0;
};
-#endif // #ifndef liblldb_RegisterContextPOSIX_x86_H_
+#endif // liblldb_RegisterContextPOSIX_x86_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextThreadMemory.h b/source/Plugins/Process/Utility/RegisterContextThreadMemory.h
index 161ef040e651..b4680de79514 100644
--- a/source/Plugins/Process/Utility/RegisterContextThreadMemory.h
+++ b/source/Plugins/Process/Utility/RegisterContextThreadMemory.h
@@ -10,8 +10,12 @@
#ifndef lldb_RegisterContextThreadMemory_h_
#define lldb_RegisterContextThreadMemory_h_
+// C Includes
+// C++ Includes
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -24,30 +28,28 @@ public:
RegisterContextThreadMemory (Thread &thread,
lldb::addr_t register_data_addr);
- virtual ~RegisterContextThreadMemory();
- //------------------------------------------------------------------
- // Subclasses must override these functions
- //------------------------------------------------------------------
- virtual void
- InvalidateAllRegisters ();
+ ~RegisterContextThreadMemory() override;
+
+ void
+ InvalidateAllRegisters() override;
- virtual size_t
- GetRegisterCount ();
+ size_t
+ GetRegisterCount() override;
- virtual const RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg);
+ const RegisterInfo *
+ GetRegisterInfoAtIndex(size_t reg) override;
- virtual size_t
- GetRegisterSetCount ();
+ size_t
+ GetRegisterSetCount() override;
- virtual const RegisterSet *
- GetRegisterSet (size_t reg_set);
+ const RegisterSet *
+ GetRegisterSet(size_t reg_set) override;
- virtual bool
- ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value);
+ bool
+ ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value) override;
- virtual bool
- WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value);
+ bool
+ WriteRegister(const RegisterInfo *reg_info, const RegisterValue &reg_value) override;
// These two functions are used to implement "push" and "pop" of register states. They are used primarily
// for expression evaluation, where we need to push a new state (storing the old one in data_sp) and then
@@ -56,48 +58,50 @@ public:
// may mean e.g. interrupting a thread that is sitting in a kernel trap. That is a somewhat disruptive operation,
// so these API's should only be used when this behavior is needed.
- virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+ bool
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+ bool
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
bool
CopyFromRegisterContext (lldb::RegisterContextSP context);
- virtual uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num);
-
- //------------------------------------------------------------------
- // Subclasses can override these functions if desired
- //------------------------------------------------------------------
- virtual uint32_t
- NumSupportedHardwareBreakpoints ();
-
- virtual uint32_t
- SetHardwareBreakpoint (lldb::addr_t addr, size_t size);
+ uint32_t
+ ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
- virtual bool
- ClearHardwareBreakpoint (uint32_t hw_idx);
+ uint32_t
+ NumSupportedHardwareBreakpoints() override;
- virtual uint32_t
- NumSupportedHardwareWatchpoints ();
+ uint32_t
+ SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override;
- virtual uint32_t
- SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write);
-
- virtual bool
- ClearHardwareWatchpoint (uint32_t hw_index);
+ bool
+ ClearHardwareBreakpoint(uint32_t hw_idx) override;
- virtual bool
- HardwareSingleStep (bool enable);
+ uint32_t
+ NumSupportedHardwareWatchpoints() override;
- virtual Error
- ReadRegisterValueFromMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr, uint32_t src_len, RegisterValue &reg_value);
+ uint32_t
+ SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) override;
- virtual Error
- WriteRegisterValueToMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, uint32_t dst_len, const RegisterValue &reg_value);
+ bool
+ ClearHardwareWatchpoint(uint32_t hw_index) override;
+ bool
+ HardwareSingleStep(bool enable) override;
+
+ Error
+ ReadRegisterValueFromMemory(const lldb_private::RegisterInfo *reg_info,
+ lldb::addr_t src_addr,
+ uint32_t src_len,
+ RegisterValue &reg_value) override;
+
+ Error
+ WriteRegisterValueToMemory(const lldb_private::RegisterInfo *reg_info,
+ lldb::addr_t dst_addr, uint32_t dst_len,
+ const RegisterValue &reg_value) override;
+
protected:
void
UpdateRegisterContext ();
@@ -106,9 +110,11 @@ protected:
lldb::RegisterContextSP m_reg_ctx_sp;
lldb::addr_t m_register_data_addr;
uint32_t m_stop_id;
+
private:
DISALLOW_COPY_AND_ASSIGN (RegisterContextThreadMemory);
};
+
} // namespace lldb_private
-#endif // lldb_RegisterContextThreadMemory_h_
+#endif // lldb_RegisterContextThreadMemory_h_
diff --git a/source/Plugins/Process/Utility/RegisterContext_mips.h b/source/Plugins/Process/Utility/RegisterContext_mips.h
index de2b4d6dccee..3603227d5e73 100644
--- a/source/Plugins/Process/Utility/RegisterContext_mips.h
+++ b/source/Plugins/Process/Utility/RegisterContext_mips.h
@@ -15,455 +15,228 @@
enum
{
// GP Registers
- gcc_dwarf_zero_mips = 0,
- gcc_dwarf_r1_mips,
- gcc_dwarf_r2_mips,
- gcc_dwarf_r3_mips,
- gcc_dwarf_r4_mips,
- gcc_dwarf_r5_mips,
- gcc_dwarf_r6_mips,
- gcc_dwarf_r7_mips,
- gcc_dwarf_r8_mips,
- gcc_dwarf_r9_mips,
- gcc_dwarf_r10_mips,
- gcc_dwarf_r11_mips,
- gcc_dwarf_r12_mips,
- gcc_dwarf_r13_mips,
- gcc_dwarf_r14_mips,
- gcc_dwarf_r15_mips,
- gcc_dwarf_r16_mips,
- gcc_dwarf_r17_mips,
- gcc_dwarf_r18_mips,
- gcc_dwarf_r19_mips,
- gcc_dwarf_r20_mips,
- gcc_dwarf_r21_mips,
- gcc_dwarf_r22_mips,
- gcc_dwarf_r23_mips,
- gcc_dwarf_r24_mips,
- gcc_dwarf_r25_mips,
- gcc_dwarf_r26_mips,
- gcc_dwarf_r27_mips,
- gcc_dwarf_gp_mips,
- gcc_dwarf_sp_mips,
- gcc_dwarf_r30_mips,
- gcc_dwarf_ra_mips,
- gcc_dwarf_sr_mips,
- gcc_dwarf_lo_mips,
- gcc_dwarf_hi_mips,
- gcc_dwarf_bad_mips,
- gcc_dwarf_cause_mips,
- gcc_dwarf_pc_mips,
- gcc_dwarf_f0_mips,
- gcc_dwarf_f1_mips,
- gcc_dwarf_f2_mips,
- gcc_dwarf_f3_mips,
- gcc_dwarf_f4_mips,
- gcc_dwarf_f5_mips,
- gcc_dwarf_f6_mips,
- gcc_dwarf_f7_mips,
- gcc_dwarf_f8_mips,
- gcc_dwarf_f9_mips,
- gcc_dwarf_f10_mips,
- gcc_dwarf_f11_mips,
- gcc_dwarf_f12_mips,
- gcc_dwarf_f13_mips,
- gcc_dwarf_f14_mips,
- gcc_dwarf_f15_mips,
- gcc_dwarf_f16_mips,
- gcc_dwarf_f17_mips,
- gcc_dwarf_f18_mips,
- gcc_dwarf_f19_mips,
- gcc_dwarf_f20_mips,
- gcc_dwarf_f21_mips,
- gcc_dwarf_f22_mips,
- gcc_dwarf_f23_mips,
- gcc_dwarf_f24_mips,
- gcc_dwarf_f25_mips,
- gcc_dwarf_f26_mips,
- gcc_dwarf_f27_mips,
- gcc_dwarf_f28_mips,
- gcc_dwarf_f29_mips,
- gcc_dwarf_f30_mips,
- gcc_dwarf_f31_mips,
- gcc_dwarf_fcsr_mips,
- gcc_dwarf_fir_mips,
- gcc_dwarf_w0_mips,
- gcc_dwarf_w1_mips,
- gcc_dwarf_w2_mips,
- gcc_dwarf_w3_mips,
- gcc_dwarf_w4_mips,
- gcc_dwarf_w5_mips,
- gcc_dwarf_w6_mips,
- gcc_dwarf_w7_mips,
- gcc_dwarf_w8_mips,
- gcc_dwarf_w9_mips,
- gcc_dwarf_w10_mips,
- gcc_dwarf_w11_mips,
- gcc_dwarf_w12_mips,
- gcc_dwarf_w13_mips,
- gcc_dwarf_w14_mips,
- gcc_dwarf_w15_mips,
- gcc_dwarf_w16_mips,
- gcc_dwarf_w17_mips,
- gcc_dwarf_w18_mips,
- gcc_dwarf_w19_mips,
- gcc_dwarf_w20_mips,
- gcc_dwarf_w21_mips,
- gcc_dwarf_w22_mips,
- gcc_dwarf_w23_mips,
- gcc_dwarf_w24_mips,
- gcc_dwarf_w25_mips,
- gcc_dwarf_w26_mips,
- gcc_dwarf_w27_mips,
- gcc_dwarf_w28_mips,
- gcc_dwarf_w29_mips,
- gcc_dwarf_w30_mips,
- gcc_dwarf_w31_mips,
- gcc_dwarf_mcsr_mips,
- gcc_dwarf_mir_mips,
- gcc_dwarf_config5_mips,
- gcc_dwarf_ic_mips,
- gcc_dwarf_dummy_mips
+ dwarf_zero_mips = 0,
+ dwarf_r1_mips,
+ dwarf_r2_mips,
+ dwarf_r3_mips,
+ dwarf_r4_mips,
+ dwarf_r5_mips,
+ dwarf_r6_mips,
+ dwarf_r7_mips,
+ dwarf_r8_mips,
+ dwarf_r9_mips,
+ dwarf_r10_mips,
+ dwarf_r11_mips,
+ dwarf_r12_mips,
+ dwarf_r13_mips,
+ dwarf_r14_mips,
+ dwarf_r15_mips,
+ dwarf_r16_mips,
+ dwarf_r17_mips,
+ dwarf_r18_mips,
+ dwarf_r19_mips,
+ dwarf_r20_mips,
+ dwarf_r21_mips,
+ dwarf_r22_mips,
+ dwarf_r23_mips,
+ dwarf_r24_mips,
+ dwarf_r25_mips,
+ dwarf_r26_mips,
+ dwarf_r27_mips,
+ dwarf_gp_mips,
+ dwarf_sp_mips,
+ dwarf_r30_mips,
+ dwarf_ra_mips,
+ dwarf_sr_mips,
+ dwarf_lo_mips,
+ dwarf_hi_mips,
+ dwarf_bad_mips,
+ dwarf_cause_mips,
+ dwarf_pc_mips,
+ dwarf_f0_mips,
+ dwarf_f1_mips,
+ dwarf_f2_mips,
+ dwarf_f3_mips,
+ dwarf_f4_mips,
+ dwarf_f5_mips,
+ dwarf_f6_mips,
+ dwarf_f7_mips,
+ dwarf_f8_mips,
+ dwarf_f9_mips,
+ dwarf_f10_mips,
+ dwarf_f11_mips,
+ dwarf_f12_mips,
+ dwarf_f13_mips,
+ dwarf_f14_mips,
+ dwarf_f15_mips,
+ dwarf_f16_mips,
+ dwarf_f17_mips,
+ dwarf_f18_mips,
+ dwarf_f19_mips,
+ dwarf_f20_mips,
+ dwarf_f21_mips,
+ dwarf_f22_mips,
+ dwarf_f23_mips,
+ dwarf_f24_mips,
+ dwarf_f25_mips,
+ dwarf_f26_mips,
+ dwarf_f27_mips,
+ dwarf_f28_mips,
+ dwarf_f29_mips,
+ dwarf_f30_mips,
+ dwarf_f31_mips,
+ dwarf_fcsr_mips,
+ dwarf_fir_mips,
+ dwarf_w0_mips,
+ dwarf_w1_mips,
+ dwarf_w2_mips,
+ dwarf_w3_mips,
+ dwarf_w4_mips,
+ dwarf_w5_mips,
+ dwarf_w6_mips,
+ dwarf_w7_mips,
+ dwarf_w8_mips,
+ dwarf_w9_mips,
+ dwarf_w10_mips,
+ dwarf_w11_mips,
+ dwarf_w12_mips,
+ dwarf_w13_mips,
+ dwarf_w14_mips,
+ dwarf_w15_mips,
+ dwarf_w16_mips,
+ dwarf_w17_mips,
+ dwarf_w18_mips,
+ dwarf_w19_mips,
+ dwarf_w20_mips,
+ dwarf_w21_mips,
+ dwarf_w22_mips,
+ dwarf_w23_mips,
+ dwarf_w24_mips,
+ dwarf_w25_mips,
+ dwarf_w26_mips,
+ dwarf_w27_mips,
+ dwarf_w28_mips,
+ dwarf_w29_mips,
+ dwarf_w30_mips,
+ dwarf_w31_mips,
+ dwarf_mcsr_mips,
+ dwarf_mir_mips,
+ dwarf_config5_mips,
+ dwarf_ic_mips,
+ dwarf_dummy_mips
};
enum
{
- gcc_dwarf_zero_mips64 = 0,
- gcc_dwarf_r1_mips64,
- gcc_dwarf_r2_mips64,
- gcc_dwarf_r3_mips64,
- gcc_dwarf_r4_mips64,
- gcc_dwarf_r5_mips64,
- gcc_dwarf_r6_mips64,
- gcc_dwarf_r7_mips64,
- gcc_dwarf_r8_mips64,
- gcc_dwarf_r9_mips64,
- gcc_dwarf_r10_mips64,
- gcc_dwarf_r11_mips64,
- gcc_dwarf_r12_mips64,
- gcc_dwarf_r13_mips64,
- gcc_dwarf_r14_mips64,
- gcc_dwarf_r15_mips64,
- gcc_dwarf_r16_mips64,
- gcc_dwarf_r17_mips64,
- gcc_dwarf_r18_mips64,
- gcc_dwarf_r19_mips64,
- gcc_dwarf_r20_mips64,
- gcc_dwarf_r21_mips64,
- gcc_dwarf_r22_mips64,
- gcc_dwarf_r23_mips64,
- gcc_dwarf_r24_mips64,
- gcc_dwarf_r25_mips64,
- gcc_dwarf_r26_mips64,
- gcc_dwarf_r27_mips64,
- gcc_dwarf_gp_mips64,
- gcc_dwarf_sp_mips64,
- gcc_dwarf_r30_mips64,
- gcc_dwarf_ra_mips64,
- gcc_dwarf_sr_mips64,
- gcc_dwarf_lo_mips64,
- gcc_dwarf_hi_mips64,
- gcc_dwarf_bad_mips64,
- gcc_dwarf_cause_mips64,
- gcc_dwarf_pc_mips64,
- gcc_dwarf_f0_mips64,
- gcc_dwarf_f1_mips64,
- gcc_dwarf_f2_mips64,
- gcc_dwarf_f3_mips64,
- gcc_dwarf_f4_mips64,
- gcc_dwarf_f5_mips64,
- gcc_dwarf_f6_mips64,
- gcc_dwarf_f7_mips64,
- gcc_dwarf_f8_mips64,
- gcc_dwarf_f9_mips64,
- gcc_dwarf_f10_mips64,
- gcc_dwarf_f11_mips64,
- gcc_dwarf_f12_mips64,
- gcc_dwarf_f13_mips64,
- gcc_dwarf_f14_mips64,
- gcc_dwarf_f15_mips64,
- gcc_dwarf_f16_mips64,
- gcc_dwarf_f17_mips64,
- gcc_dwarf_f18_mips64,
- gcc_dwarf_f19_mips64,
- gcc_dwarf_f20_mips64,
- gcc_dwarf_f21_mips64,
- gcc_dwarf_f22_mips64,
- gcc_dwarf_f23_mips64,
- gcc_dwarf_f24_mips64,
- gcc_dwarf_f25_mips64,
- gcc_dwarf_f26_mips64,
- gcc_dwarf_f27_mips64,
- gcc_dwarf_f28_mips64,
- gcc_dwarf_f29_mips64,
- gcc_dwarf_f30_mips64,
- gcc_dwarf_f31_mips64,
- gcc_dwarf_fcsr_mips64,
- gcc_dwarf_fir_mips64,
- gcc_dwarf_ic_mips64,
- gcc_dwarf_dummy_mips64,
- gcc_dwarf_w0_mips64,
- gcc_dwarf_w1_mips64,
- gcc_dwarf_w2_mips64,
- gcc_dwarf_w3_mips64,
- gcc_dwarf_w4_mips64,
- gcc_dwarf_w5_mips64,
- gcc_dwarf_w6_mips64,
- gcc_dwarf_w7_mips64,
- gcc_dwarf_w8_mips64,
- gcc_dwarf_w9_mips64,
- gcc_dwarf_w10_mips64,
- gcc_dwarf_w11_mips64,
- gcc_dwarf_w12_mips64,
- gcc_dwarf_w13_mips64,
- gcc_dwarf_w14_mips64,
- gcc_dwarf_w15_mips64,
- gcc_dwarf_w16_mips64,
- gcc_dwarf_w17_mips64,
- gcc_dwarf_w18_mips64,
- gcc_dwarf_w19_mips64,
- gcc_dwarf_w20_mips64,
- gcc_dwarf_w21_mips64,
- gcc_dwarf_w22_mips64,
- gcc_dwarf_w23_mips64,
- gcc_dwarf_w24_mips64,
- gcc_dwarf_w25_mips64,
- gcc_dwarf_w26_mips64,
- gcc_dwarf_w27_mips64,
- gcc_dwarf_w28_mips64,
- gcc_dwarf_w29_mips64,
- gcc_dwarf_w30_mips64,
- gcc_dwarf_w31_mips64,
- gcc_dwarf_mcsr_mips64,
- gcc_dwarf_mir_mips64,
- gcc_dwarf_config5_mips64,
-};
-
-// GDB Register numbers (eRegisterKindGDB)
-enum
-{
- gdb_zero_mips = 0,
- gdb_r1_mips,
- gdb_r2_mips,
- gdb_r3_mips,
- gdb_r4_mips,
- gdb_r5_mips,
- gdb_r6_mips,
- gdb_r7_mips,
- gdb_r8_mips,
- gdb_r9_mips,
- gdb_r10_mips,
- gdb_r11_mips,
- gdb_r12_mips,
- gdb_r13_mips,
- gdb_r14_mips,
- gdb_r15_mips,
- gdb_r16_mips,
- gdb_r17_mips,
- gdb_r18_mips,
- gdb_r19_mips,
- gdb_r20_mips,
- gdb_r21_mips,
- gdb_r22_mips,
- gdb_r23_mips,
- gdb_r24_mips,
- gdb_r25_mips,
- gdb_r26_mips,
- gdb_r27_mips,
- gdb_gp_mips,
- gdb_sp_mips,
- gdb_r30_mips,
- gdb_ra_mips,
- gdb_sr_mips,
- gdb_lo_mips,
- gdb_hi_mips,
- gdb_bad_mips,
- gdb_cause_mips,
- gdb_pc_mips,
- gdb_f0_mips,
- gdb_f1_mips,
- gdb_f2_mips,
- gdb_f3_mips,
- gdb_f4_mips,
- gdb_f5_mips,
- gdb_f6_mips,
- gdb_f7_mips,
- gdb_f8_mips,
- gdb_f9_mips,
- gdb_f10_mips,
- gdb_f11_mips,
- gdb_f12_mips,
- gdb_f13_mips,
- gdb_f14_mips,
- gdb_f15_mips,
- gdb_f16_mips,
- gdb_f17_mips,
- gdb_f18_mips,
- gdb_f19_mips,
- gdb_f20_mips,
- gdb_f21_mips,
- gdb_f22_mips,
- gdb_f23_mips,
- gdb_f24_mips,
- gdb_f25_mips,
- gdb_f26_mips,
- gdb_f27_mips,
- gdb_f28_mips,
- gdb_f29_mips,
- gdb_f30_mips,
- gdb_f31_mips,
- gdb_fcsr_mips,
- gdb_fir_mips,
- gdb_w0_mips,
- gdb_w1_mips,
- gdb_w2_mips,
- gdb_w3_mips,
- gdb_w4_mips,
- gdb_w5_mips,
- gdb_w6_mips,
- gdb_w7_mips,
- gdb_w8_mips,
- gdb_w9_mips,
- gdb_w10_mips,
- gdb_w11_mips,
- gdb_w12_mips,
- gdb_w13_mips,
- gdb_w14_mips,
- gdb_w15_mips,
- gdb_w16_mips,
- gdb_w17_mips,
- gdb_w18_mips,
- gdb_w19_mips,
- gdb_w20_mips,
- gdb_w21_mips,
- gdb_w22_mips,
- gdb_w23_mips,
- gdb_w24_mips,
- gdb_w25_mips,
- gdb_w26_mips,
- gdb_w27_mips,
- gdb_w28_mips,
- gdb_w29_mips,
- gdb_w30_mips,
- gdb_w31_mips,
- gdb_mcsr_mips,
- gdb_mir_mips,
- gdb_config5_mips,
- gdb_ic_mips,
- gdb_dummy_mips
-};
-
-enum
-{
- gdb_zero_mips64 = 0,
- gdb_r1_mips64,
- gdb_r2_mips64,
- gdb_r3_mips64,
- gdb_r4_mips64,
- gdb_r5_mips64,
- gdb_r6_mips64,
- gdb_r7_mips64,
- gdb_r8_mips64,
- gdb_r9_mips64,
- gdb_r10_mips64,
- gdb_r11_mips64,
- gdb_r12_mips64,
- gdb_r13_mips64,
- gdb_r14_mips64,
- gdb_r15_mips64,
- gdb_r16_mips64,
- gdb_r17_mips64,
- gdb_r18_mips64,
- gdb_r19_mips64,
- gdb_r20_mips64,
- gdb_r21_mips64,
- gdb_r22_mips64,
- gdb_r23_mips64,
- gdb_r24_mips64,
- gdb_r25_mips64,
- gdb_r26_mips64,
- gdb_r27_mips64,
- gdb_gp_mips64,
- gdb_sp_mips64,
- gdb_r30_mips64,
- gdb_ra_mips64,
- gdb_sr_mips64,
- gdb_lo_mips64,
- gdb_hi_mips64,
- gdb_bad_mips64,
- gdb_cause_mips64,
- gdb_pc_mips64,
- gdb_f0_mips64,
- gdb_f1_mips64,
- gdb_f2_mips64,
- gdb_f3_mips64,
- gdb_f4_mips64,
- gdb_f5_mips64,
- gdb_f6_mips64,
- gdb_f7_mips64,
- gdb_f8_mips64,
- gdb_f9_mips64,
- gdb_f10_mips64,
- gdb_f11_mips64,
- gdb_f12_mips64,
- gdb_f13_mips64,
- gdb_f14_mips64,
- gdb_f15_mips64,
- gdb_f16_mips64,
- gdb_f17_mips64,
- gdb_f18_mips64,
- gdb_f19_mips64,
- gdb_f20_mips64,
- gdb_f21_mips64,
- gdb_f22_mips64,
- gdb_f23_mips64,
- gdb_f24_mips64,
- gdb_f25_mips64,
- gdb_f26_mips64,
- gdb_f27_mips64,
- gdb_f28_mips64,
- gdb_f29_mips64,
- gdb_f30_mips64,
- gdb_f31_mips64,
- gdb_fcsr_mips64,
- gdb_fir_mips64,
- gdb_ic_mips64,
- gdb_dummy_mips64,
- gdb_w0_mips64,
- gdb_w1_mips64,
- gdb_w2_mips64,
- gdb_w3_mips64,
- gdb_w4_mips64,
- gdb_w5_mips64,
- gdb_w6_mips64,
- gdb_w7_mips64,
- gdb_w8_mips64,
- gdb_w9_mips64,
- gdb_w10_mips64,
- gdb_w11_mips64,
- gdb_w12_mips64,
- gdb_w13_mips64,
- gdb_w14_mips64,
- gdb_w15_mips64,
- gdb_w16_mips64,
- gdb_w17_mips64,
- gdb_w18_mips64,
- gdb_w19_mips64,
- gdb_w20_mips64,
- gdb_w21_mips64,
- gdb_w22_mips64,
- gdb_w23_mips64,
- gdb_w24_mips64,
- gdb_w25_mips64,
- gdb_w26_mips64,
- gdb_w27_mips64,
- gdb_w28_mips64,
- gdb_w29_mips64,
- gdb_w30_mips64,
- gdb_w31_mips64,
- gdb_mcsr_mips64,
- gdb_mir_mips64,
- gdb_config5_mips64,
+ dwarf_zero_mips64 = 0,
+ dwarf_r1_mips64,
+ dwarf_r2_mips64,
+ dwarf_r3_mips64,
+ dwarf_r4_mips64,
+ dwarf_r5_mips64,
+ dwarf_r6_mips64,
+ dwarf_r7_mips64,
+ dwarf_r8_mips64,
+ dwarf_r9_mips64,
+ dwarf_r10_mips64,
+ dwarf_r11_mips64,
+ dwarf_r12_mips64,
+ dwarf_r13_mips64,
+ dwarf_r14_mips64,
+ dwarf_r15_mips64,
+ dwarf_r16_mips64,
+ dwarf_r17_mips64,
+ dwarf_r18_mips64,
+ dwarf_r19_mips64,
+ dwarf_r20_mips64,
+ dwarf_r21_mips64,
+ dwarf_r22_mips64,
+ dwarf_r23_mips64,
+ dwarf_r24_mips64,
+ dwarf_r25_mips64,
+ dwarf_r26_mips64,
+ dwarf_r27_mips64,
+ dwarf_gp_mips64,
+ dwarf_sp_mips64,
+ dwarf_r30_mips64,
+ dwarf_ra_mips64,
+ dwarf_sr_mips64,
+ dwarf_lo_mips64,
+ dwarf_hi_mips64,
+ dwarf_bad_mips64,
+ dwarf_cause_mips64,
+ dwarf_pc_mips64,
+ dwarf_f0_mips64,
+ dwarf_f1_mips64,
+ dwarf_f2_mips64,
+ dwarf_f3_mips64,
+ dwarf_f4_mips64,
+ dwarf_f5_mips64,
+ dwarf_f6_mips64,
+ dwarf_f7_mips64,
+ dwarf_f8_mips64,
+ dwarf_f9_mips64,
+ dwarf_f10_mips64,
+ dwarf_f11_mips64,
+ dwarf_f12_mips64,
+ dwarf_f13_mips64,
+ dwarf_f14_mips64,
+ dwarf_f15_mips64,
+ dwarf_f16_mips64,
+ dwarf_f17_mips64,
+ dwarf_f18_mips64,
+ dwarf_f19_mips64,
+ dwarf_f20_mips64,
+ dwarf_f21_mips64,
+ dwarf_f22_mips64,
+ dwarf_f23_mips64,
+ dwarf_f24_mips64,
+ dwarf_f25_mips64,
+ dwarf_f26_mips64,
+ dwarf_f27_mips64,
+ dwarf_f28_mips64,
+ dwarf_f29_mips64,
+ dwarf_f30_mips64,
+ dwarf_f31_mips64,
+ dwarf_fcsr_mips64,
+ dwarf_fir_mips64,
+ dwarf_ic_mips64,
+ dwarf_dummy_mips64,
+ dwarf_w0_mips64,
+ dwarf_w1_mips64,
+ dwarf_w2_mips64,
+ dwarf_w3_mips64,
+ dwarf_w4_mips64,
+ dwarf_w5_mips64,
+ dwarf_w6_mips64,
+ dwarf_w7_mips64,
+ dwarf_w8_mips64,
+ dwarf_w9_mips64,
+ dwarf_w10_mips64,
+ dwarf_w11_mips64,
+ dwarf_w12_mips64,
+ dwarf_w13_mips64,
+ dwarf_w14_mips64,
+ dwarf_w15_mips64,
+ dwarf_w16_mips64,
+ dwarf_w17_mips64,
+ dwarf_w18_mips64,
+ dwarf_w19_mips64,
+ dwarf_w20_mips64,
+ dwarf_w21_mips64,
+ dwarf_w22_mips64,
+ dwarf_w23_mips64,
+ dwarf_w24_mips64,
+ dwarf_w25_mips64,
+ dwarf_w26_mips64,
+ dwarf_w27_mips64,
+ dwarf_w28_mips64,
+ dwarf_w29_mips64,
+ dwarf_w30_mips64,
+ dwarf_w31_mips64,
+ dwarf_mcsr_mips64,
+ dwarf_mir_mips64,
+ dwarf_config5_mips64,
};
struct IOVEC_mips
diff --git a/source/Plugins/Process/Utility/RegisterContext_powerpc.h b/source/Plugins/Process/Utility/RegisterContext_powerpc.h
index 7438b88971b3..2e3053cf37bc 100644
--- a/source/Plugins/Process/Utility/RegisterContext_powerpc.h
+++ b/source/Plugins/Process/Utility/RegisterContext_powerpc.h
@@ -10,223 +10,114 @@
#ifndef liblldb_RegisterContext_powerpc_H_
#define liblldb_RegisterContext_powerpc_H_
-// GCC and DWARF Register numbers (eRegisterKindGCC & eRegisterKindDWARF)
+// eh_frame and DWARF Register numbers (eRegisterKindEHFrame & eRegisterKindDWARF)
enum
{
- gcc_dwarf_r0_powerpc = 0,
- gcc_dwarf_r1_powerpc,
- gcc_dwarf_r2_powerpc,
- gcc_dwarf_r3_powerpc,
- gcc_dwarf_r4_powerpc,
- gcc_dwarf_r5_powerpc,
- gcc_dwarf_r6_powerpc,
- gcc_dwarf_r7_powerpc,
- gcc_dwarf_r8_powerpc,
- gcc_dwarf_r9_powerpc,
- gcc_dwarf_r10_powerpc,
- gcc_dwarf_r11_powerpc,
- gcc_dwarf_r12_powerpc,
- gcc_dwarf_r13_powerpc,
- gcc_dwarf_r14_powerpc,
- gcc_dwarf_r15_powerpc,
- gcc_dwarf_r16_powerpc,
- gcc_dwarf_r17_powerpc,
- gcc_dwarf_r18_powerpc,
- gcc_dwarf_r19_powerpc,
- gcc_dwarf_r20_powerpc,
- gcc_dwarf_r21_powerpc,
- gcc_dwarf_r22_powerpc,
- gcc_dwarf_r23_powerpc,
- gcc_dwarf_r24_powerpc,
- gcc_dwarf_r25_powerpc,
- gcc_dwarf_r26_powerpc,
- gcc_dwarf_r27_powerpc,
- gcc_dwarf_r28_powerpc,
- gcc_dwarf_r29_powerpc,
- gcc_dwarf_r30_powerpc,
- gcc_dwarf_r31_powerpc,
- gcc_dwarf_f0_powerpc,
- gcc_dwarf_f1_powerpc,
- gcc_dwarf_f2_powerpc,
- gcc_dwarf_f3_powerpc,
- gcc_dwarf_f4_powerpc,
- gcc_dwarf_f5_powerpc,
- gcc_dwarf_f6_powerpc,
- gcc_dwarf_f7_powerpc,
- gcc_dwarf_f8_powerpc,
- gcc_dwarf_f9_powerpc,
- gcc_dwarf_f10_powerpc,
- gcc_dwarf_f11_powerpc,
- gcc_dwarf_f12_powerpc,
- gcc_dwarf_f13_powerpc,
- gcc_dwarf_f14_powerpc,
- gcc_dwarf_f15_powerpc,
- gcc_dwarf_f16_powerpc,
- gcc_dwarf_f17_powerpc,
- gcc_dwarf_f18_powerpc,
- gcc_dwarf_f19_powerpc,
- gcc_dwarf_f20_powerpc,
- gcc_dwarf_f21_powerpc,
- gcc_dwarf_f22_powerpc,
- gcc_dwarf_f23_powerpc,
- gcc_dwarf_f24_powerpc,
- gcc_dwarf_f25_powerpc,
- gcc_dwarf_f26_powerpc,
- gcc_dwarf_f27_powerpc,
- gcc_dwarf_f28_powerpc,
- gcc_dwarf_f29_powerpc,
- gcc_dwarf_f30_powerpc,
- gcc_dwarf_f31_powerpc,
- gcc_dwarf_cr_powerpc,
- gcc_dwarf_fpscr_powerpc,
- gcc_dwarf_msr_powerpc,
- gcc_dwarf_vscr_powerpc,
- gcc_dwarf_xer_powerpc = 101,
- gcc_dwarf_lr_powerpc = 108,
- gcc_dwarf_ctr_powerpc,
- gcc_dwarf_pc_powerpc,
- gcc_dwarf_vrsave_powerpc = 356,
- gcc_dwarf_v0_powerpc = 1124,
- gcc_dwarf_v1_powerpc,
- gcc_dwarf_v2_powerpc,
- gcc_dwarf_v3_powerpc,
- gcc_dwarf_v4_powerpc,
- gcc_dwarf_v5_powerpc,
- gcc_dwarf_v6_powerpc,
- gcc_dwarf_v7_powerpc,
- gcc_dwarf_v8_powerpc,
- gcc_dwarf_v9_powerpc,
- gcc_dwarf_v10_powerpc,
- gcc_dwarf_v11_powerpc,
- gcc_dwarf_v12_powerpc,
- gcc_dwarf_v13_powerpc,
- gcc_dwarf_v14_powerpc,
- gcc_dwarf_v15_powerpc,
- gcc_dwarf_v16_powerpc,
- gcc_dwarf_v17_powerpc,
- gcc_dwarf_v18_powerpc,
- gcc_dwarf_v19_powerpc,
- gcc_dwarf_v20_powerpc,
- gcc_dwarf_v21_powerpc,
- gcc_dwarf_v22_powerpc,
- gcc_dwarf_v23_powerpc,
- gcc_dwarf_v24_powerpc,
- gcc_dwarf_v25_powerpc,
- gcc_dwarf_v26_powerpc,
- gcc_dwarf_v27_powerpc,
- gcc_dwarf_v28_powerpc,
- gcc_dwarf_v29_powerpc,
- gcc_dwarf_v30_powerpc,
- gcc_dwarf_v31_powerpc,
-};
-
-// GDB Register numbers (eRegisterKindGDB)
-enum
-{
- gdb_r0_powerpc = 0,
- gdb_r1_powerpc,
- gdb_r2_powerpc,
- gdb_r3_powerpc,
- gdb_r4_powerpc,
- gdb_r5_powerpc,
- gdb_r6_powerpc,
- gdb_r7_powerpc,
- gdb_r8_powerpc,
- gdb_r9_powerpc,
- gdb_r10_powerpc,
- gdb_r11_powerpc,
- gdb_r12_powerpc,
- gdb_r13_powerpc,
- gdb_r14_powerpc,
- gdb_r15_powerpc,
- gdb_r16_powerpc,
- gdb_r17_powerpc,
- gdb_r18_powerpc,
- gdb_r19_powerpc,
- gdb_r20_powerpc,
- gdb_r21_powerpc,
- gdb_r22_powerpc,
- gdb_r23_powerpc,
- gdb_r24_powerpc,
- gdb_r25_powerpc,
- gdb_r26_powerpc,
- gdb_r27_powerpc,
- gdb_r28_powerpc,
- gdb_r29_powerpc,
- gdb_r30_powerpc,
- gdb_r31_powerpc,
- gdb_f0_powerpc,
- gdb_f1_powerpc,
- gdb_f2_powerpc,
- gdb_f3_powerpc,
- gdb_f4_powerpc,
- gdb_f5_powerpc,
- gdb_f6_powerpc,
- gdb_f7_powerpc,
- gdb_f8_powerpc,
- gdb_f9_powerpc,
- gdb_f10_powerpc,
- gdb_f11_powerpc,
- gdb_f12_powerpc,
- gdb_f13_powerpc,
- gdb_f14_powerpc,
- gdb_f15_powerpc,
- gdb_f16_powerpc,
- gdb_f17_powerpc,
- gdb_f18_powerpc,
- gdb_f19_powerpc,
- gdb_f20_powerpc,
- gdb_f21_powerpc,
- gdb_f22_powerpc,
- gdb_f23_powerpc,
- gdb_f24_powerpc,
- gdb_f25_powerpc,
- gdb_f26_powerpc,
- gdb_f27_powerpc,
- gdb_f28_powerpc,
- gdb_f29_powerpc,
- gdb_f30_powerpc,
- gdb_f31_powerpc,
- gdb_pc_powerpc,
- gdb_cr_powerpc = 66,
- gdb_lr_powerpc,
- gdb_ctr_powerpc,
- gdb_xer_powerpc,
- gdb_fpscr_powerpc,
- gdb_v0_powerpc = 106,
- gdb_v1_powerpc,
- gdb_v2_powerpc,
- gdb_v3_powerpc,
- gdb_v4_powerpc,
- gdb_v5_powerpc,
- gdb_v6_powerpc,
- gdb_v7_powerpc,
- gdb_v8_powerpc,
- gdb_v9_powerpc,
- gdb_v10_powerpc,
- gdb_v11_powerpc,
- gdb_v12_powerpc,
- gdb_v13_powerpc,
- gdb_v14_powerpc,
- gdb_v15_powerpc,
- gdb_v16_powerpc,
- gdb_v17_powerpc,
- gdb_v18_powerpc,
- gdb_v19_powerpc,
- gdb_v20_powerpc,
- gdb_v21_powerpc,
- gdb_v22_powerpc,
- gdb_v23_powerpc,
- gdb_v24_powerpc,
- gdb_v25_powerpc,
- gdb_v26_powerpc,
- gdb_v27_powerpc,
- gdb_v28_powerpc,
- gdb_v29_powerpc,
- gdb_v30_powerpc,
- gdb_v31_powerpc,
- gdb_vscr_powerpc,
- gdb_vrsave_powerpc,
+ dwarf_r0_powerpc = 0,
+ dwarf_r1_powerpc,
+ dwarf_r2_powerpc,
+ dwarf_r3_powerpc,
+ dwarf_r4_powerpc,
+ dwarf_r5_powerpc,
+ dwarf_r6_powerpc,
+ dwarf_r7_powerpc,
+ dwarf_r8_powerpc,
+ dwarf_r9_powerpc,
+ dwarf_r10_powerpc,
+ dwarf_r11_powerpc,
+ dwarf_r12_powerpc,
+ dwarf_r13_powerpc,
+ dwarf_r14_powerpc,
+ dwarf_r15_powerpc,
+ dwarf_r16_powerpc,
+ dwarf_r17_powerpc,
+ dwarf_r18_powerpc,
+ dwarf_r19_powerpc,
+ dwarf_r20_powerpc,
+ dwarf_r21_powerpc,
+ dwarf_r22_powerpc,
+ dwarf_r23_powerpc,
+ dwarf_r24_powerpc,
+ dwarf_r25_powerpc,
+ dwarf_r26_powerpc,
+ dwarf_r27_powerpc,
+ dwarf_r28_powerpc,
+ dwarf_r29_powerpc,
+ dwarf_r30_powerpc,
+ dwarf_r31_powerpc,
+ dwarf_f0_powerpc,
+ dwarf_f1_powerpc,
+ dwarf_f2_powerpc,
+ dwarf_f3_powerpc,
+ dwarf_f4_powerpc,
+ dwarf_f5_powerpc,
+ dwarf_f6_powerpc,
+ dwarf_f7_powerpc,
+ dwarf_f8_powerpc,
+ dwarf_f9_powerpc,
+ dwarf_f10_powerpc,
+ dwarf_f11_powerpc,
+ dwarf_f12_powerpc,
+ dwarf_f13_powerpc,
+ dwarf_f14_powerpc,
+ dwarf_f15_powerpc,
+ dwarf_f16_powerpc,
+ dwarf_f17_powerpc,
+ dwarf_f18_powerpc,
+ dwarf_f19_powerpc,
+ dwarf_f20_powerpc,
+ dwarf_f21_powerpc,
+ dwarf_f22_powerpc,
+ dwarf_f23_powerpc,
+ dwarf_f24_powerpc,
+ dwarf_f25_powerpc,
+ dwarf_f26_powerpc,
+ dwarf_f27_powerpc,
+ dwarf_f28_powerpc,
+ dwarf_f29_powerpc,
+ dwarf_f30_powerpc,
+ dwarf_f31_powerpc,
+ dwarf_cr_powerpc,
+ dwarf_fpscr_powerpc,
+ dwarf_msr_powerpc,
+ dwarf_vscr_powerpc,
+ dwarf_xer_powerpc = 101,
+ dwarf_lr_powerpc = 108,
+ dwarf_ctr_powerpc,
+ dwarf_pc_powerpc,
+ dwarf_vrsave_powerpc = 356,
+ dwarf_v0_powerpc = 1124,
+ dwarf_v1_powerpc,
+ dwarf_v2_powerpc,
+ dwarf_v3_powerpc,
+ dwarf_v4_powerpc,
+ dwarf_v5_powerpc,
+ dwarf_v6_powerpc,
+ dwarf_v7_powerpc,
+ dwarf_v8_powerpc,
+ dwarf_v9_powerpc,
+ dwarf_v10_powerpc,
+ dwarf_v11_powerpc,
+ dwarf_v12_powerpc,
+ dwarf_v13_powerpc,
+ dwarf_v14_powerpc,
+ dwarf_v15_powerpc,
+ dwarf_v16_powerpc,
+ dwarf_v17_powerpc,
+ dwarf_v18_powerpc,
+ dwarf_v19_powerpc,
+ dwarf_v20_powerpc,
+ dwarf_v21_powerpc,
+ dwarf_v22_powerpc,
+ dwarf_v23_powerpc,
+ dwarf_v24_powerpc,
+ dwarf_v25_powerpc,
+ dwarf_v26_powerpc,
+ dwarf_v27_powerpc,
+ dwarf_v28_powerpc,
+ dwarf_v29_powerpc,
+ dwarf_v30_powerpc,
+ dwarf_v31_powerpc,
};
#endif // liblldb_RegisterContext_powerpc_H_
diff --git a/source/Plugins/Process/Utility/RegisterContext_x86.h b/source/Plugins/Process/Utility/RegisterContext_x86.h
index 6b3f6fb43e33..252f1253a086 100644
--- a/source/Plugins/Process/Utility/RegisterContext_x86.h
+++ b/source/Plugins/Process/Utility/RegisterContext_x86.h
@@ -11,67 +11,56 @@
#define liblldb_RegisterContext_x86_H_
//---------------------------------------------------------------------------
-// i386 gcc, dwarf, gdb enums
+// i386 ehframe, dwarf regnums
//---------------------------------------------------------------------------
-// Register numbers seen in eh_frame (eRegisterKindGCC)
+// Register numbers seen in eh_frame (eRegisterKindEHFrame) on i386 systems (non-Darwin)
//
-// From Jason Molenda: "gcc registers" is the register numbering used in the eh_frame
-// CFI. The only registers that are described in eh_frame CFI are those that are
-// preserved across function calls aka callee-saved aka non-volatile. And none
-// of the floating point registers on x86 are preserved across function calls.
-//
-// The only reason there is a "gcc register" and a "dwarf register" is because of a
-// mistake years and years ago with i386 where they got esp and ebp
-// backwards when they emitted the eh_frame instructions. Once there were
-// binaries In The Wild using the reversed numbering, we had to stick with it
-// forever.
enum
{
- // 2nd parameter in DwarfRegNum() is regnum for exception handling on x86-32.
- // See http://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register
- gcc_eax_i386 = 0,
- gcc_ecx_i386,
- gcc_edx_i386,
- gcc_ebx_i386,
+ ehframe_eax_i386 = 0,
+ ehframe_ecx_i386,
+ ehframe_edx_i386,
+ ehframe_ebx_i386,
// on Darwin esp & ebp are reversed in the eh_frame section for i386 (versus dwarf's reg numbering).
// To be specific:
// i386+darwin eh_frame: 4 is ebp, 5 is esp
// i386+everyone else eh_frame: 4 is esp, 5 is ebp
// i386 dwarf: 4 is esp, 5 is ebp
- // lldb will get the darwin-specific eh_frame reg numberings from debugserver instead of here so we
- // only encode the 4 == esp, 5 == ebp numbers in this generic header.
- gcc_esp_i386,
- gcc_ebp_i386,
- gcc_esi_i386,
- gcc_edi_i386,
- gcc_eip_i386,
- gcc_eflags_i386,
- gcc_st0_i386 = 12,
- gcc_st1_i386,
- gcc_st2_i386,
- gcc_st3_i386,
- gcc_st4_i386,
- gcc_st5_i386,
- gcc_st6_i386,
- gcc_st7_i386,
- gcc_xmm0_i386 = 21,
- gcc_xmm1_i386,
- gcc_xmm2_i386,
- gcc_xmm3_i386,
- gcc_xmm4_i386,
- gcc_xmm5_i386,
- gcc_xmm6_i386,
- gcc_xmm7_i386,
- gcc_mm0_i386 = 29,
- gcc_mm1_i386,
- gcc_mm2_i386,
- gcc_mm3_i386,
- gcc_mm4_i386,
- gcc_mm5_i386,
- gcc_mm6_i386,
- gcc_mm7_i386,
+ // lldb will get the darwin-specific eh_frame reg numberings from debugserver, or the ABI, so we
+ // only encode the generally correct 4 == esp, 5 == ebp numbers in this generic header.
+
+ ehframe_esp_i386,
+ ehframe_ebp_i386,
+ ehframe_esi_i386,
+ ehframe_edi_i386,
+ ehframe_eip_i386,
+ ehframe_eflags_i386,
+ ehframe_st0_i386 = 12,
+ ehframe_st1_i386,
+ ehframe_st2_i386,
+ ehframe_st3_i386,
+ ehframe_st4_i386,
+ ehframe_st5_i386,
+ ehframe_st6_i386,
+ ehframe_st7_i386,
+ ehframe_xmm0_i386 = 21,
+ ehframe_xmm1_i386,
+ ehframe_xmm2_i386,
+ ehframe_xmm3_i386,
+ ehframe_xmm4_i386,
+ ehframe_xmm5_i386,
+ ehframe_xmm6_i386,
+ ehframe_xmm7_i386,
+ ehframe_mm0_i386 = 29,
+ ehframe_mm1_i386,
+ ehframe_mm2_i386,
+ ehframe_mm3_i386,
+ ehframe_mm4_i386,
+ ehframe_mm5_i386,
+ ehframe_mm6_i386,
+ ehframe_mm7_i386,
};
// DWARF register numbers (eRegisterKindDWARF)
@@ -130,258 +119,109 @@ enum
// then differentiate based on size of the register.
};
-// Register numbers GDB uses (eRegisterKindGDB)
-//
-// From Jason Molenda: The "gdb numbers" are what you would see in the stabs debug format.
-enum
-{
- gdb_eax_i386,
- gdb_ecx_i386,
- gdb_edx_i386,
- gdb_ebx_i386,
- gdb_esp_i386,
- gdb_ebp_i386,
- gdb_esi_i386,
- gdb_edi_i386,
- gdb_eip_i386,
- gdb_eflags_i386,
- gdb_cs_i386,
- gdb_ss_i386,
- gdb_ds_i386,
- gdb_es_i386,
- gdb_fs_i386,
- gdb_gs_i386,
- gdb_st0_i386 = 16,
- gdb_st1_i386,
- gdb_st2_i386,
- gdb_st3_i386,
- gdb_st4_i386,
- gdb_st5_i386,
- gdb_st6_i386,
- gdb_st7_i386,
- gdb_fctrl_i386, // FPU Control Word
- gdb_fstat_i386, // FPU Status Word
- gdb_ftag_i386, // FPU Tag Word
- gdb_fiseg_i386, // FPU IP Selector
- gdb_fioff_i386, // FPU IP Offset
- gdb_foseg_i386, // FPU Operand Pointer Selector
- gdb_fooff_i386, // FPU Operand Pointer Offset
- gdb_fop_i386, // Last Instruction Opcode
- gdb_xmm0_i386 = 32,
- gdb_xmm1_i386,
- gdb_xmm2_i386,
- gdb_xmm3_i386,
- gdb_xmm4_i386,
- gdb_xmm5_i386,
- gdb_xmm6_i386,
- gdb_xmm7_i386,
- gdb_mxcsr_i386 = 40,
- gdb_ymm0h_i386,
- gdb_ymm1h_i386,
- gdb_ymm2h_i386,
- gdb_ymm3h_i386,
- gdb_ymm4h_i386,
- gdb_ymm5h_i386,
- gdb_ymm6h_i386,
- gdb_ymm7h_i386,
- gdb_mm0_i386,
- gdb_mm1_i386,
- gdb_mm2_i386,
- gdb_mm3_i386,
- gdb_mm4_i386,
- gdb_mm5_i386,
- gdb_mm6_i386,
- gdb_mm7_i386,
-};
-
//---------------------------------------------------------------------------
-// AMD x86_64, AMD64, Intel EM64T, or Intel 64 gcc, dwarf, gdb enums
+// AMD x86_64, AMD64, Intel EM64T, or Intel 64 ehframe, dwarf regnums
//---------------------------------------------------------------------------
-// GCC and DWARF Register numbers (eRegisterKindGCC & eRegisterKindDWARF)
+// EHFrame and DWARF Register numbers (eRegisterKindEHFrame & eRegisterKindDWARF)
// This is the spec I used (as opposed to x86-64-abi-0.99.pdf):
// http://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf
enum
{
// GP Registers
- gcc_dwarf_rax_x86_64 = 0,
- gcc_dwarf_rdx_x86_64,
- gcc_dwarf_rcx_x86_64,
- gcc_dwarf_rbx_x86_64,
- gcc_dwarf_rsi_x86_64,
- gcc_dwarf_rdi_x86_64,
- gcc_dwarf_rbp_x86_64,
- gcc_dwarf_rsp_x86_64,
+ dwarf_rax_x86_64 = 0,
+ dwarf_rdx_x86_64,
+ dwarf_rcx_x86_64,
+ dwarf_rbx_x86_64,
+ dwarf_rsi_x86_64,
+ dwarf_rdi_x86_64,
+ dwarf_rbp_x86_64,
+ dwarf_rsp_x86_64,
// Extended GP Registers
- gcc_dwarf_r8_x86_64 = 8,
- gcc_dwarf_r9_x86_64,
- gcc_dwarf_r10_x86_64,
- gcc_dwarf_r11_x86_64,
- gcc_dwarf_r12_x86_64,
- gcc_dwarf_r13_x86_64,
- gcc_dwarf_r14_x86_64,
- gcc_dwarf_r15_x86_64,
+ dwarf_r8_x86_64 = 8,
+ dwarf_r9_x86_64,
+ dwarf_r10_x86_64,
+ dwarf_r11_x86_64,
+ dwarf_r12_x86_64,
+ dwarf_r13_x86_64,
+ dwarf_r14_x86_64,
+ dwarf_r15_x86_64,
// Return Address (RA) mapped to RIP
- gcc_dwarf_rip_x86_64 = 16,
+ dwarf_rip_x86_64 = 16,
// SSE Vector Registers
- gcc_dwarf_xmm0_x86_64 = 17,
- gcc_dwarf_xmm1_x86_64,
- gcc_dwarf_xmm2_x86_64,
- gcc_dwarf_xmm3_x86_64,
- gcc_dwarf_xmm4_x86_64,
- gcc_dwarf_xmm5_x86_64,
- gcc_dwarf_xmm6_x86_64,
- gcc_dwarf_xmm7_x86_64,
- gcc_dwarf_xmm8_x86_64,
- gcc_dwarf_xmm9_x86_64,
- gcc_dwarf_xmm10_x86_64,
- gcc_dwarf_xmm11_x86_64,
- gcc_dwarf_xmm12_x86_64,
- gcc_dwarf_xmm13_x86_64,
- gcc_dwarf_xmm14_x86_64,
- gcc_dwarf_xmm15_x86_64,
+ dwarf_xmm0_x86_64 = 17,
+ dwarf_xmm1_x86_64,
+ dwarf_xmm2_x86_64,
+ dwarf_xmm3_x86_64,
+ dwarf_xmm4_x86_64,
+ dwarf_xmm5_x86_64,
+ dwarf_xmm6_x86_64,
+ dwarf_xmm7_x86_64,
+ dwarf_xmm8_x86_64,
+ dwarf_xmm9_x86_64,
+ dwarf_xmm10_x86_64,
+ dwarf_xmm11_x86_64,
+ dwarf_xmm12_x86_64,
+ dwarf_xmm13_x86_64,
+ dwarf_xmm14_x86_64,
+ dwarf_xmm15_x86_64,
// Floating Point Registers
- gcc_dwarf_st0_x86_64 = 33,
- gcc_dwarf_st1_x86_64,
- gcc_dwarf_st2_x86_64,
- gcc_dwarf_st3_x86_64,
- gcc_dwarf_st4_x86_64,
- gcc_dwarf_st5_x86_64,
- gcc_dwarf_st6_x86_64,
- gcc_dwarf_st7_x86_64,
+ dwarf_st0_x86_64 = 33,
+ dwarf_st1_x86_64,
+ dwarf_st2_x86_64,
+ dwarf_st3_x86_64,
+ dwarf_st4_x86_64,
+ dwarf_st5_x86_64,
+ dwarf_st6_x86_64,
+ dwarf_st7_x86_64,
// MMX Registers
- gcc_dwarf_mm0_x86_64 = 41,
- gcc_dwarf_mm1_x86_64,
- gcc_dwarf_mm2_x86_64,
- gcc_dwarf_mm3_x86_64,
- gcc_dwarf_mm4_x86_64,
- gcc_dwarf_mm5_x86_64,
- gcc_dwarf_mm6_x86_64,
- gcc_dwarf_mm7_x86_64,
+ dwarf_mm0_x86_64 = 41,
+ dwarf_mm1_x86_64,
+ dwarf_mm2_x86_64,
+ dwarf_mm3_x86_64,
+ dwarf_mm4_x86_64,
+ dwarf_mm5_x86_64,
+ dwarf_mm6_x86_64,
+ dwarf_mm7_x86_64,
// Control and Status Flags Register
- gcc_dwarf_rflags_x86_64 = 49,
+ dwarf_rflags_x86_64 = 49,
// selector registers
- gcc_dwarf_es_x86_64 = 50,
- gcc_dwarf_cs_x86_64,
- gcc_dwarf_ss_x86_64,
- gcc_dwarf_ds_x86_64,
- gcc_dwarf_fs_x86_64,
- gcc_dwarf_gs_x86_64,
+ dwarf_es_x86_64 = 50,
+ dwarf_cs_x86_64,
+ dwarf_ss_x86_64,
+ dwarf_ds_x86_64,
+ dwarf_fs_x86_64,
+ dwarf_gs_x86_64,
// Floating point control registers
- gcc_dwarf_mxcsr_x86_64 = 64, // Media Control and Status
- gcc_dwarf_fctrl_x86_64, // x87 control word
- gcc_dwarf_fstat_x86_64, // x87 status word
+ dwarf_mxcsr_x86_64 = 64, // Media Control and Status
+ dwarf_fctrl_x86_64, // x87 control word
+ dwarf_fstat_x86_64, // x87 status word
// Upper Vector Registers
- gcc_dwarf_ymm0h_x86_64 = 67,
- gcc_dwarf_ymm1h_x86_64,
- gcc_dwarf_ymm2h_x86_64,
- gcc_dwarf_ymm3h_x86_64,
- gcc_dwarf_ymm4h_x86_64,
- gcc_dwarf_ymm5h_x86_64,
- gcc_dwarf_ymm6h_x86_64,
- gcc_dwarf_ymm7h_x86_64,
- gcc_dwarf_ymm8h_x86_64,
- gcc_dwarf_ymm9h_x86_64,
- gcc_dwarf_ymm10h_x86_64,
- gcc_dwarf_ymm11h_x86_64,
- gcc_dwarf_ymm12h_x86_64,
- gcc_dwarf_ymm13h_x86_64,
- gcc_dwarf_ymm14h_x86_64,
- gcc_dwarf_ymm15h_x86_64,
+ dwarf_ymm0h_x86_64 = 67,
+ dwarf_ymm1h_x86_64,
+ dwarf_ymm2h_x86_64,
+ dwarf_ymm3h_x86_64,
+ dwarf_ymm4h_x86_64,
+ dwarf_ymm5h_x86_64,
+ dwarf_ymm6h_x86_64,
+ dwarf_ymm7h_x86_64,
+ dwarf_ymm8h_x86_64,
+ dwarf_ymm9h_x86_64,
+ dwarf_ymm10h_x86_64,
+ dwarf_ymm11h_x86_64,
+ dwarf_ymm12h_x86_64,
+ dwarf_ymm13h_x86_64,
+ dwarf_ymm14h_x86_64,
+ dwarf_ymm15h_x86_64,
// AVX2 Vector Mask Registers
- // gcc_dwarf_k0_x86_64 = 118,
- // gcc_dwarf_k1_x86_64,
- // gcc_dwarf_k2_x86_64,
- // gcc_dwarf_k3_x86_64,
- // gcc_dwarf_k4_x86_64,
- // gcc_dwarf_k5_x86_64,
- // gcc_dwarf_k6_x86_64,
- // gcc_dwarf_k7_x86_64,
-};
-
-// GDB Register numbers (eRegisterKindGDB)
-enum
-{
- // GP Registers
- gdb_rax_x86_64 = 0,
- gdb_rbx_x86_64,
- gdb_rcx_x86_64,
- gdb_rdx_x86_64,
- gdb_rsi_x86_64,
- gdb_rdi_x86_64,
- gdb_rbp_x86_64,
- gdb_rsp_x86_64,
- // Extended GP Registers
- gdb_r8_x86_64,
- gdb_r9_x86_64,
- gdb_r10_x86_64,
- gdb_r11_x86_64,
- gdb_r12_x86_64,
- gdb_r13_x86_64,
- gdb_r14_x86_64,
- gdb_r15_x86_64,
- // Return Address (RA) mapped to RIP
- gdb_rip_x86_64,
- // Control and Status Flags Register
- gdb_rflags_x86_64,
- gdb_cs_x86_64,
- gdb_ss_x86_64,
- gdb_ds_x86_64,
- gdb_es_x86_64,
- gdb_fs_x86_64,
- gdb_gs_x86_64,
- // Floating Point Registers
- gdb_st0_x86_64,
- gdb_st1_x86_64,
- gdb_st2_x86_64,
- gdb_st3_x86_64,
- gdb_st4_x86_64,
- gdb_st5_x86_64,
- gdb_st6_x86_64,
- gdb_st7_x86_64,
- gdb_fctrl_x86_64,
- gdb_fstat_x86_64,
- gdb_ftag_x86_64,
- gdb_fiseg_x86_64,
- gdb_fioff_x86_64,
- gdb_foseg_x86_64,
- gdb_fooff_x86_64,
- gdb_fop_x86_64,
- // SSE Vector Registers
- gdb_xmm0_x86_64 = 40,
- gdb_xmm1_x86_64,
- gdb_xmm2_x86_64,
- gdb_xmm3_x86_64,
- gdb_xmm4_x86_64,
- gdb_xmm5_x86_64,
- gdb_xmm6_x86_64,
- gdb_xmm7_x86_64,
- gdb_xmm8_x86_64,
- gdb_xmm9_x86_64,
- gdb_xmm10_x86_64,
- gdb_xmm11_x86_64,
- gdb_xmm12_x86_64,
- gdb_xmm13_x86_64,
- gdb_xmm14_x86_64,
- gdb_xmm15_x86_64,
- // Floating point control registers
- gdb_mxcsr_x86_64 = 56,
- gdb_ymm0h_x86_64,
- gdb_ymm1h_x86_64,
- gdb_ymm2h_x86_64,
- gdb_ymm3h_x86_64,
- gdb_ymm4h_x86_64,
- gdb_ymm5h_x86_64,
- gdb_ymm6h_x86_64,
- gdb_ymm7h_x86_64,
- gdb_ymm8h_x86_64,
- gdb_ymm9h_x86_64,
- gdb_ymm10h_x86_64,
- gdb_ymm11h_x86_64,
- gdb_ymm12h_x86_64,
- gdb_ymm13h_x86_64,
- gdb_ymm14h_x86_64,
- gdb_ymm15h_x86_64
+ // dwarf_k0_x86_64 = 118,
+ // dwarf_k1_x86_64,
+ // dwarf_k2_x86_64,
+ // dwarf_k3_x86_64,
+ // dwarf_k4_x86_64,
+ // dwarf_k5_x86_64,
+ // dwarf_k6_x86_64,
+ // dwarf_k7_x86_64,
};
//---------------------------------------------------------------------------
@@ -404,7 +244,8 @@ struct FXSAVE
{
uint16_t fctrl; // FPU Control Word (fcw)
uint16_t fstat; // FPU Status Word (fsw)
- uint16_t ftag; // FPU Tag Word (ftw)
+ uint8_t ftag; // FPU Tag Word (ftw)
+ uint8_t reserved_1; // Reserved
uint16_t fop; // Last Instruction Opcode (fop)
union
{
diff --git a/source/Plugins/Process/Utility/RegisterInfoInterface.h b/source/Plugins/Process/Utility/RegisterInfoInterface.h
index 94cb5cc791c6..801885d5f4c5 100644
--- a/source/Plugins/Process/Utility/RegisterInfoInterface.h
+++ b/source/Plugins/Process/Utility/RegisterInfoInterface.h
@@ -10,6 +10,8 @@
#ifndef lldb_RegisterInfoInterface_h
#define lldb_RegisterInfoInterface_h
+#include <vector>
+
#include "lldb/Core/ArchSpec.h"
namespace lldb_private
@@ -50,6 +52,26 @@ namespace lldb_private
GetTargetArchitecture() const
{ return m_target_arch; }
+ virtual const lldb_private::RegisterInfo *
+ GetDynamicRegisterInfo(const char *reg_name) const
+ {
+ const std::vector <lldb_private::RegisterInfo> * d_register_infos = GetDynamicRegisterInfoP();
+ if(d_register_infos != nullptr)
+ {
+ std::vector <lldb_private::RegisterInfo> ::const_iterator pos = d_register_infos->begin();
+ for(; pos < d_register_infos->end() ; pos++)
+ {
+ if(::strcmp(reg_name, pos->name) == 0)
+ return(d_register_infos->data() + (pos - d_register_infos->begin()) );
+ }
+ }
+ return nullptr;
+ }
+
+ virtual const std::vector<lldb_private::RegisterInfo> *
+ GetDynamicRegisterInfoP() const
+ { return nullptr; }
+
public:
// FIXME make private.
lldb_private::ArchSpec m_target_arch;
diff --git a/source/Plugins/Process/Utility/RegisterInfos_arm.h b/source/Plugins/Process/Utility/RegisterInfos_arm.h
index 3d144d669415..03457728b632 100644
--- a/source/Plugins/Process/Utility/RegisterInfos_arm.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_arm.h
@@ -1,21 +1,25 @@
-//===-- RegisterInfos_arm.h ----------------------------------*- C++ -*-===//
+//===-- RegisterInfos_arm.h -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
#ifdef DECLARE_REGISTER_INFOS_ARM_STRUCT
+// C Includes
#include <stddef.h>
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
-#include "Utility/ARM_GCC_Registers.h"
+#include "Utility/ARM_ehframe_Registers.h"
#include "Utility/ARM_DWARF_Registers.h"
using namespace lldb;
@@ -25,17 +29,16 @@ using namespace lldb_private;
#error GPR_OFFSET must be defined before including this header file
#endif
-
#ifndef FPU_OFFSET
#error FPU_OFFSET must be defined before including this header file
#endif
-#ifndef EXC_OFFSET
-#error EXC_OFFSET_NAME must be defined before including this header file
+#ifndef FPSCR_OFFSET
+#error FPSCR_OFFSET must be defined before including this header file
#endif
-#ifndef DBG_OFFSET
-#error DBG_OFFSET_NAME must be defined before including this header file
+#ifndef EXC_OFFSET
+#error EXC_OFFSET_NAME must be defined before including this header file
#endif
#ifndef DEFINE_DBG
@@ -96,6 +99,56 @@ enum
fpu_s31,
fpu_fpscr,
+ fpu_d0,
+ fpu_d1,
+ fpu_d2,
+ fpu_d3,
+ fpu_d4,
+ fpu_d5,
+ fpu_d6,
+ fpu_d7,
+ fpu_d8,
+ fpu_d9,
+ fpu_d10,
+ fpu_d11,
+ fpu_d12,
+ fpu_d13,
+ fpu_d14,
+ fpu_d15,
+ fpu_d16,
+ fpu_d17,
+ fpu_d18,
+ fpu_d19,
+ fpu_d20,
+ fpu_d21,
+ fpu_d22,
+ fpu_d23,
+ fpu_d24,
+ fpu_d25,
+ fpu_d26,
+ fpu_d27,
+ fpu_d28,
+ fpu_d29,
+ fpu_d30,
+ fpu_d31,
+
+ fpu_q0,
+ fpu_q1,
+ fpu_q2,
+ fpu_q3,
+ fpu_q4,
+ fpu_q5,
+ fpu_q6,
+ fpu_q7,
+ fpu_q8,
+ fpu_q9,
+ fpu_q10,
+ fpu_q11,
+ fpu_q12,
+ fpu_q13,
+ fpu_q14,
+ fpu_q15,
+
exc_exception,
exc_fsr,
exc_far,
@@ -171,65 +224,214 @@ enum
k_num_registers
};
+static uint32_t g_s0_invalidates[] = { fpu_d0, fpu_q0, LLDB_INVALID_REGNUM };
+static uint32_t g_s1_invalidates[] = { fpu_d0, fpu_q0, LLDB_INVALID_REGNUM };
+static uint32_t g_s2_invalidates[] = { fpu_d1, fpu_q0, LLDB_INVALID_REGNUM };
+static uint32_t g_s3_invalidates[] = { fpu_d1, fpu_q0, LLDB_INVALID_REGNUM };
+static uint32_t g_s4_invalidates[] = { fpu_d2, fpu_q1, LLDB_INVALID_REGNUM };
+static uint32_t g_s5_invalidates[] = { fpu_d2, fpu_q1, LLDB_INVALID_REGNUM };
+static uint32_t g_s6_invalidates[] = { fpu_d3, fpu_q1, LLDB_INVALID_REGNUM };
+static uint32_t g_s7_invalidates[] = { fpu_d3, fpu_q1, LLDB_INVALID_REGNUM };
+static uint32_t g_s8_invalidates[] = { fpu_d4, fpu_q2, LLDB_INVALID_REGNUM };
+static uint32_t g_s9_invalidates[] = { fpu_d4, fpu_q2, LLDB_INVALID_REGNUM };
+static uint32_t g_s10_invalidates[] = { fpu_d5, fpu_q2, LLDB_INVALID_REGNUM };
+static uint32_t g_s11_invalidates[] = { fpu_d5, fpu_q2, LLDB_INVALID_REGNUM };
+static uint32_t g_s12_invalidates[] = { fpu_d6, fpu_q3, LLDB_INVALID_REGNUM };
+static uint32_t g_s13_invalidates[] = { fpu_d6, fpu_q3, LLDB_INVALID_REGNUM };
+static uint32_t g_s14_invalidates[] = { fpu_d7, fpu_q3, LLDB_INVALID_REGNUM };
+static uint32_t g_s15_invalidates[] = { fpu_d7, fpu_q3, LLDB_INVALID_REGNUM };
+static uint32_t g_s16_invalidates[] = { fpu_d8, fpu_q4, LLDB_INVALID_REGNUM };
+static uint32_t g_s17_invalidates[] = { fpu_d8, fpu_q4, LLDB_INVALID_REGNUM };
+static uint32_t g_s18_invalidates[] = { fpu_d9, fpu_q4, LLDB_INVALID_REGNUM };
+static uint32_t g_s19_invalidates[] = { fpu_d9, fpu_q4, LLDB_INVALID_REGNUM };
+static uint32_t g_s20_invalidates[] = { fpu_d10, fpu_q5, LLDB_INVALID_REGNUM };
+static uint32_t g_s21_invalidates[] = { fpu_d10, fpu_q5, LLDB_INVALID_REGNUM };
+static uint32_t g_s22_invalidates[] = { fpu_d11, fpu_q5, LLDB_INVALID_REGNUM };
+static uint32_t g_s23_invalidates[] = { fpu_d11, fpu_q5, LLDB_INVALID_REGNUM };
+static uint32_t g_s24_invalidates[] = { fpu_d12, fpu_q6, LLDB_INVALID_REGNUM };
+static uint32_t g_s25_invalidates[] = { fpu_d12, fpu_q6, LLDB_INVALID_REGNUM };
+static uint32_t g_s26_invalidates[] = { fpu_d13, fpu_q6, LLDB_INVALID_REGNUM };
+static uint32_t g_s27_invalidates[] = { fpu_d13, fpu_q6, LLDB_INVALID_REGNUM };
+static uint32_t g_s28_invalidates[] = { fpu_d14, fpu_q7, LLDB_INVALID_REGNUM };
+static uint32_t g_s29_invalidates[] = { fpu_d14, fpu_q7, LLDB_INVALID_REGNUM };
+static uint32_t g_s30_invalidates[] = { fpu_d15, fpu_q7, LLDB_INVALID_REGNUM };
+static uint32_t g_s31_invalidates[] = { fpu_d15, fpu_q7, LLDB_INVALID_REGNUM };
+
+static uint32_t g_d0_contains[] = { fpu_s0, fpu_s1, LLDB_INVALID_REGNUM };
+static uint32_t g_d1_contains[] = { fpu_s2, fpu_s3, LLDB_INVALID_REGNUM };
+static uint32_t g_d2_contains[] = { fpu_s4, fpu_s5, LLDB_INVALID_REGNUM };
+static uint32_t g_d3_contains[] = { fpu_s6, fpu_s7, LLDB_INVALID_REGNUM };
+static uint32_t g_d4_contains[] = { fpu_s8, fpu_s9, LLDB_INVALID_REGNUM };
+static uint32_t g_d5_contains[] = { fpu_s10, fpu_s11, LLDB_INVALID_REGNUM };
+static uint32_t g_d6_contains[] = { fpu_s12, fpu_s13, LLDB_INVALID_REGNUM };
+static uint32_t g_d7_contains[] = { fpu_s14, fpu_s15, LLDB_INVALID_REGNUM };
+static uint32_t g_d8_contains[] = { fpu_s16, fpu_s17, LLDB_INVALID_REGNUM };
+static uint32_t g_d9_contains[] = { fpu_s18, fpu_s19, LLDB_INVALID_REGNUM };
+static uint32_t g_d10_contains[] = { fpu_s20, fpu_s21, LLDB_INVALID_REGNUM };
+static uint32_t g_d11_contains[] = { fpu_s22, fpu_s23, LLDB_INVALID_REGNUM };
+static uint32_t g_d12_contains[] = { fpu_s24, fpu_s25, LLDB_INVALID_REGNUM };
+static uint32_t g_d13_contains[] = { fpu_s26, fpu_s27, LLDB_INVALID_REGNUM };
+static uint32_t g_d14_contains[] = { fpu_s28, fpu_s29, LLDB_INVALID_REGNUM };
+static uint32_t g_d15_contains[] = { fpu_s30, fpu_s31, LLDB_INVALID_REGNUM };
+
+static uint32_t g_d0_invalidates[] = { fpu_q0, LLDB_INVALID_REGNUM };
+static uint32_t g_d1_invalidates[] = { fpu_q0, LLDB_INVALID_REGNUM };
+static uint32_t g_d2_invalidates[] = { fpu_q1, LLDB_INVALID_REGNUM };
+static uint32_t g_d3_invalidates[] = { fpu_q1, LLDB_INVALID_REGNUM };
+static uint32_t g_d4_invalidates[] = { fpu_q2, LLDB_INVALID_REGNUM };
+static uint32_t g_d5_invalidates[] = { fpu_q2, LLDB_INVALID_REGNUM };
+static uint32_t g_d6_invalidates[] = { fpu_q3, LLDB_INVALID_REGNUM };
+static uint32_t g_d7_invalidates[] = { fpu_q3, LLDB_INVALID_REGNUM };
+static uint32_t g_d8_invalidates[] = { fpu_q4, LLDB_INVALID_REGNUM };
+static uint32_t g_d9_invalidates[] = { fpu_q4, LLDB_INVALID_REGNUM };
+static uint32_t g_d10_invalidates[] = { fpu_q5, LLDB_INVALID_REGNUM };
+static uint32_t g_d11_invalidates[] = { fpu_q5, LLDB_INVALID_REGNUM };
+static uint32_t g_d12_invalidates[] = { fpu_q6, LLDB_INVALID_REGNUM };
+static uint32_t g_d13_invalidates[] = { fpu_q6, LLDB_INVALID_REGNUM };
+static uint32_t g_d14_invalidates[] = { fpu_q7, LLDB_INVALID_REGNUM };
+static uint32_t g_d15_invalidates[] = { fpu_q7, LLDB_INVALID_REGNUM };
+static uint32_t g_d16_invalidates[] = { fpu_q8, LLDB_INVALID_REGNUM };
+static uint32_t g_d17_invalidates[] = { fpu_q8, LLDB_INVALID_REGNUM };
+static uint32_t g_d18_invalidates[] = { fpu_q9, LLDB_INVALID_REGNUM };
+static uint32_t g_d19_invalidates[] = { fpu_q9, LLDB_INVALID_REGNUM };
+static uint32_t g_d20_invalidates[] = { fpu_q10, LLDB_INVALID_REGNUM };
+static uint32_t g_d21_invalidates[] = { fpu_q10, LLDB_INVALID_REGNUM };
+static uint32_t g_d22_invalidates[] = { fpu_q11, LLDB_INVALID_REGNUM };
+static uint32_t g_d23_invalidates[] = { fpu_q11, LLDB_INVALID_REGNUM };
+static uint32_t g_d24_invalidates[] = { fpu_q12, LLDB_INVALID_REGNUM };
+static uint32_t g_d25_invalidates[] = { fpu_q12, LLDB_INVALID_REGNUM };
+static uint32_t g_d26_invalidates[] = { fpu_q13, LLDB_INVALID_REGNUM };
+static uint32_t g_d27_invalidates[] = { fpu_q13, LLDB_INVALID_REGNUM };
+static uint32_t g_d28_invalidates[] = { fpu_q14, LLDB_INVALID_REGNUM };
+static uint32_t g_d29_invalidates[] = { fpu_q14, LLDB_INVALID_REGNUM };
+static uint32_t g_d30_invalidates[] = { fpu_q15, LLDB_INVALID_REGNUM };
+static uint32_t g_d31_invalidates[] = { fpu_q15, LLDB_INVALID_REGNUM };
+
+static uint32_t g_q0_contains[] = { fpu_d0, fpu_d1, fpu_s0, fpu_s1, fpu_s2, fpu_s3, LLDB_INVALID_REGNUM };
+static uint32_t g_q1_contains[] = { fpu_d2, fpu_d3, fpu_s4, fpu_s5, fpu_s6, fpu_s7, LLDB_INVALID_REGNUM };
+static uint32_t g_q2_contains[] = { fpu_d4, fpu_d5, fpu_s8, fpu_s9, fpu_s10, fpu_s11, LLDB_INVALID_REGNUM };
+static uint32_t g_q3_contains[] = { fpu_d6, fpu_d7, fpu_s12, fpu_s13, fpu_s14, fpu_s15, LLDB_INVALID_REGNUM };
+static uint32_t g_q4_contains[] = { fpu_d8, fpu_d9, fpu_s16, fpu_s17, fpu_s18, fpu_s19, LLDB_INVALID_REGNUM };
+static uint32_t g_q5_contains[] = { fpu_d10, fpu_d11, fpu_s20, fpu_s21, fpu_s22, fpu_s23, LLDB_INVALID_REGNUM };
+static uint32_t g_q6_contains[] = { fpu_d12, fpu_d13, fpu_s24, fpu_s25, fpu_s26, fpu_s27, LLDB_INVALID_REGNUM };
+static uint32_t g_q7_contains[] = { fpu_d14, fpu_d15, fpu_s28, fpu_s29, fpu_s30, fpu_s31, LLDB_INVALID_REGNUM };
+static uint32_t g_q8_contains[] = { fpu_d16, fpu_d17, LLDB_INVALID_REGNUM };
+static uint32_t g_q9_contains[] = { fpu_d18, fpu_d19, LLDB_INVALID_REGNUM };
+static uint32_t g_q10_contains[] = { fpu_d20, fpu_d21, LLDB_INVALID_REGNUM };
+static uint32_t g_q11_contains[] = { fpu_d22, fpu_d23, LLDB_INVALID_REGNUM };
+static uint32_t g_q12_contains[] = { fpu_d24, fpu_d25, LLDB_INVALID_REGNUM };
+static uint32_t g_q13_contains[] = { fpu_d26, fpu_d27, LLDB_INVALID_REGNUM };
+static uint32_t g_q14_contains[] = { fpu_d28, fpu_d29, LLDB_INVALID_REGNUM };
+static uint32_t g_q15_contains[] = { fpu_d30, fpu_d31, LLDB_INVALID_REGNUM };
+
static RegisterInfo g_register_infos_arm[] = {
-// General purpose registers
-// NAME ALT SZ OFFSET ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
-// ====== ======= == ============= ============= ============ =============== =============== ========================= ===================== ============= ========== ===============
-{ "r0", NULL, 4, GPR_OFFSET(0), eEncodingUint, eFormatHex, { gcc_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, gdb_arm_r0, gpr_r0 }, NULL, NULL},
-{ "r1", NULL, 4, GPR_OFFSET(1), eEncodingUint, eFormatHex, { gcc_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, gdb_arm_r1, gpr_r1 }, NULL, NULL},
-{ "r2", NULL, 4, GPR_OFFSET(2), eEncodingUint, eFormatHex, { gcc_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, gdb_arm_r2, gpr_r2 }, NULL, NULL},
-{ "r3", NULL, 4, GPR_OFFSET(3), eEncodingUint, eFormatHex, { gcc_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, gdb_arm_r3, gpr_r3 }, NULL, NULL},
-{ "r4", NULL, 4, GPR_OFFSET(4), eEncodingUint, eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, gdb_arm_r4, gpr_r4 }, NULL, NULL},
-{ "r5", NULL, 4, GPR_OFFSET(5), eEncodingUint, eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, gdb_arm_r5, gpr_r5 }, NULL, NULL},
-{ "r6", NULL, 4, GPR_OFFSET(6), eEncodingUint, eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, gdb_arm_r6, gpr_r6 }, NULL, NULL},
-{ "r7", NULL, 4, GPR_OFFSET(7), eEncodingUint, eFormatHex, { gcc_r7, dwarf_r7, LLDB_INVALID_REGNUM, gdb_arm_r7, gpr_r7 }, NULL, NULL},
-{ "r8", NULL, 4, GPR_OFFSET(8), eEncodingUint, eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, gdb_arm_r8, gpr_r8 }, NULL, NULL},
-{ "r9", NULL, 4, GPR_OFFSET(9), eEncodingUint, eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, gdb_arm_r9, gpr_r9 }, NULL, NULL},
-{ "r10", NULL, 4, GPR_OFFSET(10), eEncodingUint, eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, gdb_arm_r10, gpr_r10 }, NULL, NULL},
-{ "r11", NULL, 4, GPR_OFFSET(11), eEncodingUint, eFormatHex, { gcc_r11, dwarf_r11, LLDB_REGNUM_GENERIC_FP, gdb_arm_r11, gpr_r11 }, NULL, NULL},
-{ "r12", NULL, 4, GPR_OFFSET(12), eEncodingUint, eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, gdb_arm_r12, gpr_r12 }, NULL, NULL},
-{ "sp", "r13", 4, GPR_OFFSET(13), eEncodingUint, eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, gdb_arm_sp, gpr_sp }, NULL, NULL},
-{ "lr", "r14", 4, GPR_OFFSET(14), eEncodingUint, eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_arm_lr, gpr_lr }, NULL, NULL},
-{ "pc", "r15", 4, GPR_OFFSET(15), eEncodingUint, eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_arm_pc, gpr_pc }, NULL, NULL},
-{ "cpsr", "psr", 4, GPR_OFFSET(16), eEncodingUint, eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, gdb_arm_cpsr, gpr_cpsr }, NULL, NULL},
-
-{ "s0", NULL, 4, FPU_OFFSET(0), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, gdb_arm_s0, fpu_s0 }, NULL, NULL},
-{ "s1", NULL, 4, FPU_OFFSET(1), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, gdb_arm_s1, fpu_s1 }, NULL, NULL},
-{ "s2", NULL, 4, FPU_OFFSET(2), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, gdb_arm_s2, fpu_s2 }, NULL, NULL},
-{ "s3", NULL, 4, FPU_OFFSET(3), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, gdb_arm_s3, fpu_s3 }, NULL, NULL},
-{ "s4", NULL, 4, FPU_OFFSET(4), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, gdb_arm_s4, fpu_s4 }, NULL, NULL},
-{ "s5", NULL, 4, FPU_OFFSET(5), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, gdb_arm_s5, fpu_s5 }, NULL, NULL},
-{ "s6", NULL, 4, FPU_OFFSET(6), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, gdb_arm_s6, fpu_s6 }, NULL, NULL},
-{ "s7", NULL, 4, FPU_OFFSET(7), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, gdb_arm_s7, fpu_s7 }, NULL, NULL},
-{ "s8", NULL, 4, FPU_OFFSET(8), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, gdb_arm_s8, fpu_s8 }, NULL, NULL},
-{ "s9", NULL, 4, FPU_OFFSET(9), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, gdb_arm_s9, fpu_s9 }, NULL, NULL},
-{ "s10", NULL, 4, FPU_OFFSET(10), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, gdb_arm_s10, fpu_s10 }, NULL, NULL},
-{ "s11", NULL, 4, FPU_OFFSET(11), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, gdb_arm_s11, fpu_s11 }, NULL, NULL},
-{ "s12", NULL, 4, FPU_OFFSET(12), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, gdb_arm_s12, fpu_s12 }, NULL, NULL},
-{ "s13", NULL, 4, FPU_OFFSET(13), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, gdb_arm_s13, fpu_s13 }, NULL, NULL},
-{ "s14", NULL, 4, FPU_OFFSET(14), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, gdb_arm_s14, fpu_s14 }, NULL, NULL},
-{ "s15", NULL, 4, FPU_OFFSET(15), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, gdb_arm_s15, fpu_s15 }, NULL, NULL},
-{ "s16", NULL, 4, FPU_OFFSET(16), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, gdb_arm_s16, fpu_s16 }, NULL, NULL},
-{ "s17", NULL, 4, FPU_OFFSET(17), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, gdb_arm_s17, fpu_s17 }, NULL, NULL},
-{ "s18", NULL, 4, FPU_OFFSET(18), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, gdb_arm_s18, fpu_s18 }, NULL, NULL},
-{ "s19", NULL, 4, FPU_OFFSET(19), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, gdb_arm_s19, fpu_s19 }, NULL, NULL},
-{ "s20", NULL, 4, FPU_OFFSET(20), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, gdb_arm_s20, fpu_s20 }, NULL, NULL},
-{ "s21", NULL, 4, FPU_OFFSET(21), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, gdb_arm_s21, fpu_s21 }, NULL, NULL},
-{ "s22", NULL, 4, FPU_OFFSET(22), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, gdb_arm_s22, fpu_s22 }, NULL, NULL},
-{ "s23", NULL, 4, FPU_OFFSET(23), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, gdb_arm_s23, fpu_s23 }, NULL, NULL},
-{ "s24", NULL, 4, FPU_OFFSET(24), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, gdb_arm_s24, fpu_s24 }, NULL, NULL},
-{ "s25", NULL, 4, FPU_OFFSET(25), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, gdb_arm_s25, fpu_s25 }, NULL, NULL},
-{ "s26", NULL, 4, FPU_OFFSET(26), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, gdb_arm_s26, fpu_s26 }, NULL, NULL},
-{ "s27", NULL, 4, FPU_OFFSET(27), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, gdb_arm_s27, fpu_s27 }, NULL, NULL},
-{ "s28", NULL, 4, FPU_OFFSET(28), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, gdb_arm_s28, fpu_s28 }, NULL, NULL},
-{ "s29", NULL, 4, FPU_OFFSET(29), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, gdb_arm_s29, fpu_s29 }, NULL, NULL},
-{ "s30", NULL, 4, FPU_OFFSET(30), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, gdb_arm_s30, fpu_s30 }, NULL, NULL},
-{ "s31", NULL, 4, FPU_OFFSET(31), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, gdb_arm_s31, fpu_s31 }, NULL, NULL},
-{ "fpscr", NULL, 4, FPU_OFFSET(32), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, gdb_arm_fpscr, fpu_fpscr }, NULL, NULL},
-
-{ "exception",NULL, 4, EXC_OFFSET(0), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception }, NULL, NULL},
-{ "fsr", NULL, 4, EXC_OFFSET(1), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_fsr }, NULL, NULL},
-{ "far", NULL, 4, EXC_OFFSET(2), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_far }, NULL, NULL},
+// NAME ALT SZ OFFSET ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS
+// =========== ======= == ============== ================ ==================== =================== =================== ========================== =================== ============= ============== =================
+{ "r0", nullptr, 4, GPR_OFFSET(0), eEncodingUint, eFormatHex, { ehframe_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, gpr_r0 }, nullptr, nullptr },
+{ "r1", nullptr, 4, GPR_OFFSET(1), eEncodingUint, eFormatHex, { ehframe_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, gpr_r1 }, nullptr, nullptr },
+{ "r2", nullptr, 4, GPR_OFFSET(2), eEncodingUint, eFormatHex, { ehframe_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, gpr_r2 }, nullptr, nullptr },
+{ "r3", nullptr, 4, GPR_OFFSET(3), eEncodingUint, eFormatHex, { ehframe_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, gpr_r3 }, nullptr, nullptr },
+{ "r4", nullptr, 4, GPR_OFFSET(4), eEncodingUint, eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r4 }, nullptr, nullptr },
+{ "r5", nullptr, 4, GPR_OFFSET(5), eEncodingUint, eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r5 }, nullptr, nullptr },
+{ "r6", nullptr, 4, GPR_OFFSET(6), eEncodingUint, eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r6 }, nullptr, nullptr },
+{ "r7", nullptr, 4, GPR_OFFSET(7), eEncodingUint, eFormatHex, { ehframe_r7, dwarf_r7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r7 }, nullptr, nullptr },
+{ "r8", nullptr, 4, GPR_OFFSET(8), eEncodingUint, eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r8 }, nullptr, nullptr },
+{ "r9", nullptr, 4, GPR_OFFSET(9), eEncodingUint, eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r9 }, nullptr, nullptr },
+{ "r10", nullptr, 4, GPR_OFFSET(10), eEncodingUint, eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r10 }, nullptr, nullptr },
+{ "r11", nullptr, 4, GPR_OFFSET(11), eEncodingUint, eFormatHex, { ehframe_r11, dwarf_r11, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, gpr_r11 }, nullptr, nullptr },
+{ "r12", nullptr, 4, GPR_OFFSET(12), eEncodingUint, eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_r12 }, nullptr, nullptr },
+{ "sp", "r13", 4, GPR_OFFSET(13), eEncodingUint, eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, gpr_sp }, nullptr, nullptr },
+{ "lr", "r14", 4, GPR_OFFSET(14), eEncodingUint, eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, gpr_lr }, nullptr, nullptr },
+{ "pc", "r15", 4, GPR_OFFSET(15), eEncodingUint, eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, gpr_pc }, nullptr, nullptr },
+{ "cpsr", "psr", 4, GPR_OFFSET(16), eEncodingUint, eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, gpr_cpsr }, nullptr, nullptr },
+
+{ "s0", nullptr, 4, FPU_OFFSET(0), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s0 }, nullptr, g_s0_invalidates },
+{ "s1", nullptr, 4, FPU_OFFSET(1), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s1 }, nullptr, g_s1_invalidates },
+{ "s2", nullptr, 4, FPU_OFFSET(2), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s2 }, nullptr, g_s2_invalidates },
+{ "s3", nullptr, 4, FPU_OFFSET(3), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s3 }, nullptr, g_s3_invalidates },
+{ "s4", nullptr, 4, FPU_OFFSET(4), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s4 }, nullptr, g_s4_invalidates },
+{ "s5", nullptr, 4, FPU_OFFSET(5), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s5 }, nullptr, g_s5_invalidates },
+{ "s6", nullptr, 4, FPU_OFFSET(6), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s6 }, nullptr, g_s6_invalidates },
+{ "s7", nullptr, 4, FPU_OFFSET(7), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s7 }, nullptr, g_s7_invalidates },
+{ "s8", nullptr, 4, FPU_OFFSET(8), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s8 }, nullptr, g_s8_invalidates },
+{ "s9", nullptr, 4, FPU_OFFSET(9), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s9 }, nullptr, g_s9_invalidates },
+{ "s10", nullptr, 4, FPU_OFFSET(10), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s10 }, nullptr, g_s10_invalidates },
+{ "s11", nullptr, 4, FPU_OFFSET(11), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s11 }, nullptr, g_s11_invalidates },
+{ "s12", nullptr, 4, FPU_OFFSET(12), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s12 }, nullptr, g_s12_invalidates },
+{ "s13", nullptr, 4, FPU_OFFSET(13), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s13 }, nullptr, g_s13_invalidates },
+{ "s14", nullptr, 4, FPU_OFFSET(14), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s14 }, nullptr, g_s14_invalidates },
+{ "s15", nullptr, 4, FPU_OFFSET(15), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s15 }, nullptr, g_s15_invalidates },
+{ "s16", nullptr, 4, FPU_OFFSET(16), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s16 }, nullptr, g_s16_invalidates },
+{ "s17", nullptr, 4, FPU_OFFSET(17), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s17 }, nullptr, g_s17_invalidates },
+{ "s18", nullptr, 4, FPU_OFFSET(18), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s18 }, nullptr, g_s18_invalidates },
+{ "s19", nullptr, 4, FPU_OFFSET(19), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s19 }, nullptr, g_s19_invalidates },
+{ "s20", nullptr, 4, FPU_OFFSET(20), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s20 }, nullptr, g_s20_invalidates },
+{ "s21", nullptr, 4, FPU_OFFSET(21), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s21 }, nullptr, g_s21_invalidates },
+{ "s22", nullptr, 4, FPU_OFFSET(22), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s22 }, nullptr, g_s22_invalidates },
+{ "s23", nullptr, 4, FPU_OFFSET(23), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s23 }, nullptr, g_s23_invalidates },
+{ "s24", nullptr, 4, FPU_OFFSET(24), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s24 }, nullptr, g_s24_invalidates },
+{ "s25", nullptr, 4, FPU_OFFSET(25), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s25 }, nullptr, g_s25_invalidates },
+{ "s26", nullptr, 4, FPU_OFFSET(26), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s26 }, nullptr, g_s26_invalidates },
+{ "s27", nullptr, 4, FPU_OFFSET(27), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s27 }, nullptr, g_s27_invalidates },
+{ "s28", nullptr, 4, FPU_OFFSET(28), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s28 }, nullptr, g_s28_invalidates },
+{ "s29", nullptr, 4, FPU_OFFSET(29), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s29 }, nullptr, g_s29_invalidates },
+{ "s30", nullptr, 4, FPU_OFFSET(30), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s30 }, nullptr, g_s30_invalidates },
+{ "s31", nullptr, 4, FPU_OFFSET(31), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_s31 }, nullptr, g_s31_invalidates },
+{ "fpscr", nullptr, 4, FPSCR_OFFSET, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpscr }, nullptr, nullptr },
+
+{ "d0", nullptr, 8, FPU_OFFSET(0), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d0 }, g_d0_contains, g_d0_invalidates },
+{ "d1", nullptr, 8, FPU_OFFSET(2), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d1 }, g_d1_contains, g_d1_invalidates },
+{ "d2", nullptr, 8, FPU_OFFSET(4), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d2 }, g_d2_contains, g_d2_invalidates },
+{ "d3", nullptr, 8, FPU_OFFSET(6), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d3 }, g_d3_contains, g_d3_invalidates },
+{ "d4", nullptr, 8, FPU_OFFSET(8), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d4 }, g_d4_contains, g_d4_invalidates },
+{ "d5", nullptr, 8, FPU_OFFSET(10), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d5 }, g_d5_contains, g_d5_invalidates },
+{ "d6", nullptr, 8, FPU_OFFSET(12), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d6 }, g_d6_contains, g_d6_invalidates },
+{ "d7", nullptr, 8, FPU_OFFSET(14), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d7 }, g_d7_contains, g_d7_invalidates },
+{ "d8", nullptr, 8, FPU_OFFSET(16), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d8 }, g_d8_contains, g_d8_invalidates },
+{ "d9", nullptr, 8, FPU_OFFSET(18), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d9 }, g_d9_contains, g_d9_invalidates },
+{ "d10", nullptr, 8, FPU_OFFSET(20), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d10 }, g_d10_contains, g_d10_invalidates },
+{ "d11", nullptr, 8, FPU_OFFSET(22), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d11 }, g_d11_contains, g_d11_invalidates },
+{ "d12", nullptr, 8, FPU_OFFSET(24), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d12 }, g_d12_contains, g_d12_invalidates },
+{ "d13", nullptr, 8, FPU_OFFSET(26), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d13 }, g_d13_contains, g_d13_invalidates },
+{ "d14", nullptr, 8, FPU_OFFSET(28), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d14 }, g_d14_contains, g_d14_invalidates },
+{ "d15", nullptr, 8, FPU_OFFSET(30), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d15 }, g_d15_contains, g_d15_invalidates },
+{ "d16", nullptr, 8, FPU_OFFSET(32), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d16 }, nullptr, g_d16_invalidates },
+{ "d17", nullptr, 8, FPU_OFFSET(34), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d17 }, nullptr, g_d17_invalidates },
+{ "d18", nullptr, 8, FPU_OFFSET(36), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d18 }, nullptr, g_d18_invalidates },
+{ "d19", nullptr, 8, FPU_OFFSET(38), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d19 }, nullptr, g_d19_invalidates },
+{ "d20", nullptr, 8, FPU_OFFSET(40), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d20 }, nullptr, g_d20_invalidates },
+{ "d21", nullptr, 8, FPU_OFFSET(42), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d21 }, nullptr, g_d21_invalidates },
+{ "d22", nullptr, 8, FPU_OFFSET(44), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d22 }, nullptr, g_d22_invalidates },
+{ "d23", nullptr, 8, FPU_OFFSET(46), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d23 }, nullptr, g_d23_invalidates },
+{ "d24", nullptr, 8, FPU_OFFSET(48), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d24 }, nullptr, g_d24_invalidates },
+{ "d25", nullptr, 8, FPU_OFFSET(50), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d25 }, nullptr, g_d25_invalidates },
+{ "d26", nullptr, 8, FPU_OFFSET(52), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d26 }, nullptr, g_d26_invalidates },
+{ "d27", nullptr, 8, FPU_OFFSET(54), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d27 }, nullptr, g_d27_invalidates },
+{ "d28", nullptr, 8, FPU_OFFSET(56), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d28 }, nullptr, g_d28_invalidates },
+{ "d29", nullptr, 8, FPU_OFFSET(58), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d29 }, nullptr, g_d29_invalidates },
+{ "d30", nullptr, 8, FPU_OFFSET(60), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d30 }, nullptr, g_d30_invalidates },
+{ "d31", nullptr, 8, FPU_OFFSET(62), eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_d31 }, nullptr, g_d31_invalidates },
+
+{ "q0", nullptr, 16, FPU_OFFSET(0), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q0 }, g_q0_contains, nullptr, },
+{ "q1", nullptr, 16, FPU_OFFSET(4), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q1 }, g_q1_contains, nullptr, },
+{ "q2", nullptr, 16, FPU_OFFSET(8), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q2 }, g_q2_contains, nullptr, },
+{ "q3", nullptr, 16, FPU_OFFSET(12), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q3 }, g_q3_contains, nullptr, },
+{ "q4", nullptr, 16, FPU_OFFSET(16), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q4 }, g_q4_contains, nullptr, },
+{ "q5", nullptr, 16, FPU_OFFSET(20), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q5 }, g_q5_contains, nullptr, },
+{ "q6", nullptr, 16, FPU_OFFSET(24), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q6 }, g_q6_contains, nullptr, },
+{ "q7", nullptr, 16, FPU_OFFSET(28), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q7 }, g_q7_contains, nullptr, },
+{ "q8", nullptr, 16, FPU_OFFSET(32), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q8 }, g_q8_contains, nullptr, },
+{ "q9", nullptr, 16, FPU_OFFSET(36), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q9 }, g_q9_contains, nullptr, },
+{ "q10", nullptr, 16, FPU_OFFSET(40), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q10 }, g_q10_contains, nullptr, },
+{ "q11", nullptr, 16, FPU_OFFSET(44), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q11 }, g_q11_contains, nullptr, },
+{ "q12", nullptr, 16, FPU_OFFSET(48), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q12 }, g_q12_contains, nullptr, },
+{ "q13", nullptr, 16, FPU_OFFSET(52), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q13 }, g_q13_contains, nullptr, },
+{ "q14", nullptr, 16, FPU_OFFSET(56), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q14 }, g_q14_contains, nullptr, },
+{ "q15", nullptr, 16, FPU_OFFSET(60), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_q15 }, g_q15_contains, nullptr, },
+
+{ "exception", nullptr, 4, EXC_OFFSET(0), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception }, nullptr, nullptr },
+{ "fsr", nullptr, 4, EXC_OFFSET(1), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_fsr }, nullptr, nullptr },
+{ "far", nullptr, 4, EXC_OFFSET(2), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_far }, nullptr, nullptr },
{ DEFINE_DBG (bvr, 0) },
{ DEFINE_DBG (bvr, 1) },
diff --git a/source/Plugins/Process/Utility/RegisterInfos_arm64.h b/source/Plugins/Process/Utility/RegisterInfos_arm64.h
index 0255a3bc7d60..715321149a73 100644
--- a/source/Plugins/Process/Utility/RegisterInfos_arm64.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_arm64.h
@@ -1,22 +1,26 @@
-//===-- RegisterInfos_arm64.h ----------------------------------*- C++ -*-===//
+//===-- RegisterInfos_arm64.h -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
#ifdef DECLARE_REGISTER_INFOS_ARM64_STRUCT
+// C Includes
#include <stddef.h>
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
-#include "Utility/ARM64_GCC_Registers.h"
#include "Utility/ARM64_DWARF_Registers.h"
+#include "Utility/ARM64_ehframe_Registers.h"
#ifndef GPR_OFFSET
#error GPR_OFFSET must be defined before including this header file
@@ -196,84 +200,84 @@ enum
static lldb_private::RegisterInfo g_register_infos_arm64[] = {
// General purpose registers
-// NAME ALT SZ OFFSET ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS
-// ====== ======= == ============= ============= ============ =============== =============== ========================= ===================== ============= ========== ===============
-{ "x0", NULL, 8, GPR_OFFSET(0), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x0, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, arm64_gcc::x0, gpr_x0 }, NULL, NULL},
-{ "x1", NULL, 8, GPR_OFFSET(1), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x1, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, arm64_gcc::x1, gpr_x1 }, NULL, NULL},
-{ "x2", NULL, 8, GPR_OFFSET(2), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x2, arm64_dwarf::x2, LLDB_REGNUM_GENERIC_ARG3, arm64_gcc::x2, gpr_x2 }, NULL, NULL},
-{ "x3", NULL, 8, GPR_OFFSET(3), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x3, arm64_dwarf::x3, LLDB_REGNUM_GENERIC_ARG4, arm64_gcc::x3, gpr_x3 }, NULL, NULL},
-{ "x4", NULL, 8, GPR_OFFSET(4), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x4, arm64_dwarf::x4, LLDB_REGNUM_GENERIC_ARG5, arm64_gcc::x4, gpr_x4 }, NULL, NULL},
-{ "x5", NULL, 8, GPR_OFFSET(5), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x5, arm64_dwarf::x5, LLDB_REGNUM_GENERIC_ARG6, arm64_gcc::x5, gpr_x5 }, NULL, NULL},
-{ "x6", NULL, 8, GPR_OFFSET(6), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x6, arm64_dwarf::x6, LLDB_REGNUM_GENERIC_ARG7, arm64_gcc::x6, gpr_x6 }, NULL, NULL},
-{ "x7", NULL, 8, GPR_OFFSET(7), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x7, arm64_dwarf::x7, LLDB_REGNUM_GENERIC_ARG8, arm64_gcc::x7, gpr_x7 }, NULL, NULL},
-{ "x8", NULL, 8, GPR_OFFSET(8), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x8, arm64_dwarf::x8, LLDB_INVALID_REGNUM, arm64_gcc::x8, gpr_x8 }, NULL, NULL},
-{ "x9", NULL, 8, GPR_OFFSET(9), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x9, arm64_dwarf::x9, LLDB_INVALID_REGNUM, arm64_gcc::x9, gpr_x9 }, NULL, NULL},
-{ "x10", NULL, 8, GPR_OFFSET(10), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x10, arm64_dwarf::x10, LLDB_INVALID_REGNUM, arm64_gcc::x10, gpr_x10 }, NULL, NULL},
-{ "x11", NULL, 8, GPR_OFFSET(11), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x11, arm64_dwarf::x11, LLDB_INVALID_REGNUM, arm64_gcc::x11, gpr_x11 }, NULL, NULL},
-{ "x12", NULL, 8, GPR_OFFSET(12), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x12, arm64_dwarf::x12, LLDB_INVALID_REGNUM, arm64_gcc::x12, gpr_x12 }, NULL, NULL},
-{ "x13", NULL, 8, GPR_OFFSET(13), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x13, arm64_dwarf::x13, LLDB_INVALID_REGNUM, arm64_gcc::x13, gpr_x13 }, NULL, NULL},
-{ "x14", NULL, 8, GPR_OFFSET(14), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x14, arm64_dwarf::x14, LLDB_INVALID_REGNUM, arm64_gcc::x14, gpr_x14 }, NULL, NULL},
-{ "x15", NULL, 8, GPR_OFFSET(15), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x15, arm64_dwarf::x15, LLDB_INVALID_REGNUM, arm64_gcc::x15, gpr_x15 }, NULL, NULL},
-{ "x16", NULL, 8, GPR_OFFSET(16), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x16, arm64_dwarf::x16, LLDB_INVALID_REGNUM, arm64_gcc::x16, gpr_x16 }, NULL, NULL},
-{ "x17", NULL, 8, GPR_OFFSET(17), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x17, arm64_dwarf::x17, LLDB_INVALID_REGNUM, arm64_gcc::x17, gpr_x17 }, NULL, NULL},
-{ "x18", NULL, 8, GPR_OFFSET(18), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x18, arm64_dwarf::x18, LLDB_INVALID_REGNUM, arm64_gcc::x18, gpr_x18 }, NULL, NULL},
-{ "x19", NULL, 8, GPR_OFFSET(19), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x19, arm64_dwarf::x19, LLDB_INVALID_REGNUM, arm64_gcc::x19, gpr_x19 }, NULL, NULL},
-{ "x20", NULL, 8, GPR_OFFSET(20), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x20, arm64_dwarf::x20, LLDB_INVALID_REGNUM, arm64_gcc::x20, gpr_x20 }, NULL, NULL},
-{ "x21", NULL, 8, GPR_OFFSET(21), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x21, arm64_dwarf::x21, LLDB_INVALID_REGNUM, arm64_gcc::x21, gpr_x21 }, NULL, NULL},
-{ "x22", NULL, 8, GPR_OFFSET(22), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x22, arm64_dwarf::x22, LLDB_INVALID_REGNUM, arm64_gcc::x22, gpr_x22 }, NULL, NULL},
-{ "x23", NULL, 8, GPR_OFFSET(23), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x23, arm64_dwarf::x23, LLDB_INVALID_REGNUM, arm64_gcc::x23, gpr_x23 }, NULL, NULL},
-{ "x24", NULL, 8, GPR_OFFSET(24), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x24, arm64_dwarf::x24, LLDB_INVALID_REGNUM, arm64_gcc::x24, gpr_x24 }, NULL, NULL},
-{ "x25", NULL, 8, GPR_OFFSET(25), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x25, arm64_dwarf::x25, LLDB_INVALID_REGNUM, arm64_gcc::x25, gpr_x25 }, NULL, NULL},
-{ "x26", NULL, 8, GPR_OFFSET(26), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x26, arm64_dwarf::x26, LLDB_INVALID_REGNUM, arm64_gcc::x26, gpr_x26 }, NULL, NULL},
-{ "x27", NULL, 8, GPR_OFFSET(27), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x27, arm64_dwarf::x27, LLDB_INVALID_REGNUM, arm64_gcc::x27, gpr_x27 }, NULL, NULL},
-{ "x28", NULL, 8, GPR_OFFSET(28), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::x28, arm64_dwarf::x28, LLDB_INVALID_REGNUM, arm64_gcc::x28, gpr_x28 }, NULL, NULL},
+// NAME ALT SZ OFFSET ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS
+// ====== ======= == ============= ============= ============ =============== =============== ========================= ===================== ============= ========== ===============
+{ "x0", nullptr, 8, GPR_OFFSET(0), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x0, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, gpr_x0 }, nullptr, nullptr},
+{ "x1", nullptr, 8, GPR_OFFSET(1), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x1, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, gpr_x1 }, nullptr, nullptr},
+{ "x2", nullptr, 8, GPR_OFFSET(2), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x2, arm64_dwarf::x2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, gpr_x2 }, nullptr, nullptr},
+{ "x3", nullptr, 8, GPR_OFFSET(3), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x3, arm64_dwarf::x3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, gpr_x3 }, nullptr, nullptr},
+{ "x4", nullptr, 8, GPR_OFFSET(4), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x4, arm64_dwarf::x4, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM, gpr_x4 }, nullptr, nullptr},
+{ "x5", nullptr, 8, GPR_OFFSET(5), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x5, arm64_dwarf::x5, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM, gpr_x5 }, nullptr, nullptr},
+{ "x6", nullptr, 8, GPR_OFFSET(6), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x6, arm64_dwarf::x6, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM, gpr_x6 }, nullptr, nullptr},
+{ "x7", nullptr, 8, GPR_OFFSET(7), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x7, arm64_dwarf::x7, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM, gpr_x7 }, nullptr, nullptr},
+{ "x8", nullptr, 8, GPR_OFFSET(8), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x8, arm64_dwarf::x8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x8 }, nullptr, nullptr},
+{ "x9", nullptr, 8, GPR_OFFSET(9), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x9, arm64_dwarf::x9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x9 }, nullptr, nullptr},
+{ "x10", nullptr, 8, GPR_OFFSET(10), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x10, arm64_dwarf::x10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x10 }, nullptr, nullptr},
+{ "x11", nullptr, 8, GPR_OFFSET(11), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x11, arm64_dwarf::x11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x11 }, nullptr, nullptr},
+{ "x12", nullptr, 8, GPR_OFFSET(12), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x12, arm64_dwarf::x12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x12 }, nullptr, nullptr},
+{ "x13", nullptr, 8, GPR_OFFSET(13), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x13, arm64_dwarf::x13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x13 }, nullptr, nullptr},
+{ "x14", nullptr, 8, GPR_OFFSET(14), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x14, arm64_dwarf::x14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x14 }, nullptr, nullptr},
+{ "x15", nullptr, 8, GPR_OFFSET(15), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x15, arm64_dwarf::x15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x15 }, nullptr, nullptr},
+{ "x16", nullptr, 8, GPR_OFFSET(16), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x16, arm64_dwarf::x16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x16 }, nullptr, nullptr},
+{ "x17", nullptr, 8, GPR_OFFSET(17), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x17, arm64_dwarf::x17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x17 }, nullptr, nullptr},
+{ "x18", nullptr, 8, GPR_OFFSET(18), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x18, arm64_dwarf::x18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x18 }, nullptr, nullptr},
+{ "x19", nullptr, 8, GPR_OFFSET(19), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x19, arm64_dwarf::x19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x19 }, nullptr, nullptr},
+{ "x20", nullptr, 8, GPR_OFFSET(20), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x20, arm64_dwarf::x20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x20 }, nullptr, nullptr},
+{ "x21", nullptr, 8, GPR_OFFSET(21), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x21, arm64_dwarf::x21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x21 }, nullptr, nullptr},
+{ "x22", nullptr, 8, GPR_OFFSET(22), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x22, arm64_dwarf::x22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x22 }, nullptr, nullptr},
+{ "x23", nullptr, 8, GPR_OFFSET(23), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x23, arm64_dwarf::x23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x23 }, nullptr, nullptr},
+{ "x24", nullptr, 8, GPR_OFFSET(24), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x24, arm64_dwarf::x24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x24 }, nullptr, nullptr},
+{ "x25", nullptr, 8, GPR_OFFSET(25), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x25, arm64_dwarf::x25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x25 }, nullptr, nullptr},
+{ "x26", nullptr, 8, GPR_OFFSET(26), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x26, arm64_dwarf::x26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x26 }, nullptr, nullptr},
+{ "x27", nullptr, 8, GPR_OFFSET(27), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x27, arm64_dwarf::x27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x27 }, nullptr, nullptr},
+{ "x28", nullptr, 8, GPR_OFFSET(28), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::x28, arm64_dwarf::x28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x28 }, nullptr, nullptr},
-{ "fp", "x29", 8, GPR_OFFSET(29), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::fp, arm64_dwarf::fp, LLDB_REGNUM_GENERIC_FP, arm64_gcc::fp, gpr_fp }, NULL, NULL},
-{ "lr", "x30", 8, GPR_OFFSET(30), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::lr, arm64_dwarf::lr, LLDB_REGNUM_GENERIC_RA, arm64_gcc::lr, gpr_lr }, NULL, NULL},
-{ "sp", "x31", 8, GPR_OFFSET(31), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::sp, arm64_dwarf::sp, LLDB_REGNUM_GENERIC_SP, arm64_gcc::sp, gpr_sp }, NULL, NULL},
-{ "pc", NULL, 8, GPR_OFFSET(32), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::pc, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, arm64_gcc::pc, gpr_pc }, NULL, NULL},
+{ "fp", "x29", 8, GPR_OFFSET(29), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::fp, arm64_dwarf::fp, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, gpr_fp }, nullptr, nullptr},
+{ "lr", "x30", 8, GPR_OFFSET(30), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::lr, arm64_dwarf::lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, gpr_lr }, nullptr, nullptr},
+{ "sp", "x31", 8, GPR_OFFSET(31), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::sp, arm64_dwarf::sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, gpr_sp }, nullptr, nullptr},
+{ "pc", nullptr, 8, GPR_OFFSET(32), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::pc, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, gpr_pc }, nullptr, nullptr},
-{ "cpsr", NULL, 4, GPR_OFFSET_NAME(cpsr), lldb::eEncodingUint, lldb::eFormatHex, { arm64_gcc::cpsr, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, arm64_gcc::cpsr, gpr_cpsr }, NULL, NULL},
+{ "cpsr", nullptr, 4, GPR_OFFSET_NAME(cpsr), lldb::eEncodingUint, lldb::eFormatHex, { arm64_ehframe::cpsr, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, gpr_cpsr }, nullptr, nullptr},
-{ "v0", NULL, 16, FPU_OFFSET(0), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v0, LLDB_INVALID_REGNUM, arm64_gcc::v0, fpu_v0 }, NULL, NULL},
-{ "v1", NULL, 16, FPU_OFFSET(1), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v1, LLDB_INVALID_REGNUM, arm64_gcc::v1, fpu_v1 }, NULL, NULL},
-{ "v2", NULL, 16, FPU_OFFSET(2), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v2, LLDB_INVALID_REGNUM, arm64_gcc::v2, fpu_v2 }, NULL, NULL},
-{ "v3", NULL, 16, FPU_OFFSET(3), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v3, LLDB_INVALID_REGNUM, arm64_gcc::v3, fpu_v3 }, NULL, NULL},
-{ "v4", NULL, 16, FPU_OFFSET(4), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v4, LLDB_INVALID_REGNUM, arm64_gcc::v4, fpu_v4 }, NULL, NULL},
-{ "v5", NULL, 16, FPU_OFFSET(5), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v5, LLDB_INVALID_REGNUM, arm64_gcc::v5, fpu_v5 }, NULL, NULL},
-{ "v6", NULL, 16, FPU_OFFSET(6), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v6, LLDB_INVALID_REGNUM, arm64_gcc::v6, fpu_v6 }, NULL, NULL},
-{ "v7", NULL, 16, FPU_OFFSET(7), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v7, LLDB_INVALID_REGNUM, arm64_gcc::v7, fpu_v7 }, NULL, NULL},
-{ "v8", NULL, 16, FPU_OFFSET(8), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v8, LLDB_INVALID_REGNUM, arm64_gcc::v8, fpu_v8 }, NULL, NULL},
-{ "v9", NULL, 16, FPU_OFFSET(9), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v9, LLDB_INVALID_REGNUM, arm64_gcc::v9, fpu_v9 }, NULL, NULL},
-{ "v10", NULL, 16, FPU_OFFSET(10), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v10, LLDB_INVALID_REGNUM, arm64_gcc::v10, fpu_v10 }, NULL, NULL},
-{ "v11", NULL, 16, FPU_OFFSET(11), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v11, LLDB_INVALID_REGNUM, arm64_gcc::v11, fpu_v11 }, NULL, NULL},
-{ "v12", NULL, 16, FPU_OFFSET(12), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v12, LLDB_INVALID_REGNUM, arm64_gcc::v12, fpu_v12 }, NULL, NULL},
-{ "v13", NULL, 16, FPU_OFFSET(13), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v13, LLDB_INVALID_REGNUM, arm64_gcc::v13, fpu_v13 }, NULL, NULL},
-{ "v14", NULL, 16, FPU_OFFSET(14), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v14, LLDB_INVALID_REGNUM, arm64_gcc::v14, fpu_v14 }, NULL, NULL},
-{ "v15", NULL, 16, FPU_OFFSET(15), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v15, LLDB_INVALID_REGNUM, arm64_gcc::v15, fpu_v15 }, NULL, NULL},
-{ "v16", NULL, 16, FPU_OFFSET(16), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v16, LLDB_INVALID_REGNUM, arm64_gcc::v16, fpu_v16 }, NULL, NULL},
-{ "v17", NULL, 16, FPU_OFFSET(17), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v17, LLDB_INVALID_REGNUM, arm64_gcc::v17, fpu_v17 }, NULL, NULL},
-{ "v18", NULL, 16, FPU_OFFSET(18), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v18, LLDB_INVALID_REGNUM, arm64_gcc::v18, fpu_v18 }, NULL, NULL},
-{ "v19", NULL, 16, FPU_OFFSET(19), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v19, LLDB_INVALID_REGNUM, arm64_gcc::v19, fpu_v19 }, NULL, NULL},
-{ "v20", NULL, 16, FPU_OFFSET(20), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v20, LLDB_INVALID_REGNUM, arm64_gcc::v20, fpu_v20 }, NULL, NULL},
-{ "v21", NULL, 16, FPU_OFFSET(21), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v21, LLDB_INVALID_REGNUM, arm64_gcc::v21, fpu_v21 }, NULL, NULL},
-{ "v22", NULL, 16, FPU_OFFSET(22), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v22, LLDB_INVALID_REGNUM, arm64_gcc::v22, fpu_v22 }, NULL, NULL},
-{ "v23", NULL, 16, FPU_OFFSET(23), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v23, LLDB_INVALID_REGNUM, arm64_gcc::v23, fpu_v23 }, NULL, NULL},
-{ "v24", NULL, 16, FPU_OFFSET(24), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v24, LLDB_INVALID_REGNUM, arm64_gcc::v24, fpu_v24 }, NULL, NULL},
-{ "v25", NULL, 16, FPU_OFFSET(25), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v25, LLDB_INVALID_REGNUM, arm64_gcc::v25, fpu_v25 }, NULL, NULL},
-{ "v26", NULL, 16, FPU_OFFSET(26), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v26, LLDB_INVALID_REGNUM, arm64_gcc::v26, fpu_v26 }, NULL, NULL},
-{ "v27", NULL, 16, FPU_OFFSET(27), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v27, LLDB_INVALID_REGNUM, arm64_gcc::v27, fpu_v27 }, NULL, NULL},
-{ "v28", NULL, 16, FPU_OFFSET(28), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v28, LLDB_INVALID_REGNUM, arm64_gcc::v28, fpu_v28 }, NULL, NULL},
-{ "v29", NULL, 16, FPU_OFFSET(29), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v29, LLDB_INVALID_REGNUM, arm64_gcc::v29, fpu_v29 }, NULL, NULL},
-{ "v30", NULL, 16, FPU_OFFSET(30), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v30, LLDB_INVALID_REGNUM, arm64_gcc::v30, fpu_v30 }, NULL, NULL},
-{ "v31", NULL, 16, FPU_OFFSET(31), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v31, LLDB_INVALID_REGNUM, arm64_gcc::v31, fpu_v31 }, NULL, NULL},
+{ "v0", nullptr, 16, FPU_OFFSET(0), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v0 }, nullptr, nullptr},
+{ "v1", nullptr, 16, FPU_OFFSET(1), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v1 }, nullptr, nullptr},
+{ "v2", nullptr, 16, FPU_OFFSET(2), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v2 }, nullptr, nullptr},
+{ "v3", nullptr, 16, FPU_OFFSET(3), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v3 }, nullptr, nullptr},
+{ "v4", nullptr, 16, FPU_OFFSET(4), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v4 }, nullptr, nullptr},
+{ "v5", nullptr, 16, FPU_OFFSET(5), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v5 }, nullptr, nullptr},
+{ "v6", nullptr, 16, FPU_OFFSET(6), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v6 }, nullptr, nullptr},
+{ "v7", nullptr, 16, FPU_OFFSET(7), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v7 }, nullptr, nullptr},
+{ "v8", nullptr, 16, FPU_OFFSET(8), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v8 }, nullptr, nullptr},
+{ "v9", nullptr, 16, FPU_OFFSET(9), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v9 }, nullptr, nullptr},
+{ "v10", nullptr, 16, FPU_OFFSET(10), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v10 }, nullptr, nullptr},
+{ "v11", nullptr, 16, FPU_OFFSET(11), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v11 }, nullptr, nullptr},
+{ "v12", nullptr, 16, FPU_OFFSET(12), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v12 }, nullptr, nullptr},
+{ "v13", nullptr, 16, FPU_OFFSET(13), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v13 }, nullptr, nullptr},
+{ "v14", nullptr, 16, FPU_OFFSET(14), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v14 }, nullptr, nullptr},
+{ "v15", nullptr, 16, FPU_OFFSET(15), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v15 }, nullptr, nullptr},
+{ "v16", nullptr, 16, FPU_OFFSET(16), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v16 }, nullptr, nullptr},
+{ "v17", nullptr, 16, FPU_OFFSET(17), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v17 }, nullptr, nullptr},
+{ "v18", nullptr, 16, FPU_OFFSET(18), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v18 }, nullptr, nullptr},
+{ "v19", nullptr, 16, FPU_OFFSET(19), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v19 }, nullptr, nullptr},
+{ "v20", nullptr, 16, FPU_OFFSET(20), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v20 }, nullptr, nullptr},
+{ "v21", nullptr, 16, FPU_OFFSET(21), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v21 }, nullptr, nullptr},
+{ "v22", nullptr, 16, FPU_OFFSET(22), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v22 }, nullptr, nullptr},
+{ "v23", nullptr, 16, FPU_OFFSET(23), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v23 }, nullptr, nullptr},
+{ "v24", nullptr, 16, FPU_OFFSET(24), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v24 }, nullptr, nullptr},
+{ "v25", nullptr, 16, FPU_OFFSET(25), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v25 }, nullptr, nullptr},
+{ "v26", nullptr, 16, FPU_OFFSET(26), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v26 }, nullptr, nullptr},
+{ "v27", nullptr, 16, FPU_OFFSET(27), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v27 }, nullptr, nullptr},
+{ "v28", nullptr, 16, FPU_OFFSET(28), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v28 }, nullptr, nullptr},
+{ "v29", nullptr, 16, FPU_OFFSET(29), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v29 }, nullptr, nullptr},
+{ "v30", nullptr, 16, FPU_OFFSET(30), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v30 }, nullptr, nullptr},
+{ "v31", nullptr, 16, FPU_OFFSET(31), lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_v31 }, nullptr, nullptr},
-{ "fpsr", NULL, 4, FPU_OFFSET_NAME(fpsr), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpsr }, NULL, NULL},
-{ "fpcr", NULL, 4, FPU_OFFSET_NAME(fpcr), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpcr }, NULL, NULL},
+{ "fpsr", nullptr, 4, FPU_OFFSET_NAME(fpsr), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpsr }, nullptr, nullptr},
+{ "fpcr", nullptr, 4, FPU_OFFSET_NAME(fpcr), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpcr }, nullptr, nullptr},
-{ "far", NULL, 8, EXC_OFFSET_NAME(far), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_far }, NULL, NULL},
-{ "esr", NULL, 4, EXC_OFFSET_NAME(esr), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_esr }, NULL, NULL},
-{ "exception",NULL, 4, EXC_OFFSET_NAME(exception), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception }, NULL, NULL},
+{ "far", nullptr, 8, EXC_OFFSET_NAME(far), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_far }, nullptr, nullptr},
+{ "esr", nullptr, 4, EXC_OFFSET_NAME(esr), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_esr }, nullptr, nullptr},
+{ "exception",nullptr, 4, EXC_OFFSET_NAME(exception), lldb::eEncodingUint, lldb::eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception }, nullptr, nullptr},
{ DEFINE_DBG (bvr, 0) },
{ DEFINE_DBG (bvr, 1) },
diff --git a/source/Plugins/Process/Utility/RegisterInfos_i386.h b/source/Plugins/Process/Utility/RegisterInfos_i386.h
index 69825362134b..904ec4d1f0bd 100644
--- a/source/Plugins/Process/Utility/RegisterInfos_i386.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_i386.h
@@ -1,15 +1,21 @@
-//===-- RegisterInfos_i386.h -----------------------------------*- C++ -*-===//
+//===-- RegisterInfos_i386.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
-#include "llvm/Support/Compiler.h"
+//===----------------------------------------------------------------------===//
+// C Includes
#include <stddef.h>
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/Support/Compiler.h"
+
+// Project includes
+
#ifdef DECLARE_REGISTER_INFOS_I386_STRUCT
// Computes the offset of the given GPR in the user data area.
@@ -52,31 +58,31 @@
{ #name, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
eFormatHex, { kind1, kind2, kind3, kind4, lldb_##name##_i386 }, NULL, NULL }
-// RegisterKind: GCC, DWARF, Generic, GDB, LLDB
+// RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB
#define DEFINE_FP_ST(reg, i) \
{ #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(stmm[i]), \
eEncodingVector, eFormatVectorOfUInt8, \
- { gcc_st##i##_i386, dwarf_st##i##_i386, LLDB_INVALID_REGNUM, gdb_st##i##_i386, lldb_st##i##_i386 }, \
+ { ehframe_st##i##_i386, dwarf_st##i##_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_st##i##_i386 }, \
NULL, NULL }
#define DEFINE_FP_MM(reg, i) \
{ #reg#i, NULL, sizeof(uint64_t), LLVM_EXTENSION FPR_OFFSET(stmm[i]), \
eEncodingUint, eFormatHex, \
- { gcc_mm##i##_i386, dwarf_mm##i##_i386, LLDB_INVALID_REGNUM, gdb_mm##i##_i386, lldb_mm##i##_i386 }, \
+ { ehframe_mm##i##_i386, dwarf_mm##i##_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_mm##i##_i386 }, \
NULL, NULL }
#define DEFINE_XMM(reg, i) \
{ #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \
eEncodingVector, eFormatVectorOfUInt8, \
- { gcc_##reg##i##_i386, dwarf_##reg##i##_i386, LLDB_INVALID_REGNUM, gdb_##reg##i##_i386, lldb_##reg##i##_i386}, \
+ { ehframe_##reg##i##_i386, dwarf_##reg##i##_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_i386}, \
NULL, NULL }
// I believe the YMM registers use dwarf_xmm_%_i386 register numbers and then differentiate based on register size.
#define DEFINE_YMM(reg, i) \
{ #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(i), \
eEncodingVector, eFormatVectorOfUInt8, \
- { LLDB_INVALID_REGNUM, dwarf_xmm##i##_i386, LLDB_INVALID_REGNUM, gdb_##reg##i##h_i386, lldb_##reg##i##_i386 }, \
+ { LLDB_INVALID_REGNUM, dwarf_xmm##i##_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_i386 }, \
NULL, NULL }
#define DEFINE_DR(reg, i) \
@@ -98,22 +104,22 @@ static RegisterInfo
g_register_infos_i386[] =
{
// General purpose registers.
- DEFINE_GPR(eax, NULL, gcc_eax_i386, dwarf_eax_i386, LLDB_INVALID_REGNUM, gdb_eax_i386),
- DEFINE_GPR(ebx, NULL, gcc_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM, gdb_ebx_i386),
- DEFINE_GPR(ecx, NULL, gcc_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM, gdb_ecx_i386),
- DEFINE_GPR(edx, NULL, gcc_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM, gdb_edx_i386),
- DEFINE_GPR(edi, NULL, gcc_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM, gdb_edi_i386),
- DEFINE_GPR(esi, NULL, gcc_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM, gdb_esi_i386),
- DEFINE_GPR(ebp, "fp", gcc_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP, gdb_ebp_i386),
- DEFINE_GPR(esp, "sp", gcc_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP, gdb_esp_i386),
- DEFINE_GPR(eip, "pc", gcc_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC, gdb_eip_i386),
- DEFINE_GPR(eflags, "flags", gcc_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS, gdb_eflags_i386),
- DEFINE_GPR(cs, NULL, LLDB_INVALID_REGNUM, dwarf_cs_i386, LLDB_INVALID_REGNUM, gdb_cs_i386),
- DEFINE_GPR(fs, NULL, LLDB_INVALID_REGNUM, dwarf_fs_i386, LLDB_INVALID_REGNUM, gdb_fs_i386),
- DEFINE_GPR(gs, NULL, LLDB_INVALID_REGNUM, dwarf_gs_i386, LLDB_INVALID_REGNUM, gdb_gs_i386),
- DEFINE_GPR(ss, NULL, LLDB_INVALID_REGNUM, dwarf_ss_i386, LLDB_INVALID_REGNUM, gdb_ss_i386),
- DEFINE_GPR(ds, NULL, LLDB_INVALID_REGNUM, dwarf_ds_i386, LLDB_INVALID_REGNUM, gdb_ds_i386),
- DEFINE_GPR(es, NULL, LLDB_INVALID_REGNUM, dwarf_es_i386, LLDB_INVALID_REGNUM, gdb_es_i386),
+ DEFINE_GPR(eax, nullptr, ehframe_eax_i386, dwarf_eax_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ebx, nullptr, ehframe_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ecx, nullptr, ehframe_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(edx, nullptr, ehframe_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(edi, nullptr, ehframe_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(esi, nullptr, ehframe_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ebp, "fp", ehframe_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(esp, "sp", ehframe_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(eip, "pc", ehframe_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(eflags, "flags", ehframe_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(cs, nullptr, LLDB_INVALID_REGNUM, dwarf_cs_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(fs, nullptr, LLDB_INVALID_REGNUM, dwarf_fs_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(gs, nullptr, LLDB_INVALID_REGNUM, dwarf_gs_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ss, nullptr, LLDB_INVALID_REGNUM, dwarf_ss_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ds, nullptr, LLDB_INVALID_REGNUM, dwarf_ds_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(es, nullptr, LLDB_INVALID_REGNUM, dwarf_es_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
DEFINE_GPR_PSEUDO_16(ax, eax),
DEFINE_GPR_PSEUDO_16(bx, ebx),
@@ -133,15 +139,15 @@ g_register_infos_i386[] =
DEFINE_GPR_PSEUDO_8L(dl, edx),
// i387 Floating point registers.
- DEFINE_FPR(fctrl, fctrl, LLDB_INVALID_REGNUM, dwarf_fctrl_i386, LLDB_INVALID_REGNUM, gdb_fctrl_i386),
- DEFINE_FPR(fstat, fstat, LLDB_INVALID_REGNUM, dwarf_fstat_i386, LLDB_INVALID_REGNUM, gdb_fstat_i386),
- DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftag_i386),
- DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop_i386),
- DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fiseg_i386),
- DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fioff_i386),
- DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_foseg_i386),
- DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fooff_i386),
- DEFINE_FPR(mxcsr, mxcsr, LLDB_INVALID_REGNUM, dwarf_mxcsr_i386, LLDB_INVALID_REGNUM, gdb_mxcsr_i386),
+ DEFINE_FPR(fctrl, fctrl, LLDB_INVALID_REGNUM, dwarf_fctrl_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fstat, fstat, LLDB_INVALID_REGNUM, dwarf_fstat_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(mxcsr, mxcsr, LLDB_INVALID_REGNUM, dwarf_mxcsr_i386, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
// FP registers.
@@ -192,6 +198,7 @@ g_register_infos_i386[] =
DEFINE_DR(dr, 6),
DEFINE_DR(dr, 7)
};
+
static_assert((sizeof(g_register_infos_i386) / sizeof(g_register_infos_i386[0])) == k_num_registers_i386,
"g_register_infos_x86_64 has wrong number of register infos");
diff --git a/source/Plugins/Process/Utility/RegisterInfos_mips.h b/source/Plugins/Process/Utility/RegisterInfos_mips.h
index 83ce6f0d4327..eef27f0208e0 100644
--- a/source/Plugins/Process/Utility/RegisterInfos_mips.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_mips.h
@@ -6,10 +6,16 @@
// License. See LICENSE.TXT for details.
//
//===---------------------------------------------------------------------===//
-#include "llvm/Support/Compiler.h"
+// C Includes
#include <stddef.h>
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/Support/Compiler.h"
+
+// Project includes
+
#ifdef DECLARE_REGISTER_INFOS_MIPS_STRUCT
// Computes the offset of the given GPR in the user data area.
@@ -44,123 +50,124 @@
{ #reg, alt, sizeof(((MSA_linux_mips*)0)->reg), MSA_OFFSET(reg), eEncodingUint, \
eFormatHex, { kind1, kind2, kind3, kind4, msa_##reg##_mips }, NULL, NULL }
-// RegisterKind: GCC, DWARF, Generic, GDB, LLDB
+// RegisterKind: EH_Frame, DWARF, Generic, Procss Plugin, LLDB
static RegisterInfo
g_register_infos_mips[] =
{
- DEFINE_GPR (zero, "zero", gcc_dwarf_zero_mips, gcc_dwarf_zero_mips, LLDB_INVALID_REGNUM, gdb_zero_mips),
- DEFINE_GPR (r1, "at", gcc_dwarf_r1_mips, gcc_dwarf_r1_mips, LLDB_INVALID_REGNUM, gdb_r1_mips),
- DEFINE_GPR (r2, NULL, gcc_dwarf_r2_mips, gcc_dwarf_r2_mips, LLDB_INVALID_REGNUM, gdb_r2_mips),
- DEFINE_GPR (r3, NULL, gcc_dwarf_r3_mips, gcc_dwarf_r3_mips, LLDB_INVALID_REGNUM, gdb_r3_mips),
- DEFINE_GPR (r4, NULL, gcc_dwarf_r4_mips, gcc_dwarf_r4_mips, LLDB_REGNUM_GENERIC_ARG1, gdb_r4_mips),
- DEFINE_GPR (r5, NULL, gcc_dwarf_r5_mips, gcc_dwarf_r5_mips, LLDB_REGNUM_GENERIC_ARG2, gdb_r5_mips),
- DEFINE_GPR (r6, NULL, gcc_dwarf_r6_mips, gcc_dwarf_r6_mips, LLDB_REGNUM_GENERIC_ARG3, gdb_r6_mips),
- DEFINE_GPR (r7, NULL, gcc_dwarf_r7_mips, gcc_dwarf_r7_mips, LLDB_REGNUM_GENERIC_ARG4, gdb_r7_mips),
- DEFINE_GPR (r8, NULL, gcc_dwarf_r8_mips, gcc_dwarf_r8_mips, LLDB_INVALID_REGNUM, gdb_r8_mips),
- DEFINE_GPR (r9, NULL, gcc_dwarf_r9_mips, gcc_dwarf_r9_mips, LLDB_INVALID_REGNUM, gdb_r9_mips),
- DEFINE_GPR (r10, NULL, gcc_dwarf_r10_mips, gcc_dwarf_r10_mips, LLDB_INVALID_REGNUM, gdb_r10_mips),
- DEFINE_GPR (r11, NULL, gcc_dwarf_r11_mips, gcc_dwarf_r11_mips, LLDB_INVALID_REGNUM, gdb_r11_mips),
- DEFINE_GPR (r12, NULL, gcc_dwarf_r12_mips, gcc_dwarf_r12_mips, LLDB_INVALID_REGNUM, gdb_r12_mips),
- DEFINE_GPR (r13, NULL, gcc_dwarf_r13_mips, gcc_dwarf_r13_mips, LLDB_INVALID_REGNUM, gdb_r13_mips),
- DEFINE_GPR (r14, NULL, gcc_dwarf_r14_mips, gcc_dwarf_r14_mips, LLDB_INVALID_REGNUM, gdb_r14_mips),
- DEFINE_GPR (r15, NULL, gcc_dwarf_r15_mips, gcc_dwarf_r15_mips, LLDB_INVALID_REGNUM, gdb_r15_mips),
- DEFINE_GPR (r16, NULL, gcc_dwarf_r16_mips, gcc_dwarf_r16_mips, LLDB_INVALID_REGNUM, gdb_r16_mips),
- DEFINE_GPR (r17, NULL, gcc_dwarf_r17_mips, gcc_dwarf_r17_mips, LLDB_INVALID_REGNUM, gdb_r17_mips),
- DEFINE_GPR (r18, NULL, gcc_dwarf_r18_mips, gcc_dwarf_r18_mips, LLDB_INVALID_REGNUM, gdb_r18_mips),
- DEFINE_GPR (r19, NULL, gcc_dwarf_r19_mips, gcc_dwarf_r19_mips, LLDB_INVALID_REGNUM, gdb_r19_mips),
- DEFINE_GPR (r20, NULL, gcc_dwarf_r20_mips, gcc_dwarf_r20_mips, LLDB_INVALID_REGNUM, gdb_r20_mips),
- DEFINE_GPR (r21, NULL, gcc_dwarf_r21_mips, gcc_dwarf_r21_mips, LLDB_INVALID_REGNUM, gdb_r21_mips),
- DEFINE_GPR (r22, NULL, gcc_dwarf_r22_mips, gcc_dwarf_r22_mips, LLDB_INVALID_REGNUM, gdb_r22_mips),
- DEFINE_GPR (r23, NULL, gcc_dwarf_r23_mips, gcc_dwarf_r23_mips, LLDB_INVALID_REGNUM, gdb_r23_mips),
- DEFINE_GPR (r24, NULL, gcc_dwarf_r24_mips, gcc_dwarf_r24_mips, LLDB_INVALID_REGNUM, gdb_r24_mips),
- DEFINE_GPR (r25, NULL, gcc_dwarf_r25_mips, gcc_dwarf_r25_mips, LLDB_INVALID_REGNUM, gdb_r25_mips),
- DEFINE_GPR (r26, NULL, gcc_dwarf_r26_mips, gcc_dwarf_r26_mips, LLDB_INVALID_REGNUM, gdb_r26_mips),
- DEFINE_GPR (r27, NULL, gcc_dwarf_r27_mips, gcc_dwarf_r27_mips, LLDB_INVALID_REGNUM, gdb_r27_mips),
- DEFINE_GPR (gp, "gp", gcc_dwarf_gp_mips, gcc_dwarf_gp_mips, LLDB_INVALID_REGNUM, gdb_gp_mips),
- DEFINE_GPR (sp, "sp", gcc_dwarf_sp_mips, gcc_dwarf_sp_mips, LLDB_REGNUM_GENERIC_SP, gdb_sp_mips),
- DEFINE_GPR (r30, "fp", gcc_dwarf_r30_mips, gcc_dwarf_r30_mips, LLDB_REGNUM_GENERIC_FP, gdb_r30_mips),
- DEFINE_GPR (ra, "ra", gcc_dwarf_ra_mips, gcc_dwarf_ra_mips, LLDB_REGNUM_GENERIC_RA, gdb_ra_mips),
- DEFINE_GPR (sr, "status", gcc_dwarf_sr_mips, gcc_dwarf_sr_mips, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
- DEFINE_GPR (mullo, NULL, gcc_dwarf_lo_mips, gcc_dwarf_lo_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR (mulhi, NULL, gcc_dwarf_hi_mips, gcc_dwarf_hi_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR (badvaddr, NULL, gcc_dwarf_bad_mips, gcc_dwarf_bad_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR (cause, NULL, gcc_dwarf_cause_mips, gcc_dwarf_cause_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR (pc, NULL, gcc_dwarf_pc_mips, gcc_dwarf_pc_mips, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
- DEFINE_GPR (config5, NULL, gcc_dwarf_config5_mips, gcc_dwarf_config5_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_FPR (f0, NULL, gcc_dwarf_f0_mips, gcc_dwarf_f0_mips, LLDB_INVALID_REGNUM, gdb_f0_mips),
- DEFINE_FPR (f1, NULL, gcc_dwarf_f1_mips, gcc_dwarf_f1_mips, LLDB_INVALID_REGNUM, gdb_f1_mips),
- DEFINE_FPR (f2, NULL, gcc_dwarf_f2_mips, gcc_dwarf_f2_mips, LLDB_INVALID_REGNUM, gdb_f2_mips),
- DEFINE_FPR (f3, NULL, gcc_dwarf_f3_mips, gcc_dwarf_f3_mips, LLDB_INVALID_REGNUM, gdb_f3_mips),
- DEFINE_FPR (f4, NULL, gcc_dwarf_f4_mips, gcc_dwarf_f4_mips, LLDB_INVALID_REGNUM, gdb_f4_mips),
- DEFINE_FPR (f5, NULL, gcc_dwarf_f5_mips, gcc_dwarf_f5_mips, LLDB_INVALID_REGNUM, gdb_f5_mips),
- DEFINE_FPR (f6, NULL, gcc_dwarf_f6_mips, gcc_dwarf_f6_mips, LLDB_INVALID_REGNUM, gdb_f6_mips),
- DEFINE_FPR (f7, NULL, gcc_dwarf_f7_mips, gcc_dwarf_f7_mips, LLDB_INVALID_REGNUM, gdb_f7_mips),
- DEFINE_FPR (f8, NULL, gcc_dwarf_f8_mips, gcc_dwarf_f8_mips, LLDB_INVALID_REGNUM, gdb_f8_mips),
- DEFINE_FPR (f9, NULL, gcc_dwarf_f9_mips, gcc_dwarf_f9_mips, LLDB_INVALID_REGNUM, gdb_f9_mips),
- DEFINE_FPR (f10, NULL, gcc_dwarf_f10_mips, gcc_dwarf_f10_mips, LLDB_INVALID_REGNUM, gdb_f10_mips),
- DEFINE_FPR (f11, NULL, gcc_dwarf_f11_mips, gcc_dwarf_f11_mips, LLDB_INVALID_REGNUM, gdb_f11_mips),
- DEFINE_FPR (f12, NULL, gcc_dwarf_f12_mips, gcc_dwarf_f12_mips, LLDB_INVALID_REGNUM, gdb_f12_mips),
- DEFINE_FPR (f13, NULL, gcc_dwarf_f13_mips, gcc_dwarf_f13_mips, LLDB_INVALID_REGNUM, gdb_f13_mips),
- DEFINE_FPR (f14, NULL, gcc_dwarf_f14_mips, gcc_dwarf_f14_mips, LLDB_INVALID_REGNUM, gdb_f14_mips),
- DEFINE_FPR (f15, NULL, gcc_dwarf_f15_mips, gcc_dwarf_f15_mips, LLDB_INVALID_REGNUM, gdb_f15_mips),
- DEFINE_FPR (f16, NULL, gcc_dwarf_f16_mips, gcc_dwarf_f16_mips, LLDB_INVALID_REGNUM, gdb_f16_mips),
- DEFINE_FPR (f17, NULL, gcc_dwarf_f17_mips, gcc_dwarf_f17_mips, LLDB_INVALID_REGNUM, gdb_f17_mips),
- DEFINE_FPR (f18, NULL, gcc_dwarf_f18_mips, gcc_dwarf_f18_mips, LLDB_INVALID_REGNUM, gdb_f18_mips),
- DEFINE_FPR (f19, NULL, gcc_dwarf_f19_mips, gcc_dwarf_f19_mips, LLDB_INVALID_REGNUM, gdb_f19_mips),
- DEFINE_FPR (f20, NULL, gcc_dwarf_f20_mips, gcc_dwarf_f20_mips, LLDB_INVALID_REGNUM, gdb_f20_mips),
- DEFINE_FPR (f21, NULL, gcc_dwarf_f21_mips, gcc_dwarf_f21_mips, LLDB_INVALID_REGNUM, gdb_f21_mips),
- DEFINE_FPR (f22, NULL, gcc_dwarf_f22_mips, gcc_dwarf_f22_mips, LLDB_INVALID_REGNUM, gdb_f22_mips),
- DEFINE_FPR (f23, NULL, gcc_dwarf_f23_mips, gcc_dwarf_f23_mips, LLDB_INVALID_REGNUM, gdb_f23_mips),
- DEFINE_FPR (f24, NULL, gcc_dwarf_f24_mips, gcc_dwarf_f24_mips, LLDB_INVALID_REGNUM, gdb_f24_mips),
- DEFINE_FPR (f25, NULL, gcc_dwarf_f25_mips, gcc_dwarf_f25_mips, LLDB_INVALID_REGNUM, gdb_f25_mips),
- DEFINE_FPR (f26, NULL, gcc_dwarf_f26_mips, gcc_dwarf_f26_mips, LLDB_INVALID_REGNUM, gdb_f26_mips),
- DEFINE_FPR (f27, NULL, gcc_dwarf_f27_mips, gcc_dwarf_f27_mips, LLDB_INVALID_REGNUM, gdb_f27_mips),
- DEFINE_FPR (f28, NULL, gcc_dwarf_f28_mips, gcc_dwarf_f28_mips, LLDB_INVALID_REGNUM, gdb_f28_mips),
- DEFINE_FPR (f29, NULL, gcc_dwarf_f29_mips, gcc_dwarf_f29_mips, LLDB_INVALID_REGNUM, gdb_f29_mips),
- DEFINE_FPR (f30, NULL, gcc_dwarf_f30_mips, gcc_dwarf_f30_mips, LLDB_INVALID_REGNUM, gdb_f30_mips),
- DEFINE_FPR (f31, NULL, gcc_dwarf_f31_mips, gcc_dwarf_f31_mips, LLDB_INVALID_REGNUM, gdb_f31_mips),
- DEFINE_FPR (fcsr, NULL, gcc_dwarf_fcsr_mips, gcc_dwarf_fcsr_mips, LLDB_INVALID_REGNUM, gdb_fcsr_mips),
- DEFINE_FPR (fir, NULL, gcc_dwarf_fir_mips, gcc_dwarf_fir_mips, LLDB_INVALID_REGNUM, gdb_fir_mips),
- DEFINE_FPR (config5, NULL, gcc_dwarf_config5_mips, gcc_dwarf_config5_mips, LLDB_INVALID_REGNUM, gdb_config5_mips),
- DEFINE_MSA (w0, NULL, gcc_dwarf_w0_mips, gcc_dwarf_w0_mips, LLDB_INVALID_REGNUM, gdb_w0_mips),
- DEFINE_MSA (w1, NULL, gcc_dwarf_w1_mips, gcc_dwarf_w1_mips, LLDB_INVALID_REGNUM, gdb_w1_mips),
- DEFINE_MSA (w2, NULL, gcc_dwarf_w2_mips, gcc_dwarf_w2_mips, LLDB_INVALID_REGNUM, gdb_w2_mips),
- DEFINE_MSA (w3, NULL, gcc_dwarf_w3_mips, gcc_dwarf_w3_mips, LLDB_INVALID_REGNUM, gdb_w3_mips),
- DEFINE_MSA (w4, NULL, gcc_dwarf_w4_mips, gcc_dwarf_w4_mips, LLDB_INVALID_REGNUM, gdb_w4_mips),
- DEFINE_MSA (w5, NULL, gcc_dwarf_w5_mips, gcc_dwarf_w5_mips, LLDB_INVALID_REGNUM, gdb_w5_mips),
- DEFINE_MSA (w6, NULL, gcc_dwarf_w6_mips, gcc_dwarf_w6_mips, LLDB_INVALID_REGNUM, gdb_w6_mips),
- DEFINE_MSA (w7, NULL, gcc_dwarf_w7_mips, gcc_dwarf_w7_mips, LLDB_INVALID_REGNUM, gdb_w7_mips),
- DEFINE_MSA (w8, NULL, gcc_dwarf_w8_mips, gcc_dwarf_w8_mips, LLDB_INVALID_REGNUM, gdb_w8_mips),
- DEFINE_MSA (w9, NULL, gcc_dwarf_w9_mips, gcc_dwarf_w9_mips, LLDB_INVALID_REGNUM, gdb_w9_mips),
- DEFINE_MSA (w10, NULL, gcc_dwarf_w10_mips, gcc_dwarf_w10_mips, LLDB_INVALID_REGNUM, gdb_w10_mips),
- DEFINE_MSA (w11, NULL, gcc_dwarf_w11_mips, gcc_dwarf_w11_mips, LLDB_INVALID_REGNUM, gdb_w11_mips),
- DEFINE_MSA (w12, NULL, gcc_dwarf_w12_mips, gcc_dwarf_w12_mips, LLDB_INVALID_REGNUM, gdb_w12_mips),
- DEFINE_MSA (w13, NULL, gcc_dwarf_w13_mips, gcc_dwarf_w13_mips, LLDB_INVALID_REGNUM, gdb_w13_mips),
- DEFINE_MSA (w14, NULL, gcc_dwarf_w14_mips, gcc_dwarf_w14_mips, LLDB_INVALID_REGNUM, gdb_w14_mips),
- DEFINE_MSA (w15, NULL, gcc_dwarf_w15_mips, gcc_dwarf_w15_mips, LLDB_INVALID_REGNUM, gdb_w15_mips),
- DEFINE_MSA (w16, NULL, gcc_dwarf_w16_mips, gcc_dwarf_w16_mips, LLDB_INVALID_REGNUM, gdb_w16_mips),
- DEFINE_MSA (w17, NULL, gcc_dwarf_w17_mips, gcc_dwarf_w17_mips, LLDB_INVALID_REGNUM, gdb_w17_mips),
- DEFINE_MSA (w18, NULL, gcc_dwarf_w18_mips, gcc_dwarf_w18_mips, LLDB_INVALID_REGNUM, gdb_w18_mips),
- DEFINE_MSA (w19, NULL, gcc_dwarf_w19_mips, gcc_dwarf_w19_mips, LLDB_INVALID_REGNUM, gdb_w19_mips),
- DEFINE_MSA (w20, NULL, gcc_dwarf_w10_mips, gcc_dwarf_w20_mips, LLDB_INVALID_REGNUM, gdb_w20_mips),
- DEFINE_MSA (w21, NULL, gcc_dwarf_w21_mips, gcc_dwarf_w21_mips, LLDB_INVALID_REGNUM, gdb_w21_mips),
- DEFINE_MSA (w22, NULL, gcc_dwarf_w22_mips, gcc_dwarf_w22_mips, LLDB_INVALID_REGNUM, gdb_w22_mips),
- DEFINE_MSA (w23, NULL, gcc_dwarf_w23_mips, gcc_dwarf_w23_mips, LLDB_INVALID_REGNUM, gdb_w23_mips),
- DEFINE_MSA (w24, NULL, gcc_dwarf_w24_mips, gcc_dwarf_w24_mips, LLDB_INVALID_REGNUM, gdb_w24_mips),
- DEFINE_MSA (w25, NULL, gcc_dwarf_w25_mips, gcc_dwarf_w25_mips, LLDB_INVALID_REGNUM, gdb_w25_mips),
- DEFINE_MSA (w26, NULL, gcc_dwarf_w26_mips, gcc_dwarf_w26_mips, LLDB_INVALID_REGNUM, gdb_w26_mips),
- DEFINE_MSA (w27, NULL, gcc_dwarf_w27_mips, gcc_dwarf_w27_mips, LLDB_INVALID_REGNUM, gdb_w27_mips),
- DEFINE_MSA (w28, NULL, gcc_dwarf_w28_mips, gcc_dwarf_w28_mips, LLDB_INVALID_REGNUM, gdb_w28_mips),
- DEFINE_MSA (w29, NULL, gcc_dwarf_w29_mips, gcc_dwarf_w29_mips, LLDB_INVALID_REGNUM, gdb_w29_mips),
- DEFINE_MSA (w30, NULL, gcc_dwarf_w30_mips, gcc_dwarf_w30_mips, LLDB_INVALID_REGNUM, gdb_w30_mips),
- DEFINE_MSA (w31, NULL, gcc_dwarf_w31_mips, gcc_dwarf_w31_mips, LLDB_INVALID_REGNUM, gdb_w31_mips),
- DEFINE_MSA_INFO (mcsr, NULL, gcc_dwarf_mcsr_mips, gcc_dwarf_mcsr_mips, LLDB_INVALID_REGNUM, gdb_mcsr_mips),
- DEFINE_MSA_INFO (mir, NULL, gcc_dwarf_mir_mips, gcc_dwarf_mir_mips, LLDB_INVALID_REGNUM, gdb_mir_mips),
- DEFINE_MSA_INFO (fcsr, NULL, gcc_dwarf_fcsr_mips, gcc_dwarf_fcsr_mips, LLDB_INVALID_REGNUM, gdb_fcsr_mips),
- DEFINE_MSA_INFO (fir, NULL, gcc_dwarf_fir_mips, gcc_dwarf_fir_mips, LLDB_INVALID_REGNUM, gdb_fir_mips),
- DEFINE_MSA_INFO (config5, NULL, gcc_dwarf_config5_mips, gcc_dwarf_config5_mips, LLDB_INVALID_REGNUM, gdb_config5_mips)
+ DEFINE_GPR (zero, "zero", dwarf_zero_mips, dwarf_zero_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r1, "at", dwarf_r1_mips, dwarf_r1_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r2, nullptr, dwarf_r2_mips, dwarf_r2_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r3, nullptr, dwarf_r3_mips, dwarf_r3_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r4, nullptr, dwarf_r4_mips, dwarf_r4_mips, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r5, nullptr, dwarf_r5_mips, dwarf_r5_mips, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r6, nullptr, dwarf_r6_mips, dwarf_r6_mips, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r7, nullptr, dwarf_r7_mips, dwarf_r7_mips, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r8, nullptr, dwarf_r8_mips, dwarf_r8_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r9, nullptr, dwarf_r9_mips, dwarf_r9_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r10, nullptr, dwarf_r10_mips, dwarf_r10_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r11, nullptr, dwarf_r11_mips, dwarf_r11_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r12, nullptr, dwarf_r12_mips, dwarf_r12_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r13, nullptr, dwarf_r13_mips, dwarf_r13_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r14, nullptr, dwarf_r14_mips, dwarf_r14_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r15, nullptr, dwarf_r15_mips, dwarf_r15_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r16, nullptr, dwarf_r16_mips, dwarf_r16_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r17, nullptr, dwarf_r17_mips, dwarf_r17_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r18, nullptr, dwarf_r18_mips, dwarf_r18_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r19, nullptr, dwarf_r19_mips, dwarf_r19_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r20, nullptr, dwarf_r20_mips, dwarf_r20_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r21, nullptr, dwarf_r21_mips, dwarf_r21_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r22, nullptr, dwarf_r22_mips, dwarf_r22_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r23, nullptr, dwarf_r23_mips, dwarf_r23_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r24, nullptr, dwarf_r24_mips, dwarf_r24_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r25, nullptr, dwarf_r25_mips, dwarf_r25_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r26, nullptr, dwarf_r26_mips, dwarf_r26_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r27, nullptr, dwarf_r27_mips, dwarf_r27_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (gp, "gp", dwarf_gp_mips, dwarf_gp_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (sp, "sp", dwarf_sp_mips, dwarf_sp_mips, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (r30, "fp", dwarf_r30_mips, dwarf_r30_mips, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (ra, "ra", dwarf_ra_mips, dwarf_ra_mips, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (sr, "status", dwarf_sr_mips, dwarf_sr_mips, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (mullo, nullptr, dwarf_lo_mips, dwarf_lo_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (mulhi, nullptr, dwarf_hi_mips, dwarf_hi_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (badvaddr, nullptr, dwarf_bad_mips, dwarf_bad_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (cause, nullptr, dwarf_cause_mips, dwarf_cause_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (pc, nullptr, dwarf_pc_mips, dwarf_pc_mips, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ DEFINE_GPR (config5, nullptr, dwarf_config5_mips, dwarf_config5_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f0, nullptr, dwarf_f0_mips, dwarf_f0_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f1, nullptr, dwarf_f1_mips, dwarf_f1_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f2, nullptr, dwarf_f2_mips, dwarf_f2_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f3, nullptr, dwarf_f3_mips, dwarf_f3_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f4, nullptr, dwarf_f4_mips, dwarf_f4_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f5, nullptr, dwarf_f5_mips, dwarf_f5_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f6, nullptr, dwarf_f6_mips, dwarf_f6_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f7, nullptr, dwarf_f7_mips, dwarf_f7_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f8, nullptr, dwarf_f8_mips, dwarf_f8_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f9, nullptr, dwarf_f9_mips, dwarf_f9_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f10, nullptr, dwarf_f10_mips, dwarf_f10_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f11, nullptr, dwarf_f11_mips, dwarf_f11_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f12, nullptr, dwarf_f12_mips, dwarf_f12_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f13, nullptr, dwarf_f13_mips, dwarf_f13_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f14, nullptr, dwarf_f14_mips, dwarf_f14_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f15, nullptr, dwarf_f15_mips, dwarf_f15_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f16, nullptr, dwarf_f16_mips, dwarf_f16_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f17, nullptr, dwarf_f17_mips, dwarf_f17_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f18, nullptr, dwarf_f18_mips, dwarf_f18_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f19, nullptr, dwarf_f19_mips, dwarf_f19_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f20, nullptr, dwarf_f20_mips, dwarf_f20_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f21, nullptr, dwarf_f21_mips, dwarf_f21_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f22, nullptr, dwarf_f22_mips, dwarf_f22_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f23, nullptr, dwarf_f23_mips, dwarf_f23_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f24, nullptr, dwarf_f24_mips, dwarf_f24_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f25, nullptr, dwarf_f25_mips, dwarf_f25_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f26, nullptr, dwarf_f26_mips, dwarf_f26_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f27, nullptr, dwarf_f27_mips, dwarf_f27_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f28, nullptr, dwarf_f28_mips, dwarf_f28_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f29, nullptr, dwarf_f29_mips, dwarf_f29_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f30, nullptr, dwarf_f30_mips, dwarf_f30_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f31, nullptr, dwarf_f31_mips, dwarf_f31_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (fcsr, nullptr, dwarf_fcsr_mips, dwarf_fcsr_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (fir, nullptr, dwarf_fir_mips, dwarf_fir_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (config5, nullptr, dwarf_config5_mips, dwarf_config5_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w0, nullptr, dwarf_w0_mips, dwarf_w0_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w1, nullptr, dwarf_w1_mips, dwarf_w1_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w2, nullptr, dwarf_w2_mips, dwarf_w2_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w3, nullptr, dwarf_w3_mips, dwarf_w3_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w4, nullptr, dwarf_w4_mips, dwarf_w4_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w5, nullptr, dwarf_w5_mips, dwarf_w5_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w6, nullptr, dwarf_w6_mips, dwarf_w6_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w7, nullptr, dwarf_w7_mips, dwarf_w7_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w8, nullptr, dwarf_w8_mips, dwarf_w8_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w9, nullptr, dwarf_w9_mips, dwarf_w9_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w10, nullptr, dwarf_w10_mips, dwarf_w10_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w11, nullptr, dwarf_w11_mips, dwarf_w11_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w12, nullptr, dwarf_w12_mips, dwarf_w12_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w13, nullptr, dwarf_w13_mips, dwarf_w13_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w14, nullptr, dwarf_w14_mips, dwarf_w14_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w15, nullptr, dwarf_w15_mips, dwarf_w15_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w16, nullptr, dwarf_w16_mips, dwarf_w16_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w17, nullptr, dwarf_w17_mips, dwarf_w17_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w18, nullptr, dwarf_w18_mips, dwarf_w18_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w19, nullptr, dwarf_w19_mips, dwarf_w19_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w20, nullptr, dwarf_w10_mips, dwarf_w20_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w21, nullptr, dwarf_w21_mips, dwarf_w21_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w22, nullptr, dwarf_w22_mips, dwarf_w22_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w23, nullptr, dwarf_w23_mips, dwarf_w23_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w24, nullptr, dwarf_w24_mips, dwarf_w24_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w25, nullptr, dwarf_w25_mips, dwarf_w25_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w26, nullptr, dwarf_w26_mips, dwarf_w26_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w27, nullptr, dwarf_w27_mips, dwarf_w27_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w28, nullptr, dwarf_w28_mips, dwarf_w28_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w29, nullptr, dwarf_w29_mips, dwarf_w29_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w30, nullptr, dwarf_w30_mips, dwarf_w30_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w31, nullptr, dwarf_w31_mips, dwarf_w31_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (mcsr, nullptr, dwarf_mcsr_mips, dwarf_mcsr_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (mir, nullptr, dwarf_mir_mips, dwarf_mir_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (fcsr, nullptr, dwarf_fcsr_mips, dwarf_fcsr_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (fir, nullptr, dwarf_fir_mips, dwarf_fir_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (config5, nullptr, dwarf_config5_mips, dwarf_config5_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM)
};
+
static_assert((sizeof(g_register_infos_mips) / sizeof(g_register_infos_mips[0])) == k_num_registers_mips,
"g_register_infos_mips has wrong number of register infos");
diff --git a/source/Plugins/Process/Utility/RegisterInfos_mips64.h b/source/Plugins/Process/Utility/RegisterInfos_mips64.h
index 101842e66d49..45853d7931dd 100644
--- a/source/Plugins/Process/Utility/RegisterInfos_mips64.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_mips64.h
@@ -1,15 +1,21 @@
-//===-- RegisterInfos_mips64.h ---------------------------------*- C++ -*-===//
+//===-- RegisterInfos_mips64.h ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
-#include "llvm/Support/Compiler.h"
+//===----------------------------------------------------------------------===//
+// C Includes
#include <stddef.h>
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/Support/Compiler.h"
+
+// Project includes
+
#ifdef DECLARE_REGISTER_INFOS_MIPS64_STRUCT
// Computes the offset of the given GPR in the user data area.
@@ -32,7 +38,7 @@
(LLVM_EXTENSION offsetof(UserArea, msa) + \
LLVM_EXTENSION offsetof(MSA_linux_mips, regname))
-// RegisterKind: GCC, DWARF, Generic, GDB, LLDB
+// RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB
// Note that the size and offset will be updated by platform-specific classes.
#ifdef LINUX_MIPS64
@@ -64,161 +70,160 @@
static RegisterInfo
g_register_infos_mips64[] =
{
- // General purpose registers. GCC, DWARF, Generic, GDB
+ // General purpose registers. EH_Frame, DWARF, Generic, Process Plugin
#ifndef LINUX_MIPS64
- DEFINE_GPR(zero, "r0", gcc_dwarf_zero_mips64, gcc_dwarf_zero_mips64, LLDB_INVALID_REGNUM, gdb_zero_mips64),
- DEFINE_GPR(r1, NULL, gcc_dwarf_r1_mips64, gcc_dwarf_r1_mips64, LLDB_INVALID_REGNUM, gdb_r1_mips64),
- DEFINE_GPR(r2, NULL, gcc_dwarf_r2_mips64, gcc_dwarf_r2_mips64, LLDB_INVALID_REGNUM, gdb_r2_mips64),
- DEFINE_GPR(r3, NULL, gcc_dwarf_r3_mips64, gcc_dwarf_r3_mips64, LLDB_INVALID_REGNUM, gdb_r3_mips64),
- DEFINE_GPR(r4, NULL, gcc_dwarf_r4_mips64, gcc_dwarf_r4_mips64, LLDB_REGNUM_GENERIC_ARG1, gdb_r4_mips64),
- DEFINE_GPR(r5, NULL, gcc_dwarf_r5_mips64, gcc_dwarf_r5_mips64, LLDB_REGNUM_GENERIC_ARG2, gdb_r5_mips64),
- DEFINE_GPR(r6, NULL, gcc_dwarf_r6_mips64, gcc_dwarf_r6_mips64, LLDB_REGNUM_GENERIC_ARG3, gdb_r6_mips64),
- DEFINE_GPR(r7, NULL, gcc_dwarf_r7_mips64, gcc_dwarf_r7_mips64, LLDB_REGNUM_GENERIC_ARG4, gdb_r7_mips64),
- DEFINE_GPR(r8, NULL, gcc_dwarf_r8_mips64, gcc_dwarf_r8_mips64, LLDB_REGNUM_GENERIC_ARG5, gdb_r8_mips64),
- DEFINE_GPR(r9, NULL, gcc_dwarf_r9_mips64, gcc_dwarf_r9_mips64, LLDB_REGNUM_GENERIC_ARG6, gdb_r9_mips64),
- DEFINE_GPR(r10, NULL, gcc_dwarf_r10_mips64, gcc_dwarf_r10_mips64, LLDB_REGNUM_GENERIC_ARG7, gdb_r10_mips64),
- DEFINE_GPR(r11, NULL, gcc_dwarf_r11_mips64, gcc_dwarf_r11_mips64, LLDB_REGNUM_GENERIC_ARG8, gdb_r11_mips64),
- DEFINE_GPR(r12, NULL, gcc_dwarf_r12_mips64, gcc_dwarf_r12_mips64, LLDB_INVALID_REGNUM, gdb_r12_mips64),
- DEFINE_GPR(r13, NULL, gcc_dwarf_r13_mips64, gcc_dwarf_r13_mips64, LLDB_INVALID_REGNUM, gdb_r13_mips64),
- DEFINE_GPR(r14, NULL, gcc_dwarf_r14_mips64, gcc_dwarf_r14_mips64, LLDB_INVALID_REGNUM, gdb_r14_mips64),
- DEFINE_GPR(r15, NULL, gcc_dwarf_r15_mips64, gcc_dwarf_r15_mips64, LLDB_INVALID_REGNUM, gdb_r15_mips64),
- DEFINE_GPR(r16, NULL, gcc_dwarf_r16_mips64, gcc_dwarf_r16_mips64, LLDB_INVALID_REGNUM, gdb_r16_mips64),
- DEFINE_GPR(r17, NULL, gcc_dwarf_r17_mips64, gcc_dwarf_r17_mips64, LLDB_INVALID_REGNUM, gdb_r17_mips64),
- DEFINE_GPR(r18, NULL, gcc_dwarf_r18_mips64, gcc_dwarf_r18_mips64, LLDB_INVALID_REGNUM, gdb_r18_mips64),
- DEFINE_GPR(r19, NULL, gcc_dwarf_r19_mips64, gcc_dwarf_r19_mips64, LLDB_INVALID_REGNUM, gdb_r19_mips64),
- DEFINE_GPR(r20, NULL, gcc_dwarf_r20_mips64, gcc_dwarf_r20_mips64, LLDB_INVALID_REGNUM, gdb_r20_mips64),
- DEFINE_GPR(r21, NULL, gcc_dwarf_r21_mips64, gcc_dwarf_r21_mips64, LLDB_INVALID_REGNUM, gdb_r21_mips64),
- DEFINE_GPR(r22, NULL, gcc_dwarf_r22_mips64, gcc_dwarf_r22_mips64, LLDB_INVALID_REGNUM, gdb_r22_mips64),
- DEFINE_GPR(r23, NULL, gcc_dwarf_r23_mips64, gcc_dwarf_r23_mips64, LLDB_INVALID_REGNUM, gdb_r23_mips64),
- DEFINE_GPR(r24, NULL, gcc_dwarf_r24_mips64, gcc_dwarf_r24_mips64, LLDB_INVALID_REGNUM, gdb_r24_mips64),
- DEFINE_GPR(r25, NULL, gcc_dwarf_r25_mips64, gcc_dwarf_r25_mips64, LLDB_INVALID_REGNUM, gdb_r25_mips64),
- DEFINE_GPR(r26, NULL, gcc_dwarf_r26_mips64, gcc_dwarf_r26_mips64, LLDB_INVALID_REGNUM, gdb_r26_mips64),
- DEFINE_GPR(r27, NULL, gcc_dwarf_r27_mips64, gcc_dwarf_r27_mips64, LLDB_INVALID_REGNUM, gdb_r27_mips64),
- DEFINE_GPR(gp, "r28", gcc_dwarf_gp_mips64, gcc_dwarf_gp_mips64, LLDB_INVALID_REGNUM, gdb_gp_mips64),
- DEFINE_GPR(sp, "r29", gcc_dwarf_sp_mips64, gcc_dwarf_sp_mips64, LLDB_REGNUM_GENERIC_SP, gdb_sp_mips64),
- DEFINE_GPR(r30, NULL, gcc_dwarf_r30_mips64, gcc_dwarf_r30_mips64, LLDB_REGNUM_GENERIC_FP, gdb_r30_mips64),
- DEFINE_GPR(ra, "r31", gcc_dwarf_ra_mips64, gcc_dwarf_ra_mips64, LLDB_REGNUM_GENERIC_RA, gdb_ra_mips64),
- DEFINE_GPR(sr, NULL, gcc_dwarf_sr_mips64, gcc_dwarf_sr_mips64, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
- DEFINE_GPR(mullo, NULL, gcc_dwarf_lo_mips64, gcc_dwarf_lo_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(mulhi, NULL, gcc_dwarf_hi_mips64, gcc_dwarf_hi_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(badvaddr, NULL, gcc_dwarf_bad_mips64, gcc_dwarf_bad_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(cause, NULL, gcc_dwarf_cause_mips64, gcc_dwarf_cause_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(pc, "pc", gcc_dwarf_pc_mips64, gcc_dwarf_pc_mips64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
- DEFINE_GPR(ic, NULL, gcc_dwarf_ic_mips64, gcc_dwarf_ic_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(dummy, NULL, gcc_dwarf_dummy_mips64, gcc_dwarf_dummy_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(zero, "r0", dwarf_zero_mips64, dwarf_zero_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r1, nullptr, dwarf_r1_mips64, dwarf_r1_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r2, nullptr, dwarf_r2_mips64, dwarf_r2_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r3, nullptr, dwarf_r3_mips64, dwarf_r3_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r4, nullptr, dwarf_r4_mips64, dwarf_r4_mips64, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r5, nullptr, dwarf_r5_mips64, dwarf_r5_mips64, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r6, nullptr, dwarf_r6_mips64, dwarf_r6_mips64, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r7, nullptr, dwarf_r7_mips64, dwarf_r7_mips64, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r8, nullptr, dwarf_r8_mips64, dwarf_r8_mips64, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r9, nullptr, dwarf_r9_mips64, dwarf_r9_mips64, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r10, nullptr, dwarf_r10_mips64, dwarf_r10_mips64, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r11, nullptr, dwarf_r11_mips64, dwarf_r11_mips64, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r12, nullptr, dwarf_r12_mips64, dwarf_r12_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r13, nullptr, dwarf_r13_mips64, dwarf_r13_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r14, nullptr, dwarf_r14_mips64, dwarf_r14_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r15, nullptr, dwarf_r15_mips64, dwarf_r15_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r16, nullptr, dwarf_r16_mips64, dwarf_r16_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r17, nullptr, dwarf_r17_mips64, dwarf_r17_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r18, nullptr, dwarf_r18_mips64, dwarf_r18_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r19, nullptr, dwarf_r19_mips64, dwarf_r19_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r20, nullptr, dwarf_r20_mips64, dwarf_r20_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r21, nullptr, dwarf_r21_mips64, dwarf_r21_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r22, nullptr, dwarf_r22_mips64, dwarf_r22_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r23, nullptr, dwarf_r23_mips64, dwarf_r23_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r24, nullptr, dwarf_r24_mips64, dwarf_r24_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r25, nullptr, dwarf_r25_mips64, dwarf_r25_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r26, nullptr, dwarf_r26_mips64, dwarf_r26_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r27, nullptr, dwarf_r27_mips64, dwarf_r27_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(gp, "r28", dwarf_gp_mips64, dwarf_gp_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(sp, "r29", dwarf_sp_mips64, dwarf_sp_mips64, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r30, nullptr, dwarf_r30_mips64, dwarf_r30_mips64, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ra, "r31", dwarf_ra_mips64, dwarf_ra_mips64, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(sr, nullptr, dwarf_sr_mips64, dwarf_sr_mips64, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(mullo, nullptr, dwarf_lo_mips64, dwarf_lo_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(mulhi, nullptr, dwarf_hi_mips64, dwarf_hi_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(badvaddr, nullptr, dwarf_bad_mips64, dwarf_bad_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(cause, nullptr, dwarf_cause_mips64, dwarf_cause_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(pc, "pc", dwarf_pc_mips64, dwarf_pc_mips64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ic, nullptr, dwarf_ic_mips64, dwarf_ic_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(dummy, nullptr, dwarf_dummy_mips64, dwarf_dummy_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
#else
-
- DEFINE_GPR(zero, "r0", gcc_dwarf_zero_mips64, gcc_dwarf_zero_mips64, LLDB_INVALID_REGNUM, gdb_zero_mips64),
- DEFINE_GPR(r1, NULL, gcc_dwarf_r1_mips64, gcc_dwarf_r1_mips64, LLDB_INVALID_REGNUM, gdb_r1_mips64),
- DEFINE_GPR(r2, NULL, gcc_dwarf_r2_mips64, gcc_dwarf_r2_mips64, LLDB_INVALID_REGNUM, gdb_r2_mips64),
- DEFINE_GPR(r3, NULL, gcc_dwarf_r3_mips64, gcc_dwarf_r3_mips64, LLDB_INVALID_REGNUM, gdb_r3_mips64),
- DEFINE_GPR(r4, NULL, gcc_dwarf_r4_mips64, gcc_dwarf_r4_mips64, LLDB_REGNUM_GENERIC_ARG1, gdb_r4_mips64),
- DEFINE_GPR(r5, NULL, gcc_dwarf_r5_mips64, gcc_dwarf_r5_mips64, LLDB_REGNUM_GENERIC_ARG2, gdb_r5_mips64),
- DEFINE_GPR(r6, NULL, gcc_dwarf_r6_mips64, gcc_dwarf_r6_mips64, LLDB_REGNUM_GENERIC_ARG3, gdb_r6_mips64),
- DEFINE_GPR(r7, NULL, gcc_dwarf_r7_mips64, gcc_dwarf_r7_mips64, LLDB_REGNUM_GENERIC_ARG4, gdb_r7_mips64),
- DEFINE_GPR(r8, NULL, gcc_dwarf_r8_mips64, gcc_dwarf_r8_mips64, LLDB_REGNUM_GENERIC_ARG5, gdb_r8_mips64),
- DEFINE_GPR(r9, NULL, gcc_dwarf_r9_mips64, gcc_dwarf_r9_mips64, LLDB_REGNUM_GENERIC_ARG6, gdb_r9_mips64),
- DEFINE_GPR(r10, NULL, gcc_dwarf_r10_mips64, gcc_dwarf_r10_mips64, LLDB_REGNUM_GENERIC_ARG7, gdb_r10_mips64),
- DEFINE_GPR(r11, NULL, gcc_dwarf_r11_mips64, gcc_dwarf_r11_mips64, LLDB_REGNUM_GENERIC_ARG8, gdb_r11_mips64),
- DEFINE_GPR(r12, NULL, gcc_dwarf_r12_mips64, gcc_dwarf_r12_mips64, LLDB_INVALID_REGNUM, gdb_r12_mips64),
- DEFINE_GPR(r13, NULL, gcc_dwarf_r13_mips64, gcc_dwarf_r13_mips64, LLDB_INVALID_REGNUM, gdb_r13_mips64),
- DEFINE_GPR(r14, NULL, gcc_dwarf_r14_mips64, gcc_dwarf_r14_mips64, LLDB_INVALID_REGNUM, gdb_r14_mips64),
- DEFINE_GPR(r15, NULL, gcc_dwarf_r15_mips64, gcc_dwarf_r15_mips64, LLDB_INVALID_REGNUM, gdb_r15_mips64),
- DEFINE_GPR(r16, NULL, gcc_dwarf_r16_mips64, gcc_dwarf_r16_mips64, LLDB_INVALID_REGNUM, gdb_r16_mips64),
- DEFINE_GPR(r17, NULL, gcc_dwarf_r17_mips64, gcc_dwarf_r17_mips64, LLDB_INVALID_REGNUM, gdb_r17_mips64),
- DEFINE_GPR(r18, NULL, gcc_dwarf_r18_mips64, gcc_dwarf_r18_mips64, LLDB_INVALID_REGNUM, gdb_r18_mips64),
- DEFINE_GPR(r19, NULL, gcc_dwarf_r19_mips64, gcc_dwarf_r19_mips64, LLDB_INVALID_REGNUM, gdb_r19_mips64),
- DEFINE_GPR(r20, NULL, gcc_dwarf_r20_mips64, gcc_dwarf_r20_mips64, LLDB_INVALID_REGNUM, gdb_r20_mips64),
- DEFINE_GPR(r21, NULL, gcc_dwarf_r21_mips64, gcc_dwarf_r21_mips64, LLDB_INVALID_REGNUM, gdb_r21_mips64),
- DEFINE_GPR(r22, NULL, gcc_dwarf_r22_mips64, gcc_dwarf_r22_mips64, LLDB_INVALID_REGNUM, gdb_r22_mips64),
- DEFINE_GPR(r23, NULL, gcc_dwarf_r23_mips64, gcc_dwarf_r23_mips64, LLDB_INVALID_REGNUM, gdb_r23_mips64),
- DEFINE_GPR(r24, NULL, gcc_dwarf_r24_mips64, gcc_dwarf_r24_mips64, LLDB_INVALID_REGNUM, gdb_r24_mips64),
- DEFINE_GPR(r25, NULL, gcc_dwarf_r25_mips64, gcc_dwarf_r25_mips64, LLDB_INVALID_REGNUM, gdb_r25_mips64),
- DEFINE_GPR(r26, NULL, gcc_dwarf_r26_mips64, gcc_dwarf_r26_mips64, LLDB_INVALID_REGNUM, gdb_r26_mips64),
- DEFINE_GPR(r27, NULL, gcc_dwarf_r27_mips64, gcc_dwarf_r27_mips64, LLDB_INVALID_REGNUM, gdb_r27_mips64),
- DEFINE_GPR(gp, "r28", gcc_dwarf_gp_mips64, gcc_dwarf_gp_mips64, LLDB_INVALID_REGNUM, gdb_gp_mips64),
- DEFINE_GPR(sp, "r29", gcc_dwarf_sp_mips64, gcc_dwarf_sp_mips64, LLDB_REGNUM_GENERIC_SP, gdb_sp_mips64),
- DEFINE_GPR(r30, NULL, gcc_dwarf_r30_mips64, gcc_dwarf_r30_mips64, LLDB_REGNUM_GENERIC_FP, gdb_r30_mips64),
- DEFINE_GPR(ra, "r31", gcc_dwarf_ra_mips64, gcc_dwarf_ra_mips64, LLDB_REGNUM_GENERIC_RA, gdb_ra_mips64),
- DEFINE_GPR_INFO(sr, NULL, gcc_dwarf_sr_mips64, gcc_dwarf_sr_mips64, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
- DEFINE_GPR(mullo, NULL, gcc_dwarf_lo_mips64, gcc_dwarf_lo_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(mulhi, NULL, gcc_dwarf_hi_mips64, gcc_dwarf_hi_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(badvaddr, NULL, gcc_dwarf_bad_mips64, gcc_dwarf_bad_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR_INFO(cause, NULL, gcc_dwarf_cause_mips64, gcc_dwarf_cause_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_GPR(pc, "pc", gcc_dwarf_pc_mips64, gcc_dwarf_pc_mips64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
- DEFINE_GPR_INFO(config5, NULL, gcc_dwarf_config5_mips64, gcc_dwarf_config5_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
- DEFINE_FPR (f0, NULL, gcc_dwarf_f0_mips64, gcc_dwarf_f0_mips64, LLDB_INVALID_REGNUM, gdb_f0_mips64),
- DEFINE_FPR (f1, NULL, gcc_dwarf_f1_mips64, gcc_dwarf_f1_mips64, LLDB_INVALID_REGNUM, gdb_f1_mips64),
- DEFINE_FPR (f2, NULL, gcc_dwarf_f2_mips64, gcc_dwarf_f2_mips64, LLDB_INVALID_REGNUM, gdb_f2_mips64),
- DEFINE_FPR (f3, NULL, gcc_dwarf_f3_mips64, gcc_dwarf_f3_mips64, LLDB_INVALID_REGNUM, gdb_f3_mips64),
- DEFINE_FPR (f4, NULL, gcc_dwarf_f4_mips64, gcc_dwarf_f4_mips64, LLDB_INVALID_REGNUM, gdb_f4_mips64),
- DEFINE_FPR (f5, NULL, gcc_dwarf_f5_mips64, gcc_dwarf_f5_mips64, LLDB_INVALID_REGNUM, gdb_f5_mips64),
- DEFINE_FPR (f6, NULL, gcc_dwarf_f6_mips64, gcc_dwarf_f6_mips64, LLDB_INVALID_REGNUM, gdb_f6_mips64),
- DEFINE_FPR (f7, NULL, gcc_dwarf_f7_mips64, gcc_dwarf_f7_mips64, LLDB_INVALID_REGNUM, gdb_f7_mips64),
- DEFINE_FPR (f8, NULL, gcc_dwarf_f8_mips64, gcc_dwarf_f8_mips64, LLDB_INVALID_REGNUM, gdb_f8_mips64),
- DEFINE_FPR (f9, NULL, gcc_dwarf_f9_mips64, gcc_dwarf_f9_mips64, LLDB_INVALID_REGNUM, gdb_f9_mips64),
- DEFINE_FPR (f10, NULL, gcc_dwarf_f10_mips64, gcc_dwarf_f10_mips64, LLDB_INVALID_REGNUM, gdb_f10_mips64),
- DEFINE_FPR (f11, NULL, gcc_dwarf_f11_mips64, gcc_dwarf_f11_mips64, LLDB_INVALID_REGNUM, gdb_f11_mips64),
- DEFINE_FPR (f12, NULL, gcc_dwarf_f12_mips64, gcc_dwarf_f12_mips64, LLDB_INVALID_REGNUM, gdb_f12_mips64),
- DEFINE_FPR (f13, NULL, gcc_dwarf_f13_mips64, gcc_dwarf_f13_mips64, LLDB_INVALID_REGNUM, gdb_f13_mips64),
- DEFINE_FPR (f14, NULL, gcc_dwarf_f14_mips64, gcc_dwarf_f14_mips64, LLDB_INVALID_REGNUM, gdb_f14_mips64),
- DEFINE_FPR (f15, NULL, gcc_dwarf_f15_mips64, gcc_dwarf_f15_mips64, LLDB_INVALID_REGNUM, gdb_f15_mips64),
- DEFINE_FPR (f16, NULL, gcc_dwarf_f16_mips64, gcc_dwarf_f16_mips64, LLDB_INVALID_REGNUM, gdb_f16_mips64),
- DEFINE_FPR (f17, NULL, gcc_dwarf_f17_mips64, gcc_dwarf_f17_mips64, LLDB_INVALID_REGNUM, gdb_f17_mips64),
- DEFINE_FPR (f18, NULL, gcc_dwarf_f18_mips64, gcc_dwarf_f18_mips64, LLDB_INVALID_REGNUM, gdb_f18_mips64),
- DEFINE_FPR (f19, NULL, gcc_dwarf_f19_mips64, gcc_dwarf_f19_mips64, LLDB_INVALID_REGNUM, gdb_f19_mips64),
- DEFINE_FPR (f20, NULL, gcc_dwarf_f20_mips64, gcc_dwarf_f20_mips64, LLDB_INVALID_REGNUM, gdb_f20_mips64),
- DEFINE_FPR (f21, NULL, gcc_dwarf_f21_mips64, gcc_dwarf_f21_mips64, LLDB_INVALID_REGNUM, gdb_f21_mips64),
- DEFINE_FPR (f22, NULL, gcc_dwarf_f22_mips64, gcc_dwarf_f22_mips64, LLDB_INVALID_REGNUM, gdb_f22_mips64),
- DEFINE_FPR (f23, NULL, gcc_dwarf_f23_mips64, gcc_dwarf_f23_mips64, LLDB_INVALID_REGNUM, gdb_f23_mips64),
- DEFINE_FPR (f24, NULL, gcc_dwarf_f24_mips64, gcc_dwarf_f24_mips64, LLDB_INVALID_REGNUM, gdb_f24_mips64),
- DEFINE_FPR (f25, NULL, gcc_dwarf_f25_mips64, gcc_dwarf_f25_mips64, LLDB_INVALID_REGNUM, gdb_f25_mips64),
- DEFINE_FPR (f26, NULL, gcc_dwarf_f26_mips64, gcc_dwarf_f26_mips64, LLDB_INVALID_REGNUM, gdb_f26_mips64),
- DEFINE_FPR (f27, NULL, gcc_dwarf_f27_mips64, gcc_dwarf_f27_mips64, LLDB_INVALID_REGNUM, gdb_f27_mips64),
- DEFINE_FPR (f28, NULL, gcc_dwarf_f28_mips64, gcc_dwarf_f28_mips64, LLDB_INVALID_REGNUM, gdb_f28_mips64),
- DEFINE_FPR (f29, NULL, gcc_dwarf_f29_mips64, gcc_dwarf_f29_mips64, LLDB_INVALID_REGNUM, gdb_f29_mips64),
- DEFINE_FPR (f30, NULL, gcc_dwarf_f30_mips64, gcc_dwarf_f30_mips64, LLDB_INVALID_REGNUM, gdb_f30_mips64),
- DEFINE_FPR (f31, NULL, gcc_dwarf_f31_mips64, gcc_dwarf_f31_mips64, LLDB_INVALID_REGNUM, gdb_f31_mips64),
- DEFINE_FPR (fcsr, NULL, gcc_dwarf_fcsr_mips64, gcc_dwarf_fcsr_mips64, LLDB_INVALID_REGNUM, gdb_fcsr_mips64),
- DEFINE_FPR (fir, NULL, gcc_dwarf_fir_mips64, gcc_dwarf_fir_mips64, LLDB_INVALID_REGNUM, gdb_fir_mips64),
- DEFINE_FPR (config5, NULL, gcc_dwarf_config5_mips64, gcc_dwarf_config5_mips64, LLDB_INVALID_REGNUM, gdb_config5_mips64),
- DEFINE_MSA (w0, NULL, gcc_dwarf_w0_mips64, gcc_dwarf_w0_mips64, LLDB_INVALID_REGNUM, gdb_w0_mips64),
- DEFINE_MSA (w1, NULL, gcc_dwarf_w1_mips64, gcc_dwarf_w1_mips64, LLDB_INVALID_REGNUM, gdb_w1_mips64),
- DEFINE_MSA (w2, NULL, gcc_dwarf_w2_mips64, gcc_dwarf_w2_mips64, LLDB_INVALID_REGNUM, gdb_w2_mips64),
- DEFINE_MSA (w3, NULL, gcc_dwarf_w3_mips64, gcc_dwarf_w3_mips64, LLDB_INVALID_REGNUM, gdb_w3_mips64),
- DEFINE_MSA (w4, NULL, gcc_dwarf_w4_mips64, gcc_dwarf_w4_mips64, LLDB_INVALID_REGNUM, gdb_w4_mips64),
- DEFINE_MSA (w5, NULL, gcc_dwarf_w5_mips64, gcc_dwarf_w5_mips64, LLDB_INVALID_REGNUM, gdb_w5_mips64),
- DEFINE_MSA (w6, NULL, gcc_dwarf_w6_mips64, gcc_dwarf_w6_mips64, LLDB_INVALID_REGNUM, gdb_w6_mips64),
- DEFINE_MSA (w7, NULL, gcc_dwarf_w7_mips64, gcc_dwarf_w7_mips64, LLDB_INVALID_REGNUM, gdb_w7_mips64),
- DEFINE_MSA (w8, NULL, gcc_dwarf_w8_mips64, gcc_dwarf_w8_mips64, LLDB_INVALID_REGNUM, gdb_w8_mips64),
- DEFINE_MSA (w9, NULL, gcc_dwarf_w9_mips64, gcc_dwarf_w9_mips64, LLDB_INVALID_REGNUM, gdb_w9_mips64),
- DEFINE_MSA (w10, NULL, gcc_dwarf_w10_mips64, gcc_dwarf_w10_mips64, LLDB_INVALID_REGNUM, gdb_w10_mips64),
- DEFINE_MSA (w11, NULL, gcc_dwarf_w11_mips64, gcc_dwarf_w11_mips64, LLDB_INVALID_REGNUM, gdb_w11_mips64),
- DEFINE_MSA (w12, NULL, gcc_dwarf_w12_mips64, gcc_dwarf_w12_mips64, LLDB_INVALID_REGNUM, gdb_w12_mips64),
- DEFINE_MSA (w13, NULL, gcc_dwarf_w13_mips64, gcc_dwarf_w13_mips64, LLDB_INVALID_REGNUM, gdb_w13_mips64),
- DEFINE_MSA (w14, NULL, gcc_dwarf_w14_mips64, gcc_dwarf_w14_mips64, LLDB_INVALID_REGNUM, gdb_w14_mips64),
- DEFINE_MSA (w15, NULL, gcc_dwarf_w15_mips64, gcc_dwarf_w15_mips64, LLDB_INVALID_REGNUM, gdb_w15_mips64),
- DEFINE_MSA (w16, NULL, gcc_dwarf_w16_mips64, gcc_dwarf_w16_mips64, LLDB_INVALID_REGNUM, gdb_w16_mips64),
- DEFINE_MSA (w17, NULL, gcc_dwarf_w17_mips64, gcc_dwarf_w17_mips64, LLDB_INVALID_REGNUM, gdb_w17_mips64),
- DEFINE_MSA (w18, NULL, gcc_dwarf_w18_mips64, gcc_dwarf_w18_mips64, LLDB_INVALID_REGNUM, gdb_w18_mips64),
- DEFINE_MSA (w19, NULL, gcc_dwarf_w19_mips64, gcc_dwarf_w19_mips64, LLDB_INVALID_REGNUM, gdb_w19_mips64),
- DEFINE_MSA (w20, NULL, gcc_dwarf_w10_mips64, gcc_dwarf_w20_mips64, LLDB_INVALID_REGNUM, gdb_w20_mips64),
- DEFINE_MSA (w21, NULL, gcc_dwarf_w21_mips64, gcc_dwarf_w21_mips64, LLDB_INVALID_REGNUM, gdb_w21_mips64),
- DEFINE_MSA (w22, NULL, gcc_dwarf_w22_mips64, gcc_dwarf_w22_mips64, LLDB_INVALID_REGNUM, gdb_w22_mips64),
- DEFINE_MSA (w23, NULL, gcc_dwarf_w23_mips64, gcc_dwarf_w23_mips64, LLDB_INVALID_REGNUM, gdb_w23_mips64),
- DEFINE_MSA (w24, NULL, gcc_dwarf_w24_mips64, gcc_dwarf_w24_mips64, LLDB_INVALID_REGNUM, gdb_w24_mips64),
- DEFINE_MSA (w25, NULL, gcc_dwarf_w25_mips64, gcc_dwarf_w25_mips64, LLDB_INVALID_REGNUM, gdb_w25_mips64),
- DEFINE_MSA (w26, NULL, gcc_dwarf_w26_mips64, gcc_dwarf_w26_mips64, LLDB_INVALID_REGNUM, gdb_w26_mips64),
- DEFINE_MSA (w27, NULL, gcc_dwarf_w27_mips64, gcc_dwarf_w27_mips64, LLDB_INVALID_REGNUM, gdb_w27_mips64),
- DEFINE_MSA (w28, NULL, gcc_dwarf_w28_mips64, gcc_dwarf_w28_mips64, LLDB_INVALID_REGNUM, gdb_w28_mips64),
- DEFINE_MSA (w29, NULL, gcc_dwarf_w29_mips64, gcc_dwarf_w29_mips64, LLDB_INVALID_REGNUM, gdb_w29_mips64),
- DEFINE_MSA (w30, NULL, gcc_dwarf_w30_mips64, gcc_dwarf_w30_mips64, LLDB_INVALID_REGNUM, gdb_w30_mips64),
- DEFINE_MSA (w31, NULL, gcc_dwarf_w31_mips64, gcc_dwarf_w31_mips64, LLDB_INVALID_REGNUM, gdb_w31_mips64),
- DEFINE_MSA_INFO (mcsr, NULL, gcc_dwarf_mcsr_mips64, gcc_dwarf_mcsr_mips64, LLDB_INVALID_REGNUM, gdb_mcsr_mips64),
- DEFINE_MSA_INFO (mir, NULL, gcc_dwarf_mir_mips64, gcc_dwarf_mir_mips64, LLDB_INVALID_REGNUM, gdb_mir_mips64),
- DEFINE_MSA_INFO (fcsr, NULL, gcc_dwarf_fcsr_mips64, gcc_dwarf_fcsr_mips64, LLDB_INVALID_REGNUM, gdb_fcsr_mips64),
- DEFINE_MSA_INFO (fir, NULL, gcc_dwarf_fir_mips64, gcc_dwarf_fir_mips64, LLDB_INVALID_REGNUM, gdb_fir_mips64),
- DEFINE_MSA_INFO (config5, NULL, gcc_dwarf_config5_mips64, gcc_dwarf_config5_mips64, LLDB_INVALID_REGNUM, gdb_config5_mips64)
+ DEFINE_GPR(zero, "r0", dwarf_zero_mips64, dwarf_zero_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r1, nullptr, dwarf_r1_mips64, dwarf_r1_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r2, nullptr, dwarf_r2_mips64, dwarf_r2_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r3, nullptr, dwarf_r3_mips64, dwarf_r3_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r4, nullptr, dwarf_r4_mips64, dwarf_r4_mips64, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r5, nullptr, dwarf_r5_mips64, dwarf_r5_mips64, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r6, nullptr, dwarf_r6_mips64, dwarf_r6_mips64, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r7, nullptr, dwarf_r7_mips64, dwarf_r7_mips64, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r8, nullptr, dwarf_r8_mips64, dwarf_r8_mips64, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r9, nullptr, dwarf_r9_mips64, dwarf_r9_mips64, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r10, nullptr, dwarf_r10_mips64, dwarf_r10_mips64, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r11, nullptr, dwarf_r11_mips64, dwarf_r11_mips64, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r12, nullptr, dwarf_r12_mips64, dwarf_r12_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r13, nullptr, dwarf_r13_mips64, dwarf_r13_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r14, nullptr, dwarf_r14_mips64, dwarf_r14_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r15, nullptr, dwarf_r15_mips64, dwarf_r15_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r16, nullptr, dwarf_r16_mips64, dwarf_r16_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r17, nullptr, dwarf_r17_mips64, dwarf_r17_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r18, nullptr, dwarf_r18_mips64, dwarf_r18_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r19, nullptr, dwarf_r19_mips64, dwarf_r19_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r20, nullptr, dwarf_r20_mips64, dwarf_r20_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r21, nullptr, dwarf_r21_mips64, dwarf_r21_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r22, nullptr, dwarf_r22_mips64, dwarf_r22_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r23, nullptr, dwarf_r23_mips64, dwarf_r23_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r24, nullptr, dwarf_r24_mips64, dwarf_r24_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r25, nullptr, dwarf_r25_mips64, dwarf_r25_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r26, nullptr, dwarf_r26_mips64, dwarf_r26_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r27, nullptr, dwarf_r27_mips64, dwarf_r27_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(gp, "r28", dwarf_gp_mips64, dwarf_gp_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(sp, "r29", dwarf_sp_mips64, dwarf_sp_mips64, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r30, nullptr, dwarf_r30_mips64, dwarf_r30_mips64, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ra, "r31", dwarf_ra_mips64, dwarf_ra_mips64, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM),
+ DEFINE_GPR_INFO(sr, nullptr, dwarf_sr_mips64, dwarf_sr_mips64, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(mullo, nullptr, dwarf_lo_mips64, dwarf_lo_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(mulhi, nullptr, dwarf_hi_mips64, dwarf_hi_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(badvaddr, nullptr, dwarf_bad_mips64, dwarf_bad_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR_INFO(cause, nullptr, dwarf_cause_mips64, dwarf_cause_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(pc, "pc", dwarf_pc_mips64, dwarf_pc_mips64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ DEFINE_GPR_INFO(config5, nullptr, dwarf_config5_mips64, dwarf_config5_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f0, nullptr, dwarf_f0_mips64, dwarf_f0_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f1, nullptr, dwarf_f1_mips64, dwarf_f1_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f2, nullptr, dwarf_f2_mips64, dwarf_f2_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f3, nullptr, dwarf_f3_mips64, dwarf_f3_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f4, nullptr, dwarf_f4_mips64, dwarf_f4_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f5, nullptr, dwarf_f5_mips64, dwarf_f5_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f6, nullptr, dwarf_f6_mips64, dwarf_f6_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f7, nullptr, dwarf_f7_mips64, dwarf_f7_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f8, nullptr, dwarf_f8_mips64, dwarf_f8_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f9, nullptr, dwarf_f9_mips64, dwarf_f9_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f10, nullptr, dwarf_f10_mips64, dwarf_f10_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f11, nullptr, dwarf_f11_mips64, dwarf_f11_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f12, nullptr, dwarf_f12_mips64, dwarf_f12_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f13, nullptr, dwarf_f13_mips64, dwarf_f13_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f14, nullptr, dwarf_f14_mips64, dwarf_f14_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f15, nullptr, dwarf_f15_mips64, dwarf_f15_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f16, nullptr, dwarf_f16_mips64, dwarf_f16_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f17, nullptr, dwarf_f17_mips64, dwarf_f17_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f18, nullptr, dwarf_f18_mips64, dwarf_f18_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f19, nullptr, dwarf_f19_mips64, dwarf_f19_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f20, nullptr, dwarf_f20_mips64, dwarf_f20_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f21, nullptr, dwarf_f21_mips64, dwarf_f21_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f22, nullptr, dwarf_f22_mips64, dwarf_f22_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f23, nullptr, dwarf_f23_mips64, dwarf_f23_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f24, nullptr, dwarf_f24_mips64, dwarf_f24_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f25, nullptr, dwarf_f25_mips64, dwarf_f25_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f26, nullptr, dwarf_f26_mips64, dwarf_f26_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f27, nullptr, dwarf_f27_mips64, dwarf_f27_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f28, nullptr, dwarf_f28_mips64, dwarf_f28_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f29, nullptr, dwarf_f29_mips64, dwarf_f29_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f30, nullptr, dwarf_f30_mips64, dwarf_f30_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (f31, nullptr, dwarf_f31_mips64, dwarf_f31_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (fcsr, nullptr, dwarf_fcsr_mips64, dwarf_fcsr_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (fir, nullptr, dwarf_fir_mips64, dwarf_fir_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR (config5, nullptr, dwarf_config5_mips64, dwarf_config5_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w0, nullptr, dwarf_w0_mips64, dwarf_w0_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w1, nullptr, dwarf_w1_mips64, dwarf_w1_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w2, nullptr, dwarf_w2_mips64, dwarf_w2_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w3, nullptr, dwarf_w3_mips64, dwarf_w3_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w4, nullptr, dwarf_w4_mips64, dwarf_w4_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w5, nullptr, dwarf_w5_mips64, dwarf_w5_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w6, nullptr, dwarf_w6_mips64, dwarf_w6_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w7, nullptr, dwarf_w7_mips64, dwarf_w7_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w8, nullptr, dwarf_w8_mips64, dwarf_w8_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w9, nullptr, dwarf_w9_mips64, dwarf_w9_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w10, nullptr, dwarf_w10_mips64, dwarf_w10_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w11, nullptr, dwarf_w11_mips64, dwarf_w11_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w12, nullptr, dwarf_w12_mips64, dwarf_w12_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w13, nullptr, dwarf_w13_mips64, dwarf_w13_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w14, nullptr, dwarf_w14_mips64, dwarf_w14_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w15, nullptr, dwarf_w15_mips64, dwarf_w15_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w16, nullptr, dwarf_w16_mips64, dwarf_w16_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w17, nullptr, dwarf_w17_mips64, dwarf_w17_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w18, nullptr, dwarf_w18_mips64, dwarf_w18_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w19, nullptr, dwarf_w19_mips64, dwarf_w19_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w20, nullptr, dwarf_w10_mips64, dwarf_w20_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w21, nullptr, dwarf_w21_mips64, dwarf_w21_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w22, nullptr, dwarf_w22_mips64, dwarf_w22_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w23, nullptr, dwarf_w23_mips64, dwarf_w23_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w24, nullptr, dwarf_w24_mips64, dwarf_w24_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w25, nullptr, dwarf_w25_mips64, dwarf_w25_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w26, nullptr, dwarf_w26_mips64, dwarf_w26_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w27, nullptr, dwarf_w27_mips64, dwarf_w27_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w28, nullptr, dwarf_w28_mips64, dwarf_w28_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w29, nullptr, dwarf_w29_mips64, dwarf_w29_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w30, nullptr, dwarf_w30_mips64, dwarf_w30_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA (w31, nullptr, dwarf_w31_mips64, dwarf_w31_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (mcsr, nullptr, dwarf_mcsr_mips64, dwarf_mcsr_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (mir, nullptr, dwarf_mir_mips64, dwarf_mir_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (fcsr, nullptr, dwarf_fcsr_mips64, dwarf_fcsr_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (fir, nullptr, dwarf_fir_mips64, dwarf_fir_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_MSA_INFO (config5, nullptr, dwarf_config5_mips64, dwarf_config5_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM)
#endif
};
diff --git a/source/Plugins/Process/Utility/RegisterInfos_powerpc.h b/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
index fe145e99588b..95347ae51592 100644
--- a/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
@@ -24,15 +24,15 @@
// Note that the size and offset will be updated by platform-specific classes.
#define DEFINE_GPR(reg, alt, lldb_kind) \
{ #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \
- eFormatHex, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, gpr_##reg##_powerpc }, NULL, NULL }
+ eFormatHex, { dwarf_##reg##_powerpc, dwarf_##reg##_powerpc, lldb_kind, LLDB_INVALID_REGNUM, gpr_##reg##_powerpc }, NULL, NULL }
#define DEFINE_FPR(reg, lldb_kind) \
{ #reg, NULL, 8, FPR_OFFSET(reg), eEncodingIEEE754, \
- eFormatFloat, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, fpr_##reg##_powerpc }, NULL, NULL }
+ eFormatFloat, { dwarf_##reg##_powerpc, dwarf_##reg##_powerpc, lldb_kind, LLDB_INVALID_REGNUM, fpr_##reg##_powerpc }, NULL, NULL }
#define DEFINE_VMX(reg, lldb_kind) \
{ #reg, NULL, 16, VMX_OFFSET(reg), eEncodingVector, \
- eFormatVectorOfUInt32, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, vmx_##reg##_powerpc }, NULL, NULL }
+ eFormatVectorOfUInt32, { dwarf_##reg##_powerpc, dwarf_##reg##_powerpc, lldb_kind, LLDB_INVALID_REGNUM, vmx_##reg##_powerpc }, NULL, NULL }
- // General purpose registers. GCC, DWARF, Generic, GDB
+ // General purpose registers. EH_Frame, DWARF, Generic, Process Plugin
#define POWERPC_REGS \
DEFINE_GPR(r0, NULL, LLDB_INVALID_REGNUM), \
DEFINE_GPR(r1, "sp", LLDB_REGNUM_GENERIC_SP), \
@@ -103,7 +103,7 @@
DEFINE_FPR(f29, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f30, LLDB_INVALID_REGNUM), \
DEFINE_FPR(f31, LLDB_INVALID_REGNUM), \
- { "fpscr", NULL, 8, FPR_OFFSET(fpscr), eEncodingUint, eFormatHex, { gcc_dwarf_fpscr_powerpc, gcc_dwarf_fpscr_powerpc, LLDB_INVALID_REGNUM, gdb_fpscr_powerpc, fpr_fpscr_powerpc }, NULL, NULL }, \
+ { "fpscr", NULL, 8, FPR_OFFSET(fpscr), eEncodingUint, eFormatHex, { dwarf_fpscr_powerpc, dwarf_fpscr_powerpc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_fpscr_powerpc }, NULL, NULL }, \
DEFINE_VMX(v0, LLDB_INVALID_REGNUM), \
DEFINE_VMX(v1, LLDB_INVALID_REGNUM), \
DEFINE_VMX(v2, LLDB_INVALID_REGNUM), \
@@ -136,8 +136,8 @@
DEFINE_VMX(v29, LLDB_INVALID_REGNUM), \
DEFINE_VMX(v30, LLDB_INVALID_REGNUM), \
DEFINE_VMX(v31, LLDB_INVALID_REGNUM), \
- { "vrsave", NULL, 4, VMX_OFFSET(vrsave), eEncodingUint, eFormatHex, { gcc_dwarf_vrsave_powerpc, gcc_dwarf_vrsave_powerpc, LLDB_INVALID_REGNUM, gdb_vrsave_powerpc, vmx_vrsave_powerpc }, NULL, NULL }, \
- { "vscr", NULL, 4, VMX_OFFSET(vscr), eEncodingUint, eFormatHex, { gcc_dwarf_vscr_powerpc, gcc_dwarf_vscr_powerpc, LLDB_INVALID_REGNUM, gdb_vscr_powerpc, vmx_vscr_powerpc }, NULL, NULL },
+ { "vrsave", NULL, 4, VMX_OFFSET(vrsave), eEncodingUint, eFormatHex, { dwarf_vrsave_powerpc, dwarf_vrsave_powerpc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, vmx_vrsave_powerpc }, NULL, NULL }, \
+ { "vscr", NULL, 4, VMX_OFFSET(vscr), eEncodingUint, eFormatHex, { dwarf_vscr_powerpc, dwarf_vscr_powerpc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, vmx_vscr_powerpc }, NULL, NULL },
static RegisterInfo
g_register_infos_powerpc64[] =
diff --git a/source/Plugins/Process/Utility/RegisterInfos_x86_64.h b/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
index 5da74ff83487..a393089dd129 100644
--- a/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
@@ -1,15 +1,21 @@
-//===-- RegisterInfos_x86_64.h ---------------------------------*- C++ -*-===//
+//===-- RegisterInfos_x86_64.h ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
-#include "llvm/Support/Compiler.h"
+//===----------------------------------------------------------------------===//
+// C Includes
#include <stddef.h>
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/Support/Compiler.h"
+
+// Project includes
+
// Computes the offset of the given GPR in the user data area.
#define GPR_OFFSET(regname) \
(LLVM_EXTENSION offsetof(GPR, regname))
@@ -44,7 +50,7 @@
#define DR_SIZE sizeof(((DBG*)NULL)->dr[0])
-// RegisterKind: GCC, DWARF, Generic, GDB, LLDB
+// RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB
// Note that the size and offset will be updated by platform-specific classes.
#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
@@ -58,25 +64,25 @@
#define DEFINE_FP_ST(reg, i) \
{ #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(stmm[i]), \
eEncodingVector, eFormatVectorOfUInt8, \
- { gcc_dwarf_st##i##_x86_64, gcc_dwarf_st##i##_x86_64, LLDB_INVALID_REGNUM, gdb_st##i##_x86_64, lldb_st##i##_x86_64 }, \
+ { dwarf_st##i##_x86_64, dwarf_st##i##_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_st##i##_x86_64 }, \
NULL, NULL }
#define DEFINE_FP_MM(reg, i) \
{ #reg#i, NULL, sizeof(uint64_t), LLVM_EXTENSION FPR_OFFSET(stmm[i]), \
eEncodingUint, eFormatHex, \
- { gcc_dwarf_mm##i##_x86_64, gcc_dwarf_mm##i##_x86_64, LLDB_INVALID_REGNUM, gdb_st##i##_x86_64, lldb_mm##i##_x86_64 }, \
+ { dwarf_mm##i##_x86_64, dwarf_mm##i##_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_mm##i##_x86_64 }, \
NULL, NULL }
#define DEFINE_XMM(reg, i) \
{ #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]), \
eEncodingVector, eFormatVectorOfUInt8, \
- { gcc_dwarf_##reg##i##_x86_64, gcc_dwarf_##reg##i##_x86_64, LLDB_INVALID_REGNUM, gdb_##reg##i##_x86_64, lldb_##reg##i##_x86_64}, \
+ { dwarf_##reg##i##_x86_64, dwarf_##reg##i##_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_x86_64}, \
NULL, NULL }
#define DEFINE_YMM(reg, i) \
{ #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(i), \
eEncodingVector, eFormatVectorOfUInt8, \
- { gcc_dwarf_##reg##i##h_x86_64, gcc_dwarf_##reg##i##h_x86_64, LLDB_INVALID_REGNUM, gdb_##reg##i##h_x86_64, lldb_##reg##i##_x86_64 }, \
+ { dwarf_##reg##i##h_x86_64, dwarf_##reg##i##h_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_x86_64 }, \
NULL, NULL }
#define DEFINE_DR(reg, i) \
@@ -100,31 +106,31 @@
static RegisterInfo
g_register_infos_x86_64[] =
{
- // General purpose registers. GCC, DWARF, Generic, GDB
- DEFINE_GPR(rax, NULL, gcc_dwarf_rax_x86_64, gcc_dwarf_rax_x86_64, LLDB_INVALID_REGNUM, gdb_rax_x86_64),
- DEFINE_GPR(rbx, NULL, gcc_dwarf_rbx_x86_64, gcc_dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, gdb_rbx_x86_64),
- DEFINE_GPR(rcx, "arg4", gcc_dwarf_rcx_x86_64, gcc_dwarf_rcx_x86_64, LLDB_REGNUM_GENERIC_ARG4, gdb_rcx_x86_64),
- DEFINE_GPR(rdx, "arg3", gcc_dwarf_rdx_x86_64, gcc_dwarf_rdx_x86_64, LLDB_REGNUM_GENERIC_ARG3, gdb_rdx_x86_64),
- DEFINE_GPR(rdi, "arg1", gcc_dwarf_rdi_x86_64, gcc_dwarf_rdi_x86_64, LLDB_REGNUM_GENERIC_ARG1, gdb_rdi_x86_64),
- DEFINE_GPR(rsi, "arg2", gcc_dwarf_rsi_x86_64, gcc_dwarf_rsi_x86_64, LLDB_REGNUM_GENERIC_ARG2, gdb_rsi_x86_64),
- DEFINE_GPR(rbp, "fp", gcc_dwarf_rbp_x86_64, gcc_dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, gdb_rbp_x86_64),
- DEFINE_GPR(rsp, "sp", gcc_dwarf_rsp_x86_64, gcc_dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, gdb_rsp_x86_64),
- DEFINE_GPR(r8, "arg5", gcc_dwarf_r8_x86_64, gcc_dwarf_r8_x86_64, LLDB_REGNUM_GENERIC_ARG5, gdb_r8_x86_64),
- DEFINE_GPR(r9, "arg6", gcc_dwarf_r9_x86_64, gcc_dwarf_r9_x86_64, LLDB_REGNUM_GENERIC_ARG6, gdb_r9_x86_64),
- DEFINE_GPR(r10, NULL, gcc_dwarf_r10_x86_64, gcc_dwarf_r10_x86_64, LLDB_INVALID_REGNUM, gdb_r10_x86_64),
- DEFINE_GPR(r11, NULL, gcc_dwarf_r11_x86_64, gcc_dwarf_r11_x86_64, LLDB_INVALID_REGNUM, gdb_r11_x86_64),
- DEFINE_GPR(r12, NULL, gcc_dwarf_r12_x86_64, gcc_dwarf_r12_x86_64, LLDB_INVALID_REGNUM, gdb_r12_x86_64),
- DEFINE_GPR(r13, NULL, gcc_dwarf_r13_x86_64, gcc_dwarf_r13_x86_64, LLDB_INVALID_REGNUM, gdb_r13_x86_64),
- DEFINE_GPR(r14, NULL, gcc_dwarf_r14_x86_64, gcc_dwarf_r14_x86_64, LLDB_INVALID_REGNUM, gdb_r14_x86_64),
- DEFINE_GPR(r15, NULL, gcc_dwarf_r15_x86_64, gcc_dwarf_r15_x86_64, LLDB_INVALID_REGNUM, gdb_r15_x86_64),
- DEFINE_GPR(rip, "pc", gcc_dwarf_rip_x86_64, gcc_dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC, gdb_rip_x86_64),
- DEFINE_GPR(rflags, "flags", gcc_dwarf_rflags_x86_64, gcc_dwarf_rflags_x86_64, LLDB_REGNUM_GENERIC_FLAGS, gdb_rflags_x86_64),
- DEFINE_GPR(cs, NULL, gcc_dwarf_cs_x86_64, gcc_dwarf_cs_x86_64, LLDB_INVALID_REGNUM, gdb_cs_x86_64),
- DEFINE_GPR(fs, NULL, gcc_dwarf_fs_x86_64, gcc_dwarf_fs_x86_64, LLDB_INVALID_REGNUM, gdb_fs_x86_64),
- DEFINE_GPR(gs, NULL, gcc_dwarf_gs_x86_64, gcc_dwarf_gs_x86_64, LLDB_INVALID_REGNUM, gdb_gs_x86_64),
- DEFINE_GPR(ss, NULL, gcc_dwarf_ss_x86_64, gcc_dwarf_ss_x86_64, LLDB_INVALID_REGNUM, gdb_ss_x86_64),
- DEFINE_GPR(ds, NULL, gcc_dwarf_ds_x86_64, gcc_dwarf_ds_x86_64, LLDB_INVALID_REGNUM, gdb_ds_x86_64),
- DEFINE_GPR(es, NULL, gcc_dwarf_es_x86_64, gcc_dwarf_es_x86_64, LLDB_INVALID_REGNUM, gdb_es_x86_64),
+ // General purpose registers. EH_Frame, DWARF, Generic, Process Plugin
+ DEFINE_GPR(rax, nullptr, dwarf_rax_x86_64, dwarf_rax_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(rbx, nullptr, dwarf_rbx_x86_64, dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(rcx, "arg4", dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(rdx, "arg3", dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(rdi, "arg1", dwarf_rdi_x86_64, dwarf_rdi_x86_64, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(rsi, "arg2", dwarf_rsi_x86_64, dwarf_rsi_x86_64, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(rbp, "fp", dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(rsp, "sp", dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r8, "arg5", dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r9, "arg6", dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r10, nullptr, dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r11, nullptr, dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r12, nullptr, dwarf_r12_x86_64, dwarf_r12_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r13, nullptr, dwarf_r13_x86_64, dwarf_r13_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r14, nullptr, dwarf_r14_x86_64, dwarf_r14_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(r15, nullptr, dwarf_r15_x86_64, dwarf_r15_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(rip, "pc", dwarf_rip_x86_64, dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(rflags, "flags", dwarf_rflags_x86_64, dwarf_rflags_x86_64, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(cs, nullptr, dwarf_cs_x86_64, dwarf_cs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(fs, nullptr, dwarf_fs_x86_64, dwarf_fs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(gs, nullptr, dwarf_gs_x86_64, dwarf_gs_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ss, nullptr, dwarf_ss_x86_64, dwarf_ss_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(ds, nullptr, dwarf_ds_x86_64, dwarf_ds_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_GPR(es, nullptr, dwarf_es_x86_64, dwarf_es_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
DEFINE_GPR_PSEUDO_32(eax, rax),
DEFINE_GPR_PSEUDO_32(ebx, rbx),
@@ -179,16 +185,16 @@ g_register_infos_x86_64[] =
DEFINE_GPR_PSEUDO_8L(r14l, r14),
DEFINE_GPR_PSEUDO_8L(r15l, r15),
- // i387 Floating point registers. GCC, DWARF, Generic, GDB
- DEFINE_FPR(fctrl, fctrl, gcc_dwarf_fctrl_x86_64, gcc_dwarf_fctrl_x86_64, LLDB_INVALID_REGNUM, gdb_fctrl_x86_64),
- DEFINE_FPR(fstat, fstat, gcc_dwarf_fstat_x86_64, gcc_dwarf_fstat_x86_64, LLDB_INVALID_REGNUM, gdb_fstat_x86_64),
- DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftag_x86_64),
- DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop_x86_64),
- DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fiseg_x86_64),
- DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fioff_x86_64),
- DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_foseg_x86_64),
- DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fooff_x86_64),
- DEFINE_FPR(mxcsr, mxcsr, gcc_dwarf_mxcsr_x86_64, gcc_dwarf_mxcsr_x86_64, LLDB_INVALID_REGNUM, gdb_mxcsr_x86_64),
+ // i387 Floating point registers. EH_frame, DWARF, Generic, Process Plugin
+ DEFINE_FPR(fctrl, fctrl, dwarf_fctrl_x86_64, dwarf_fctrl_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fstat, fstat, dwarf_fstat_x86_64, dwarf_fstat_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+ DEFINE_FPR(mxcsr, mxcsr, dwarf_mxcsr_x86_64, dwarf_mxcsr_x86_64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
// FP registers.
@@ -255,6 +261,7 @@ g_register_infos_x86_64[] =
DEFINE_DR(dr, 6),
DEFINE_DR(dr, 7)
};
+
static_assert((sizeof(g_register_infos_x86_64) / sizeof(g_register_infos_x86_64[0])) == k_num_registers_x86_64,
"g_register_infos_x86_64 has wrong number of register infos");
@@ -275,7 +282,6 @@ static_assert((sizeof(g_register_infos_x86_64) / sizeof(g_register_infos_x86_64[
#endif // DECLARE_REGISTER_INFOS_X86_64_STRUCT
-
#ifdef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
#define UPDATE_GPR_INFO(reg, reg64) \
diff --git a/source/Plugins/Process/Utility/StopInfoMachException.cpp b/source/Plugins/Process/Utility/StopInfoMachException.cpp
index 7c68d0d07821..3bf766e875c9 100644
--- a/source/Plugins/Process/Utility/StopInfoMachException.cpp
+++ b/source/Plugins/Process/Utility/StopInfoMachException.cpp
@@ -58,6 +58,7 @@ StopInfoMachException::GetDescription ()
}
break;
case llvm::Triple::arm:
+ case llvm::Triple::thumb:
switch (m_exc_code)
{
case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break;
@@ -104,6 +105,7 @@ StopInfoMachException::GetDescription ()
break;
case llvm::Triple::arm:
+ case llvm::Triple::thumb:
if (m_exc_code == 1)
code_desc = "EXC_ARM_UNDEFINED";
break;
@@ -188,6 +190,7 @@ StopInfoMachException::GetDescription ()
break;
case llvm::Triple::arm:
+ case llvm::Triple::thumb:
switch (m_exc_code)
{
case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break;
@@ -408,6 +411,7 @@ StopInfoMachException::CreateStopReasonWithMachException
break;
case llvm::Triple::arm:
+ case llvm::Triple::thumb:
if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
{
// It's a watchpoint, then, if the exc_sub_code indicates a known/enabled
diff --git a/source/Plugins/Process/Utility/StopInfoMachException.h b/source/Plugins/Process/Utility/StopInfoMachException.h
index 130ee0b709b0..25e05ecc1ec7 100644
--- a/source/Plugins/Process/Utility/StopInfoMachException.h
+++ b/source/Plugins/Process/Utility/StopInfoMachException.h
@@ -38,19 +38,16 @@ public:
{
}
- virtual ~StopInfoMachException()
- {
- }
+ ~StopInfoMachException() override = default;
-
- virtual lldb::StopReason
- GetStopReason () const
+ lldb::StopReason
+ GetStopReason() const override
{
return lldb::eStopReasonException;
}
- virtual const char *
- GetDescription ();
+ const char *
+ GetDescription() override;
// Since some mach exceptions will be reported as breakpoints, signals,
// or trace, we use this static accessor which will translate the mach
@@ -71,7 +68,6 @@ protected:
uint64_t m_exc_subcode;
};
-
} // namespace lldb_private
-#endif // liblldb_StopInfoMachException_h_
+#endif // liblldb_StopInfoMachException_h_
diff --git a/source/Plugins/Process/Utility/ThreadMemory.h b/source/Plugins/Process/Utility/ThreadMemory.h
index 07eb45dcb431..1e7cbfa44815 100644
--- a/source/Plugins/Process/Utility/ThreadMemory.h
+++ b/source/Plugins/Process/Utility/ThreadMemory.h
@@ -1,4 +1,4 @@
-//===-- ThreadMemory.h -----------------------------------------*- C++ -*-===//
+//===-- ThreadMemory.h ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,13 +10,18 @@
#ifndef liblldb_ThreadMemory_h_
#define liblldb_ThreadMemory_h_
+// C Includes
+// C++ Includes
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/Target/Thread.h"
class ThreadMemory :
public lldb_private::Thread
{
public:
-
ThreadMemory (lldb_private::Process &process,
lldb::tid_t tid,
const lldb::ValueObjectSP &thread_info_valobj_sp);
@@ -27,69 +32,65 @@ public:
const char *queue,
lldb::addr_t register_data_addr);
- virtual
- ~ThreadMemory();
+ ~ThreadMemory() override;
- //------------------------------------------------------------------
- // lldb_private::Thread methods
- //------------------------------------------------------------------
- virtual lldb::RegisterContextSP
- GetRegisterContext ();
+ lldb::RegisterContextSP
+ GetRegisterContext() override;
- virtual lldb::RegisterContextSP
- CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
- virtual bool
- CalculateStopInfo ();
+ bool
+ CalculateStopInfo() override;
- virtual const char *
- GetInfo ()
+ const char *
+ GetInfo() override
{
if (m_backing_thread_sp)
m_backing_thread_sp->GetInfo();
- return NULL;
+ return nullptr;
}
- virtual const char *
- GetName ()
+ const char *
+ GetName() override
{
if (!m_name.empty())
return m_name.c_str();
if (m_backing_thread_sp)
m_backing_thread_sp->GetName();
- return NULL;
+ return nullptr;
}
- virtual const char *
- GetQueueName ()
+ const char *
+ GetQueueName() override
{
if (!m_queue.empty())
return m_queue.c_str();
if (m_backing_thread_sp)
m_backing_thread_sp->GetQueueName();
- return NULL;
+ return nullptr;
}
- virtual void
- WillResume (lldb::StateType resume_state);
+ void
+ WillResume(lldb::StateType resume_state) override;
- virtual void
- DidResume ()
+ void
+ DidResume() override
{
if (m_backing_thread_sp)
m_backing_thread_sp->DidResume();
}
- virtual lldb::user_id_t
- GetProtocolID () const
+ lldb::user_id_t
+ GetProtocolID() const override
{
if (m_backing_thread_sp)
return m_backing_thread_sp->GetProtocolID();
return Thread::GetProtocolID();
}
- virtual void
- RefreshStateAfterStop();
+ void
+ RefreshStateAfterStop() override;
lldb::ValueObjectSP &
GetValueObject ()
@@ -97,41 +98,36 @@ public:
return m_thread_info_valobj_sp;
}
- virtual void
- ClearStackFrames ();
+ void
+ ClearStackFrames() override;
- virtual void
- ClearBackingThread ()
+ void
+ ClearBackingThread() override
{
m_backing_thread_sp.reset();
}
- virtual bool
- SetBackingThread (const lldb::ThreadSP &thread_sp)
+ bool
+ SetBackingThread(const lldb::ThreadSP &thread_sp) override
{
//printf ("Thread 0x%llx is being backed by thread 0x%llx\n", GetID(), thread_sp->GetID());
m_backing_thread_sp = thread_sp;
return (bool)thread_sp;
}
- virtual lldb::ThreadSP
- GetBackingThread () const
+ lldb::ThreadSP
+ GetBackingThread() const override
{
return m_backing_thread_sp;
}
protected:
-
- virtual bool
- IsOperatingSystemPluginThread () const
+ bool
+ IsOperatingSystemPluginThread() const override
{
return true;
}
-
- //------------------------------------------------------------------
- // For ThreadMemory and subclasses
- //------------------------------------------------------------------
// If this memory thread is actually represented by a thread from the
// lldb_private::Process subclass, then fill in the thread here and
// all APIs will be routed through this thread object. If m_backing_thread_sp
@@ -142,11 +138,9 @@ protected:
std::string m_name;
std::string m_queue;
lldb::addr_t m_register_data_addr;
+
private:
- //------------------------------------------------------------------
- // For ThreadMemory only
- //------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (ThreadMemory);
};
-#endif // liblldb_ThreadMemory_h_
+#endif // liblldb_ThreadMemory_h_
diff --git a/source/Plugins/Process/Utility/UnwindLLDB.cpp b/source/Plugins/Process/Utility/UnwindLLDB.cpp
index 1cdae9011673..9be09c478a0e 100644
--- a/source/Plugins/Process/Utility/UnwindLLDB.cpp
+++ b/source/Plugins/Process/Utility/UnwindLLDB.cpp
@@ -86,6 +86,9 @@ UnwindLLDB::AddFirstFrame ()
if (m_frames.size() > 0)
return true;
+ ProcessSP process_sp (m_thread.GetProcess());
+ ABI *abi = process_sp ? process_sp->GetABI().get() : NULL;
+
// First, set up the 0th (initial) frame
CursorSP first_cursor_sp(new Cursor ());
RegisterContextLLDBSP reg_ctx_sp (new RegisterContextLLDB (m_thread,
@@ -108,6 +111,10 @@ UnwindLLDB::AddFirstFrame ()
// cursor own it in its shared pointer
first_cursor_sp->reg_ctx_lldb_sp = reg_ctx_sp;
m_frames.push_back (first_cursor_sp);
+
+ // Update the Full Unwind Plan for this frame if not valid
+ UpdateUnwindPlanForFirstFrameIfInvalid(abi);
+
return true;
unwind_done:
@@ -161,7 +168,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
// true. Subsequent calls to TryFallbackUnwindPlan() will return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ {
+ // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of
+ // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it.
+ if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
+ return nullptr;
+
return GetOneMoreFrame (abi);
+ }
if (log)
log->Printf ("%*sFrame %d did not get a RegisterContext, stopping.",
@@ -175,7 +189,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
// See if the regctx below this on the stack has a fallback unwind plan it can use.
// Subsequent calls to TryFallbackUnwindPlan() will return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ {
+ // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of
+ // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it.
+ if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
+ return nullptr;
+
return GetOneMoreFrame (abi);
+ }
if (log)
log->Printf("%*sFrame %d invalid RegisterContext for this frame, stopping stack walk",
@@ -187,7 +208,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
// true. Subsequent calls to TryFallbackUnwindPlan() will return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ {
+ // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of
+ // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it.
+ if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
+ return nullptr;
+
return GetOneMoreFrame (abi);
+ }
if (log)
log->Printf("%*sFrame %d did not get CFA for this frame, stopping stack walk",
@@ -212,7 +240,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
|| abi->CallFrameAddressIsValid(cursor_sp->cfa) == false)
{
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ {
+ // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of
+ // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it.
+ if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
+ return nullptr;
+
return GetOneMoreFrame (abi);
+ }
if (log)
log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk",
@@ -232,7 +267,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
// true. Subsequent calls to TryFallbackUnwindPlan() will return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ {
+ // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of
+ // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it.
+ if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
+ return nullptr;
+
return GetOneMoreFrame (abi);
+ }
if (log)
log->Printf("%*sFrame %d did not get PC for this frame, stopping stack walk",
@@ -244,7 +286,14 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
// true. Subsequent calls to TryFallbackUnwindPlan() will return false.
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan())
+ {
+ // TryFallbackUnwindPlan for prev_frame succeeded and updated reg_ctx_lldb_sp field of
+ // prev_frame. However, cfa field of prev_frame still needs to be updated. Hence updating it.
+ if ( !(prev_frame->reg_ctx_lldb_sp->GetCFA(prev_frame->cfa)))
+ return nullptr;
+
return GetOneMoreFrame (abi);
+ }
if (log)
log->Printf("%*sFrame %d did not get a valid PC, stopping stack walk",
@@ -263,6 +312,33 @@ UnwindLLDB::GetOneMoreFrame (ABI* abi)
return cursor_sp;
}
+void
+UnwindLLDB::UpdateUnwindPlanForFirstFrameIfInvalid (ABI *abi)
+{
+ // This function is called for First Frame only.
+ assert (m_frames.size() == 1 && "No. of cursor frames are not 1");
+
+ bool old_m_unwind_complete = m_unwind_complete;
+ CursorSP old_m_candidate_frame = m_candidate_frame;
+
+ // Try to unwind 2 more frames using the Unwinder. It uses Full UnwindPlan
+ // and if Full UnwindPlan fails, then uses FallBack UnwindPlan. Also
+ // update the cfa of Frame 0 (if required).
+ AddOneMoreFrame(abi);
+
+ // Remove all the frames added by above function as the purpose of
+ // using above function was just to check whether Unwinder of Frame 0
+ // works or not.
+ for(uint32_t i=1; i<m_frames.size(); i++)
+ m_frames.pop_back();
+
+ // Restore status after calling AddOneMoreFrame
+ m_unwind_complete = old_m_unwind_complete;
+ m_candidate_frame = old_m_candidate_frame;
+ return;
+}
+
+
bool
UnwindLLDB::AddOneMoreFrame (ABI *abi)
{
@@ -321,9 +397,17 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
m_frames.push_back(new_frame_v2);
m_candidate_frame = GetOneMoreFrame(abi);
if (m_candidate_frame)
+ {
+ // If control reached here then TryFallbackUnwindPlan had succeeded for Cursor::m_frames[m_frames.size() - 2].
+ // It also succeeded to Unwind next 2 frames i.e. m_frames[m_frames.size() - 1] and a frame after that.
+ // For Cursor::m_frames[m_frames.size() - 2], reg_ctx_lldb_sp field was already updated during TryFallbackUnwindPlan
+ // call above. However, cfa field still needs to be updated. Hence updating it here and then returning.
+ if ( !(m_frames[m_frames.size() - 2]->reg_ctx_lldb_sp->GetCFA(m_frames[m_frames.size() - 2]->cfa)))
+ return false;
return true;
+ }
- // The new frame isn't helped in unwinding. Fall back to the original one as the default unwind
+ // The new frame hasn't helped in unwinding. Fall back to the original one as the default unwind
// plan is usually more reliable then the fallback one.
m_frames.pop_back();
m_frames.push_back(new_frame);
diff --git a/source/Plugins/Process/Utility/UnwindLLDB.h b/source/Plugins/Process/Utility/UnwindLLDB.h
index ce897cd82423..d3c07078759b 100644
--- a/source/Plugins/Process/Utility/UnwindLLDB.h
+++ b/source/Plugins/Process/Utility/UnwindLLDB.h
@@ -10,8 +10,12 @@
#ifndef lldb_UnwindLLDB_h_
#define lldb_UnwindLLDB_h_
+// C Includes
+// C++ Includes
#include <vector>
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-public.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Symbol/FuncUnwinders.h"
@@ -27,9 +31,8 @@ class UnwindLLDB : public lldb_private::Unwind
{
public:
UnwindLLDB (lldb_private::Thread &thread);
-
- virtual
- ~UnwindLLDB() { }
+
+ ~UnwindLLDB() override = default;
enum RegisterSearchResult
{
@@ -62,23 +65,23 @@ protected:
};
void
- DoClear()
+ DoClear() override
{
m_frames.clear();
m_candidate_frame.reset();
m_unwind_complete = false;
}
- virtual uint32_t
- DoGetFrameCount();
+ uint32_t
+ DoGetFrameCount() override;
bool
- DoGetFrameInfoAtIndex (uint32_t frame_idx,
- lldb::addr_t& cfa,
- lldb::addr_t& start_pc);
+ DoGetFrameInfoAtIndex(uint32_t frame_idx,
+ lldb::addr_t& cfa,
+ lldb::addr_t& start_pc) override;
lldb::RegisterContextSP
- DoCreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+ DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
typedef std::shared_ptr<RegisterContextLLDB> RegisterContextLLDBSP;
@@ -112,7 +115,6 @@ protected:
}
private:
-
struct Cursor
{
lldb::addr_t start_pc; // The start address of the function/symbol for this frame - current pc if unknown
@@ -134,6 +136,15 @@ private:
std::vector<ConstString> m_user_supplied_trap_handler_functions;
+ //-----------------------------------------------------------------
+ // Check if Full UnwindPlan of First frame is valid or not.
+ // If not then try Fallback UnwindPlan of the frame. If Fallback
+ // UnwindPlan succeeds then update the Full UnwindPlan with the
+ // Fallback UnwindPlan.
+ //-----------------------------------------------------------------
+ void
+ UpdateUnwindPlanForFirstFrameIfInvalid (ABI* abi);
+
CursorSP
GetOneMoreFrame (ABI* abi);
@@ -149,6 +160,6 @@ private:
DISALLOW_COPY_AND_ASSIGN (UnwindLLDB);
};
-} // namespace lldb_private
+} // namespace lldb_private
-#endif // lldb_UnwindLLDB_h_
+#endif // lldb_UnwindLLDB_h_
diff --git a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
index 2695376fd6e0..f195514ed1ba 100644
--- a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
+++ b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
@@ -15,7 +15,6 @@
#include <vector>
// Other libraries and framework includes
-
// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/Unwind.h"
@@ -24,29 +23,26 @@ class UnwindMacOSXFrameBackchain : public lldb_private::Unwind
{
public:
UnwindMacOSXFrameBackchain (lldb_private::Thread &thread);
-
- virtual
- ~UnwindMacOSXFrameBackchain()
- {
- }
-
+
+ ~UnwindMacOSXFrameBackchain() override = default;
+
protected:
- virtual void
- DoClear()
+ void
+ DoClear() override
{
m_cursors.clear();
}
- virtual uint32_t
- DoGetFrameCount();
+ uint32_t
+ DoGetFrameCount() override;
bool
- DoGetFrameInfoAtIndex (uint32_t frame_idx,
- lldb::addr_t& cfa,
- lldb::addr_t& pc);
+ DoGetFrameInfoAtIndex(uint32_t frame_idx,
+ lldb::addr_t& cfa,
+ lldb::addr_t& pc) override;
lldb::RegisterContextSP
- DoCreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+ DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
friend class RegisterContextMacOSXFrameBackchain;
@@ -71,4 +67,4 @@ private:
DISALLOW_COPY_AND_ASSIGN (UnwindMacOSXFrameBackchain);
};
-#endif // lldb_UnwindMacOSXFrameBackchain_h_
+#endif // lldb_UnwindMacOSXFrameBackchain_h_
diff --git a/source/Plugins/Process/Utility/lldb-arm-register-enums.h b/source/Plugins/Process/Utility/lldb-arm-register-enums.h
index a617f6550f65..4d82c10a78ea 100644
--- a/source/Plugins/Process/Utility/lldb-arm-register-enums.h
+++ b/source/Plugins/Process/Utility/lldb-arm-register-enums.h
@@ -74,7 +74,55 @@ namespace lldb_private
fpu_s30_arm,
fpu_s31_arm,
fpu_fpscr_arm,
- k_last_fpr_arm = fpu_fpscr_arm,
+ fpu_d0_arm,
+ fpu_d1_arm,
+ fpu_d2_arm,
+ fpu_d3_arm,
+ fpu_d4_arm,
+ fpu_d5_arm,
+ fpu_d6_arm,
+ fpu_d7_arm,
+ fpu_d8_arm,
+ fpu_d9_arm,
+ fpu_d10_arm,
+ fpu_d11_arm,
+ fpu_d12_arm,
+ fpu_d13_arm,
+ fpu_d14_arm,
+ fpu_d15_arm,
+ fpu_d16_arm,
+ fpu_d17_arm,
+ fpu_d18_arm,
+ fpu_d19_arm,
+ fpu_d20_arm,
+ fpu_d21_arm,
+ fpu_d22_arm,
+ fpu_d23_arm,
+ fpu_d24_arm,
+ fpu_d25_arm,
+ fpu_d26_arm,
+ fpu_d27_arm,
+ fpu_d28_arm,
+ fpu_d29_arm,
+ fpu_d30_arm,
+ fpu_d31_arm,
+ fpu_q0_arm,
+ fpu_q1_arm,
+ fpu_q2_arm,
+ fpu_q3_arm,
+ fpu_q4_arm,
+ fpu_q5_arm,
+ fpu_q6_arm,
+ fpu_q7_arm,
+ fpu_q8_arm,
+ fpu_q9_arm,
+ fpu_q10_arm,
+ fpu_q11_arm,
+ fpu_q12_arm,
+ fpu_q13_arm,
+ fpu_q14_arm,
+ fpu_q15_arm,
+ k_last_fpr_arm = fpu_q15_arm,
exc_exception_arm,
exc_fsr_arm,
exc_far_arm,
diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index bf5cad8e39c5..5b5d98a86d5e 100644
--- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -57,7 +57,7 @@ ProcessElfCore::Terminate()
lldb::ProcessSP
-ProcessElfCore::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file)
+ProcessElfCore::CreateInstance (lldb::TargetSP target_sp, Listener &listener, const FileSpec *crash_file)
{
lldb::ProcessSP process_sp;
if (crash_file)
@@ -75,7 +75,7 @@ ProcessElfCore::CreateInstance (Target &target, Listener &listener, const FileSp
if (elf_header.Parse(data, &data_offset))
{
if (elf_header.e_type == llvm::ELF::ET_CORE)
- process_sp.reset(new ProcessElfCore (target, listener, *crash_file));
+ process_sp.reset(new ProcessElfCore (target_sp, listener, *crash_file));
}
}
}
@@ -83,12 +83,12 @@ ProcessElfCore::CreateInstance (Target &target, Listener &listener, const FileSp
}
bool
-ProcessElfCore::CanDebug(Target &target, bool plugin_specified_by_name)
+ProcessElfCore::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name)
{
// For now we are just making sure the file exists for a given module
if (!m_core_module_sp && m_core_file.Exists())
{
- ModuleSpec core_module_spec(m_core_file, target.GetArchitecture());
+ ModuleSpec core_module_spec(m_core_file, target_sp->GetArchitecture());
Error error (ModuleList::GetSharedModule (core_module_spec, m_core_module_sp,
NULL, NULL, NULL));
if (m_core_module_sp)
@@ -104,9 +104,9 @@ ProcessElfCore::CanDebug(Target &target, bool plugin_specified_by_name)
//----------------------------------------------------------------------
// ProcessElfCore constructor
//----------------------------------------------------------------------
-ProcessElfCore::ProcessElfCore(Target& target, Listener &listener,
+ProcessElfCore::ProcessElfCore(lldb::TargetSP target_sp, Listener &listener,
const FileSpec &core_file) :
- Process (target, listener),
+ Process (target_sp, listener),
m_core_module_sp (),
m_core_file (core_file),
m_dyld_plugin_name (),
@@ -233,10 +233,29 @@ ProcessElfCore::DoLoadCore ()
// it to match the core file which is always single arch.
ArchSpec arch (m_core_module_sp->GetArchitecture());
if (arch.IsValid())
- m_target.SetArchitecture(arch);
+ GetTarget().SetArchitecture(arch);
SetUnixSignals(UnixSignals::Create(GetArchitecture()));
+ // Core files are useless without the main executable. See if we can locate the main
+ // executable using data we found in the core file notes.
+ lldb::ModuleSP exe_module_sp = GetTarget().GetExecutableModule();
+ if (!exe_module_sp)
+ {
+ // The first entry in the NT_FILE might be our executable
+ if (!m_nt_file_entries.empty())
+ {
+ ModuleSpec exe_module_spec;
+ exe_module_spec.GetArchitecture() = arch;
+ exe_module_spec.GetFileSpec().SetFile(m_nt_file_entries[0].path.GetCString(), false);
+ if (exe_module_spec.GetFileSpec())
+ {
+ exe_module_sp = GetTarget().GetSharedModule(exe_module_spec);
+ if (exe_module_sp)
+ GetTarget().SetExecutableModule(exe_module_sp, false);
+ }
+ }
+ }
return error;
}
@@ -258,7 +277,7 @@ ProcessElfCore::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_t
for (lldb::tid_t tid = 0; tid < num_threads; ++tid)
{
const ThreadData &td = m_thread_data[tid];
- lldb::ThreadSP thread_sp(new ThreadElfCore (*this, tid, td));
+ lldb::ThreadSP thread_sp(new ThreadElfCore (*this, td));
new_thread_list.AddThread (thread_sp);
}
return new_thread_list.GetSize(false) > 0;
@@ -352,8 +371,7 @@ ProcessElfCore::Clear()
m_thread_list.Clear();
m_os = llvm::Triple::UnknownOS;
- static const auto s_default_unix_signals_sp = std::make_shared<UnixSignals>();
- SetUnixSignals(s_default_unix_signals_sp);
+ SetUnixSignals(std::make_shared<UnixSignals>());
}
void
@@ -371,12 +389,11 @@ ProcessElfCore::Initialize()
lldb::addr_t
ProcessElfCore::GetImageInfoAddress()
{
- Target *target = &GetTarget();
- ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
- Address addr = obj_file->GetImageInfoAddress(target);
+ ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile();
+ Address addr = obj_file->GetImageInfoAddress(&GetTarget());
if (addr.IsValid())
- return addr.GetLoadAddress(target);
+ return addr.GetLoadAddress(&GetTarget());
return LLDB_INVALID_ADDRESS;
}
@@ -387,7 +404,8 @@ enum {
NT_PRPSINFO,
NT_TASKSTRUCT,
NT_PLATFORM,
- NT_AUXV
+ NT_AUXV,
+ NT_FILE = 0x46494c45
};
namespace FREEBSD {
@@ -429,7 +447,7 @@ ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data,
offset += 16;
thread_data.signo = data.GetU32(&offset); // pr_cursig
- offset += 4; // pr_pid
+ thread_data.tid = data.GetU32(&offset); // pr_pid
if (lp64)
offset += 4;
@@ -503,6 +521,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
// Store the NOTE information in the current thread
DataExtractor note_data (segment_data, note_start, note_size);
+ note_data.SetAddressByteSize(m_core_module_sp->GetArchitecture().GetAddressByteSize());
if (note.n_name == "FreeBSD")
{
m_os = llvm::Triple::FreeBSD;
@@ -532,7 +551,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
break;
}
}
- else
+ else if (note.n_name == "CORE")
{
switch (note.n_type)
{
@@ -543,6 +562,8 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
header_size = ELFLinuxPrStatus::GetSize(arch);
len = note_data.GetByteSize() - header_size;
thread_data->gpregset = DataExtractor(note_data, header_size, len);
+ // FIXME: Obtain actual tid on Linux
+ thread_data->tid = m_thread_data.size();
break;
case NT_FPREGSET:
thread_data->fpregset = note_data;
@@ -555,6 +576,28 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
case NT_AUXV:
m_auxv = DataExtractor(note_data);
break;
+ case NT_FILE:
+ {
+ m_nt_file_entries.clear();
+ lldb::offset_t offset = 0;
+ const uint64_t count = note_data.GetAddress(&offset);
+ note_data.GetAddress(&offset); // Skip page size
+ for (uint64_t i = 0; i<count; ++i)
+ {
+ NT_FILE_Entry entry;
+ entry.start = note_data.GetAddress(&offset);
+ entry.end = note_data.GetAddress(&offset);
+ entry.file_ofs = note_data.GetAddress(&offset);
+ m_nt_file_entries.push_back(entry);
+ }
+ for (uint64_t i = 0; i<count; ++i)
+ {
+ const char *path = note_data.GetCStr(&offset);
+ if (path && path[0])
+ m_nt_file_entries[i].path.SetCString(path);
+ }
+ }
+ break;
default:
break;
}
diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.h b/source/Plugins/Process/elf-core/ProcessElfCore.h
index 775d9e94dd8e..12ce04c5ce38 100644
--- a/source/Plugins/Process/elf-core/ProcessElfCore.h
+++ b/source/Plugins/Process/elf-core/ProcessElfCore.h
@@ -1,4 +1,4 @@
-//===-- ProcessElfCore.h ---------------------------------------*- C++ -*-===//
+//===-- ProcessElfCore.h ----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,18 +10,20 @@
// 2) The ELF file's PT_NOTE and PT_LOAD segments describes the program's
// address space and thread contexts.
// 3) PT_NOTE segment contains note entries which describes a thread context.
-// 4) PT_LOAD segment describes a valid contigous range of process address
+// 4) PT_LOAD segment describes a valid contiguous range of process address
// space.
//===----------------------------------------------------------------------===//
#ifndef liblldb_ProcessElfCore_h_
#define liblldb_ProcessElfCore_h_
+// C Includes
// C++ Includes
#include <list>
#include <vector>
// Other libraries and framework includes
+// Project includes
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Error.h"
#include "lldb/Target/Process.h"
@@ -37,7 +39,7 @@ public:
// Constructors and Destructors
//------------------------------------------------------------------
static lldb::ProcessSP
- CreateInstance (lldb_private::Target& target,
+ CreateInstance (lldb::TargetSP target_sp,
lldb_private::Listener &listener,
const lldb_private::FileSpec *crash_file_path);
@@ -56,17 +58,16 @@ public:
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
- ProcessElfCore(lldb_private::Target& target,
- lldb_private::Listener &listener,
- const lldb_private::FileSpec &core_file);
+ ProcessElfCore(lldb::TargetSP target_sp,
+ lldb_private::Listener &listener,
+ const lldb_private::FileSpec &core_file);
- virtual
- ~ProcessElfCore();
+ ~ProcessElfCore() override;
//------------------------------------------------------------------
// Check if a given Process
//------------------------------------------------------------------
- bool CanDebug(lldb_private::Target &target, bool plugin_specified_by_name) override;
+ bool CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override;
//------------------------------------------------------------------
// Creating a new process, or attaching to an existing one
@@ -118,6 +119,14 @@ protected:
lldb_private::ThreadList &new_thread_list) override;
private:
+ struct NT_FILE_Entry
+ {
+ lldb::addr_t start;
+ lldb::addr_t end;
+ lldb::addr_t file_ofs;
+ lldb_private::ConstString path;
+ };
+
//------------------------------------------------------------------
// For ProcessElfCore only
//------------------------------------------------------------------
@@ -143,6 +152,9 @@ private:
// Address ranges found in the core
VMRangeToFileOffset m_core_aranges;
+ // NT_FILE entries found from the NOTE segment
+ std::vector<NT_FILE_Entry> m_nt_file_entries;
+
// Parse thread(s) data structures(prstatus, prpsinfo) from given NOTE segment
void
ParseThreadContextsFromNoteSegment (const elf::ELFProgramHeader *segment_header,
@@ -157,4 +169,4 @@ private:
AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *header);
};
-#endif // liblldb_ProcessElffCore_h_
+#endif // liblldb_ProcessElfCore_h_
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp
index f046c112d8b6..6778aeaaac00 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp
@@ -10,7 +10,6 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
-#include "Plugins/Process/Utility/RegisterContextPOSIX.h"
#include "RegisterContextPOSIXCore_arm.h"
using namespace lldb_private;
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h
index 73e2ef7c3a93..0e74897b5b5c 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.h
@@ -1,15 +1,19 @@
-//===-- RegisterContextCorePOSIX_arm.h -----------------------*- C++ -*-===//
+//===-- RegisterContextCorePOSIX_arm.h --------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextCorePOSIX_arm_H_
-#define liblldb_RegisterContextCorePOSIX_arm_H_
+#ifndef liblldb_RegisterContextCorePOSIX_arm_h_
+#define liblldb_RegisterContextCorePOSIX_arm_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/DataBufferHeap.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h"
@@ -22,39 +26,41 @@ public:
const lldb_private::DataExtractor &gpregset,
const lldb_private::DataExtractor &fpregset);
- ~RegisterContextCorePOSIX_arm();
+ ~RegisterContextCorePOSIX_arm() override;
- virtual bool
- ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
bool
- HardwareSingleStep(bool enable);
+ HardwareSingleStep(bool enable) override;
protected:
bool
- ReadGPR();
+ ReadGPR() override;
bool
- ReadFPR();
+ ReadFPR() override;
bool
- WriteGPR();
+ WriteGPR() override;
bool
- WriteFPR();
+ WriteFPR() override;
private:
lldb::DataBufferSP m_gpr_buffer;
lldb_private::DataExtractor m_gpr;
};
-#endif // #ifndef liblldb_RegisterContextCorePOSIX_arm_H_
+#endif // liblldb_RegisterContextCorePOSIX_arm_h_
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
index 53c0c83c264a..7cfdd415ad5b 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
@@ -10,7 +10,6 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
-#include "Plugins/Process/Utility/RegisterContextPOSIX.h"
#include "RegisterContextPOSIXCore_arm64.h"
using namespace lldb_private;
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
index 2e1d6b4f9ca8..9b05edb1935f 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
@@ -1,15 +1,19 @@
-//===-- RegisterContextCorePOSIX_arm64.h -----------------------*- C++ -*-===//
+//===-- RegisterContextCorePOSIX_arm64.h ------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextCorePOSIX_arm64_H_
-#define liblldb_RegisterContextCorePOSIX_arm64_H_
+#ifndef liblldb_RegisterContextCorePOSIX_arm64_h_
+#define liblldb_RegisterContextCorePOSIX_arm64_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/DataBufferHeap.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
@@ -22,39 +26,41 @@ public:
const lldb_private::DataExtractor &gpregset,
const lldb_private::DataExtractor &fpregset);
- ~RegisterContextCorePOSIX_arm64();
+ ~RegisterContextCorePOSIX_arm64() override;
- virtual bool
- ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
bool
- HardwareSingleStep(bool enable);
+ HardwareSingleStep(bool enable) override;
protected:
bool
- ReadGPR();
+ ReadGPR() override;
bool
- ReadFPR();
+ ReadFPR() override;
bool
- WriteGPR();
+ WriteGPR() override;
bool
- WriteFPR();
+ WriteFPR() override;
private:
lldb::DataBufferSP m_gpr_buffer;
lldb_private::DataExtractor m_gpr;
};
-#endif // #ifndef liblldb_RegisterContextCorePOSIX_arm64_H_
+#endif // liblldb_RegisterContextCorePOSIX_arm64_h_
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
index f0750a0cee18..9d908e371a32 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
@@ -10,7 +10,6 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
-#include "Plugins/Process/Utility/RegisterContextPOSIX.h"
#include "RegisterContextPOSIXCore_mips64.h"
using namespace lldb_private;
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h
index ca29d4f0febd..6cbfd504b7db 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.h
@@ -1,15 +1,19 @@
-//===-- RegisterContextCorePOSIX_mips64.h ----------------------*- C++ -*-===//
+//===-- RegisterContextCorePOSIX_mips64.h -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextCorePOSIX_mips64_H_
-#define liblldb_RegisterContextCorePOSIX_mips64_H_
+#ifndef liblldb_RegisterContextCorePOSIX_mips64_h_
+#define liblldb_RegisterContextCorePOSIX_mips64_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/DataBufferHeap.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h"
@@ -22,39 +26,41 @@ public:
const lldb_private::DataExtractor &gpregset,
const lldb_private::DataExtractor &fpregset);
- ~RegisterContextCorePOSIX_mips64();
+ ~RegisterContextCorePOSIX_mips64() override;
- virtual bool
- ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
bool
- HardwareSingleStep(bool enable);
+ HardwareSingleStep(bool enable) override;
protected:
bool
- ReadGPR();
+ ReadGPR() override;
bool
- ReadFPR();
+ ReadFPR() override;
bool
- WriteGPR();
+ WriteGPR() override;
bool
- WriteFPR();
+ WriteFPR() override;
private:
lldb::DataBufferSP m_gpr_buffer;
lldb_private::DataExtractor m_gpr;
};
-#endif // #ifndef liblldb_RegisterContextCorePOSIX_mips64_H_
+#endif // liblldb_RegisterContextCorePOSIX_mips64_h_
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
index d12df21a8664..9d8c97849ff8 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
@@ -10,7 +10,6 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
-#include "RegisterContextPOSIX.h"
#include "RegisterContextPOSIXCore_powerpc.h"
using namespace lldb_private;
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h
index a3590601fa7e..0f587fd1459c 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h
@@ -5,11 +5,15 @@
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextCorePOSIX_powerpc_H_
-#define liblldb_RegisterContextCorePOSIX_powerpc_H_
+#ifndef liblldb_RegisterContextCorePOSIX_powerpc_h_
+#define liblldb_RegisterContextCorePOSIX_powerpc_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/DataBufferHeap.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
@@ -23,41 +27,43 @@ public:
const lldb_private::DataExtractor &fpregset,
const lldb_private::DataExtractor &vregset);
- ~RegisterContextCorePOSIX_powerpc();
+ ~RegisterContextCorePOSIX_powerpc() override;
- virtual bool
- ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
bool
- HardwareSingleStep(bool enable);
+ HardwareSingleStep(bool enable) override;
protected:
bool
- ReadGPR();
+ ReadGPR() override;
bool
- ReadFPR();
+ ReadFPR() override;
bool
- ReadVMX();
+ ReadVMX() override;
bool
- WriteGPR();
+ WriteGPR() override;
bool
- WriteFPR();
+ WriteFPR() override;
bool
- WriteVMX();
+ WriteVMX() override;
private:
lldb::DataBufferSP m_gpr_buffer;
@@ -68,4 +74,4 @@ private:
lldb_private::DataExtractor m_vec;
};
-#endif // #ifndef liblldb_RegisterContextCorePOSIX_powerpc_H_
+#endif // liblldb_RegisterContextCorePOSIX_powerpc_h_
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
index 412c7ade8295..926c7aff3603 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
@@ -10,7 +10,6 @@
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
-#include "Plugins/Process/Utility/RegisterContextPOSIX.h"
#include "RegisterContextPOSIXCore_x86_64.h"
using namespace lldb_private;
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
index ac0f49c3db52..60f2ad33b4a5 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h
@@ -1,15 +1,19 @@
-//===-- RegisterContextCorePOSIX_x86_64.h ----------------------*- C++ -*-===//
+//===-- RegisterContextCorePOSIX_x86_64.h -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
-//===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
-#ifndef liblldb_RegisterContextCorePOSIX_x86_64_H_
-#define liblldb_RegisterContextCorePOSIX_x86_64_H_
+#ifndef liblldb_RegisterContextCorePOSIX_x86_64_h_
+#define liblldb_RegisterContextCorePOSIX_x86_64_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h"
class RegisterContextCorePOSIX_x86_64 :
@@ -21,38 +25,40 @@ public:
const lldb_private::DataExtractor &gpregset,
const lldb_private::DataExtractor &fpregset);
- ~RegisterContextCorePOSIX_x86_64();
+ ~RegisterContextCorePOSIX_x86_64() override;
- virtual bool
- ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+ bool
+ ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
- virtual bool
- WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+ bool
+ WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
bool
- ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+ ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
bool
- WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+ WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
bool
- HardwareSingleStep(bool enable);
+ HardwareSingleStep(bool enable) override;
protected:
bool
- ReadGPR();
+ ReadGPR() override;
bool
- ReadFPR();
+ ReadFPR() override;
bool
- WriteGPR();
+ WriteGPR() override;
bool
- WriteFPR();
+ WriteFPR() override;
private:
uint8_t *m_gpregset;
};
-#endif // #ifndef liblldb_RegisterContextCorePOSIX_x86_64_H_
+#endif // liblldb_RegisterContextCorePOSIX_x86_64_h_
diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp
index 2abb6ba5decd..9cc7829fc391 100644
--- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp
@@ -37,9 +37,8 @@ using namespace lldb_private;
//----------------------------------------------------------------------
// Construct a Thread object with given data
//----------------------------------------------------------------------
-ThreadElfCore::ThreadElfCore (Process &process, tid_t tid,
- const ThreadData &td) :
- Thread(process, tid),
+ThreadElfCore::ThreadElfCore (Process &process, const ThreadData &td) :
+ Thread(process, td.tid),
m_thread_name(td.name),
m_thread_reg_ctx_sp (),
m_signo(td.signo),
diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.h b/source/Plugins/Process/elf-core/ThreadElfCore.h
index 50502c101daf..d3a42e0eb54d 100644
--- a/source/Plugins/Process/elf-core/ThreadElfCore.h
+++ b/source/Plugins/Process/elf-core/ThreadElfCore.h
@@ -1,4 +1,4 @@
-//===-- ThreadElfCore.h ----------------------------------------*- C++ -*-===//
+//===-- ThreadElfCore.h -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,8 +10,12 @@
#ifndef liblldb_ThreadElfCore_h_
#define liblldb_ThreadElfCore_h_
+// C Includes
+// C++ Includes
#include <string>
+// Other libraries and framework includes
+// Project includes
#include "lldb/Target/Thread.h"
#include "lldb/Core/DataExtractor.h"
@@ -104,7 +108,6 @@ struct ELFLinuxPrPsInfo
return 0;
}
}
-
};
struct ThreadData
@@ -112,6 +115,7 @@ struct ThreadData
lldb_private::DataExtractor gpregset;
lldb_private::DataExtractor fpregset;
lldb_private::DataExtractor vregset;
+ lldb::tid_t tid;
int signo;
std::string name;
};
@@ -119,23 +123,21 @@ struct ThreadData
class ThreadElfCore : public lldb_private::Thread
{
public:
- ThreadElfCore (lldb_private::Process &process, lldb::tid_t tid,
- const ThreadData &td);
+ ThreadElfCore (lldb_private::Process &process, const ThreadData &td);
- virtual
- ~ThreadElfCore ();
+ ~ThreadElfCore() override;
- virtual void
- RefreshStateAfterStop();
+ void
+ RefreshStateAfterStop() override;
- virtual lldb::RegisterContextSP
- GetRegisterContext ();
+ lldb::RegisterContextSP
+ GetRegisterContext() override;
- virtual lldb::RegisterContextSP
- CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
- virtual void
- ClearStackFrames ();
+ void
+ ClearStackFrames() override;
static bool
ThreadIDIsValid (lldb::tid_t thread)
@@ -143,8 +145,8 @@ public:
return thread != 0;
}
- virtual const char *
- GetName ()
+ const char *
+ GetName() override
{
if (m_thread_name.empty())
return NULL;
@@ -152,7 +154,7 @@ public:
}
void
- SetName (const char *name)
+ SetName(const char *name) override
{
if (name && name[0])
m_thread_name.assign (name);
@@ -173,8 +175,7 @@ protected:
lldb_private::DataExtractor m_fpregset_data;
lldb_private::DataExtractor m_vregset_data;
- virtual bool CalculateStopInfo();
-
+ bool CalculateStopInfo() override;
};
-#endif // liblldb_ThreadElfCore_h_
+#endif // liblldb_ThreadElfCore_h_
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 9c263c8c4087..2ea1f206008a 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -30,6 +30,7 @@
#include "lldb/Host/StringConvert.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/TimeValue.h"
+#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "llvm/ADT/SmallString.h"
@@ -574,15 +575,24 @@ GDBRemoteCommunication::DecompressPacket ()
return true;
if (m_bytes[1] != 'C' && m_bytes[1] != 'N')
return true;
- if (m_bytes[pkt_size - 3] != '#')
+
+ size_t hash_mark_idx = m_bytes.find ('#');
+ if (hash_mark_idx == std::string::npos)
+ return true;
+ if (hash_mark_idx + 2 >= m_bytes.size())
return true;
- if (!::isxdigit (m_bytes[pkt_size - 2]) || !::isxdigit (m_bytes[pkt_size - 1]))
+
+ if (!::isxdigit (m_bytes[hash_mark_idx + 1]) || !::isxdigit (m_bytes[hash_mark_idx + 2]))
return true;
- size_t content_length = pkt_size - 5; // not counting '$', 'C' | 'N', '#', & the two hex checksum chars
- size_t content_start = 2; // The first character of the compressed/not-compressed text of the packet
- size_t hash_mark_idx = pkt_size - 3; // The '#' character marking the end of the packet
- size_t checksum_idx = pkt_size - 2; // The first character of the two hex checksum characters
+ size_t content_length = pkt_size - 5; // not counting '$', 'C' | 'N', '#', & the two hex checksum chars
+ size_t content_start = 2; // The first character of the compressed/not-compressed text of the packet
+ size_t checksum_idx = hash_mark_idx + 1; // The first character of the two hex checksum characters
+
+ // Normally size_of_first_packet == m_bytes.size() but m_bytes may contain multiple packets.
+ // size_of_first_packet is the size of the initial packet which we'll replace with the decompressed
+ // version of, leaving the rest of m_bytes unmodified.
+ size_t size_of_first_packet = hash_mark_idx + 3;
// Compressed packets ("$C") start with a base10 number which is the size of the uncompressed payload,
// then a : and then the compressed data. e.g. $C1024:<binary>#00
@@ -604,7 +614,7 @@ GDBRemoteCommunication::DecompressPacket ()
decompressed_bufsize = ::strtoul (bufsize_str.c_str(), NULL, 10);
if (errno != 0 || decompressed_bufsize == ULONG_MAX)
{
- m_bytes.erase (0, pkt_size);
+ m_bytes.erase (0, size_of_first_packet);
return false;
}
}
@@ -633,7 +643,7 @@ GDBRemoteCommunication::DecompressPacket ()
if (!success)
{
SendNack();
- m_bytes.erase (0, pkt_size);
+ m_bytes.erase (0, size_of_first_packet);
return false;
}
else
@@ -677,7 +687,7 @@ GDBRemoteCommunication::DecompressPacket ()
decompressed_buffer = (uint8_t *) malloc (decompressed_bufsize + 1);
if (decompressed_buffer == nullptr)
{
- m_bytes.erase (0, pkt_size);
+ m_bytes.erase (0, size_of_first_packet);
return false;
}
@@ -751,7 +761,7 @@ GDBRemoteCommunication::DecompressPacket ()
{
if (decompressed_buffer)
free (decompressed_buffer);
- m_bytes.erase (0, pkt_size);
+ m_bytes.erase (0, size_of_first_packet);
return false;
}
@@ -773,7 +783,7 @@ GDBRemoteCommunication::DecompressPacket ()
new_packet.push_back ('0');
}
- m_bytes = new_packet;
+ m_bytes.replace (0, size_of_first_packet, new_packet.data(), new_packet.size());
free (decompressed_buffer);
return true;
@@ -927,8 +937,10 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri
{
for (size_t i=0; !binary && i<total_length; ++i)
{
- if (isprint(m_bytes[i]) == 0)
+ if (isprint (m_bytes[i]) == 0 && isspace (m_bytes[i]) == 0)
+ {
binary = true;
+ }
}
}
if (binary)
@@ -1100,16 +1112,16 @@ GDBRemoteCommunication::ListenThread (lldb::thread_arg_t arg)
}
Error
-GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
- uint16_t in_port,
+GDBRemoteCommunication::StartDebugserverProcess (const char *url,
+ Platform *platform,
ProcessLaunchInfo &launch_info,
- uint16_t &out_port)
+ uint16_t *port,
+ const Args& inferior_args)
{
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
if (log)
- log->Printf ("GDBRemoteCommunication::%s(hostname=%s, in_port=%" PRIu16 ", out_port=%" PRIu16, __FUNCTION__, hostname ? hostname : "<empty>", in_port, out_port);
+ log->Printf ("GDBRemoteCommunication::%s(url=%s, port=%" PRIu16, __FUNCTION__, url ? url : "<empty>", port ? *port : uint16_t(0));
- out_port = in_port;
Error error;
// If we locate debugserver, keep that located version around
static FileSpec g_debugserver_file_spec;
@@ -1146,11 +1158,20 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
}
else
{
- if (log)
- log->Printf ("GDBRemoteCommunication::%s() could not find gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ());
-
+ debugserver_file_spec = platform->LocateExecutable(DEBUGSERVER_BASENAME);
+ if (debugserver_file_spec)
+ {
+ // Platform::LocateExecutable() wouldn't return a path if it doesn't exist
+ debugserver_exists = true;
+ }
+ else
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunication::%s() could not find gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ());
+ }
+ // Don't cache the platform specific GDB server binary as it could change
+ // from platform to platform
g_debugserver_file_spec.Clear();
- debugserver_file_spec.Clear();
}
}
}
@@ -1171,17 +1192,9 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
debugserver_args.AppendArgument("gdbserver");
#endif
- // If a host and port is supplied then use it
- char host_and_port[128];
- if (hostname)
- {
- snprintf (host_and_port, sizeof(host_and_port), "%s:%u", hostname, in_port);
- debugserver_args.AppendArgument(host_and_port);
- }
- else
- {
- host_and_port[0] = '\0';
- }
+ // If a url is supplied then use it
+ if (url)
+ debugserver_args.AppendArgument(url);
// use native registers, not the GDB registers
debugserver_args.AppendArgument("--native-regs");
@@ -1192,30 +1205,41 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
}
llvm::SmallString<PATH_MAX> named_pipe_path;
- Pipe port_pipe;
-
- if (host_and_port[0] && in_port == 0)
+ // socket_pipe is used by debug server to communicate back either
+ // TCP port or domain socket name which it listens on.
+ // The second purpose of the pipe to serve as a synchronization point -
+ // once data is written to the pipe, debug server is up and running.
+ Pipe socket_pipe;
+
+ // port is null when debug server should listen on domain socket -
+ // we're not interested in port value but rather waiting for debug server
+ // to become available.
+ if ((port != nullptr && *port == 0) || port == nullptr)
{
- // Create a temporary file to get the stdout/stderr and redirect the
- // output of the command into this file. We will later read this file
- // if all goes well and fill the data into "command_output_ptr"
-
- // Binding to port zero, we need to figure out what port it ends up
- // using using a named pipe...
- error = port_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path);
- if (error.Success())
+ if (url)
{
+ // Create a temporary file to get the stdout/stderr and redirect the
+ // output of the command into this file. We will later read this file
+ // if all goes well and fill the data into "command_output_ptr"
+
+#if defined(__APPLE__)
+ // Binding to port zero, we need to figure out what port it ends up
+ // using using a named pipe...
+ error = socket_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path);
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf("GDBRemoteCommunication::%s() "
+ "named pipe creation failed: %s",
+ __FUNCTION__, error.AsCString());
+ return error;
+ }
debugserver_args.AppendArgument("--named-pipe");
debugserver_args.AppendArgument(named_pipe_path.c_str());
- }
- else
- {
- if (log)
- log->Printf("GDBRemoteCommunication::%s() "
- "named pipe creation failed: %s",
- __FUNCTION__, error.AsCString());
- // let's try an unnamed pipe
- error = port_pipe.CreateNew(true);
+#else
+ // Binding to port zero, we need to figure out what port it ends up
+ // using using an unnamed pipe...
+ error = socket_pipe.CreateNew(true);
if (error.Fail())
{
if (log)
@@ -1224,42 +1248,43 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
__FUNCTION__, error.AsCString());
return error;
}
- int write_fd = port_pipe.GetWriteFileDescriptor();
+ int write_fd = socket_pipe.GetWriteFileDescriptor();
debugserver_args.AppendArgument("--pipe");
debugserver_args.AppendArgument(std::to_string(write_fd).c_str());
- launch_info.AppendCloseFileAction(port_pipe.GetReadFileDescriptor());
- }
- }
- else
- {
- // No host and port given, so lets listen on our end and make the debugserver
- // connect to us..
- error = StartListenThread ("127.0.0.1", 0);
- if (error.Fail())
- {
- if (log)
- log->Printf ("GDBRemoteCommunication::%s() unable to start listen thread: %s", __FUNCTION__, error.AsCString());
- return error;
- }
-
- ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection ();
- // Wait for 10 seconds to resolve the bound port
- out_port = connection->GetListeningPort(10);
- if (out_port > 0)
- {
- char port_cstr[32];
- snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", out_port);
- // Send the host and port down that debugserver and specify an option
- // so that it connects back to the port we are listening to in this process
- debugserver_args.AppendArgument("--reverse-connect");
- debugserver_args.AppendArgument(port_cstr);
+ launch_info.AppendCloseFileAction(socket_pipe.GetReadFileDescriptor());
+#endif
}
else
{
- error.SetErrorString ("failed to bind to port 0 on 127.0.0.1");
- if (log)
- log->Printf ("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, error.AsCString());
- return error;
+ // No host and port given, so lets listen on our end and make the debugserver
+ // connect to us..
+ error = StartListenThread ("127.0.0.1", 0);
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunication::%s() unable to start listen thread: %s", __FUNCTION__, error.AsCString());
+ return error;
+ }
+
+ ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection ();
+ // Wait for 10 seconds to resolve the bound port
+ *port = connection->GetListeningPort(10);
+ if (*port > 0)
+ {
+ char port_cstr[32];
+ snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", *port);
+ // Send the host and port down that debugserver and specify an option
+ // so that it connects back to the port we are listening to in this process
+ debugserver_args.AppendArgument("--reverse-connect");
+ debugserver_args.AppendArgument(port_cstr);
+ }
+ else
+ {
+ error.SetErrorString ("failed to bind to port 0 on 127.0.0.1");
+ if (log)
+ log->Printf ("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, error.AsCString());
+ return error;
+ }
}
}
@@ -1304,6 +1329,20 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
}
} while (has_env_var);
+ if (inferior_args.GetArgumentCount() > 0)
+ {
+ debugserver_args.AppendArgument ("--");
+ debugserver_args.AppendArguments (inferior_args);
+ }
+
+ // Copy the current environment to the gdbserver/debugserver instance
+ StringList env;
+ if (Host::GetEnvironment(env))
+ {
+ for (size_t i = 0; i < env.GetSize(); ++i)
+ launch_info.GetEnvironmentEntries().AppendArgument(env[i].c_str());
+ }
+
// Close STDIN, STDOUT and STDERR.
launch_info.AppendCloseFileAction (STDIN_FILENO);
launch_info.AppendCloseFileAction (STDOUT_FILENO);
@@ -1316,11 +1355,12 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
error = Host::LaunchProcess(launch_info);
- if (error.Success() && launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
+ if (error.Success() &&
+ launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
{
if (named_pipe_path.size() > 0)
{
- error = port_pipe.OpenAsReader(named_pipe_path, false);
+ error = socket_pipe.OpenAsReader(named_pipe_path, false);
if (error.Fail())
if (log)
log->Printf("GDBRemoteCommunication::%s() "
@@ -1328,24 +1368,24 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
__FUNCTION__, named_pipe_path.c_str(), error.AsCString());
}
- if (port_pipe.CanWrite())
- port_pipe.CloseWriteFileDescriptor();
- if (port_pipe.CanRead())
+ if (socket_pipe.CanWrite())
+ socket_pipe.CloseWriteFileDescriptor();
+ if (socket_pipe.CanRead())
{
- char port_cstr[256];
+ char port_cstr[PATH_MAX] = {0};
port_cstr[0] = '\0';
size_t num_bytes = sizeof(port_cstr);
// Read port from pipe with 10 second timeout.
- error = port_pipe.ReadWithTimeout(port_cstr, num_bytes,
+ error = socket_pipe.ReadWithTimeout(port_cstr, num_bytes,
std::chrono::seconds{10}, num_bytes);
- if (error.Success())
+ if (error.Success() && (port != nullptr))
{
assert(num_bytes > 0 && port_cstr[num_bytes-1] == '\0');
- out_port = StringConvert::ToUInt32(port_cstr, 0);
+ *port = StringConvert::ToUInt32(port_cstr, 0);
if (log)
log->Printf("GDBRemoteCommunication::%s() "
- "debugserver listens %u port",
- __FUNCTION__, out_port);
+ "debugserver listens %u port",
+ __FUNCTION__, *port);
}
else
{
@@ -1355,12 +1395,12 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
__FUNCTION__, named_pipe_path.c_str(), error.AsCString());
}
- port_pipe.Close();
+ socket_pipe.Close();
}
if (named_pipe_path.size() > 0)
{
- const auto err = port_pipe.Delete(named_pipe_path);
+ const auto err = socket_pipe.Delete(named_pipe_path);
if (err.Fail())
{
if (log)
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index 7379bb3aa09b..2a01bcec260c 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -12,9 +12,9 @@
// C Includes
// C++ Includes
-#include <list>
#include <string>
#include <queue>
+#include <vector>
// Other libraries and framework includes
// Project includes
@@ -25,6 +25,7 @@
#include "lldb/Host/Mutex.h"
#include "lldb/Host/Predicate.h"
#include "lldb/Host/TimeValue.h"
+#include "lldb/Interpreter/Args.h"
#include "Utility/StringExtractorGDBRemote.h"
@@ -94,14 +95,10 @@ public:
uint32_t m_saved_timeout;
};
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
GDBRemoteCommunication(const char *comm_name,
const char *listener_name);
- virtual
- ~GDBRemoteCommunication();
+ ~GDBRemoteCommunication() override;
PacketResult
GetAck ();
@@ -117,12 +114,13 @@ public:
size_t payload_length);
bool
- GetSequenceMutex (Mutex::Locker& locker, const char *failure_message = NULL);
+ GetSequenceMutex(Mutex::Locker& locker, const char *failure_message = nullptr);
PacketType
CheckForPacket (const uint8_t *src,
size_t src_len,
StringExtractorGDBRemote &packet);
+
bool
IsRunning() const
{
@@ -162,21 +160,22 @@ public:
{
return m_packet_timeout * TimeValue::MicroSecPerSec;
}
+
//------------------------------------------------------------------
// Start a debugserver instance on the current host using the
// supplied connection URL.
//------------------------------------------------------------------
Error
- StartDebugserverProcess (const char *hostname,
- uint16_t in_port, // If set to zero, then out_port will contain the bound port on exit
- ProcessLaunchInfo &launch_info,
- uint16_t &out_port);
+ StartDebugserverProcess(const char *url,
+ Platform *platform, // If non nullptr, then check with the platform for the GDB server binary if it can't be located
+ ProcessLaunchInfo &launch_info,
+ uint16_t *port,
+ const Args& inferior_args = Args());
void
DumpHistory(Stream &strm);
protected:
-
class History
{
public:
@@ -223,6 +222,7 @@ protected:
AddPacket (char packet_char,
PacketType type,
uint32_t bytes_transmitted);
+
void
AddPacket (const std::string &src,
uint32_t src_len,
@@ -241,7 +241,7 @@ protected:
return m_dumped_to_log;
}
-protected:
+ protected:
uint32_t
GetFirstSavedPacketIndex () const
{
@@ -275,13 +275,30 @@ protected:
return i % m_packets.size();
}
-
std::vector<Entry> m_packets;
uint32_t m_curr_idx;
uint32_t m_total_packet_count;
mutable bool m_dumped_to_log;
};
+ uint32_t m_packet_timeout;
+ uint32_t m_echo_number;
+ LazyBool m_supports_qEcho;
+#ifdef ENABLE_MUTEX_ERROR_CHECKING
+ TrackingMutex m_sequence_mutex;
+#else
+ Mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time
+#endif
+ Predicate<bool> m_public_is_running;
+ Predicate<bool> m_private_is_running;
+ History m_history;
+ bool m_send_acks;
+ bool m_is_platform; // Set to true if this class represents a platform,
+ // false if this class represents a debug session for
+ // a single process
+
+ CompressionType m_compression_type;
+
PacketResult
SendPacket (const char *payload,
size_t payload_length);
@@ -321,27 +338,6 @@ protected:
bool
DecompressPacket ();
- //------------------------------------------------------------------
- // Classes that inherit from GDBRemoteCommunication can see and modify these
- //------------------------------------------------------------------
- uint32_t m_packet_timeout;
- uint32_t m_echo_number;
- LazyBool m_supports_qEcho;
-#ifdef ENABLE_MUTEX_ERROR_CHECKING
- TrackingMutex m_sequence_mutex;
-#else
- Mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time
-#endif
- Predicate<bool> m_public_is_running;
- Predicate<bool> m_private_is_running;
- History m_history;
- bool m_send_acks;
- bool m_is_platform; // Set to true if this class represents a platform,
- // false if this class represents a debug session for
- // a single process
-
- CompressionType m_compression_type;
-
Error
StartListenThread (const char *hostname = "127.0.0.1", uint16_t port = 0);
@@ -361,10 +357,12 @@ protected:
// This method is defined as part of communication.h
// when the read thread gets any bytes it will pass them on to this function
- virtual void AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, lldb::ConnectionStatus status);
+ void AppendBytesToCache(const uint8_t * bytes,
+ size_t len,
+ bool broadcast,
+ lldb::ConnectionStatus status) override;
private:
-
std::queue<StringExtractorGDBRemote> m_packet_queue; // The packet queue
lldb_private::Mutex m_packet_queue_mutex; // Mutex for accessing queue
Condition m_condition_queue_not_empty; // Condition variable to wait for packets
@@ -372,13 +370,10 @@ private:
HostThread m_listen_thread;
std::string m_listen_url;
- //------------------------------------------------------------------
- // For GDBRemoteCommunication only
- //------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunication);
};
} // namespace process_gdb_remote
} // namespace lldb_private
-#endif // liblldb_GDBRemoteCommunication_h_
+#endif // liblldb_GDBRemoteCommunication_h_
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index b8c67c593b1f..5c7f6caca511 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -619,7 +619,6 @@ GDBRemoteCommunicationClient::GetThreadsInfo()
if (m_supports_jThreadsInfo)
{
StringExtractorGDBRemote response;
- m_supports_jThreadExtendedInfo = eLazyBoolNo;
if (SendPacketAndWaitForResponse("jThreadsInfo", response, false) == PacketResult::Success)
{
if (response.IsUnsupportedResponse())
@@ -782,7 +781,7 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
// In order to stop async notifications from being processed in the middle of the
- // send/recieve sequence Hijack the broadcast. Then rebroadcast any events when we are done.
+ // send/receive sequence Hijack the broadcast. Then rebroadcast any events when we are done.
static Listener hijack_listener("lldb.NotifyHijacker");
HijackBroadcaster(&hijack_listener, eBroadcastBitGdbReadThreadGotNotify);
@@ -878,10 +877,10 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
}
}
- // Remove our Hijacking listner from the broadcast.
+ // Remove our Hijacking listener from the broadcast.
RestoreBroadcaster();
- // If a notification event occured, rebroadcast since it can now be processed safely.
+ // If a notification event occurred, rebroadcast since it can now be processed safely.
EventSP event_sp;
if (hijack_listener.GetNextEvent(event_sp))
BroadcastEvent(event_sp);
@@ -1050,7 +1049,6 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
Mutex::Locker locker(m_sequence_mutex);
StateType state = eStateRunning;
- BroadcastEvent(eBroadcastBitRunPacketSent, NULL);
m_public_is_running.SetValue (true, eBroadcastNever);
// Set the starting continue packet into "continue_packet". This packet
// may change if we are interrupted and we continue after an async packet...
@@ -1060,6 +1058,7 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
const auto sigint_signo = process->GetUnixSignals()->GetSignalNumberFromName("SIGINT");
bool got_async_packet = false;
+ bool broadcast_sent = false;
while (state == eStateRunning)
{
@@ -1072,6 +1071,12 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
else
m_interrupt_sent = false;
+ if (! broadcast_sent)
+ {
+ BroadcastEvent(eBroadcastBitRunPacketSent, NULL);
+ broadcast_sent = true;
+ }
+
m_private_is_running.SetValue (true, eBroadcastAlways);
}
@@ -1133,10 +1138,10 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
continue_after_async = false;
// We didn't get a SIGINT or SIGSTOP, so try for a
- // very brief time (1 ms) to get another stop reply
+ // very brief time (0.1s) to get another stop reply
// packet to make sure it doesn't get in the way
StringExtractorGDBRemote extra_stop_reply_packet;
- uint32_t timeout_usec = 1000;
+ uint32_t timeout_usec = 100000;
if (ReadPacket (extra_stop_reply_packet, timeout_usec, false) == PacketResult::Success)
{
switch (extra_stop_reply_packet.GetChar())
@@ -1262,9 +1267,13 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
got_async_packet = true;
std::string inferior_stdout;
inferior_stdout.reserve(response.GetBytesLeft () / 2);
- char ch;
- while ((ch = response.GetHexU8()) != '\0')
- inferior_stdout.append(1, ch);
+
+ uint8_t ch;
+ while (response.GetHexU8Ex(ch))
+ {
+ if (ch != 0)
+ inferior_stdout.append(1, (char)ch);
+ }
process->AppendSTDOUT (inferior_stdout.c_str(), inferior_stdout.size());
}
break;
@@ -1574,6 +1583,8 @@ GDBRemoteCommunicationClient::SendEnvironmentPacket (char const *name_equal_valu
{
case '$':
case '#':
+ case '*':
+ case '}':
send_hex_encoding = true;
break;
default:
@@ -2308,7 +2319,8 @@ GDBRemoteCommunicationClient::Detach (bool keep_stopped)
const int packet_len = ::snprintf(packet, sizeof(packet), "qSupportsDetachAndStayStopped:");
assert (packet_len < (int)sizeof(packet));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
+ if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success
+ && response.IsOKResponse())
{
m_supports_detach_stay_stopped = eLazyBoolYes;
}
@@ -2326,7 +2338,7 @@ GDBRemoteCommunicationClient::Detach (bool keep_stopped)
else
{
StringExtractorGDBRemote response;
- PacketResult packet_result = SendPacketAndWaitForResponse ("D1", 1, response, false);
+ PacketResult packet_result = SendPacketAndWaitForResponse ("D1", 2, response, false);
if (packet_result != PacketResult::Success)
error.SetErrorString ("Sending extended disconnect packet failed.");
}
@@ -3311,10 +3323,16 @@ GDBRemoteCommunicationClient::SendSpeedTestPacket (uint32_t send_size, uint32_t
return SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success;
}
-uint16_t
-GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const char *remote_accept_hostname)
+bool
+GDBRemoteCommunicationClient::LaunchGDBServer (const char *remote_accept_hostname,
+ lldb::pid_t &pid,
+ uint16_t &port,
+ std::string &socket_name)
{
pid = LLDB_INVALID_PROCESS_ID;
+ port = 0;
+ socket_name.clear();
+
StringExtractorGDBRemote response;
StreamString stream;
stream.PutCString("qLaunchGDBServer;");
@@ -3339,22 +3357,67 @@ GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const
// give the process a few seconds to startup
GDBRemoteCommunication::ScopedTimeout timeout (*this, 10);
-
+
if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
std::string name;
std::string value;
- uint16_t port = 0;
+ StringExtractor extractor;
while (response.GetNameColonValue(name, value))
{
if (name.compare("port") == 0)
port = StringConvert::ToUInt32(value.c_str(), 0, 0);
else if (name.compare("pid") == 0)
pid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_PROCESS_ID, 0);
+ else if (name.compare("socket_name") == 0)
+ {
+ extractor.GetStringRef().swap(value);
+ extractor.SetFilePos(0);
+ extractor.GetHexByteString(value);
+
+ socket_name = value;
+ }
}
- return port;
+ return true;
}
- return 0;
+ return false;
+}
+
+size_t
+GDBRemoteCommunicationClient::QueryGDBServer (std::vector<std::pair<uint16_t, std::string>>& connection_urls)
+{
+ connection_urls.clear();
+
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse("qQueryGDBServer", response, false) != PacketResult::Success)
+ return 0;
+
+ StructuredData::ObjectSP data = StructuredData::ParseJSON(response.GetStringRef());
+ if (!data)
+ return 0;
+
+ StructuredData::Array* array = data->GetAsArray();
+ if (!array)
+ return 0;
+
+ for (size_t i = 0, count = array->GetSize(); i < count; ++i)
+ {
+ StructuredData::Dictionary* element = nullptr;
+ if (!array->GetItemAtIndexAsDictionary(i, element))
+ continue;
+
+ uint16_t port = 0;
+ if (StructuredData::ObjectSP port_osp = element->GetValueForKey(llvm::StringRef("port")))
+ port = port_osp->GetIntegerValue(0);
+
+ std::string socket_name;
+ if (StructuredData::ObjectSP socket_name_osp = element->GetValueForKey(llvm::StringRef("socket_name")))
+ socket_name = socket_name_osp->GetStringValue();
+
+ if (port != 0 || !socket_name.empty())
+ connection_urls.emplace_back(port, socket_name);
+ }
+ return connection_urls.size();
}
bool
@@ -3395,6 +3458,17 @@ GDBRemoteCommunicationClient::SetCurrentThread (uint64_t tid)
m_curr_tid = tid;
return true;
}
+
+ /*
+ * Connected bare-iron target (like YAMON gdb-stub) may not have support for Hg packet.
+ * The reply from '?' packet could be as simple as 'S05'. There is no packet which can
+ * give us pid and/or tid. Assume pid=tid=1 in such cases.
+ */
+ if (response.IsUnsupportedResponse() && IsConnected())
+ {
+ m_curr_tid = 1;
+ return true;
+ }
}
return false;
}
@@ -3421,6 +3495,17 @@ GDBRemoteCommunicationClient::SetCurrentThreadForRun (uint64_t tid)
m_curr_tid_run = tid;
return true;
}
+
+ /*
+ * Connected bare-iron target (like YAMON gdb-stub) may not have support for Hc packet.
+ * The reply from '?' packet could be as simple as 'S05'. There is no packet which can
+ * give us pid and/or tid. Assume pid=tid=1 in such cases.
+ */
+ if (response.IsUnsupportedResponse() && IsConnected())
+ {
+ m_curr_tid_run = 1;
+ return true;
+ }
}
return false;
}
@@ -3546,6 +3631,17 @@ GDBRemoteCommunicationClient::GetCurrentThreadIDs (std::vector<lldb::tid_t> &thr
} while (ch == ','); // Make sure we got a comma separator
}
}
+
+ /*
+ * Connected bare-iron target (like YAMON gdb-stub) may not have support for
+ * qProcessInfo, qC and qfThreadInfo packets. The reply from '?' packet could
+ * be as simple as 'S05'. There is no packet which can give us pid and/or tid.
+ * Assume pid=tid=1 in such cases.
+ */
+ if (response.IsUnsupportedResponse() && thread_ids.size() == 0 && IsConnected())
+ {
+ thread_ids.push_back (1);
+ }
}
else
{
@@ -4347,100 +4443,97 @@ GDBRemoteCommunicationClient::ServeSymbolLookups(lldb_private::Process *process)
{
StreamString packet;
packet.PutCString ("qSymbol::");
- while (1)
+ StringExtractorGDBRemote response;
+ while (SendPacketAndWaitForResponseNoLock(packet.GetData(), packet.GetSize(), response) == PacketResult::Success)
{
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponseNoLock(packet.GetData(), packet.GetSize(), response) == PacketResult::Success)
+ if (response.IsOKResponse())
{
- if (response.IsOKResponse())
- {
- // We are done serving symbols requests
- return;
- }
+ // We are done serving symbols requests
+ return;
+ }
- if (response.IsUnsupportedResponse())
- {
- // qSymbol is not supported by the current GDB server we are connected to
- m_supports_qSymbol = false;
- return;
- }
- else
+ if (response.IsUnsupportedResponse())
+ {
+ // qSymbol is not supported by the current GDB server we are connected to
+ m_supports_qSymbol = false;
+ return;
+ }
+ else
+ {
+ llvm::StringRef response_str(response.GetStringRef());
+ if (response_str.startswith("qSymbol:"))
{
- llvm::StringRef response_str(response.GetStringRef());
- if (response_str.startswith("qSymbol:"))
+ response.SetFilePos(strlen("qSymbol:"));
+ std::string symbol_name;
+ if (response.GetHexByteString(symbol_name))
{
- response.SetFilePos(strlen("qSymbol:"));
- std::string symbol_name;
- if (response.GetHexByteString(symbol_name))
- {
- if (symbol_name.empty())
- return;
+ if (symbol_name.empty())
+ return;
- addr_t symbol_load_addr = LLDB_INVALID_ADDRESS;
- lldb_private::SymbolContextList sc_list;
- if (process->GetTarget().GetImages().FindSymbolsWithNameAndType(ConstString(symbol_name), eSymbolTypeAny, sc_list))
+ addr_t symbol_load_addr = LLDB_INVALID_ADDRESS;
+ lldb_private::SymbolContextList sc_list;
+ if (process->GetTarget().GetImages().FindSymbolsWithNameAndType(ConstString(symbol_name), eSymbolTypeAny, sc_list))
+ {
+ const size_t num_scs = sc_list.GetSize();
+ for (size_t sc_idx=0; sc_idx<num_scs && symbol_load_addr == LLDB_INVALID_ADDRESS; ++sc_idx)
{
- const size_t num_scs = sc_list.GetSize();
- for (size_t sc_idx=0; sc_idx<num_scs && symbol_load_addr == LLDB_INVALID_ADDRESS; ++sc_idx)
+ SymbolContext sc;
+ if (sc_list.GetContextAtIndex(sc_idx, sc))
{
- SymbolContext sc;
- if (sc_list.GetContextAtIndex(sc_idx, sc))
+ if (sc.symbol)
{
- if (sc.symbol)
+ switch (sc.symbol->GetType())
{
- switch (sc.symbol->GetType())
- {
- case eSymbolTypeInvalid:
- case eSymbolTypeAbsolute:
- case eSymbolTypeUndefined:
- case eSymbolTypeSourceFile:
- case eSymbolTypeHeaderFile:
- case eSymbolTypeObjectFile:
- case eSymbolTypeCommonBlock:
- case eSymbolTypeBlock:
- case eSymbolTypeLocal:
- case eSymbolTypeParam:
- case eSymbolTypeVariable:
- case eSymbolTypeVariableType:
- case eSymbolTypeLineEntry:
- case eSymbolTypeLineHeader:
- case eSymbolTypeScopeBegin:
- case eSymbolTypeScopeEnd:
- case eSymbolTypeAdditional:
- case eSymbolTypeCompiler:
- case eSymbolTypeInstrumentation:
- case eSymbolTypeTrampoline:
- break;
-
- case eSymbolTypeCode:
- case eSymbolTypeResolver:
- case eSymbolTypeData:
- case eSymbolTypeRuntime:
- case eSymbolTypeException:
- case eSymbolTypeObjCClass:
- case eSymbolTypeObjCMetaClass:
- case eSymbolTypeObjCIVar:
- case eSymbolTypeReExported:
- symbol_load_addr = sc.symbol->GetLoadAddress(&process->GetTarget());
- break;
- }
+ case eSymbolTypeInvalid:
+ case eSymbolTypeAbsolute:
+ case eSymbolTypeUndefined:
+ case eSymbolTypeSourceFile:
+ case eSymbolTypeHeaderFile:
+ case eSymbolTypeObjectFile:
+ case eSymbolTypeCommonBlock:
+ case eSymbolTypeBlock:
+ case eSymbolTypeLocal:
+ case eSymbolTypeParam:
+ case eSymbolTypeVariable:
+ case eSymbolTypeVariableType:
+ case eSymbolTypeLineEntry:
+ case eSymbolTypeLineHeader:
+ case eSymbolTypeScopeBegin:
+ case eSymbolTypeScopeEnd:
+ case eSymbolTypeAdditional:
+ case eSymbolTypeCompiler:
+ case eSymbolTypeInstrumentation:
+ case eSymbolTypeTrampoline:
+ break;
+
+ case eSymbolTypeCode:
+ case eSymbolTypeResolver:
+ case eSymbolTypeData:
+ case eSymbolTypeRuntime:
+ case eSymbolTypeException:
+ case eSymbolTypeObjCClass:
+ case eSymbolTypeObjCMetaClass:
+ case eSymbolTypeObjCIVar:
+ case eSymbolTypeReExported:
+ symbol_load_addr = sc.symbol->GetLoadAddress(&process->GetTarget());
+ break;
}
}
}
}
- // This is the normal path where our symbol lookup was successful and we want
- // to send a packet with the new symbol value and see if another lookup needs to be
- // done.
-
- // Change "packet" to contain the requested symbol value and name
- packet.Clear();
- packet.PutCString("qSymbol:");
- if (symbol_load_addr != LLDB_INVALID_ADDRESS)
- packet.Printf("%" PRIx64, symbol_load_addr);
- packet.PutCString(":");
- packet.PutBytesAsRawHex8(symbol_name.data(), symbol_name.size());
- continue; // go back to the while loop and send "packet" and wait for another response
}
+ // This is the normal path where our symbol lookup was successful and we want
+ // to send a packet with the new symbol value and see if another lookup needs to be
+ // done.
+
+ // Change "packet" to contain the requested symbol value and name
+ packet.Clear();
+ packet.PutCString("qSymbol:");
+ if (symbol_load_addr != LLDB_INVALID_ADDRESS)
+ packet.Printf("%" PRIx64, symbol_load_addr);
+ packet.PutCString(":");
+ packet.PutBytesAsRawHex8(symbol_name.data(), symbol_name.size());
+ continue; // go back to the while loop and send "packet" and wait for another response
}
}
}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index b08ff0647797..d2df214d0dba 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -12,6 +12,8 @@
// C Includes
// C++ Includes
+#include <map>
+#include <string>
#include <vector>
// Other libraries and framework includes
@@ -28,12 +30,9 @@ namespace process_gdb_remote {
class GDBRemoteCommunicationClient : public GDBRemoteCommunication
{
public:
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
GDBRemoteCommunicationClient();
- ~GDBRemoteCommunicationClient();
+ ~GDBRemoteCommunicationClient() override;
//------------------------------------------------------------------
// After connecting, send the handshake to the server to make sure
@@ -79,6 +78,7 @@ public:
const char *packet_payload,
size_t packet_length,
StringExtractorGDBRemote &response);
+
bool
SendvContPacket (ProcessGDBRemote *process,
const char *payload,
@@ -114,9 +114,15 @@ public:
bool
GetLaunchSuccess (std::string &error_str);
- uint16_t
- LaunchGDBserverAndGetPort (lldb::pid_t &pid, const char *remote_accept_hostname);
-
+ bool
+ LaunchGDBServer (const char *remote_accept_hostname,
+ lldb::pid_t &pid,
+ uint16_t &port,
+ std::string &socket_name);
+
+ size_t
+ QueryGDBServer (std::vector<std::pair<uint16_t, std::string>>& connection_urls);
+
bool
KillSpawnedProcess (lldb::pid_t pid);
@@ -161,7 +167,7 @@ public:
SendLaunchArchPacket (const char *arch);
int
- SendLaunchEventDataPacket (const char *data, bool *was_supported = NULL);
+ SendLaunchEventDataPacket(const char *data, bool *was_supported = nullptr);
//------------------------------------------------------------------
/// Sends a "vAttach:PID" where PID is in hex.
@@ -182,7 +188,6 @@ public:
SendAttach (lldb::pid_t pid,
StringExtractorGDBRemote& response);
-
//------------------------------------------------------------------
/// Sends a GDB remote protocol 'I' packet that delivers stdin
/// data to the remote process.
@@ -396,6 +401,7 @@ public:
default: return false;
}
}
+
uint8_t
SendGDBStoppointTypePacket (GDBStoppointType type, // Type of breakpoint or watchpoint
bool insert, // Insert or remove?
@@ -505,11 +511,11 @@ public:
GetFileExists (const FileSpec& file_spec);
Error
- RunShellCommand(const char *command, // Shouldn't be NULL
+ RunShellCommand(const char *command, // Shouldn't be nullptr
const FileSpec &working_dir, // Pass empty FileSpec to use the current working directory
- int *status_ptr, // Pass NULL if you don't want the process exit status
- int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
- std::string *command_output, // Pass NULL if you don't want the command output
+ int *status_ptr, // Pass nullptr if you don't want the process exit status
+ int *signo_ptr, // Pass nullptr if you don't want the signal that caused the process to exit
+ std::string *command_output, // Pass nullptr if you don't want the command output
uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish
bool
@@ -567,26 +573,6 @@ public:
ServeSymbolLookups(lldb_private::Process *process);
protected:
-
- PacketResult
- SendPacketAndWaitForResponseNoLock (const char *payload,
- size_t payload_length,
- StringExtractorGDBRemote &response);
-
- bool
- GetCurrentProcessInfo (bool allow_lazy_pid = true);
-
- bool
- GetGDBServerVersion();
-
- // Given the list of compression types that the remote debug stub can support,
- // possibly enable compression if we find an encoding we can handle.
- void
- MaybeEnableCompression (std::vector<std::string> supported_compressions);
-
- //------------------------------------------------------------------
- // Classes that inherit from GDBRemoteCommunicationClient can see and modify these
- //------------------------------------------------------------------
LazyBool m_supports_not_sending_acks;
LazyBool m_supports_thread_suffix;
LazyBool m_supports_threads_in_stop_reply;
@@ -639,7 +625,6 @@ protected:
lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all other operations
lldb::tid_t m_curr_tid_run; // Current gdb remote protocol thread index for continue, step, etc
-
uint32_t m_num_supported_hardware_watchpoints;
// If we need to send a packet while the target is running, the m_async_XXX
@@ -667,18 +652,31 @@ protected:
uint32_t m_default_packet_timeout;
uint64_t m_max_packet_size; // as returned by qSupported
-
+ PacketResult
+ SendPacketAndWaitForResponseNoLock (const char *payload,
+ size_t payload_length,
+ StringExtractorGDBRemote &response);
+
+ bool
+ GetCurrentProcessInfo (bool allow_lazy_pid = true);
+
+ bool
+ GetGDBServerVersion();
+
+ // Given the list of compression types that the remote debug stub can support,
+ // possibly enable compression if we find an encoding we can handle.
+ void
+ MaybeEnableCompression (std::vector<std::string> supported_compressions);
+
bool
DecodeProcessInfoResponse (StringExtractorGDBRemote &response,
ProcessInstanceInfo &process_info);
+
private:
- //------------------------------------------------------------------
- // For GDBRemoteCommunicationClient only
- //------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationClient);
};
} // namespace process_gdb_remote
} // namespace lldb_private
-#endif // liblldb_GDBRemoteCommunicationClient_h_
+#endif // liblldb_GDBRemoteCommunicationClient_h_
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index 44c0f6a32f5b..1d512bf1de59 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -39,8 +39,7 @@ public:
GDBRemoteCommunicationServer(const char *comm_name,
const char *listener_name);
- virtual
- ~GDBRemoteCommunicationServer();
+ ~GDBRemoteCommunicationServer() override;
void RegisterPacketHandler(StringExtractorGDBRemote::ServerPacketType packet_type,
PacketHandler handler);
@@ -73,13 +72,10 @@ protected:
SendOKResponse ();
private:
- //------------------------------------------------------------------
- // For GDBRemoteCommunicationServer only
- //------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationServer);
};
} // namespace process_gdb_remote
} // namespace lldb_private
-#endif // liblldb_GDBRemoteCommunicationServer_h_
+#endif // liblldb_GDBRemoteCommunicationServer_h_
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index 698854e5dfbd..7f876fb393d9 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -58,8 +58,6 @@ using namespace lldb_private::process_gdb_remote;
//----------------------------------------------------------------------
GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon(const char *comm_name, const char *listener_name) :
GDBRemoteCommunicationServer (comm_name, listener_name),
- m_spawned_pids (),
- m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),
m_process_launch_info (),
m_process_launch_error (),
m_proc_infos (),
@@ -79,8 +77,6 @@ GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon(const cha
&GDBRemoteCommunicationServerCommon::Handle_qGroupName);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qHostInfo,
&GDBRemoteCommunicationServerCommon::Handle_qHostInfo);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess,
- &GDBRemoteCommunicationServerCommon::Handle_qKillSpawnedProcess);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QLaunchArch,
&GDBRemoteCommunicationServerCommon::Handle_QLaunchArch);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess,
@@ -185,14 +181,20 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo (StringExtractorGDBRemote &
else
response.Printf("watchpoint_exceptions_received:after;");
#else
- if (host_arch.GetMachine() == llvm::Triple::mips64 ||
- host_arch.GetMachine() == llvm::Triple::mips64el)
+ if (host_arch.GetMachine() == llvm::Triple::aarch64 ||
+ host_arch.GetMachine() == llvm::Triple::aarch64_be ||
+ host_arch.GetMachine() == llvm::Triple::arm ||
+ host_arch.GetMachine() == llvm::Triple::armeb ||
+ host_arch.GetMachine() == llvm::Triple::mips64 ||
+ host_arch.GetMachine() == llvm::Triple::mips64el ||
+ host_arch.GetMachine() == llvm::Triple::mips ||
+ host_arch.GetMachine() == llvm::Triple::mipsel)
response.Printf("watchpoint_exceptions_received:before;");
else
response.Printf("watchpoint_exceptions_received:after;");
#endif
- switch (lldb::endian::InlHostByteOrder())
+ switch (endian::InlHostByteOrder())
{
case eByteOrderBig: response.PutCString ("endian:big;"); break;
case eByteOrderLittle: response.PutCString ("endian:little;"); break;
@@ -485,94 +487,6 @@ GDBRemoteCommunicationServerCommon::Handle_qSpeedTest (StringExtractorGDBRemote
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
-
- lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
-
- // verify that we know anything about this pid.
- // Scope for locker
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- {
- // not a pid we know about
- return SendErrorResponse (10);
- }
- }
-
- // go ahead and attempt to kill the spawned process
- if (KillSpawnedProcess (pid))
- return SendOKResponse ();
- else
- return SendErrorResponse (11);
-}
-
-bool
-GDBRemoteCommunicationServerCommon::KillSpawnedProcess (lldb::pid_t pid)
-{
- // make sure we know about this process
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return false;
- }
-
- // first try a SIGTERM (standard kill)
- Host::Kill (pid, SIGTERM);
-
- // check if that worked
- for (size_t i=0; i<10; ++i)
- {
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- {
- // it is now killed
- return true;
- }
- }
- usleep (10000);
- }
-
- // check one more time after the final usleep
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return true;
- }
-
- // the launched process still lives. Now try killing it again,
- // this time with an unblockable signal.
- Host::Kill (pid, SIGKILL);
-
- for (size_t i=0; i<10; ++i)
- {
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- {
- // it is now killed
- return true;
- }
- }
- usleep (10000);
- }
-
- // check one more time after the final usleep
- // Scope for locker
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return true;
- }
-
- // no luck - the process still lives
- return false;
-}
-
-GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_vFile_Open (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen("vFile:open:"));
@@ -1299,6 +1213,7 @@ GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse_DebugServerStyle (
switch (proc_triple.getArch ())
{
case llvm::Triple::arm:
+ case llvm::Triple::thumb:
case llvm::Triple::aarch64:
ostype = "ios";
break;
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
index 62b129bb18b9..f55b2eb3f4dc 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
@@ -12,14 +12,14 @@
// C Includes
// C++ Includes
-#include <set>
+#include <string>
// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private-forward.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Target/Process.h"
-// Project includes
#include "GDBRemoteCommunicationServer.h"
#include "GDBRemoteCommunicationServerCommon.h"
@@ -36,12 +36,9 @@ class GDBRemoteCommunicationServerCommon :
public:
GDBRemoteCommunicationServerCommon(const char *comm_name, const char *listener_name);
- virtual
- ~GDBRemoteCommunicationServerCommon();
+ ~GDBRemoteCommunicationServerCommon() override;
protected:
- std::set<lldb::pid_t> m_spawned_pids;
- Mutex m_spawned_pids_mutex;
ProcessLaunchInfo m_process_launch_info;
Error m_process_launch_error;
ProcessInstanceInfoList m_proc_infos;
@@ -74,9 +71,6 @@ protected:
Handle_qSpeedTest (StringExtractorGDBRemote &packet);
PacketResult
- Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet);
-
- PacketResult
Handle_vFile_Open (StringExtractorGDBRemote &packet);
PacketResult
@@ -160,9 +154,6 @@ protected:
PacketResult
Handle_QLaunchArch (StringExtractorGDBRemote &packet);
- bool
- KillSpawnedProcess (lldb::pid_t pid);
-
static void
CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info,
StreamString &response);
@@ -213,4 +204,4 @@ protected:
} // namespace process_gdb_remote
} // namespace lldb_private
-#endif // liblldb_GDBRemoteCommunicationServerCommon_h_
+#endif // liblldb_GDBRemoteCommunicationServerCommon_h_
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index c4523252f190..921369c7ef21 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -43,6 +43,8 @@
#include "lldb/Host/common/NativeRegisterContext.h"
#include "lldb/Host/common/NativeProcessProtocol.h"
#include "lldb/Host/common/NativeThreadProtocol.h"
+#include "lldb/Utility/JSON.h"
+#include "lldb/Utility/LLDBAssert.h"
// Project includes
#include "Utility/StringExtractorGDBRemote.h"
@@ -96,20 +98,6 @@ GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS(
RegisterPacketHandlers();
}
-//----------------------------------------------------------------------
-// Destructor
-//----------------------------------------------------------------------
-GDBRemoteCommunicationServerLLGS::~GDBRemoteCommunicationServerLLGS()
-{
- Mutex::Locker locker (m_debugged_process_mutex);
-
- if (m_debugged_process_sp)
- {
- m_debugged_process_sp->Terminate ();
- m_debugged_process_sp.reset ();
- }
-}
-
void
GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers()
{
@@ -126,7 +114,7 @@ GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers()
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
&GDBRemoteCommunicationServerLLGS::Handle_interrupt);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_m,
- &GDBRemoteCommunicationServerLLGS::Handle_m);
+ &GDBRemoteCommunicationServerLLGS::Handle_memory_read);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_M,
&GDBRemoteCommunicationServerLLGS::Handle_M);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_p,
@@ -161,6 +149,8 @@ GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers()
&GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qThreadStopInfo,
&GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_jThreadsInfo,
+ &GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo,
&GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qXfer_auxv_read,
@@ -175,6 +165,8 @@ GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers()
&GDBRemoteCommunicationServerLLGS::Handle_vCont);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vCont_actions,
&GDBRemoteCommunicationServerLLGS::Handle_vCont_actions);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_x,
+ &GDBRemoteCommunicationServerLLGS::Handle_memory_read);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_Z,
&GDBRemoteCommunicationServerLLGS::Handle_Z);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z,
@@ -223,6 +215,7 @@ GDBRemoteCommunicationServerLLGS::LaunchProcess ()
error = NativeProcessProtocol::Launch(
m_process_launch_info,
*this,
+ m_mainloop,
m_debugged_process_sp);
}
@@ -274,17 +267,6 @@ GDBRemoteCommunicationServerLLGS::LaunchProcess ()
printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID ());
- // Add to list of spawned processes.
- lldb::pid_t pid;
- if ((pid = m_process_launch_info.GetProcessID ()) != LLDB_INVALID_PROCESS_ID)
- {
- // add to spawned pids
- Mutex::Locker locker (m_spawned_pids_mutex);
- // On an lldb-gdbserver, we would expect there to be only one.
- assert (m_spawned_pids.empty () && "lldb-gdbserver adding tracked process but one already existed");
- m_spawned_pids.insert (pid);
- }
-
return error;
}
@@ -297,48 +279,37 @@ GDBRemoteCommunicationServerLLGS::AttachToProcess (lldb::pid_t pid)
if (log)
log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64, __FUNCTION__, pid);
- // Scope for mutex locker.
+ // Before we try to attach, make sure we aren't already monitoring something else.
+ if (m_debugged_process_sp && m_debugged_process_sp->GetID() != LLDB_INVALID_PROCESS_ID)
+ return Error("cannot attach to a process %" PRIu64 " when another process with pid %" PRIu64 " is being debugged.", pid, m_debugged_process_sp->GetID());
+
+ // Try to attach.
+ error = NativeProcessProtocol::Attach(pid, *this, m_mainloop, m_debugged_process_sp);
+ if (!error.Success ())
{
- // Before we try to attach, make sure we aren't already monitoring something else.
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (!m_spawned_pids.empty ())
- {
- error.SetErrorStringWithFormat ("cannot attach to a process %" PRIu64 " when another process with pid %" PRIu64 " is being debugged.", pid, *m_spawned_pids.begin());
- return error;
- }
+ fprintf (stderr, "%s: failed to attach to process %" PRIu64 ": %s", __FUNCTION__, pid, error.AsCString ());
+ return error;
+ }
- // Try to attach.
- error = NativeProcessProtocol::Attach(pid, *this, m_debugged_process_sp);
- if (!error.Success ())
- {
- fprintf (stderr, "%s: failed to attach to process %" PRIu64 ": %s", __FUNCTION__, pid, error.AsCString ());
+ // Setup stdout/stderr mapping from inferior.
+ auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor ();
+ if (terminal_fd >= 0)
+ {
+ if (log)
+ log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s setting inferior STDIO fd to %d", __FUNCTION__, terminal_fd);
+ error = SetSTDIOFileDescriptor (terminal_fd);
+ if (error.Fail ())
return error;
- }
-
- // Setup stdout/stderr mapping from inferior.
- auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor ();
- if (terminal_fd >= 0)
- {
- if (log)
- log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s setting inferior STDIO fd to %d", __FUNCTION__, terminal_fd);
- error = SetSTDIOFileDescriptor (terminal_fd);
- if (error.Fail ())
- return error;
- }
- else
- {
- if (log)
- log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd);
- }
-
- printf ("Attached to process %" PRIu64 "...\n", pid);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd);
+ }
- // Add to list of spawned processes.
- assert (m_spawned_pids.empty () && "lldb-gdbserver adding tracked process but one already existed");
- m_spawned_pids.insert (pid);
+ printf ("Attached to process %" PRIu64 "...\n", pid);
- return error;
- }
+ return error;
}
void
@@ -455,6 +426,178 @@ WriteRegisterValueInHexFixedWidth (StreamString &response,
}
}
+static JSONObject::SP
+GetRegistersAsJSON(NativeThreadProtocol &thread, bool abridged)
+{
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_THREAD));
+
+ NativeRegisterContextSP reg_ctx_sp = thread.GetRegisterContext ();
+ if (! reg_ctx_sp)
+ return nullptr;
+
+ JSONObject::SP register_object_sp = std::make_shared<JSONObject>();
+
+#ifdef LLDB_JTHREADSINFO_FULL_REGISTER_SET
+ // Expedite all registers in the first register set (i.e. should be GPRs) that are not contained in other registers.
+ const RegisterSet *reg_set_p = reg_ctx_sp->GetRegisterSet(0);
+ if (! reg_set_p)
+ return nullptr;
+ for (const uint32_t *reg_num_p = reg_set_p->registers; *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p)
+ {
+ uint32_t reg_num = *reg_num_p;
+#else
+ // Expedite only a couple of registers until we figure out why sending registers is
+ // expensive.
+ static const uint32_t k_expedited_registers[] = {
+ LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM
+ };
+ static const uint32_t k_abridged_expedited_registers[] = {
+ LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM
+ };
+
+ for (const uint32_t *generic_reg_p = abridged ? k_abridged_expedited_registers : k_expedited_registers;
+ *generic_reg_p != LLDB_INVALID_REGNUM;
+ ++generic_reg_p)
+ {
+ uint32_t reg_num = reg_ctx_sp->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, *generic_reg_p);
+ if (reg_num == LLDB_INVALID_REGNUM)
+ continue; // Target does not support the given register.
+#endif
+
+ const RegisterInfo *const reg_info_p = reg_ctx_sp->GetRegisterInfoAtIndex(reg_num);
+ if (reg_info_p == nullptr)
+ {
+ if (log)
+ log->Printf("%s failed to get register info for register index %" PRIu32,
+ __FUNCTION__, reg_num);
+ continue;
+ }
+
+ if (reg_info_p->value_regs != nullptr)
+ continue; // Only expedite registers that are not contained in other registers.
+
+ RegisterValue reg_value;
+ Error error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value);
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s", __FUNCTION__,
+ reg_info_p->name ? reg_info_p->name : "<unnamed-register>", reg_num,
+ error.AsCString ());
+ continue;
+ }
+
+ StreamString stream;
+ WriteRegisterValueInHexFixedWidth(stream, reg_ctx_sp, *reg_info_p, &reg_value);
+
+ register_object_sp->SetObject(std::to_string(reg_num),
+ std::make_shared<JSONString>(stream.GetString()));
+ }
+
+ return register_object_sp;
+}
+
+static const char *
+GetStopReasonString(StopReason stop_reason)
+{
+ switch (stop_reason)
+ {
+ case eStopReasonTrace:
+ return "trace";
+ case eStopReasonBreakpoint:
+ return "breakpoint";
+ case eStopReasonWatchpoint:
+ return "watchpoint";
+ case eStopReasonSignal:
+ return "signal";
+ case eStopReasonException:
+ return "exception";
+ case eStopReasonExec:
+ return "exec";
+ case eStopReasonInstrumentation:
+ case eStopReasonInvalid:
+ case eStopReasonPlanComplete:
+ case eStopReasonThreadExiting:
+ case eStopReasonNone:
+ break; // ignored
+ }
+ return nullptr;
+}
+
+static JSONArray::SP
+GetJSONThreadsInfo(NativeProcessProtocol &process, bool abridged)
+{
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+
+ JSONArray::SP threads_array_sp = std::make_shared<JSONArray>();
+
+ // Ensure we can get info on the given thread.
+ uint32_t thread_idx = 0;
+ for ( NativeThreadProtocolSP thread_sp;
+ (thread_sp = process.GetThreadAtIndex(thread_idx)) != nullptr;
+ ++thread_idx)
+ {
+
+ lldb::tid_t tid = thread_sp->GetID();
+
+ // Grab the reason this thread stopped.
+ struct ThreadStopInfo tid_stop_info;
+ std::string description;
+ if (!thread_sp->GetStopReason (tid_stop_info, description))
+ return nullptr;
+
+ const int signum = tid_stop_info.details.signal.signo;
+ if (log)
+ {
+ log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " got signal signo = %d, reason = %d, exc_type = %" PRIu64,
+ __FUNCTION__,
+ process.GetID (),
+ tid,
+ signum,
+ tid_stop_info.reason,
+ tid_stop_info.details.exception.type);
+ }
+
+ JSONObject::SP thread_obj_sp = std::make_shared<JSONObject>();
+ threads_array_sp->AppendObject(thread_obj_sp);
+
+ if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp, abridged))
+ thread_obj_sp->SetObject("registers", registers_sp);
+
+ thread_obj_sp->SetObject("tid", std::make_shared<JSONNumber>(tid));
+ if (signum != 0)
+ thread_obj_sp->SetObject("signal", std::make_shared<JSONNumber>(signum));
+
+ const std::string thread_name = thread_sp->GetName ();
+ if (! thread_name.empty())
+ thread_obj_sp->SetObject("name", std::make_shared<JSONString>(thread_name));
+
+ if (const char *stop_reason_str = GetStopReasonString(tid_stop_info.reason))
+ thread_obj_sp->SetObject("reason", std::make_shared<JSONString>(stop_reason_str));
+
+ if (! description.empty())
+ thread_obj_sp->SetObject("description", std::make_shared<JSONString>(description));
+
+ if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type)
+ {
+ thread_obj_sp->SetObject("metype",
+ std::make_shared<JSONNumber>(tid_stop_info.details.exception.type));
+
+ JSONArray::SP medata_array_sp = std::make_shared<JSONArray>();
+ for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i)
+ {
+ medata_array_sp->AppendObject(std::make_shared<JSONNumber>(
+ tid_stop_info.details.exception.data[i]));
+ }
+ thread_obj_sp->SetObject("medata", medata_array_sp);
+ }
+
+ // TODO: Expedite interesting regions of inferior memory
+ }
+
+ return threads_array_sp;
+}
+
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread (lldb::tid_t tid)
{
@@ -548,6 +691,31 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread (lldb::tid_t tid)
response.Printf ("%" PRIx64, listed_thread_sp->GetID ());
}
response.PutChar (';');
+
+ // Include JSON info that describes the stop reason for any threads
+ // that actually have stop reasons. We use the new "jstopinfo" key
+ // whose values is hex ascii JSON that contains the thread IDs
+ // thread stop info only for threads that have stop reasons. Only send
+ // this if we have more than one thread otherwise this packet has all
+ // the info it needs.
+ if (thread_index > 0)
+ {
+ const bool threads_with_valid_stop_info_only = true;
+ JSONArray::SP threads_info_sp = GetJSONThreadsInfo(*m_debugged_process_sp,
+ threads_with_valid_stop_info_only);
+ if (threads_info_sp)
+ {
+ response.PutCString("jstopinfo:");
+ StreamString unescaped_response;
+ threads_info_sp->Write(unescaped_response);
+ response.PutCStringAsRawHex8(unescaped_response.GetData());
+ response.PutChar(';');
+ }
+ else if (log)
+ log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to prepare a jstopinfo field for pid %" PRIu64,
+ __FUNCTION__, m_debugged_process_sp->GetID());
+
+ }
}
//
@@ -595,34 +763,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread (lldb::tid_t tid)
}
}
- const char* reason_str = nullptr;
- switch (tid_stop_info.reason)
- {
- case eStopReasonTrace:
- reason_str = "trace";
- break;
- case eStopReasonBreakpoint:
- reason_str = "breakpoint";
- break;
- case eStopReasonWatchpoint:
- reason_str = "watchpoint";
- break;
- case eStopReasonSignal:
- reason_str = "signal";
- break;
- case eStopReasonException:
- reason_str = "exception";
- break;
- case eStopReasonExec:
- reason_str = "exec";
- break;
- case eStopReasonInstrumentation:
- case eStopReasonInvalid:
- case eStopReasonPlanComplete:
- case eStopReasonThreadExiting:
- case eStopReasonNone:
- break;
- }
+ const char* reason_str = GetStopReasonString(tid_stop_info.reason);
if (reason_str != nullptr)
{
response.Printf ("reason:%s;", reason_str);
@@ -663,43 +804,15 @@ GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited (NativeProcessProto
if (log)
log->Printf ("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
- // Send the exit result, and don't flush output.
- // Note: flushing output here would join the inferior stdio reflection thread, which
- // would gunk up the waitpid monitor thread that is calling this.
- PacketResult result = SendStopReasonForState (StateType::eStateExited, false);
+ PacketResult result = SendStopReasonForState(StateType::eStateExited);
if (result != PacketResult::Success)
{
if (log)
log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to send stop notification for PID %" PRIu64 ", state: eStateExited", __FUNCTION__, process->GetID ());
}
- // Remove the process from the list of spawned pids.
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.erase (process->GetID ()) < 1)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to remove PID %" PRIu64 " from the spawned pids list", __FUNCTION__, process->GetID ());
-
- }
- }
-
- // FIXME can't do this yet - since process state propagation is currently
- // synchronous, it is running off the NativeProcessProtocol's innards and
- // will tear down the NPP while it still has code to execute.
-#if 0
- // Clear the NativeProcessProtocol pointer.
- {
- Mutex::Locker locker (m_debugged_process_mutex);
- m_debugged_process_sp.reset();
- }
-#endif
-
// Close the pipe to the inferior terminal i/o if we launched it
- // and set one up. Otherwise, 'k' and its flush of stdio could
- // end up waiting on a thread join that will never end. Consider
- // adding a timeout to the connection thread join call so we
- // can avoid that scenario altogether.
+ // and set one up.
MaybeCloseInferiorTerminalConnection ();
// We are ready to exit the debug monitor.
@@ -725,7 +838,7 @@ GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped (NativeProcessProt
break;
default:
// In all other cases, send the stop reason.
- PacketResult result = SendStopReasonForState (StateType::eStateStopped, false);
+ PacketResult result = SendStopReasonForState(StateType::eStateStopped);
if (result != PacketResult::Success)
{
if (log)
@@ -748,21 +861,30 @@ GDBRemoteCommunicationServerLLGS::ProcessStateChanged (NativeProcessProtocol *pr
StateAsCString (state));
}
- // Make sure we get all of the pending stdout/stderr from the inferior
- // and send it to the lldb host before we send the state change
- // notification
- m_stdio_communication.SynchronizeWithReadThread();
-
switch (state)
{
- case StateType::eStateExited:
- HandleInferiorState_Exited (process);
+ case StateType::eStateRunning:
+ StartSTDIOForwarding();
break;
case StateType::eStateStopped:
+ // Make sure we get all of the pending stdout/stderr from the inferior
+ // and send it to the lldb host before we send the state change
+ // notification
+ SendProcessOutput();
+ // Then stop the forwarding, so that any late output (see llvm.org/pr25652) does not
+ // interfere with our protocol.
+ StopSTDIOForwarding();
HandleInferiorState_Stopped (process);
break;
+ case StateType::eStateExited:
+ // Same as above
+ SendProcessOutput();
+ StopSTDIOForwarding();
+ HandleInferiorState_Exited (process);
+ break;
+
default:
if (log)
{
@@ -796,7 +918,6 @@ GDBRemoteCommunicationServerLLGS::DataAvailableCallback ()
if(log)
log->Printf("GDBRemoteCommunicationServerLLGS::%s handshake with client failed, exiting",
__FUNCTION__);
- m_read_handle_up.reset();
m_mainloop.RequestTermination();
return;
}
@@ -817,7 +938,6 @@ GDBRemoteCommunicationServerLLGS::DataAvailableCallback ()
if(log)
log->Printf("GDBRemoteCommunicationServerLLGS::%s processing a packet failed: %s",
__FUNCTION__, error.AsCString());
- m_read_handle_up.reset();
m_mainloop.RequestTermination();
break;
}
@@ -831,7 +951,7 @@ GDBRemoteCommunicationServerLLGS::InitializeConnection (std::unique_ptr<Connecti
GDBRemoteCommunicationServer::SetConnection(connection.release());
Error error;
- m_read_handle_up = m_mainloop.RegisterReadObject(read_object_sp,
+ m_network_handle_up = m_mainloop.RegisterReadObject(read_object_sp,
[this] (MainLoopBase &) { DataAvailableCallback(); }, error);
return error;
}
@@ -857,7 +977,7 @@ GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor (int fd)
{
Error error;
- // Set up the Read Thread for reading/handling process I/O
+ // Set up the reading/handling of process I/O
std::unique_ptr<ConnectionFileDescriptor> conn_up (new ConnectionFileDescriptor (fd, true));
if (!conn_up)
{
@@ -873,29 +993,73 @@ GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor (int fd)
return error;
}
+ return Error();
+}
+
+void
+GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding()
+{
+ // Don't forward if not connected (e.g. when attaching).
+ if (! m_stdio_communication.IsConnected())
+ return;
+
// llgs local-process debugging may specify PTY paths, which will make these
// file actions non-null
// process launch -e/o will also make these file actions non-null
// nullptr means that the traffic is expected to flow over gdb-remote protocol
- if (
- m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) == nullptr ||
- m_process_launch_info.GetFileActionForFD(STDERR_FILENO) == nullptr
- )
+ if ( m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) &&
+ m_process_launch_info.GetFileActionForFD(STDERR_FILENO))
+ return;
+
+ Error error;
+ lldbassert(! m_stdio_handle_up);
+ m_stdio_handle_up = m_mainloop.RegisterReadObject(
+ m_stdio_communication.GetConnection()->GetReadObject(),
+ [this] (MainLoopBase &) { SendProcessOutput(); }, error);
+
+ if (! m_stdio_handle_up)
{
- // output from the process must be forwarded over gdb-remote
- // create a thread to read the handle and send the data
- m_stdio_communication.SetReadThreadBytesReceivedCallback (STDIOReadThreadBytesReceived, this);
- m_stdio_communication.StartReadThread();
+ // Not much we can do about the failure. Log it and continue without forwarding.
+ if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS))
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to set up stdio forwarding: %s",
+ __FUNCTION__, error.AsCString());
}
+}
- return error;
+void
+GDBRemoteCommunicationServerLLGS::StopSTDIOForwarding()
+{
+ m_stdio_handle_up.reset();
}
void
-GDBRemoteCommunicationServerLLGS::STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len)
+GDBRemoteCommunicationServerLLGS::SendProcessOutput()
{
- GDBRemoteCommunicationServerLLGS *server = reinterpret_cast<GDBRemoteCommunicationServerLLGS*> (baton);
- static_cast<void> (server->SendONotification (static_cast<const char *>(src), src_len));
+ char buffer[1024];
+ ConnectionStatus status;
+ Error error;
+ while (true)
+ {
+ size_t bytes_read = m_stdio_communication.Read(buffer, sizeof buffer, 0, status, &error);
+ switch (status)
+ {
+ case eConnectionStatusSuccess:
+ SendONotification(buffer, bytes_read);
+ break;
+ case eConnectionStatusLostConnection:
+ case eConnectionStatusEndOfFile:
+ case eConnectionStatusError:
+ case eConnectionStatusNoConnection:
+ if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS))
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s Stopping stdio forwarding as communication returned status %d (error: %s)", __FUNCTION__, status, error.AsCString());
+ m_stdio_handle_up.reset();
+ return;
+
+ case eConnectionStatusInterrupted:
+ case eConnectionStatusTimedOut:
+ return;
+ }
+ }
}
GDBRemoteCommunication::PacketResult
@@ -941,49 +1105,24 @@ GDBRemoteCommunicationServerLLGS::Handle_qC (StringExtractorGDBRemote &packet)
return SendPacketNoLock (response.GetData(), response.GetSize());
}
-bool
-GDBRemoteCommunicationServerLLGS::DebuggedProcessReaped (lldb::pid_t pid)
-{
- // reap a process that we were debugging (but not debugserver)
- Mutex::Locker locker (m_spawned_pids_mutex);
- return m_spawned_pids.erase(pid) > 0;
-}
-
-bool
-GDBRemoteCommunicationServerLLGS::ReapDebuggedProcess (void *callback_baton,
- lldb::pid_t pid,
- bool exited,
- int signal, // Zero for no signal
- int status) // Exit value of process if signal is zero
-{
- GDBRemoteCommunicationServerLLGS *server = (GDBRemoteCommunicationServerLLGS *)callback_baton;
- server->DebuggedProcessReaped (pid);
- return true;
-}
-
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_k (StringExtractorGDBRemote &packet)
{
- // shutdown all spawned processes
- std::set<lldb::pid_t> spawned_pids_copy;
+ Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- // copy pids
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- spawned_pids_copy.insert (m_spawned_pids.begin (), m_spawned_pids.end ());
- }
+ StopSTDIOForwarding();
- // nuke the spawned processes
- for (auto it = spawned_pids_copy.begin (); it != spawned_pids_copy.end (); ++it)
+ if (! m_debugged_process_sp)
{
- lldb::pid_t spawned_pid = *it;
- if (!KillSpawnedProcess (spawned_pid))
- {
- fprintf (stderr, "%s: failed to kill spawned pid %" PRIu64 ", ignoring.\n", __FUNCTION__, spawned_pid);
- }
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s No debugged process found.", __FUNCTION__);
+ return PacketResult::Success;
}
- FlushInferiorOutput ();
+ Error error = m_debugged_process_sp->Kill();
+ if (error.Fail() && log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to kill debugged process %" PRIu64 ": %s",
+ __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString());
// No OK response for kill packet.
// return SendOKResponse ();
@@ -1316,11 +1455,11 @@ GDBRemoteCommunicationServerLLGS::Handle_stop_reason (StringExtractorGDBRemote &
if (!m_debugged_process_sp)
return SendErrorResponse (02);
- return SendStopReasonForState (m_debugged_process_sp->GetState (), true);
+ return SendStopReasonForState (m_debugged_process_sp->GetState());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::SendStopReasonForState (lldb::StateType process_state, bool flush_on_exit)
+GDBRemoteCommunicationServerLLGS::SendStopReasonForState (lldb::StateType process_state)
{
Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
@@ -1349,8 +1488,6 @@ GDBRemoteCommunicationServerLLGS::SendStopReasonForState (lldb::StateType proces
case eStateInvalid:
case eStateUnloaded:
case eStateExited:
- if (flush_on_exit)
- FlushInferiorOutput ();
return SendWResponse(m_debugged_process_sp.get());
default:
@@ -1448,8 +1585,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo (StringExtractorGDBRemote
response.PutChar (';');
}
- if (reg_info->kinds[RegisterKind::eRegisterKindGCC] != LLDB_INVALID_REGNUM)
- response.Printf ("gcc:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindGCC]);
+ if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] != LLDB_INVALID_REGNUM)
+ response.Printf ("ehframe:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindEHFrame]);
if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
response.Printf ("dwarf:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindDWARF]);
@@ -1856,7 +1993,7 @@ GDBRemoteCommunicationServerLLGS::Handle_interrupt (StringExtractorGDBRemote &pa
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_m (StringExtractorGDBRemote &packet)
+GDBRemoteCommunicationServerLLGS::Handle_memory_read(StringExtractorGDBRemote &packet)
{
Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
@@ -1889,7 +2026,7 @@ GDBRemoteCommunicationServerLLGS::Handle_m (StringExtractorGDBRemote &packet)
{
if (log)
log->Printf ("GDBRemoteCommunicationServerLLGS::%s nothing to read: zero-length packet", __FUNCTION__);
- return PacketResult::Success;
+ return SendOKResponse();
}
// Allocate the response buffer.
@@ -1916,8 +2053,16 @@ GDBRemoteCommunicationServerLLGS::Handle_m (StringExtractorGDBRemote &packet)
}
StreamGDBRemote response;
- for (size_t i = 0; i < bytes_read; ++i)
- response.PutHex8(buf[i]);
+ packet.SetFilePos(0);
+ char kind = packet.GetChar('?');
+ if (kind == 'x')
+ response.PutEscapedBytes(buf.data(), byte_count);
+ else
+ {
+ assert(kind == 'm');
+ for (size_t i = 0; i < bytes_read; ++i)
+ response.PutHex8(buf[i]);
+ }
return SendPacketNoLock(response.GetData(), response.GetSize());
}
@@ -2108,6 +2253,7 @@ GDBRemoteCommunicationServerLLGS::Handle_Z (StringExtractorGDBRemote &packet)
bool want_breakpoint = true;
bool want_hardware = false;
+ uint32_t watch_flags = 0;
const GDBStoppointType stoppoint_type =
GDBStoppointType(packet.GetS32 (eStoppointInvalid));
@@ -2118,10 +2264,13 @@ GDBRemoteCommunicationServerLLGS::Handle_Z (StringExtractorGDBRemote &packet)
case eBreakpointHardware:
want_hardware = true; want_breakpoint = true; break;
case eWatchpointWrite:
+ watch_flags = 1;
want_hardware = true; want_breakpoint = false; break;
case eWatchpointRead:
+ watch_flags = 2;
want_hardware = true; want_breakpoint = false; break;
case eWatchpointReadWrite:
+ watch_flags = 3;
want_hardware = true; want_breakpoint = false; break;
case eStoppointInvalid:
return SendIllFormedResponse(packet, "Z packet had invalid software/hardware specifier");
@@ -2161,11 +2310,6 @@ GDBRemoteCommunicationServerLLGS::Handle_Z (StringExtractorGDBRemote &packet)
}
else
{
- uint32_t watch_flags =
- stoppoint_type == eWatchpointWrite
- ? 0x1 // Write
- : 0x3; // ReadWrite
-
// Try to set the watchpoint.
const Error error = m_debugged_process_sp->SetWatchpoint (
addr, size, watch_flags, want_hardware);
@@ -2555,7 +2699,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttach (StringExtractorGDBRemote &pack
}
// Notify we attached by sending a stop packet.
- return SendStopReasonForState (m_debugged_process_sp->GetState (), true);
+ return SendStopReasonForState (m_debugged_process_sp->GetState ());
}
GDBRemoteCommunication::PacketResult
@@ -2563,8 +2707,7 @@ GDBRemoteCommunicationServerLLGS::Handle_D (StringExtractorGDBRemote &packet)
{
Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS));
- // Scope for mutex locker.
- Mutex::Locker locker (m_spawned_pids_mutex);
+ StopSTDIOForwarding();
// Fail if we don't have a current process.
if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
@@ -2574,14 +2717,6 @@ GDBRemoteCommunicationServerLLGS::Handle_D (StringExtractorGDBRemote &packet)
return SendErrorResponse (0x15);
}
- if (m_spawned_pids.find(m_debugged_process_sp->GetID ()) == m_spawned_pids.end())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to find PID %" PRIu64 " in spawned pids list",
- __FUNCTION__, m_debugged_process_sp->GetID ());
- return SendErrorResponse (0x1);
- }
-
lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
// Consume the ';' after D.
@@ -2603,11 +2738,6 @@ GDBRemoteCommunicationServerLLGS::Handle_D (StringExtractorGDBRemote &packet)
return SendIllFormedResponse (packet, "Invalid pid");
}
- if (m_stdio_communication.IsConnected ())
- {
- m_stdio_communication.StopReadThread ();
- }
-
const Error error = m_debugged_process_sp->Detach ();
if (error.Fail ())
{
@@ -2617,7 +2747,6 @@ GDBRemoteCommunicationServerLLGS::Handle_D (StringExtractorGDBRemote &packet)
return SendErrorResponse (0x01);
}
- m_spawned_pids.erase (m_debugged_process_sp->GetID ());
return SendOKResponse ();
}
@@ -2638,6 +2767,38 @@ GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo (StringExtractorGDBRemo
}
GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo (StringExtractorGDBRemote &)
+{
+ Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+
+ // Ensure we have a debugged process.
+ if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse (50);
+
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServerLLGS::%s preparing packet for pid %" PRIu64,
+ __FUNCTION__, m_debugged_process_sp->GetID());
+
+
+ StreamString response;
+ const bool threads_with_valid_stop_info_only = false;
+ JSONArray::SP threads_array_sp = GetJSONThreadsInfo(*m_debugged_process_sp,
+ threads_with_valid_stop_info_only);
+ if (! threads_array_sp)
+ {
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to prepare a packet for pid %" PRIu64,
+ __FUNCTION__, m_debugged_process_sp->GetID());
+ return SendErrorResponse(52);
+ }
+
+ threads_array_sp->Write(response);
+ StreamGDBRemote escaped_response;
+ escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
+ return SendPacketNoLock (escaped_response.GetData(), escaped_response.GetSize());
+}
+
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet)
{
// Fail if we don't have a current process.
@@ -2686,21 +2847,6 @@ GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress (StringExtractorGDBRem
}
void
-GDBRemoteCommunicationServerLLGS::FlushInferiorOutput ()
-{
- // If we're not monitoring an inferior's terminal, ignore this.
- if (!m_stdio_communication.IsConnected())
- return;
-
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s() called", __FUNCTION__);
-
- // FIXME implement a timeout on the join.
- m_stdio_communication.JoinReadThread();
-}
-
-void
GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection ()
{
Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
index 29f3fdebcfb0..f16057781ddc 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -42,9 +42,6 @@ public:
//------------------------------------------------------------------
GDBRemoteCommunicationServerLLGS(const lldb::PlatformSP& platform_sp, MainLoop &mainloop);
- virtual
- ~GDBRemoteCommunicationServerLLGS();
-
//------------------------------------------------------------------
/// Specify the program to launch and its arguments.
///
@@ -119,12 +116,15 @@ public:
protected:
lldb::PlatformSP m_platform_sp;
MainLoop &m_mainloop;
- MainLoop::ReadHandleUP m_read_handle_up;
+ MainLoop::ReadHandleUP m_network_handle_up;
lldb::tid_t m_current_tid;
lldb::tid_t m_continue_tid;
Mutex m_debugged_process_mutex;
NativeProcessProtocolSP m_debugged_process_sp;
+
Communication m_stdio_communication;
+ MainLoop::ReadHandleUP m_stdio_handle_up;
+
lldb::StateType m_inferior_prev_state;
lldb::DataBufferSP m_active_auxv_buffer_sp;
Mutex m_saved_registers_mutex;
@@ -142,7 +142,7 @@ protected:
SendStopReplyPacketForThread (lldb::tid_t tid);
PacketResult
- SendStopReasonForState (lldb::StateType process_state, bool flush_on_exit);
+ SendStopReasonForState (lldb::StateType process_state);
PacketResult
Handle_k (StringExtractorGDBRemote &packet);
@@ -201,8 +201,9 @@ protected:
PacketResult
Handle_interrupt (StringExtractorGDBRemote &packet);
+ // Handles $m and $x packets.
PacketResult
- Handle_m (StringExtractorGDBRemote &packet);
+ Handle_memory_read (StringExtractorGDBRemote &packet);
PacketResult
Handle_M (StringExtractorGDBRemote &packet);
@@ -241,6 +242,9 @@ protected:
Handle_qThreadStopInfo (StringExtractorGDBRemote &packet);
PacketResult
+ Handle_jThreadsInfo (StringExtractorGDBRemote &packet);
+
+ PacketResult
Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet);
PacketResult
@@ -261,32 +265,16 @@ protected:
Error
SetSTDIOFileDescriptor (int fd);
- static void
- STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len);
-
FileSpec
FindModuleFile (const std::string& module_path, const ArchSpec& arch) override;
private:
- bool
- DebuggedProcessReaped (lldb::pid_t pid);
-
- static bool
- ReapDebuggedProcess (void *callback_baton,
- lldb::pid_t pid,
- bool exited,
- int signal,
- int status);
-
void
HandleInferiorState_Exited (NativeProcessProtocol *process);
void
HandleInferiorState_Stopped (NativeProcessProtocol *process);
- void
- FlushInferiorOutput ();
-
NativeThreadProtocolSP
GetThreadFromSuffix (StringExtractorGDBRemote &packet);
@@ -305,6 +293,15 @@ private:
void
DataAvailableCallback ();
+ void
+ SendProcessOutput ();
+
+ void
+ StartSTDIOForwarding();
+
+ void
+ StopSTDIOForwarding();
+
//------------------------------------------------------------------
// For GDBRemoteCommunicationServerLLGS only
//------------------------------------------------------------------
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
index 1205049db3fb..f88ac1247526 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
@@ -15,19 +15,26 @@
// C++ Includes
#include <cstring>
#include <chrono>
+#include <mutex>
+#include <sstream>
// Other libraries and framework includes
+#include "llvm/Support/FileSystem.h"
+
#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamGDBRemote.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/UnixSignals.h"
+#include "lldb/Utility/JSON.h"
// Project includes
#include "Utility/StringExtractorGDBRemote.h"
@@ -40,18 +47,29 @@ using namespace lldb_private::process_gdb_remote;
//----------------------------------------------------------------------
// GDBRemoteCommunicationServerPlatform constructor
//----------------------------------------------------------------------
-GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform() :
+GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol,
+ const char* socket_scheme) :
GDBRemoteCommunicationServerCommon ("gdb-remote.server", "gdb-remote.server.rx_packet"),
+ m_socket_protocol(socket_protocol),
+ m_socket_scheme(socket_scheme),
+ m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),
m_platform_sp (Platform::GetHostPlatform ()),
m_port_map (),
m_port_offset(0)
{
+ m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID;
+ m_pending_gdb_server.port = 0;
+
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC,
&GDBRemoteCommunicationServerPlatform::Handle_qC);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
&GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer,
&GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer,
+ &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess,
+ &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
&GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);
RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
@@ -78,38 +96,16 @@ GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform()
{
}
-GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
+Error
+GDBRemoteCommunicationServerPlatform::LaunchGDBServer(const lldb_private::Args& args,
+ std::string hostname,
+ lldb::pid_t& pid,
+ uint16_t& port,
+ std::string& socket_name)
{
-#ifdef _WIN32
- return SendErrorResponse(9);
-#else
- // Spawn a local debugserver as a platform so we can then attach or launch
- // a process...
-
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
- if (log)
- log->Printf ("GDBRemoteCommunicationServerPlatform::%s() called", __FUNCTION__);
-
- // Sleep and wait a bit for debugserver to start to listen...
- ConnectionFileDescriptor file_conn;
- std::string hostname;
- // TODO: /tmp/ should not be hardcoded. User might want to override /tmp
- // with the TMPDIR environment variable
- packet.SetFilePos(::strlen ("qLaunchGDBServer;"));
- std::string name;
- std::string value;
- uint16_t port = UINT16_MAX;
- while (packet.GetNameColonValue(name, value))
- {
- if (name.compare ("host") == 0)
- hostname.swap(value);
- else if (name.compare ("port") == 0)
- port = StringConvert::ToUInt32(value.c_str(), 0, 0);
- }
if (port == UINT16_MAX)
port = GetNextAvailablePort();
-
+
// Spawn a new thread to accept the port that gets bound after
// binding to port 0 (zero).
@@ -120,6 +116,8 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGD
ProcessLaunchInfo debugserver_launch_info;
if (hostname.empty())
hostname = "127.0.0.1";
+
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port);
@@ -133,53 +131,210 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGD
int platform_port;
std::string platform_path;
bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, platform_ip, platform_port, platform_path);
+ UNUSED_IF_ASSERT_DISABLED(ok);
assert(ok);
- Error error = StartDebugserverProcess (
- platform_ip.c_str(),
- port,
- debugserver_launch_info,
- port);
- lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
+ std::ostringstream url;
+ uint16_t* port_ptr = &port;
+ if (m_socket_protocol == Socket::ProtocolTcp)
+ url << platform_ip << ":" << port;
+ else
+ {
+ socket_name = GetDomainSocketPath("gdbserver").GetPath();
+ url << socket_name;
+ port_ptr = nullptr;
+ }
+ Error error = StartDebugserverProcess (url.str().c_str(),
+ nullptr,
+ debugserver_launch_info,
+ port_ptr,
+ args);
- if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+ pid = debugserver_launch_info.GetProcessID();
+ if (pid != LLDB_INVALID_PROCESS_ID)
{
Mutex::Locker locker (m_spawned_pids_mutex);
- m_spawned_pids.insert(debugserver_pid);
+ m_spawned_pids.insert(pid);
if (port > 0)
- AssociatePortWithProcess(port, debugserver_pid);
+ AssociatePortWithProcess(port, pid);
}
else
{
if (port > 0)
- FreePort (port);
+ FreePort(port);
+ }
+ return error;
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
+{
+#ifdef _WIN32
+ return SendErrorResponse(9);
+#else
+ // Spawn a local debugserver as a platform so we can then attach or launch
+ // a process...
+
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServerPlatform::%s() called", __FUNCTION__);
+
+ ConnectionFileDescriptor file_conn;
+ std::string hostname;
+ packet.SetFilePos(::strlen ("qLaunchGDBServer;"));
+ std::string name;
+ std::string value;
+ uint16_t port = UINT16_MAX;
+ while (packet.GetNameColonValue(name, value))
+ {
+ if (name.compare ("host") == 0)
+ hostname.swap(value);
+ else if (name.compare ("port") == 0)
+ port = StringConvert::ToUInt32(value.c_str(), 0, 0);
}
- if (error.Success())
+ lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
+ std::string socket_name;
+ Error error = LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
+ if (error.Fail())
{
if (log)
- log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid);
+ log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ());
+ return SendErrorResponse(9);
+ }
- char response[256];
- const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
- assert (response_len < (int)sizeof(response));
- PacketResult packet_result = SendPacketNoLock (response, response_len);
+ if (log)
+ log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid);
- if (packet_result != PacketResult::Success)
+ StreamGDBRemote response;
+ response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
+ if (!socket_name.empty())
+ {
+ response.PutCString("socket_name:");
+ response.PutCStringAsRawHex8(socket_name.c_str());
+ response.PutChar(';');
+ }
+
+ PacketResult packet_result = SendPacketNoLock(response.GetData(), response.GetSize());
+ if (packet_result != PacketResult::Success)
+ {
+ if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+ ::kill (debugserver_pid, SIGINT);
+ }
+ return packet_result;
+#endif
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer (StringExtractorGDBRemote &packet)
+{
+ if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID)
+ return SendErrorResponse(4);
+
+ JSONObject::SP server_sp = std::make_shared<JSONObject>();
+ server_sp->SetObject("port", std::make_shared<JSONNumber>(m_pending_gdb_server.port));
+ if (!m_pending_gdb_server.socket_name.empty())
+ server_sp->SetObject("socket_name",
+ std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str()));
+
+ JSONArray server_list;
+ server_list.AppendObject(server_sp);
+
+ StreamGDBRemote response;
+ server_list.Write(response);
+
+ StreamGDBRemote escaped_response;
+ escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
+ return SendPacketNoLock(escaped_response.GetData(), escaped_response.GetSize());
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
+
+ lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
+
+ // verify that we know anything about this pid.
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
{
- if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
- ::kill (debugserver_pid, SIGINT);
+ // not a pid we know about
+ return SendErrorResponse (10);
}
- return packet_result;
}
+
+ // go ahead and attempt to kill the spawned process
+ if (KillSpawnedProcess (pid))
+ return SendOKResponse ();
else
+ return SendErrorResponse (11);
+}
+
+bool
+GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid)
+{
+ // make sure we know about this process
{
- if (log)
- log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ());
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return false;
}
- return SendErrorResponse (9);
-#endif
+
+ // first try a SIGTERM (standard kill)
+ Host::Kill (pid, SIGTERM);
+
+ // check if that worked
+ for (size_t i=0; i<10; ++i)
+ {
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ {
+ // it is now killed
+ return true;
+ }
+ }
+ usleep (10000);
+ }
+
+ // check one more time after the final usleep
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+
+ // the launched process still lives. Now try killing it again,
+ // this time with an unblockable signal.
+ Host::Kill (pid, SIGKILL);
+
+ for (size_t i=0; i<10; ++i)
+ {
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ {
+ // it is now killed
+ return true;
+ }
+ }
+ usleep (10000);
+ }
+
+ // check one more time after the final usleep
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+
+ // no luck - the process still lives
+ return false;
}
GDBRemoteCommunication::PacketResult
@@ -402,8 +557,48 @@ GDBRemoteCommunicationServerPlatform::FreePortForProcess (lldb::pid_t pid)
return false;
}
+const FileSpec&
+GDBRemoteCommunicationServerPlatform::GetDomainSocketDir()
+{
+ static FileSpec g_domainsocket_dir;
+ static std::once_flag g_once_flag;
+
+ std::call_once(g_once_flag, []() {
+ const char* domainsocket_dir_env = ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
+ if (domainsocket_dir_env != nullptr)
+ g_domainsocket_dir = FileSpec(domainsocket_dir_env, false);
+ else
+ HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, g_domainsocket_dir);
+ });
+
+ return g_domainsocket_dir;
+}
+
+FileSpec
+GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char* prefix)
+{
+ llvm::SmallString<PATH_MAX> socket_path;
+ llvm::SmallString<PATH_MAX> socket_name((llvm::StringRef(prefix) + ".%%%%%%").str());
+
+ FileSpec socket_path_spec(GetDomainSocketDir());
+ socket_path_spec.AppendPathComponent(socket_name.c_str());
+
+ llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path);
+ return FileSpec(socket_path.c_str(), false);
+}
+
void
-GDBRemoteCommunicationServerPlatform::SetPortOffset (uint16_t port_offset)
+GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset)
{
m_port_offset = port_offset;
}
+
+void
+GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(lldb::pid_t pid,
+ uint16_t port,
+ const std::string& socket_name)
+{
+ m_pending_gdb_server.pid = pid;
+ m_pending_gdb_server.port = port;
+ m_pending_gdb_server.socket_name = socket_name;
+}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h
index 5c011371a3eb..1fe7207d2bc2 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h
@@ -10,7 +10,15 @@
#ifndef liblldb_GDBRemoteCommunicationServerPlatform_h_
#define liblldb_GDBRemoteCommunicationServerPlatform_h_
+// C Includes
+// C++ Includes
+#include <map>
+#include <set>
+
+// Other libraries and framework includes
+// Project includes
#include "GDBRemoteCommunicationServerCommon.h"
+#include "lldb/Host/Socket.h"
namespace lldb_private {
namespace process_gdb_remote {
@@ -21,10 +29,10 @@ class GDBRemoteCommunicationServerPlatform :
public:
typedef std::map<uint16_t, lldb::pid_t> PortMap;
- GDBRemoteCommunicationServerPlatform();
+ GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol,
+ const char* socket_scheme);
- virtual
- ~GDBRemoteCommunicationServerPlatform();
+ ~GDBRemoteCommunicationServerPlatform() override;
Error
LaunchProcess () override;
@@ -58,16 +66,40 @@ public:
void
SetPortOffset (uint16_t port_offset);
+ void
+ SetInferiorArguments (const lldb_private::Args& args);
+
+ Error
+ LaunchGDBServer(const lldb_private::Args& args,
+ std::string hostname,
+ lldb::pid_t& pid,
+ uint16_t& port,
+ std::string& socket_name);
+
+ void
+ SetPendingGdbServer(lldb::pid_t pid, uint16_t port, const std::string& socket_name);
+
protected:
+ const Socket::SocketProtocol m_socket_protocol;
+ const std::string m_socket_scheme;
+ Mutex m_spawned_pids_mutex;
+ std::set<lldb::pid_t> m_spawned_pids;
lldb::PlatformSP m_platform_sp;
PortMap m_port_map;
uint16_t m_port_offset;
+ struct { lldb::pid_t pid; uint16_t port; std::string socket_name; } m_pending_gdb_server;
PacketResult
Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet);
PacketResult
+ Handle_qQueryGDBServer (StringExtractorGDBRemote &packet);
+
+ PacketResult
+ Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet);
+
+ PacketResult
Handle_qProcessInfo (StringExtractorGDBRemote &packet);
PacketResult
@@ -84,6 +116,9 @@ protected:
private:
bool
+ KillSpawnedProcess (lldb::pid_t pid);
+
+ bool
DebugserverProcessReaped (lldb::pid_t pid);
static bool
@@ -93,13 +128,16 @@ private:
int signal,
int status);
- //------------------------------------------------------------------
- // For GDBRemoteCommunicationServerPlatform only
- //------------------------------------------------------------------
+ static const FileSpec&
+ GetDomainSocketDir();
+
+ static FileSpec
+ GetDomainSocketPath(const char* prefix);
+
DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationServerPlatform);
};
} // namespace process_gdb_remote
} // namespace lldb_private
-#endif // liblldb_GDBRemoteCommunicationServerPlatform_h_
+#endif // liblldb_GDBRemoteCommunicationServerPlatform_h_
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index f5f134e80d6a..b0a1eaaeb79c 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -17,9 +17,6 @@
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
-#ifndef LLDB_DISABLE_PYTHON
-#include "lldb/Interpreter/PythonDataObjects.h"
-#endif
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Utils.h"
@@ -28,8 +25,8 @@
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
#include "ThreadGDBRemote.h"
-#include "Utility/ARM_GCC_Registers.h"
#include "Utility/ARM_DWARF_Registers.h"
+#include "Utility/ARM_ehframe_Registers.h"
using namespace lldb;
using namespace lldb_private;
@@ -150,6 +147,52 @@ GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, StringExtractor
return success;
}
+bool
+GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, uint64_t new_reg_val)
+{
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
+ if (reg_info == NULL)
+ return false;
+
+ // Early in process startup, we can get a thread that has an invalid byte order
+ // because the process hasn't been completely set up yet (see the ctor where the
+ // byte order is setfrom the process). If that's the case, we can't set the
+ // value here.
+ if (m_reg_data.GetByteOrder() == eByteOrderInvalid)
+ {
+ return false;
+ }
+
+ // Invalidate if needed
+ InvalidateIfNeeded (false);
+
+ DataBufferSP buffer_sp (new DataBufferHeap (&new_reg_val, sizeof (new_reg_val)));
+ DataExtractor data (buffer_sp, endian::InlHostByteOrder(), sizeof (void*));
+
+ // If our register context and our register info disagree, which should never happen, don't
+ // overwrite past the end of the buffer.
+ if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
+ return false;
+
+ // Grab a pointer to where we are going to put this register
+ uint8_t *dst = const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size));
+
+ if (dst == NULL)
+ return false;
+
+
+ if (data.CopyByteOrderedData (0, // src offset
+ reg_info->byte_size, // src length
+ dst, // dst
+ reg_info->byte_size, // dst length
+ m_reg_data.GetByteOrder())) // dst byte order
+ {
+ SetRegisterIsValid (reg, true);
+ return true;
+ }
+ return false;
+}
+
// Helper function for GDBRemoteRegisterContext::ReadRegisterBytes().
bool
GDBRemoteRegisterContext::GetPrimordialRegister(const RegisterInfo *reg_info,
@@ -186,7 +229,8 @@ GDBRemoteRegisterContext::ReadRegisterBytes (const RegisterInfo *reg_info, DataE
if (!gdb_comm.ReadAllRegisters(m_thread.GetProtocolID(), response))
return false;
if (response.IsNormalResponse())
- if (response.GetHexBytes ((void *)m_reg_data.GetDataStart(), m_reg_data.GetByteSize(), '\xcc') == m_reg_data.GetByteSize())
+ if (response.GetHexBytes(const_cast<void *>(reinterpret_cast<const void *>(m_reg_data.GetDataStart())),
+ m_reg_data.GetByteSize(), '\xcc') == m_reg_data.GetByteSize())
SetAllRegisterValid (true);
}
else if (reg_info->value_regs)
@@ -275,8 +319,8 @@ GDBRemoteRegisterContext::SetPrimordialRegister(const RegisterInfo *reg_info,
packet.Printf ("P%x=", reg);
packet.PutBytesAsRawHex8 (m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size),
reg_info->byte_size,
- lldb::endian::InlHostByteOrder(),
- lldb::endian::InlHostByteOrder());
+ endian::InlHostByteOrder(),
+ endian::InlHostByteOrder());
if (gdb_comm.GetThreadSuffixSupported())
packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
@@ -372,8 +416,8 @@ GDBRemoteRegisterContext::WriteRegisterBytes (const RegisterInfo *reg_info, Data
packet.PutChar ('G');
packet.PutBytesAsRawHex8 (m_reg_data.GetDataStart(),
m_reg_data.GetByteSize(),
- lldb::endian::InlHostByteOrder(),
- lldb::endian::InlHostByteOrder());
+ endian::InlHostByteOrder(),
+ endian::InlHostByteOrder());
if (thread_suffix_supported)
packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
@@ -772,8 +816,8 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data
packet.Printf ("P%x=", reg);
packet.PutBytesAsRawHex8 (restore_src,
reg_byte_size,
- lldb::endian::InlHostByteOrder(),
- lldb::endian::InlHostByteOrder());
+ endian::InlHostByteOrder(),
+ endian::InlHostByteOrder());
if (thread_suffix_supported)
packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
@@ -795,8 +839,8 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data
packet.Printf ("P%x=", reg);
packet.PutBytesAsRawHex8 (restore_src,
reg_byte_size,
- lldb::endian::InlHostByteOrder(),
- lldb::endian::InlHostByteOrder());
+ endian::InlHostByteOrder(),
+ endian::InlHostByteOrder());
if (thread_suffix_supported)
packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
@@ -851,7 +895,7 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data
}
StreamString packet;
packet.Printf ("P%x=", reg_info->kinds[eRegisterKindLLDB]);
- packet.PutBytesAsRawHex8 (data_sp->GetBytes() + reg_info->byte_offset, reg_info->byte_size, lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder());
+ packet.PutBytesAsRawHex8 (data_sp->GetBytes() + reg_info->byte_offset, reg_info->byte_size, endian::InlHostByteOrder(), endian::InlHostByteOrder());
if (thread_suffix_supported)
packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
@@ -941,115 +985,115 @@ GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch)
};
static RegisterInfo g_register_infos[] = {
-// NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB VALUE REGS INVALIDATE REGS
-// ====== ====== === === ============= ============ =================== =================== ====================== === ==== ========== ===============
- { "r0", "arg1", 4, 0, eEncodingUint, eFormatHex, { gcc_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1,0, 0 }, NULL, NULL},
- { "r1", "arg2", 4, 0, eEncodingUint, eFormatHex, { gcc_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2,1, 1 }, NULL, NULL},
- { "r2", "arg3", 4, 0, eEncodingUint, eFormatHex, { gcc_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3,2, 2 }, NULL, NULL},
- { "r3", "arg4", 4, 0, eEncodingUint, eFormatHex, { gcc_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4,3, 3 }, NULL, NULL},
- { "r4", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, 4, 4 }, NULL, NULL},
- { "r5", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, 5, 5 }, NULL, NULL},
- { "r6", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, 6, 6 }, NULL, NULL},
- { "r7", "fp", 4, 0, eEncodingUint, eFormatHex, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, 7, 7 }, NULL, NULL},
- { "r8", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, 8, 8 }, NULL, NULL},
- { "r9", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, 9, 9 }, NULL, NULL},
- { "r10", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, 10, 10 }, NULL, NULL},
- { "r11", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM, 11, 11 }, NULL, NULL},
- { "r12", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, 12, 12 }, NULL, NULL},
- { "sp", "r13", 4, 0, eEncodingUint, eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, 13, 13 }, NULL, NULL},
- { "lr", "r14", 4, 0, eEncodingUint, eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, 14, 14 }, NULL, NULL},
- { "pc", "r15", 4, 0, eEncodingUint, eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, 15, 15 }, NULL, NULL},
- { "f0", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 16, 16 }, NULL, NULL},
- { "f1", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 17, 17 }, NULL, NULL},
- { "f2", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 18, 18 }, NULL, NULL},
- { "f3", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 19, 19 }, NULL, NULL},
- { "f4", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 20, 20 }, NULL, NULL},
- { "f5", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 21, 21 }, NULL, NULL},
- { "f6", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 22, 22 }, NULL, NULL},
- { "f7", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 23, 23 }, NULL, NULL},
- { "fps", NULL, 4, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 24, 24 }, NULL, NULL},
- { "cpsr","flags", 4, 0, eEncodingUint, eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_INVALID_REGNUM, 25, 25 }, NULL, NULL},
- { "s0", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, 26, 26 }, NULL, NULL},
- { "s1", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, 27, 27 }, NULL, NULL},
- { "s2", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, 28, 28 }, NULL, NULL},
- { "s3", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, 29, 29 }, NULL, NULL},
- { "s4", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, 30, 30 }, NULL, NULL},
- { "s5", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, 31, 31 }, NULL, NULL},
- { "s6", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, 32, 32 }, NULL, NULL},
- { "s7", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, 33, 33 }, NULL, NULL},
- { "s8", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, 34, 34 }, NULL, NULL},
- { "s9", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, 35, 35 }, NULL, NULL},
- { "s10", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, 36, 36 }, NULL, NULL},
- { "s11", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, 37, 37 }, NULL, NULL},
- { "s12", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, 38, 38 }, NULL, NULL},
- { "s13", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, 39, 39 }, NULL, NULL},
- { "s14", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, 40, 40 }, NULL, NULL},
- { "s15", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, 41, 41 }, NULL, NULL},
- { "s16", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, 42, 42 }, NULL, NULL},
- { "s17", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, 43, 43 }, NULL, NULL},
- { "s18", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, 44, 44 }, NULL, NULL},
- { "s19", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, 45, 45 }, NULL, NULL},
- { "s20", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, 46, 46 }, NULL, NULL},
- { "s21", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, 47, 47 }, NULL, NULL},
- { "s22", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, 48, 48 }, NULL, NULL},
- { "s23", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, 49, 49 }, NULL, NULL},
- { "s24", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, 50, 50 }, NULL, NULL},
- { "s25", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, 51, 51 }, NULL, NULL},
- { "s26", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, 52, 52 }, NULL, NULL},
- { "s27", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, 53, 53 }, NULL, NULL},
- { "s28", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, 54, 54 }, NULL, NULL},
- { "s29", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, 55, 55 }, NULL, NULL},
- { "s30", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, 56, 56 }, NULL, NULL},
- { "s31", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, 57, 57 }, NULL, NULL},
- { "fpscr",NULL, 4, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 58, 58 }, NULL, NULL},
- { "d16", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, 59, 59 }, NULL, NULL},
- { "d17", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, 60, 60 }, NULL, NULL},
- { "d18", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, 61, 61 }, NULL, NULL},
- { "d19", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, 62, 62 }, NULL, NULL},
- { "d20", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, 63, 63 }, NULL, NULL},
- { "d21", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, 64, 64 }, NULL, NULL},
- { "d22", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, 65, 65 }, NULL, NULL},
- { "d23", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, 66, 66 }, NULL, NULL},
- { "d24", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, 67, 67 }, NULL, NULL},
- { "d25", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, 68, 68 }, NULL, NULL},
- { "d26", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, 69, 69 }, NULL, NULL},
- { "d27", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, 70, 70 }, NULL, NULL},
- { "d28", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, 71, 71 }, NULL, NULL},
- { "d29", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, 72, 72 }, NULL, NULL},
- { "d30", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, 73, 73 }, NULL, NULL},
- { "d31", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, 74, 74 }, NULL, NULL},
- { "d0", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, 75, 75 }, g_d0_regs, NULL},
- { "d1", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, 76, 76 }, g_d1_regs, NULL},
- { "d2", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, 77, 77 }, g_d2_regs, NULL},
- { "d3", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, 78, 78 }, g_d3_regs, NULL},
- { "d4", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, 79, 79 }, g_d4_regs, NULL},
- { "d5", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, 80, 80 }, g_d5_regs, NULL},
- { "d6", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, 81, 81 }, g_d6_regs, NULL},
- { "d7", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, 82, 82 }, g_d7_regs, NULL},
- { "d8", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, 83, 83 }, g_d8_regs, NULL},
- { "d9", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, 84, 84 }, g_d9_regs, NULL},
- { "d10", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, 85, 85 }, g_d10_regs, NULL},
- { "d11", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, 86, 86 }, g_d11_regs, NULL},
- { "d12", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, 87, 87 }, g_d12_regs, NULL},
- { "d13", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, 88, 88 }, g_d13_regs, NULL},
- { "d14", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, 89, 89 }, g_d14_regs, NULL},
- { "d15", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, 90, 90 }, g_d15_regs, NULL},
- { "q0", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q0, LLDB_INVALID_REGNUM, 91, 91 }, g_q0_regs, NULL},
- { "q1", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q1, LLDB_INVALID_REGNUM, 92, 92 }, g_q1_regs, NULL},
- { "q2", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q2, LLDB_INVALID_REGNUM, 93, 93 }, g_q2_regs, NULL},
- { "q3", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q3, LLDB_INVALID_REGNUM, 94, 94 }, g_q3_regs, NULL},
- { "q4", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q4, LLDB_INVALID_REGNUM, 95, 95 }, g_q4_regs, NULL},
- { "q5", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q5, LLDB_INVALID_REGNUM, 96, 96 }, g_q5_regs, NULL},
- { "q6", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q6, LLDB_INVALID_REGNUM, 97, 97 }, g_q6_regs, NULL},
- { "q7", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q7, LLDB_INVALID_REGNUM, 98, 98 }, g_q7_regs, NULL},
- { "q8", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q8, LLDB_INVALID_REGNUM, 99, 99 }, g_q8_regs, NULL},
- { "q9", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q9, LLDB_INVALID_REGNUM, 100, 100 }, g_q9_regs, NULL},
- { "q10", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q10, LLDB_INVALID_REGNUM, 101, 101 }, g_q10_regs, NULL},
- { "q11", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q11, LLDB_INVALID_REGNUM, 102, 102 }, g_q11_regs, NULL},
- { "q12", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q12, LLDB_INVALID_REGNUM, 103, 103 }, g_q12_regs, NULL},
- { "q13", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q13, LLDB_INVALID_REGNUM, 104, 104 }, g_q13_regs, NULL},
- { "q14", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q14, LLDB_INVALID_REGNUM, 105, 105 }, g_q14_regs, NULL},
- { "q15", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q15, LLDB_INVALID_REGNUM, 106, 106 }, g_q15_regs, NULL}
+// NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB VALUE REGS INVALIDATE REGS
+// ====== ====== === === ============= ============ =================== =================== ====================== ============= ==== ========== ===============
+ { "r0", "arg1", 4, 0, eEncodingUint, eFormatHex, { ehframe_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1,0, 0 }, NULL, NULL},
+ { "r1", "arg2", 4, 0, eEncodingUint, eFormatHex, { ehframe_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2,1, 1 }, NULL, NULL},
+ { "r2", "arg3", 4, 0, eEncodingUint, eFormatHex, { ehframe_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3,2, 2 }, NULL, NULL},
+ { "r3", "arg4", 4, 0, eEncodingUint, eFormatHex, { ehframe_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4,3, 3 }, NULL, NULL},
+ { "r4", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, 4, 4 }, NULL, NULL},
+ { "r5", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, 5, 5 }, NULL, NULL},
+ { "r6", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, 6, 6 }, NULL, NULL},
+ { "r7", "fp", 4, 0, eEncodingUint, eFormatHex, { ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, 7, 7 }, NULL, NULL},
+ { "r8", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, 8, 8 }, NULL, NULL},
+ { "r9", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, 9, 9 }, NULL, NULL},
+ { "r10", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, 10, 10 }, NULL, NULL},
+ { "r11", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, 11, 11 }, NULL, NULL},
+ { "r12", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, 12, 12 }, NULL, NULL},
+ { "sp", "r13", 4, 0, eEncodingUint, eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, 13, 13 }, NULL, NULL},
+ { "lr", "r14", 4, 0, eEncodingUint, eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, 14, 14 }, NULL, NULL},
+ { "pc", "r15", 4, 0, eEncodingUint, eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, 15, 15 }, NULL, NULL},
+ { "f0", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 16, 16 }, NULL, NULL},
+ { "f1", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 17, 17 }, NULL, NULL},
+ { "f2", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 18, 18 }, NULL, NULL},
+ { "f3", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 19, 19 }, NULL, NULL},
+ { "f4", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 20, 20 }, NULL, NULL},
+ { "f5", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 21, 21 }, NULL, NULL},
+ { "f6", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 22, 22 }, NULL, NULL},
+ { "f7", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 23, 23 }, NULL, NULL},
+ { "fps", NULL, 4, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 24, 24 }, NULL, NULL},
+ { "cpsr","flags", 4, 0, eEncodingUint, eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_INVALID_REGNUM, 25, 25 }, NULL, NULL},
+ { "s0", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, 26, 26 }, NULL, NULL},
+ { "s1", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, 27, 27 }, NULL, NULL},
+ { "s2", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, 28, 28 }, NULL, NULL},
+ { "s3", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, 29, 29 }, NULL, NULL},
+ { "s4", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, 30, 30 }, NULL, NULL},
+ { "s5", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, 31, 31 }, NULL, NULL},
+ { "s6", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, 32, 32 }, NULL, NULL},
+ { "s7", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, 33, 33 }, NULL, NULL},
+ { "s8", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, 34, 34 }, NULL, NULL},
+ { "s9", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, 35, 35 }, NULL, NULL},
+ { "s10", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, 36, 36 }, NULL, NULL},
+ { "s11", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, 37, 37 }, NULL, NULL},
+ { "s12", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, 38, 38 }, NULL, NULL},
+ { "s13", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, 39, 39 }, NULL, NULL},
+ { "s14", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, 40, 40 }, NULL, NULL},
+ { "s15", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, 41, 41 }, NULL, NULL},
+ { "s16", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, 42, 42 }, NULL, NULL},
+ { "s17", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, 43, 43 }, NULL, NULL},
+ { "s18", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, 44, 44 }, NULL, NULL},
+ { "s19", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, 45, 45 }, NULL, NULL},
+ { "s20", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, 46, 46 }, NULL, NULL},
+ { "s21", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, 47, 47 }, NULL, NULL},
+ { "s22", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, 48, 48 }, NULL, NULL},
+ { "s23", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, 49, 49 }, NULL, NULL},
+ { "s24", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, 50, 50 }, NULL, NULL},
+ { "s25", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, 51, 51 }, NULL, NULL},
+ { "s26", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, 52, 52 }, NULL, NULL},
+ { "s27", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, 53, 53 }, NULL, NULL},
+ { "s28", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, 54, 54 }, NULL, NULL},
+ { "s29", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, 55, 55 }, NULL, NULL},
+ { "s30", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, 56, 56 }, NULL, NULL},
+ { "s31", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, 57, 57 }, NULL, NULL},
+ { "fpscr",NULL, 4, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 58, 58 }, NULL, NULL},
+ { "d16", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, 59, 59 }, NULL, NULL},
+ { "d17", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, 60, 60 }, NULL, NULL},
+ { "d18", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, 61, 61 }, NULL, NULL},
+ { "d19", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, 62, 62 }, NULL, NULL},
+ { "d20", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, 63, 63 }, NULL, NULL},
+ { "d21", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, 64, 64 }, NULL, NULL},
+ { "d22", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, 65, 65 }, NULL, NULL},
+ { "d23", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, 66, 66 }, NULL, NULL},
+ { "d24", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, 67, 67 }, NULL, NULL},
+ { "d25", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, 68, 68 }, NULL, NULL},
+ { "d26", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, 69, 69 }, NULL, NULL},
+ { "d27", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, 70, 70 }, NULL, NULL},
+ { "d28", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, 71, 71 }, NULL, NULL},
+ { "d29", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, 72, 72 }, NULL, NULL},
+ { "d30", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, 73, 73 }, NULL, NULL},
+ { "d31", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, 74, 74 }, NULL, NULL},
+ { "d0", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, 75, 75 }, g_d0_regs, NULL},
+ { "d1", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, 76, 76 }, g_d1_regs, NULL},
+ { "d2", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, 77, 77 }, g_d2_regs, NULL},
+ { "d3", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, 78, 78 }, g_d3_regs, NULL},
+ { "d4", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, 79, 79 }, g_d4_regs, NULL},
+ { "d5", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, 80, 80 }, g_d5_regs, NULL},
+ { "d6", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, 81, 81 }, g_d6_regs, NULL},
+ { "d7", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, 82, 82 }, g_d7_regs, NULL},
+ { "d8", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, 83, 83 }, g_d8_regs, NULL},
+ { "d9", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, 84, 84 }, g_d9_regs, NULL},
+ { "d10", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, 85, 85 }, g_d10_regs, NULL},
+ { "d11", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, 86, 86 }, g_d11_regs, NULL},
+ { "d12", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, 87, 87 }, g_d12_regs, NULL},
+ { "d13", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, 88, 88 }, g_d13_regs, NULL},
+ { "d14", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, 89, 89 }, g_d14_regs, NULL},
+ { "d15", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, 90, 90 }, g_d15_regs, NULL},
+ { "q0", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q0, LLDB_INVALID_REGNUM, 91, 91 }, g_q0_regs, NULL},
+ { "q1", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q1, LLDB_INVALID_REGNUM, 92, 92 }, g_q1_regs, NULL},
+ { "q2", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q2, LLDB_INVALID_REGNUM, 93, 93 }, g_q2_regs, NULL},
+ { "q3", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q3, LLDB_INVALID_REGNUM, 94, 94 }, g_q3_regs, NULL},
+ { "q4", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q4, LLDB_INVALID_REGNUM, 95, 95 }, g_q4_regs, NULL},
+ { "q5", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q5, LLDB_INVALID_REGNUM, 96, 96 }, g_q5_regs, NULL},
+ { "q6", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q6, LLDB_INVALID_REGNUM, 97, 97 }, g_q6_regs, NULL},
+ { "q7", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q7, LLDB_INVALID_REGNUM, 98, 98 }, g_q7_regs, NULL},
+ { "q8", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q8, LLDB_INVALID_REGNUM, 99, 99 }, g_q8_regs, NULL},
+ { "q9", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q9, LLDB_INVALID_REGNUM, 100, 100 }, g_q9_regs, NULL},
+ { "q10", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q10, LLDB_INVALID_REGNUM, 101, 101 }, g_q10_regs, NULL},
+ { "q11", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q11, LLDB_INVALID_REGNUM, 102, 102 }, g_q11_regs, NULL},
+ { "q12", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q12, LLDB_INVALID_REGNUM, 103, 103 }, g_q12_regs, NULL},
+ { "q13", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q13, LLDB_INVALID_REGNUM, 104, 104 }, g_q13_regs, NULL},
+ { "q14", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q14, LLDB_INVALID_REGNUM, 105, 105 }, g_q14_regs, NULL},
+ { "q15", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q15, LLDB_INVALID_REGNUM, 106, 106 }, g_q15_regs, NULL}
};
static const uint32_t num_registers = llvm::array_lengthof(g_register_infos);
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index 117d280cc547..0e26c69eb2a9 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -42,32 +42,22 @@ public:
{
}
- ~GDBRemoteDynamicRegisterInfo ()
- {
- }
+ ~GDBRemoteDynamicRegisterInfo() override = default;
void
HardcodeARMRegisters(bool from_scratch);
-
};
class GDBRemoteRegisterContext : public RegisterContext
{
public:
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
GDBRemoteRegisterContext (ThreadGDBRemote &thread,
uint32_t concrete_frame_idx,
GDBRemoteDynamicRegisterInfo &reg_info,
bool read_all_at_once);
- virtual
- ~GDBRemoteRegisterContext ();
+ ~GDBRemoteRegisterContext() override;
- //------------------------------------------------------------------
- // Subclasses must override these functions
- //------------------------------------------------------------------
void
InvalidateAllRegisters () override;
@@ -119,6 +109,9 @@ protected:
bool
PrivateSetRegisterValue (uint32_t reg, StringExtractor &response);
+ bool
+ PrivateSetRegisterValue (uint32_t reg, uint64_t val);
+
void
SetAllRegisterValid (bool b);
@@ -166,13 +159,10 @@ private:
bool SetPrimordialRegister(const RegisterInfo *reg_info,
GDBRemoteCommunicationClient &gdb_comm);
- //------------------------------------------------------------------
- // For GDBRemoteRegisterContext only
- //------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN (GDBRemoteRegisterContext);
};
} // namespace process_gdb_remote
} // namespace lldb_private
-#endif // lldb_GDBRemoteRegisterContext_h_
+#endif // lldb_GDBRemoteRegisterContext_h_
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 1e150b1dda9f..2e7a5b5384f4 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -40,6 +40,7 @@
#include "lldb/Core/Timer.h"
#include "lldb/Core/Value.h"
#include "lldb/DataFormatters/FormatManager.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Host/Symbols.h"
@@ -56,6 +57,7 @@
#include "lldb/Interpreter/OptionGroupUInt64.h"
#include "lldb/Interpreter/Property.h"
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
@@ -192,7 +194,7 @@ public:
{
for (uint32_t i = 0; i < e_num; ++i)
m_has[i] = false;
- };
+ }
void set_name (const std::string & name)
{
@@ -216,6 +218,16 @@ public:
return m_has[e_has_base];
}
+ void set_base_is_offset (bool is_offset)
+ {
+ m_base_is_offset = is_offset;
+ }
+ bool get_base_is_offset(bool & out) const
+ {
+ out = m_base_is_offset;
+ return m_has[e_has_base];
+ }
+
void set_link_map (const lldb::addr_t addr)
{
m_link_map = addr;
@@ -250,6 +262,7 @@ public:
std::string m_name;
lldb::addr_t m_link_map;
lldb::addr_t m_base;
+ bool m_base_is_offset;
lldb::addr_t m_dynamic;
};
@@ -322,22 +335,22 @@ ProcessGDBRemote::Terminate()
lldb::ProcessSP
-ProcessGDBRemote::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file_path)
+ProcessGDBRemote::CreateInstance (lldb::TargetSP target_sp, Listener &listener, const FileSpec *crash_file_path)
{
lldb::ProcessSP process_sp;
if (crash_file_path == NULL)
- process_sp.reset (new ProcessGDBRemote (target, listener));
+ process_sp.reset (new ProcessGDBRemote (target_sp, listener));
return process_sp;
}
bool
-ProcessGDBRemote::CanDebug (Target &target, bool plugin_specified_by_name)
+ProcessGDBRemote::CanDebug (lldb::TargetSP target_sp, bool plugin_specified_by_name)
{
if (plugin_specified_by_name)
return true;
// For now we are just making sure the file exists for a given module
- Module *exe_module = target.GetExecutableModulePointer();
+ Module *exe_module = target_sp->GetExecutableModulePointer();
if (exe_module)
{
ObjectFile *exe_objfile = exe_module->GetObjectFile();
@@ -366,17 +379,20 @@ ProcessGDBRemote::CanDebug (Target &target, bool plugin_specified_by_name)
//----------------------------------------------------------------------
// ProcessGDBRemote constructor
//----------------------------------------------------------------------
-ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
- Process (target, listener),
+ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, Listener &listener) :
+ Process (target_sp, listener),
m_flags (0),
m_gdb_comm (),
m_debugserver_pid (LLDB_INVALID_PROCESS_ID),
m_last_stop_packet_mutex (Mutex::eMutexTypeRecursive),
m_register_info (),
m_async_broadcaster (NULL, "lldb.process.gdb-remote.async-broadcaster"),
+ m_async_listener("lldb.process.gdb-remote.async-listener"),
m_async_thread_state_mutex(Mutex::eMutexTypeRecursive),
m_thread_ids (),
- m_threads_info_sp (),
+ m_thread_pcs (),
+ m_jstopinfo_sp (),
+ m_jthreadsinfo_sp (),
m_continue_c_tids (),
m_continue_C_tids (),
m_continue_s_tids (),
@@ -394,6 +410,25 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit, "async thread should exit");
m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue, "async thread continue");
m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadDidExit, "async thread did exit");
+
+ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_ASYNC));
+
+ const uint32_t async_event_mask = eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit;
+
+ if (m_async_listener.StartListeningForEvents(&m_async_broadcaster, async_event_mask) != async_event_mask)
+ {
+ if (log)
+ log->Printf("ProcessGDBRemote::%s failed to listen for m_async_broadcaster events", __FUNCTION__);
+ }
+
+ const uint32_t gdb_event_mask = Communication::eBroadcastBitReadThreadDidExit |
+ GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify;
+ if (m_async_listener.StartListeningForEvents(&m_gdb_comm, gdb_event_mask) != gdb_event_mask)
+ {
+ if (log)
+ log->Printf("ProcessGDBRemote::%s failed to listen for m_gdb_comm events", __FUNCTION__);
+ }
+
const uint64_t timeout_seconds = GetGlobalPluginProperties()->GetPacketTimeout();
if (timeout_seconds > 0)
m_gdb_comm.SetPacketTimeout(timeout_seconds);
@@ -481,6 +516,40 @@ ProcessGDBRemote::ParsePythonTargetDefinition(const FileSpec &target_definition_
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)
{
@@ -524,11 +593,23 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
// 3 - Fall back on the qRegisterInfo packets.
FileSpec target_definition_fspec = GetGlobalPluginProperties()->GetTargetDefinitionFile ();
+ if (!target_definition_fspec.Exists())
+ {
+ // If the filename doesn't exist, it may be a ~ not having been expanded - try to resolve it.
+ target_definition_fspec.ResolvePath();
+ }
if (target_definition_fspec)
{
// See if we can get register definitions from a python file
if (ParsePythonTargetDefinition (target_definition_fspec))
+ {
return;
+ }
+ else
+ {
+ StreamSP stream_sp = GetTarget().GetDebugger().GetAsyncOutputStream();
+ stream_sp->Printf ("ERROR: target description file %s failed to parse.\n", target_definition_fspec.GetPath().c_str());
+ }
}
if (GetGDBServerRegisterInfo ())
@@ -561,12 +642,12 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
0, // byte size
reg_offset, // offset
eEncodingUint, // encoding
- eFormatHex, // formate
+ eFormatHex, // format
{
- LLDB_INVALID_REGNUM, // GCC reg num
+ LLDB_INVALID_REGNUM, // eh_frame reg num
LLDB_INVALID_REGNUM, // DWARF reg num
LLDB_INVALID_REGNUM, // generic reg num
- reg_num, // GDB reg num
+ reg_num, // process plugin reg num
reg_num // native register number
},
NULL,
@@ -635,9 +716,9 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
{
set_name.SetCString(value.c_str());
}
- else if (name.compare("gcc") == 0)
+ else if (name.compare("gcc") == 0 || name.compare("ehframe") == 0)
{
- reg_info.kinds[eRegisterKindGCC] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0);
+ reg_info.kinds[eRegisterKindEHFrame] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0);
}
else if (name.compare("dwarf") == 0)
{
@@ -671,6 +752,8 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
reg_info.invalidate_regs = invalidate_regs.data();
}
+ AugmentRegisterInfoViaABI (reg_info, reg_name, GetABI ());
+
m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);
}
else
@@ -711,11 +794,12 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
if (!target_arch.IsValid())
{
if (remote_arch.IsValid()
- && remote_arch.GetMachine() == llvm::Triple::arm
+ && (remote_arch.GetMachine() == llvm::Triple::arm || remote_arch.GetMachine() == llvm::Triple::thumb)
&& remote_arch.GetTriple().getVendor() == llvm::Triple::Apple)
m_register_info.HardcodeARMRegisters(from_scratch);
}
- else if (target_arch.GetMachine() == llvm::Triple::arm)
+ else if (target_arch.GetMachine() == llvm::Triple::arm
+ || target_arch.GetMachine() == llvm::Triple::thumb)
{
m_register_info.HardcodeARMRegisters(from_scratch);
}
@@ -779,20 +863,21 @@ ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
if (GetTarget().GetNonStopModeEnabled())
HandleStopReplySequence();
- if (!m_target.GetArchitecture().IsValid())
+ Target &target = GetTarget();
+ if (!target.GetArchitecture().IsValid())
{
if (m_gdb_comm.GetProcessArchitecture().IsValid())
{
- m_target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
+ target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
}
else
{
- m_target.SetArchitecture(m_gdb_comm.GetHostArchitecture());
+ target.SetArchitecture(m_gdb_comm.GetHostArchitecture());
}
}
const StateType state = SetThreadStopInfo (response);
- if (state == eStateStopped)
+ if (state != eStateInvalid)
{
SetPrivateState (state);
}
@@ -910,27 +995,22 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)
ObjectFile * object_file = exe_module->GetObjectFile();
if (object_file)
{
- // Make sure we aren't already connected?
- if (!m_gdb_comm.IsConnected())
- {
- error = LaunchAndConnectToDebugserver (launch_info);
- }
-
+ error = EstablishConnectionIfNeeded (launch_info);
if (error.Success())
{
lldb_utility::PseudoTerminal pty;
const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
- PlatformSP platform_sp (m_target.GetPlatform());
+ PlatformSP platform_sp (GetTarget().GetPlatform());
if (disable_stdio)
{
// set to /dev/null unless redirected to a file above
if (!stdin_file_spec)
- stdin_file_spec.SetFile("/dev/null", false);
+ stdin_file_spec.SetFile(FileSystem::DEV_NULL, false);
if (!stdout_file_spec)
- stdout_file_spec.SetFile("/dev/null", false);
+ stdout_file_spec.SetFile(FileSystem::DEV_NULL, false);
if (!stderr_file_spec)
- stderr_file_spec.SetFile("/dev/null", false);
+ stderr_file_spec.SetFile(FileSystem::DEV_NULL, false);
}
else if (platform_sp && platform_sp->IsHost())
{
@@ -977,7 +1057,7 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)
m_gdb_comm.SetDisableASLR (launch_flags & eLaunchFlagDisableASLR);
m_gdb_comm.SetDetachOnError (launch_flags & eLaunchFlagDetachOnError);
- m_gdb_comm.SendLaunchArchPacket (m_target.GetArchitecture().GetArchitectureName());
+ m_gdb_comm.SendLaunchArchPacket (GetTarget().GetArchitecture().GetArchitectureName());
const char * launch_event_data = launch_info.GetLaunchEventData();
if (launch_event_data != NULL && *launch_event_data != '\0')
@@ -1044,13 +1124,13 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)
if (process_arch.IsValid())
{
- m_target.MergeArchitecture(process_arch);
+ GetTarget().MergeArchitecture(process_arch);
}
else
{
const ArchSpec &host_arch = m_gdb_comm.GetHostArchitecture();
if (host_arch.IsValid())
- m_target.MergeArchitecture(host_arch);
+ GetTarget().MergeArchitecture(host_arch);
}
SetPrivateState (SetThreadStopInfo (response));
@@ -1226,8 +1306,8 @@ ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch)
// it has, so we really need to take the remote host architecture as our
// defacto architecture in this case.
- if (process_arch.GetMachine() == llvm::Triple::arm &&
- process_arch.GetTriple().getVendor() == llvm::Triple::Apple)
+ if ((process_arch.GetMachine() == llvm::Triple::arm || process_arch.GetMachine() == llvm::Triple::thumb)
+ && process_arch.GetTriple().getVendor() == llvm::Triple::Apple)
{
GetTarget().SetArchitecture (process_arch);
if (log)
@@ -1295,21 +1375,7 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const Process
Clear();
if (attach_pid != LLDB_INVALID_PROCESS_ID)
{
- // Make sure we aren't already connected?
- if (!m_gdb_comm.IsConnected())
- {
- error = LaunchAndConnectToDebugserver (attach_info);
-
- if (error.Fail())
- {
- const char *error_string = error.AsCString();
- if (error_string == NULL)
- error_string = "unable to launch " DEBUGSERVER_BASENAME;
-
- SetExitStatus (-1, error_string);
- }
- }
-
+ error = EstablishConnectionIfNeeded (attach_info);
if (error.Success())
{
m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());
@@ -1319,6 +1385,8 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const Process
SetID (attach_pid);
m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet, packet_len));
}
+ else
+ SetExitStatus (-1, error.AsCString());
}
return error;
@@ -1333,21 +1401,7 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, const Pro
if (process_name && process_name[0])
{
- // Make sure we aren't already connected?
- if (!m_gdb_comm.IsConnected())
- {
- error = LaunchAndConnectToDebugserver (attach_info);
-
- if (error.Fail())
- {
- const char *error_string = error.AsCString();
- if (error_string == NULL)
- error_string = "unable to launch " DEBUGSERVER_BASENAME;
-
- SetExitStatus (-1, error_string);
- }
- }
-
+ error = EstablishConnectionIfNeeded (attach_info);
if (error.Success())
{
StreamString packet;
@@ -1371,11 +1425,13 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, const Pro
else
packet.PutCString("vAttachName");
packet.PutChar(';');
- packet.PutBytesAsRawHex8(process_name, strlen(process_name), lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder());
+ packet.PutBytesAsRawHex8(process_name, strlen(process_name), endian::InlHostByteOrder(), endian::InlHostByteOrder());
m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet.GetData(), packet.GetSize()));
}
+ else
+ SetExitStatus (-1, error.AsCString());
}
return error;
}
@@ -1403,6 +1459,8 @@ ProcessGDBRemote::WillResume ()
m_continue_C_tids.clear();
m_continue_s_tids.clear();
m_continue_S_tids.clear();
+ m_jstopinfo_sp.reset();
+ m_jthreadsinfo_sp.reset();
return Error();
}
@@ -1694,12 +1752,14 @@ ProcessGDBRemote::ClearThreadIDList ()
{
Mutex::Locker locker(m_thread_list_real.GetMutex());
m_thread_ids.clear();
+ m_thread_pcs.clear();
}
size_t
ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue (std::string &value)
{
m_thread_ids.clear();
+ m_thread_pcs.clear();
size_t comma_pos;
lldb::tid_t tid;
while ((comma_pos = value.find(',')) != std::string::npos)
@@ -1717,18 +1777,39 @@ ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue (std::string &value)
return m_thread_ids.size();
}
+size_t
+ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue (std::string &value)
+{
+ m_thread_pcs.clear();
+ size_t comma_pos;
+ lldb::addr_t pc;
+ while ((comma_pos = value.find(',')) != std::string::npos)
+ {
+ value[comma_pos] = '\0';
+ pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
+ if (pc != LLDB_INVALID_ADDRESS)
+ m_thread_pcs.push_back (pc);
+ value.erase(0, comma_pos + 1);
+ }
+ pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
+ if (pc != LLDB_INVALID_THREAD_ID)
+ m_thread_pcs.push_back (pc);
+ return m_thread_pcs.size();
+}
+
bool
ProcessGDBRemote::UpdateThreadIDList ()
{
Mutex::Locker locker(m_thread_list_real.GetMutex());
- if (m_threads_info_sp)
+ if (m_jthreadsinfo_sp)
{
// If we have the JSON threads info, we can get the thread list from that
- StructuredData::Array *thread_infos = m_threads_info_sp->GetAsArray();
+ StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray();
if (thread_infos && thread_infos->GetSize() > 0)
{
m_thread_ids.clear();
+ m_thread_pcs.clear();
thread_infos->ForEach([this](StructuredData::Object* object) -> bool {
StructuredData::Dictionary *thread_dict = object->GetAsDictionary();
if (thread_dict)
@@ -1751,25 +1832,43 @@ ProcessGDBRemote::UpdateThreadIDList ()
// that might contain a "threads" key/value pair
// Lock the thread stack while we access it
- Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex);
- // Get the number of stop packets on the stack
- int nItems = m_stop_packet_stack.size();
- // Iterate over them
- for (int i = 0; i < nItems; i++)
+ //Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex);
+ Mutex::Locker stop_stack_lock;
+ if (stop_stack_lock.TryLock(m_last_stop_packet_mutex))
{
- // Get the thread stop info
- StringExtractorGDBRemote &stop_info = m_stop_packet_stack[i];
- const std::string &stop_info_str = stop_info.GetStringRef();
- const size_t threads_pos = stop_info_str.find(";threads:");
- if (threads_pos != std::string::npos)
+ // Get the number of stop packets on the stack
+ int nItems = m_stop_packet_stack.size();
+ // Iterate over them
+ for (int i = 0; i < nItems; i++)
{
- const size_t start = threads_pos + strlen(";threads:");
- const size_t end = stop_info_str.find(';', start);
- if (end != std::string::npos)
+ // Get the thread stop info
+ StringExtractorGDBRemote &stop_info = m_stop_packet_stack[i];
+ const std::string &stop_info_str = stop_info.GetStringRef();
+
+ m_thread_pcs.clear();
+ const size_t thread_pcs_pos = stop_info_str.find(";thread-pcs:");
+ if (thread_pcs_pos != std::string::npos)
+ {
+ const size_t start = thread_pcs_pos + strlen(";thread-pcs:");
+ const size_t end = stop_info_str.find(';', start);
+ if (end != std::string::npos)
+ {
+ std::string value = stop_info_str.substr(start, end - start);
+ UpdateThreadPCsFromStopReplyThreadsValue(value);
+ }
+ }
+
+ const size_t threads_pos = stop_info_str.find(";threads:");
+ if (threads_pos != std::string::npos)
{
- std::string value = stop_info_str.substr(start, end - start);
- if (UpdateThreadIDsFromStopReplyThreadsValue(value))
- return true;
+ const size_t start = threads_pos + strlen(";threads:");
+ const size_t end = stop_info_str.find(';', start);
+ if (end != std::string::npos)
+ {
+ std::string value = stop_info_str.substr(start, end - start);
+ if (UpdateThreadIDsFromStopReplyThreadsValue(value))
+ return true;
+ }
}
}
}
@@ -1826,6 +1925,25 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new
__FUNCTION__, static_cast<void*>(thread_sp.get()),
thread_sp->GetID());
}
+ // The m_thread_pcs vector has pc values in big-endian order, not target-endian, unlike most
+ // of the register read/write packets in gdb-remote protocol.
+ // Early in the process startup, we may not yet have set the process ByteOrder so we ignore these;
+ // they are a performance improvement over fetching thread register values individually, the
+ // method we will fall back to if needed.
+ if (m_thread_ids.size() == m_thread_pcs.size() && thread_sp.get() && GetByteOrder() != eByteOrderInvalid)
+ {
+ ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get());
+ RegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext());
+ if (reg_ctx_sp)
+ {
+ uint32_t pc_regnum = reg_ctx_sp->ConvertRegisterKindToRegisterNumber
+ (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ if (pc_regnum != LLDB_INVALID_REGNUM)
+ {
+ gdb_thread->PrivateSetRegisterValue (pc_regnum, m_thread_pcs[i]);
+ }
+ }
+ }
new_thread_list.AddThread(thread_sp);
}
}
@@ -1846,13 +1964,14 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new
return true;
}
+
bool
-ProcessGDBRemote::CalculateThreadStopInfo (ThreadGDBRemote *thread)
+ProcessGDBRemote::GetThreadStopInfoFromJSON (ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp)
{
// See if we got thread stop infos for all threads via the "jThreadsInfo" packet
- if (m_threads_info_sp)
+ if (thread_infos_sp)
{
- StructuredData::Array *thread_infos = m_threads_info_sp->GetAsArray();
+ StructuredData::Array *thread_infos = thread_infos_sp->GetAsArray();
if (thread_infos)
{
lldb::tid_t tid;
@@ -1865,12 +1984,36 @@ ProcessGDBRemote::CalculateThreadStopInfo (ThreadGDBRemote *thread)
if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid, LLDB_INVALID_THREAD_ID))
{
if (tid == thread->GetID())
- return SetThreadStopInfo(thread_dict);
+ return (bool)SetThreadStopInfo(thread_dict);
}
}
}
}
}
+ return false;
+}
+
+bool
+ProcessGDBRemote::CalculateThreadStopInfo (ThreadGDBRemote *thread)
+{
+ // See if we got thread stop infos for all threads via the "jThreadsInfo" packet
+ if (GetThreadStopInfoFromJSON (thread, m_jthreadsinfo_sp))
+ return true;
+
+ // See if we got thread stop info for any threads valid stop info reasons threads
+ // via the "jstopinfo" packet stop reply packet key/value pair?
+ if (m_jstopinfo_sp)
+ {
+ // If we have "jstopinfo" then we have stop descriptions for all threads
+ // that have stop reasons, and if there is no entry for a thread, then
+ // it has no stop reason.
+ thread->GetRegisterContext()->InvalidateIfNeeded(true);
+ if (!GetThreadStopInfoFromJSON (thread, m_jstopinfo_sp))
+ {
+ thread->SetStopInfo (StopInfoSP());
+ }
+ return true;
+ }
// Fall back to using the qThreadStopInfo packet
StringExtractorGDBRemote stop_packet;
@@ -1926,8 +2069,6 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,
gdb_thread->PrivateSetRegisterValue (pair.first, reg_value_extractor);
}
- // Clear the stop info just in case we don't set it to anything
- thread_sp->SetStopInfo (StopInfoSP());
thread_sp->SetName (thread_name.empty() ? NULL : thread_name.c_str());
gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr);
@@ -1937,145 +2078,159 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,
else
gdb_thread->ClearQueueInfo();
-
- if (exc_type != 0)
- {
- const size_t exc_data_size = exc_data.size();
-
- thread_sp->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp,
- exc_type,
- exc_data_size,
- exc_data_size >= 1 ? exc_data[0] : 0,
- exc_data_size >= 2 ? exc_data[1] : 0,
- exc_data_size >= 3 ? exc_data[2] : 0));
- }
- else
+ // Make sure we update our thread stop reason just once
+ if (!thread_sp->StopInfoIsUpToDate())
{
- bool handled = false;
- bool did_exec = false;
- if (!reason.empty())
+ thread_sp->SetStopInfo (StopInfoSP());
+ // If there's a memory thread backed by this thread, we need to use it to calcualte StopInfo.
+ ThreadSP memory_thread_sp = m_thread_list.FindThreadByProtocolID(thread_sp->GetProtocolID());
+ if (memory_thread_sp)
+ thread_sp = memory_thread_sp;
+
+ if (exc_type != 0)
{
- if (reason.compare("trace") == 0)
- {
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
- handled = true;
- }
- else if (reason.compare("breakpoint") == 0)
+ const size_t exc_data_size = exc_data.size();
+
+ thread_sp->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp,
+ exc_type,
+ exc_data_size,
+ exc_data_size >= 1 ? exc_data[0] : 0,
+ exc_data_size >= 2 ? exc_data[1] : 0,
+ exc_data_size >= 3 ? exc_data[2] : 0));
+ }
+ else
+ {
+ bool handled = false;
+ bool did_exec = false;
+ if (!reason.empty())
{
- addr_t pc = thread_sp->GetRegisterContext()->GetPC();
- lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
- if (bp_site_sp)
+ if (reason.compare("trace") == 0)
{
- // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
- // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that
- // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
handled = true;
- if (bp_site_sp->ValidForThisThread (thread_sp.get()))
- {
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
- }
- else
+ }
+ else if (reason.compare("breakpoint") == 0)
+ {
+ addr_t pc = thread_sp->GetRegisterContext()->GetPC();
+ lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
+ if (bp_site_sp)
{
- StopInfoSP invalid_stop_info_sp;
- thread_sp->SetStopInfo (invalid_stop_info_sp);
+ // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
+ // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that
+ // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
+ handled = true;
+ if (bp_site_sp->ValidForThisThread (thread_sp.get()))
+ {
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
+ }
+ else
+ {
+ StopInfoSP invalid_stop_info_sp;
+ thread_sp->SetStopInfo (invalid_stop_info_sp);
+ }
}
}
- }
- else if (reason.compare("trap") == 0)
- {
- // Let the trap just use the standard signal stop reason below...
- }
- else if (reason.compare("watchpoint") == 0)
- {
- StringExtractor desc_extractor(description.c_str());
- addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
- uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32);
- addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
- watch_id_t watch_id = LLDB_INVALID_WATCH_ID;
- if (wp_addr != LLDB_INVALID_ADDRESS)
+ else if (reason.compare("trap") == 0)
{
- WatchpointSP wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr);
- if (wp_sp)
+ // Let the trap just use the standard signal stop reason below...
+ }
+ else if (reason.compare("watchpoint") == 0)
+ {
+ StringExtractor desc_extractor(description.c_str());
+ addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
+ uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32);
+ addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
+ watch_id_t watch_id = LLDB_INVALID_WATCH_ID;
+ if (wp_addr != LLDB_INVALID_ADDRESS)
+ {
+ WatchpointSP wp_sp;
+ ArchSpec::Core core = GetTarget().GetArchitecture().GetCore();
+ if (core >= ArchSpec::kCore_mips_first && core <= ArchSpec::kCore_mips_last)
+ wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_hit_addr);
+ if (!wp_sp)
+ wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr);
+ if (wp_sp)
+ {
+ wp_sp->SetHardwareIndex(wp_index);
+ watch_id = wp_sp->GetID();
+ }
+ }
+ if (watch_id == LLDB_INVALID_WATCH_ID)
{
- wp_sp->SetHardwareIndex(wp_index);
- watch_id = wp_sp->GetID();
+ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_WATCHPOINTS));
+ if (log) log->Printf ("failed to find watchpoint");
}
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id, wp_hit_addr));
+ handled = true;
}
- if (watch_id == LLDB_INVALID_WATCH_ID)
+ else if (reason.compare("exception") == 0)
{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_WATCHPOINTS));
- if (log) log->Printf ("failed to find watchpoint");
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException(*thread_sp, description.c_str()));
+ handled = true;
+ }
+ else if (reason.compare("exec") == 0)
+ {
+ did_exec = true;
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithExec(*thread_sp));
+ handled = true;
}
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id, wp_hit_addr));
- handled = true;
- }
- else if (reason.compare("exception") == 0)
- {
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException(*thread_sp, description.c_str()));
- handled = true;
- }
- else if (reason.compare("exec") == 0)
- {
- did_exec = true;
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithExec(*thread_sp));
- handled = true;
}
- }
- if (!handled && signo && did_exec == false)
- {
- if (signo == SIGTRAP)
+ if (!handled && signo && did_exec == false)
{
- // Currently we are going to assume SIGTRAP means we are either
- // hitting a breakpoint or hardware single stepping.
- handled = true;
- addr_t pc = thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset;
- lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
-
- if (bp_site_sp)
+ if (signo == SIGTRAP)
{
- // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
- // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that
- // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
- if (bp_site_sp->ValidForThisThread (thread_sp.get()))
+ // Currently we are going to assume SIGTRAP means we are either
+ // hitting a breakpoint or hardware single stepping.
+ handled = true;
+ addr_t pc = thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset;
+ lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
+
+ if (bp_site_sp)
{
- if(m_breakpoint_pc_offset != 0)
- thread_sp->GetRegisterContext()->SetPC(pc);
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
+ // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
+ // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that
+ // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
+ if (bp_site_sp->ValidForThisThread (thread_sp.get()))
+ {
+ if(m_breakpoint_pc_offset != 0)
+ thread_sp->GetRegisterContext()->SetPC(pc);
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
+ }
+ else
+ {
+ StopInfoSP invalid_stop_info_sp;
+ thread_sp->SetStopInfo (invalid_stop_info_sp);
+ }
}
else
{
- StopInfoSP invalid_stop_info_sp;
- thread_sp->SetStopInfo (invalid_stop_info_sp);
+ // If we were stepping then assume the stop was the result of the trace. If we were
+ // not stepping then report the SIGTRAP.
+ // FIXME: We are still missing the case where we single step over a trap instruction.
+ if (thread_sp->GetTemporaryResumeState() == eStateStepping)
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
+ else
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal(*thread_sp, signo, description.c_str()));
}
}
- else
- {
- // If we were stepping then assume the stop was the result of the trace. If we were
- // not stepping then report the SIGTRAP.
- // FIXME: We are still missing the case where we single step over a trap instruction.
- if (thread_sp->GetTemporaryResumeState() == eStateStepping)
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
- else
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal(*thread_sp, signo, description.c_str()));
- }
+ if (!handled)
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo, description.c_str()));
}
- if (!handled)
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo, description.c_str()));
- }
- if (!description.empty())
- {
- lldb::StopInfoSP stop_info_sp (thread_sp->GetStopInfo ());
- if (stop_info_sp)
- {
- const char *stop_info_desc = stop_info_sp->GetDescription();
- if (!stop_info_desc || !stop_info_desc[0])
- stop_info_sp->SetDescription (description.c_str());
- }
- else
+ if (!description.empty())
{
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException (*thread_sp, description.c_str()));
+ lldb::StopInfoSP stop_info_sp (thread_sp->GetStopInfo ());
+ if (stop_info_sp)
+ {
+ const char *stop_info_desc = stop_info_sp->GetDescription();
+ if (!stop_info_desc || !stop_info_desc[0])
+ stop_info_sp->SetDescription (description.c_str());
+ }
+ else
+ {
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException (*thread_sp, description.c_str()));
+ }
}
}
}
@@ -2084,7 +2239,7 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,
return thread_sp;
}
-StateType
+lldb::ThreadSP
ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
{
static ConstString g_key_tid("tid");
@@ -2101,6 +2256,7 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
static ConstString g_key_address("address");
static ConstString g_key_bytes("bytes");
static ConstString g_key_description("description");
+ static ConstString g_key_signal("signal");
// Stop with signal and thread info
lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
@@ -2159,7 +2315,7 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
}
else if (key == g_key_name)
{
- thread_name = std::move(object->GetStringValue());
+ thread_name = object->GetStringValue();
}
else if (key == g_key_qaddr)
{
@@ -2168,7 +2324,7 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
else if (key == g_key_queue_name)
{
queue_vars_valid = true;
- queue_name = std::move(object->GetStringValue());
+ queue_name = object->GetStringValue();
}
else if (key == g_key_queue_kind)
{
@@ -2192,11 +2348,11 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
}
else if (key == g_key_reason)
{
- reason = std::move(object->GetStringValue());
+ reason = object->GetStringValue();
}
else if (key == g_key_description)
{
- description = std::move(object->GetStringValue());
+ description = object->GetStringValue();
}
else if (key == g_key_registers)
{
@@ -2207,7 +2363,7 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
registers_dict->ForEach([&expedited_register_map](ConstString key, StructuredData::Object* object) -> bool {
const uint32_t reg = StringConvert::ToUInt32 (key.GetCString(), UINT32_MAX, 10);
if (reg != UINT32_MAX)
- expedited_register_map[reg] = std::move(object->GetStringValue());
+ expedited_register_map[reg] = object->GetStringValue();
return true; // Keep iterating through all array items
});
}
@@ -2245,24 +2401,24 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
}
}
+ else if (key == g_key_signal)
+ signo = object->GetIntegerValue(LLDB_INVALID_SIGNAL_NUMBER);
return true; // Keep iterating through all dictionary key/value pairs
});
- SetThreadStopInfo (tid,
- expedited_register_map,
- signo,
- thread_name,
- reason,
- description,
- exc_type,
- exc_data,
- thread_dispatch_qaddr,
- queue_vars_valid,
- queue_name,
- queue_kind,
- queue_serial);
-
- return eStateExited;
+ return SetThreadStopInfo (tid,
+ expedited_register_map,
+ signo,
+ thread_name,
+ reason,
+ description,
+ exc_type,
+ exc_data,
+ thread_dispatch_qaddr,
+ queue_vars_valid,
+ queue_name,
+ queue_kind,
+ queue_serial);
}
StateType
@@ -2348,6 +2504,39 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
if (tid != LLDB_INVALID_THREAD_ID)
m_thread_ids.push_back (tid);
}
+ else if (key.compare("thread-pcs") == 0)
+ {
+ m_thread_pcs.clear();
+ // A comma separated list of all threads in the current
+ // process that includes the thread for this stop reply
+ // packet
+ size_t comma_pos;
+ lldb::addr_t pc;
+ while ((comma_pos = value.find(',')) != std::string::npos)
+ {
+ value[comma_pos] = '\0';
+ // thread in big endian hex
+ pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
+ if (pc != LLDB_INVALID_ADDRESS)
+ m_thread_pcs.push_back (pc);
+ value.erase(0, comma_pos + 1);
+ }
+ pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
+ if (pc != LLDB_INVALID_ADDRESS)
+ m_thread_pcs.push_back (pc);
+ }
+ else if (key.compare("jstopinfo") == 0)
+ {
+ StringExtractor json_extractor;
+ // Swap "value" over into "name_extractor"
+ json_extractor.GetStringRef().swap(value);
+ // Now convert the HEX bytes into a string value
+ json_extractor.GetHexByteString (value);
+
+ // This JSON contains thread IDs and thread stop info for all threads.
+ // It doesn't contain expedited registers, memory or queue info.
+ m_jstopinfo_sp = StructuredData::ParseJSON (value);
+ }
else if (key.compare("hexname") == 0)
{
StringExtractor name_extractor;
@@ -2431,7 +2620,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
if (mem_cache_addr != LLDB_INVALID_ADDRESS)
{
StringExtractor bytes;
- bytes.GetStringRef() = std::move(pair.second.str());
+ bytes.GetStringRef() = pair.second.str();
const size_t byte_size = bytes.GetStringRef().size()/2;
DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0));
const size_t bytes_copied = bytes.GetHexBytes (data_buffer_sp->GetBytes(), byte_size, 0);
@@ -2455,6 +2644,10 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
ostr.Printf("%" PRIu64 " %" PRIu32, wp_addr, wp_index);
description = ostr.GetString().c_str();
}
+ else if (key.compare("library") == 0)
+ {
+ LoadModules();
+ }
else if (key.size() == 2 && ::isxdigit(key[0]) && ::isxdigit(key[1]))
{
uint32_t reg = StringConvert::ToUInt32 (key.c_str(), UINT32_MAX, 16);
@@ -2509,6 +2702,7 @@ ProcessGDBRemote::RefreshStateAfterStop ()
{
Mutex::Locker locker(m_thread_list_real.GetMutex());
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.
@@ -2545,11 +2739,6 @@ ProcessGDBRemote::RefreshStateAfterStop ()
m_initial_tid = LLDB_INVALID_THREAD_ID;
}
- // Fetch the threads via an efficient packet that gets stop infos for all threads
- // only if we have more than one thread
- if (m_thread_ids.size() > 1)
- m_threads_info_sp = m_gdb_comm.GetThreadsInfo();
-
// Let all threads recover from stopping and do any clean up based
// on the previous thread state (if any).
m_thread_list_real.RefreshStateAfterStop();
@@ -2824,6 +3013,12 @@ ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)
{
// Lock the thread stack while we access it
Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex);
+
+ // We are are not using non-stop mode, there can only be one last stop
+ // reply packet, so clear the list.
+ if (GetTarget().GetNonStopModeEnabled() == false)
+ m_stop_packet_stack.clear();
+
// Add this stop packet to the stop packet stack
// This stack will get popped and examined when we switch to the
// Stopped state
@@ -2831,6 +3026,11 @@ ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)
}
}
+void
+ProcessGDBRemote::SetUnixSignals(const UnixSignalsSP &signals_sp)
+{
+ Process::SetUnixSignals(std::make_shared<GDBRemoteSignals>(signals_sp));
+}
//------------------------------------------------------------------
// Process Queries
@@ -2839,7 +3039,7 @@ ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)
bool
ProcessGDBRemote::IsAlive ()
{
- return m_gdb_comm.IsConnected() && m_private_state.GetValue() != eStateExited;
+ return m_gdb_comm.IsConnected() && Process::IsAlive();
}
addr_t
@@ -2859,6 +3059,35 @@ ProcessGDBRemote::GetImageInfoAddress()
return addr;
}
+void
+ProcessGDBRemote::WillPublicStop ()
+{
+ // See if the GDB remote client supports the JSON threads info.
+ // If so, we gather stop info for all threads, expedited registers,
+ // expedited memory, runtime queue information (iOS and MacOSX only),
+ // and more. Expediting memory will help stack backtracing be much
+ // faster. Expediting registers will make sure we don't have to read
+ // the thread registers for GPRs.
+ m_jthreadsinfo_sp = m_gdb_comm.GetThreadsInfo();
+
+ if (m_jthreadsinfo_sp)
+ {
+ // Now set the stop info for each thread and also expedite any registers
+ // and memory that was in the jThreadsInfo response.
+ StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray();
+ if (thread_infos)
+ {
+ const size_t n = thread_infos->GetSize();
+ for (size_t i=0; i<n; ++i)
+ {
+ StructuredData::Dictionary *thread_dict = thread_infos->GetItemAtIndex(i)->GetAsDictionary();
+ if (thread_dict)
+ SetThreadStopInfo(thread_dict);
+ }
+ }
+ }
+}
+
//------------------------------------------------------------------
// Process Memory
//------------------------------------------------------------------
@@ -2877,14 +3106,8 @@ ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &erro
char packet[64];
int packet_len;
bool binary_memory_read = m_gdb_comm.GetxPacketSupported();
- if (binary_memory_read)
- {
- packet_len = ::snprintf (packet, sizeof(packet), "x0x%" PRIx64 ",0x%" PRIx64, (uint64_t)addr, (uint64_t)size);
- }
- else
- {
- packet_len = ::snprintf (packet, sizeof(packet), "m%" PRIx64 ",%" PRIx64, (uint64_t)addr, (uint64_t)size);
- }
+ packet_len = ::snprintf(packet, sizeof(packet), "%c%" PRIx64 ",%" PRIx64,
+ binary_memory_read ? 'x' : 'm', (uint64_t)addr, (uint64_t)size);
assert (packet_len + 1 < (int)sizeof(packet));
StringExtractorGDBRemote response;
if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true) == GDBRemoteCommunication::PacketResult::Success)
@@ -2940,7 +3163,7 @@ ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Erro
StreamString packet;
packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size);
- packet.PutBytesAsRawHex8(buf, size, lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder());
+ packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(), endian::InlHostByteOrder());
StringExtractorGDBRemote response;
if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, true) == GDBRemoteCommunication::PacketResult::Success)
{
@@ -3377,6 +3600,27 @@ ProcessGDBRemote::DoSignal (int signo)
}
Error
+ProcessGDBRemote::EstablishConnectionIfNeeded (const ProcessInfo &process_info)
+{
+ // Make sure we aren't already connected?
+ if (m_gdb_comm.IsConnected())
+ return Error();
+
+ PlatformSP platform_sp (GetTarget ().GetPlatform ());
+ if (platform_sp && !platform_sp->IsHost ())
+ return Error("Lost debug server connection");
+
+ auto error = LaunchAndConnectToDebugserver (process_info);
+ if (error.Fail())
+ {
+ const char *error_string = error.AsCString();
+ if (error_string == nullptr)
+ error_string = "unable to launch " DEBUGSERVER_BASENAME;
+ }
+ return error;
+}
+
+Error
ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info)
{
Error error;
@@ -3401,14 +3645,22 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info
// Set hostname being NULL to do the reverse connect where debugserver
// will bind to port zero and it will communicate back to us the port
// that we will connect to
- const char *hostname = NULL;
+ const char *hostname = nullptr;
uint16_t port = 0;
#endif
- error = m_gdb_comm.StartDebugserverProcess (hostname,
- port,
+ StreamString url_str;
+ const char* url = nullptr;
+ if (hostname != nullptr)
+ {
+ url_str.Printf("%s:%u", hostname, port);
+ url = url_str.GetData();
+ }
+
+ error = m_gdb_comm.StartDebugserverProcess (url,
+ GetTarget().GetPlatform().get(),
debugserver_launch_info,
- port);
+ &port);
if (error.Success ())
m_debugserver_pid = debugserver_launch_info.GetProcessID();
@@ -3653,164 +3905,174 @@ ProcessGDBRemote::AsyncThread (void *arg)
if (log)
log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread starting...", __FUNCTION__, arg, process->GetID());
- Listener listener ("ProcessGDBRemote::AsyncThread");
EventSP event_sp;
- const uint32_t desired_event_mask = eBroadcastBitAsyncContinue |
- eBroadcastBitAsyncThreadShouldExit;
-
- if (listener.StartListeningForEvents (&process->m_async_broadcaster, desired_event_mask) == desired_event_mask)
+ bool done = false;
+ while (!done)
{
- listener.StartListeningForEvents (&process->m_gdb_comm, Communication::eBroadcastBitReadThreadDidExit |
- GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify);
-
- bool done = false;
- while (!done)
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID());
+ if (process->m_async_listener.WaitForEvent (NULL, event_sp))
{
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID());
- if (listener.WaitForEvent (NULL, event_sp))
+ const uint32_t event_type = event_sp->GetType();
+ if (event_sp->BroadcasterIs (&process->m_async_broadcaster))
{
- const uint32_t event_type = event_sp->GetType();
- if (event_sp->BroadcasterIs (&process->m_async_broadcaster))
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type);
+
+ switch (event_type)
{
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type);
+ case eBroadcastBitAsyncContinue:
+ {
+ const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get());
- switch (event_type)
- {
- case eBroadcastBitAsyncContinue:
+ if (continue_packet)
{
- const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get());
+ const char *continue_cstr = (const char *)continue_packet->GetBytes ();
+ const size_t continue_cstr_len = continue_packet->GetByteSize ();
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr);
- if (continue_packet)
+ if (::strstr (continue_cstr, "vAttach") == NULL)
+ process->SetPrivateState(eStateRunning);
+ StringExtractorGDBRemote response;
+
+ // If in Non-Stop-Mode
+ if (process->GetTarget().GetNonStopModeEnabled())
{
- const char *continue_cstr = (const char *)continue_packet->GetBytes ();
- const size_t continue_cstr_len = continue_packet->GetByteSize ();
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr);
-
- if (::strstr (continue_cstr, "vAttach") == NULL)
- process->SetPrivateState(eStateRunning);
- StringExtractorGDBRemote response;
-
- // If in Non-Stop-Mode
- if (process->GetTarget().GetNonStopModeEnabled())
+ // send the vCont packet
+ if (!process->GetGDBRemote().SendvContPacket(process, continue_cstr, continue_cstr_len, response))
{
- // send the vCont packet
- if (!process->GetGDBRemote().SendvContPacket(process, continue_cstr, continue_cstr_len, response))
- {
- // Something went wrong
- done = true;
- break;
- }
+ // Something went wrong
+ done = true;
+ break;
}
- // If in All-Stop-Mode
- else
- {
- StateType stop_state = process->GetGDBRemote().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response);
-
- // We need to immediately clear the thread ID list so we are sure to get a valid list of threads.
- // The thread ID list might be contained within the "response", or the stop reply packet that
- // caused the stop. So clear it now before we give the stop reply packet to the process
- // using the process->SetLastStopPacket()...
- process->ClearThreadIDList ();
+ }
+ // If in All-Stop-Mode
+ else
+ {
+ StateType stop_state = process->GetGDBRemote().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response);
- switch (stop_state)
- {
- case eStateStopped:
- case eStateCrashed:
- case eStateSuspended:
- process->SetLastStopPacket (response);
- process->SetPrivateState (stop_state);
- break;
+ // We need to immediately clear the thread ID list so we are sure to get a valid list of threads.
+ // The thread ID list might be contained within the "response", or the stop reply packet that
+ // caused the stop. So clear it now before we give the stop reply packet to the process
+ // using the process->SetLastStopPacket()...
+ process->ClearThreadIDList ();
- case eStateExited:
+ switch (stop_state)
+ {
+ case eStateStopped:
+ case eStateCrashed:
+ case eStateSuspended:
+ process->SetLastStopPacket (response);
+ process->SetPrivateState (stop_state);
+ break;
+
+ case eStateExited:
+ {
+ process->SetLastStopPacket (response);
+ process->ClearThreadIDList();
+ response.SetFilePos(1);
+
+ int exit_status = response.GetHexU8();
+ const char *desc_cstr = NULL;
+ StringExtractor extractor;
+ std::string desc_string;
+ if (response.GetBytesLeft() > 0 && response.GetChar('-') == ';')
{
- process->SetLastStopPacket (response);
- process->ClearThreadIDList();
- response.SetFilePos(1);
-
- int exit_status = response.GetHexU8();
- const char *desc_cstr = NULL;
- StringExtractor extractor;
- std::string desc_string;
- if (response.GetBytesLeft() > 0 && response.GetChar('-') == ';')
+ std::string desc_token;
+ while (response.GetNameColonValue (desc_token, desc_string))
{
- std::string desc_token;
- while (response.GetNameColonValue (desc_token, desc_string))
+ if (desc_token == "description")
{
- if (desc_token == "description")
- {
- extractor.GetStringRef().swap(desc_string);
- extractor.SetFilePos(0);
- extractor.GetHexByteString (desc_string);
- desc_cstr = desc_string.c_str();
- }
+ extractor.GetStringRef().swap(desc_string);
+ extractor.SetFilePos(0);
+ extractor.GetHexByteString (desc_string);
+ desc_cstr = desc_string.c_str();
}
}
- process->SetExitStatus(exit_status, desc_cstr);
- done = true;
- break;
}
- case eStateInvalid:
+ process->SetExitStatus(exit_status, desc_cstr);
+ done = true;
+ break;
+ }
+ case eStateInvalid:
+ {
+ // Check to see if we were trying to attach and if we got back
+ // the "E87" error code from debugserver -- this indicates that
+ // the process is not debuggable. Return a slightly more helpful
+ // error message about why the attach failed.
+ if (::strstr (continue_cstr, "vAttach") != NULL
+ && response.GetError() == 0x87)
+ {
+ process->SetExitStatus(-1, "cannot attach to process due to System Integrity Protection");
+ }
+ // E01 code from vAttach means that the attach failed
+ if (::strstr (continue_cstr, "vAttach") != NULL
+ && response.GetError() == 0x1)
+ {
+ process->SetExitStatus(-1, "unable to attach");
+ }
+ else
+ {
process->SetExitStatus(-1, "lost connection");
+ }
break;
+ }
- default:
- process->SetPrivateState (stop_state);
- break;
- } // switch(stop_state)
- } // else // if in All-stop-mode
- } // if (continue_packet)
- } // case eBroadcastBitAysncContinue
- break;
+ default:
+ process->SetPrivateState (stop_state);
+ break;
+ } // switch(stop_state)
+ } // else // if in All-stop-mode
+ } // if (continue_packet)
+ } // case eBroadcastBitAysncContinue
+ break;
- case eBroadcastBitAsyncThreadShouldExit:
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID());
- done = true;
- break;
+ case eBroadcastBitAsyncThreadShouldExit:
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID());
+ done = true;
+ break;
- default:
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
- done = true;
- break;
- }
+ default:
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
+ done = true;
+ break;
}
- else if (event_sp->BroadcasterIs (&process->m_gdb_comm))
+ }
+ else if (event_sp->BroadcasterIs (&process->m_gdb_comm))
+ {
+ switch (event_type)
{
- switch (event_type)
- {
- case Communication::eBroadcastBitReadThreadDidExit:
- process->SetExitStatus (-1, "lost connection");
- done = true;
- break;
-
- case GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify:
- {
- lldb_private::Event *event = event_sp.get();
- const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event);
- StringExtractorGDBRemote notify((const char*)continue_packet->GetBytes());
- // Hand this over to the process to handle
- process->HandleNotifyPacket(notify);
- break;
- }
+ case Communication::eBroadcastBitReadThreadDidExit:
+ process->SetExitStatus (-1, "lost connection");
+ done = true;
+ break;
- default:
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
- done = true;
- break;
+ case GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify:
+ {
+ lldb_private::Event *event = event_sp.get();
+ const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event);
+ StringExtractorGDBRemote notify((const char*)continue_packet->GetBytes());
+ // Hand this over to the process to handle
+ process->HandleNotifyPacket(notify);
+ break;
}
+
+ default:
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
+ done = true;
+ break;
}
}
- else
- {
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID());
- done = true;
- }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID());
+ done = true;
}
}
@@ -3864,10 +4126,10 @@ ProcessGDBRemote::StartNoticingNewThreads()
}
else
{
- PlatformSP platform_sp (m_target.GetPlatform());
+ PlatformSP platform_sp (GetTarget().GetPlatform());
if (platform_sp)
{
- m_thread_create_bp_sp = platform_sp->SetThreadCreationBreakpoint(m_target);
+ m_thread_create_bp_sp = platform_sp->SetThreadCreationBreakpoint(GetTarget());
if (m_thread_create_bp_sp)
{
if (log && log->GetVerbose())
@@ -3986,6 +4248,9 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres
if (m_gdb_comm.GetLoadedDynamicLibrariesInfosSupported())
{
+ // Scope for the scoped timeout object
+ GDBRemoteCommunication::ScopedTimeout timeout (m_gdb_comm, 10);
+
StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
args_dict->GetAsDictionary()->AddIntegerItem ("image_list_address", image_list_address);
args_dict->GetAsDictionary()->AddIntegerItem ("image_count", image_count);
@@ -4009,8 +4274,6 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres
{
if (!response.Empty())
{
- // The packet has already had the 0x7d xor quoting stripped out at the
- // GDBRemoteCommunication packet receive level.
object_sp = StructuredData::ParseJSON (response.GetStringRef());
}
}
@@ -4019,7 +4282,6 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres
return object_sp;
}
-
// Establish the largest memory read/write payloads we should use.
// If the remote stub has a max packet size, stay under that size.
//
@@ -4113,6 +4375,18 @@ ProcessGDBRemote::GetModuleSpec(const FileSpec& module_file_spec,
return true;
}
+bool
+ProcessGDBRemote::GetHostOSVersion(uint32_t &major,
+ uint32_t &minor,
+ uint32_t &update)
+{
+ if (m_gdb_comm.GetOSVersion(major, minor, update))
+ return true;
+ // We failed to get the host OS version, defer to the base
+ // implementation to correctly invalidate the arguments.
+ return Process::GetHostOSVersion(major, minor, update);
+}
+
namespace {
typedef std::vector<std::string> stringVec;
@@ -4135,15 +4409,15 @@ struct GdbServerTargetInfo
};
bool
-ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info)
+ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp)
{
if (!feature_node)
return false;
- uint32_t prev_reg_num = 0;
+ uint32_t cur_reg_num = 0;
uint32_t reg_offset = 0;
- feature_node.ForEachChildElementWithName("reg", [&target_info, &dyn_reg_info, &prev_reg_num, &reg_offset](const XMLNode &reg_node) -> bool {
+ feature_node.ForEachChildElementWithName("reg", [&target_info, &dyn_reg_info, &cur_reg_num, &reg_offset, &abi_sp](const XMLNode &reg_node) -> bool {
std::string gdb_group;
std::string gdb_type;
ConstString reg_name;
@@ -4158,19 +4432,19 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot
0, // byte size
reg_offset, // offset
eEncodingUint, // encoding
- eFormatHex, // formate
+ eFormatHex, // format
{
- LLDB_INVALID_REGNUM, // GCC reg num
+ LLDB_INVALID_REGNUM, // eh_frame reg num
LLDB_INVALID_REGNUM, // DWARF reg num
LLDB_INVALID_REGNUM, // generic reg num
- prev_reg_num, // GDB reg num
- prev_reg_num // native register number
+ cur_reg_num, // process plugin reg num
+ cur_reg_num // native register number
},
NULL,
NULL
};
- reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, &reg_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, &reg_info, &prev_reg_num, &reg_offset](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {
+ reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, &reg_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, &reg_info, &cur_reg_num, &reg_offset](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {
if (name == "name")
{
reg_name.SetString(value);
@@ -4192,9 +4466,7 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot
const uint32_t regnum = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
if (regnum != LLDB_INVALID_REGNUM)
{
- reg_info.kinds[eRegisterKindGDB] = regnum;
- reg_info.kinds[eRegisterKindLLDB] = regnum;
- prev_reg_num = regnum;
+ reg_info.kinds[eRegisterKindProcessPlugin] = regnum;
}
}
else if (name == "offset")
@@ -4240,9 +4512,9 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot
if (pos != target_info.reg_set_map.end())
set_name = pos->second.name;
}
- else if (name == "gcc_regnum")
+ else if (name == "gcc_regnum" || name == "ehframe_regnum")
{
- reg_info.kinds[eRegisterKindGCC] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
+ reg_info.kinds[eRegisterKindEHFrame] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
}
else if (name == "dwarf_regnum")
{
@@ -4305,7 +4577,8 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot
reg_info.invalidate_regs = invalidate_regs.data();
}
- ++prev_reg_num;
+ ++cur_reg_num;
+ AugmentRegisterInfoViaABI (reg_info, reg_name, abi_sp);
dyn_reg_info.AddRegister(reg_info, reg_name, alt_name, set_name);
return true; // Keep iterating through all "reg" elements
@@ -4401,7 +4674,7 @@ ProcessGDBRemote::GetGDBServerRegisterInfo ()
if (feature_node)
{
- ParseRegisters(feature_node, target_info, this->m_register_info);
+ ParseRegisters(feature_node, target_info, this->m_register_info, GetABI());
}
for (const auto &include : target_info.includes)
@@ -4419,7 +4692,7 @@ ProcessGDBRemote::GetGDBServerRegisterInfo ()
XMLNode include_feature_node = include_xml_document.GetRootElement("feature");
if (include_feature_node)
{
- ParseRegisters(include_feature_node, target_info, this->m_register_info);
+ ParseRegisters(include_feature_node, target_info, this->m_register_info, GetABI());
}
}
this->m_register_info.Finalize(GetTarget().GetArchitecture());
@@ -4489,7 +4762,8 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
{
// the displacement as read from the field 'l_addr' of the link_map struct.
module.set_base(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0));
-
+ // base address is always a displacement, not an absolute value.
+ module.set_base_is_offset(true);
}
else if (name == "l_ld")
{
@@ -4504,13 +4778,15 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
{
std::string name;
lldb::addr_t lm=0, base=0, ld=0;
+ bool base_is_offset;
module.get_name (name);
module.get_link_map (lm);
module.get_base (base);
+ module.get_base_is_offset (base_is_offset);
module.get_dynamic (ld);
- log->Printf ("found (link_map:0x08%" PRIx64 ", base:0x08%" PRIx64 ", ld:0x08%" PRIx64 ", name:'%s')", lm, base, ld, name.c_str());
+ log->Printf ("found (link_map:0x%08" PRIx64 ", base:0x%08" PRIx64 "[%s], ld:0x%08" PRIx64 ", name:'%s')", lm, base, (base_is_offset ? "offset" : "absolute"), ld, name.c_str());
}
list.add (module);
@@ -4552,15 +4828,19 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
const XMLNode &section = library.FindFirstChildElementWithName("section");
llvm::StringRef address = section.GetAttributeValue("address");
module.set_base(StringConvert::ToUInt64(address.data(), LLDB_INVALID_ADDRESS, 0));
+ // These addresses are absolute values.
+ module.set_base_is_offset(false);
if (log)
{
std::string name;
lldb::addr_t base = 0;
+ bool base_is_offset;
module.get_name (name);
module.get_base (base);
+ module.get_base_is_offset (base_is_offset);
- log->Printf ("found (base:0x%" PRIx64 ", name:'%s')", base, name.c_str());
+ log->Printf ("found (base:0x%08" PRIx64 "[%s], name:'%s')", base, (base_is_offset ? "offset" : "absolute"), name.c_str());
}
list.add (module);
@@ -4577,7 +4857,7 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
}
lldb::ModuleSP
-ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr)
+ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr, bool value_is_offset)
{
Target &target = m_process->GetTarget();
ModuleList &modules = target.GetImages();
@@ -4588,11 +4868,11 @@ ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_a
ModuleSpec module_spec (file, target.GetArchitecture());
if ((module_sp = modules.FindFirstModule (module_spec)))
{
- module_sp->SetLoadAddress (target, base_addr, true, changed);
+ module_sp->SetLoadAddress (target, base_addr, value_is_offset, changed);
}
else if ((module_sp = target.GetSharedModule (module_spec)))
{
- module_sp->SetLoadAddress (target, base_addr, true, changed);
+ module_sp->SetLoadAddress (target, base_addr, value_is_offset, changed);
}
return module_sp;
@@ -4615,10 +4895,12 @@ ProcessGDBRemote::LoadModules ()
{
std::string mod_name;
lldb::addr_t mod_base;
+ bool mod_base_is_offset;
bool valid = true;
valid &= modInfo.get_name (mod_name);
valid &= modInfo.get_base (mod_base);
+ valid &= modInfo.get_base_is_offset (mod_base_is_offset);
if (!valid)
continue;
@@ -4630,7 +4912,7 @@ ProcessGDBRemote::LoadModules ()
marker += 1;
FileSpec file (mod_name.c_str()+marker, true);
- lldb::ModuleSP module_sp = LoadModuleAtAddress (file, mod_base);
+ lldb::ModuleSP module_sp = LoadModuleAtAddress (file, mod_base, mod_base_is_offset);
if (module_sp.get())
new_modules.Append (module_sp);
@@ -4638,7 +4920,7 @@ ProcessGDBRemote::LoadModules ()
if (new_modules.GetSize() > 0)
{
- Target & target = m_target;
+ Target &target = GetTarget();
new_modules.ForEach ([&target](const lldb::ModuleSP module_sp) -> bool
{
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 45c74ea64ee5..54749827d6ac 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -11,12 +11,14 @@
#define liblldb_ProcessGDBRemote_h_
// C Includes
-
// C++ Includes
-#include <list>
+#include <atomic>
+#include <map>
+#include <string>
#include <vector>
// Other libraries and framework includes
+// Project includes
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/ConstString.h"
@@ -42,11 +44,12 @@ class ThreadGDBRemote;
class ProcessGDBRemote : public Process
{
public:
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
+ ProcessGDBRemote(lldb::TargetSP target_sp, Listener &listener);
+
+ ~ProcessGDBRemote() override;
+
static lldb::ProcessSP
- CreateInstance (Target& target,
+ CreateInstance (lldb::TargetSP target_sp,
Listener &listener,
const FileSpec *crash_file_path);
@@ -66,18 +69,10 @@ public:
GetPluginDescriptionStatic();
//------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
- ProcessGDBRemote(Target& target, Listener &listener);
-
- virtual
- ~ProcessGDBRemote();
-
- //------------------------------------------------------------------
// Check if a given Process
//------------------------------------------------------------------
bool
- CanDebug (Target &target, bool plugin_specified_by_name) override;
+ CanDebug (lldb::TargetSP target_sp, bool plugin_specified_by_name) override;
CommandObject *
GetPluginCommandObject() override;
@@ -152,6 +147,9 @@ public:
void
RefreshStateAfterStop() override;
+ void
+ SetUnixSignals(const lldb::UnixSignalsSP &signals_sp);
+
//------------------------------------------------------------------
// Process Queries
//------------------------------------------------------------------
@@ -161,6 +159,9 @@ public:
lldb::addr_t
GetImageInfoAddress() override;
+ void
+ WillPublicStop () override;
+
//------------------------------------------------------------------
// Process Memory
//------------------------------------------------------------------
@@ -238,6 +239,11 @@ public:
const ArchSpec& arch,
ModuleSpec &module_spec) override;
+ bool
+ GetHostOSVersion(uint32_t &major,
+ uint32_t &minor,
+ uint32_t &update) override;
+
size_t
LoadModules() override;
@@ -257,20 +263,63 @@ protected:
class GDBLoadedModuleInfoList;
+ //------------------------------------------------------------------
+ /// Broadcaster event bits definitions.
+ //------------------------------------------------------------------
+ enum
+ {
+ eBroadcastBitAsyncContinue = (1 << 0),
+ eBroadcastBitAsyncThreadShouldExit = (1 << 1),
+ eBroadcastBitAsyncThreadDidExit = (1 << 2)
+ };
+
+ Flags m_flags; // Process specific flags (see eFlags enums)
+ GDBRemoteCommunicationClient m_gdb_comm;
+ std::atomic<lldb::pid_t> m_debugserver_pid;
+ std::vector<StringExtractorGDBRemote> m_stop_packet_stack; // The stop packet stack replaces the last stop packet variable
+ Mutex m_last_stop_packet_mutex;
+ GDBRemoteDynamicRegisterInfo m_register_info;
+ Broadcaster m_async_broadcaster;
+ Listener m_async_listener;
+ HostThread m_async_thread;
+ Mutex m_async_thread_state_mutex;
+ typedef std::vector<lldb::tid_t> tid_collection;
+ typedef std::vector< std::pair<lldb::tid_t,int> > tid_sig_collection;
+ typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
+ typedef std::map<uint32_t, std::string> ExpeditedRegisterMap;
+ tid_collection m_thread_ids; // Thread IDs for all threads. This list gets updated after stopping
+ std::vector<lldb::addr_t> m_thread_pcs; // PC values for all the threads.
+ StructuredData::ObjectSP m_jstopinfo_sp; // Stop info only for any threads that have valid stop infos
+ StructuredData::ObjectSP m_jthreadsinfo_sp; // Full stop info, expedited registers and memory for all threads if "jThreadsInfo" packet is supported
+ tid_collection m_continue_c_tids; // 'c' for continue
+ tid_sig_collection m_continue_C_tids; // 'C' for continue with signal
+ tid_collection m_continue_s_tids; // 's' for step
+ tid_sig_collection m_continue_S_tids; // 'S' for step with signal
+ uint64_t m_max_memory_size; // The maximum number of bytes to read/write when reading and writing memory
+ uint64_t m_remote_stub_max_memory_size; // The maximum memory size the remote gdb stub can handle
+ MMapMap m_addr_to_mmap_size;
+ lldb::BreakpointSP m_thread_create_bp_sp;
+ bool m_waiting_for_attach;
+ bool m_destroy_tried_resuming;
+ 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
+
//----------------------------------------------------------------------
// Accessors
//----------------------------------------------------------------------
bool
IsRunning ( lldb::StateType state )
{
- return state == lldb::eStateRunning || IsStepping(state);
+ return state == lldb::eStateRunning || IsStepping(state);
}
bool
IsStepping ( lldb::StateType state)
{
- return state == lldb::eStateStepping;
+ return state == lldb::eStateStepping;
}
+
bool
CanResume ( lldb::StateType state)
{
@@ -306,6 +355,9 @@ protected:
ThreadList &new_thread_list) override;
Error
+ EstablishConnectionIfNeeded (const ProcessInfo &process_info);
+
+ Error
LaunchAndConnectToDebugserver (const ProcessInfo &process_info);
void
@@ -333,46 +385,10 @@ protected:
CalculateThreadStopInfo (ThreadGDBRemote *thread);
size_t
- UpdateThreadIDsFromStopReplyThreadsValue (std::string &value);
+ UpdateThreadPCsFromStopReplyThreadsValue (std::string &value);
- //------------------------------------------------------------------
- /// Broadcaster event bits definitions.
- //------------------------------------------------------------------
- enum
- {
- eBroadcastBitAsyncContinue = (1 << 0),
- eBroadcastBitAsyncThreadShouldExit = (1 << 1),
- eBroadcastBitAsyncThreadDidExit = (1 << 2)
- };
-
- Flags m_flags; // Process specific flags (see eFlags enums)
- GDBRemoteCommunicationClient m_gdb_comm;
- std::atomic<lldb::pid_t> m_debugserver_pid;
- std::vector<StringExtractorGDBRemote> m_stop_packet_stack; // The stop packet stack replaces the last stop packet variable
- Mutex m_last_stop_packet_mutex;
- GDBRemoteDynamicRegisterInfo m_register_info;
- Broadcaster m_async_broadcaster;
- HostThread m_async_thread;
- Mutex m_async_thread_state_mutex;
- typedef std::vector<lldb::tid_t> tid_collection;
- typedef std::vector< std::pair<lldb::tid_t,int> > tid_sig_collection;
- typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
- typedef std::map<uint32_t, std::string> ExpeditedRegisterMap;
- tid_collection m_thread_ids; // Thread IDs for all threads. This list gets updated after stopping
- StructuredData::ObjectSP m_threads_info_sp; // Stop info for all threads if "jThreadsInfo" packet is supported
- tid_collection m_continue_c_tids; // 'c' for continue
- tid_sig_collection m_continue_C_tids; // 'C' for continue with signal
- tid_collection m_continue_s_tids; // 's' for step
- tid_sig_collection m_continue_S_tids; // 'S' for step with signal
- uint64_t m_max_memory_size; // The maximum number of bytes to read/write when reading and writing memory
- uint64_t m_remote_stub_max_memory_size; // The maximum memory size the remote gdb stub can handle
- MMapMap m_addr_to_mmap_size;
- lldb::BreakpointSP m_thread_create_bp_sp;
- bool m_waiting_for_attach;
- bool m_destroy_tried_resuming;
- lldb::CommandObjectSP m_command_sp;
- int64_t m_breakpoint_pc_offset;
- lldb::tid_t m_initial_tid; // The inital thread ID, given by stub on attach
+ size_t
+ UpdateThreadIDsFromStopReplyThreadsValue (std::string &value);
bool
HandleNotifyPacket(StringExtractorGDBRemote &packet);
@@ -396,7 +412,10 @@ protected:
lldb::StateType
SetThreadStopInfo (StringExtractor& stop_packet);
- lldb::StateType
+ bool
+ GetThreadStopInfoFromJSON (ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp);
+
+ lldb::ThreadSP
SetThreadStopInfo (StructuredData::Dictionary *thread_dict);
lldb::ThreadSP
@@ -445,7 +464,7 @@ protected:
GetLoadedModuleList (GDBLoadedModuleInfoList &);
lldb::ModuleSP
- LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr);
+ LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr, bool value_is_offset);
private:
//------------------------------------------------------------------
@@ -458,10 +477,9 @@ private:
lldb::user_id_t break_loc_id);
DISALLOW_COPY_AND_ASSIGN (ProcessGDBRemote);
-
};
} // namespace process_gdb_remote
} // namespace lldb_private
-#endif // liblldb_ProcessGDBRemote_h_
+#endif // liblldb_ProcessGDBRemote_h_
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index d2a6503caf8e..9b410d8b5b8c 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -313,6 +313,14 @@ ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, StringExtractor &respons
}
bool
+ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, uint64_t regval)
+{
+ GDBRemoteRegisterContext *gdb_reg_ctx = static_cast<GDBRemoteRegisterContext *>(GetRegisterContext ().get());
+ assert (gdb_reg_ctx);
+ return gdb_reg_ctx->PrivateSetRegisterValue (reg, regval);
+}
+
+bool
ThreadGDBRemote::CalculateStopInfo ()
{
ProcessSP process_sp (GetProcess());
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
index 175433a3e20c..24693ba891cc 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
@@ -10,8 +10,12 @@
#ifndef liblldb_ThreadGDBRemote_h_
#define liblldb_ThreadGDBRemote_h_
+// C Includes
+// C++ Includes
#include <string>
+// Other libraries and framework includes
+// Project includes
#include "lldb/Core/StructuredData.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
@@ -28,8 +32,7 @@ class ThreadGDBRemote : public Thread
public:
ThreadGDBRemote (Process &process, lldb::tid_t tid);
- virtual
- ~ThreadGDBRemote ();
+ ~ThreadGDBRemote() override;
void
WillResume (lldb::StateType resume_state) override;
@@ -101,30 +104,27 @@ public:
FetchThreadExtendedInfo () override;
protected:
-
friend class ProcessGDBRemote;
+ std::string m_thread_name;
+ std::string m_dispatch_queue_name;
+ lldb::addr_t m_thread_dispatch_qaddr;
+ lldb::QueueKind m_queue_kind; // Queue info from stop reply/stop info for thread
+ uint64_t m_queue_serial; // Queue info from stop reply/stop info for thread
+
bool
PrivateSetRegisterValue (uint32_t reg,
StringExtractor &response);
bool
+ PrivateSetRegisterValue (uint32_t reg,
+ uint64_t regval);
+
+ bool
CachedQueueInfoIsValid() const
{
return m_queue_kind != lldb::eQueueKindUnknown;
}
- //------------------------------------------------------------------
- // Member variables.
- //------------------------------------------------------------------
- std::string m_thread_name;
- std::string m_dispatch_queue_name;
- lldb::addr_t m_thread_dispatch_qaddr;
- lldb::QueueKind m_queue_kind; // Queue info from stop reply/stop info for thread
- uint64_t m_queue_serial; // Queue info from stop reply/stop info for thread
- //------------------------------------------------------------------
- // Member variables.
- //------------------------------------------------------------------
-
void
SetStopInfoFromPacket (StringExtractor &stop_packet, uint32_t stop_id);
@@ -135,4 +135,4 @@ protected:
} // namespace process_gdb_remote
} // namespace lldb_private
-#endif // liblldb_ThreadGDBRemote_h_
+#endif // liblldb_ThreadGDBRemote_h_
diff --git a/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp b/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
new file mode 100644
index 000000000000..1a352fa1987f
--- /dev/null
+++ b/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
@@ -0,0 +1,93 @@
+//===-- ScriptInterpreterNone.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ScriptInterpreterNone.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StringList.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+
+#include <mutex>
+
+using namespace lldb;
+using namespace lldb_private;
+
+ScriptInterpreterNone::ScriptInterpreterNone(CommandInterpreter &interpreter)
+ : ScriptInterpreter(interpreter, eScriptLanguageNone)
+{
+}
+
+ScriptInterpreterNone::~ScriptInterpreterNone()
+{
+}
+
+bool
+ScriptInterpreterNone::ExecuteOneLine(const char *command, CommandReturnObject *, const ExecuteScriptOptions &)
+{
+ m_interpreter.GetDebugger().GetErrorFile()->PutCString(
+ "error: there is no embedded script interpreter in this mode.\n");
+ return false;
+}
+
+void
+ScriptInterpreterNone::ExecuteInterpreterLoop()
+{
+ m_interpreter.GetDebugger().GetErrorFile()->PutCString(
+ "error: there is no embedded script interpreter in this mode.\n");
+}
+
+void
+ScriptInterpreterNone::Initialize()
+{
+ static std::once_flag g_once_flag;
+
+ std::call_once(g_once_flag, []()
+ {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(),
+ lldb::eScriptLanguageNone, CreateInstance);
+ });
+}
+
+void
+ScriptInterpreterNone::Terminate()
+{
+}
+
+lldb::ScriptInterpreterSP
+ScriptInterpreterNone::CreateInstance(CommandInterpreter &interpreter)
+{
+ return std::make_shared<ScriptInterpreterNone>(interpreter);
+}
+
+lldb_private::ConstString
+ScriptInterpreterNone::GetPluginNameStatic()
+{
+ static ConstString g_name("script-none");
+ return g_name;
+}
+
+const char *
+ScriptInterpreterNone::GetPluginDescriptionStatic()
+{
+ return "Null script interpreter";
+}
+
+lldb_private::ConstString
+ScriptInterpreterNone::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ScriptInterpreterNone::GetPluginVersion()
+{
+ return 1;
+}
diff --git a/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h b/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h
new file mode 100644
index 000000000000..49fd4fabfbc5
--- /dev/null
+++ b/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h
@@ -0,0 +1,66 @@
+//===-- ScriptInterpreterNone.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ScriptInterpreterNone_h_
+#define liblldb_ScriptInterpreterNone_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/ScriptInterpreter.h"
+
+namespace lldb_private
+{
+
+class ScriptInterpreterNone : public ScriptInterpreter
+{
+ public:
+ ScriptInterpreterNone(CommandInterpreter &interpreter);
+
+ ~ScriptInterpreterNone() override;
+
+ bool
+ ExecuteOneLine(const char *command, CommandReturnObject *result,
+ const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
+
+ void
+ ExecuteInterpreterLoop() override;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb::ScriptInterpreterSP
+ CreateInstance(CommandInterpreter &interpreter);
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ static const char *
+ GetPluginDescriptionStatic();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ScriptInterpreterNone_h_
diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
new file mode 100644
index 000000000000..3107677ee948
--- /dev/null
+++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
@@ -0,0 +1,1069 @@
+//===-- PythonDataObjects.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifdef LLDB_DISABLE_PYTHON
+
+// Python is disabled in this build
+
+#else
+
+#include "lldb-python.h"
+#include "PythonDataObjects.h"
+#include "ScriptInterpreterPython.h"
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Host/File.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+
+#include <stdio.h>
+
+using namespace lldb_private;
+using namespace lldb;
+
+void
+StructuredPythonObject::Dump(Stream &s) const
+{
+ s << "Python Obj: 0x" << GetValue();
+}
+
+//----------------------------------------------------------------------
+// PythonObject
+//----------------------------------------------------------------------
+
+void
+PythonObject::Dump(Stream &strm) const
+{
+ if (m_py_obj)
+ {
+ FILE *file = ::tmpfile();
+ if (file)
+ {
+ ::PyObject_Print (m_py_obj, file, 0);
+ const long length = ftell (file);
+ if (length)
+ {
+ ::rewind(file);
+ std::vector<char> file_contents (length,'\0');
+ const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file);
+ if (length_read > 0)
+ strm.Write (file_contents.data(), length_read);
+ }
+ ::fclose (file);
+ }
+ }
+ else
+ strm.PutCString ("NULL");
+}
+
+PyObjectType
+PythonObject::GetObjectType() const
+{
+ if (!IsAllocated())
+ return PyObjectType::None;
+
+ if (PythonModule::Check(m_py_obj))
+ return PyObjectType::Module;
+ if (PythonList::Check(m_py_obj))
+ return PyObjectType::List;
+ if (PythonTuple::Check(m_py_obj))
+ return PyObjectType::Tuple;
+ if (PythonDictionary::Check(m_py_obj))
+ return PyObjectType::Dictionary;
+ if (PythonString::Check(m_py_obj))
+ return PyObjectType::String;
+ if (PythonInteger::Check(m_py_obj))
+ return PyObjectType::Integer;
+ if (PythonFile::Check(m_py_obj))
+ return PyObjectType::File;
+ if (PythonCallable::Check(m_py_obj))
+ return PyObjectType::Callable;
+ return PyObjectType::Unknown;
+}
+
+PythonString
+PythonObject::Repr() const
+{
+ if (!m_py_obj)
+ return PythonString();
+ PyObject *repr = PyObject_Repr(m_py_obj);
+ if (!repr)
+ return PythonString();
+ return PythonString(PyRefType::Owned, repr);
+}
+
+PythonString
+PythonObject::Str() const
+{
+ if (!m_py_obj)
+ return PythonString();
+ PyObject *str = PyObject_Str(m_py_obj);
+ if (!str)
+ return PythonString();
+ return PythonString(PyRefType::Owned, str);
+}
+
+PythonObject
+PythonObject::ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict)
+{
+ size_t dot_pos = name.find_first_of('.');
+ llvm::StringRef piece = name.substr(0, dot_pos);
+ PythonObject result = dict.GetItemForKey(PythonString(piece));
+ if (dot_pos == llvm::StringRef::npos)
+ {
+ // There was no dot, we're done.
+ return result;
+ }
+
+ // There was a dot. The remaining portion of the name should be looked up in
+ // the context of the object that was found in the dictionary.
+ return result.ResolveName(name.substr(dot_pos + 1));
+}
+
+PythonObject
+PythonObject::ResolveName(llvm::StringRef name) const
+{
+ // Resolve the name in the context of the specified object. If,
+ // for example, `this` refers to a PyModule, then this will look for
+ // `name` in this module. If `this` refers to a PyType, then it will
+ // resolve `name` as an attribute of that type. If `this` refers to
+ // an instance of an object, then it will resolve `name` as the value
+ // of the specified field.
+ //
+ // This function handles dotted names so that, for example, if `m_py_obj`
+ // refers to the `sys` module, and `name` == "path.append", then it
+ // will find the function `sys.path.append`.
+
+ size_t dot_pos = name.find_first_of('.');
+ if (dot_pos == llvm::StringRef::npos)
+ {
+ // No dots in the name, we should be able to find the value immediately
+ // as an attribute of `m_py_obj`.
+ return GetAttributeValue(name);
+ }
+
+ // Look up the first piece of the name, and resolve the rest as a child of that.
+ PythonObject parent = ResolveName(name.substr(0, dot_pos));
+ if (!parent.IsAllocated())
+ return PythonObject();
+
+ // Tail recursion.. should be optimized by the compiler
+ return parent.ResolveName(name.substr(dot_pos + 1));
+}
+
+bool
+PythonObject::HasAttribute(llvm::StringRef attr) const
+{
+ if (!IsValid())
+ return false;
+ PythonString py_attr(attr);
+ return !!PyObject_HasAttr(m_py_obj, py_attr.get());
+}
+
+PythonObject
+PythonObject::GetAttributeValue(llvm::StringRef attr) const
+{
+ if (!IsValid())
+ return PythonObject();
+
+ PythonString py_attr(attr);
+ if (!PyObject_HasAttr(m_py_obj, py_attr.get()))
+ return PythonObject();
+
+ return PythonObject(PyRefType::Owned,
+ PyObject_GetAttr(m_py_obj, py_attr.get()));
+}
+
+bool
+PythonObject::IsNone() const
+{
+ return m_py_obj == Py_None;
+}
+
+bool
+PythonObject::IsValid() const
+{
+ return m_py_obj != nullptr;
+}
+
+bool
+PythonObject::IsAllocated() const
+{
+ return IsValid() && !IsNone();
+}
+
+StructuredData::ObjectSP
+PythonObject::CreateStructuredObject() const
+{
+ switch (GetObjectType())
+ {
+ case PyObjectType::Dictionary:
+ return PythonDictionary(PyRefType::Borrowed, m_py_obj).CreateStructuredDictionary();
+ case PyObjectType::Integer:
+ return PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger();
+ case PyObjectType::List:
+ return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
+ case PyObjectType::String:
+ return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
+ case PyObjectType::None:
+ return StructuredData::ObjectSP();
+ default:
+ return StructuredData::ObjectSP(new StructuredPythonObject(m_py_obj));
+ }
+}
+
+//----------------------------------------------------------------------
+// PythonString
+//----------------------------------------------------------------------
+
+PythonString::PythonString(PyRefType type, PyObject *py_obj)
+ : PythonObject()
+{
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
+}
+
+PythonString::PythonString(const PythonString &object)
+ : PythonObject(object)
+{
+}
+
+PythonString::PythonString(llvm::StringRef string)
+ : PythonObject()
+{
+ SetString(string);
+}
+
+PythonString::PythonString(const char *string)
+ : PythonObject()
+{
+ SetString(llvm::StringRef(string));
+}
+
+PythonString::PythonString()
+ : PythonObject()
+{
+}
+
+PythonString::~PythonString ()
+{
+}
+
+bool
+PythonString::Check(PyObject *py_obj)
+{
+ if (!py_obj)
+ return false;
+
+ if (PyUnicode_Check(py_obj))
+ return true;
+#if PY_MAJOR_VERSION < 3
+ if (PyString_Check(py_obj))
+ return true;
+#endif
+ return false;
+}
+
+void
+PythonString::Reset(PyRefType type, PyObject *py_obj)
+{
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonString::Check(py_obj))
+ {
+ PythonObject::Reset();
+ return;
+ }
+#if PY_MAJOR_VERSION < 3
+ // In Python 2, Don't store PyUnicode objects directly, because we need
+ // access to their underlying character buffers which Python 2 doesn't
+ // provide.
+ if (PyUnicode_Check(py_obj))
+ result.Reset(PyRefType::Owned, PyUnicode_AsUTF8String(result.get()));
+#endif
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+llvm::StringRef
+PythonString::GetString() const
+{
+ if (!IsValid())
+ return llvm::StringRef();
+
+ Py_ssize_t size;
+ char *c;
+
+#if PY_MAJOR_VERSION >= 3
+ c = PyUnicode_AsUTF8AndSize(m_py_obj, &size);
+#else
+ PyString_AsStringAndSize(m_py_obj, &c, &size);
+#endif
+ return llvm::StringRef(c, size);
+}
+
+size_t
+PythonString::GetSize() const
+{
+ if (IsValid())
+ {
+#if PY_MAJOR_VERSION >= 3
+ return PyUnicode_GetSize(m_py_obj);
+#else
+ return PyString_Size(m_py_obj);
+#endif
+ }
+ return 0;
+}
+
+void
+PythonString::SetString (llvm::StringRef string)
+{
+#if PY_MAJOR_VERSION >= 3
+ PyObject *unicode = PyUnicode_FromStringAndSize(string.data(), string.size());
+ PythonObject::Reset(PyRefType::Owned, unicode);
+#else
+ PyObject *str = PyString_FromStringAndSize(string.data(), string.size());
+ PythonObject::Reset(PyRefType::Owned, str);
+#endif
+}
+
+StructuredData::StringSP
+PythonString::CreateStructuredString() const
+{
+ StructuredData::StringSP result(new StructuredData::String);
+ result->SetValue(GetString());
+ return result;
+}
+
+//----------------------------------------------------------------------
+// PythonInteger
+//----------------------------------------------------------------------
+
+PythonInteger::PythonInteger()
+ : PythonObject()
+{
+
+}
+
+PythonInteger::PythonInteger(PyRefType type, PyObject *py_obj)
+ : PythonObject()
+{
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a integer type
+}
+
+PythonInteger::PythonInteger(const PythonInteger &object)
+ : PythonObject(object)
+{
+}
+
+PythonInteger::PythonInteger(int64_t value)
+ : PythonObject()
+{
+ SetInteger(value);
+}
+
+
+PythonInteger::~PythonInteger ()
+{
+}
+
+bool
+PythonInteger::Check(PyObject *py_obj)
+{
+ if (!py_obj)
+ return false;
+
+#if PY_MAJOR_VERSION >= 3
+ // Python 3 does not have PyInt_Check. There is only one type of
+ // integral value, long.
+ return PyLong_Check(py_obj);
+#else
+ return PyLong_Check(py_obj) || PyInt_Check(py_obj);
+#endif
+}
+
+void
+PythonInteger::Reset(PyRefType type, PyObject *py_obj)
+{
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonInteger::Check(py_obj))
+ {
+ PythonObject::Reset();
+ return;
+ }
+
+#if PY_MAJOR_VERSION < 3
+ // Always store this as a PyLong, which makes interoperability between
+ // Python 2.x and Python 3.x easier. This is only necessary in 2.x,
+ // since 3.x doesn't even have a PyInt.
+ if (PyInt_Check(py_obj))
+ {
+ // Since we converted the original object to a different type, the new
+ // object is an owned object regardless of the ownership semantics requested
+ // by the user.
+ result.Reset(PyRefType::Owned, PyLong_FromLongLong(PyInt_AsLong(py_obj)));
+ }
+#endif
+
+ assert(PyLong_Check(result.get()) && "Couldn't get a PyLong from this PyObject");
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+int64_t
+PythonInteger::GetInteger() const
+{
+ if (m_py_obj)
+ {
+ assert(PyLong_Check(m_py_obj) && "PythonInteger::GetInteger has a PyObject that isn't a PyLong");
+
+ return PyLong_AsLongLong(m_py_obj);
+ }
+ return UINT64_MAX;
+}
+
+void
+PythonInteger::SetInteger(int64_t value)
+{
+ PythonObject::Reset(PyRefType::Owned, PyLong_FromLongLong(value));
+}
+
+StructuredData::IntegerSP
+PythonInteger::CreateStructuredInteger() const
+{
+ StructuredData::IntegerSP result(new StructuredData::Integer);
+ result->SetValue(GetInteger());
+ return result;
+}
+
+//----------------------------------------------------------------------
+// PythonList
+//----------------------------------------------------------------------
+
+PythonList::PythonList(PyInitialValue value)
+ : PythonObject()
+{
+ if (value == PyInitialValue::Empty)
+ Reset(PyRefType::Owned, PyList_New(0));
+}
+
+PythonList::PythonList(int list_size)
+ : PythonObject()
+{
+ Reset(PyRefType::Owned, PyList_New(list_size));
+}
+
+PythonList::PythonList(PyRefType type, PyObject *py_obj)
+ : PythonObject()
+{
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a list
+}
+
+PythonList::PythonList(const PythonList &list)
+ : PythonObject(list)
+{
+}
+
+PythonList::~PythonList ()
+{
+}
+
+bool
+PythonList::Check(PyObject *py_obj)
+{
+ if (!py_obj)
+ return false;
+ return PyList_Check(py_obj);
+}
+
+void
+PythonList::Reset(PyRefType type, PyObject *py_obj)
+{
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonList::Check(py_obj))
+ {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+uint32_t
+PythonList::GetSize() const
+{
+ if (IsValid())
+ return PyList_GET_SIZE(m_py_obj);
+ return 0;
+}
+
+PythonObject
+PythonList::GetItemAtIndex(uint32_t index) const
+{
+ if (IsValid())
+ return PythonObject(PyRefType::Borrowed, PyList_GetItem(m_py_obj, index));
+ return PythonObject();
+}
+
+void
+PythonList::SetItemAtIndex(uint32_t index, const PythonObject &object)
+{
+ if (IsAllocated() && object.IsValid())
+ {
+ // PyList_SetItem is documented to "steal" a reference, so we need to
+ // convert it to an owned reference by incrementing it.
+ Py_INCREF(object.get());
+ PyList_SetItem(m_py_obj, index, object.get());
+ }
+}
+
+void
+PythonList::AppendItem(const PythonObject &object)
+{
+ if (IsAllocated() && object.IsValid())
+ {
+ // `PyList_Append` does *not* steal a reference, so do not call `Py_INCREF`
+ // here like we do with `PyList_SetItem`.
+ PyList_Append(m_py_obj, object.get());
+ }
+}
+
+StructuredData::ArraySP
+PythonList::CreateStructuredArray() const
+{
+ StructuredData::ArraySP result(new StructuredData::Array);
+ uint32_t count = GetSize();
+ for (uint32_t i = 0; i < count; ++i)
+ {
+ PythonObject obj = GetItemAtIndex(i);
+ result->AddItem(obj.CreateStructuredObject());
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------
+// PythonTuple
+//----------------------------------------------------------------------
+
+PythonTuple::PythonTuple(PyInitialValue value)
+ : PythonObject()
+{
+ if (value == PyInitialValue::Empty)
+ Reset(PyRefType::Owned, PyTuple_New(0));
+}
+
+PythonTuple::PythonTuple(int tuple_size)
+ : PythonObject()
+{
+ Reset(PyRefType::Owned, PyTuple_New(tuple_size));
+}
+
+PythonTuple::PythonTuple(PyRefType type, PyObject *py_obj)
+ : PythonObject()
+{
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a tuple
+}
+
+PythonTuple::PythonTuple(const PythonTuple &tuple)
+ : PythonObject(tuple)
+{
+}
+
+PythonTuple::PythonTuple(std::initializer_list<PythonObject> objects)
+{
+ m_py_obj = PyTuple_New(objects.size());
+
+ uint32_t idx = 0;
+ for (auto object : objects)
+ {
+ if (object.IsValid())
+ SetItemAtIndex(idx, object);
+ idx++;
+ }
+}
+
+PythonTuple::PythonTuple(std::initializer_list<PyObject*> objects)
+{
+ m_py_obj = PyTuple_New(objects.size());
+
+ uint32_t idx = 0;
+ for (auto py_object : objects)
+ {
+ PythonObject object(PyRefType::Borrowed, py_object);
+ if (object.IsValid())
+ SetItemAtIndex(idx, object);
+ idx++;
+ }
+}
+
+PythonTuple::~PythonTuple()
+{
+}
+
+bool
+PythonTuple::Check(PyObject *py_obj)
+{
+ if (!py_obj)
+ return false;
+ return PyTuple_Check(py_obj);
+}
+
+void
+PythonTuple::Reset(PyRefType type, PyObject *py_obj)
+{
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonTuple::Check(py_obj))
+ {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+uint32_t
+PythonTuple::GetSize() const
+{
+ if (IsValid())
+ return PyTuple_GET_SIZE(m_py_obj);
+ return 0;
+}
+
+PythonObject
+PythonTuple::GetItemAtIndex(uint32_t index) const
+{
+ if (IsValid())
+ return PythonObject(PyRefType::Borrowed, PyTuple_GetItem(m_py_obj, index));
+ return PythonObject();
+}
+
+void
+PythonTuple::SetItemAtIndex(uint32_t index, const PythonObject &object)
+{
+ if (IsAllocated() && object.IsValid())
+ {
+ // PyTuple_SetItem is documented to "steal" a reference, so we need to
+ // convert it to an owned reference by incrementing it.
+ Py_INCREF(object.get());
+ PyTuple_SetItem(m_py_obj, index, object.get());
+ }
+}
+
+StructuredData::ArraySP
+PythonTuple::CreateStructuredArray() const
+{
+ StructuredData::ArraySP result(new StructuredData::Array);
+ uint32_t count = GetSize();
+ for (uint32_t i = 0; i < count; ++i)
+ {
+ PythonObject obj = GetItemAtIndex(i);
+ result->AddItem(obj.CreateStructuredObject());
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------
+// PythonDictionary
+//----------------------------------------------------------------------
+
+PythonDictionary::PythonDictionary(PyInitialValue value)
+ : PythonObject()
+{
+ if (value == PyInitialValue::Empty)
+ Reset(PyRefType::Owned, PyDict_New());
+}
+
+PythonDictionary::PythonDictionary(PyRefType type, PyObject *py_obj)
+ : PythonObject()
+{
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a dictionary
+}
+
+PythonDictionary::PythonDictionary(const PythonDictionary &object)
+ : PythonObject(object)
+{
+}
+
+PythonDictionary::~PythonDictionary ()
+{
+}
+
+bool
+PythonDictionary::Check(PyObject *py_obj)
+{
+ if (!py_obj)
+ return false;
+
+ return PyDict_Check(py_obj);
+}
+
+void
+PythonDictionary::Reset(PyRefType type, PyObject *py_obj)
+{
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonDictionary::Check(py_obj))
+ {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+uint32_t
+PythonDictionary::GetSize() const
+{
+ if (IsValid())
+ return PyDict_Size(m_py_obj);
+ return 0;
+}
+
+PythonList
+PythonDictionary::GetKeys() const
+{
+ if (IsValid())
+ return PythonList(PyRefType::Owned, PyDict_Keys(m_py_obj));
+ return PythonList(PyInitialValue::Invalid);
+}
+
+PythonObject
+PythonDictionary::GetItemForKey(const PythonObject &key) const
+{
+ if (IsAllocated() && key.IsValid())
+ return PythonObject(PyRefType::Borrowed, PyDict_GetItem(m_py_obj, key.get()));
+ return PythonObject();
+}
+
+void
+PythonDictionary::SetItemForKey(const PythonObject &key, const PythonObject &value)
+{
+ if (IsAllocated() && key.IsValid() && value.IsValid())
+ PyDict_SetItem(m_py_obj, key.get(), value.get());
+}
+
+StructuredData::DictionarySP
+PythonDictionary::CreateStructuredDictionary() const
+{
+ StructuredData::DictionarySP result(new StructuredData::Dictionary);
+ PythonList keys(GetKeys());
+ uint32_t num_keys = keys.GetSize();
+ for (uint32_t i = 0; i < num_keys; ++i)
+ {
+ PythonObject key = keys.GetItemAtIndex(i);
+ PythonObject value = GetItemForKey(key);
+ StructuredData::ObjectSP structured_value = value.CreateStructuredObject();
+ result->AddItem(key.Str().GetString(), structured_value);
+ }
+ return result;
+}
+
+PythonModule::PythonModule() : PythonObject()
+{
+}
+
+PythonModule::PythonModule(PyRefType type, PyObject *py_obj)
+{
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a module
+}
+
+PythonModule::PythonModule(const PythonModule &dict) : PythonObject(dict)
+{
+}
+
+PythonModule::~PythonModule()
+{
+}
+
+PythonModule
+PythonModule::BuiltinsModule()
+{
+#if PY_MAJOR_VERSION >= 3
+ return AddModule("builtins");
+#else
+ return AddModule("__builtin__");
+#endif
+}
+
+PythonModule
+PythonModule::MainModule()
+{
+ return AddModule("__main__");
+}
+
+PythonModule
+PythonModule::AddModule(llvm::StringRef module)
+{
+ std::string str = module.str();
+ return PythonModule(PyRefType::Borrowed, PyImport_AddModule(str.c_str()));
+}
+
+
+PythonModule
+PythonModule::ImportModule(llvm::StringRef module)
+{
+ std::string str = module.str();
+ return PythonModule(PyRefType::Owned, PyImport_ImportModule(str.c_str()));
+}
+
+bool
+PythonModule::Check(PyObject *py_obj)
+{
+ if (!py_obj)
+ return false;
+
+ return PyModule_Check(py_obj);
+}
+
+void
+PythonModule::Reset(PyRefType type, PyObject *py_obj)
+{
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonModule::Check(py_obj))
+ {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+PythonDictionary
+PythonModule::GetDictionary() const
+{
+ return PythonDictionary(PyRefType::Borrowed, PyModule_GetDict(m_py_obj));
+}
+
+PythonCallable::PythonCallable() : PythonObject()
+{
+}
+
+PythonCallable::PythonCallable(PyRefType type, PyObject *py_obj)
+{
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a callable
+}
+
+PythonCallable::PythonCallable(const PythonCallable &callable)
+ : PythonObject(callable)
+{
+}
+
+PythonCallable::~PythonCallable()
+{
+}
+
+bool
+PythonCallable::Check(PyObject *py_obj)
+{
+ if (!py_obj)
+ return false;
+
+ return PyCallable_Check(py_obj);
+}
+
+void
+PythonCallable::Reset(PyRefType type, PyObject *py_obj)
+{
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonCallable::Check(py_obj))
+ {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+
+PythonCallable::ArgInfo
+PythonCallable::GetNumArguments() const
+{
+ ArgInfo result = { 0, false, false };
+ if (!IsValid())
+ return result;
+
+ PyObject *py_func_obj = m_py_obj;
+ if (PyMethod_Check(py_func_obj))
+ py_func_obj = PyMethod_GET_FUNCTION(py_func_obj);
+
+ if (!py_func_obj)
+ return result;
+
+ PyCodeObject* code = (PyCodeObject*)PyFunction_GET_CODE(py_func_obj);
+ if (!code)
+ return result;
+
+ result.count = code->co_argcount;
+ result.has_varargs = !!(code->co_flags & CO_VARARGS);
+ result.has_kwargs = !!(code->co_flags & CO_VARKEYWORDS);
+ return result;
+}
+
+PythonObject
+PythonCallable::operator ()()
+{
+ return PythonObject(PyRefType::Owned,
+ PyObject_CallObject(m_py_obj, nullptr));
+}
+
+PythonObject
+PythonCallable::operator ()(std::initializer_list<PyObject*> args)
+{
+ PythonTuple arg_tuple(args);
+ return PythonObject(PyRefType::Owned,
+ PyObject_CallObject(m_py_obj, arg_tuple.get()));
+}
+
+PythonObject
+PythonCallable::operator ()(std::initializer_list<PythonObject> args)
+{
+ PythonTuple arg_tuple(args);
+ return PythonObject(PyRefType::Owned,
+ PyObject_CallObject(m_py_obj, arg_tuple.get()));
+}
+
+PythonFile::PythonFile()
+ : PythonObject()
+{
+}
+
+PythonFile::PythonFile(File &file, const char *mode)
+{
+ Reset(file, mode);
+}
+
+PythonFile::PythonFile(const char *path, const char *mode)
+{
+ FILE *fp = nullptr;
+ fp = fopen(path, mode);
+ lldb_private::File file(fp, true);
+ Reset(file, mode);
+}
+
+PythonFile::PythonFile(PyRefType type, PyObject *o)
+{
+ Reset(type, o);
+}
+
+PythonFile::~PythonFile()
+{
+}
+
+bool
+PythonFile::Check(PyObject *py_obj)
+{
+#if PY_MAJOR_VERSION < 3
+ return PyFile_Check(py_obj);
+#else
+ // In Python 3, there is no `PyFile_Check`, and in fact PyFile is not even a
+ // first-class object type anymore. `PyFile_FromFd` is just a thin wrapper
+ // over `io.open()`, which returns some object derived from `io.IOBase`.
+ // As a result, the only way to detect a file in Python 3 is to check whether
+ // it inherits from `io.IOBase`. Since it is possible for non-files to also
+ // inherit from `io.IOBase`, we additionally verify that it has the `fileno`
+ // attribute, which should guarantee that it is backed by the file system.
+ PythonObject io_module(PyRefType::Owned, PyImport_ImportModule("io"));
+ PythonDictionary io_dict(PyRefType::Borrowed, PyModule_GetDict(io_module.get()));
+ PythonObject io_base_class = io_dict.GetItemForKey(PythonString("IOBase"));
+
+ PythonObject object_type(PyRefType::Owned, PyObject_Type(py_obj));
+
+ if (1 != PyObject_IsSubclass(object_type.get(), io_base_class.get()))
+ return false;
+ if (!object_type.HasAttribute("fileno"))
+ return false;
+
+ return true;
+#endif
+}
+
+void
+PythonFile::Reset(PyRefType type, PyObject *py_obj)
+{
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonFile::Check(py_obj))
+ {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack
+ // overflow since it calls back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+void
+PythonFile::Reset(File &file, const char *mode)
+{
+ if (!file.IsValid())
+ {
+ Reset();
+ return;
+ }
+
+ char *cmode = const_cast<char *>(mode);
+#if PY_MAJOR_VERSION >= 3
+ Reset(PyRefType::Owned,
+ PyFile_FromFd(file.GetDescriptor(), nullptr, cmode, -1, nullptr, "ignore", nullptr, 0));
+#else
+ // Read through the Python source, doesn't seem to modify these strings
+ Reset(PyRefType::Owned,
+ PyFile_FromFile(file.GetStream(), const_cast<char *>(""), cmode, nullptr));
+#endif
+}
+
+bool
+PythonFile::GetUnderlyingFile(File &file) const
+{
+ if (!IsValid())
+ return false;
+
+ file.Close();
+ // We don't own the file descriptor returned by this function, make sure the
+ // File object knows about that.
+ file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), false);
+ return file.IsValid();
+}
+
+
+#endif
diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
new file mode 100644
index 000000000000..c9d17c0f0fad
--- /dev/null
+++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
@@ -0,0 +1,498 @@
+//===-- PythonDataObjects.h--------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
+
+#ifndef LLDB_DISABLE_PYTHON
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-defines.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/StructuredData.h"
+#include "lldb/Core/Flags.h"
+#include "lldb/Host/File.h"
+#include "lldb/Interpreter/OptionValue.h"
+
+namespace lldb_private {
+
+class PythonString;
+class PythonList;
+class PythonDictionary;
+class PythonInteger;
+
+class StructuredPythonObject : public StructuredData::Generic
+{
+public:
+ StructuredPythonObject()
+ : StructuredData::Generic()
+ {
+ }
+
+ StructuredPythonObject(void *obj)
+ : StructuredData::Generic(obj)
+ {
+ Py_XINCREF(GetValue());
+ }
+
+ ~StructuredPythonObject() override
+ {
+ if (Py_IsInitialized())
+ Py_XDECREF(GetValue());
+ SetValue(nullptr);
+ }
+
+ bool
+ IsValid() const override
+ {
+ return GetValue() && GetValue() != Py_None;
+ }
+
+ void Dump(Stream &s) const override;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(StructuredPythonObject);
+};
+
+enum class PyObjectType
+{
+ Unknown,
+ None,
+ Integer,
+ Dictionary,
+ List,
+ String,
+ Module,
+ Callable,
+ Tuple,
+ File
+};
+
+enum class PyRefType
+{
+ Borrowed, // We are not given ownership of the incoming PyObject.
+ // We cannot safely hold it without calling Py_INCREF.
+ Owned // We have ownership of the incoming PyObject. We should
+ // not call Py_INCREF.
+};
+
+enum class PyInitialValue
+{
+ Invalid,
+ Empty
+};
+
+class PythonObject
+{
+public:
+ PythonObject()
+ : m_py_obj(nullptr)
+ {
+ }
+
+ PythonObject(PyRefType type, PyObject *py_obj)
+ : m_py_obj(nullptr)
+ {
+ Reset(type, py_obj);
+ }
+
+ PythonObject(const PythonObject &rhs)
+ : m_py_obj(nullptr)
+ {
+ Reset(rhs);
+ }
+
+ virtual ~PythonObject()
+ {
+ Reset();
+ }
+
+ void
+ Reset()
+ {
+ // Avoid calling the virtual method since it's not necessary
+ // to actually validate the type of the PyObject if we're
+ // just setting to null.
+ if (Py_IsInitialized())
+ Py_XDECREF(m_py_obj);
+ m_py_obj = nullptr;
+ }
+
+ void
+ Reset(const PythonObject &rhs)
+ {
+ // Avoid calling the virtual method if it's not necessary
+ // to actually validate the type of the PyObject.
+ if (!rhs.IsValid())
+ Reset();
+ else
+ Reset(PyRefType::Borrowed, rhs.m_py_obj);
+ }
+
+ // PythonObject is implicitly convertible to PyObject *, which will call the
+ // wrong overload. We want to explicitly disallow this, since a PyObject
+ // *always* owns its reference. Therefore the overload which takes a
+ // PyRefType doesn't make sense, and the copy constructor should be used.
+ void
+ Reset(PyRefType type, const PythonObject &ref) = delete;
+
+ virtual void
+ Reset(PyRefType type, PyObject *py_obj)
+ {
+ if (py_obj == m_py_obj)
+ return;
+
+ if (Py_IsInitialized())
+ Py_XDECREF(m_py_obj);
+
+ m_py_obj = py_obj;
+
+ // If this is a borrowed reference, we need to convert it to
+ // an owned reference by incrementing it. If it is an owned
+ // reference (for example the caller allocated it with PyDict_New()
+ // then we must *not* increment it.
+ if (Py_IsInitialized() && type == PyRefType::Borrowed)
+ Py_XINCREF(m_py_obj);
+ }
+
+ void
+ Dump () const
+ {
+ if (m_py_obj)
+ _PyObject_Dump (m_py_obj);
+ else
+ puts ("NULL");
+ }
+
+ void
+ Dump (Stream &strm) const;
+
+ PyObject*
+ get() const
+ {
+ return m_py_obj;
+ }
+
+ PyObject*
+ release()
+ {
+ PyObject *result = m_py_obj;
+ m_py_obj = nullptr;
+ return result;
+ }
+
+ PythonObject &
+ operator=(const PythonObject &other)
+ {
+ Reset(PyRefType::Borrowed, other.get());
+ return *this;
+ }
+
+ PyObjectType
+ GetObjectType() const;
+
+ PythonString
+ Repr() const;
+
+ PythonString
+ Str() const;
+
+ static PythonObject
+ ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict);
+
+ template<typename T>
+ static T
+ ResolveNameWithDictionary(llvm::StringRef name, const PythonDictionary &dict)
+ {
+ return ResolveNameWithDictionary(name, dict).AsType<T>();
+ }
+
+ PythonObject
+ ResolveName(llvm::StringRef name) const;
+
+ template<typename T>
+ T
+ ResolveName(llvm::StringRef name) const
+ {
+ return ResolveName(name).AsType<T>();
+ }
+
+ bool
+ HasAttribute(llvm::StringRef attribute) const;
+
+ PythonObject
+ GetAttributeValue(llvm::StringRef attribute) const;
+
+ bool
+ IsValid() const;
+
+ bool
+ IsAllocated() const;
+
+ bool
+ IsNone() const;
+
+ template<typename T>
+ T AsType() const
+ {
+ if (!T::Check(m_py_obj))
+ return T();
+ return T(PyRefType::Borrowed, m_py_obj);
+ }
+
+ StructuredData::ObjectSP
+ CreateStructuredObject() const;
+
+protected:
+ PyObject* m_py_obj;
+};
+
+class PythonString : public PythonObject
+{
+public:
+ PythonString();
+ explicit PythonString(llvm::StringRef string);
+ explicit PythonString(const char *string);
+ PythonString(PyRefType type, PyObject *o);
+ PythonString(const PythonString &object);
+
+ ~PythonString() override;
+
+ static bool Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+
+ llvm::StringRef
+ GetString() const;
+
+ size_t
+ GetSize() const;
+
+ void SetString(llvm::StringRef string);
+
+ StructuredData::StringSP CreateStructuredString() const;
+};
+
+class PythonInteger : public PythonObject
+{
+public:
+ PythonInteger();
+ explicit PythonInteger(int64_t value);
+ PythonInteger(PyRefType type, PyObject *o);
+ PythonInteger(const PythonInteger &object);
+
+ ~PythonInteger() override;
+
+ static bool Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+
+ int64_t GetInteger() const;
+
+ void
+ SetInteger (int64_t value);
+
+ StructuredData::IntegerSP CreateStructuredInteger() const;
+};
+
+class PythonList : public PythonObject
+{
+public:
+ PythonList() {}
+ explicit PythonList(PyInitialValue value);
+ explicit PythonList(int list_size);
+ PythonList(PyRefType type, PyObject *o);
+ PythonList(const PythonList &list);
+
+ ~PythonList() override;
+
+ static bool Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+
+ uint32_t GetSize() const;
+
+ PythonObject GetItemAtIndex(uint32_t index) const;
+
+ void SetItemAtIndex(uint32_t index, const PythonObject &object);
+
+ void AppendItem(const PythonObject &object);
+
+ StructuredData::ArraySP CreateStructuredArray() const;
+};
+
+class PythonTuple : public PythonObject
+{
+public:
+ PythonTuple() {}
+ explicit PythonTuple(PyInitialValue value);
+ explicit PythonTuple(int tuple_size);
+ PythonTuple(PyRefType type, PyObject *o);
+ PythonTuple(const PythonTuple &tuple);
+ PythonTuple(std::initializer_list<PythonObject> objects);
+ PythonTuple(std::initializer_list<PyObject*> objects);
+
+ ~PythonTuple() override;
+
+ static bool Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+
+ uint32_t GetSize() const;
+
+ PythonObject GetItemAtIndex(uint32_t index) const;
+
+ void SetItemAtIndex(uint32_t index, const PythonObject &object);
+
+ StructuredData::ArraySP CreateStructuredArray() const;
+};
+
+class PythonDictionary : public PythonObject
+{
+public:
+ PythonDictionary() {}
+ explicit PythonDictionary(PyInitialValue value);
+ PythonDictionary(PyRefType type, PyObject *o);
+ PythonDictionary(const PythonDictionary &dict);
+
+ ~PythonDictionary() override;
+
+ static bool Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+
+ uint32_t GetSize() const;
+
+ PythonList GetKeys() const;
+
+ PythonObject GetItemForKey(const PythonObject &key) const;
+ void SetItemForKey(const PythonObject &key, const PythonObject &value);
+
+ StructuredData::DictionarySP CreateStructuredDictionary() const;
+};
+
+class PythonModule : public PythonObject
+{
+ public:
+ PythonModule();
+ PythonModule(PyRefType type, PyObject *o);
+ PythonModule(const PythonModule &dict);
+
+ ~PythonModule() override;
+
+ static bool Check(PyObject *py_obj);
+
+ static PythonModule
+ BuiltinsModule();
+
+ static PythonModule
+ MainModule();
+
+ static PythonModule
+ AddModule(llvm::StringRef module);
+
+ static PythonModule
+ ImportModule(llvm::StringRef module);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+
+ PythonDictionary GetDictionary() const;
+};
+
+class PythonCallable : public PythonObject
+{
+public:
+ struct ArgInfo {
+ size_t count;
+ bool has_varargs : 1;
+ bool has_kwargs : 1;
+ };
+
+ PythonCallable();
+ PythonCallable(PyRefType type, PyObject *o);
+ PythonCallable(const PythonCallable &dict);
+
+ ~PythonCallable() override;
+
+ static bool
+ Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void
+ Reset(PyRefType type, PyObject *py_obj) override;
+
+ ArgInfo
+ GetNumArguments() const;
+
+ PythonObject
+ operator ()();
+
+ PythonObject
+ operator ()(std::initializer_list<PyObject*> args);
+
+ PythonObject
+ operator ()(std::initializer_list<PythonObject> args);
+
+ template<typename Arg, typename... Args>
+ PythonObject
+ operator ()(const Arg &arg, Args... args)
+ {
+ return operator()({ arg, args... });
+ }
+};
+
+
+class PythonFile : public PythonObject
+{
+ public:
+ PythonFile();
+ PythonFile(File &file, const char *mode);
+ PythonFile(const char *path, const char *mode);
+ PythonFile(PyRefType type, PyObject *o);
+
+ ~PythonFile() override;
+
+ static bool Check(PyObject *py_obj);
+
+ using PythonObject::Reset;
+
+ void Reset(PyRefType type, PyObject *py_obj) override;
+ void Reset(File &file, const char *mode);
+
+ bool GetUnderlyingFile(File &file) const;
+};
+
+} // namespace lldb_private
+
+#endif
+
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONDATAOBJECTS_H
diff --git a/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp b/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp
new file mode 100644
index 000000000000..2cbd85bfa11e
--- /dev/null
+++ b/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp
@@ -0,0 +1,201 @@
+//===-- PythonExceptionState.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_DISABLE_PYTHON
+
+#include "lldb-python.h"
+#include "PythonExceptionState.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace lldb_private;
+
+PythonExceptionState::PythonExceptionState(bool restore_on_exit)
+ : m_restore_on_exit(restore_on_exit)
+{
+ Acquire(restore_on_exit);
+}
+
+PythonExceptionState::~PythonExceptionState()
+{
+ if (m_restore_on_exit)
+ Restore();
+}
+
+void
+PythonExceptionState::Acquire(bool restore_on_exit)
+{
+ // If a state is already acquired, the user needs to decide whether they
+ // want to discard or restore it. Don't allow the potential silent
+ // loss of a valid state.
+ assert(!IsError());
+
+ if (!HasErrorOccurred())
+ return;
+
+ PyObject *py_type = nullptr;
+ PyObject *py_value = nullptr;
+ PyObject *py_traceback = nullptr;
+ PyErr_Fetch(&py_type, &py_value, &py_traceback);
+ // PyErr_Fetch clears the error flag.
+ assert(!HasErrorOccurred());
+
+ // Ownership of the objects returned by `PyErr_Fetch` is transferred
+ // to us.
+ m_type.Reset(PyRefType::Owned, py_type);
+ m_value.Reset(PyRefType::Owned, py_value);
+ m_traceback.Reset(PyRefType::Owned, py_traceback);
+ m_restore_on_exit = restore_on_exit;
+}
+
+void
+PythonExceptionState::Restore()
+{
+ if (m_type.IsValid())
+ {
+ // The documentation for PyErr_Restore says "Do not pass a null type and
+ // non-null value or traceback. So only restore if type was non-null
+ // to begin with. In this case we're passing ownership back to Python
+ // so release them all.
+ PyErr_Restore(m_type.release(), m_value.release(), m_traceback.release());
+ }
+
+ // After we restore, we should not hold onto the exception state. Demand that
+ // it be re-acquired.
+ Discard();
+}
+
+void
+PythonExceptionState::Discard()
+{
+ m_type.Reset();
+ m_value.Reset();
+ m_traceback.Reset();
+}
+
+void
+PythonExceptionState::Reset()
+{
+ if (m_restore_on_exit)
+ Restore();
+ else
+ Discard();
+}
+
+bool
+PythonExceptionState::HasErrorOccurred()
+{
+ return PyErr_Occurred();
+}
+
+bool
+PythonExceptionState::IsError() const
+{
+ return m_type.IsValid() || m_value.IsValid() || m_traceback.IsValid();
+}
+
+PythonObject
+PythonExceptionState::GetType() const
+{
+ return m_type;
+}
+
+PythonObject
+PythonExceptionState::GetValue() const
+{
+ return m_value;
+}
+
+PythonObject
+PythonExceptionState::GetTraceback() const
+{
+ return m_traceback;
+}
+
+std::string
+PythonExceptionState::Format() const
+{
+ // Don't allow this function to modify the error state.
+ PythonExceptionState state(true);
+
+ std::string backtrace = ReadBacktrace();
+ if (!IsError())
+ return std::string();
+
+ // It's possible that ReadPythonBacktrace generated another exception.
+ // If this happens we have to clear the exception, because otherwise
+ // PyObject_Str() will assert below. That's why we needed to do the
+ // save / restore at the beginning of this function.
+ PythonExceptionState bt_error_state(false);
+
+ std::string error_string;
+ llvm::raw_string_ostream error_stream(error_string);
+ error_stream << m_value.Str().GetString() << "\n";
+
+ if (!bt_error_state.IsError())
+ {
+ // If we were able to read the backtrace, just append it.
+ error_stream << backtrace << "\n";
+ }
+ else
+ {
+ // Otherwise, append some information about why we were unable to
+ // obtain the backtrace.
+ PythonString bt_error = bt_error_state.GetValue().Str();
+ error_stream << "An error occurred while retrieving the backtrace: " << bt_error.GetString() << "\n";
+ }
+ return error_stream.str();
+}
+
+std::string
+PythonExceptionState::ReadBacktrace() const
+{
+ std::string retval("backtrace unavailable");
+
+ auto traceback_module = PythonModule::ImportModule("traceback");
+#if PY_MAJOR_VERSION >= 3
+ auto stringIO_module = PythonModule::ImportModule("io");
+#else
+ auto stringIO_module = PythonModule::ImportModule("StringIO");
+#endif
+ if (!m_traceback.IsAllocated())
+ return retval;
+
+ if (!traceback_module.IsAllocated() || !stringIO_module.IsAllocated())
+ return retval;
+
+ auto stringIO_builder = stringIO_module.ResolveName<PythonCallable>("StringIO");
+ if (!stringIO_builder.IsAllocated())
+ return retval;
+
+ auto stringIO_buffer = stringIO_builder();
+ if (!stringIO_buffer.IsAllocated())
+ return retval;
+
+ auto printTB = traceback_module.ResolveName<PythonCallable>("print_tb");
+ if (!printTB.IsAllocated())
+ return retval;
+
+ auto printTB_result = printTB(m_traceback.get(), Py_None, stringIO_buffer.get());
+ auto stringIO_getvalue = stringIO_buffer.ResolveName<PythonCallable>("getvalue");
+ if (!stringIO_getvalue.IsAllocated())
+ return retval;
+
+ auto printTB_string = stringIO_getvalue().AsType<PythonString>();
+ if (!printTB_string.IsAllocated())
+ return retval;
+
+ llvm::StringRef string_data(printTB_string.GetString());
+ retval.assign(string_data.data(), string_data.size());
+
+ return retval;
+}
+
+#endif
diff --git a/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h b/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h
new file mode 100644
index 000000000000..c74e52b9ef56
--- /dev/null
+++ b/source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h
@@ -0,0 +1,70 @@
+//===-- PythonExceptionState.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONEXCEPTIONSTATE_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_PYTHONEXCEPTIONSTATE_H
+
+#ifndef LLDB_DISABLE_PYTHON
+
+#include "PythonDataObjects.h"
+
+namespace lldb_private
+{
+
+class PythonExceptionState
+{
+ public:
+ explicit PythonExceptionState(bool restore_on_exit);
+ ~PythonExceptionState();
+
+ void
+ Acquire(bool restore_on_exit);
+
+ void
+ Restore();
+
+ void
+ Discard();
+
+ void
+ Reset();
+
+ static bool
+ HasErrorOccurred();
+
+ bool
+ IsError() const;
+
+ PythonObject
+ GetType() const;
+
+ PythonObject
+ GetValue() const;
+
+ PythonObject
+ GetTraceback() const;
+
+ std::string
+ Format() const;
+
+ private:
+ std::string
+ ReadBacktrace() const;
+
+ bool m_restore_on_exit;
+
+ PythonObject m_type;
+ PythonObject m_value;
+ PythonObject m_traceback;
+};
+}
+
+#endif
+
+#endif
diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
new file mode 100644
index 000000000000..b1dd34b46f69
--- /dev/null
+++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -0,0 +1,3172 @@
+//===-- ScriptInterpreterPython.cpp -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifdef LLDB_DISABLE_PYTHON
+
+// Python is disabled in this build
+
+#else
+
+#include "lldb-python.h"
+#include "ScriptInterpreterPython.h"
+#include "PythonDataObjects.h"
+#include "PythonExceptionState.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <mutex>
+#include <string>
+
+#include "lldb/API/SBValue.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Breakpoint/WatchpointOptions.h"
+#include "lldb/Core/Communication.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/Host/ConnectionFileDescriptor.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Host/Pipe.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+
+#if defined(_WIN32)
+#include "lldb/Host/windows/ConnectionGenericFileWindows.h"
+#endif
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/STLExtras.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static ScriptInterpreterPython::SWIGInitCallback g_swig_init_callback = nullptr;
+static ScriptInterpreterPython::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = nullptr;
+static ScriptInterpreterPython::SWIGWatchpointCallbackFunction g_swig_watchpoint_callback = nullptr;
+static ScriptInterpreterPython::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = nullptr;
+static ScriptInterpreterPython::SWIGPythonCreateSyntheticProvider g_swig_synthetic_script = nullptr;
+static ScriptInterpreterPython::SWIGPythonCreateCommandObject g_swig_create_cmd = nullptr;
+static ScriptInterpreterPython::SWIGPythonCalculateNumChildren g_swig_calc_children = nullptr;
+static ScriptInterpreterPython::SWIGPythonGetChildAtIndex g_swig_get_child_index = nullptr;
+static ScriptInterpreterPython::SWIGPythonGetIndexOfChildWithName g_swig_get_index_child = nullptr;
+static ScriptInterpreterPython::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = nullptr;
+static ScriptInterpreterPython::SWIGPythonGetValueObjectSPFromSBValue g_swig_get_valobj_sp_from_sbvalue = nullptr;
+static ScriptInterpreterPython::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = nullptr;
+static ScriptInterpreterPython::SWIGPythonMightHaveChildrenSynthProviderInstance g_swig_mighthavechildren_provider = nullptr;
+static ScriptInterpreterPython::SWIGPythonGetValueSynthProviderInstance g_swig_getvalue_provider = nullptr;
+static ScriptInterpreterPython::SWIGPythonCallCommand g_swig_call_command = nullptr;
+static ScriptInterpreterPython::SWIGPythonCallCommandObject g_swig_call_command_object = nullptr;
+static ScriptInterpreterPython::SWIGPythonCallModuleInit g_swig_call_module_init = nullptr;
+static ScriptInterpreterPython::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = nullptr;
+static ScriptInterpreterPython::SWIGPythonScriptKeyword_Process g_swig_run_script_keyword_process = nullptr;
+static ScriptInterpreterPython::SWIGPythonScriptKeyword_Thread g_swig_run_script_keyword_thread = nullptr;
+static ScriptInterpreterPython::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = nullptr;
+static ScriptInterpreterPython::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = nullptr;
+static ScriptInterpreterPython::SWIGPythonScriptKeyword_Value g_swig_run_script_keyword_value = nullptr;
+static ScriptInterpreterPython::SWIGPython_GetDynamicSetting g_swig_plugin_get = nullptr;
+static ScriptInterpreterPython::SWIGPythonCreateScriptedThreadPlan g_swig_thread_plan_script = nullptr;
+static ScriptInterpreterPython::SWIGPythonCallThreadPlan g_swig_call_thread_plan = nullptr;
+
+static bool g_initialized = false;
+
+namespace
+{
+
+// Initializing Python is not a straightforward process. We cannot control what
+// external code may have done before getting to this point in LLDB, including
+// potentially having already initialized Python, so we need to do a lot of work
+// to ensure that the existing state of the system is maintained across our
+// initialization. We do this by using an RAII pattern where we save off initial
+// state at the beginning, and restore it at the end
+struct InitializePythonRAII
+{
+public:
+ InitializePythonRAII() :
+ m_gil_state(PyGILState_UNLOCKED),
+ m_was_already_initialized(false)
+ {
+ // Python will muck with STDIN terminal state, so save off any current TTY
+ // settings so we can restore them.
+ m_stdin_tty_state.Save(STDIN_FILENO, false);
+
+ InitializePythonHome();
+
+ // Python < 3.2 and Python >= 3.2 reversed the ordering requirements for
+ // calling `Py_Initialize` and `PyEval_InitThreads`. < 3.2 requires that you
+ // call `PyEval_InitThreads` first, and >= 3.2 requires that you call it last.
+#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 2) || (PY_MAJOR_VERSION > 3)
+ Py_InitializeEx(0);
+ InitializeThreadsPrivate();
+#else
+ InitializeThreadsPrivate();
+ Py_InitializeEx(0);
+#endif
+ }
+
+ ~InitializePythonRAII()
+ {
+ if (m_was_already_initialized)
+ {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
+
+ if (log)
+ {
+ log->Printf("Releasing PyGILState. Returning to state = %slocked\n",
+ m_was_already_initialized == PyGILState_UNLOCKED ? "un" : "");
+ }
+ PyGILState_Release(m_gil_state);
+ }
+ else
+ {
+ // We initialized the threads in this function, just unlock the GIL.
+ PyEval_SaveThread();
+ }
+
+ m_stdin_tty_state.Restore();
+ }
+
+private:
+ void InitializePythonHome()
+ {
+#if defined(LLDB_PYTHON_HOME)
+#if PY_MAJOR_VERSION >= 3
+ size_t size = 0;
+ static wchar_t *g_python_home = Py_DecodeLocale(LLDB_PYTHON_HOME, &size);
+#else
+ static char *g_python_home = LLDB_PYTHON_HOME;
+#endif
+ Py_SetPythonHome(g_python_home);
+#endif
+ }
+
+ void InitializeThreadsPrivate()
+ {
+ if (PyEval_ThreadsInitialized())
+ {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
+
+ m_was_already_initialized = true;
+ m_gil_state = PyGILState_Ensure();
+ if (log)
+ {
+ log->Printf("Ensured PyGILState. Previous state = %slocked\n",
+ m_gil_state == PyGILState_UNLOCKED ? "un" : "");
+ }
+ return;
+ }
+
+ // InitThreads acquires the GIL if it hasn't been called before.
+ PyEval_InitThreads();
+ }
+
+ TerminalState m_stdin_tty_state;
+ PyGILState_STATE m_gil_state;
+ bool m_was_already_initialized;
+};
+
+}
+
+ScriptInterpreterPython::Locker::Locker (ScriptInterpreterPython *py_interpreter,
+ uint16_t on_entry,
+ uint16_t on_leave,
+ FILE *in,
+ FILE *out,
+ FILE *err) :
+ ScriptInterpreterLocker (),
+ m_teardown_session( (on_leave & TearDownSession) == TearDownSession ),
+ m_python_interpreter(py_interpreter)
+{
+ DoAcquireLock();
+ if ((on_entry & InitSession) == InitSession)
+ {
+ if (DoInitSession(on_entry, in, out, err) == false)
+ {
+ // Don't teardown the session if we didn't init it.
+ m_teardown_session = false;
+ }
+ }
+}
+
+bool
+ScriptInterpreterPython::Locker::DoAcquireLock()
+{
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
+ m_GILState = PyGILState_Ensure();
+ if (log)
+ log->Printf("Ensured PyGILState. Previous state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : "");
+
+ // we need to save the thread state when we first start the command
+ // because we might decide to interrupt it while some action is taking
+ // place outside of Python (e.g. printing to screen, waiting for the network, ...)
+ // in that case, _PyThreadState_Current will be NULL - and we would be unable
+ // to set the asynchronous exception - not a desirable situation
+ m_python_interpreter->SetThreadState(PyThreadState_Get());
+ m_python_interpreter->IncrementLockCount();
+ return true;
+}
+
+bool
+ScriptInterpreterPython::Locker::DoInitSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err)
+{
+ if (!m_python_interpreter)
+ return false;
+ return m_python_interpreter->EnterSession (on_entry_flags, in, out, err);
+}
+
+bool
+ScriptInterpreterPython::Locker::DoFreeLock()
+{
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
+ if (log)
+ log->Printf("Releasing PyGILState. Returning to state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : "");
+ PyGILState_Release(m_GILState);
+ m_python_interpreter->DecrementLockCount();
+ return true;
+}
+
+bool
+ScriptInterpreterPython::Locker::DoTearDownSession()
+{
+ if (!m_python_interpreter)
+ return false;
+ m_python_interpreter->LeaveSession ();
+ return true;
+}
+
+ScriptInterpreterPython::Locker::~Locker()
+{
+ if (m_teardown_session)
+ DoTearDownSession();
+ DoFreeLock();
+}
+
+ScriptInterpreterPython::ScriptInterpreterPython(CommandInterpreter &interpreter) :
+ ScriptInterpreter(interpreter, eScriptLanguagePython),
+ IOHandlerDelegateMultiline("DONE"),
+ m_saved_stdin(),
+ m_saved_stdout(),
+ m_saved_stderr(),
+ m_main_module(),
+ m_lldb_module(),
+ m_session_dict(PyInitialValue::Invalid),
+ m_sys_module_dict(PyInitialValue::Invalid),
+ m_run_one_line_function(),
+ m_run_one_line_str_global(),
+ m_dictionary_name(interpreter.GetDebugger().GetInstanceName().AsCString()),
+ m_terminal_state(),
+ m_active_io_handler(eIOHandlerNone),
+ m_session_is_active(false),
+ m_pty_slave_is_open(false),
+ m_valid_session(true),
+ m_lock_count(0),
+ m_command_thread_state(nullptr)
+{
+ assert(g_initialized && "ScriptInterpreterPython created but InitializePrivate has not been called!");
+
+ m_dictionary_name.append("_dict");
+ StreamString run_string;
+ run_string.Printf ("%s = dict()", m_dictionary_name.c_str());
+
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
+ PyRun_SimpleString (run_string.GetData());
+
+ run_string.Clear();
+ run_string.Printf ("run_one_line (%s, 'import copy, keyword, os, re, sys, uuid, lldb')", m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+
+ // Reloading modules requires a different syntax in Python 2 and Python 3. This provides
+ // a consistent syntax no matter what version of Python.
+ run_string.Clear();
+ run_string.Printf("run_one_line (%s, 'from six.moves import reload_module')", m_dictionary_name.c_str());
+ PyRun_SimpleString(run_string.GetData());
+
+ // WARNING: temporary code that loads Cocoa formatters - this should be done on a per-platform basis rather than loading the whole set
+ // and letting the individual formatter classes exploit APIs to check whether they can/cannot do their task
+ run_string.Clear();
+ run_string.Printf ("run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp, pydoc')", m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear();
+
+ run_string.Printf ("run_one_line (%s, 'import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line')", m_dictionary_name.c_str());
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear();
+
+ run_string.Printf ("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64 "; pydoc.pager = pydoc.plainpager')", m_dictionary_name.c_str(),
+ interpreter.GetDebugger().GetID());
+ PyRun_SimpleString (run_string.GetData());
+}
+
+ScriptInterpreterPython::~ScriptInterpreterPython ()
+{
+ // the session dictionary may hold objects with complex state
+ // which means that they may need to be torn down with some level of smarts
+ // and that, in turn, requires a valid thread state
+ // force Python to procure itself such a thread state, nuke the session dictionary
+ // and then release it for others to use and proceed with the rest of the shutdown
+ auto gil_state = PyGILState_Ensure();
+ m_session_dict.Reset();
+ PyGILState_Release(gil_state);
+}
+
+void
+ScriptInterpreterPython::Initialize()
+{
+ static std::once_flag g_once_flag;
+
+ std::call_once(g_once_flag, []()
+ {
+ InitializePrivate();
+
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(),
+ lldb::eScriptLanguagePython,
+ CreateInstance);
+ });
+}
+
+void
+ScriptInterpreterPython::Terminate()
+{
+
+}
+
+lldb::ScriptInterpreterSP
+ScriptInterpreterPython::CreateInstance(CommandInterpreter &interpreter)
+{
+ return std::make_shared<ScriptInterpreterPython>(interpreter);
+}
+
+lldb_private::ConstString
+ScriptInterpreterPython::GetPluginNameStatic()
+{
+ static ConstString g_name("script-python");
+ return g_name;
+}
+
+const char *
+ScriptInterpreterPython::GetPluginDescriptionStatic()
+{
+ return "Embedded Python interpreter";
+}
+
+lldb_private::ConstString
+ScriptInterpreterPython::GetPluginName()
+{
+ return GetPluginNameStatic();
+}
+
+uint32_t
+ScriptInterpreterPython::GetPluginVersion()
+{
+ return 1;
+}
+
+void
+ScriptInterpreterPython::IOHandlerActivated (IOHandler &io_handler)
+{
+ const char *instructions = nullptr;
+
+ switch (m_active_io_handler)
+ {
+ case eIOHandlerNone:
+ break;
+ case eIOHandlerBreakpoint:
+ instructions = R"(Enter your Python command(s). Type 'DONE' to end.
+def function (frame, bp_loc, internal_dict):
+ """frame: the lldb.SBFrame for the location at which you stopped
+ bp_loc: an lldb.SBBreakpointLocation for the breakpoint location information
+ internal_dict: an LLDB support object not to be used"""
+)";
+ break;
+ case eIOHandlerWatchpoint:
+ instructions = "Enter your Python command(s). Type 'DONE' to end.\n";
+ break;
+ }
+
+ if (instructions)
+ {
+ StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+ if (output_sp)
+ {
+ output_sp->PutCString(instructions);
+ output_sp->Flush();
+ }
+ }
+}
+
+void
+ScriptInterpreterPython::IOHandlerInputComplete (IOHandler &io_handler, std::string &data)
+{
+ io_handler.SetIsDone(true);
+ bool batch_mode = m_interpreter.GetBatchCommandMode();
+
+ switch (m_active_io_handler)
+ {
+ case eIOHandlerNone:
+ break;
+ case eIOHandlerBreakpoint:
+ {
+ std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
+ for (auto bp_options : *bp_options_vec)
+ {
+ if (!bp_options)
+ continue;
+
+ std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
+ if (data_ap.get())
+ {
+ data_ap->user_source.SplitIntoLines(data);
+
+ if (GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source).Success())
+ {
+ BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
+ bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
+ }
+ else if (!batch_mode)
+ {
+ StreamFileSP error_sp = io_handler.GetErrorStreamFile();
+ if (error_sp)
+ {
+ error_sp->Printf ("Warning: No command attached to breakpoint.\n");
+ error_sp->Flush();
+ }
+ }
+ }
+ }
+ m_active_io_handler = eIOHandlerNone;
+ }
+ break;
+ case eIOHandlerWatchpoint:
+ {
+ WatchpointOptions *wp_options = (WatchpointOptions *)io_handler.GetUserData();
+ std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
+ if (data_ap.get())
+ {
+ data_ap->user_source.SplitIntoLines(data);
+
+ if (GenerateWatchpointCommandCallbackData (data_ap->user_source, data_ap->script_source))
+ {
+ BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
+ wp_options->SetCallback (ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp);
+ }
+ else if (!batch_mode)
+ {
+ StreamFileSP error_sp = io_handler.GetErrorStreamFile();
+ if (error_sp)
+ {
+ error_sp->Printf ("Warning: No command attached to breakpoint.\n");
+ error_sp->Flush();
+ }
+ }
+ }
+ m_active_io_handler = eIOHandlerNone;
+ }
+ break;
+ }
+}
+
+
+void
+ScriptInterpreterPython::ResetOutputFileHandle (FILE *fh)
+{
+}
+
+void
+ScriptInterpreterPython::SaveTerminalState (int fd)
+{
+ // Python mucks with the terminal state of STDIN. If we can possibly avoid
+ // this by setting the file handles up correctly prior to entering the
+ // interpreter we should. For now we save and restore the terminal state
+ // on the input file handle.
+ m_terminal_state.Save (fd, false);
+}
+
+void
+ScriptInterpreterPython::RestoreTerminalState ()
+{
+ // Python mucks with the terminal state of STDIN. If we can possibly avoid
+ // this by setting the file handles up correctly prior to entering the
+ // interpreter we should. For now we save and restore the terminal state
+ // on the input file handle.
+ m_terminal_state.Restore();
+}
+
+void
+ScriptInterpreterPython::LeaveSession ()
+{
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
+ if (log)
+ log->PutCString("ScriptInterpreterPython::LeaveSession()");
+
+ // checking that we have a valid thread state - since we use our own threading and locking
+ // in some (rare) cases during cleanup Python may end up believing we have no thread state
+ // and PyImport_AddModule will crash if that is the case - since that seems to only happen
+ // when destroying the SBDebugger, we can make do without clearing up stdout and stderr
+
+ // rdar://problem/11292882
+ // When the current thread state is NULL, PyThreadState_Get() issues a fatal error.
+ if (PyThreadState_GetDict())
+ {
+ PythonDictionary &sys_module_dict = GetSysModuleDictionary ();
+ if (sys_module_dict.IsValid())
+ {
+ if (m_saved_stdin.IsValid())
+ {
+ sys_module_dict.SetItemForKey(PythonString("stdin"), m_saved_stdin);
+ m_saved_stdin.Reset ();
+ }
+ if (m_saved_stdout.IsValid())
+ {
+ sys_module_dict.SetItemForKey(PythonString("stdout"), m_saved_stdout);
+ m_saved_stdout.Reset ();
+ }
+ if (m_saved_stderr.IsValid())
+ {
+ sys_module_dict.SetItemForKey(PythonString("stderr"), m_saved_stderr);
+ m_saved_stderr.Reset ();
+ }
+ }
+ }
+
+ m_session_is_active = false;
+}
+
+bool
+ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags,
+ FILE *in,
+ FILE *out,
+ FILE *err)
+{
+ // If we have already entered the session, without having officially 'left' it, then there is no need to
+ // 'enter' it again.
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
+ if (m_session_is_active)
+ {
+ if (log)
+ log->Printf("ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16 ") session is already active, returning without doing anything", on_entry_flags);
+ return false;
+ }
+
+ if (log)
+ log->Printf("ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16 ")", on_entry_flags);
+
+
+ m_session_is_active = true;
+
+ StreamString run_string;
+
+ if (on_entry_flags & Locker::InitGlobals)
+ {
+ run_string.Printf ( "run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID());
+ run_string.Printf ( "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")", GetCommandInterpreter().GetDebugger().GetID());
+ run_string.PutCString ("; lldb.target = lldb.debugger.GetSelectedTarget()");
+ run_string.PutCString ("; lldb.process = lldb.target.GetProcess()");
+ run_string.PutCString ("; lldb.thread = lldb.process.GetSelectedThread ()");
+ run_string.PutCString ("; lldb.frame = lldb.thread.GetSelectedFrame ()");
+ run_string.PutCString ("')");
+ }
+ else
+ {
+ // If we aren't initing the globals, we should still always set the debugger (since that is always unique.)
+ run_string.Printf ( "run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID());
+ run_string.Printf ( "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")", GetCommandInterpreter().GetDebugger().GetID());
+ run_string.PutCString ("')");
+ }
+
+ PyRun_SimpleString (run_string.GetData());
+ run_string.Clear();
+
+ PythonDictionary &sys_module_dict = GetSysModuleDictionary ();
+ if (sys_module_dict.IsValid())
+ {
+ File in_file(in, false);
+ File out_file(out, false);
+ File err_file(err, false);
+
+ lldb::StreamFileSP in_sp;
+ lldb::StreamFileSP out_sp;
+ lldb::StreamFileSP err_sp;
+ if (!in_file.IsValid() || !out_file.IsValid() || !err_file.IsValid())
+ m_interpreter.GetDebugger().AdoptTopIOHandlerFilesIfInvalid (in_sp, out_sp, err_sp);
+
+ m_saved_stdin.Reset();
+
+ if ((on_entry_flags & Locker::NoSTDIN) == 0)
+ {
+ // STDIN is enabled
+ if (!in_file.IsValid() && in_sp)
+ in_file = in_sp->GetFile();
+ if (in_file.IsValid())
+ {
+ // Flush the file before giving it to python to avoid interleaved output.
+ in_file.Flush();
+
+ m_saved_stdin = sys_module_dict.GetItemForKey(PythonString("stdin")).AsType<PythonFile>();
+ // This call can deadlock your process if the file is locked
+ PythonFile new_file(in_file, "r");
+ sys_module_dict.SetItemForKey (PythonString("stdin"), new_file);
+ }
+ }
+
+ if (!out_file.IsValid() && out_sp)
+ out_file = out_sp->GetFile();
+ if (out_file.IsValid())
+ {
+ // Flush the file before giving it to python to avoid interleaved output.
+ out_file.Flush();
+
+ m_saved_stdout = sys_module_dict.GetItemForKey(PythonString("stdout")).AsType<PythonFile>();
+
+ PythonFile new_file(out_file, "w");
+ sys_module_dict.SetItemForKey (PythonString("stdout"), new_file);
+ }
+ else
+ m_saved_stdout.Reset();
+
+ if (!err_file.IsValid() && err_sp)
+ err_file = err_sp->GetFile();
+ if (err_file.IsValid())
+ {
+ // Flush the file before giving it to python to avoid interleaved output.
+ err_file.Flush();
+
+ m_saved_stderr = sys_module_dict.GetItemForKey(PythonString("stderr")).AsType<PythonFile>();
+
+ PythonFile new_file(err_file, "w");
+ sys_module_dict.SetItemForKey (PythonString("stderr"), new_file);
+ }
+ else
+ m_saved_stderr.Reset();
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear ();
+
+ return true;
+}
+
+PythonObject &
+ScriptInterpreterPython::GetMainModule()
+{
+ if (!m_main_module.IsValid())
+ m_main_module.Reset(PyRefType::Borrowed, PyImport_AddModule("__main__"));
+ return m_main_module;
+}
+
+PythonDictionary &
+ScriptInterpreterPython::GetSessionDictionary ()
+{
+ if (m_session_dict.IsValid())
+ return m_session_dict;
+
+ PythonObject &main_module = GetMainModule();
+ if (!main_module.IsValid())
+ return m_session_dict;
+
+ PythonDictionary main_dict(PyRefType::Borrowed, PyModule_GetDict(main_module.get()));
+ if (!main_dict.IsValid())
+ return m_session_dict;
+
+ PythonObject item = main_dict.GetItemForKey(PythonString(m_dictionary_name));
+ m_session_dict.Reset(PyRefType::Borrowed, item.get());
+ return m_session_dict;
+}
+
+PythonDictionary &
+ScriptInterpreterPython::GetSysModuleDictionary ()
+{
+ if (m_sys_module_dict.IsValid())
+ return m_sys_module_dict;
+
+ PythonObject sys_module(PyRefType::Borrowed, PyImport_AddModule("sys"));
+ if (sys_module.IsValid())
+ m_sys_module_dict.Reset(PyRefType::Borrowed, PyModule_GetDict(sys_module.get()));
+ return m_sys_module_dict;
+}
+
+static std::string
+GenerateUniqueName (const char* base_name_wanted,
+ uint32_t& functions_counter,
+ const void* name_token = nullptr)
+{
+ StreamString sstr;
+
+ if (!base_name_wanted)
+ return std::string();
+
+ if (!name_token)
+ sstr.Printf ("%s_%d", base_name_wanted, functions_counter++);
+ else
+ sstr.Printf ("%s_%p", base_name_wanted, name_token);
+
+ return sstr.GetString();
+}
+
+bool
+ScriptInterpreterPython::GetEmbeddedInterpreterModuleObjects ()
+{
+ if (m_run_one_line_function.IsValid())
+ return true;
+
+ PythonObject module(PyRefType::Borrowed, PyImport_AddModule ("lldb.embedded_interpreter"));
+ if (!module.IsValid())
+ return false;
+
+ PythonDictionary module_dict(PyRefType::Borrowed, PyModule_GetDict(module.get()));
+ if (!module_dict.IsValid())
+ return false;
+
+ m_run_one_line_function = module_dict.GetItemForKey(PythonString("run_one_line"));
+ m_run_one_line_str_global = module_dict.GetItemForKey(PythonString("g_run_one_line_str"));
+ return m_run_one_line_function.IsValid();
+}
+
+static void
+ReadThreadBytesReceived(void *baton, const void *src, size_t src_len)
+{
+ if (src && src_len)
+ {
+ Stream *strm = (Stream *)baton;
+ strm->Write(src, src_len);
+ strm->Flush();
+ }
+}
+
+bool
+ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObject *result, const ExecuteScriptOptions &options)
+{
+ if (!m_valid_session)
+ return false;
+
+ if (command && command[0])
+ {
+ // We want to call run_one_line, passing in the dictionary and the command string. We cannot do this through
+ // PyRun_SimpleString here because the command string may contain escaped characters, and putting it inside
+ // another string to pass to PyRun_SimpleString messes up the escaping. So we use the following more complicated
+ // method to pass the command string directly down to Python.
+ Debugger &debugger = m_interpreter.GetDebugger();
+
+ StreamFileSP input_file_sp;
+ StreamFileSP output_file_sp;
+ StreamFileSP error_file_sp;
+ Communication output_comm ("lldb.ScriptInterpreterPython.ExecuteOneLine.comm");
+ bool join_read_thread = false;
+ if (options.GetEnableIO())
+ {
+ if (result)
+ {
+ input_file_sp = debugger.GetInputFile();
+ // Set output to a temporary file so we can forward the results on to the result object
+
+ Pipe pipe;
+ Error pipe_result = pipe.CreateNew(false);
+ if (pipe_result.Success())
+ {
+#if defined(_WIN32)
+ lldb::file_t read_file = pipe.GetReadNativeHandle();
+ pipe.ReleaseReadFileDescriptor();
+ std::unique_ptr<ConnectionGenericFile> conn_ap(new ConnectionGenericFile(read_file, true));
+#else
+ std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor(pipe.ReleaseReadFileDescriptor(), true));
+#endif
+ if (conn_ap->IsConnected())
+ {
+ output_comm.SetConnection(conn_ap.release());
+ output_comm.SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived, &result->GetOutputStream());
+ output_comm.StartReadThread();
+ join_read_thread = true;
+ FILE *outfile_handle = fdopen (pipe.ReleaseWriteFileDescriptor(), "w");
+ output_file_sp.reset(new StreamFile(outfile_handle, true));
+ error_file_sp = output_file_sp;
+ if (outfile_handle)
+ ::setbuf (outfile_handle, nullptr);
+
+ result->SetImmediateOutputFile(debugger.GetOutputFile()->GetFile().GetStream());
+ result->SetImmediateErrorFile(debugger.GetErrorFile()->GetFile().GetStream());
+ }
+ }
+ }
+ if (!input_file_sp || !output_file_sp || !error_file_sp)
+ debugger.AdoptTopIOHandlerFilesIfInvalid(input_file_sp, output_file_sp, error_file_sp);
+ }
+ else
+ {
+ input_file_sp.reset (new StreamFile ());
+ input_file_sp->GetFile().Open(FileSystem::DEV_NULL, File::eOpenOptionRead);
+ output_file_sp.reset (new StreamFile ());
+ output_file_sp->GetFile().Open(FileSystem::DEV_NULL, File::eOpenOptionWrite);
+ error_file_sp = output_file_sp;
+ }
+
+ FILE *in_file = input_file_sp->GetFile().GetStream();
+ FILE *out_file = output_file_sp->GetFile().GetStream();
+ FILE *err_file = error_file_sp->GetFile().GetStream();
+ bool success = false;
+ {
+ // WARNING! It's imperative that this RAII scope be as tight as possible. In particular, the
+ // scope must end *before* we try to join the read thread. The reason for this is that a
+ // pre-requisite for joining the read thread is that we close the write handle (to break the
+ // pipe and cause it to wake up and exit). But acquiring the GIL as below will redirect Python's
+ // stdio to use this same handle. If we close the handle while Python is still using it, bad
+ // things will happen.
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock |
+ ScriptInterpreterPython::Locker::InitSession |
+ (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) |
+ ((result && result->GetInteractive()) ? 0: Locker::NoSTDIN),
+ ScriptInterpreterPython::Locker::FreeAcquiredLock |
+ ScriptInterpreterPython::Locker::TearDownSession,
+ in_file,
+ out_file,
+ err_file);
+
+ // Find the correct script interpreter dictionary in the main module.
+ PythonDictionary &session_dict = GetSessionDictionary ();
+ if (session_dict.IsValid())
+ {
+ if (GetEmbeddedInterpreterModuleObjects ())
+ {
+ if (PyCallable_Check(m_run_one_line_function.get()))
+ {
+ PythonObject pargs(PyRefType::Owned, Py_BuildValue("(Os)", session_dict.get(), command));
+ if (pargs.IsValid())
+ {
+ PythonObject return_value(PyRefType::Owned,
+ PyObject_CallObject(m_run_one_line_function.get(), pargs.get()));
+ if (return_value.IsValid())
+ success = true;
+ else if (options.GetMaskoutErrors() && PyErr_Occurred ())
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ }
+ }
+ }
+ }
+
+ // Flush our output and error file handles
+ ::fflush (out_file);
+ if (out_file != err_file)
+ ::fflush (err_file);
+ }
+
+ if (join_read_thread)
+ {
+ // Close the write end of the pipe since we are done with our
+ // one line script. This should cause the read thread that
+ // output_comm is using to exit
+ output_file_sp->GetFile().Close();
+ // The close above should cause this thread to exit when it gets
+ // to the end of file, so let it get all its data
+ output_comm.JoinReadThread();
+ // Now we can close the read end of the pipe
+ output_comm.Disconnect();
+ }
+
+
+ if (success)
+ return true;
+
+ // The one-liner failed. Append the error message.
+ if (result)
+ result->AppendErrorWithFormat ("python failed attempting to evaluate '%s'\n", command);
+ return false;
+ }
+
+ if (result)
+ result->AppendError ("empty command passed to python\n");
+ return false;
+}
+
+
+class IOHandlerPythonInterpreter :
+ public IOHandler
+{
+public:
+
+ IOHandlerPythonInterpreter (Debugger &debugger,
+ ScriptInterpreterPython *python) :
+ IOHandler (debugger, IOHandler::Type::PythonInterpreter),
+ m_python(python)
+ {
+
+ }
+
+ ~IOHandlerPythonInterpreter() override
+ {
+
+ }
+
+ ConstString
+ GetControlSequence (char ch) override
+ {
+ if (ch == 'd')
+ return ConstString("quit()\n");
+ return ConstString();
+ }
+
+ void
+ Run () override
+ {
+ if (m_python)
+ {
+ int stdin_fd = GetInputFD();
+ if (stdin_fd >= 0)
+ {
+ Terminal terminal(stdin_fd);
+ TerminalState terminal_state;
+ const bool is_a_tty = terminal.IsATerminal();
+
+ if (is_a_tty)
+ {
+ terminal_state.Save (stdin_fd, false);
+ terminal.SetCanonical(false);
+ terminal.SetEcho(true);
+ }
+
+ ScriptInterpreterPython::Locker locker (m_python,
+ ScriptInterpreterPython::Locker::AcquireLock |
+ ScriptInterpreterPython::Locker::InitSession |
+ ScriptInterpreterPython::Locker::InitGlobals,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock |
+ ScriptInterpreterPython::Locker::TearDownSession);
+
+ // The following call drops into the embedded interpreter loop and stays there until the
+ // user chooses to exit from the Python interpreter.
+ // This embedded interpreter will, as any Python code that performs I/O, unlock the GIL before
+ // a system call that can hang, and lock it when the syscall has returned.
+
+ // We need to surround the call to the embedded interpreter with calls to PyGILState_Ensure and
+ // PyGILState_Release (using the Locker above). This is because Python has a global lock which must be held whenever we want
+ // to touch any Python objects. Otherwise, if the user calls Python code, the interpreter state will be off,
+ // and things could hang (it's happened before).
+
+ StreamString run_string;
+ run_string.Printf ("run_python_interpreter (%s)", m_python->GetDictionaryName ());
+ PyRun_SimpleString (run_string.GetData());
+
+ if (is_a_tty)
+ terminal_state.Restore();
+ }
+ }
+ SetIsDone(true);
+ }
+
+ void
+ Cancel () override
+ {
+
+ }
+
+ bool
+ Interrupt () override
+ {
+ return m_python->Interrupt();
+ }
+
+ void
+ GotEOF() override
+ {
+
+ }
+protected:
+ ScriptInterpreterPython *m_python;
+};
+
+
+void
+ScriptInterpreterPython::ExecuteInterpreterLoop ()
+{
+ Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+
+ Debugger &debugger = GetCommandInterpreter().GetDebugger();
+
+ // At the moment, the only time the debugger does not have an input file handle is when this is called
+ // directly from Python, 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 Python interpreter loop, so we won't
+ // do it.
+
+ if (!debugger.GetInputFile()->GetFile().IsValid())
+ return;
+
+ IOHandlerSP io_handler_sp (new IOHandlerPythonInterpreter (debugger, this));
+ if (io_handler_sp)
+ {
+ debugger.PushIOHandler(io_handler_sp);
+ }
+}
+
+bool
+ScriptInterpreterPython::Interrupt()
+{
+ Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
+
+ if (IsExecutingPython())
+ {
+ PyThreadState *state = PyThreadState_Get();
+ if (!state)
+ state = GetThreadState();
+ if (state)
+ {
+ long tid = state->thread_id;
+ PyThreadState_Swap(state);
+ int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt);
+ if (log)
+ log->Printf("ScriptInterpreterPython::Interrupt() sending PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...", tid, num_threads);
+ return true;
+ }
+ }
+ if (log)
+ log->Printf("ScriptInterpreterPython::Interrupt() python code not running, can't interrupt");
+ return false;
+
+}
+bool
+ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
+ ScriptInterpreter::ScriptReturnType return_type,
+ void *ret_value,
+ const ExecuteScriptOptions &options)
+{
+
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | Locker::NoSTDIN,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
+
+ PythonObject py_return;
+ PythonObject &main_module = GetMainModule();
+ PythonDictionary globals(PyRefType::Borrowed, PyModule_GetDict(main_module.get()));
+ PythonObject py_error;
+ bool ret_success = false;
+ int success;
+
+ PythonDictionary locals = GetSessionDictionary ();
+
+ if (!locals.IsValid())
+ {
+ locals.Reset(PyRefType::Owned, PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str()));
+ }
+
+ if (!locals.IsValid())
+ locals = globals;
+
+ py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
+ if (py_error.IsValid())
+ PyErr_Clear();
+
+ if (in_string != nullptr)
+ {
+ { // scope for PythonInputReaderManager
+ //PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
+ py_return.Reset(PyRefType::Owned, PyRun_String(in_string, Py_eval_input, globals.get(), locals.get()));
+ if (!py_return.IsValid())
+ {
+ py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
+ if (py_error.IsValid())
+ PyErr_Clear();
+
+ py_return.Reset(PyRefType::Owned, PyRun_String(in_string, Py_single_input, globals.get(), locals.get()));
+ }
+ }
+
+ if (py_return.IsValid())
+ {
+ switch (return_type)
+ {
+ case eScriptReturnTypeCharPtr: // "char *"
+ {
+ const char format[3] = "s#";
+ success = PyArg_Parse (py_return.get(), format, (char **) ret_value);
+ break;
+ }
+ case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return == Py_None
+ {
+ const char format[3] = "z";
+ success = PyArg_Parse (py_return.get(), format, (char **) ret_value);
+ break;
+ }
+ case eScriptReturnTypeBool:
+ {
+ const char format[2] = "b";
+ success = PyArg_Parse (py_return.get(), format, (bool *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeShortInt:
+ {
+ const char format[2] = "h";
+ success = PyArg_Parse (py_return.get(), format, (short *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeShortIntUnsigned:
+ {
+ const char format[2] = "H";
+ success = PyArg_Parse (py_return.get(), format, (unsigned short *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeInt:
+ {
+ const char format[2] = "i";
+ success = PyArg_Parse (py_return.get(), format, (int *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeIntUnsigned:
+ {
+ const char format[2] = "I";
+ success = PyArg_Parse (py_return.get(), format, (unsigned int *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongInt:
+ {
+ const char format[2] = "l";
+ success = PyArg_Parse (py_return.get(), format, (long *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongIntUnsigned:
+ {
+ const char format[2] = "k";
+ success = PyArg_Parse (py_return.get(), format, (unsigned long *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongLong:
+ {
+ const char format[2] = "L";
+ success = PyArg_Parse (py_return.get(), format, (long long *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeLongLongUnsigned:
+ {
+ const char format[2] = "K";
+ success = PyArg_Parse (py_return.get(), format, (unsigned long long *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeFloat:
+ {
+ const char format[2] = "f";
+ success = PyArg_Parse (py_return.get(), format, (float *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeDouble:
+ {
+ const char format[2] = "d";
+ success = PyArg_Parse (py_return.get(), format, (double *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeChar:
+ {
+ const char format[2] = "c";
+ success = PyArg_Parse (py_return.get(), format, (char *) ret_value);
+ break;
+ }
+ case eScriptReturnTypeOpaqueObject:
+ {
+ success = true;
+ PyObject *saved_value = py_return.get();
+ Py_XINCREF(saved_value);
+ *((PyObject **)ret_value) = saved_value;
+ break;
+ }
+ }
+
+ if (success)
+ ret_success = true;
+ else
+ ret_success = false;
+ }
+ }
+
+ py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
+ if (py_error.IsValid())
+ {
+ ret_success = false;
+ if (options.GetMaskoutErrors())
+ {
+ if (PyErr_GivenExceptionMatches (py_error.get(), PyExc_SyntaxError))
+ PyErr_Print ();
+ PyErr_Clear();
+ }
+ }
+
+ return ret_success;
+}
+
+Error
+ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const ExecuteScriptOptions &options)
+{
+ Error error;
+
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | Locker::NoSTDIN,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
+
+ PythonObject return_value;
+ PythonObject &main_module = GetMainModule();
+ PythonDictionary globals(PyRefType::Borrowed, PyModule_GetDict(main_module.get()));
+ PythonObject py_error;
+
+ PythonDictionary locals = GetSessionDictionary();
+
+ if (!locals.IsValid())
+ locals.Reset(PyRefType::Owned, PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str()));
+
+ if (!locals.IsValid())
+ locals = globals;
+
+ py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
+ if (py_error.IsValid())
+ PyErr_Clear();
+
+ if (in_string != nullptr)
+ {
+ PythonObject code_object;
+ code_object.Reset(PyRefType::Owned, Py_CompileString(in_string, "temp.py", Py_file_input));
+
+ if (code_object.IsValid())
+ {
+ // In Python 2.x, PyEval_EvalCode takes a PyCodeObject, but in Python 3.x, it takes
+ // a PyObject. They are convertible (hence the function PyCode_Check(PyObject*), so
+ // we have to do the cast for Python 2.x
+#if PY_MAJOR_VERSION >= 3
+ PyObject *py_code_obj = code_object.get();
+#else
+ PyCodeObject *py_code_obj = reinterpret_cast<PyCodeObject *>(code_object.get());
+#endif
+ return_value.Reset(PyRefType::Owned, PyEval_EvalCode(py_code_obj, globals.get(), locals.get()));
+ }
+ }
+
+ PythonExceptionState exception_state(!options.GetMaskoutErrors());
+ if (exception_state.IsError())
+ error.SetErrorString(exception_state.Format().c_str());
+
+ return error;
+}
+
+
+void
+ScriptInterpreterPython::CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
+ CommandReturnObject &result)
+{
+ m_active_io_handler = eIOHandlerBreakpoint;
+ m_interpreter.GetPythonCommandsFromIOHandler (" ", *this, true, &bp_options_vec);
+}
+
+void
+ScriptInterpreterPython::CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options,
+ CommandReturnObject &result)
+{
+ m_active_io_handler = eIOHandlerWatchpoint;
+ m_interpreter.GetPythonCommandsFromIOHandler (" ", *this, true, wp_options);
+}
+
+void
+ScriptInterpreterPython::SetBreakpointCommandCallbackFunction (BreakpointOptions *bp_options,
+ const char *function_name)
+{
+ // 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_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
+ oneliner.c_str());
+}
+
+// Set a Python one-liner as the callback for the breakpoint.
+Error
+ScriptInterpreterPython::SetBreakpointCommandCallback (BreakpointOptions *bp_options,
+ const char *command_body_text)
+{
+ std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
+
+ // 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. That is what
+ // the callback will actually invoke.
+
+ data_ap->user_source.SplitIntoLines(command_body_text);
+ Error error = GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source);
+ if (error.Success())
+ {
+ BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
+ bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
+ return error;
+ }
+ else
+ return error;
+}
+
+// Set a Python one-liner as the callback for the watchpoint.
+void
+ScriptInterpreterPython::SetWatchpointCommandCallback (WatchpointOptions *wp_options,
+ const char *oneliner)
+{
+ std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
+
+ // It's necessary to set both user_source and script_source to the oneliner.
+ // The former is used to generate callback description (as in watchpoint command list)
+ // while the latter is used for Python to interpret during the actual callback.
+
+ data_ap->user_source.AppendString (oneliner);
+ data_ap->script_source.assign (oneliner);
+
+ if (GenerateWatchpointCommandCallbackData (data_ap->user_source, data_ap->script_source))
+ {
+ BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
+ wp_options->SetCallback (ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp);
+ }
+
+ return;
+}
+
+Error
+ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &function_def)
+{
+ // Convert StringList to one long, newline delimited, const char *.
+ std::string function_def_string(function_def.CopyList());
+
+ Error error = ExecuteMultipleLines (function_def_string.c_str(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false));
+ return error;
+}
+
+Error
+ScriptInterpreterPython::GenerateFunction(const char *signature, const StringList &input)
+{
+ Error error;
+ int num_lines = input.GetSize ();
+ if (num_lines == 0)
+ {
+ error.SetErrorString ("No input data.");
+ return error;
+ }
+
+ if (!signature || *signature == 0)
+ {
+ error.SetErrorString("No output function name.");
+ return error;
+ }
+
+ StreamString sstr;
+ StringList auto_generated_function;
+ auto_generated_function.AppendString (signature);
+ auto_generated_function.AppendString (" global_dict = globals()"); // Grab the global dictionary
+ auto_generated_function.AppendString (" new_keys = internal_dict.keys()"); // Make a list of keys in the session dict
+ auto_generated_function.AppendString (" old_keys = global_dict.keys()"); // Save list of keys in global dict
+ auto_generated_function.AppendString (" global_dict.update (internal_dict)"); // Add the session dictionary to the
+ // global dictionary.
+
+ // Wrap everything up inside the function, increasing the indentation.
+
+ auto_generated_function.AppendString(" if True:");
+ for (int i = 0; i < num_lines; ++i)
+ {
+ sstr.Clear ();
+ sstr.Printf (" %s", input.GetStringAtIndex (i));
+ auto_generated_function.AppendString (sstr.GetData());
+ }
+ auto_generated_function.AppendString (" for key in new_keys:"); // Iterate over all the keys from session dict
+ auto_generated_function.AppendString (" internal_dict[key] = global_dict[key]"); // Update session dict values
+ auto_generated_function.AppendString (" if key not in old_keys:"); // If key was not originally in global dict
+ auto_generated_function.AppendString (" del global_dict[key]"); // ...then remove key/value from global dict
+
+ // Verify that the results are valid Python.
+
+ error = ExportFunctionDefinitionToInterpreter (auto_generated_function);
+
+ return error;
+}
+
+bool
+ScriptInterpreterPython::GenerateTypeScriptFunction (StringList &user_input, std::string& output, const void* name_token)
+{
+ static uint32_t num_created_functions = 0;
+ user_input.RemoveBlankLines ();
+ StreamString sstr;
+
+ // Check to see if we have any data; if not, just return.
+ if (user_input.GetSize() == 0)
+ return false;
+
+ // Take what the user wrote, wrap it all up inside one big auto-generated Python function, passing in the
+ // ValueObject as parameter to the function.
+
+ std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_type_print_func", num_created_functions, name_token));
+ sstr.Printf ("def %s (valobj, internal_dict):", auto_generated_function_name.c_str());
+
+ if (!GenerateFunction(sstr.GetData(), user_input).Success())
+ return false;
+
+ // Store the name of the auto-generated function to be called.
+ output.assign(auto_generated_function_name);
+ return true;
+}
+
+bool
+ScriptInterpreterPython::GenerateScriptAliasFunction (StringList &user_input, std::string &output)
+{
+ static uint32_t num_created_functions = 0;
+ user_input.RemoveBlankLines ();
+ StreamString sstr;
+
+ // Check to see if we have any data; if not, just return.
+ if (user_input.GetSize() == 0)
+ return false;
+
+ std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_cmd_alias_func", num_created_functions));
+
+ sstr.Printf ("def %s (debugger, args, result, internal_dict):", auto_generated_function_name.c_str());
+
+ if (!GenerateFunction(sstr.GetData(),user_input).Success())
+ return false;
+
+ // Store the name of the auto-generated function to be called.
+ output.assign(auto_generated_function_name);
+ return true;
+}
+
+
+bool
+ScriptInterpreterPython::GenerateTypeSynthClass (StringList &user_input, std::string &output, const void* name_token)
+{
+ static uint32_t num_created_classes = 0;
+ user_input.RemoveBlankLines ();
+ int num_lines = user_input.GetSize ();
+ StreamString sstr;
+
+ // Check to see if we have any data; if not, just return.
+ if (user_input.GetSize() == 0)
+ return false;
+
+ // Wrap all user input into a Python class
+
+ std::string auto_generated_class_name(GenerateUniqueName("lldb_autogen_python_type_synth_class",num_created_classes,name_token));
+
+ StringList auto_generated_class;
+
+ // Create the function name & definition string.
+
+ sstr.Printf ("class %s:", auto_generated_class_name.c_str());
+ auto_generated_class.AppendString (sstr.GetData());
+
+ // Wrap everything up inside the class, increasing the indentation.
+ // we don't need to play any fancy indentation tricks here because there is no
+ // surrounding code whose indentation we need to honor
+ for (int i = 0; i < num_lines; ++i)
+ {
+ sstr.Clear ();
+ sstr.Printf (" %s", user_input.GetStringAtIndex (i));
+ auto_generated_class.AppendString (sstr.GetData());
+ }
+
+
+ // Verify that the results are valid Python.
+ // (even though the method is ExportFunctionDefinitionToInterpreter, a class will actually be exported)
+ // (TODO: rename that method to ExportDefinitionToInterpreter)
+ if (!ExportFunctionDefinitionToInterpreter (auto_generated_class).Success())
+ return false;
+
+ // Store the name of the auto-generated class
+
+ output.assign(auto_generated_class_name);
+ return true;
+}
+
+StructuredData::GenericSP
+ScriptInterpreterPython::OSPlugin_CreatePluginObject(const char *class_name, lldb::ProcessSP process_sp)
+{
+ if (class_name == nullptr || class_name[0] == '\0')
+ return StructuredData::GenericSP();
+
+ if (!process_sp)
+ return StructuredData::GenericSP();
+
+ void* ret_val;
+
+ {
+ Locker py_lock (this,
+ Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
+ ret_val = g_swig_create_os_plugin (class_name,
+ m_dictionary_name.c_str(),
+ process_sp);
+ }
+
+ return StructuredData::GenericSP(new StructuredPythonObject(ret_val));
+}
+
+StructuredData::DictionarySP
+ScriptInterpreterPython::OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp)
+{
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
+
+ static char callee_name[] = "get_register_info";
+
+ if (!os_plugin_object_sp)
+ return StructuredData::DictionarySP();
+
+ StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
+ if (!generic)
+ return nullptr;
+
+ PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue());
+
+ if (!implementor.IsAllocated())
+ return StructuredData::DictionarySP();
+
+ PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return StructuredData::DictionarySP();
+
+ if (PyCallable_Check(pmeth.get()) == 0)
+ {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ return StructuredData::DictionarySP();
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ // right now we know this function exists and is callable..
+ PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ assert(PythonDictionary::Check(py_return.get()) && "get_register_info returned unknown object type!");
+
+ PythonDictionary result_dict(PyRefType::Borrowed, py_return.get());
+ return result_dict.CreateStructuredDictionary();
+}
+
+StructuredData::ArraySP
+ScriptInterpreterPython::OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp)
+{
+ Locker py_lock (this,
+ Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
+
+ static char callee_name[] = "get_thread_info";
+
+ if (!os_plugin_object_sp)
+ return StructuredData::ArraySP();
+
+ StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
+ if (!generic)
+ return nullptr;
+
+ PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue());
+
+ if (!implementor.IsAllocated())
+ return StructuredData::ArraySP();
+
+ PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return StructuredData::ArraySP();
+
+ if (PyCallable_Check(pmeth.get()) == 0)
+ {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ return StructuredData::ArraySP();
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ // right now we know this function exists and is callable..
+ PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ assert(PythonList::Check(py_return.get()) && "get_thread_info returned unknown object type!");
+
+ PythonList result_list(PyRefType::Borrowed, py_return.get());
+ return result_list.CreateStructuredArray();
+}
+
+// GetPythonValueFormatString provides a system independent type safe way to
+// convert a variable's type into a python value format. Python value formats
+// are defined in terms of builtin C types and could change from system to
+// as the underlying typedef for uint* types, size_t, off_t and other values
+// change.
+
+template <typename T>
+const char *GetPythonValueFormatString(T t)
+{
+ assert(!"Unhandled type passed to GetPythonValueFormatString(T), make a specialization of GetPythonValueFormatString() to support this type.");
+ return nullptr;
+}
+template <> const char *GetPythonValueFormatString (char *) { return "s"; }
+template <> const char *GetPythonValueFormatString (char) { return "b"; }
+template <> const char *GetPythonValueFormatString (unsigned char) { return "B"; }
+template <> const char *GetPythonValueFormatString (short) { return "h"; }
+template <> const char *GetPythonValueFormatString (unsigned short) { return "H"; }
+template <> const char *GetPythonValueFormatString (int) { return "i"; }
+template <> const char *GetPythonValueFormatString (unsigned int) { return "I"; }
+template <> const char *GetPythonValueFormatString (long) { return "l"; }
+template <> const char *GetPythonValueFormatString (unsigned long) { return "k"; }
+template <> const char *GetPythonValueFormatString (long long) { return "L"; }
+template <> const char *GetPythonValueFormatString (unsigned long long) { return "K"; }
+template <> const char *GetPythonValueFormatString (float t) { return "f"; }
+template <> const char *GetPythonValueFormatString (double t) { return "d"; }
+
+StructuredData::StringSP
+ScriptInterpreterPython::OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid)
+{
+ Locker py_lock (this,
+ Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
+
+ static char callee_name[] = "get_register_data";
+ static char *param_format = const_cast<char *>(GetPythonValueFormatString(tid));
+
+ if (!os_plugin_object_sp)
+ return StructuredData::StringSP();
+
+ StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
+ if (!generic)
+ return nullptr;
+ PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue());
+
+ if (!implementor.IsAllocated())
+ return StructuredData::StringSP();
+
+ PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return StructuredData::StringSP();
+
+ if (PyCallable_Check(pmeth.get()) == 0)
+ {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ return StructuredData::StringSP();
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ // right now we know this function exists and is callable..
+ PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, param_format, tid));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ assert(PythonString::Check(py_return.get()) && "get_register_data returned unknown object type!");
+
+ PythonString result_string(PyRefType::Borrowed, py_return.get());
+ return result_string.CreateStructuredString();
+}
+
+StructuredData::DictionarySP
+ScriptInterpreterPython::OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid, lldb::addr_t context)
+{
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
+
+ static char callee_name[] = "create_thread";
+ std::string param_format;
+ param_format += GetPythonValueFormatString(tid);
+ param_format += GetPythonValueFormatString(context);
+
+ if (!os_plugin_object_sp)
+ return StructuredData::DictionarySP();
+
+ StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
+ if (!generic)
+ return nullptr;
+
+ PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue());
+
+ if (!implementor.IsAllocated())
+ return StructuredData::DictionarySP();
+
+ PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return StructuredData::DictionarySP();
+
+ if (PyCallable_Check(pmeth.get()) == 0)
+ {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ return StructuredData::DictionarySP();
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ // right now we know this function exists and is callable..
+ PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, &param_format[0], tid, context));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ assert(PythonDictionary::Check(py_return.get()) && "create_thread returned unknown object type!");
+
+ PythonDictionary result_dict(PyRefType::Borrowed, py_return.get());
+ return result_dict.CreateStructuredDictionary();
+}
+
+StructuredData::ObjectSP
+ScriptInterpreterPython::CreateScriptedThreadPlan(const char *class_name, lldb::ThreadPlanSP thread_plan_sp)
+{
+ if (class_name == nullptr || class_name[0] == '\0')
+ return StructuredData::ObjectSP();
+
+ if (!thread_plan_sp.get())
+ return StructuredData::ObjectSP();
+
+ Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger();
+ ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
+ ScriptInterpreterPython *python_interpreter = static_cast<ScriptInterpreterPython *>(script_interpreter);
+
+ if (!script_interpreter)
+ return StructuredData::ObjectSP();
+
+ void* ret_val;
+
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+
+ ret_val = g_swig_thread_plan_script (class_name,
+ python_interpreter->m_dictionary_name.c_str(),
+ thread_plan_sp);
+ }
+
+ return StructuredData::ObjectSP(new StructuredPythonObject(ret_val));
+}
+
+bool
+ScriptInterpreterPython::ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error)
+{
+ bool explains_stop = true;
+ StructuredData::Generic *generic = nullptr;
+ if (implementor_sp)
+ generic = implementor_sp->GetAsGeneric();
+ if (generic)
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ explains_stop = g_swig_call_thread_plan(generic->GetValue(), "explains_stop", event, script_error);
+ if (script_error)
+ return true;
+ }
+ return explains_stop;
+}
+
+bool
+ScriptInterpreterPython::ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error)
+{
+ bool should_stop = true;
+ StructuredData::Generic *generic = nullptr;
+ if (implementor_sp)
+ generic = implementor_sp->GetAsGeneric();
+ if (generic)
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ should_stop = g_swig_call_thread_plan(generic->GetValue(), "should_stop", event, script_error);
+ if (script_error)
+ return true;
+ }
+ return should_stop;
+}
+
+lldb::StateType
+ScriptInterpreterPython::ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp, bool &script_error)
+{
+ bool should_step = false;
+ StructuredData::Generic *generic = nullptr;
+ if (implementor_sp)
+ generic = implementor_sp->GetAsGeneric();
+ if (generic)
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ should_step = g_swig_call_thread_plan(generic->GetValue(), "should_step", NULL, script_error);
+ if (script_error)
+ should_step = true;
+ }
+ if (should_step)
+ return lldb::eStateStepping;
+ else
+ return lldb::eStateRunning;
+}
+
+StructuredData::ObjectSP
+ScriptInterpreterPython::LoadPluginModule(const FileSpec &file_spec, lldb_private::Error &error)
+{
+ if (!file_spec.Exists())
+ {
+ error.SetErrorString("no such file");
+ return StructuredData::ObjectSP();
+ }
+
+ StructuredData::ObjectSP module_sp;
+
+ if (LoadScriptingModule(file_spec.GetPath().c_str(),true,true,error,&module_sp))
+ return module_sp;
+
+ return StructuredData::ObjectSP();
+}
+
+StructuredData::DictionarySP
+ScriptInterpreterPython::GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name,
+ lldb_private::Error &error)
+{
+ if (!plugin_module_sp || !target || !setting_name || !setting_name[0] || !g_swig_plugin_get)
+ return StructuredData::DictionarySP();
+ StructuredData::Generic *generic = plugin_module_sp->GetAsGeneric();
+ if (!generic)
+ return StructuredData::DictionarySP();
+
+ PythonObject reply_pyobj;
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ TargetSP target_sp(target->shared_from_this());
+ reply_pyobj.Reset(PyRefType::Owned,
+ (PyObject *)g_swig_plugin_get(generic->GetValue(), setting_name, target_sp));
+ }
+
+ PythonDictionary py_dict(PyRefType::Borrowed, reply_pyobj.get());
+ return py_dict.CreateStructuredDictionary();
+}
+
+StructuredData::ObjectSP
+ScriptInterpreterPython::CreateSyntheticScriptedProvider(const char *class_name, lldb::ValueObjectSP valobj)
+{
+ if (class_name == nullptr || class_name[0] == '\0')
+ return StructuredData::ObjectSP();
+
+ if (!valobj.get())
+ return StructuredData::ObjectSP();
+
+ ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
+ Target *target = exe_ctx.GetTargetPtr();
+
+ if (!target)
+ return StructuredData::ObjectSP();
+
+ Debugger &debugger = target->GetDebugger();
+ ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
+ ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter;
+
+ if (!script_interpreter)
+ return StructuredData::ObjectSP();
+
+ void *ret_val = nullptr;
+
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_synthetic_script (class_name,
+ python_interpreter->m_dictionary_name.c_str(),
+ valobj);
+ }
+
+ return StructuredData::ObjectSP(new StructuredPythonObject(ret_val));
+}
+
+StructuredData::GenericSP
+ScriptInterpreterPython::CreateScriptCommandObject (const char *class_name)
+{
+ DebuggerSP debugger_sp(GetCommandInterpreter().GetDebugger().shared_from_this());
+
+ if (class_name == nullptr || class_name[0] == '\0')
+ return StructuredData::GenericSP();
+
+ if (!debugger_sp.get())
+ return StructuredData::GenericSP();
+
+ void* ret_val;
+
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_create_cmd (class_name,
+ m_dictionary_name.c_str(),
+ debugger_sp);
+ }
+
+ return StructuredData::GenericSP(new StructuredPythonObject(ret_val));
+}
+
+bool
+ScriptInterpreterPython::GenerateTypeScriptFunction (const char* oneliner, std::string& output, const void* name_token)
+{
+ StringList input;
+ input.SplitIntoLines(oneliner, strlen(oneliner));
+ return GenerateTypeScriptFunction(input, output, name_token);
+}
+
+bool
+ScriptInterpreterPython::GenerateTypeSynthClass (const char* oneliner, std::string& output, const void* name_token)
+{
+ StringList input;
+ input.SplitIntoLines(oneliner, strlen(oneliner));
+ return GenerateTypeSynthClass(input, output, name_token);
+}
+
+
+Error
+ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, std::string& output)
+{
+ static uint32_t num_created_functions = 0;
+ user_input.RemoveBlankLines ();
+ StreamString sstr;
+ Error error;
+ if (user_input.GetSize() == 0)
+ {
+ error.SetErrorString("No input data.");
+ return error;
+ }
+
+ 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());
+
+ error = GenerateFunction(sstr.GetData(), user_input);
+ if (!error.Success())
+ return error;
+
+ // Store the name of the auto-generated function to be called.
+ output.assign(auto_generated_function_name);
+ return error;
+}
+
+bool
+ScriptInterpreterPython::GenerateWatchpointCommandCallbackData (StringList &user_input, std::string& output)
+{
+ static uint32_t num_created_functions = 0;
+ user_input.RemoveBlankLines ();
+ StreamString sstr;
+
+ if (user_input.GetSize() == 0)
+ return false;
+
+ std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_wp_callback_func_",num_created_functions));
+ sstr.Printf ("def %s (frame, wp, internal_dict):", auto_generated_function_name.c_str());
+
+ if (!GenerateFunction(sstr.GetData(), user_input).Success())
+ return false;
+
+ // Store the name of the auto-generated function to be called.
+ output.assign(auto_generated_function_name);
+ return true;
+}
+
+bool
+ScriptInterpreterPython::GetScriptedSummary(const char *python_function_name, lldb::ValueObjectSP valobj,
+ StructuredData::ObjectSP &callee_wrapper_sp, const TypeSummaryOptions &options,
+ std::string &retval)
+{
+
+ Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+
+ if (!valobj.get())
+ {
+ retval.assign("<no object>");
+ return false;
+ }
+
+ void *old_callee = nullptr;
+ StructuredData::Generic *generic = nullptr;
+ if (callee_wrapper_sp)
+ {
+ generic = callee_wrapper_sp->GetAsGeneric();
+ if (generic)
+ old_callee = generic->GetValue();
+ }
+ void* new_callee = old_callee;
+
+ bool ret_val;
+ if (python_function_name && *python_function_name)
+ {
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ {
+ TypeSummaryOptionsSP options_sp(new TypeSummaryOptions(options));
+
+ Timer scoped_timer ("g_swig_typescript_callback","g_swig_typescript_callback");
+ ret_val = g_swig_typescript_callback (python_function_name,
+ GetSessionDictionary().get(),
+ valobj,
+ &new_callee,
+ options_sp,
+ retval);
+ }
+ }
+ }
+ else
+ {
+ retval.assign("<no function name>");
+ return false;
+ }
+
+ if (new_callee && old_callee != new_callee)
+ callee_wrapper_sp.reset(new StructuredPythonObject(new_callee));
+
+ return ret_val;
+}
+
+void
+ScriptInterpreterPython::Clear ()
+{
+ // Release any global variables that might have strong references to
+ // LLDB objects when clearing the python script interpreter.
+ Locker locker(this,
+ ScriptInterpreterPython::Locker::AcquireLock,
+ ScriptInterpreterPython::Locker::FreeAcquiredLock);
+
+ // This may be called as part of Py_Finalize. In that case the modules are destroyed in random
+ // order and we can't guarantee that we can access these.
+ if (Py_IsInitialized())
+ PyRun_SimpleString("lldb.debugger = None; lldb.target = None; lldb.process = None; lldb.thread = None; lldb.frame = None");
+}
+
+bool
+ScriptInterpreterPython::BreakpointCallbackFunction
+(
+ void *baton,
+ StoppointCallbackContext *context,
+ user_id_t break_id,
+ user_id_t break_loc_id
+)
+{
+ BreakpointOptions::CommandData *bp_option_data = (BreakpointOptions::CommandData *) baton;
+ const char *python_function_name = bp_option_data->script_source.c_str();
+
+ if (!context)
+ return true;
+
+ ExecutionContext exe_ctx (context->exe_ctx_ref);
+ Target *target = exe_ctx.GetTargetPtr();
+
+ if (!target)
+ return true;
+
+ Debugger &debugger = target->GetDebugger();
+ ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
+ ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter;
+
+ if (!script_interpreter)
+ return true;
+
+ if (python_function_name && python_function_name[0])
+ {
+ const StackFrameSP stop_frame_sp (exe_ctx.GetFrameSP());
+ BreakpointSP breakpoint_sp = target->GetBreakpointByID (break_id);
+ if (breakpoint_sp)
+ {
+ const BreakpointLocationSP bp_loc_sp (breakpoint_sp->FindLocationByID (break_loc_id));
+
+ if (stop_frame_sp && bp_loc_sp)
+ {
+ bool ret_val = true;
+ {
+ Locker py_lock(python_interpreter, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_breakpoint_callback (python_function_name,
+ python_interpreter->m_dictionary_name.c_str(),
+ stop_frame_sp,
+ bp_loc_sp);
+ }
+ return ret_val;
+ }
+ }
+ }
+ // We currently always true so we stop in case anything goes wrong when
+ // trying to call the script function
+ return true;
+}
+
+bool
+ScriptInterpreterPython::WatchpointCallbackFunction
+(
+ void *baton,
+ StoppointCallbackContext *context,
+ user_id_t watch_id
+)
+{
+ WatchpointOptions::CommandData *wp_option_data = (WatchpointOptions::CommandData *) baton;
+ const char *python_function_name = wp_option_data->script_source.c_str();
+
+ if (!context)
+ return true;
+
+ ExecutionContext exe_ctx (context->exe_ctx_ref);
+ Target *target = exe_ctx.GetTargetPtr();
+
+ if (!target)
+ return true;
+
+ Debugger &debugger = target->GetDebugger();
+ ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
+ ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter;
+
+ if (!script_interpreter)
+ return true;
+
+ if (python_function_name && python_function_name[0])
+ {
+ const StackFrameSP stop_frame_sp (exe_ctx.GetFrameSP());
+ WatchpointSP wp_sp = target->GetWatchpointList().FindByID (watch_id);
+ if (wp_sp)
+ {
+ if (stop_frame_sp && wp_sp)
+ {
+ bool ret_val = true;
+ {
+ Locker py_lock(python_interpreter, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_watchpoint_callback (python_function_name,
+ python_interpreter->m_dictionary_name.c_str(),
+ stop_frame_sp,
+ wp_sp);
+ }
+ return ret_val;
+ }
+ }
+ }
+ // We currently always true so we stop in case anything goes wrong when
+ // trying to call the script function
+ return true;
+}
+
+size_t
+ScriptInterpreterPython::CalculateNumChildren(const StructuredData::ObjectSP &implementor_sp, uint32_t max)
+{
+ if (!implementor_sp)
+ return 0;
+ StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
+ if (!generic)
+ return 0;
+ void *implementor = generic->GetValue();
+ if (!implementor)
+ return 0;
+
+ if (!g_swig_calc_children)
+ return 0;
+
+ size_t ret_val = 0;
+
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_calc_children (implementor, max);
+ }
+
+ return ret_val;
+}
+
+lldb::ValueObjectSP
+ScriptInterpreterPython::GetChildAtIndex(const StructuredData::ObjectSP &implementor_sp, uint32_t idx)
+{
+ if (!implementor_sp)
+ return lldb::ValueObjectSP();
+
+ StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
+ if (!generic)
+ return lldb::ValueObjectSP();
+ void *implementor = generic->GetValue();
+ if (!implementor)
+ return lldb::ValueObjectSP();
+
+ if (!g_swig_get_child_index || !g_swig_cast_to_sbvalue)
+ return lldb::ValueObjectSP();
+
+ lldb::ValueObjectSP ret_val;
+
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ void* child_ptr = g_swig_get_child_index (implementor,idx);
+ if (child_ptr != nullptr && child_ptr != Py_None)
+ {
+ lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr);
+ if (sb_value_ptr == nullptr)
+ Py_XDECREF(child_ptr);
+ else
+ ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr);
+ }
+ else
+ {
+ Py_XDECREF(child_ptr);
+ }
+ }
+
+ return ret_val;
+}
+
+int
+ScriptInterpreterPython::GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor_sp, const char *child_name)
+{
+ if (!implementor_sp)
+ return UINT32_MAX;
+
+ StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
+ if (!generic)
+ return UINT32_MAX;
+ void *implementor = generic->GetValue();
+ if (!implementor)
+ return UINT32_MAX;
+
+ if (!g_swig_get_index_child)
+ return UINT32_MAX;
+
+ int ret_val = UINT32_MAX;
+
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_get_index_child (implementor, child_name);
+ }
+
+ return ret_val;
+}
+
+bool
+ScriptInterpreterPython::UpdateSynthProviderInstance(const StructuredData::ObjectSP &implementor_sp)
+{
+ bool ret_val = false;
+
+ if (!implementor_sp)
+ return ret_val;
+
+ StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
+ if (!generic)
+ return ret_val;
+ void *implementor = generic->GetValue();
+ if (!implementor)
+ return ret_val;
+
+ if (!g_swig_update_provider)
+ return ret_val;
+
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_update_provider (implementor);
+ }
+
+ return ret_val;
+}
+
+bool
+ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance(const StructuredData::ObjectSP &implementor_sp)
+{
+ bool ret_val = false;
+
+ if (!implementor_sp)
+ return ret_val;
+
+ StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
+ if (!generic)
+ return ret_val;
+ void *implementor = generic->GetValue();
+ if (!implementor)
+ return ret_val;
+
+ if (!g_swig_mighthavechildren_provider)
+ return ret_val;
+
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_mighthavechildren_provider (implementor);
+ }
+
+ return ret_val;
+}
+
+lldb::ValueObjectSP
+ScriptInterpreterPython::GetSyntheticValue(const StructuredData::ObjectSP &implementor_sp)
+{
+ lldb::ValueObjectSP ret_val(nullptr);
+
+ if (!implementor_sp)
+ return ret_val;
+
+ StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
+ if (!generic)
+ return ret_val;
+ void *implementor = generic->GetValue();
+ if (!implementor)
+ return ret_val;
+
+ if (!g_swig_getvalue_provider || !g_swig_cast_to_sbvalue || !g_swig_get_valobj_sp_from_sbvalue)
+ return ret_val;
+
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ void* child_ptr = g_swig_getvalue_provider (implementor);
+ if (child_ptr != nullptr && child_ptr != Py_None)
+ {
+ lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr);
+ if (sb_value_ptr == nullptr)
+ Py_XDECREF(child_ptr);
+ else
+ ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr);
+ }
+ else
+ {
+ Py_XDECREF(child_ptr);
+ }
+ }
+
+ return ret_val;
+}
+
+bool
+ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
+ Process* process,
+ std::string& output,
+ Error& error)
+{
+ bool ret_val;
+ if (!process)
+ {
+ error.SetErrorString("no process");
+ return false;
+ }
+ if (!impl_function || !impl_function[0])
+ {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
+ if (!g_swig_run_script_keyword_process)
+ {
+ error.SetErrorString("internal helper function missing");
+ return false;
+ }
+ {
+ ProcessSP process_sp(process->shared_from_this());
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_run_script_keyword_process (impl_function, m_dictionary_name.c_str(), process_sp, output);
+ if (!ret_val)
+ error.SetErrorString("python script evaluation failed");
+ }
+ return ret_val;
+}
+
+bool
+ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
+ Thread* thread,
+ std::string& output,
+ Error& error)
+{
+ bool ret_val;
+ if (!thread)
+ {
+ error.SetErrorString("no thread");
+ return false;
+ }
+ if (!impl_function || !impl_function[0])
+ {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
+ if (!g_swig_run_script_keyword_thread)
+ {
+ error.SetErrorString("internal helper function missing");
+ return false;
+ }
+ {
+ ThreadSP thread_sp(thread->shared_from_this());
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_run_script_keyword_thread (impl_function, m_dictionary_name.c_str(), thread_sp, output);
+ if (!ret_val)
+ error.SetErrorString("python script evaluation failed");
+ }
+ return ret_val;
+}
+
+bool
+ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
+ Target* target,
+ std::string& output,
+ Error& error)
+{
+ bool ret_val;
+ if (!target)
+ {
+ error.SetErrorString("no thread");
+ return false;
+ }
+ if (!impl_function || !impl_function[0])
+ {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
+ if (!g_swig_run_script_keyword_target)
+ {
+ error.SetErrorString("internal helper function missing");
+ return false;
+ }
+ {
+ TargetSP target_sp(target->shared_from_this());
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_run_script_keyword_target (impl_function, m_dictionary_name.c_str(), target_sp, output);
+ if (!ret_val)
+ error.SetErrorString("python script evaluation failed");
+ }
+ return ret_val;
+}
+
+bool
+ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
+ StackFrame* frame,
+ std::string& output,
+ Error& error)
+{
+ bool ret_val;
+ if (!frame)
+ {
+ error.SetErrorString("no frame");
+ return false;
+ }
+ if (!impl_function || !impl_function[0])
+ {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
+ if (!g_swig_run_script_keyword_frame)
+ {
+ error.SetErrorString("internal helper function missing");
+ return false;
+ }
+ {
+ StackFrameSP frame_sp(frame->shared_from_this());
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_run_script_keyword_frame (impl_function, m_dictionary_name.c_str(), frame_sp, output);
+ if (!ret_val)
+ error.SetErrorString("python script evaluation failed");
+ }
+ return ret_val;
+}
+
+bool
+ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
+ ValueObject *value,
+ std::string& output,
+ Error& error)
+{
+ bool ret_val;
+ if (!value)
+ {
+ error.SetErrorString("no value");
+ return false;
+ }
+ if (!impl_function || !impl_function[0])
+ {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
+ if (!g_swig_run_script_keyword_value)
+ {
+ error.SetErrorString("internal helper function missing");
+ return false;
+ }
+ {
+ ValueObjectSP value_sp(value->GetSP());
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ ret_val = g_swig_run_script_keyword_value (impl_function, m_dictionary_name.c_str(), value_sp, output);
+ if (!ret_val)
+ error.SetErrorString("python script evaluation failed");
+ }
+ return ret_val;
+}
+
+uint64_t replace_all(std::string& str, const std::string& oldStr, const std::string& newStr)
+{
+ size_t pos = 0;
+ uint64_t matches = 0;
+ while((pos = str.find(oldStr, pos)) != std::string::npos)
+ {
+ matches++;
+ str.replace(pos, oldStr.length(), newStr);
+ pos += newStr.length();
+ }
+ return matches;
+}
+
+bool
+ScriptInterpreterPython::LoadScriptingModule(const char *pathname, bool can_reload, bool init_session, lldb_private::Error &error,
+ StructuredData::ObjectSP *module_sp)
+{
+ if (!pathname || !pathname[0])
+ {
+ error.SetErrorString("invalid pathname");
+ return false;
+ }
+
+ if (!g_swig_call_module_init)
+ {
+ error.SetErrorString("internal helper function missing");
+ return false;
+ }
+
+ lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this();
+
+ {
+ FileSpec target_file(pathname, true);
+ std::string basename(target_file.GetFilename().GetCString());
+
+ StreamString command_stream;
+
+ // Before executing Pyton code, lock the GIL.
+ Locker py_lock (this,
+ Locker::AcquireLock | (init_session ? Locker::InitSession : 0) | Locker::NoSTDIN,
+ Locker::FreeAcquiredLock | (init_session ? Locker::TearDownSession : 0));
+
+ if (target_file.GetFileType() == FileSpec::eFileTypeInvalid ||
+ target_file.GetFileType() == FileSpec::eFileTypeUnknown)
+ {
+ // if not a valid file of any sort, check if it might be a filename still
+ // dot can't be used but / and \ can, and if either is found, reject
+ if (strchr(pathname,'\\') || strchr(pathname,'/'))
+ {
+ error.SetErrorString("invalid pathname");
+ return false;
+ }
+ basename = pathname; // not a filename, probably a package of some sort, let it go through
+ }
+ else if (target_file.GetFileType() == FileSpec::eFileTypeDirectory ||
+ target_file.GetFileType() == FileSpec::eFileTypeRegular ||
+ target_file.GetFileType() == FileSpec::eFileTypeSymbolicLink)
+ {
+ std::string directory(target_file.GetDirectory().GetCString());
+ replace_all(directory,"'","\\'");
+
+ // now make sure that Python has "directory" in the search path
+ StreamString command_stream;
+ command_stream.Printf("if not (sys.path.__contains__('%s')):\n sys.path.insert(1,'%s');\n\n",
+ directory.c_str(),
+ directory.c_str());
+ bool syspath_retval = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)).Success();
+ if (!syspath_retval)
+ {
+ error.SetErrorString("Python sys.path handling failed");
+ return false;
+ }
+
+ // strip .py or .pyc extension
+ ConstString extension = target_file.GetFileNameExtension();
+ if (extension)
+ {
+ if (::strcmp(extension.GetCString(), "py") == 0)
+ basename.resize(basename.length()-3);
+ else if(::strcmp(extension.GetCString(), "pyc") == 0)
+ basename.resize(basename.length()-4);
+ }
+ }
+ else
+ {
+ error.SetErrorString("no known way to import this module specification");
+ return false;
+ }
+
+ // check if the module is already import-ed
+ command_stream.Clear();
+ command_stream.Printf("sys.modules.__contains__('%s')",basename.c_str());
+ bool does_contain = false;
+ // this call will succeed if the module was ever imported in any Debugger in the lifetime of the process
+ // in which this LLDB framework is living
+ bool was_imported_globally = (ExecuteOneLineWithReturn(command_stream.GetData(),
+ ScriptInterpreterPython::eScriptReturnTypeBool,
+ &does_contain,
+ ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)) && does_contain);
+ // this call will fail if the module was not imported in this Debugger before
+ command_stream.Clear();
+ command_stream.Printf("sys.getrefcount(%s)",basename.c_str());
+ bool was_imported_locally = GetSessionDictionary().GetItemForKey(PythonString(basename)).IsAllocated();
+
+ bool was_imported = (was_imported_globally || was_imported_locally);
+
+ if (was_imported == true && can_reload == false)
+ {
+ error.SetErrorString("module already imported");
+ return false;
+ }
+
+ // now actually do the import
+ command_stream.Clear();
+
+ if (was_imported)
+ {
+ if (!was_imported_locally)
+ command_stream.Printf("import %s ; reload_module(%s)",basename.c_str(),basename.c_str());
+ else
+ command_stream.Printf("reload_module(%s)",basename.c_str());
+ }
+ else
+ command_stream.Printf("import %s",basename.c_str());
+
+ error = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false));
+ if (error.Fail())
+ return false;
+
+ // if we are here, everything worked
+ // call __lldb_init_module(debugger,dict)
+ if (!g_swig_call_module_init (basename.c_str(),
+ m_dictionary_name.c_str(),
+ debugger_sp))
+ {
+ error.SetErrorString("calling __lldb_init_module failed");
+ return false;
+ }
+
+ if (module_sp)
+ {
+ // everything went just great, now set the module object
+ command_stream.Clear();
+ command_stream.Printf("%s",basename.c_str());
+ void* module_pyobj = nullptr;
+ if (ExecuteOneLineWithReturn(command_stream.GetData(),ScriptInterpreter::eScriptReturnTypeOpaqueObject,&module_pyobj) && module_pyobj)
+ module_sp->reset(new StructuredPythonObject(module_pyobj));
+ }
+
+ return true;
+ }
+}
+
+bool
+ScriptInterpreterPython::IsReservedWord (const char* word)
+{
+ if (!word || !word[0])
+ return false;
+
+ llvm::StringRef word_sr(word);
+
+ // filter out a few characters that would just confuse us
+ // and that are clearly not keyword material anyway
+ if (word_sr.find_first_of("'\"") != llvm::StringRef::npos)
+ return false;
+
+ StreamString command_stream;
+ command_stream.Printf("keyword.iskeyword('%s')", word);
+ bool result;
+ ExecuteScriptOptions options;
+ options.SetEnableIO(false);
+ options.SetMaskoutErrors(true);
+ options.SetSetLLDBGlobals(false);
+ if (ExecuteOneLineWithReturn(command_stream.GetData(), ScriptInterpreter::eScriptReturnTypeBool, &result, options))
+ return result;
+ return false;
+}
+
+ScriptInterpreterPython::SynchronicityHandler::SynchronicityHandler (lldb::DebuggerSP debugger_sp,
+ ScriptedCommandSynchronicity synchro) :
+ m_debugger_sp(debugger_sp),
+ m_synch_wanted(synchro),
+ m_old_asynch(debugger_sp->GetAsyncExecution())
+{
+ if (m_synch_wanted == eScriptedCommandSynchronicitySynchronous)
+ m_debugger_sp->SetAsyncExecution(false);
+ else if (m_synch_wanted == eScriptedCommandSynchronicityAsynchronous)
+ m_debugger_sp->SetAsyncExecution(true);
+}
+
+ScriptInterpreterPython::SynchronicityHandler::~SynchronicityHandler()
+{
+ if (m_synch_wanted != eScriptedCommandSynchronicityCurrentValue)
+ m_debugger_sp->SetAsyncExecution(m_old_asynch);
+}
+
+bool
+ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function,
+ const char* args,
+ ScriptedCommandSynchronicity synchronicity,
+ lldb_private::CommandReturnObject& cmd_retobj,
+ Error& error,
+ const lldb_private::ExecutionContext& exe_ctx)
+{
+ if (!impl_function)
+ {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
+
+ if (!g_swig_call_command)
+ {
+ error.SetErrorString("no helper function to run scripted commands");
+ return false;
+ }
+
+ lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this();
+ lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx));
+
+ if (!debugger_sp.get())
+ {
+ error.SetErrorString("invalid Debugger pointer");
+ return false;
+ }
+
+ bool ret_val = false;
+
+ std::string err_msg;
+
+ {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),
+ Locker::FreeLock | Locker::TearDownSession);
+
+ SynchronicityHandler synch_handler(debugger_sp,
+ synchronicity);
+
+ ret_val = g_swig_call_command (impl_function,
+ m_dictionary_name.c_str(),
+ debugger_sp,
+ args,
+ cmd_retobj,
+ exe_ctx_ref_sp);
+ }
+
+ if (!ret_val)
+ error.SetErrorString("unable to execute script function");
+ else
+ error.Clear();
+
+ return ret_val;
+}
+
+bool
+ScriptInterpreterPython::RunScriptBasedCommand (StructuredData::GenericSP impl_obj_sp,
+ const char* args,
+ ScriptedCommandSynchronicity synchronicity,
+ lldb_private::CommandReturnObject& cmd_retobj,
+ Error& error,
+ const lldb_private::ExecutionContext& exe_ctx)
+{
+ if (!impl_obj_sp || !impl_obj_sp->IsValid())
+ {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
+
+ if (!g_swig_call_command_object)
+ {
+ error.SetErrorString("no helper function to run scripted commands");
+ return false;
+ }
+
+ lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this();
+ lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx));
+
+ if (!debugger_sp.get())
+ {
+ error.SetErrorString("invalid Debugger pointer");
+ return false;
+ }
+
+ bool ret_val = false;
+
+ std::string err_msg;
+
+ {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),
+ Locker::FreeLock | Locker::TearDownSession);
+
+ SynchronicityHandler synch_handler(debugger_sp,
+ synchronicity);
+
+ ret_val = g_swig_call_command_object (impl_obj_sp->GetValue(),
+ debugger_sp,
+ args,
+ cmd_retobj,
+ exe_ctx_ref_sp);
+ }
+
+ if (!ret_val)
+ error.SetErrorString("unable to execute script function");
+ else
+ error.Clear();
+
+ return ret_val;
+}
+
+// in Python, a special attribute __doc__ contains the docstring
+// for an object (function, method, class, ...) if any is defined
+// Otherwise, the attribute's value is None
+bool
+ScriptInterpreterPython::GetDocumentationForItem(const char* item, std::string& dest)
+{
+ dest.clear();
+ if (!item || !*item)
+ return false;
+ std::string command(item);
+ command += ".__doc__";
+
+ char* result_ptr = nullptr; // Python is going to point this to valid data if ExecuteOneLineWithReturn returns successfully
+
+ if (ExecuteOneLineWithReturn (command.c_str(),
+ ScriptInterpreter::eScriptReturnTypeCharStrOrNone,
+ &result_ptr,
+ ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false)))
+ {
+ if (result_ptr)
+ dest.assign(result_ptr);
+ return true;
+ }
+ else
+ {
+ StreamString str_stream;
+ str_stream.Printf("Function %s was not found. Containing module might be missing.",item);
+ dest.assign(str_stream.GetData());
+ return false;
+ }
+}
+
+bool
+ScriptInterpreterPython::GetShortHelpForCommandObject (StructuredData::GenericSP cmd_obj_sp,
+ std::string& dest)
+{
+ bool got_string = false;
+ dest.clear();
+
+ Locker py_lock (this,
+ Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
+
+ static char callee_name[] = "get_short_help";
+
+ if (!cmd_obj_sp)
+ return false;
+
+ PythonObject implementor(PyRefType::Borrowed, (PyObject *)cmd_obj_sp->GetValue());
+
+ if (!implementor.IsAllocated())
+ return false;
+
+ PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return false;
+
+ if (PyCallable_Check(pmeth.get()) == 0)
+ {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ return false;
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ // right now we know this function exists and is callable..
+ PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ if (py_return.IsAllocated() && PythonString::Check(py_return.get()))
+ {
+ PythonString py_string(PyRefType::Borrowed, py_return.get());
+ llvm::StringRef return_data(py_string.GetString());
+ dest.assign(return_data.data(), return_data.size());
+ got_string = true;
+ }
+ return got_string;
+}
+
+uint32_t
+ScriptInterpreterPython::GetFlagsForCommandObject (StructuredData::GenericSP cmd_obj_sp)
+{
+ uint32_t result = 0;
+
+ Locker py_lock (this,
+ Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
+
+ static char callee_name[] = "get_flags";
+
+ if (!cmd_obj_sp)
+ return result;
+
+ PythonObject implementor(PyRefType::Borrowed, (PyObject *)cmd_obj_sp->GetValue());
+
+ if (!implementor.IsAllocated())
+ return result;
+
+ PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return result;
+
+ if (PyCallable_Check(pmeth.get()) == 0)
+ {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ return result;
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ // right now we know this function exists and is callable..
+ PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ if (py_return.IsAllocated() && PythonInteger::Check(py_return.get()))
+ {
+ PythonInteger int_value(PyRefType::Borrowed, py_return.get());
+ result = int_value.GetInteger();
+ }
+
+ return result;
+}
+
+bool
+ScriptInterpreterPython::GetLongHelpForCommandObject (StructuredData::GenericSP cmd_obj_sp,
+ std::string& dest)
+{
+ bool got_string = false;
+ dest.clear();
+
+ Locker py_lock (this,
+ Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
+
+ static char callee_name[] = "get_long_help";
+
+ if (!cmd_obj_sp)
+ return false;
+
+ PythonObject implementor(PyRefType::Borrowed, (PyObject *)cmd_obj_sp->GetValue());
+
+ if (!implementor.IsAllocated())
+ return false;
+
+ PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return false;
+
+ if (PyCallable_Check(pmeth.get()) == 0)
+ {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ return false;
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ // right now we know this function exists and is callable..
+ PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ if (py_return.IsAllocated() && PythonString::Check(py_return.get()))
+ {
+ PythonString str(PyRefType::Borrowed, py_return.get());
+ llvm::StringRef str_data(str.GetString());
+ dest.assign(str_data.data(), str_data.size());
+ got_string = true;
+ }
+
+ return got_string;
+}
+
+std::unique_ptr<ScriptInterpreterLocker>
+ScriptInterpreterPython::AcquireInterpreterLock ()
+{
+ std::unique_ptr<ScriptInterpreterLocker> py_lock(new Locker(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN,
+ Locker::FreeLock | Locker::TearDownSession));
+ return py_lock;
+}
+
+void
+ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callback,
+ SWIGBreakpointCallbackFunction swig_breakpoint_callback,
+ SWIGWatchpointCallbackFunction swig_watchpoint_callback,
+ SWIGPythonTypeScriptCallbackFunction swig_typescript_callback,
+ SWIGPythonCreateSyntheticProvider swig_synthetic_script,
+ SWIGPythonCreateCommandObject swig_create_cmd,
+ SWIGPythonCalculateNumChildren swig_calc_children,
+ SWIGPythonGetChildAtIndex swig_get_child_index,
+ SWIGPythonGetIndexOfChildWithName swig_get_index_child,
+ SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue ,
+ SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,
+ SWIGPythonUpdateSynthProviderInstance swig_update_provider,
+ SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider,
+ SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider,
+ SWIGPythonCallCommand swig_call_command,
+ SWIGPythonCallCommandObject swig_call_command_object,
+ SWIGPythonCallModuleInit swig_call_module_init,
+ SWIGPythonCreateOSPlugin swig_create_os_plugin,
+ SWIGPythonScriptKeyword_Process swig_run_script_keyword_process,
+ SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
+ SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
+ SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
+ SWIGPythonScriptKeyword_Value swig_run_script_keyword_value,
+ SWIGPython_GetDynamicSetting swig_plugin_get,
+ SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
+ SWIGPythonCallThreadPlan swig_call_thread_plan)
+{
+ g_swig_init_callback = swig_init_callback;
+ g_swig_breakpoint_callback = swig_breakpoint_callback;
+ g_swig_watchpoint_callback = swig_watchpoint_callback;
+ g_swig_typescript_callback = swig_typescript_callback;
+ g_swig_synthetic_script = swig_synthetic_script;
+ g_swig_create_cmd = swig_create_cmd;
+ g_swig_calc_children = swig_calc_children;
+ g_swig_get_child_index = swig_get_child_index;
+ g_swig_get_index_child = swig_get_index_child;
+ g_swig_cast_to_sbvalue = swig_cast_to_sbvalue;
+ g_swig_get_valobj_sp_from_sbvalue = swig_get_valobj_sp_from_sbvalue;
+ g_swig_update_provider = swig_update_provider;
+ g_swig_mighthavechildren_provider = swig_mighthavechildren_provider;
+ g_swig_getvalue_provider = swig_getvalue_provider;
+ g_swig_call_command = swig_call_command;
+ g_swig_call_command_object = swig_call_command_object;
+ g_swig_call_module_init = swig_call_module_init;
+ g_swig_create_os_plugin = swig_create_os_plugin;
+ g_swig_run_script_keyword_process = swig_run_script_keyword_process;
+ g_swig_run_script_keyword_thread = swig_run_script_keyword_thread;
+ g_swig_run_script_keyword_target = swig_run_script_keyword_target;
+ g_swig_run_script_keyword_frame = swig_run_script_keyword_frame;
+ g_swig_run_script_keyword_value = swig_run_script_keyword_value;
+ g_swig_plugin_get = swig_plugin_get;
+ g_swig_thread_plan_script = swig_thread_plan_script;
+ g_swig_call_thread_plan = swig_call_thread_plan;
+}
+
+void
+ScriptInterpreterPython::InitializePrivate ()
+{
+ assert(!g_initialized && "ScriptInterpreterPython::InitializePrivate() called more than once!");
+ g_initialized = true;
+
+ Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
+
+ // RAII-based initialization which correctly handles multiple-initialization, version-
+ // specific differences among Python 2 and Python 3, and saving and restoring various
+ // other pieces of state that can get mucked with during initialization.
+ InitializePythonRAII initialize_guard;
+
+ if (g_swig_init_callback)
+ g_swig_init_callback ();
+
+ // Update the path python uses to search for modules to include the current directory.
+
+ PyRun_SimpleString ("import sys");
+ AddToSysPath(AddLocation::End, ".");
+
+ FileSpec file_spec;
+ // Don't denormalize paths when calling file_spec.GetPath(). On platforms that use
+ // a backslash as the path separator, this will result in executing python code containing
+ // paths with unescaped backslashes. But Python also accepts forward slashes, so to make
+ // life easier we just use that.
+ if (HostInfo::GetLLDBPath(ePathTypePythonDir, file_spec))
+ AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
+ if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, file_spec))
+ AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
+
+ PyRun_SimpleString ("sys.dont_write_bytecode = 1; import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line");
+}
+
+void
+ScriptInterpreterPython::AddToSysPath(AddLocation location, std::string path)
+{
+ std::string path_copy;
+
+ std::string statement;
+ if (location == AddLocation::Beginning)
+ {
+ statement.assign("sys.path.insert(0,\"");
+ statement.append (path);
+ statement.append ("\")");
+ }
+ else
+ {
+ statement.assign("sys.path.append(\"");
+ statement.append(path);
+ statement.append("\")");
+ }
+ PyRun_SimpleString (statement.c_str());
+}
+
+
+//void
+//ScriptInterpreterPython::Terminate ()
+//{
+// // We are intentionally NOT calling Py_Finalize here (this would be the logical place to call it). Calling
+// // Py_Finalize here causes test suite runs to seg fault: The test suite runs in Python. It registers
+// // SBDebugger::Terminate to be called 'at_exit'. When the test suite Python harness finishes up, it calls
+// // Py_Finalize, which calls all the 'at_exit' registered functions. SBDebugger::Terminate calls Debugger::Terminate,
+// // which calls lldb::Terminate, which calls ScriptInterpreter::Terminate, which calls
+// // ScriptInterpreterPython::Terminate. So if we call Py_Finalize here, we end up with Py_Finalize being called from
+// // within Py_Finalize, which results in a seg fault.
+// //
+// // Since this function only gets called when lldb is shutting down and going away anyway, the fact that we don't
+// // actually call Py_Finalize should not cause any problems (everything should shut down/go away anyway when the
+// // process exits).
+// //
+//// Py_Finalize ();
+//}
+
+#endif // #ifdef LLDB_DISABLE_PYTHON
diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
new file mode 100644
index 000000000000..4c6eb3949898
--- /dev/null
+++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
@@ -0,0 +1,607 @@
+//===-- ScriptInterpreterPython.h -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHON_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHON_H
+
+#ifdef LLDB_DISABLE_PYTHON
+
+// Python is disabled in this build
+
+#else
+
+// C Includes
+// C++ Includes
+#include <memory>
+#include <string>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "PythonDataObjects.h"
+#include "lldb/Core/IOHandler.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Host/Terminal.h"
+
+class IOHandlerPythonInterpreter;
+
+namespace lldb_private {
+
+class ScriptInterpreterPython :
+ public ScriptInterpreter,
+ public IOHandlerDelegateMultiline
+{
+public:
+#if PY_MAJOR_VERSION >= 3
+ typedef PyObject*(*SWIGInitCallback) (void);
+#else
+ typedef void(*SWIGInitCallback) (void);
+#endif
+
+ typedef bool (*SWIGBreakpointCallbackFunction) (const char *python_function_name,
+ const char *session_dictionary_name,
+ const lldb::StackFrameSP& frame_sp,
+ const lldb::BreakpointLocationSP &bp_loc_sp);
+
+ typedef bool (*SWIGWatchpointCallbackFunction) (const char *python_function_name,
+ const char *session_dictionary_name,
+ const lldb::StackFrameSP& frame_sp,
+ const lldb::WatchpointSP &wp_sp);
+
+ typedef bool (*SWIGPythonTypeScriptCallbackFunction) (const char *python_function_name,
+ void *session_dictionary,
+ const lldb::ValueObjectSP& valobj_sp,
+ void** pyfunct_wrapper,
+ const lldb::TypeSummaryOptionsSP& options,
+ std::string& retval);
+
+ typedef void* (*SWIGPythonCreateSyntheticProvider) (const char *python_class_name,
+ const char *session_dictionary_name,
+ const lldb::ValueObjectSP& valobj_sp);
+
+ typedef void* (*SWIGPythonCreateCommandObject) (const char *python_class_name,
+ const char *session_dictionary_name,
+ const lldb::DebuggerSP debugger_sp);
+
+ typedef void* (*SWIGPythonCreateScriptedThreadPlan) (const char *python_class_name,
+ const char *session_dictionary_name,
+ const lldb::ThreadPlanSP& thread_plan_sp);
+
+ typedef bool (*SWIGPythonCallThreadPlan) (void *implementor, const char *method_name, Event *event_sp, bool &got_error);
+
+ typedef void* (*SWIGPythonCreateOSPlugin) (const char *python_class_name,
+ const char *session_dictionary_name,
+ const lldb::ProcessSP& process_sp);
+
+ typedef size_t (*SWIGPythonCalculateNumChildren) (void *implementor, uint32_t max);
+
+ typedef void* (*SWIGPythonGetChildAtIndex) (void *implementor, uint32_t idx);
+
+ typedef int (*SWIGPythonGetIndexOfChildWithName) (void *implementor, const char* child_name);
+
+ typedef void* (*SWIGPythonCastPyObjectToSBValue) (void* data);
+
+ typedef lldb::ValueObjectSP (*SWIGPythonGetValueObjectSPFromSBValue) (void* data);
+
+ typedef bool (*SWIGPythonUpdateSynthProviderInstance) (void* data);
+
+ typedef bool (*SWIGPythonMightHaveChildrenSynthProviderInstance) (void* data);
+
+ typedef void* (*SWIGPythonGetValueSynthProviderInstance) (void *implementor);
+
+ typedef bool (*SWIGPythonCallCommand) (const char *python_function_name,
+ const char *session_dictionary_name,
+ lldb::DebuggerSP& debugger,
+ const char* args,
+ lldb_private::CommandReturnObject& cmd_retobj,
+ lldb::ExecutionContextRefSP exe_ctx_ref_sp);
+
+ typedef bool (*SWIGPythonCallCommandObject) (void *implementor,
+ lldb::DebuggerSP& debugger,
+ const char* args,
+ lldb_private::CommandReturnObject& cmd_retobj,
+ lldb::ExecutionContextRefSP exe_ctx_ref_sp);
+
+ typedef bool (*SWIGPythonCallModuleInit) (const char *python_module_name,
+ const char *session_dictionary_name,
+ lldb::DebuggerSP& debugger);
+
+ typedef bool (*SWIGPythonScriptKeyword_Process) (const char* python_function_name,
+ const char* session_dictionary_name,
+ lldb::ProcessSP& process,
+ std::string& output);
+
+ typedef bool (*SWIGPythonScriptKeyword_Thread) (const char* python_function_name,
+ const char* session_dictionary_name,
+ lldb::ThreadSP& thread,
+ std::string& output);
+
+ typedef bool (*SWIGPythonScriptKeyword_Target) (const char* python_function_name,
+ const char* session_dictionary_name,
+ lldb::TargetSP& target,
+ std::string& output);
+
+ typedef bool (*SWIGPythonScriptKeyword_Frame) (const char* python_function_name,
+ const char* session_dictionary_name,
+ lldb::StackFrameSP& frame,
+ std::string& output);
+
+ typedef bool (*SWIGPythonScriptKeyword_Value) (const char* python_function_name,
+ const char* session_dictionary_name,
+ lldb::ValueObjectSP& value,
+ std::string& output);
+
+ typedef void* (*SWIGPython_GetDynamicSetting) (void* module,
+ const char* setting,
+ const lldb::TargetSP& target_sp);
+
+ friend class ::IOHandlerPythonInterpreter;
+
+ ScriptInterpreterPython (CommandInterpreter &interpreter);
+
+ ~ScriptInterpreterPython() override;
+
+ bool
+ Interrupt() override;
+
+ bool
+ ExecuteOneLine (const char *command,
+ CommandReturnObject *result,
+ const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
+
+ void
+ ExecuteInterpreterLoop () override;
+
+ bool
+ ExecuteOneLineWithReturn (const char *in_string,
+ ScriptInterpreter::ScriptReturnType return_type,
+ void *ret_value,
+ const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
+
+ lldb_private::Error
+ ExecuteMultipleLines (const char *in_string,
+ const ExecuteScriptOptions &options = ExecuteScriptOptions()) override;
+
+ Error
+ ExportFunctionDefinitionToInterpreter (StringList &function_def) override;
+
+ bool
+ GenerateTypeScriptFunction(StringList &input, std::string& output, const void* name_token = nullptr) override;
+
+ bool
+ GenerateTypeSynthClass(StringList &input, std::string& output, const void* name_token = nullptr) override;
+
+ bool
+ GenerateTypeSynthClass(const char* oneliner, std::string& output, const void* name_token = nullptr) override;
+
+ // use this if the function code is just a one-liner script
+ bool
+ GenerateTypeScriptFunction(const char* oneliner, std::string& output, const void* name_token = nullptr) override;
+
+ bool
+ GenerateScriptAliasFunction (StringList &input, std::string& output) override;
+
+ StructuredData::ObjectSP CreateSyntheticScriptedProvider(const char *class_name, lldb::ValueObjectSP valobj) override;
+
+ StructuredData::GenericSP CreateScriptCommandObject (const char *class_name) override;
+
+ StructuredData::ObjectSP CreateScriptedThreadPlan(const char *class_name, lldb::ThreadPlanSP thread_plan) override;
+
+ bool ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) override;
+
+ bool ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) override;
+
+ lldb::StateType ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp, bool &script_error) override;
+
+ StructuredData::GenericSP OSPlugin_CreatePluginObject(const char *class_name, lldb::ProcessSP process_sp) override;
+
+ StructuredData::DictionarySP OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp) override;
+
+ StructuredData::ArraySP OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp) override;
+
+ StructuredData::StringSP OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t thread_id) override;
+
+ StructuredData::DictionarySP OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid,
+ lldb::addr_t context) override;
+
+ StructuredData::ObjectSP LoadPluginModule(const FileSpec &file_spec, lldb_private::Error &error) override;
+
+ StructuredData::DictionarySP GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name,
+ lldb_private::Error &error) override;
+
+ size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor, uint32_t max) override;
+
+ lldb::ValueObjectSP GetChildAtIndex(const StructuredData::ObjectSP &implementor, uint32_t idx) override;
+
+ int GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor, const char *child_name) override;
+
+ bool UpdateSynthProviderInstance(const StructuredData::ObjectSP &implementor) override;
+
+ bool MightHaveChildrenSynthProviderInstance(const StructuredData::ObjectSP &implementor) override;
+
+ lldb::ValueObjectSP GetSyntheticValue(const StructuredData::ObjectSP &implementor) override;
+
+ bool
+ RunScriptBasedCommand(const char* impl_function,
+ const char* args,
+ ScriptedCommandSynchronicity synchronicity,
+ lldb_private::CommandReturnObject& cmd_retobj,
+ Error& error,
+ const lldb_private::ExecutionContext& exe_ctx) override;
+
+ bool
+ RunScriptBasedCommand (StructuredData::GenericSP impl_obj_sp,
+ const char* args,
+ ScriptedCommandSynchronicity synchronicity,
+ lldb_private::CommandReturnObject& cmd_retobj,
+ Error& error,
+ const lldb_private::ExecutionContext& exe_ctx) override;
+
+ Error
+ GenerateFunction(const char *signature, const StringList &input) override;
+
+ Error
+ GenerateBreakpointCommandCallbackData (StringList &input, std::string& output) override;
+
+ bool
+ GenerateWatchpointCommandCallbackData (StringList &input, std::string& output) override;
+
+// static size_t
+// GenerateBreakpointOptionsCommandCallback (void *baton,
+// InputReader &reader,
+// lldb::InputReaderAction notification,
+// const char *bytes,
+// size_t bytes_len);
+//
+// static size_t
+// GenerateWatchpointOptionsCommandCallback (void *baton,
+// InputReader &reader,
+// lldb::InputReaderAction notification,
+// const char *bytes,
+// size_t bytes_len);
+
+ static bool
+ BreakpointCallbackFunction (void *baton,
+ StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+
+ static bool
+ WatchpointCallbackFunction (void *baton,
+ StoppointCallbackContext *context,
+ lldb::user_id_t watch_id);
+
+ bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj, StructuredData::ObjectSP &callee_wrapper_sp,
+ const TypeSummaryOptions &options, std::string &retval) override;
+
+ void
+ Clear () override;
+
+ bool
+ GetDocumentationForItem (const char* item, std::string& dest) override;
+
+ bool
+ GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, std::string& dest) override;
+
+ uint32_t
+ GetFlagsForCommandObject (StructuredData::GenericSP cmd_obj_sp) override;
+
+ bool
+ GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, std::string& dest) override;
+
+ bool
+ CheckObjectExists (const char* name) override
+ {
+ if (!name || !name[0])
+ return false;
+ std::string temp;
+ return GetDocumentationForItem (name,temp);
+ }
+
+ bool
+ RunScriptFormatKeyword (const char* impl_function,
+ Process* process,
+ std::string& output,
+ Error& error) override;
+
+ bool
+ RunScriptFormatKeyword (const char* impl_function,
+ Thread* thread,
+ std::string& output,
+ Error& error) override;
+
+ bool
+ RunScriptFormatKeyword (const char* impl_function,
+ Target* target,
+ std::string& output,
+ Error& error) override;
+
+ bool
+ RunScriptFormatKeyword (const char* impl_function,
+ StackFrame* frame,
+ std::string& output,
+ Error& error) override;
+
+ bool
+ RunScriptFormatKeyword (const char* impl_function,
+ ValueObject* value,
+ std::string& output,
+ Error& error) override;
+
+ bool LoadScriptingModule(const char *filename, bool can_reload, bool init_session, lldb_private::Error &error,
+ StructuredData::ObjectSP *module_sp = nullptr) override;
+
+ bool
+ IsReservedWord (const char* word) override;
+
+ std::unique_ptr<ScriptInterpreterLocker>
+ AcquireInterpreterLock () override;
+
+ void
+ CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
+ CommandReturnObject &result) override;
+
+ void
+ CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options,
+ CommandReturnObject &result) override;
+
+ /// Set the callback body text into the callback for the breakpoint.
+ Error
+ SetBreakpointCommandCallback (BreakpointOptions *bp_options,
+ const char *callback_body) override;
+
+ void
+ SetBreakpointCommandCallbackFunction (BreakpointOptions *bp_options,
+ const char *function_name) override;
+
+ /// Set a one-liner as the callback for the watchpoint.
+ void
+ SetWatchpointCommandCallback (WatchpointOptions *wp_options,
+ const char *oneliner) override;
+
+ StringList
+ ReadCommandInputFromUser (FILE *in_file);
+
+ void ResetOutputFileHandle(FILE *new_fh) override;
+
+ static void
+ InitializePrivate ();
+
+ static void
+ InitializeInterpreter (SWIGInitCallback python_swig_init_callback,
+ SWIGBreakpointCallbackFunction swig_breakpoint_callback,
+ SWIGWatchpointCallbackFunction swig_watchpoint_callback,
+ SWIGPythonTypeScriptCallbackFunction swig_typescript_callback,
+ SWIGPythonCreateSyntheticProvider swig_synthetic_script,
+ SWIGPythonCreateCommandObject swig_create_cmd,
+ SWIGPythonCalculateNumChildren swig_calc_children,
+ SWIGPythonGetChildAtIndex swig_get_child_index,
+ SWIGPythonGetIndexOfChildWithName swig_get_index_child,
+ SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue ,
+ SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,
+ SWIGPythonUpdateSynthProviderInstance swig_update_provider,
+ SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider,
+ SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider,
+ SWIGPythonCallCommand swig_call_command,
+ SWIGPythonCallCommandObject swig_call_command_object,
+ SWIGPythonCallModuleInit swig_call_module_init,
+ SWIGPythonCreateOSPlugin swig_create_os_plugin,
+ SWIGPythonScriptKeyword_Process swig_run_script_keyword_process,
+ SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
+ SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
+ SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
+ SWIGPythonScriptKeyword_Value swig_run_script_keyword_value,
+ SWIGPython_GetDynamicSetting swig_plugin_get,
+ SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
+ SWIGPythonCallThreadPlan swig_call_thread_plan);
+
+ const char *
+ GetDictionaryName ()
+ {
+ return m_dictionary_name.c_str();
+ }
+
+ PyThreadState *
+ GetThreadState()
+ {
+ return m_command_thread_state;
+ }
+
+ void
+ SetThreadState (PyThreadState *s)
+ {
+ if (s)
+ m_command_thread_state = s;
+ }
+
+ //----------------------------------------------------------------------
+ // IOHandlerDelegate
+ //----------------------------------------------------------------------
+ void
+ IOHandlerActivated (IOHandler &io_handler) override;
+
+ void
+ IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override;
+
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void
+ Initialize();
+
+ static void
+ Terminate();
+
+ static lldb::ScriptInterpreterSP
+ CreateInstance(CommandInterpreter &interpreter);
+
+ static lldb_private::ConstString
+ GetPluginNameStatic();
+
+ static const char *
+ GetPluginDescriptionStatic();
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ lldb_private::ConstString
+ GetPluginName() override;
+
+ uint32_t
+ GetPluginVersion() override;
+
+ class Locker : public ScriptInterpreterLocker
+ {
+ public:
+ enum OnEntry
+ {
+ AcquireLock = 0x0001,
+ InitSession = 0x0002,
+ InitGlobals = 0x0004,
+ NoSTDIN = 0x0008
+ };
+
+ enum OnLeave
+ {
+ FreeLock = 0x0001,
+ FreeAcquiredLock = 0x0002, // do not free the lock if we already held it when calling constructor
+ TearDownSession = 0x0004
+ };
+
+ Locker(ScriptInterpreterPython *py_interpreter = nullptr,
+ uint16_t on_entry = AcquireLock | InitSession,
+ uint16_t on_leave = FreeLock | TearDownSession,
+ FILE *in = nullptr,
+ FILE *out = nullptr,
+ FILE *err = nullptr);
+
+ ~Locker () override;
+
+ private:
+ bool
+ DoAcquireLock ();
+
+ bool
+ DoInitSession (uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err);
+
+ bool
+ DoFreeLock ();
+
+ bool
+ DoTearDownSession ();
+
+ static void
+ ReleasePythonLock ();
+
+ bool m_teardown_session;
+ ScriptInterpreterPython *m_python_interpreter;
+// FILE* m_tmp_fh;
+ PyGILState_STATE m_GILState;
+ };
+
+protected:
+ class SynchronicityHandler
+ {
+ private:
+ lldb::DebuggerSP m_debugger_sp;
+ ScriptedCommandSynchronicity m_synch_wanted;
+ bool m_old_asynch;
+
+ public:
+ SynchronicityHandler(lldb::DebuggerSP,
+ ScriptedCommandSynchronicity);
+
+ ~SynchronicityHandler();
+ };
+
+ enum class AddLocation
+ {
+ Beginning,
+ End
+ };
+
+ static void AddToSysPath(AddLocation location, std::string path);
+
+ bool
+ EnterSession(uint16_t on_entry_flags,
+ FILE *in,
+ FILE *out,
+ FILE *err);
+
+ void
+ LeaveSession();
+
+ void
+ SaveTerminalState(int fd);
+
+ void
+ RestoreTerminalState();
+
+ uint32_t
+ IsExecutingPython () const
+ {
+ return m_lock_count > 0;
+ }
+
+ uint32_t
+ IncrementLockCount()
+ {
+ return ++m_lock_count;
+ }
+
+ uint32_t
+ DecrementLockCount()
+ {
+ if (m_lock_count > 0)
+ --m_lock_count;
+ return m_lock_count;
+ }
+
+ enum ActiveIOHandler {
+ eIOHandlerNone,
+ eIOHandlerBreakpoint,
+ eIOHandlerWatchpoint
+ };
+
+ PythonObject &GetMainModule();
+
+ PythonDictionary &
+ GetSessionDictionary ();
+
+ PythonDictionary &
+ GetSysModuleDictionary ();
+
+ bool
+ GetEmbeddedInterpreterModuleObjects ();
+
+ PythonFile m_saved_stdin;
+ PythonFile m_saved_stdout;
+ PythonFile m_saved_stderr;
+ PythonObject m_main_module;
+ PythonObject m_lldb_module;
+ PythonDictionary m_session_dict;
+ PythonDictionary m_sys_module_dict;
+ PythonObject m_run_one_line_function;
+ PythonObject m_run_one_line_str_global;
+ std::string m_dictionary_name;
+ TerminalState m_terminal_state;
+ ActiveIOHandler m_active_io_handler;
+ bool m_session_is_active;
+ bool m_pty_slave_is_open;
+ bool m_valid_session;
+ uint32_t m_lock_count;
+ PyThreadState *m_command_thread_state;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_DISABLE_PYTHON
+
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTINTERPRETERPYTHON_H
diff --git a/source/Plugins/ScriptInterpreter/Python/lldb-python.h b/source/Plugins/ScriptInterpreter/Python/lldb-python.h
new file mode 100644
index 000000000000..013492c39bf8
--- /dev/null
+++ b/source/Plugins/ScriptInterpreter/Python/lldb-python.h
@@ -0,0 +1,31 @@
+//===-- lldb-python.h --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_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 defined(__linux__)
+// features.h will define _POSIX_C_SOURCE if _GNU_SOURCE is defined. This value
+// may be different from the value that Python defines it to be which results
+// in a warning. Undefine _POSIX_C_SOURCE before including Python.h The same
+// holds for _XOPEN_SOURCE.
+#undef _POSIX_C_SOURCE
+#undef _XOPEN_SOURCE
+#endif
+
+// Include python for non windows machines
+#include <Python.h>
+#endif // LLDB_DISABLE_PYTHON
+
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_LLDB_PYTHON_H
diff --git a/source/Plugins/SymbolFile/DWARF/DIERef.cpp b/source/Plugins/SymbolFile/DWARF/DIERef.cpp
new file mode 100644
index 000000000000..c0754a1fdd54
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DIERef.cpp
@@ -0,0 +1,56 @@
+//===-- DIERef.cpp ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DIERef.h"
+#include "DWARFCompileUnit.h"
+#include "DWARFFormValue.h"
+
+DIERef::DIERef() :
+ cu_offset(DW_INVALID_OFFSET),
+ die_offset(DW_INVALID_OFFSET)
+{}
+
+DIERef::DIERef(dw_offset_t d) :
+ cu_offset(DW_INVALID_OFFSET),
+ die_offset(d)
+{}
+
+DIERef::DIERef(dw_offset_t c, dw_offset_t d) :
+ cu_offset(c),
+ die_offset(d)
+{}
+
+DIERef::DIERef(lldb::user_id_t uid) :
+ cu_offset(uid>>32),
+ die_offset(uid&0xffffffff)
+{}
+
+DIERef::DIERef(const DWARFFormValue& form_value) :
+ cu_offset(DW_INVALID_OFFSET),
+ die_offset(DW_INVALID_OFFSET)
+{
+ if (form_value.IsValid())
+ {
+ const DWARFCompileUnit* dwarf_cu = form_value.GetCompileUnit();
+ if (dwarf_cu)
+ {
+ if (dwarf_cu->GetBaseObjOffset() != DW_INVALID_OFFSET)
+ cu_offset = dwarf_cu->GetBaseObjOffset();
+ else
+ cu_offset = dwarf_cu->GetOffset();
+ }
+ die_offset = form_value.Reference();
+ }
+}
+
+lldb::user_id_t
+DIERef::GetUID() const
+{
+ return ((lldb::user_id_t)cu_offset) << 32 | die_offset;
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DIERef.h b/source/Plugins/SymbolFile/DWARF/DIERef.h
new file mode 100644
index 000000000000..a5484db6bd6c
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DIERef.h
@@ -0,0 +1,42 @@
+//===-- DIERef.h ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DIERef_h_
+#define SymbolFileDWARF_DIERef_h_
+
+#include "lldb/Core/dwarf.h"
+#include "lldb/lldb-defines.h"
+
+class DWARFFormValue;
+
+struct DIERef
+{
+ DIERef();
+
+ explicit
+ DIERef(dw_offset_t d);
+
+ DIERef(dw_offset_t c, dw_offset_t d);
+
+ explicit
+ DIERef(lldb::user_id_t uid);
+
+ explicit
+ DIERef(const DWARFFormValue& form_value);
+
+ lldb::user_id_t
+ GetUID() const;
+
+ dw_offset_t cu_offset;
+ dw_offset_t die_offset;
+};
+
+typedef std::vector<DIERef> DIEArray;
+
+#endif // SymbolFileDWARF_DIERef_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
new file mode 100644
index 000000000000..ab20844bfcfd
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
@@ -0,0 +1,65 @@
+//===-- DWARFASTParser.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFASTParser_h_
+#define SymbolFileDWARF_DWARFASTParser_h_
+
+#include "DWARFDefines.h"
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/Symbol/CompilerDecl.h"
+#include "lldb/Symbol/CompilerDeclContext.h"
+
+class DWARFDIE;
+
+class DWARFASTParser
+{
+public:
+ virtual ~DWARFASTParser() {}
+
+ virtual lldb::TypeSP
+ ParseTypeFromDWARF (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &die,
+ lldb_private::Log *log,
+ bool *type_is_new_ptr) = 0;
+
+ virtual lldb_private::Function *
+ ParseFunctionFromDWARF (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &die) = 0;
+
+ virtual bool
+ CanCompleteType (const lldb_private::CompilerType &compiler_type)
+ {
+ return false;
+ }
+
+ virtual bool
+ CompleteType (const lldb_private::CompilerType &compiler_type)
+ {
+ return false;
+ }
+
+ virtual bool
+ CompleteTypeFromDWARF (const DWARFDIE &die,
+ lldb_private::Type *type,
+ lldb_private::CompilerType &compiler_type) = 0;
+
+ virtual lldb_private::CompilerDecl
+ GetDeclForUIDFromDWARF (const DWARFDIE &die) = 0;
+
+ virtual lldb_private::CompilerDeclContext
+ GetDeclContextForUIDFromDWARF (const DWARFDIE &die) = 0;
+
+ virtual lldb_private::CompilerDeclContext
+ GetDeclContextContainingUIDFromDWARF (const DWARFDIE &die) = 0;
+
+ virtual std::vector<DWARFDIE>
+ GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) = 0;
+};
+
+#endif // SymbolFileDWARF_DWARFASTParser_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
new file mode 100644
index 000000000000..68a0285b69df
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -0,0 +1,4034 @@
+//===-- DWARFASTParserClang.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFASTParserClang.h"
+#include "DWARFCompileUnit.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFDeclContext.h"
+#include "DWARFDefines.h"
+#include "DWARFDIE.h"
+#include "DWARFDIECollection.h"
+#include "SymbolFileDWARF.h"
+#include "SymbolFileDWARFDebugMap.h"
+#include "UniqueDWARFASTType.h"
+
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Symbol/ClangASTImporter.h"
+#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/TypeMap.h"
+#include "lldb/Target/Language.h"
+#include "Plugins/Language/ObjC/ObjCLanguage.h"
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+
+#include <map>
+#include <vector>
+
+//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
+
+#ifdef ENABLE_DEBUG_PRINTF
+#include <stdio.h>
+#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
+#else
+#define DEBUG_PRINTF(fmt, ...)
+#endif
+
+
+using namespace lldb;
+using namespace lldb_private;
+DWARFASTParserClang::DWARFASTParserClang (ClangASTContext &ast) :
+ m_ast (ast),
+ m_die_to_decl_ctx (),
+ m_decl_ctx_to_die ()
+{
+}
+
+DWARFASTParserClang::~DWARFASTParserClang ()
+{
+}
+
+
+static AccessType
+DW_ACCESS_to_AccessType (uint32_t dwarf_accessibility)
+{
+ switch (dwarf_accessibility)
+ {
+ case DW_ACCESS_public: return eAccessPublic;
+ case DW_ACCESS_private: return eAccessPrivate;
+ case DW_ACCESS_protected: return eAccessProtected;
+ default: break;
+ }
+ return eAccessNone;
+}
+
+static bool
+DeclKindIsCXXClass (clang::Decl::Kind decl_kind)
+{
+ switch (decl_kind)
+ {
+ case clang::Decl::CXXRecord:
+ case clang::Decl::ClassTemplateSpecialization:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+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 ()
+ {
+ return (bit_size != LLDB_INVALID_ADDRESS) &&
+ (bit_offset != LLDB_INVALID_ADDRESS);
+ }
+};
+
+
+ClangASTImporter &
+DWARFASTParserClang::GetClangASTImporter()
+{
+ if (!m_clang_ast_importer_ap)
+ {
+ m_clang_ast_importer_ap.reset (new ClangASTImporter);
+ }
+ return *m_clang_ast_importer_ap;
+}
+
+
+TypeSP
+DWARFASTParserClang::ParseTypeFromDWO (const DWARFDIE &die, Log *log)
+{
+ ModuleSP dwo_module_sp = die.GetContainingDWOModule();
+ if (dwo_module_sp)
+ {
+ // This type comes from an external DWO module
+ std::vector<CompilerContext> dwo_context;
+ die.GetDWOContext(dwo_context);
+ TypeMap dwo_types;
+ if (dwo_module_sp->GetSymbolVendor()->FindTypes(dwo_context, true, dwo_types))
+ {
+ const size_t num_dwo_types = dwo_types.GetSize();
+ if (num_dwo_types == 1)
+ {
+ // 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
+ TypeSP dwo_type_sp = dwo_types.GetTypeAtIndex(0);
+ if (dwo_type_sp)
+ {
+ lldb_private::CompilerType dwo_type = dwo_type_sp->GetForwardCompilerType();
+
+ lldb_private::CompilerType type = GetClangASTImporter().CopyType (m_ast, dwo_type);
+
+ //printf ("copied_qual_type: ast = %p, clang_type = %p, name = '%s'\n", m_ast, copied_qual_type.getAsOpaquePtr(), external_type->GetName().GetCString());
+ if (type)
+ {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ TypeSP type_sp (new Type (die.GetID(),
+ dwarf,
+ dwo_type_sp->GetName(),
+ dwo_type_sp->GetByteSize(),
+ NULL,
+ LLDB_INVALID_UID,
+ Type::eEncodingInvalid,
+ &dwo_type_sp->GetDeclaration(),
+ type,
+ Type::eResolveStateForward));
+
+ dwarf->GetTypeList()->Insert(type_sp);
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+ clang::TagDecl *tag_decl = ClangASTContext::GetAsTagDecl(type);
+ if (tag_decl)
+ LinkDeclContextToDIE(tag_decl, die);
+ else
+ {
+ clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(die);
+ if (defn_decl_ctx)
+ LinkDeclContextToDIE(defn_decl_ctx, die);
+ }
+ return type_sp;
+ }
+ }
+ }
+ }
+ }
+ return TypeSP();
+}
+
+TypeSP
+DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc,
+ const DWARFDIE &die,
+ Log *log,
+ bool *type_is_new_ptr)
+{
+ TypeSP type_sp;
+
+ if (type_is_new_ptr)
+ *type_is_new_ptr = false;
+
+ AccessType accessibility = eAccessNone;
+ if (die)
+ {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ if (log)
+ {
+ DWARFDIE context_die;
+ clang::DeclContext *context = GetClangDeclContextContainingDIE (die, &context_die);
+
+ dwarf->GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (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());
+
+ }
+ //
+ // Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
+ // if (log && dwarf_cu)
+ // {
+ // StreamString s;
+ // die->DumpLocation (this, dwarf_cu, s);
+ // dwarf->GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDwarf::%s %s", __FUNCTION__, s.GetData());
+ //
+ // }
+
+ Type *type_ptr = dwarf->GetDIEToType().lookup (die.GetDIE());
+ TypeList* type_list = dwarf->GetTypeList();
+ if (type_ptr == NULL)
+ {
+ if (type_is_new_ptr)
+ *type_is_new_ptr = true;
+
+ const dw_tag_t tag = die.Tag();
+
+ bool is_forward_declaration = false;
+ DWARFAttributes attributes;
+ const char *type_name_cstr = NULL;
+ ConstString type_name_const_str;
+ Type::ResolveState resolve_state = Type::eResolveStateUnresolved;
+ uint64_t byte_size = 0;
+ Declaration decl;
+
+ Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
+ CompilerType clang_type;
+ DWARFFormValue form_value;
+
+ dw_attr_t attr;
+
+ switch (tag)
+ {
+ case DW_TAG_base_type:
+ case DW_TAG_pointer_type:
+ case DW_TAG_reference_type:
+ case DW_TAG_rvalue_reference_type:
+ case DW_TAG_typedef:
+ case DW_TAG_const_type:
+ case DW_TAG_restrict_type:
+ case DW_TAG_volatile_type:
+ case DW_TAG_unspecified_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
+
+ const size_t num_attributes = die.GetAttributes (attributes);
+ uint32_t encoding = 0;
+ lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
+
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i=0; i<num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+ case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
+ case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+ case DW_AT_name:
+
+ type_name_cstr = form_value.AsCString();
+ // Work around a bug in llvm-gcc where they give a name to a reference type which doesn't
+ // include the "&"...
+ if (tag == DW_TAG_reference_type)
+ {
+ if (strchr (type_name_cstr, '&') == NULL)
+ type_name_cstr = NULL;
+ }
+ if (type_name_cstr)
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+ case DW_AT_byte_size: byte_size = form_value.Unsigned(); break;
+ case DW_AT_encoding: encoding = form_value.Unsigned(); break;
+ case DW_AT_type: encoding_uid = DIERef(form_value).GetUID(); break;
+ default:
+ case DW_AT_sibling:
+ 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);
+
+ switch (tag)
+ {
+ default:
+ break;
+
+ case DW_TAG_unspecified_type:
+ if (strcmp(type_name_cstr, "nullptr_t") == 0 ||
+ strcmp(type_name_cstr, "decltype(nullptr)") == 0 )
+ {
+ 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...
+
+ case DW_TAG_base_type:
+ resolve_state = Type::eResolveStateFull;
+ clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize (type_name_cstr,
+ encoding,
+ byte_size * 8);
+ 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;
+ }
+
+ if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID || encoding_data_type == Type::eEncodingIsTypedefUID) && sc.comp_unit != NULL)
+ {
+ bool translation_unit_is_objc = (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus);
+
+ if (translation_unit_is_objc)
+ {
+ if (type_name_cstr != NULL)
+ {
+ 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 (type_name_const_str == 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;
+ encoding_uid = LLDB_INVALID_UID;
+ resolve_state = Type::eResolveStateFull;
+
+ }
+ else if (type_name_const_str == g_objc_type_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;
+ encoding_uid = LLDB_INVALID_UID;
+ resolve_state = Type::eResolveStateFull;
+ }
+ else if (type_name_const_str == 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);
+ encoding_data_type = Type::eEncodingIsUID;
+ encoding_uid = LLDB_INVALID_UID;
+ resolve_state = Type::eResolveStateFull;
+ }
+ }
+ else if (encoding_data_type == Type::eEncodingIsPointerUID && encoding_uid != LLDB_INVALID_UID)
+ {
+ // Clang sometimes erroneously emits id as objc_object*. In that case we fix up the type to "id".
+
+ const DWARFDIE encoding_die = die.GetDIE(encoding_uid);
+
+ 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;
+ encoding_uid = LLDB_INVALID_UID;
+ resolve_state = Type::eResolveStateFull;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ type_sp.reset( new Type (die.GetID(),
+ dwarf,
+ type_name_const_str,
+ byte_size,
+ NULL,
+ encoding_uid,
+ encoding_data_type,
+ &decl,
+ clang_type,
+ resolve_state));
+
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+
+ // Type* encoding_type = GetUniquedTypeForDIEOffset(encoding_uid, type_sp, NULL, 0, 0, false);
+ // if (encoding_type != NULL)
+ // {
+ // if (encoding_type != DIE_IS_BEING_PARSED)
+ // type_sp->SetEncodingType(encoding_type);
+ // else
+ // m_indirect_fixups.push_back(type_sp.get());
+ // }
+ }
+ break;
+
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_class_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
+ bool byte_size_valid = false;
+
+ LanguageType class_language = eLanguageTypeUnknown;
+ bool is_complete_objc_class = false;
+ //bool struct_is_class = false;
+ const size_t num_attributes = die.GetAttributes (attributes);
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i=0; i<num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_decl_file:
+ if (die.GetCU()->DW_AT_decl_file_attributes_are_invalid())
+ {
+ // llvm-gcc outputs invalid DW_AT_decl_file attributes that always
+ // point to the compile unit file, so we clear this invalid value
+ // so that we can still unique types efficiently.
+ decl.SetFile(FileSpec ("<invalid>", false));
+ }
+ else
+ decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned()));
+ break;
+
+ case DW_AT_decl_line:
+ decl.SetLine(form_value.Unsigned());
+ break;
+
+ case DW_AT_decl_column:
+ decl.SetColumn(form_value.Unsigned());
+ break;
+
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+
+ case DW_AT_byte_size:
+ byte_size = form_value.Unsigned();
+ byte_size_valid = true;
+ break;
+
+ case DW_AT_accessibility:
+ accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());
+ break;
+
+ case DW_AT_declaration:
+ is_forward_declaration = form_value.Boolean();
+ break;
+
+ case DW_AT_APPLE_runtime_class:
+ class_language = (LanguageType)form_value.Signed();
+ break;
+
+ case DW_AT_APPLE_objc_complete_type:
+ is_complete_objc_class = form_value.Signed();
+ break;
+
+ case DW_AT_allocated:
+ case DW_AT_associated:
+ case DW_AT_data_location:
+ case DW_AT_description:
+ case DW_AT_start_scope:
+ case DW_AT_visibility:
+ default:
+ case DW_AT_sibling:
+ break;
+ }
+ }
+ }
+ }
+
+ // UniqueDWARFASTType is large, so don't create a local variables on the
+ // stack, put it on the heap. This function is often called recursively
+ // and clang isn't good and sharing the stack space for variables in different blocks.
+ std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(new UniqueDWARFASTType());
+
+ if (type_name_const_str)
+ {
+ LanguageType die_language = die.GetLanguage();
+ bool handled = false;
+ if (Language::LanguageIsCPlusPlus(die_language))
+ {
+ std::string qualified_name;
+ if (die.GetQualifiedName(qualified_name))
+ {
+ handled = true;
+ ConstString const_qualified_name(qualified_name);
+ if (dwarf->GetUniqueDWARFASTTypeMap().Find(const_qualified_name, die, Declaration(),
+ byte_size_valid ? byte_size : -1,
+ *unique_ast_entry_ap))
+ {
+ type_sp = unique_ast_entry_ap->m_type_sp;
+ if (type_sp)
+ {
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+ return type_sp;
+ }
+ }
+ }
+ }
+
+ if (!handled)
+ {
+ if (dwarf->GetUniqueDWARFASTTypeMap().Find(type_name_const_str, die, decl,
+ byte_size_valid ? byte_size : -1,
+ *unique_ast_entry_ap))
+ {
+ type_sp = unique_ast_entry_ap->m_type_sp;
+ if (type_sp)
+ {
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+ return type_sp;
+ }
+ }
+ }
+ }
+
+ DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr);
+
+ 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;
+ }
+
+ if (byte_size_valid && byte_size == 0 && type_name_cstr &&
+ die.HasChildren() == false &&
+ sc.comp_unit->GetLanguage() == eLanguageTypeObjC)
+ {
+ // Work around an issue with clang at the moment where
+ // forward declarations for objective C classes are emitted
+ // as:
+ // DW_TAG_structure_type [2]
+ // DW_AT_name( "ForwardObjcClass" )
+ // DW_AT_byte_size( 0x00 )
+ // DW_AT_decl_file( "..." )
+ // DW_AT_decl_line( 1 )
+ //
+ // Note that there is no DW_AT_declaration and there are
+ // no children, and the byte size is zero.
+ is_forward_declaration = true;
+ }
+
+ if (class_language == eLanguageTypeObjC ||
+ class_language == eLanguageTypeObjC_plus_plus)
+ {
+ if (!is_complete_objc_class && die.Supports_DW_AT_APPLE_objc_complete_type())
+ {
+ // We have a valid eSymbolTypeObjCClass class symbol whose
+ // name matches the current objective C class that we
+ // are trying to find and this DIE isn't the complete
+ // definition (we checked is_complete_objc_class above and
+ // know it is false), so the real definition is in here somewhere
+ type_sp = dwarf->FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true);
+
+ 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->FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true);
+ }
+ }
+
+ if (type_sp)
+ {
+ if (log)
+ {
+ dwarf->GetObjectFile()->GetModule()->LogMessage (log,
+ "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an incomplete objc type, complete type is 0x%8.8" PRIx64,
+ static_cast<void*>(this),
+ die.GetOffset(),
+ DW_TAG_value_to_name(tag),
+ type_name_cstr,
+ type_sp->GetID());
+ }
+
+ // 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();
+ return type_sp;
+ }
+ }
+ }
+
+
+ if (is_forward_declaration)
+ {
+ // We have a forward declaration to a type and we need
+ // to try and find a full declaration. We look in the
+ // current type index just in case we have a forward
+ // declaration followed by an actual declarations in the
+ // DWARF. If this fails, we need to look elsewhere...
+ if (log)
+ {
+ dwarf->GetObjectFile()->GetModule()->LogMessage (log,
+ "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, trying to find complete type",
+ static_cast<void*>(this),
+ die.GetOffset(),
+ DW_TAG_value_to_name(tag),
+ type_name_cstr);
+ }
+
+ // See if the type comes from a DWO module and if so, track down that type.
+ type_sp = ParseTypeFromDWO(die, log);
+ if (type_sp)
+ return type_sp;
+
+ DWARFDeclContext die_decl_ctx;
+ die.GetDWARFDeclContext(die_decl_ctx);
+
+ //type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, type_name_const_str);
+ 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);
+ }
+ }
+
+ 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),
+ type_name_cstr,
+ type_sp->GetID());
+ }
+
+ // 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->DebugInfo()->GetDIE(DIERef(type_sp->GetID())));
+ if (defn_decl_ctx)
+ LinkDeclContextToDIE(defn_decl_ctx, die);
+ return type_sp;
+ }
+ }
+ assert (tag_decl_kind != -1);
+ bool clang_type_was_created = false;
+ clang_type.SetCompilerType(&m_ast, dwarf->GetForwardDeclDieToClangType().lookup (die.GetDIE()));
+ if (!clang_type)
+ {
+ clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE (die, nullptr);
+ if (accessibility == eAccessNone && decl_ctx)
+ {
+ // Check the decl context that contains this class/struct/union.
+ // If it is a class we must give it an accessibility.
+ const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind();
+ if (DeclKindIsCXXClass (containing_decl_kind))
+ accessibility = default_accessibility;
+ }
+
+ ClangASTMetadata metadata;
+ metadata.SetUserID(die.GetID());
+ metadata.SetIsDynamicCXXType(dwarf->ClassOrStructIsVirtual (die));
+
+ if (type_name_cstr && strchr (type_name_cstr, '<'))
+ {
+ ClangASTContext::TemplateParameterInfos template_param_infos;
+ if (ParseTemplateParameterInfos (die, template_param_infos))
+ {
+ clang::ClassTemplateDecl *class_template_decl = m_ast.ParseClassTemplateDecl (decl_ctx,
+ accessibility,
+ type_name_cstr,
+ tag_decl_kind,
+ template_param_infos);
+
+ clang::ClassTemplateSpecializationDecl *class_specialization_decl = m_ast.CreateClassTemplateSpecializationDecl (decl_ctx,
+ class_template_decl,
+ tag_decl_kind,
+ template_param_infos);
+ clang_type = m_ast.CreateClassTemplateSpecializationType (class_specialization_decl);
+ clang_type_was_created = true;
+
+ m_ast.SetMetadata (class_template_decl, metadata);
+ m_ast.SetMetadata (class_specialization_decl, metadata);
+ }
+ }
+
+ if (!clang_type_was_created)
+ {
+ clang_type_was_created = true;
+ clang_type = m_ast.CreateRecordType (decl_ctx,
+ accessibility,
+ type_name_cstr,
+ tag_decl_kind,
+ class_language,
+ &metadata);
+ }
+ }
+
+ // Store a forward declaration to this class type in case any
+ // parameters in any class methods need it for the clang
+ // types for function prototypes.
+ LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die);
+ type_sp.reset (new Type (die.GetID(),
+ dwarf,
+ type_name_const_str,
+ byte_size,
+ NULL,
+ LLDB_INVALID_UID,
+ Type::eEncodingIsUID,
+ &decl,
+ clang_type,
+ Type::eResolveStateForward));
+
+ type_sp->SetIsCompleteObjCClass(is_complete_objc_class);
+
+
+ // Add our type to the unique type map so we don't
+ // end up creating many copies of the same type over
+ // and over in the ASTContext for our module
+ unique_ast_entry_ap->m_type_sp = type_sp;
+ unique_ast_entry_ap->m_die = die;
+ unique_ast_entry_ap->m_declaration = decl;
+ unique_ast_entry_ap->m_byte_size = byte_size;
+ dwarf->GetUniqueDWARFASTTypeMap().Insert (type_name_const_str,
+ *unique_ast_entry_ap);
+
+ if (is_forward_declaration && die.HasChildren())
+ {
+ // Check to see if the DIE actually has a definition, some version of GCC will
+ // emit DIEs with DW_AT_declaration set to true, but yet still have subprogram,
+ // members, or inheritance, so we can't trust it
+ DWARFDIE child_die = die.GetFirstChild();
+ while (child_die)
+ {
+ switch (child_die.Tag())
+ {
+ case DW_TAG_inheritance:
+ case DW_TAG_subprogram:
+ case DW_TAG_member:
+ case DW_TAG_APPLE_property:
+ case DW_TAG_class_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_typedef:
+ case DW_TAG_union_type:
+ child_die.Clear();
+ is_forward_declaration = false;
+ break;
+ default:
+ child_die = child_die.GetSibling();
+ break;
+ }
+ }
+ }
+
+ if (!is_forward_declaration)
+ {
+ // Always start the definition for a class type so that
+ // if the class has child classes or types that require
+ // the class to be created for use as their decl contexts
+ // the class will be ready to accept these child definitions.
+ if (die.HasChildren() == false)
+ {
+ // No children for this struct/union/class, lets finish it
+ ClangASTContext::StartTagDeclarationDefinition (clang_type);
+ ClangASTContext::CompleteTagDeclarationDefinition (clang_type);
+
+ if (tag == DW_TAG_structure_type) // this only applies in C
+ {
+ clang::RecordDecl *record_decl = ClangASTContext::GetAsRecordDecl(clang_type);
+
+ if (record_decl)
+ m_record_decl_to_layout_map.insert(std::make_pair(record_decl, LayoutInfo()));
+ }
+ }
+ else if (clang_type_was_created)
+ {
+ // Start the definition if the class is not objective C since
+ // the underlying decls respond to isCompleteDefinition(). Objective
+ // C decls don't respond to isCompleteDefinition() so we can't
+ // start the declaration definition right away. For C++ class/union/structs
+ // we want to start the definition in case the class is needed as the
+ // declaration context for a contained class or type without the need
+ // to complete that type..
+
+ if (class_language != eLanguageTypeObjC &&
+ class_language != eLanguageTypeObjC_plus_plus)
+ ClangASTContext::StartTagDeclarationDefinition (clang_type);
+
+ // Leave this as a forward declaration until we need
+ // to know the details of the type. lldb_private::Type
+ // will automatically call the SymbolFile virtual function
+ // "SymbolFileDWARF::CompleteType(Type *)"
+ // When the definition needs to be defined.
+ assert(!dwarf->GetForwardDeclClangTypeToDie().count(ClangASTContext::RemoveFastQualifiers(clang_type).GetOpaqueQualType()) &&
+ "Type already in the forward declaration map!");
+ assert(((SymbolFileDWARF*)m_ast.GetSymbolFile())->UserIDMatches(die.GetDIERef().GetUID()) &&
+ "Adding incorrect type to forward declaration map");
+ dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = clang_type.GetOpaqueQualType();
+ dwarf->GetForwardDeclClangTypeToDie()[ClangASTContext::RemoveFastQualifiers(clang_type).GetOpaqueQualType()] = die.GetDIERef();
+ m_ast.SetHasExternalStorage (clang_type.GetOpaqueQualType(), true);
+ }
+ }
+ }
+ break;
+
+ case DW_TAG_enumeration_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
+
+ DWARFFormValue encoding_form;
+
+ const size_t num_attributes = die.GetAttributes (attributes);
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+
+ for (i=0; i<num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+ case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
+ case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+ case DW_AT_type: encoding_form = form_value; break;
+ case DW_AT_byte_size: byte_size = form_value.Unsigned(); break;
+ case DW_AT_accessibility: break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
+ case DW_AT_declaration: is_forward_declaration = form_value.Boolean(); break;
+ case DW_AT_allocated:
+ case DW_AT_associated:
+ case DW_AT_bit_stride:
+ case DW_AT_byte_stride:
+ case DW_AT_data_location:
+ case DW_AT_description:
+ case DW_AT_start_scope:
+ case DW_AT_visibility:
+ case DW_AT_specification:
+ case DW_AT_abstract_origin:
+ case DW_AT_sibling:
+ break;
+ }
+ }
+ }
+
+ if (is_forward_declaration)
+ {
+ type_sp = ParseTypeFromDWO(die, log);
+ if (type_sp)
+ return type_sp;
+
+ DWARFDeclContext die_decl_ctx;
+ die.GetDWARFDeclContext(die_decl_ctx);
+
+ 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);
+ }
+ }
+
+ 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),
+ type_name_cstr,
+ type_sp->GetID());
+ }
+
+ // 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->DebugInfo()->GetDIE(DIERef(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);
+
+ CompilerType enumerator_clang_type;
+ clang_type.SetCompilerType (&m_ast, dwarf->GetForwardDeclDieToClangType().lookup (die.GetDIE()));
+ if (!clang_type)
+ {
+ if (encoding_form.IsValid())
+ {
+ Type *enumerator_type = dwarf->ResolveTypeUID(DIERef(encoding_form).GetUID());
+ if (enumerator_type)
+ enumerator_clang_type = enumerator_type->GetFullCompilerType ();
+ }
+
+ if (!enumerator_clang_type)
+ enumerator_clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize (NULL,
+ DW_ATE_signed,
+ byte_size * 8);
+
+ clang_type = m_ast.CreateEnumerationType (type_name_cstr,
+ GetClangDeclContextContainingDIE (die, nullptr),
+ decl,
+ enumerator_clang_type);
+ }
+ else
+ {
+ enumerator_clang_type = m_ast.GetEnumerationIntegerType (clang_type.GetOpaqueQualType());
+ }
+
+ LinkDeclContextToDIE(ClangASTContext::GetDeclContextForType(clang_type), die);
+
+ type_sp.reset( new Type (die.GetID(),
+ dwarf,
+ type_name_const_str,
+ byte_size,
+ NULL,
+ DIERef(encoding_form).GetUID(),
+ Type::eEncodingIsUID,
+ &decl,
+ clang_type,
+ Type::eResolveStateForward));
+
+ ClangASTContext::StartTagDeclarationDefinition (clang_type);
+ if (die.HasChildren())
+ {
+ SymbolContext cu_sc(die.GetLLDBCompileUnit());
+ bool is_signed = false;
+ enumerator_clang_type.IsIntegerType(is_signed);
+ ParseChildEnumerators(cu_sc, clang_type, is_signed, type_sp->GetByteSize(), die);
+ }
+ ClangASTContext::CompleteTagDeclarationDefinition (clang_type);
+ }
+ }
+ break;
+
+ case DW_TAG_inlined_subroutine:
+ case DW_TAG_subprogram:
+ case DW_TAG_subroutine_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
+
+ DWARFFormValue type_die_form;
+ bool is_variadic = false;
+ bool is_inline = false;
+ bool is_static = false;
+ bool is_virtual = false;
+ bool is_explicit = false;
+ bool is_artificial = false;
+ DWARFFormValue specification_die_form;
+ DWARFFormValue abstract_origin_die_form;
+ dw_offset_t object_pointer_die_offset = DW_INVALID_OFFSET;
+
+ unsigned type_quals = 0;
+ clang::StorageClass storage = clang::SC_None;//, Extern, Static, PrivateExtern
+
+
+ const size_t num_attributes = die.GetAttributes (attributes);
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i=0; i<num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+ case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
+ case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+
+ case DW_AT_linkage_name:
+ case DW_AT_MIPS_linkage_name: break; // mangled = form_value.AsCString(&dwarf->get_debug_str_data()); break;
+ case DW_AT_type: type_die_form = form_value; break;
+ case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
+ case DW_AT_declaration: break; // is_forward_declaration = form_value.Boolean(); break;
+ case DW_AT_inline: is_inline = form_value.Boolean(); break;
+ case DW_AT_virtuality: is_virtual = form_value.Boolean(); break;
+ case DW_AT_explicit: is_explicit = form_value.Boolean(); break;
+ case DW_AT_artificial: is_artificial = form_value.Boolean(); break;
+
+
+ case DW_AT_external:
+ if (form_value.Unsigned())
+ {
+ if (storage == clang::SC_None)
+ storage = clang::SC_Extern;
+ else
+ storage = clang::SC_PrivateExtern;
+ }
+ break;
+
+ case DW_AT_specification:
+ specification_die_form = form_value;
+ break;
+
+ case DW_AT_abstract_origin:
+ abstract_origin_die_form = form_value;
+ break;
+
+ case DW_AT_object_pointer:
+ object_pointer_die_offset = form_value.Reference();
+ break;
+
+ case DW_AT_allocated:
+ case DW_AT_associated:
+ case DW_AT_address_class:
+ case DW_AT_calling_convention:
+ case DW_AT_data_location:
+ case DW_AT_elemental:
+ case DW_AT_entry_pc:
+ case DW_AT_frame_base:
+ case DW_AT_high_pc:
+ case DW_AT_low_pc:
+ case DW_AT_prototyped:
+ case DW_AT_pure:
+ case DW_AT_ranges:
+ case DW_AT_recursive:
+ case DW_AT_return_addr:
+ case DW_AT_segment:
+ case DW_AT_start_scope:
+ case DW_AT_static_link:
+ case DW_AT_trampoline:
+ case DW_AT_visibility:
+ case DW_AT_vtable_elem_location:
+ case DW_AT_description:
+ case DW_AT_sibling:
+ break;
+ }
+ }
+ }
+ }
+
+ std::string object_pointer_name;
+ if (object_pointer_die_offset != DW_INVALID_OFFSET)
+ {
+ DWARFDIE object_pointer_die = die.GetDIE (object_pointer_die_offset);
+ if (object_pointer_die)
+ {
+ const char *object_pointer_name_cstr = object_pointer_die.GetName();
+ if (object_pointer_name_cstr)
+ object_pointer_name = object_pointer_name_cstr;
+ }
+ }
+
+ DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr);
+
+ CompilerType return_clang_type;
+ Type *func_type = NULL;
+
+ if (type_die_form.IsValid())
+ func_type = dwarf->ResolveTypeUID(DIERef(type_die_form).GetUID());
+
+ 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();
+
+ const 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 (sc,
+ containing_decl_ctx,
+ die,
+ skip_artificial,
+ is_static,
+ is_variadic,
+ function_param_types,
+ function_param_decls,
+ type_quals);
+ }
+
+ // 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);
+
+ bool ignore_containing_context = false;
+
+ if (type_name_cstr)
+ {
+ bool type_handled = false;
+ if (tag == DW_TAG_subprogram ||
+ tag == DW_TAG_inlined_subroutine)
+ {
+ ObjCLanguage::MethodName objc_method (type_name_cstr, 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 (accessibility == eAccessNone)
+ accessibility = eAccessPublic;
+
+ clang::ObjCMethodDecl *objc_method_decl = m_ast.AddMethodToObjCObjectType (class_opaque_type,
+ type_name_cstr,
+ clang_type,
+ accessibility,
+ is_artificial);
+ 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));
+ }
+ }
+ }
+ 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"...
+ SymbolFileDWARF *class_symfile = NULL;
+ DWARFDIE class_type_die;
+
+ SymbolFileDWARFDebugMap *debug_map_symfile = dwarf->GetDebugMapSymfile();
+ if (debug_map_symfile)
+ {
+ class_symfile = debug_map_symfile->GetSymbolFileByOSOIndex(SymbolFileDWARFDebugMap::GetOSOIndexFromUserID(class_type->GetID()));
+ class_type_die = class_symfile->DebugInfo()->GetDIE (DIERef(class_type->GetID()));
+ }
+ else
+ {
+ class_symfile = dwarf;
+ class_type_die = dwarf->DebugInfo()->GetDIE (DIERef(class_type->GetID()));
+ }
+ if (class_type_die)
+ {
+ DWARFDIECollection 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;
+ }
+ }
+ }
+
+ if (specification_die_form.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 = dwarf->DebugInfo()->GetDIE(DIERef(specification_die_form));
+ 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.8" PRIx64 ") has no decl\n",
+ die.GetID(),
+ specification_die_form.Reference());
+ }
+ type_handled = true;
+ }
+ else if (abstract_origin_die_form.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 = dwarf->DebugInfo()->GetDIE (DIERef(abstract_origin_die_form));
+ 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.8" PRIx64 ") has no decl\n",
+ die.GetID(),
+ abstract_origin_die_form.Reference());
+ }
+ 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() == std::string(type_name_cstr))
+ {
+ if (method_decl->getType() == ClangASTContext::GetQualType(clang_type))
+ {
+ add_method = false;
+ LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(method_decl), die);
+ type_handled = true;
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (add_method)
+ {
+ // REMOVE THE CRASH DESCRIPTION BELOW
+ Host::SetCrashDescriptionWithFormat ("SymbolFileDWARF::ParseType() is adding a method %s to class %s in DIE 0x%8.8" PRIx64 " from %s",
+ type_name_cstr,
+ 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 (accessibility == eAccessNone)
+ accessibility = eAccessPublic;
+
+ clang::CXXMethodDecl *cxx_method_decl;
+ cxx_method_decl = m_ast.AddMethodToCXXRecordType (class_opaque_type.GetOpaqueQualType(),
+ type_name_cstr,
+ clang_type,
+ accessibility,
+ is_virtual,
+ is_static,
+ is_inline,
+ is_explicit,
+ is_attr_used,
+ is_artificial);
+
+ type_handled = cxx_method_decl != NULL;
+
+ if (type_handled)
+ {
+ LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(cxx_method_decl), die);
+
+ Host::SetCrashDescription (NULL);
+
+ ClangASTMetadata metadata;
+ metadata.SetUserID(die.GetID());
+
+ if (!object_pointer_name.empty())
+ {
+ metadata.SetObjectPtrName(object_pointer_name.c_str());
+ if (log)
+ log->Printf ("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;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!type_handled)
+ {
+ // We just have a function that isn't part of a class
+ clang::FunctionDecl *function_decl = m_ast.CreateFunctionDeclaration (ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx,
+ type_name_cstr,
+ clang_type,
+ storage,
+ is_inline);
+
+ // if (template_param_infos.GetSize() > 0)
+ // {
+ // clang::FunctionTemplateDecl *func_template_decl = CreateFunctionTemplateDecl (containing_decl_ctx,
+ // function_decl,
+ // type_name_cstr,
+ // template_param_infos);
+ //
+ // CreateFunctionTemplateSpecializationInfo (function_decl,
+ // func_template_decl,
+ // template_param_infos);
+ // }
+ // Add the decl to our DIE to decl context map
+ assert (function_decl);
+ LinkDeclContextToDIE(function_decl, die);
+ if (!function_param_decls.empty())
+ m_ast.SetFunctionParameters (function_decl,
+ &function_param_decls.front(),
+ function_param_decls.size());
+
+ ClangASTMetadata metadata;
+ metadata.SetUserID(die.GetID());
+
+ if (!object_pointer_name.empty())
+ {
+ metadata.SetObjectPtrName(object_pointer_name.c_str());
+ if (log)
+ log->Printf ("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.reset( new Type (die.GetID(),
+ dwarf,
+ type_name_const_str,
+ 0,
+ NULL,
+ LLDB_INVALID_UID,
+ Type::eEncodingIsUID,
+ &decl,
+ clang_type,
+ Type::eResolveStateFull));
+ assert(type_sp.get());
+ }
+ break;
+
+ case DW_TAG_array_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
+
+ DWARFFormValue type_die_form;
+ int64_t first_index = 0;
+ uint32_t byte_stride = 0;
+ uint32_t bit_stride = 0;
+ bool is_vector = false;
+ const size_t num_attributes = die.GetAttributes (attributes);
+
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i=0; i<num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+ case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
+ case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+
+ case DW_AT_type: type_die_form = form_value; break;
+ case DW_AT_byte_size: break; // byte_size = form_value.Unsigned(); break;
+ case DW_AT_byte_stride: byte_stride = form_value.Unsigned(); break;
+ case DW_AT_bit_stride: bit_stride = form_value.Unsigned(); break;
+ case DW_AT_GNU_vector: is_vector = form_value.Boolean(); break;
+ case DW_AT_accessibility: break; // accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
+ case DW_AT_declaration: break; // is_forward_declaration = form_value.Boolean(); break;
+ case DW_AT_allocated:
+ case DW_AT_associated:
+ case DW_AT_data_location:
+ case DW_AT_description:
+ case DW_AT_ordering:
+ case DW_AT_start_scope:
+ case DW_AT_visibility:
+ case DW_AT_specification:
+ case DW_AT_abstract_origin:
+ case DW_AT_sibling:
+ break;
+ }
+ }
+ }
+
+ DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr);
+
+ Type *element_type = dwarf->ResolveTypeUID(DIERef(type_die_form).GetUID());
+
+ if (element_type)
+ {
+ std::vector<uint64_t> element_orders;
+ ParseChildArrayInfo(sc, die, first_index, element_orders, byte_stride, bit_stride);
+ if (byte_stride == 0 && bit_stride == 0)
+ byte_stride = element_type->GetByteSize();
+ CompilerType array_element_type = element_type->GetForwardCompilerType ();
+ uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride;
+ if (element_orders.size() > 0)
+ {
+ uint64_t num_elements = 0;
+ std::vector<uint64_t>::const_reverse_iterator pos;
+ std::vector<uint64_t>::const_reverse_iterator end = element_orders.rend();
+ for (pos = element_orders.rbegin(); pos != end; ++pos)
+ {
+ num_elements = *pos;
+ clang_type = m_ast.CreateArrayType (array_element_type,
+ num_elements,
+ 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, is_vector);
+ }
+ ConstString empty_name;
+ type_sp.reset( new Type (die.GetID(),
+ dwarf,
+ empty_name,
+ array_element_bit_stride / 8,
+ NULL,
+ DIERef(type_die_form).GetUID(),
+ Type::eEncodingIsUID,
+ &decl,
+ clang_type,
+ Type::eResolveStateFull));
+ type_sp->SetEncodingType (element_type);
+ }
+ }
+ }
+ break;
+
+ case DW_TAG_ptr_to_member_type:
+ {
+ DWARFFormValue type_die_form;
+ DWARFFormValue containing_type_die_form;
+
+ const size_t num_attributes = die.GetAttributes (attributes);
+
+ if (num_attributes > 0) {
+ uint32_t i;
+ for (i=0; i<num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_type:
+ type_die_form = form_value; break;
+ case DW_AT_containing_type:
+ containing_type_die_form = form_value; break;
+ }
+ }
+ }
+
+ Type *pointee_type = dwarf->ResolveTypeUID(DIERef(type_die_form).GetUID());
+ Type *class_type = dwarf->ResolveTypeUID(DIERef(containing_type_die_form).GetUID());
+
+ CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType ();
+ CompilerType class_clang_type = class_type->GetLayoutCompilerType ();
+
+ clang_type = ClangASTContext::CreateMemberPointerType(class_clang_type, pointee_clang_type);
+
+ byte_size = clang_type.GetByteSize(nullptr);
+
+ type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, byte_size, NULL,
+ LLDB_INVALID_UID, Type::eEncodingIsUID, NULL, clang_type,
+ Type::eResolveStateForward));
+ }
+
+ 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 (type_sp.get())
+ {
+ DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die);
+ dw_tag_t sc_parent_tag = sc_parent_die.Tag();
+
+ SymbolContextScope * symbol_context_scope = NULL;
+ if (sc_parent_tag == DW_TAG_compile_unit)
+ {
+ symbol_context_scope = sc.comp_unit;
+ }
+ else if (sc.function != NULL && sc_parent_die)
+ {
+ symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
+ if (symbol_context_scope == NULL)
+ symbol_context_scope = sc.function;
+ }
+
+ if (symbol_context_scope != NULL)
+ {
+ type_sp->SetSymbolContextScope(symbol_context_scope);
+ }
+
+ // We are ready to put this type into the uniqued list up at the module level
+ type_list->Insert (type_sp);
+
+ dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+ }
+ }
+ else if (type_ptr != DIE_IS_BEING_PARSED)
+ {
+ type_sp = type_ptr->shared_from_this();
+ }
+ }
+ return type_sp;
+}
+
+// DWARF parsing functions
+
+class DWARFASTParserClang::DelayedAddObjCClassProperty
+{
+public:
+ DelayedAddObjCClassProperty(const CompilerType &class_opaque_type,
+ const char *property_name,
+ const CompilerType &property_opaque_type, // The property type is only required if you don't have an ivar decl
+ clang::ObjCIvarDecl *ivar_decl,
+ const char *property_setter_name,
+ const char *property_getter_name,
+ uint32_t property_attributes,
+ const ClangASTMetadata *metadata) :
+ m_class_opaque_type (class_opaque_type),
+ m_property_name (property_name),
+ m_property_opaque_type (property_opaque_type),
+ m_ivar_decl (ivar_decl),
+ m_property_setter_name (property_setter_name),
+ m_property_getter_name (property_getter_name),
+ m_property_attributes (property_attributes)
+ {
+ if (metadata != NULL)
+ {
+ m_metadata_ap.reset(new ClangASTMetadata());
+ *m_metadata_ap = *metadata;
+ }
+ }
+
+ DelayedAddObjCClassProperty (const DelayedAddObjCClassProperty &rhs)
+ {
+ *this = rhs;
+ }
+
+ DelayedAddObjCClassProperty& operator= (const DelayedAddObjCClassProperty &rhs)
+ {
+ m_class_opaque_type = rhs.m_class_opaque_type;
+ m_property_name = rhs.m_property_name;
+ m_property_opaque_type = rhs.m_property_opaque_type;
+ m_ivar_decl = rhs.m_ivar_decl;
+ m_property_setter_name = rhs.m_property_setter_name;
+ m_property_getter_name = rhs.m_property_getter_name;
+ m_property_attributes = rhs.m_property_attributes;
+
+ if (rhs.m_metadata_ap.get())
+ {
+ m_metadata_ap.reset (new ClangASTMetadata());
+ *m_metadata_ap = *rhs.m_metadata_ap;
+ }
+ return *this;
+ }
+
+ bool
+ Finalize()
+ {
+ return ClangASTContext::AddObjCClassProperty (m_class_opaque_type,
+ m_property_name,
+ m_property_opaque_type,
+ m_ivar_decl,
+ m_property_setter_name,
+ m_property_getter_name,
+ m_property_attributes,
+ m_metadata_ap.get());
+ }
+
+private:
+ CompilerType m_class_opaque_type;
+ const char *m_property_name;
+ CompilerType m_property_opaque_type;
+ clang::ObjCIvarDecl *m_ivar_decl;
+ const char *m_property_setter_name;
+ const char *m_property_getter_name;
+ uint32_t m_property_attributes;
+ std::unique_ptr<ClangASTMetadata> m_metadata_ap;
+};
+
+bool
+DWARFASTParserClang::ParseTemplateDIE (const DWARFDIE &die,
+ ClangASTContext::TemplateParameterInfos &template_param_infos)
+{
+ const dw_tag_t tag = die.Tag();
+
+ switch (tag)
+ {
+ case DW_TAG_template_type_parameter:
+ case DW_TAG_template_value_parameter:
+ {
+ DWARFAttributes attributes;
+ const size_t num_attributes = die.GetAttributes (attributes);
+ const char *name = NULL;
+ Type *lldb_type = NULL;
+ CompilerType clang_type;
+ uint64_t uval64 = 0;
+ bool uval64_valid = false;
+ if (num_attributes > 0)
+ {
+ DWARFFormValue form_value;
+ for (size_t i=0; i<num_attributes; ++i)
+ {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+
+ switch (attr)
+ {
+ case DW_AT_name:
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ name = form_value.AsCString();
+ break;
+
+ case DW_AT_type:
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ lldb_type = die.ResolveTypeUID(DIERef(form_value).GetUID());
+ if (lldb_type)
+ clang_type = lldb_type->GetForwardCompilerType ();
+ }
+ break;
+
+ case DW_AT_const_value:
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ uval64_valid = true;
+ uval64 = form_value.Unsigned();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ clang::ASTContext *ast = m_ast.getASTContext();
+ if (!clang_type)
+ clang_type = m_ast.GetBasicType(eBasicTypeVoid);
+
+ if (clang_type)
+ {
+ bool is_signed = false;
+ if (name && name[0])
+ template_param_infos.names.push_back(name);
+ else
+ template_param_infos.names.push_back(NULL);
+
+ if (tag == DW_TAG_template_value_parameter &&
+ lldb_type != NULL &&
+ clang_type.IsIntegerType (is_signed) &&
+ uval64_valid)
+ {
+ llvm::APInt apint (lldb_type->GetByteSize() * 8, uval64, is_signed);
+ template_param_infos.args.push_back (clang::TemplateArgument (*ast,
+ llvm::APSInt(apint),
+ ClangASTContext::GetQualType(clang_type)));
+ }
+ else
+ {
+ template_param_infos.args.push_back (clang::TemplateArgument (ClangASTContext::GetQualType(clang_type)));
+ }
+ }
+ else
+ {
+ return false;
+ }
+
+ }
+ }
+ return true;
+
+ default:
+ break;
+ }
+ return false;
+}
+
+bool
+DWARFASTParserClang::ParseTemplateParameterInfos (const DWARFDIE &parent_die,
+ ClangASTContext::TemplateParameterInfos &template_param_infos)
+{
+
+ if (!parent_die)
+ return false;
+
+ Args template_parameter_names;
+ for (DWARFDIE die = parent_die.GetFirstChild();
+ die.IsValid();
+ die = die.GetSibling())
+ {
+ const dw_tag_t tag = die.Tag();
+
+ switch (tag)
+ {
+ case DW_TAG_template_type_parameter:
+ case DW_TAG_template_value_parameter:
+ ParseTemplateDIE (die, template_param_infos);
+ break;
+
+ default:
+ break;
+ }
+ }
+ if (template_param_infos.args.empty())
+ return false;
+ return template_param_infos.args.size() == template_param_infos.names.size();
+}
+
+bool
+DWARFASTParserClang::CanCompleteType (const lldb_private::CompilerType &compiler_type)
+{
+ if (m_clang_ast_importer_ap)
+ return ClangASTContext::CanImport(compiler_type, GetClangASTImporter());
+ else
+ return false;
+}
+
+bool
+DWARFASTParserClang::CompleteType (const lldb_private::CompilerType &compiler_type)
+{
+ if (CanCompleteType(compiler_type))
+ {
+ if (ClangASTContext::Import(compiler_type, GetClangASTImporter()))
+ {
+ ClangASTContext::CompleteTagDeclarationDefinition(compiler_type);
+ return true;
+ }
+ else
+ {
+ ClangASTContext::SetHasExternalStorage (compiler_type.GetOpaqueQualType(), false);
+ }
+ }
+ return false;
+}
+
+bool
+DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die,
+ lldb_private::Type *type,
+ CompilerType &clang_type)
+{
+ // Disable external storage for this type so we don't get anymore
+ // clang::ExternalASTSource queries for this type.
+ m_ast.SetHasExternalStorage (clang_type.GetOpaqueQualType(), false);
+
+ if (!die)
+ return false;
+
+ const dw_tag_t tag = die.Tag();
+
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+
+ Log *log = nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION));
+ if (log)
+ dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace (log,
+ "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...",
+ die.GetID(),
+ die.GetTagAsCString(),
+ type->GetName().AsCString());
+ assert (clang_type);
+ DWARFAttributes attributes;
+ switch (tag)
+ {
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_class_type:
+ {
+ 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;
+ }
+
+ SymbolContext sc(die.GetLLDBCompileUnit());
+ std::vector<clang::CXXBaseSpecifier *> base_classes;
+ std::vector<int> member_accessibilities;
+ bool is_a_class = false;
+ // Parse members and base classes first
+ DWARFDIECollection member_function_dies;
+
+ DelayedPropertyList delayed_properties;
+ ParseChildMembers (sc,
+ die,
+ clang_type,
+ class_language,
+ base_classes,
+ member_accessibilities,
+ member_function_dies,
+ delayed_properties,
+ default_accessibility,
+ is_a_class,
+ layout_info);
+
+ // Now parse any methods if there were any...
+ size_t num_functions = member_function_dies.Size();
+ if (num_functions > 0)
+ {
+ for (size_t i=0; i<num_functions; ++i)
+ {
+ dwarf->ResolveType(member_function_dies.GetDIEAtIndex(i));
+ }
+ }
+
+ 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 (ClangASTContext::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 (!base_classes.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.SetBaseClassesForClassType()
+ for (auto &base_class : base_classes)
+ {
+ 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() == false)
+ {
+ 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() == DWARFCompileUnit::eProducerClang)
+ module->ReportError (":: Try compiling the source file with -fno-limit-debug-info.");
+
+ // 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.SetBaseClassesForClassType()"
+ // 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.
+ ClangASTContext::StartTagDeclarationDefinition (base_class_type);
+ ClangASTContext::CompleteTagDeclarationDefinition (base_class_type);
+ }
+ }
+ }
+ m_ast.SetBaseClassesForClassType (clang_type.GetOpaqueQualType(),
+ &base_classes.front(),
+ base_classes.size());
+
+ // Clang will copy each CXXBaseSpecifier in "base_classes"
+ // so we have to free them all.
+ ClangASTContext::DeleteBaseClassSpecifiers (&base_classes.front(),
+ base_classes.size());
+ }
+ }
+ }
+
+ 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() * 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());
+ }
+ }
+
+ }
+ }
+ m_record_decl_to_layout_map.insert(std::make_pair(record_decl, layout_info));
+ }
+ }
+ }
+
+ return (bool)clang_type;
+
+ case DW_TAG_enumeration_type:
+ ClangASTContext::StartTagDeclarationDefinition (clang_type);
+ if (die.HasChildren())
+ {
+ SymbolContext sc(die.GetLLDBCompileUnit());
+ bool is_signed = false;
+ clang_type.IsIntegerType(is_signed);
+ ParseChildEnumerators(sc, clang_type, is_signed, type->GetByteSize(), die);
+ }
+ ClangASTContext::CompleteTagDeclarationDefinition (clang_type);
+ return (bool)clang_type;
+
+ default:
+ assert(false && "not a forward clang type decl!");
+ break;
+ }
+
+ return false;
+}
+
+std::vector<DWARFDIE>
+DWARFASTParserClang::GetDIEForDeclContext(lldb_private::CompilerDeclContext decl_context)
+{
+ std::vector<DWARFDIE> result;
+ for (auto it = m_decl_ctx_to_die.find((clang::DeclContext *)decl_context.GetOpaqueDeclContext()); it != m_decl_ctx_to_die.end(); it++)
+ result.push_back(it->second);
+ return result;
+}
+
+CompilerDecl
+DWARFASTParserClang::GetDeclForUIDFromDWARF (const DWARFDIE &die)
+{
+ clang::Decl *clang_decl = GetClangDeclForDIE(die);
+ if (clang_decl != nullptr)
+ return CompilerDecl(&m_ast, clang_decl);
+ return CompilerDecl();
+}
+
+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 CompilerDeclContext();
+}
+
+CompilerDeclContext
+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 CompilerDeclContext();
+}
+
+size_t
+DWARFASTParserClang::ParseChildEnumerators (const SymbolContext& sc,
+ lldb_private::CompilerType &clang_type,
+ bool is_signed,
+ uint32_t enumerator_byte_size,
+ const DWARFDIE &parent_die)
+{
+ if (!parent_die)
+ return 0;
+
+ size_t enumerators_added = 0;
+
+ for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
+ {
+ const dw_tag_t tag = die.Tag();
+ if (tag == DW_TAG_enumerator)
+ {
+ DWARFAttributes attributes;
+ const size_t num_child_attributes = die.GetAttributes(attributes);
+ if (num_child_attributes > 0)
+ {
+ const char *name = NULL;
+ bool got_value = false;
+ int64_t enum_value = 0;
+ Declaration decl;
+
+ uint32_t i;
+ for (i=0; i<num_child_attributes; ++i)
+ {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_const_value:
+ got_value = true;
+ if (is_signed)
+ enum_value = form_value.Signed();
+ else
+ enum_value = form_value.Unsigned();
+ break;
+
+ case DW_AT_name:
+ name = form_value.AsCString();
+ break;
+
+ case DW_AT_description:
+ default:
+ case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+ case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
+ case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+ case DW_AT_sibling:
+ break;
+ }
+ }
+ }
+
+ if (name && name[0] && got_value)
+ {
+ m_ast.AddEnumerationValueToEnumerationType (clang_type.GetOpaqueQualType(),
+ m_ast.GetEnumerationIntegerType(clang_type.GetOpaqueQualType()),
+ decl,
+ name,
+ enum_value,
+ enumerator_byte_size * 8);
+ ++enumerators_added;
+ }
+ }
+ }
+ }
+ 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 (const SymbolContext& sc,
+ const DWARFDIE &die)
+{
+ DWARFRangeList func_ranges;
+ const char *name = NULL;
+ const char *mangled = NULL;
+ int decl_file = 0;
+ int decl_line = 0;
+ int decl_column = 0;
+ int call_file = 0;
+ int call_line = 0;
+ int call_column = 0;
+ DWARFExpression frame_base(die.GetCU());
+
+ const dw_tag_t tag = die.Tag();
+
+ if (tag != DW_TAG_subprogram)
+ return NULL;
+
+ if (die.GetDIENamesAndRanges (name,
+ mangled,
+ func_ranges,
+ decl_file,
+ decl_line,
+ decl_column,
+ call_file,
+ call_line,
+ call_column,
+ &frame_base))
+ {
+
+ // Union of all ranges in the function DIE (if the function is discontiguous)
+ AddressRange func_range;
+ lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase (0);
+ lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd (0);
+ if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr)
+ {
+ ModuleSP module_sp (die.GetModule());
+ func_range.GetBaseAddress().ResolveAddressUsingFileSections (lowest_func_addr, module_sp->GetSectionList());
+ if (func_range.GetBaseAddress().IsValid())
+ func_range.SetByteSize(highest_func_addr - lowest_func_addr);
+ }
+
+ if (func_range.GetBaseAddress().IsValid())
+ {
+ Mangled func_name;
+ if (mangled)
+ func_name.SetValue(ConstString(mangled), true);
+ else if (die.GetParent().Tag() == DW_TAG_compile_unit &&
+ Language::LanguageIsCPlusPlus(die.GetLanguage()) &&
+ name && strcmp(name, "main") != 0)
+ {
+ // If the mangled name is not present in the DWARF, generate the demangled name
+ // using the decl context. We skip if the function is "main" as its name is
+ // never mangled.
+ bool is_static = false;
+ bool is_variadic = false;
+ unsigned type_quals = 0;
+ std::vector<CompilerType> param_types;
+ std::vector<clang::ParmVarDecl*> param_decls;
+ DWARFDeclContext decl_ctx;
+ StreamString sstr;
+
+ die.GetDWARFDeclContext(decl_ctx);
+ sstr << decl_ctx.GetQualifiedName();
+
+ clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE(die, nullptr);
+ ParseChildParameters(sc,
+ containing_decl_ctx,
+ die,
+ true,
+ is_static,
+ is_variadic,
+ param_types,
+ param_decls,
+ type_quals);
+ sstr << "(";
+ for (size_t i = 0; i < param_types.size(); i++)
+ {
+ if (i > 0)
+ sstr << ", ";
+ sstr << param_types[i].GetTypeName();
+ }
+ if (is_variadic)
+ sstr << ", ...";
+ sstr << ")";
+ if (type_quals & clang::Qualifiers::Const)
+ sstr << " const";
+
+ func_name.SetValue(ConstString(sstr.GetData()), false);
+ }
+ else
+ func_name.SetValue(ConstString(name), false);
+
+ FunctionSP func_sp;
+ std::unique_ptr<Declaration> decl_ap;
+ if (decl_file != 0 || decl_line != 0 || decl_column != 0)
+ decl_ap.reset(new Declaration (sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file),
+ decl_line,
+ decl_column));
+
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ // Supply the type _only_ if it has already been parsed
+ Type *func_type = dwarf->GetDIEToType().lookup (die.GetDIE());
+
+ assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED);
+
+ if (dwarf->FixupAddress (func_range.GetBaseAddress()))
+ {
+ const user_id_t func_user_id = die.GetID();
+ func_sp.reset(new Function (sc.comp_unit,
+ func_user_id, // UserID is the DIE offset
+ func_user_id,
+ func_name,
+ func_type,
+ func_range)); // first address range
+
+ if (func_sp.get() != NULL)
+ {
+ if (frame_base.IsValid())
+ func_sp->GetFrameBaseExpression() = frame_base;
+ sc.comp_unit->AddFunction(func_sp);
+ return func_sp.get();
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+
+bool
+DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc,
+ const DWARFDIE &parent_die,
+ CompilerType &class_clang_type,
+ const LanguageType class_language,
+ std::vector<clang::CXXBaseSpecifier *>& base_classes,
+ std::vector<int>& member_accessibilities,
+ DWARFDIECollection& member_function_dies,
+ DelayedPropertyList& delayed_properties,
+ AccessType& default_accessibility,
+ bool &is_a_class,
+ LayoutInfo &layout_info)
+{
+ if (!parent_die)
+ return 0;
+
+ 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 0;
+
+ 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)
+ {
+ Declaration decl;
+ //DWARFExpression location;
+ const char *name = NULL;
+ const char *prop_name = NULL;
+ const char *prop_getter_name = NULL;
+ const char *prop_setter_name = NULL;
+ uint32_t prop_attributes = 0;
+
+
+ bool is_artificial = false;
+ DWARFFormValue encoding_form;
+ AccessType accessibility = eAccessNone;
+ uint32_t member_byte_offset = UINT32_MAX;
+ size_t byte_size = 0;
+ size_t bit_offset = 0;
+ 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_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+ case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
+ case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+ 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.Unsigned(); 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_member_location:
+ if (form_value.BlockData())
+ {
+ Value initialValue(0);
+ Value memberOffset(0);
+ const DWARFDataExtractor& debug_info_data = die.GetDWARF()->get_debug_info_data();
+ uint32_t block_length = form_value.Unsigned();
+ uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
+ if (DWARFExpression::Evaluate(NULL, // ExecutionContext *
+ NULL, // ClangExpressionVariableList *
+ NULL, // ClangExpressionDeclMap *
+ NULL, // RegisterContext *
+ module_sp,
+ debug_info_data,
+ die.GetCU(),
+ block_offset,
+ block_length,
+ eRegisterKindDWARF,
+ &initialValue,
+ memberOffset,
+ NULL))
+ {
+ member_byte_offset = memberOffset.ResolveValue(NULL).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;
+ }
+ }
+ }
+
+ 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();
+ }
+
+ 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();
+ }
+
+ // If the names haven't been provided, they need to be
+ // filled in.
+
+ if (!prop_getter_name)
+ {
+ prop_getter_name = prop_name;
+ }
+ if (!prop_setter_name && prop_name[0] && !(prop_attributes & DW_APPLE_PROPERTY_readonly))
+ {
+ StreamString ss;
+
+ ss.Printf("set%c%s:",
+ toupper(prop_name[0]),
+ &prop_name[1]);
+
+ fixed_setter.SetCString(ss.GetData());
+ prop_setter_name = fixed_setter.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 (bit_offset > 128)
+ {
+ 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;
+
+ if (member_idx == 0 && !is_artificial && name && (strstr (name, "_vptr$") == name))
+ {
+ // Not all compilers will mark the vtable pointer
+ // member as artificial (llvm-gcc). We can't have
+ // the virtual members in our classes otherwise it
+ // throws off all child offsets since we end up
+ // having and extra pointer sized member in our
+ // class layouts.
+ is_artificial = true;
+ }
+
+ // Handle static members
+ if (is_external && member_byte_offset == UINT32_MAX)
+ {
+ Type *var_type = die.ResolveTypeUID(DIERef(encoding_form).GetUID());
+
+ if (var_type)
+ {
+ if (accessibility == eAccessNone)
+ accessibility = eAccessPublic;
+ ClangASTContext::AddVariableToRecordType (class_clang_type,
+ name,
+ var_type->GetLayoutCompilerType (),
+ accessibility);
+ }
+ break;
+ }
+
+ if (is_artificial == false)
+ {
+ Type *member_type = die.ResolveTypeUID(DIERef(encoding_form).GetUID());
+
+ clang::FieldDecl *field_decl = NULL;
+ 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 (byte_size == 0)
+ byte_size = member_type->GetByteSize();
+
+ if (die.GetDWARF()->GetObjectFile()->GetByteOrder() == eByteOrderLittle)
+ {
+ this_field_info.bit_offset += byte_size * 8;
+ this_field_info.bit_offset -= (bit_offset + bit_size);
+ }
+ else
+ {
+ this_field_info.bit_offset += bit_offset;
+ }
+
+ // 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;
+ }
+ }
+ }
+
+ if (anon_field_info.IsValid())
+ {
+ clang::FieldDecl *unnamed_bitfield_decl =
+ ClangASTContext::AddFieldToRecordType (class_clang_type,
+ NULL,
+ 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();
+ }
+
+ 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)
+ {
+ module_sp->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 " which extends beyond the bounds of 0x%8.8" PRIx64,
+ die.GetID(),
+ name,
+ encoding_form.Reference(),
+ parent_die.GetID());
+ }
+
+ member_clang_type = m_ast.CreateArrayType(member_array_element_type, 0, false);
+ }
+ }
+ }
+
+ if (ClangASTContext::IsCXXClassType(member_clang_type) && member_clang_type.GetCompleteType() == false)
+ {
+ if (die.GetCU()->GetProducer() == DWARFCompileUnit::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 -fno-limit-debug-info",
+ 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,
+ sc.comp_unit ? sc.comp_unit->GetPath().c_str() : "the source file");
+ // 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.
+ ClangASTContext::StartTagDeclarationDefinition(member_clang_type);
+ ClangASTContext::CompleteTagDeclarationDefinition(member_clang_type);
+ }
+
+ field_decl = ClangASTContext::AddFieldToRecordType (class_clang_type,
+ name,
+ member_clang_type,
+ accessibility,
+ bit_size);
+
+ m_ast.SetMetadataAsUserID (field_decl, die.GetID());
+
+ 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.8" PRIx64 " which was unable to be parsed",
+ die.GetID(),
+ name,
+ encoding_form.Reference());
+ else
+ module_sp->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member refers to type 0x%8.8" PRIx64 " which was unable to be parsed",
+ die.GetID(),
+ encoding_form.Reference());
+ }
+ }
+
+ if (prop_name != NULL && member_type)
+ {
+ clang::ObjCIvarDecl *ivar_decl = NULL;
+
+ if (field_decl)
+ {
+ ivar_decl = clang::dyn_cast<clang::ObjCIvarDecl>(field_decl);
+ assert (ivar_decl != NULL);
+ }
+
+ 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;
+
+ case DW_TAG_subprogram:
+ // Let the type parsing code handle this one for us.
+ member_function_dies.Append (die);
+ break;
+
+ case DW_TAG_inheritance:
+ {
+ is_a_class = true;
+ if (default_accessibility == eAccessNone)
+ default_accessibility = eAccessPrivate;
+ // TODO: implement DW_TAG_inheritance type parsing
+ DWARFAttributes attributes;
+ const size_t num_attributes = die.GetAttributes (attributes);
+ if (num_attributes > 0)
+ {
+ Declaration decl;
+ DWARFExpression location(die.GetCU());
+ DWARFFormValue encoding_form;
+ AccessType accessibility = default_accessibility;
+ bool is_virtual = false;
+ bool is_base_of_class = true;
+ off_t member_byte_offset = 0;
+ uint32_t i;
+ for (i=0; i<num_attributes; ++i)
+ {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+ case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
+ case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+ case DW_AT_type: encoding_form = form_value; break;
+ case DW_AT_data_member_location:
+ if (form_value.BlockData())
+ {
+ Value initialValue(0);
+ Value memberOffset(0);
+ const DWARFDataExtractor& debug_info_data = die.GetDWARF()->get_debug_info_data();
+ uint32_t block_length = form_value.Unsigned();
+ uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
+ if (DWARFExpression::Evaluate (NULL,
+ NULL,
+ NULL,
+ NULL,
+ module_sp,
+ debug_info_data,
+ die.GetCU(),
+ block_offset,
+ block_length,
+ eRegisterKindDWARF,
+ &initialValue,
+ memberOffset,
+ NULL))
+ {
+ member_byte_offset = memberOffset.ResolveValue(NULL).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_virtuality:
+ is_virtual = form_value.Boolean();
+ break;
+
+ case DW_AT_sibling:
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ Type *base_class_type = die.ResolveTypeUID(DIERef(encoding_form).GetUID());
+ if (base_class_type == NULL)
+ {
+ module_sp->ReportError("0x%8.8x: DW_TAG_inheritance failed to resolve the base class at 0x%8.8" PRIx64 " from enclosing type 0x%8.8x. \nPlease file a bug and attach the file at the start of this error message",
+ die.GetOffset(),
+ encoding_form.Reference(),
+ parent_die.GetOffset());
+ break;
+ }
+
+ CompilerType base_class_clang_type = base_class_type->GetFullCompilerType ();
+ assert (base_class_clang_type);
+ if (class_language == eLanguageTypeObjC)
+ {
+ ast->SetObjCSuperClass(class_clang_type, base_class_clang_type);
+ }
+ else
+ {
+ base_classes.push_back (ast->CreateBaseClassSpecifier (base_class_clang_type.GetOpaqueQualType(),
+ accessibility,
+ is_virtual,
+ is_base_of_class));
+
+ if (is_virtual)
+ {
+ // Do not specify any offset for virtual inheritance. The DWARF produced by clang doesn't
+ // give us a constant offset, but gives us a DWARF expressions that requires an actual object
+ // in memory. the DW_AT_data_member_location for a virtual base class looks like:
+ // DW_AT_data_member_location( DW_OP_dup, DW_OP_deref, DW_OP_constu(0x00000018), DW_OP_minus, DW_OP_deref, DW_OP_plus )
+ // Given this, there is really no valid response we can give to clang for virtual base
+ // class offsets, and this should eventually be removed from LayoutRecordType() in the external
+ // AST source in clang.
+ }
+ else
+ {
+ layout_info.base_offsets.insert(
+ std::make_pair(ast->GetAsCXXRecordDecl(base_class_clang_type.GetOpaqueQualType()),
+ clang::CharUnits::fromQuantity(member_byte_offset)));
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return true;
+}
+
+
+size_t
+DWARFASTParserClang::ParseChildParameters (const SymbolContext& sc,
+ clang::DeclContext *containing_decl_ctx,
+ const DWARFDIE &parent_die,
+ bool skip_artificial,
+ bool &is_static,
+ bool &is_variadic,
+ std::vector<CompilerType>& function_param_types,
+ std::vector<clang::ParmVarDecl*>& function_param_decls,
+ unsigned &type_quals)
+{
+ if (!parent_die)
+ return 0;
+
+ size_t arg_idx = 0;
+ for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
+ {
+ const dw_tag_t tag = die.Tag();
+ switch (tag)
+ {
+ case DW_TAG_formal_parameter:
+ {
+ DWARFAttributes attributes;
+ const size_t num_attributes = die.GetAttributes(attributes);
+ if (num_attributes > 0)
+ {
+ const char *name = NULL;
+ Declaration decl;
+ DWARFFormValue param_type_die_form;
+ bool is_artificial = false;
+ // one of None, Auto, Register, Extern, Static, PrivateExtern
+
+ clang::StorageClass storage = clang::SC_None;
+ uint32_t i;
+ for (i=0; i<num_attributes; ++i)
+ {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+ case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
+ case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+ case DW_AT_name: name = form_value.AsCString();
+ break;
+ case DW_AT_type: param_type_die_form = form_value; break;
+ case DW_AT_artificial: is_artificial = form_value.Boolean(); break;
+ case DW_AT_location:
+ // if (form_value.BlockData())
+ // {
+ // const DWARFDataExtractor& debug_info_data = debug_info();
+ // uint32_t block_length = form_value.Unsigned();
+ // DWARFDataExtractor location(debug_info_data, form_value.BlockData() - debug_info_data.GetDataStart(), block_length);
+ // }
+ // else
+ // {
+ // }
+ // break;
+ case DW_AT_const_value:
+ case DW_AT_default_value:
+ case DW_AT_description:
+ case DW_AT_endianity:
+ case DW_AT_is_optional:
+ case DW_AT_segment:
+ case DW_AT_variable_parameter:
+ default:
+ case DW_AT_abstract_origin:
+ case DW_AT_sibling:
+ break;
+ }
+ }
+ }
+
+ bool skip = false;
+ if (skip_artificial)
+ {
+ if (is_artificial)
+ {
+ // In order to determine if a C++ member function is
+ // "const" we have to look at the const-ness of "this"...
+ // Ugly, but that
+ if (arg_idx == 0)
+ {
+ if (DeclKindIsCXXClass(containing_decl_ctx->getDeclKind()))
+ {
+ // Often times compilers omit the "this" name for the
+ // specification DIEs, so we can't rely upon the name
+ // being in the formal parameter DIE...
+ if (name == NULL || ::strcmp(name, "this")==0)
+ {
+ Type *this_type = die.ResolveTypeUID (DIERef(param_type_die_form).GetUID());
+ if (this_type)
+ {
+ uint32_t encoding_mask = this_type->GetEncodingMask();
+ if (encoding_mask & Type::eEncodingIsPointerUID)
+ {
+ is_static = false;
+
+ if (encoding_mask & (1u << Type::eEncodingIsConstUID))
+ type_quals |= clang::Qualifiers::Const;
+ if (encoding_mask & (1u << Type::eEncodingIsVolatileUID))
+ type_quals |= clang::Qualifiers::Volatile;
+ }
+ }
+ }
+ }
+ }
+ skip = true;
+ }
+ else
+ {
+
+ // HACK: Objective C formal parameters "self" and "_cmd"
+ // are not marked as artificial in the DWARF...
+ CompileUnit *comp_unit = die.GetLLDBCompileUnit();
+ if (comp_unit)
+ {
+ switch (comp_unit->GetLanguage())
+ {
+ case eLanguageTypeObjC:
+ case eLanguageTypeObjC_plus_plus:
+ if (name && name[0] && (strcmp (name, "self") == 0 || strcmp (name, "_cmd") == 0))
+ skip = true;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ if (!skip)
+ {
+ Type *type = die.ResolveTypeUID(DIERef(param_type_die_form).GetUID());
+ if (type)
+ {
+ function_param_types.push_back (type->GetForwardCompilerType ());
+
+ clang::ParmVarDecl *param_var_decl = m_ast.CreateParameterDeclaration (name,
+ type->GetForwardCompilerType (),
+ storage);
+ assert(param_var_decl);
+ function_param_decls.push_back(param_var_decl);
+
+ m_ast.SetMetadataAsUserID (param_var_decl, die.GetID());
+ }
+ }
+ }
+ arg_idx++;
+ }
+ break;
+
+ case DW_TAG_unspecified_parameters:
+ is_variadic = true;
+ break;
+
+ case DW_TAG_template_type_parameter:
+ case DW_TAG_template_value_parameter:
+ // The one caller of this was never using the template_param_infos,
+ // and the local variable was taking up a large amount of stack space
+ // in SymbolFileDWARF::ParseType() so this was removed. If we ever need
+ // the template params back, we can add them back.
+ // ParseTemplateDIE (dwarf_cu, die, template_param_infos);
+ break;
+
+ default:
+ break;
+ }
+ }
+ return arg_idx;
+}
+
+void
+DWARFASTParserClang::ParseChildArrayInfo (const SymbolContext& sc,
+ const DWARFDIE &parent_die,
+ int64_t& first_index,
+ std::vector<uint64_t>& element_orders,
+ uint32_t& byte_stride,
+ uint32_t& bit_stride)
+{
+ if (!parent_die)
+ return;
+
+ for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
+ {
+ const dw_tag_t tag = die.Tag();
+ switch (tag)
+ {
+ case DW_TAG_subrange_type:
+ {
+ DWARFAttributes attributes;
+ const size_t num_child_attributes = die.GetAttributes(attributes);
+ if (num_child_attributes > 0)
+ {
+ uint64_t num_elements = 0;
+ uint64_t lower_bound = 0;
+ uint64_t upper_bound = 0;
+ bool upper_bound_valid = false;
+ uint32_t i;
+ for (i=0; i<num_child_attributes; ++i)
+ {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_name:
+ break;
+
+ case DW_AT_count:
+ num_elements = form_value.Unsigned();
+ break;
+
+ case DW_AT_bit_stride:
+ bit_stride = form_value.Unsigned();
+ break;
+
+ case DW_AT_byte_stride:
+ byte_stride = form_value.Unsigned();
+ break;
+
+ case DW_AT_lower_bound:
+ lower_bound = form_value.Unsigned();
+ break;
+
+ case DW_AT_upper_bound:
+ upper_bound_valid = true;
+ upper_bound = form_value.Unsigned();
+ break;
+
+ default:
+ case DW_AT_abstract_origin:
+ case DW_AT_accessibility:
+ case DW_AT_allocated:
+ case DW_AT_associated:
+ case DW_AT_data_location:
+ case DW_AT_declaration:
+ case DW_AT_description:
+ case DW_AT_sibling:
+ case DW_AT_threads_scaled:
+ case DW_AT_type:
+ case DW_AT_visibility:
+ break;
+ }
+ }
+ }
+
+ if (num_elements == 0)
+ {
+ if (upper_bound_valid && upper_bound >= lower_bound)
+ num_elements = upper_bound - lower_bound + 1;
+ }
+
+ element_orders.push_back (num_elements);
+ }
+ }
+ break;
+ }
+ }
+}
+
+Type *
+DWARFASTParserClang::GetTypeForDIE (const DWARFDIE &die)
+{
+ if (die)
+ {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ DWARFAttributes attributes;
+ const size_t num_attributes = die.GetAttributes(attributes);
+ if (num_attributes > 0)
+ {
+ DWARFFormValue type_die_form;
+ for (size_t i = 0; i < num_attributes; ++i)
+ {
+ dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+
+ if (attr == DW_AT_type && attributes.ExtractFormValueAtIndex(i, form_value))
+ return dwarf->ResolveTypeUID(DIERef(form_value).GetUID());
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+clang::Decl *
+DWARFASTParserClang::GetClangDeclForDIE (const DWARFDIE &die)
+{
+ if (!die)
+ return nullptr;
+
+ switch (die.Tag())
+ {
+ case DW_TAG_variable:
+ case DW_TAG_constant:
+ case DW_TAG_formal_parameter:
+ case DW_TAG_imported_declaration:
+ case DW_TAG_imported_module:
+ break;
+ default:
+ return nullptr;
+ }
+
+ DIEToDeclMap::iterator cache_pos = m_die_to_decl.find(die.GetDIE());
+ if (cache_pos != m_die_to_decl.end())
+ return cache_pos->second;
+
+ if (DWARFDIE spec_die = die.GetReferencedDIE(DW_AT_specification))
+ {
+ clang::Decl *decl = GetClangDeclForDIE(spec_die);
+ m_die_to_decl[die.GetDIE()] = decl;
+ m_decl_to_die[decl].insert(die.GetDIE());
+ return decl;
+ }
+
+ clang::Decl *decl = nullptr;
+ switch (die.Tag())
+ {
+ case DW_TAG_variable:
+ case DW_TAG_constant:
+ case DW_TAG_formal_parameter:
+ {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ Type *type = GetTypeForDIE(die);
+ const char *name = die.GetName();
+ clang::DeclContext *decl_context = ClangASTContext::DeclContextGetAsDeclContext(dwarf->GetDeclContextContainingUID(die.GetID()));
+ decl = m_ast.CreateVariableDeclaration(
+ decl_context,
+ name,
+ ClangASTContext::GetQualType(type->GetForwardCompilerType()));
+ break;
+ }
+ case DW_TAG_imported_declaration:
+ {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ lldb::user_id_t imported_uid = die.GetAttributeValueAsReference(DW_AT_import, DW_INVALID_OFFSET);
+
+ if (dwarf->UserIDMatches(imported_uid))
+ {
+ CompilerDecl imported_decl = dwarf->GetDeclForUID(imported_uid);
+ if (imported_decl)
+ {
+ clang::DeclContext *decl_context = ClangASTContext::DeclContextGetAsDeclContext(dwarf->GetDeclContextContainingUID(die.GetID()));
+ if (clang::NamedDecl *clang_imported_decl = llvm::dyn_cast<clang::NamedDecl>((clang::Decl *)imported_decl.GetOpaqueDecl()))
+ decl = m_ast.CreateUsingDeclaration(decl_context, clang_imported_decl);
+ }
+ }
+ break;
+ }
+ case DW_TAG_imported_module:
+ {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ lldb::user_id_t imported_uid = die.GetAttributeValueAsReference(DW_AT_import, DW_INVALID_OFFSET);
+
+ if (dwarf->UserIDMatches(imported_uid))
+ {
+ CompilerDeclContext imported_decl = dwarf->GetDeclContextForUID(imported_uid);
+ if (imported_decl)
+ {
+ clang::DeclContext *decl_context = ClangASTContext::DeclContextGetAsDeclContext(dwarf->GetDeclContextContainingUID(die.GetID()));
+ if (clang::NamespaceDecl *ns_decl = ClangASTContext::DeclContextGetAsNamespaceDecl(imported_decl))
+ decl = m_ast.CreateUsingDirectiveDeclaration(decl_context, ns_decl);
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ m_die_to_decl[die.GetDIE()] = decl;
+ m_decl_to_die[decl].insert(die.GetDIE());
+
+ return decl;
+}
+
+clang::DeclContext *
+DWARFASTParserClang::GetClangDeclContextForDIE (const DWARFDIE &die)
+{
+ if (die)
+ {
+ clang::DeclContext *decl_ctx = GetCachedClangDeclContextForDIE (die);
+ if (decl_ctx)
+ return decl_ctx;
+
+ bool try_parsing_type = true;
+ switch (die.Tag())
+ {
+ case DW_TAG_compile_unit:
+ decl_ctx = m_ast.GetTranslationUnitDecl();
+ try_parsing_type = false;
+ break;
+
+ case DW_TAG_namespace:
+ decl_ctx = ResolveNamespaceDIE (die);
+ try_parsing_type = false;
+ break;
+
+ case DW_TAG_lexical_block:
+ decl_ctx = (clang::DeclContext *)ResolveBlockDIE(die);
+ try_parsing_type = false;
+ break;
+
+ default:
+ break;
+ }
+
+ if (decl_ctx == nullptr && try_parsing_type)
+ {
+ Type* type = die.GetDWARF()->ResolveType (die);
+ if (type)
+ decl_ctx = GetCachedClangDeclContextForDIE (die);
+ }
+
+ if (decl_ctx)
+ {
+ LinkDeclContextToDIE (decl_ctx, die);
+ return decl_ctx;
+ }
+ }
+ return nullptr;
+}
+
+clang::BlockDecl *
+DWARFASTParserClang::ResolveBlockDIE (const DWARFDIE &die)
+{
+ if (die && die.Tag() == DW_TAG_lexical_block)
+ {
+ clang::BlockDecl *decl = llvm::cast_or_null<clang::BlockDecl>(m_die_to_decl_ctx[die.GetDIE()]);
+
+ if (!decl)
+ {
+ DWARFDIE decl_context_die;
+ clang::DeclContext *decl_context = GetClangDeclContextContainingDIE(die, &decl_context_die);
+ decl = m_ast.CreateBlockDeclaration(decl_context);
+
+ if (decl)
+ LinkDeclContextToDIE((clang::DeclContext *)decl, die);
+ }
+
+ return decl;
+ }
+ return nullptr;
+}
+
+clang::NamespaceDecl *
+DWARFASTParserClang::ResolveNamespaceDIE (const DWARFDIE &die)
+{
+ if (die && die.Tag() == DW_TAG_namespace)
+ {
+ // See if we already parsed this namespace DIE and associated it with a
+ // uniqued namespace declaration
+ clang::NamespaceDecl *namespace_decl = static_cast<clang::NamespaceDecl *>(m_die_to_decl_ctx[die.GetDIE()]);
+ if (namespace_decl)
+ return namespace_decl;
+ else
+ {
+ const char *namespace_name = die.GetName();
+ clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (die, nullptr);
+ namespace_decl = m_ast.GetUniqueNamespaceDeclaration (namespace_name, containing_decl_ctx);
+ Log *log = nullptr;// (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
+ if (log)
+ {
+ 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(),
+ 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(),
+ static_cast<void*>(namespace_decl),
+ static_cast<void*>(namespace_decl->getOriginalNamespace()));
+ }
+ }
+
+ if (namespace_decl)
+ LinkDeclContextToDIE((clang::DeclContext*)namespace_decl, die);
+ return namespace_decl;
+ }
+ }
+ return nullptr;
+}
+
+clang::DeclContext *
+DWARFASTParserClang::GetClangDeclContextContainingDIE (const DWARFDIE &die,
+ DWARFDIE *decl_ctx_die_copy)
+{
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+
+ DWARFDIE decl_ctx_die = dwarf->GetDeclContextDIEContainingDIE (die);
+
+ if (decl_ctx_die_copy)
+ *decl_ctx_die_copy = decl_ctx_die;
+
+ if (decl_ctx_die)
+ {
+ clang::DeclContext *clang_decl_ctx = GetClangDeclContextForDIE (decl_ctx_die);
+ if (clang_decl_ctx)
+ return clang_decl_ctx;
+ }
+ return m_ast.GetTranslationUnitDecl();
+}
+
+clang::DeclContext *
+DWARFASTParserClang::GetCachedClangDeclContextForDIE (const DWARFDIE &die)
+{
+ if (die)
+ {
+ DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die.GetDIE());
+ if (pos != m_die_to_decl_ctx.end())
+ return pos->second;
+ }
+ return nullptr;
+}
+
+void
+DWARFASTParserClang::LinkDeclContextToDIE (clang::DeclContext *decl_ctx, const DWARFDIE &die)
+{
+ m_die_to_decl_ctx[die.GetDIE()] = decl_ctx;
+ // There can be many DIEs for a single decl context
+ //m_decl_ctx_to_die[decl_ctx].insert(die.GetDIE());
+ m_decl_ctx_to_die.insert(std::make_pair(decl_ctx, die));
+}
+
+bool
+DWARFASTParserClang::CopyUniqueClassMethodTypes (const DWARFDIE &src_class_die,
+ const DWARFDIE &dst_class_die,
+ lldb_private::Type *class_type,
+ DWARFDIECollection &failures)
+{
+ if (!class_type || !src_class_die || !dst_class_die)
+ return false;
+ if (src_class_die.Tag() != dst_class_die.Tag())
+ return false;
+
+ // We need to complete the class type so we can get all of the method types
+ // parsed so we can then unique those types to their equivalent counterparts
+ // in "dst_cu" and "dst_class_die"
+ class_type->GetFullCompilerType ();
+
+ DWARFDIE src_die;
+ DWARFDIE dst_die;
+ UniqueCStringMap<DWARFDIE> src_name_to_die;
+ UniqueCStringMap<DWARFDIE> dst_name_to_die;
+ UniqueCStringMap<DWARFDIE> src_name_to_die_artificial;
+ UniqueCStringMap<DWARFDIE> dst_name_to_die_artificial;
+ for (src_die = src_class_die.GetFirstChild(); src_die.IsValid(); src_die = src_die.GetSibling())
+ {
+ if (src_die.Tag() == DW_TAG_subprogram)
+ {
+ // Make sure this is a declaration and not a concrete instance by looking
+ // for DW_AT_declaration set to 1. Sometimes concrete function instances
+ // are placed inside the class definitions and shouldn't be included in
+ // the list of things are are tracking here.
+ if (src_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1)
+ {
+ const char *src_name = src_die.GetMangledName ();
+ if (src_name)
+ {
+ ConstString src_const_name(src_name);
+ if (src_die.GetAttributeValueAsUnsigned(DW_AT_artificial, 0))
+ src_name_to_die_artificial.Append(src_const_name.GetCString(), src_die);
+ else
+ src_name_to_die.Append(src_const_name.GetCString(), src_die);
+ }
+ }
+ }
+ }
+ for (dst_die = dst_class_die.GetFirstChild(); dst_die.IsValid(); dst_die = dst_die.GetSibling())
+ {
+ if (dst_die.Tag() == DW_TAG_subprogram)
+ {
+ // Make sure this is a declaration and not a concrete instance by looking
+ // for DW_AT_declaration set to 1. Sometimes concrete function instances
+ // are placed inside the class definitions and shouldn't be included in
+ // the list of things are are tracking here.
+ if (dst_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1)
+ {
+ const char *dst_name = dst_die.GetMangledName ();
+ if (dst_name)
+ {
+ ConstString dst_const_name(dst_name);
+ if ( dst_die.GetAttributeValueAsUnsigned(DW_AT_artificial, 0))
+ dst_name_to_die_artificial.Append(dst_const_name.GetCString(), dst_die);
+ else
+ dst_name_to_die.Append(dst_const_name.GetCString(), dst_die);
+ }
+ }
+ }
+ }
+ const uint32_t src_size = src_name_to_die.GetSize ();
+ const uint32_t dst_size = dst_name_to_die.GetSize ();
+ Log *log = nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_TYPE_COMPLETION));
+
+ // Is everything kosher so we can go through the members at top speed?
+ bool fast_path = true;
+
+ if (src_size != dst_size)
+ {
+ if (src_size != 0 && dst_size != 0)
+ {
+ if (log)
+ log->Printf("warning: trying to unique class DIE 0x%8.8x to 0x%8.8x, but they didn't have the same size (src=%d, dst=%d)",
+ src_class_die.GetOffset(),
+ dst_class_die.GetOffset(),
+ src_size,
+ dst_size);
+ }
+
+ fast_path = false;
+ }
+
+ uint32_t idx;
+
+ if (fast_path)
+ {
+ for (idx = 0; idx < src_size; ++idx)
+ {
+ src_die = src_name_to_die.GetValueAtIndexUnchecked (idx);
+ dst_die = dst_name_to_die.GetValueAtIndexUnchecked (idx);
+
+ if (src_die.Tag() != dst_die.Tag())
+ {
+ if (log)
+ log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) tags didn't match 0x%8.8x (%s)",
+ src_class_die.GetOffset(),
+ dst_class_die.GetOffset(),
+ src_die.GetOffset(),
+ src_die.GetTagAsCString(),
+ dst_die.GetOffset(),
+ dst_die.GetTagAsCString());
+ fast_path = false;
+ }
+
+ const char *src_name = src_die.GetMangledName ();
+ const char *dst_name = dst_die.GetMangledName ();
+
+ // Make sure the names match
+ if (src_name == dst_name || (strcmp (src_name, dst_name) == 0))
+ continue;
+
+ if (log)
+ log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) names didn't match 0x%8.8x (%s)",
+ src_class_die.GetOffset(),
+ dst_class_die.GetOffset(),
+ src_die.GetOffset(),
+ src_name,
+ dst_die.GetOffset(),
+ dst_name);
+
+ fast_path = false;
+ }
+ }
+
+ DWARFASTParserClang *src_dwarf_ast_parser = (DWARFASTParserClang *)src_die.GetDWARFParser();
+ DWARFASTParserClang *dst_dwarf_ast_parser = (DWARFASTParserClang *)dst_die.GetDWARFParser();
+
+ // Now do the work of linking the DeclContexts and Types.
+ if (fast_path)
+ {
+ // We can do this quickly. Just run across the tables index-for-index since
+ // we know each node has matching names and tags.
+ for (idx = 0; idx < src_size; ++idx)
+ {
+ src_die = src_name_to_die.GetValueAtIndexUnchecked (idx);
+ dst_die = dst_name_to_die.GetValueAtIndexUnchecked (idx);
+
+ clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()];
+ if (src_decl_ctx)
+ {
+ if (log)
+ log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x",
+ static_cast<void*>(src_decl_ctx),
+ src_die.GetOffset(), dst_die.GetOffset());
+ dst_dwarf_ast_parser->LinkDeclContextToDIE (src_decl_ctx, dst_die);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found",
+ src_die.GetOffset(), dst_die.GetOffset());
+ }
+
+ Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()];
+ if (src_child_type)
+ {
+ if (log)
+ log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x",
+ static_cast<void*>(src_child_type),
+ src_child_type->GetID(),
+ src_die.GetOffset(), dst_die.GetOffset());
+ dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type;
+ }
+ else
+ {
+ if (log)
+ log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset());
+ }
+ }
+ }
+ else
+ {
+ // We must do this slowly. For each member of the destination, look
+ // up a member in the source with the same name, check its tag, and
+ // unique them if everything matches up. Report failures.
+
+ if (!src_name_to_die.IsEmpty() && !dst_name_to_die.IsEmpty())
+ {
+ src_name_to_die.Sort();
+
+ for (idx = 0; idx < dst_size; ++idx)
+ {
+ const char *dst_name = dst_name_to_die.GetCStringAtIndex(idx);
+ dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx);
+ src_die = src_name_to_die.Find(dst_name, DWARFDIE());
+
+ if (src_die && (src_die.Tag() == dst_die.Tag()))
+ {
+ clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()];
+ if (src_decl_ctx)
+ {
+ if (log)
+ log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x",
+ static_cast<void*>(src_decl_ctx),
+ src_die.GetOffset(),
+ dst_die.GetOffset());
+ dst_dwarf_ast_parser->LinkDeclContextToDIE (src_decl_ctx, dst_die);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset());
+ }
+
+ Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()];
+ if (src_child_type)
+ {
+ if (log)
+ log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x",
+ static_cast<void*>(src_child_type),
+ src_child_type->GetID(),
+ src_die.GetOffset(),
+ dst_die.GetOffset());
+ dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type;
+ }
+ else
+ {
+ if (log)
+ log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset());
+ }
+ }
+ else
+ {
+ if (log)
+ log->Printf ("warning: couldn't find a match for 0x%8.8x", dst_die.GetOffset());
+
+ failures.Append(dst_die);
+ }
+ }
+ }
+ }
+
+ const uint32_t src_size_artificial = src_name_to_die_artificial.GetSize ();
+ const uint32_t dst_size_artificial = dst_name_to_die_artificial.GetSize ();
+
+ if (src_size_artificial && dst_size_artificial)
+ {
+ dst_name_to_die_artificial.Sort();
+
+ for (idx = 0; idx < src_size_artificial; ++idx)
+ {
+ const char *src_name_artificial = src_name_to_die_artificial.GetCStringAtIndex(idx);
+ src_die = src_name_to_die_artificial.GetValueAtIndexUnchecked (idx);
+ dst_die = dst_name_to_die_artificial.Find(src_name_artificial, DWARFDIE());
+
+ if (dst_die)
+ {
+ // Both classes have the artificial types, link them
+ clang::DeclContext *src_decl_ctx = src_dwarf_ast_parser->m_die_to_decl_ctx[src_die.GetDIE()];
+ if (src_decl_ctx)
+ {
+ if (log)
+ log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x",
+ static_cast<void*>(src_decl_ctx),
+ src_die.GetOffset(), dst_die.GetOffset());
+ dst_dwarf_ast_parser->LinkDeclContextToDIE (src_decl_ctx, dst_die);
+ }
+ else
+ {
+ if (log)
+ log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset());
+ }
+
+ Type *src_child_type = dst_die.GetDWARF()->GetDIEToType()[src_die.GetDIE()];
+ if (src_child_type)
+ {
+ if (log)
+ log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x",
+ static_cast<void*>(src_child_type),
+ src_child_type->GetID(),
+ src_die.GetOffset(), dst_die.GetOffset());
+ dst_die.GetDWARF()->GetDIEToType()[dst_die.GetDIE()] = src_child_type;
+ }
+ else
+ {
+ if (log)
+ log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die.GetOffset(), dst_die.GetOffset());
+ }
+ }
+ }
+ }
+
+ if (dst_size_artificial)
+ {
+ for (idx = 0; idx < dst_size_artificial; ++idx)
+ {
+ const char *dst_name_artificial = dst_name_to_die_artificial.GetCStringAtIndex(idx);
+ dst_die = dst_name_to_die_artificial.GetValueAtIndexUnchecked (idx);
+ if (log)
+ log->Printf ("warning: need to create artificial method for 0x%8.8x for method '%s'", dst_die.GetOffset(), dst_name_artificial);
+
+ failures.Append(dst_die);
+ }
+ }
+
+ return (failures.Size() != 0);
+}
+
+
+bool
+DWARFASTParserClang::LayoutRecordType(const clang::RecordDecl *record_decl,
+ uint64_t &bit_size,
+ uint64_t &alignment,
+ llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets)
+{
+ RecordDeclToLayoutMap::iterator pos = m_record_decl_to_layout_map.find (record_decl);
+ bool success = false;
+ base_offsets.clear();
+ vbase_offsets.clear();
+ if (pos != m_record_decl_to_layout_map.end())
+ {
+ bit_size = pos->second.bit_size;
+ alignment = pos->second.alignment;
+ field_offsets.swap(pos->second.field_offsets);
+ base_offsets.swap (pos->second.base_offsets);
+ vbase_offsets.swap (pos->second.vbase_offsets);
+ m_record_decl_to_layout_map.erase(pos);
+ success = true;
+ }
+ else
+ {
+ bit_size = 0;
+ alignment = 0;
+ field_offsets.clear();
+ }
+ return success;
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
new file mode 100644
index 000000000000..3814758fdd2c
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -0,0 +1,213 @@
+//===-- DWARFASTParserClang.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFASTParserClang_h_
+#define SymbolFileDWARF_DWARFASTParserClang_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "clang/AST/CharUnits.h"
+
+// Project includes
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "DWARFDefines.h"
+#include "DWARFASTParser.h"
+
+class DWARFDebugInfoEntry;
+class DWARFDIECollection;
+
+class DWARFASTParserClang : public DWARFASTParser
+{
+public:
+ DWARFASTParserClang (lldb_private::ClangASTContext &ast);
+
+ ~DWARFASTParserClang() override;
+
+ lldb::TypeSP
+ ParseTypeFromDWARF (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &die,
+ lldb_private::Log *log,
+ bool *type_is_new_ptr) override;
+
+
+ lldb_private::Function *
+ ParseFunctionFromDWARF (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &die) override;
+
+ bool
+ CanCompleteType (const lldb_private::CompilerType &compiler_type) override;
+
+ bool
+ CompleteType (const lldb_private::CompilerType &compiler_type) override;
+
+ bool
+ CompleteTypeFromDWARF (const DWARFDIE &die,
+ lldb_private::Type *type,
+ lldb_private::CompilerType &compiler_type) override;
+
+ lldb_private::CompilerDecl
+ GetDeclForUIDFromDWARF (const DWARFDIE &die) override;
+
+ std::vector<DWARFDIE>
+ GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) override;
+
+ lldb_private::CompilerDeclContext
+ GetDeclContextForUIDFromDWARF (const DWARFDIE &die) override;
+
+ lldb_private::CompilerDeclContext
+ GetDeclContextContainingUIDFromDWARF (const DWARFDIE &die) override;
+
+ bool
+ LayoutRecordType(const clang::RecordDecl *record_decl,
+ uint64_t &bit_size,
+ uint64_t &alignment,
+ llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets);
+
+protected:
+ class DelayedAddObjCClassProperty;
+ typedef std::vector <DelayedAddObjCClassProperty> DelayedPropertyList;
+
+ struct LayoutInfo
+ {
+ LayoutInfo () :
+ bit_size(0),
+ alignment(0),
+ field_offsets(),
+ base_offsets(),
+ vbase_offsets()
+ {
+ }
+ uint64_t bit_size;
+ uint64_t alignment;
+ llvm::DenseMap<const clang::FieldDecl *, uint64_t> field_offsets;
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> base_offsets;
+ llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> vbase_offsets;
+ };
+
+ clang::BlockDecl *
+ ResolveBlockDIE (const DWARFDIE &die);
+
+ clang::NamespaceDecl *
+ ResolveNamespaceDIE (const DWARFDIE &die);
+
+ typedef llvm::DenseMap<const clang::RecordDecl *, LayoutInfo> RecordDeclToLayoutMap;
+
+ bool
+ ParseTemplateDIE (const DWARFDIE &die,
+ lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos);
+ bool
+ ParseTemplateParameterInfos (const DWARFDIE &parent_die,
+ lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos);
+
+ bool
+ ParseChildMembers (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &die,
+ lldb_private::CompilerType &class_compiler_type,
+ const lldb::LanguageType class_language,
+ std::vector<clang::CXXBaseSpecifier *>& base_classes,
+ std::vector<int>& member_accessibilities,
+ DWARFDIECollection& member_function_dies,
+ DelayedPropertyList& delayed_properties,
+ lldb::AccessType &default_accessibility,
+ bool &is_a_class,
+ LayoutInfo &layout_info);
+
+ size_t
+ ParseChildParameters (const lldb_private::SymbolContext& sc,
+ clang::DeclContext *containing_decl_ctx,
+ const DWARFDIE &parent_die,
+ bool skip_artificial,
+ bool &is_static,
+ bool &is_variadic,
+ std::vector<lldb_private::CompilerType>& function_args,
+ std::vector<clang::ParmVarDecl*>& function_param_decls,
+ unsigned &type_quals);
+
+ void
+ ParseChildArrayInfo (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &parent_die,
+ int64_t& first_index,
+ std::vector<uint64_t>& element_orders,
+ uint32_t& byte_stride,
+ uint32_t& bit_stride);
+
+ size_t
+ ParseChildEnumerators (const lldb_private::SymbolContext& sc,
+ lldb_private::CompilerType &compiler_type,
+ bool is_signed,
+ uint32_t enumerator_byte_size,
+ const DWARFDIE &parent_die);
+
+ lldb_private::Type *
+ GetTypeForDIE (const DWARFDIE &die);
+
+ clang::Decl *
+ GetClangDeclForDIE (const DWARFDIE &die);
+
+ clang::DeclContext *
+ GetClangDeclContextForDIE (const DWARFDIE &die);
+
+ clang::DeclContext *
+ GetClangDeclContextContainingDIE (const DWARFDIE &die,
+ DWARFDIE *decl_ctx_die);
+
+ bool
+ CopyUniqueClassMethodTypes (const DWARFDIE &src_class_die,
+ const DWARFDIE &dst_class_die,
+ lldb_private::Type *class_type,
+ DWARFDIECollection &failures);
+
+ clang::DeclContext *
+ GetCachedClangDeclContextForDIE (const DWARFDIE &die);
+
+ void
+ LinkDeclContextToDIE (clang::DeclContext *decl_ctx,
+ const DWARFDIE &die);
+
+ void
+ LinkDeclToDIE (clang::Decl *decl, const DWARFDIE &die);
+
+ lldb_private::ClangASTImporter &
+ GetClangASTImporter();
+
+ lldb::TypeSP
+ ParseTypeFromDWO (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);
+
+ typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet;
+ typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap;
+ //typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> DeclContextToDIEMap;
+ typedef std::multimap<const clang::DeclContext *, const DWARFDIE> DeclContextToDIEMap;
+ typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::Decl *> DIEToDeclMap;
+ typedef llvm::DenseMap<const clang::Decl *, DIEPointerSet> DeclToDIEMap;
+
+ lldb_private::ClangASTContext &m_ast;
+ DIEToDeclMap m_die_to_decl;
+ DeclToDIEMap m_decl_to_die;
+ DIEToDeclContextMap m_die_to_decl_ctx;
+ DeclContextToDIEMap m_decl_ctx_to_die;
+ RecordDeclToLayoutMap m_record_decl_to_layout_map;
+ std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_ap;
+};
+
+#endif // SymbolFileDWARF_DWARFASTParserClang_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
new file mode 100644
index 000000000000..bde2694461e2
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
@@ -0,0 +1,828 @@
+//===-- DWARFASTParserGo.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFASTParserGo.h"
+
+#include "DWARFASTParserGo.h"
+#include "DWARFCompileUnit.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFDeclContext.h"
+#include "DWARFDefines.h"
+#include "DWARFDIE.h"
+#include "DWARFDIECollection.h"
+#include "SymbolFileDWARF.h"
+#include "SymbolFileDWARFDebugMap.h"
+#include "UniqueDWARFASTType.h"
+
+#include "clang/Basic/Specifiers.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/TypeList.h"
+
+//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
+
+#ifdef ENABLE_DEBUG_PRINTF
+#include <stdio.h>
+#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
+#else
+#define DEBUG_PRINTF(fmt, ...)
+#endif
+
+#define DW_AT_go_kind 0x2900
+#define DW_AT_go_key 0x2901
+#define DW_AT_go_elem 0x2902
+
+using namespace lldb;
+using namespace lldb_private;
+DWARFASTParserGo::DWARFASTParserGo(GoASTContext &ast)
+ : m_ast(ast)
+{
+}
+
+DWARFASTParserGo::~DWARFASTParserGo()
+{
+}
+
+TypeSP
+DWARFASTParserGo::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, lldb_private::Log *log,
+ bool *type_is_new_ptr)
+{
+ TypeSP type_sp;
+
+ if (type_is_new_ptr)
+ *type_is_new_ptr = false;
+
+ if (die)
+ {
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ if (log)
+ {
+ dwarf->GetObjectFile()->GetModule()->LogMessage(
+ log, "DWARFASTParserGo::ParseTypeFromDWARF (die = 0x%8.8x) %s name = '%s')", die.GetOffset(),
+ DW_TAG_value_to_name(die.Tag()), die.GetName());
+ }
+
+ Type *type_ptr = dwarf->m_die_to_type.lookup(die.GetDIE());
+ TypeList *type_list = dwarf->GetTypeList();
+ if (type_ptr == NULL)
+ {
+ if (type_is_new_ptr)
+ *type_is_new_ptr = true;
+
+ const dw_tag_t tag = die.Tag();
+
+ bool is_forward_declaration = false;
+ DWARFAttributes attributes;
+ const char *type_name_cstr = NULL;
+ ConstString type_name_const_str;
+ Type::ResolveState resolve_state = Type::eResolveStateUnresolved;
+ uint64_t byte_size = 0;
+ uint64_t go_kind = 0;
+ Declaration decl;
+
+ Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
+ CompilerType compiler_type;
+ DWARFFormValue form_value;
+
+ dw_attr_t attr;
+
+ switch (tag)
+ {
+ case DW_TAG_base_type:
+ case DW_TAG_pointer_type:
+ case DW_TAG_typedef:
+ case DW_TAG_unspecified_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
+
+ const size_t num_attributes = die.GetAttributes(attributes);
+ lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
+
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i = 0; i < num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ if (type_name_cstr)
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+ case DW_AT_byte_size:
+ byte_size = form_value.Unsigned();
+ break;
+ case DW_AT_encoding:
+ // = form_value.Unsigned();
+ break;
+ case DW_AT_type:
+ encoding_uid = form_value.Reference();
+ break;
+ case DW_AT_go_kind:
+ go_kind = form_value.Unsigned();
+ break;
+ default:
+ // Do we care about DW_AT_go_key or DW_AT_go_elem?
+ break;
+ }
+ }
+ }
+ }
+
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", dwarf->MakeUserID(die.GetOffset()),
+ DW_TAG_value_to_name(tag), type_name_cstr, encoding_uid);
+
+ switch (tag)
+ {
+ default:
+ break;
+
+ case DW_TAG_unspecified_type:
+ resolve_state = Type::eResolveStateFull;
+ compiler_type = m_ast.CreateVoidType(type_name_const_str);
+ break;
+
+ case DW_TAG_base_type:
+ resolve_state = Type::eResolveStateFull;
+ compiler_type = m_ast.CreateBaseType(go_kind, type_name_const_str, byte_size);
+ break;
+
+ case DW_TAG_pointer_type:
+ encoding_data_type = Type::eEncodingIsPointerUID;
+ break;
+ case DW_TAG_typedef:
+ encoding_data_type = Type::eEncodingIsTypedefUID;
+ CompilerType impl;
+ Type *type = dwarf->ResolveTypeUID(encoding_uid);
+ if (type)
+ {
+ if (go_kind == 0 && type->GetName() == type_name_const_str)
+ {
+ // Go emits extra typedefs as a forward declaration. Ignore these.
+ dwarf->m_die_to_type[die.GetDIE()] = type;
+ return type->shared_from_this();
+ }
+ impl = type->GetForwardCompilerType();
+ compiler_type = m_ast.CreateTypedefType (go_kind, type_name_const_str, impl);
+ }
+ break;
+ }
+
+ type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, byte_size,
+ NULL, encoding_uid, encoding_data_type, &decl, compiler_type, resolve_state));
+
+ dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
+ }
+ break;
+
+ case DW_TAG_structure_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
+ bool byte_size_valid = false;
+
+ const size_t num_attributes = die.GetAttributes(attributes);
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i = 0; i < num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+
+ case DW_AT_byte_size:
+ byte_size = form_value.Unsigned();
+ byte_size_valid = true;
+ break;
+
+ case DW_AT_go_kind:
+ go_kind = form_value.Unsigned();
+ break;
+
+ // TODO: Should we use SLICETYPE's DW_AT_go_elem?
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ // TODO(ribrdb): Do we need this?
+
+ // UniqueDWARFASTType is large, so don't create a local variables on the
+ // stack, put it on the heap. This function is often called recursively
+ // and clang isn't good and sharing the stack space for variables in different blocks.
+ std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(new UniqueDWARFASTType());
+
+ // Only try and unique the type if it has a name.
+ if (type_name_const_str &&
+ dwarf->GetUniqueDWARFASTTypeMap().Find(type_name_const_str, die, decl,
+ byte_size_valid ? byte_size : -1, *unique_ast_entry_ap))
+ {
+ // We have already parsed this type or from another
+ // compile unit. GCC loves to use the "one definition
+ // rule" which can result in multiple definitions
+ // of the same class over and over in each compile
+ // unit.
+ type_sp = unique_ast_entry_ap->m_type_sp;
+ if (type_sp)
+ {
+ dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
+ return type_sp;
+ }
+ }
+
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()),
+ DW_TAG_value_to_name(tag), type_name_cstr);
+
+ bool compiler_type_was_created = false;
+ compiler_type.SetCompilerType(&m_ast, dwarf->m_forward_decl_die_to_clang_type.lookup(die.GetDIE()));
+ if (!compiler_type)
+ {
+ compiler_type_was_created = true;
+ compiler_type = m_ast.CreateStructType(go_kind, type_name_const_str, byte_size);
+ }
+
+ type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, byte_size,
+ NULL, LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, compiler_type,
+ Type::eResolveStateForward));
+
+ // Add our type to the unique type map so we don't
+ // end up creating many copies of the same type over
+ // and over in the ASTContext for our module
+ unique_ast_entry_ap->m_type_sp = type_sp;
+ unique_ast_entry_ap->m_die = die;
+ unique_ast_entry_ap->m_declaration = decl;
+ unique_ast_entry_ap->m_byte_size = byte_size;
+ dwarf->GetUniqueDWARFASTTypeMap().Insert(type_name_const_str, *unique_ast_entry_ap);
+
+ if (!is_forward_declaration)
+ {
+ // Always start the definition for a class type so that
+ // if the class has child classes or types that require
+ // the class to be created for use as their decl contexts
+ // the class will be ready to accept these child definitions.
+ if (die.HasChildren() == false)
+ {
+ // No children for this struct/union/class, lets finish it
+ m_ast.CompleteStructType(compiler_type);
+ }
+ else if (compiler_type_was_created)
+ {
+ // Leave this as a forward declaration until we need
+ // to know the details of the type. lldb_private::Type
+ // will automatically call the SymbolFile virtual function
+ // "SymbolFileDWARF::CompleteType(Type *)"
+ // When the definition needs to be defined.
+ dwarf->m_forward_decl_die_to_clang_type[die.GetDIE()] = compiler_type.GetOpaqueQualType();
+ dwarf->m_forward_decl_clang_type_to_die[compiler_type.GetOpaqueQualType()] = die.GetDIERef();
+ // SetHasExternalStorage (compiler_type.GetOpaqueQualType(), true);
+ }
+ }
+ }
+ break;
+
+ case DW_TAG_subprogram:
+ case DW_TAG_subroutine_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
+
+ bool is_variadic = false;
+ clang::StorageClass storage = clang::SC_None; //, Extern, Static, PrivateExtern
+
+ const size_t num_attributes = die.GetAttributes(attributes);
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i = 0; i < num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+
+ case DW_AT_external:
+ if (form_value.Unsigned())
+ {
+ if (storage == clang::SC_None)
+ storage = clang::SC_Extern;
+ else
+ storage = clang::SC_PrivateExtern;
+ }
+ break;
+
+ case DW_AT_high_pc:
+ case DW_AT_low_pc:
+ break;
+ }
+ }
+ }
+ }
+
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()),
+ DW_TAG_value_to_name(tag), type_name_cstr);
+
+ std::vector<CompilerType> function_param_types;
+
+ // Parse the function children for the parameters
+
+ if (die.HasChildren())
+ {
+ ParseChildParameters(sc, die, is_variadic, function_param_types);
+ }
+
+ // compiler_type will get the function prototype clang type after this call
+ compiler_type = m_ast.CreateFunctionType(type_name_const_str, function_param_types.data(),
+ function_param_types.size(), is_variadic);
+
+ type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, 0, NULL,
+ LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, compiler_type,
+ Type::eResolveStateFull));
+ assert(type_sp.get());
+ }
+ break;
+
+ case DW_TAG_array_type:
+ {
+ // Set a bit that lets us know that we are currently parsing this
+ dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
+
+ lldb::user_id_t type_die_offset = DW_INVALID_OFFSET;
+ int64_t first_index = 0;
+ uint32_t byte_stride = 0;
+ uint32_t bit_stride = 0;
+ const size_t num_attributes = die.GetAttributes(attributes);
+
+ if (num_attributes > 0)
+ {
+ uint32_t i;
+ for (i = 0; i < num_attributes; ++i)
+ {
+ attr = attributes.AttributeAtIndex(i);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_name:
+ type_name_cstr = form_value.AsCString();
+ type_name_const_str.SetCString(type_name_cstr);
+ break;
+
+ case DW_AT_type:
+ type_die_offset = form_value.Reference();
+ break;
+ case DW_AT_byte_size:
+ break; // byte_size = form_value.Unsigned(); break;
+ case DW_AT_go_kind:
+ go_kind = form_value.Unsigned();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()),
+ DW_TAG_value_to_name(tag), type_name_cstr);
+
+ Type *element_type = dwarf->ResolveTypeUID(type_die_offset);
+
+ if (element_type)
+ {
+ std::vector<uint64_t> element_orders;
+ ParseChildArrayInfo(sc, die, first_index, element_orders, byte_stride, bit_stride);
+ if (byte_stride == 0)
+ byte_stride = element_type->GetByteSize();
+ CompilerType array_element_type = element_type->GetForwardCompilerType();
+ if (element_orders.size() > 0)
+ {
+ if (element_orders.size() > 1)
+ printf("golang: unsupported multi-dimensional array %s\n", type_name_cstr);
+ compiler_type =
+ m_ast.CreateArrayType(type_name_const_str, array_element_type, element_orders[0]);
+ }
+ else
+ {
+ compiler_type = m_ast.CreateArrayType(type_name_const_str, array_element_type, 0);
+ }
+ type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str,
+ byte_stride, NULL, type_die_offset, Type::eEncodingIsUID, &decl,
+ compiler_type, Type::eResolveStateFull));
+ type_sp->SetEncodingType(element_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 (type_sp.get())
+ {
+ DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die);
+ dw_tag_t sc_parent_tag = sc_parent_die.Tag();
+
+ SymbolContextScope *symbol_context_scope = NULL;
+ if (sc_parent_tag == DW_TAG_compile_unit)
+ {
+ symbol_context_scope = sc.comp_unit;
+ }
+ else if (sc.function != NULL && sc_parent_die)
+ {
+ symbol_context_scope =
+ sc.function->GetBlock(true).FindBlockByID(dwarf->MakeUserID(sc_parent_die.GetOffset()));
+ if (symbol_context_scope == NULL)
+ symbol_context_scope = sc.function;
+ }
+
+ if (symbol_context_scope != NULL)
+ {
+ type_sp->SetSymbolContextScope(symbol_context_scope);
+ }
+
+ // We are ready to put this type into the uniqued list up at the module level
+ type_list->Insert(type_sp);
+
+ dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
+ }
+ }
+ else if (type_ptr != DIE_IS_BEING_PARSED)
+ {
+ type_sp = type_ptr->shared_from_this();
+ }
+ }
+ return type_sp;
+}
+
+size_t
+DWARFASTParserGo::ParseChildParameters(const SymbolContext &sc,
+
+ const DWARFDIE &parent_die, bool &is_variadic,
+ std::vector<CompilerType> &function_param_types)
+{
+ if (!parent_die)
+ return 0;
+
+ size_t arg_idx = 0;
+ for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
+ {
+
+ dw_tag_t tag = die.Tag();
+ switch (tag)
+ {
+ case DW_TAG_formal_parameter:
+ {
+ DWARFAttributes attributes;
+ const size_t num_attributes = die.GetAttributes(attributes);
+ if (num_attributes > 0)
+ {
+ Declaration decl;
+ dw_offset_t param_type_die_offset = DW_INVALID_OFFSET;
+
+ uint32_t i;
+ for (i = 0; i < num_attributes; ++i)
+ {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_name:
+ // = form_value.AsCString();
+ break;
+ case DW_AT_type:
+ param_type_die_offset = form_value.Reference();
+ break;
+ case DW_AT_location:
+ // if (form_value.BlockData())
+ // {
+ // const DWARFDataExtractor& debug_info_data =
+ // debug_info();
+ // uint32_t block_length = form_value.Unsigned();
+ // DWARFDataExtractor location(debug_info_data,
+ // form_value.BlockData() - debug_info_data.GetDataStart(),
+ // block_length);
+ // }
+ // else
+ // {
+ // }
+ // break;
+ default:
+ break;
+ }
+ }
+ }
+
+ Type *type = parent_die.ResolveTypeUID(param_type_die_offset);
+ if (type)
+ {
+ function_param_types.push_back(type->GetForwardCompilerType());
+ }
+ }
+ arg_idx++;
+ }
+ break;
+
+ case DW_TAG_unspecified_parameters:
+ is_variadic = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+ return arg_idx;
+}
+
+void
+DWARFASTParserGo::ParseChildArrayInfo(const SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index,
+ std::vector<uint64_t> &element_orders, uint32_t &byte_stride,
+ uint32_t &bit_stride)
+{
+ if (!parent_die)
+ return;
+
+ for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
+ {
+ const dw_tag_t tag = die.Tag();
+ switch (tag)
+ {
+ case DW_TAG_subrange_type:
+ {
+ DWARFAttributes attributes;
+ const size_t num_child_attributes = die.GetAttributes(attributes);
+ if (num_child_attributes > 0)
+ {
+ uint64_t num_elements = 0;
+ uint32_t i;
+ for (i = 0; i < num_child_attributes; ++i)
+ {
+ const dw_attr_t attr = attributes.AttributeAtIndex(i);
+ DWARFFormValue form_value;
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ {
+ switch (attr)
+ {
+ case DW_AT_count:
+ num_elements = form_value.Unsigned();
+ break;
+
+ default:
+ case DW_AT_type:
+ break;
+ }
+ }
+ }
+
+ element_orders.push_back(num_elements);
+ }
+ }
+ break;
+ }
+ }
+}
+
+bool
+DWARFASTParserGo::CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type, CompilerType &compiler_type)
+{
+ if (!die)
+ return false;
+
+ const dw_tag_t tag = die.Tag();
+
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ Log *log = nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION));
+ if (log)
+ dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
+ log, "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...", dwarf->MakeUserID(die.GetOffset()),
+ DW_TAG_value_to_name(tag), type->GetName().AsCString());
+ assert(compiler_type);
+ DWARFAttributes attributes;
+
+ switch (tag)
+ {
+ case DW_TAG_structure_type:
+ {
+ {
+ if (die.HasChildren())
+ {
+ SymbolContext sc(die.GetLLDBCompileUnit());
+
+ ParseChildMembers(sc, die, compiler_type);
+ }
+ }
+ m_ast.CompleteStructType(compiler_type);
+ return (bool)compiler_type;
+ }
+
+ default:
+ assert(false && "not a forward go type decl!");
+ break;
+ }
+
+ return false;
+}
+
+size_t
+DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc, const DWARFDIE &parent_die, CompilerType &class_compiler_type)
+{
+ size_t count = 0;
+ uint32_t member_idx = 0;
+
+ ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
+ GoASTContext *ast = llvm::dyn_cast_or_null<GoASTContext>(class_compiler_type.GetTypeSystem());
+ if (ast == nullptr)
+ return 0;
+
+ for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
+ {
+ dw_tag_t tag = die.Tag();
+
+ switch (tag)
+ {
+ case DW_TAG_member:
+ {
+ DWARFAttributes attributes;
+ const size_t num_attributes = die.GetAttributes(attributes);
+ if (num_attributes > 0)
+ {
+ Declaration decl;
+ const char *name = NULL;
+
+ lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
+ uint32_t member_byte_offset = UINT32_MAX;
+ uint32_t i;
+ for (i = 0; i < num_attributes; ++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_uid = form_value.Reference();
+ break;
+ case DW_AT_data_member_location:
+ if (form_value.BlockData())
+ {
+ Value initialValue(0);
+ Value memberOffset(0);
+ const DWARFDataExtractor &debug_info_data =
+ die.GetDWARF()->get_debug_info_data();
+ uint32_t block_length = form_value.Unsigned();
+ uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
+ if (DWARFExpression::Evaluate(NULL, // ExecutionContext *
+ NULL, // ClangExpressionVariableList *
+ NULL, // ClangExpressionDeclMap *
+ NULL, // RegisterContext *
+ module_sp, debug_info_data, die.GetCU(),
+ block_offset, block_length, eRegisterKindDWARF,
+ &initialValue, memberOffset, NULL))
+ {
+ member_byte_offset = memberOffset.ResolveValue(NULL).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;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ Type *member_type = die.ResolveTypeUID(encoding_uid);
+ if (member_type)
+ {
+ CompilerType member_go_type = member_type->GetFullCompilerType();
+ ConstString name_const_str(name);
+ m_ast.AddFieldToStruct(class_compiler_type, name_const_str, member_go_type, member_byte_offset);
+ }
+ }
+ ++member_idx;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return count;
+}
+
+Function *
+DWARFASTParserGo::ParseFunctionFromDWARF(const SymbolContext &sc, const DWARFDIE &die)
+{
+ DWARFRangeList func_ranges;
+ const char *name = NULL;
+ const char *mangled = NULL;
+ int decl_file = 0;
+ int decl_line = 0;
+ int decl_column = 0;
+ int call_file = 0;
+ int call_line = 0;
+ int call_column = 0;
+ DWARFExpression frame_base(die.GetCU());
+
+ assert(die.Tag() == DW_TAG_subprogram);
+
+ if (die.Tag() != DW_TAG_subprogram)
+ return NULL;
+
+ if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line, decl_column, call_file, call_line,
+ call_column, &frame_base))
+ {
+ // Union of all ranges in the function DIE (if the function is discontiguous)
+ AddressRange func_range;
+ lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase(0);
+ lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd(0);
+ if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr)
+ {
+ ModuleSP module_sp(die.GetModule());
+ func_range.GetBaseAddress().ResolveAddressUsingFileSections(lowest_func_addr, module_sp->GetSectionList());
+ if (func_range.GetBaseAddress().IsValid())
+ func_range.SetByteSize(highest_func_addr - lowest_func_addr);
+ }
+
+ if (func_range.GetBaseAddress().IsValid())
+ {
+ Mangled func_name;
+ func_name.SetValue(ConstString(name), false);
+
+ FunctionSP func_sp;
+ std::unique_ptr<Declaration> decl_ap;
+ if (decl_file != 0 || decl_line != 0 || decl_column != 0)
+ decl_ap.reset(new Declaration(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file), decl_line,
+ decl_column));
+
+ SymbolFileDWARF *dwarf = die.GetDWARF();
+ // Supply the type _only_ if it has already been parsed
+ Type *func_type = dwarf->m_die_to_type.lookup(die.GetDIE());
+
+ assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED);
+
+ if (dwarf->FixupAddress(func_range.GetBaseAddress()))
+ {
+ const user_id_t func_user_id = dwarf->MakeUserID(die.GetOffset());
+ func_sp.reset(new Function(sc.comp_unit,
+ dwarf->MakeUserID(func_user_id), // UserID is the DIE offset
+ dwarf->MakeUserID(func_user_id), func_name, func_type,
+ func_range)); // first address range
+
+ if (func_sp.get() != NULL)
+ {
+ if (frame_base.IsValid())
+ func_sp->GetFrameBaseExpression() = frame_base;
+ sc.comp_unit->AddFunction(func_sp);
+ return func_sp.get();
+ }
+ }
+ }
+ }
+ return NULL;
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h
new file mode 100644
index 000000000000..5039fc7f7672
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h
@@ -0,0 +1,84 @@
+//===-- DWARFASTParserGo.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFASTParserGo_h_
+#define SymbolFileDWARF_DWARFASTParserGo_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+
+// Project includes
+#include "lldb/Core/PluginInterface.h"
+#include "lldb/Symbol/GoASTContext.h"
+#include "DWARFDefines.h"
+#include "DWARFASTParser.h"
+#include "DWARFDIE.h"
+
+class DWARFDebugInfoEntry;
+class DWARFDIECollection;
+
+class DWARFASTParserGo : public DWARFASTParser
+{
+public:
+ DWARFASTParserGo(lldb_private::GoASTContext &ast);
+
+ ~DWARFASTParserGo() override;
+
+ lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, lldb_private::Log *log,
+ bool *type_is_new_ptr) override;
+
+ lldb_private::Function *
+ ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc,
+ const DWARFDIE &die) override;
+
+ bool
+ CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type,
+ lldb_private::CompilerType &go_type) override;
+
+ lldb_private::CompilerDeclContext
+ GetDeclContextForUIDFromDWARF(const DWARFDIE &die) override
+ {
+ return lldb_private::CompilerDeclContext();
+ }
+
+ lldb_private::CompilerDeclContext
+ GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) override
+ {
+ return lldb_private::CompilerDeclContext();
+ }
+
+ lldb_private::CompilerDecl
+ GetDeclForUIDFromDWARF (const DWARFDIE &die) override
+ {
+ return lldb_private::CompilerDecl();
+ }
+
+ std::vector<DWARFDIE>
+ GetDIEForDeclContext (lldb_private::CompilerDeclContext decl_context) override
+ {
+ return std::vector<DWARFDIE>();
+ }
+
+private:
+ size_t ParseChildParameters(const lldb_private::SymbolContext &sc, const DWARFDIE &parent_die, bool &is_variadic,
+ std::vector<lldb_private::CompilerType> &function_param_types);
+ void ParseChildArrayInfo(const lldb_private::SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index,
+ std::vector<uint64_t> &element_orders, uint32_t &byte_stride, uint32_t &bit_stride);
+
+ size_t ParseChildMembers(const lldb_private::SymbolContext &sc, const DWARFDIE &die,
+ lldb_private::CompilerType &class_compiler_type);
+
+ lldb_private::GoASTContext &m_ast;
+};
+
+#endif // SymbolFileDWARF_DWARFASTParserGo_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
new file mode 100644
index 000000000000..a522bcb35288
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
@@ -0,0 +1,90 @@
+//===-- DWARFAttribute.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFAttribute.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFCompileUnit.h"
+
+DWARFAttributes::DWARFAttributes() :
+ m_infos()
+{
+}
+
+DWARFAttributes::~DWARFAttributes()
+{
+}
+
+
+uint32_t
+DWARFAttributes::FindAttributeIndex(dw_attr_t attr) const
+{
+ collection::const_iterator end = m_infos.end();
+ collection::const_iterator beg = m_infos.begin();
+ collection::const_iterator pos;
+ for (pos = beg; pos != end; ++pos)
+ {
+ if (pos->attr.get_attr() == attr)
+ return std::distance(beg, pos);
+ }
+ return UINT32_MAX;
+}
+
+void
+DWARFAttributes::Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form)
+{
+ AttributeValue attr_value = { cu, attr_die_offset, { attr, form } };
+ m_infos.push_back(attr_value);
+}
+
+bool
+DWARFAttributes::ContainsAttribute(dw_attr_t attr) const
+{
+ return FindAttributeIndex(attr) != UINT32_MAX;
+}
+
+bool
+DWARFAttributes::RemoveAttribute(dw_attr_t attr)
+{
+ uint32_t attr_index = FindAttributeIndex(attr);
+ if (attr_index != UINT32_MAX)
+ {
+ m_infos.erase(m_infos.begin() + attr_index);
+ return true;
+ }
+ return false;
+}
+
+bool
+DWARFAttributes::ExtractFormValueAtIndex (uint32_t i, DWARFFormValue &form_value) const
+{
+ const DWARFCompileUnit *cu = CompileUnitAtIndex(i);
+ form_value.SetCompileUnit(cu);
+ form_value.SetForm(FormAtIndex(i));
+ lldb::offset_t offset = DIEOffsetAtIndex(i);
+ return form_value.ExtractValue(cu->GetSymbolFileDWARF()->get_debug_info_data(), &offset);
+}
+
+uint64_t
+DWARFAttributes::FormValueAsUnsigned (dw_attr_t attr, uint64_t fail_value) const
+{
+ const uint32_t attr_idx = FindAttributeIndex (attr);
+ if (attr_idx != UINT32_MAX)
+ return FormValueAsUnsignedAtIndex (attr_idx, fail_value);
+ return fail_value;
+}
+
+uint64_t
+DWARFAttributes::FormValueAsUnsignedAtIndex(uint32_t i, uint64_t fail_value) const
+{
+ DWARFFormValue form_value;
+ if (ExtractFormValueAtIndex(i, form_value))
+ return form_value.Reference();
+ return fail_value;
+}
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
index 40c8af3d6e8e..f5ca9cce525e 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
@@ -10,36 +10,72 @@
#ifndef SymbolFileDWARF_DWARFAttribute_h_
#define SymbolFileDWARF_DWARFAttribute_h_
+#include "llvm/ADT/SmallVector.h"
#include "DWARFDefines.h"
#include <vector>
+class DWARFCompileUnit;
+class DWARFFormValue;
+
class DWARFAttribute
{
public:
DWARFAttribute(dw_attr_t attr, dw_form_t form) :
- m_attr_form ( attr << 16 | form )
+ m_attr (attr),
+ m_form (form)
{
}
- void set(dw_attr_t attr, dw_form_t form) { m_attr_form = (attr << 16) | form; }
- void set_attr(dw_attr_t attr) { m_attr_form = (m_attr_form & 0x0000ffffu) | (attr << 16); }
- void set_form(dw_form_t form) { m_attr_form = (m_attr_form & 0xffff0000u) | form; }
- dw_attr_t get_attr() const { return m_attr_form >> 16; }
- dw_form_t get_form() const { return (dw_form_t)m_attr_form; }
- void get(dw_attr_t& attr, dw_form_t& form) const
+ void set (dw_attr_t attr, dw_form_t form) { m_attr = attr; m_form = form; }
+ void set_attr (dw_attr_t attr) { m_attr = attr; }
+ void set_form (dw_form_t form) { m_form = form; }
+ dw_attr_t get_attr () const { return m_attr; }
+ dw_form_t get_form () const { return m_form; }
+ void get (dw_attr_t& attr, dw_form_t& form) const
{
- uint32_t attr_form = m_attr_form;
- attr = attr_form >> 16;
- form = (dw_form_t)attr_form;
+ attr = m_attr;
+ form = m_form;
}
- bool operator == (const DWARFAttribute& rhs) const { return m_attr_form == rhs.m_attr_form; }
+ bool operator == (const DWARFAttribute& rhs) const { return m_attr == rhs.m_attr && m_form == rhs.m_form; }
typedef std::vector<DWARFAttribute> collection;
typedef collection::iterator iterator;
typedef collection::const_iterator const_iterator;
protected:
- uint32_t m_attr_form; // Upper 16 bits is attribute, lower 16 bits is form
+ dw_attr_t m_attr;
+ dw_form_t m_form;
};
+class DWARFAttributes
+{
+public:
+ DWARFAttributes();
+ ~DWARFAttributes();
+
+ void Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form);
+ const DWARFCompileUnit * CompileUnitAtIndex(uint32_t i) const { return m_infos[i].cu; }
+ dw_offset_t DIEOffsetAtIndex(uint32_t i) const { return m_infos[i].die_offset; }
+ dw_attr_t AttributeAtIndex(uint32_t i) const { return m_infos[i].attr.get_attr(); }
+ dw_attr_t FormAtIndex(uint32_t i) const { return m_infos[i].attr.get_form(); }
+ bool ExtractFormValueAtIndex (uint32_t i, DWARFFormValue &form_value) const;
+ uint64_t FormValueAsUnsignedAtIndex (uint32_t i, uint64_t fail_value) const;
+ uint64_t FormValueAsUnsigned (dw_attr_t attr, uint64_t fail_value) const;
+ uint32_t FindAttributeIndex(dw_attr_t attr) const;
+ bool ContainsAttribute(dw_attr_t attr) const;
+ bool RemoveAttribute(dw_attr_t attr);
+ void Clear() { m_infos.clear(); }
+ size_t Size() const { return m_infos.size(); }
+
+protected:
+ struct AttributeValue
+ {
+ const DWARFCompileUnit *cu; // Keep the compile unit with each attribute in case we have DW_FORM_ref_addr values
+ dw_offset_t die_offset;
+ DWARFAttribute attr;
+ };
+ typedef llvm::SmallVector<AttributeValue, 8> collection;
+ collection m_infos;
+};
+
#endif // SymbolFileDWARF_DWARFAttribute_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
index 60933108c97a..e7cb2b413ad7 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -12,12 +12,13 @@
#include "lldb/Core/Mangled.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
#include "lldb/Core/Timer.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include "DWARFDebugAbbrev.h"
#include "DWARFDebugAranges.h"
@@ -27,6 +28,7 @@
#include "LogChannelDWARF.h"
#include "NameToDIE.h"
#include "SymbolFileDWARF.h"
+#include "SymbolFileDWARFDwo.h"
#include "SymbolFileDWARFDebugMap.h"
using namespace lldb;
@@ -52,10 +54,16 @@ DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF* dwarf2Data) :
m_producer_version_minor (0),
m_producer_version_update (0),
m_language_type (eLanguageTypeUnknown),
- m_is_dwarf64 (false)
+ m_is_dwarf64 (false),
+ m_is_optimized (eLazyBoolCalculate),
+ m_addr_base (0),
+ m_base_obj_offset (DW_INVALID_OFFSET)
{
}
+DWARFCompileUnit::~DWARFCompileUnit()
+{}
+
void
DWARFCompileUnit::Clear()
{
@@ -71,6 +79,9 @@ DWARFCompileUnit::Clear()
m_producer = eProducerInvalid;
m_language_type = eLanguageTypeUnknown;
m_is_dwarf64 = false;
+ m_is_optimized = eLazyBoolCalculate;
+ m_addr_base = 0;
+ m_base_obj_offset = DW_INVALID_OFFSET;
}
bool
@@ -128,6 +139,9 @@ DWARFCompileUnit::ClearDIEs(bool keep_compile_unit_die)
if (keep_compile_unit_die)
m_die_array.push_back(tmp_array.front());
}
+
+ if (m_dwo_symbol_file)
+ m_dwo_symbol_file->GetCompileUnit()->ClearDIEs(keep_compile_unit_die);
}
//----------------------------------------------------------------------
@@ -174,7 +188,8 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only)
die_index_stack.reserve(32);
die_index_stack.push_back(0);
bool prev_die_had_children = false;
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64);
+ DWARFFormValue::FixedFormSizes fixed_form_sizes =
+ DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64);
while (offset < next_cu_offset &&
die.FastExtract (debug_info_data, this, fixed_form_sizes, &offset))
{
@@ -188,12 +203,12 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only)
const bool null_die = die.IsNULL();
if (depth == 0)
{
- uint64_t base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
+ if (initial_die_array_size == 0)
+ AddCompileUnitDIE(die);
+ uint64_t base_addr = die.GetAttributeValueAsAddress(m_dwarf2Data, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
if (base_addr == LLDB_INVALID_ADDRESS)
- base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_entry_pc, 0);
+ base_addr = die.GetAttributeValueAsAddress(m_dwarf2Data, this, DW_AT_entry_pc, 0);
SetBaseAddress (base_addr);
- if (initial_die_array_size == 0)
- AddDIE (die);
if (cu_die_only)
return 1;
}
@@ -283,9 +298,83 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only)
verbose_log->PutCString (strm.GetString().c_str());
}
- return m_die_array.size();
+ if (!m_dwo_symbol_file)
+ return m_die_array.size();
+
+ DWARFCompileUnit* dwo_cu = m_dwo_symbol_file->GetCompileUnit();
+ size_t dwo_die_count = dwo_cu->ExtractDIEsIfNeeded(cu_die_only);
+ return m_die_array.size() + dwo_die_count - 1; // We have 2 CU die, but we waht to count it only as one
}
+void
+DWARFCompileUnit::AddCompileUnitDIE(DWARFDebugInfoEntry& die)
+{
+ assert (m_die_array.empty() && "Compile unit DIE already added");
+ AddDIE(die);
+
+ DWARFDebugInfoEntry& cu_die = m_die_array.front();
+
+ const char* dwo_name = cu_die.GetAttributeValueAsString(m_dwarf2Data,
+ this,
+ DW_AT_GNU_dwo_name,
+ nullptr);
+ if (!dwo_name)
+ return;
+
+ FileSpec dwo_file(dwo_name, true);
+ if (dwo_file.IsRelative())
+ {
+ const char* comp_dir = cu_die.GetAttributeValueAsString(m_dwarf2Data,
+ this,
+ DW_AT_comp_dir,
+ nullptr);
+ if (!comp_dir)
+ return;
+
+ dwo_file.SetFile(comp_dir, true);
+ dwo_file.AppendPathComponent(dwo_name);
+ }
+
+ if (!dwo_file.Exists())
+ return;
+
+ DataBufferSP dwo_file_data_sp;
+ lldb::offset_t dwo_file_data_offset = 0;
+ ObjectFileSP dwo_obj_file = ObjectFile::FindPlugin(m_dwarf2Data->GetObjectFile()->GetModule(),
+ &dwo_file,
+ 0 /* file_offset */,
+ dwo_file.GetByteSize(),
+ dwo_file_data_sp,
+ dwo_file_data_offset);
+ if (dwo_obj_file == nullptr)
+ return;
+
+ std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file(new SymbolFileDWARFDwo(dwo_obj_file, this));
+
+ DWARFCompileUnit* dwo_cu = dwo_symbol_file->GetCompileUnit();
+ if (!dwo_cu)
+ return; // Can't fetch the compile unit from the dwo file.
+
+ DWARFDIE dwo_cu_die = dwo_cu->GetCompileUnitDIEOnly();
+ if (!dwo_cu_die.IsValid())
+ return; // Can't fetch the compile unit DIE from the dwo file.
+
+ uint64_t main_dwo_id = cu_die.GetAttributeValueAsUnsigned(m_dwarf2Data,
+ this,
+ DW_AT_GNU_dwo_id,
+ 0);
+ uint64_t sub_dwo_id = dwo_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_dwo_id, 0);
+ if (main_dwo_id != sub_dwo_id)
+ return; // The 2 dwo ID isn't match. Don't use the dwo file as it belongs to a differectn compilation.
+
+ m_dwo_symbol_file = std::move(dwo_symbol_file);
+
+ dw_addr_t addr_base = cu_die.GetAttributeValueAsUnsigned(m_dwarf2Data,
+ this,
+ DW_AT_GNU_addr_base,
+ 0);
+ dwo_cu->SetAddrBase(addr_base, m_offset);
+}
dw_offset_t
DWARFCompileUnit::GetAbbrevOffset() const
@@ -373,6 +462,16 @@ DWARFCompileUnit::SetDefaultAddressSize(uint8_t addr_size)
g_default_addr_size = addr_size;
}
+lldb::user_id_t
+DWARFCompileUnit::GetID () const
+{
+ dw_offset_t local_id = m_base_obj_offset != DW_INVALID_OFFSET ? m_base_obj_offset : m_offset;
+ if (m_dwarf2Data)
+ return m_dwarf2Data->MakeUserID(local_id);
+ else
+ return local_id;
+}
+
void
DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
DWARFDebugAranges* debug_aranges)
@@ -381,13 +480,15 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
// in order to produce a compile unit level set of address ranges that
// is accurate.
+ size_t num_debug_aranges = debug_aranges->GetNumRanges();
+
// First get the compile unit DIE only and check if it has a DW_AT_ranges
- const DWARFDebugInfoEntry* die = GetCompileUnitDIEOnly();
+ const DWARFDebugInfoEntry* die = GetCompileUnitDIEPtrOnly();
const dw_offset_t cu_offset = GetOffset();
if (die)
{
- DWARFDebugRanges::RangeList ranges;
+ DWARFRangeList ranges;
const size_t num_ranges = die->GetAttributeAddressRanges(dwarf2Data, this, ranges, false);
if (num_ranges > 0)
{
@@ -397,7 +498,7 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
// this with recent GCC builds.
for (size_t i=0; i<num_ranges; ++i)
{
- const DWARFDebugRanges::RangeList::Entry &range = ranges.GetEntryRef(i);
+ const DWARFRangeList::Entry &range = ranges.GetEntryRef(i);
debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), range.GetRangeEnd());
}
@@ -411,11 +512,11 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
// and then throwing them all away to keep memory usage down.
const bool clear_dies = ExtractDIEsIfNeeded (false) > 1;
- die = DIE();
+ die = DIEPtr();
if (die)
die->BuildAddressRangeTable(dwarf2Data, this, debug_aranges);
- if (debug_aranges->IsEmpty())
+ if (debug_aranges->GetNumRanges() == num_debug_aranges)
{
// We got nothing from the functions, maybe we have a line tables only
// situation. Check the line tables and build the arange table from this.
@@ -437,7 +538,6 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
{
const LineTable::FileAddressRanges::Entry &range = file_ranges.GetEntryRef(idx);
debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), range.GetRangeEnd());
- printf ("0x%8.8x: [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", GetOffset(), range.GetRangeBase(), range.GetRangeEnd());
}
}
}
@@ -446,7 +546,7 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
}
}
- if (debug_aranges->IsEmpty())
+ if (debug_aranges->GetNumRanges() == num_debug_aranges)
{
// We got nothing from the functions, maybe we have a line tables only
// situation. Check the line tables and build the arange table from this.
@@ -465,7 +565,6 @@ DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
{
const LineTable::FileAddressRanges::Entry &range = file_ranges.GetEntryRef(idx);
debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), range.GetRangeEnd());
- printf ("0x%8.8x: [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", GetOffset(), range.GetRangeBase(), range.GetRangeEnd());
}
}
}
@@ -493,119 +592,85 @@ DWARFCompileUnit::GetFunctionAranges ()
"DWARFCompileUnit::GetFunctionAranges() for compile unit at .debug_info[0x%8.8x]",
GetOffset());
}
- const DWARFDebugInfoEntry* die = DIE();
+ const DWARFDebugInfoEntry* die = DIEPtr();
if (die)
die->BuildFunctionAddressRangeTable (m_dwarf2Data, this, m_func_aranges_ap.get());
+
+ if (m_dwo_symbol_file)
+ {
+ DWARFCompileUnit* dwo_cu = m_dwo_symbol_file->GetCompileUnit();
+ const DWARFDebugInfoEntry* dwo_die = dwo_cu->DIEPtr();
+ if (dwo_die)
+ dwo_die->BuildFunctionAddressRangeTable (m_dwo_symbol_file.get(),
+ dwo_cu,
+ m_func_aranges_ap.get());
+ }
+
const bool minimize = false;
m_func_aranges_ap->Sort(minimize);
}
return *m_func_aranges_ap.get();
}
-bool
-DWARFCompileUnit::LookupAddress
-(
- const dw_addr_t address,
- DWARFDebugInfoEntry** function_die_handle,
- DWARFDebugInfoEntry** block_die_handle
-)
+DWARFDIE
+DWARFCompileUnit::LookupAddress (const dw_addr_t address)
{
- bool success = false;
-
- if (function_die_handle != NULL && DIE())
+ if (DIE())
{
-
const DWARFDebugAranges &func_aranges = GetFunctionAranges ();
// Re-check the aranges auto pointer contents in case it was created above
if (!func_aranges.IsEmpty())
- {
- *function_die_handle = GetDIEPtr(func_aranges.FindAddress(address));
- if (*function_die_handle != NULL)
- {
- success = true;
- if (block_die_handle != NULL)
- {
- DWARFDebugInfoEntry* child = (*function_die_handle)->GetFirstChild();
- while (child)
- {
- if (child->LookupAddress(address, m_dwarf2Data, this, NULL, block_die_handle))
- break;
- child = child->GetSibling();
- }
- }
- }
- }
+ return GetDIE(func_aranges.FindAddress(address));
}
- return success;
+ return DWARFDIE();
}
//----------------------------------------------------------------------
// Compare function DWARFDebugAranges::Range structures
//----------------------------------------------------------------------
-static bool CompareDIEOffset (const DWARFDebugInfoEntry& die1, const DWARFDebugInfoEntry& die2)
+static bool CompareDIEOffset (const DWARFDebugInfoEntry& die, const dw_offset_t die_offset)
{
- return die1.GetOffset() < die2.GetOffset();
+ return die.GetOffset() < die_offset;
}
//----------------------------------------------------------------------
-// GetDIEPtr()
+// GetDIE()
//
-// Get the DIE (Debug Information Entry) with the specified offset.
+// Get the DIE (Debug Information Entry) with the specified offset by
+// first checking if the DIE is contained within this compile unit and
+// grabbing the DIE from this compile unit. Otherwise we grab the DIE
+// from the DWARF file.
//----------------------------------------------------------------------
-DWARFDebugInfoEntry*
-DWARFCompileUnit::GetDIEPtr(dw_offset_t die_offset)
+DWARFDIE
+DWARFCompileUnit::GetDIE (dw_offset_t die_offset)
{
if (die_offset != DW_INVALID_OFFSET)
{
- ExtractDIEsIfNeeded (false);
- DWARFDebugInfoEntry compare_die;
- compare_die.SetOffset(die_offset);
- DWARFDebugInfoEntry::iterator end = m_die_array.end();
- DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset);
- if (pos != end)
- {
- if (die_offset == (*pos).GetOffset())
- return &(*pos);
- }
- }
- return NULL; // Not found in any compile units
-}
+ if (m_dwo_symbol_file)
+ return m_dwo_symbol_file->GetCompileUnit()->GetDIE(die_offset);
-//----------------------------------------------------------------------
-// GetDIEPtrContainingOffset()
-//
-// Get the DIE (Debug Information Entry) that contains the specified
-// .debug_info offset.
-//----------------------------------------------------------------------
-const DWARFDebugInfoEntry*
-DWARFCompileUnit::GetDIEPtrContainingOffset(dw_offset_t die_offset)
-{
- if (die_offset != DW_INVALID_OFFSET)
- {
- ExtractDIEsIfNeeded (false);
- DWARFDebugInfoEntry compare_die;
- compare_die.SetOffset(die_offset);
- DWARFDebugInfoEntry::iterator end = m_die_array.end();
- DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset);
- if (pos != end)
+ if (ContainsDIEOffset(die_offset))
{
- if (die_offset >= (*pos).GetOffset())
+ ExtractDIEsIfNeeded (false);
+ DWARFDebugInfoEntry::iterator end = m_die_array.end();
+ DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, die_offset, CompareDIEOffset);
+ if (pos != end)
{
- DWARFDebugInfoEntry::iterator next = pos + 1;
- if (next != end)
- {
- if (die_offset < (*next).GetOffset())
- return &(*pos);
- }
+ if (die_offset == (*pos).GetOffset())
+ return DWARFDIE(this, &(*pos));
}
}
+ else
+ {
+ // Don't specify the compile unit offset as we don't know it because the DIE belongs to
+ // a different compile unit in the same symbol file.
+ return m_dwarf2Data->DebugInfo()->GetDIE (DIERef(die_offset));
+ }
}
- return NULL; // Not found in any compile units
+ return DWARFDIE(); // Not found
}
-
-
size_t
DWARFCompileUnit::AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& dies, uint32_t depth) const
{
@@ -615,7 +680,7 @@ DWARFCompileUnit::AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& die
for (pos = m_die_array.begin(); pos != end; ++pos)
{
if (pos->Tag() == tag)
- dies.Append (&(*pos));
+ dies.Append (DWARFDIE(this, &(*pos)));
}
// Return the number of DIEs added to the collection
@@ -646,8 +711,7 @@ DWARFCompileUnit::AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& die
void
-DWARFCompileUnit::Index (const uint32_t cu_idx,
- NameToDIE& func_basenames,
+DWARFCompileUnit::Index (NameToDIE& func_basenames,
NameToDIE& func_fullnames,
NameToDIE& func_methods,
NameToDIE& func_selectors,
@@ -656,10 +720,6 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
NameToDIE& types,
NameToDIE& namespaces)
{
- const DWARFDataExtractor* debug_str = &m_dwarf2Data->get_debug_str_data();
-
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64);
-
Log *log (LogChannelDWARF::GetLogIfAll (DWARF_LOG_LOOKUPS));
if (log)
@@ -670,9 +730,57 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
}
const LanguageType cu_language = GetLanguageType();
+ DWARFFormValue::FixedFormSizes fixed_form_sizes =
+ DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64);
+
+ IndexPrivate(this,
+ cu_language,
+ fixed_form_sizes,
+ GetOffset(),
+ func_basenames,
+ func_fullnames,
+ func_methods,
+ func_selectors,
+ objc_class_selectors,
+ globals,
+ types,
+ namespaces);
+
+ SymbolFileDWARFDwo* dwo_symbol_file = GetDwoSymbolFile();
+ if (dwo_symbol_file)
+ {
+ IndexPrivate(dwo_symbol_file->GetCompileUnit(),
+ cu_language,
+ fixed_form_sizes,
+ GetOffset(),
+ func_basenames,
+ func_fullnames,
+ func_methods,
+ func_selectors,
+ objc_class_selectors,
+ globals,
+ types,
+ namespaces);
+ }
+}
+
+void
+DWARFCompileUnit::IndexPrivate (DWARFCompileUnit* dwarf_cu,
+ const LanguageType cu_language,
+ const DWARFFormValue::FixedFormSizes& fixed_form_sizes,
+ const dw_offset_t cu_offset,
+ NameToDIE& func_basenames,
+ NameToDIE& func_fullnames,
+ NameToDIE& func_methods,
+ NameToDIE& func_selectors,
+ NameToDIE& objc_class_selectors,
+ NameToDIE& globals,
+ NameToDIE& types,
+ NameToDIE& namespaces)
+{
DWARFDebugInfoEntry::const_iterator pos;
- DWARFDebugInfoEntry::const_iterator begin = m_die_array.begin();
- DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
+ DWARFDebugInfoEntry::const_iterator begin = dwarf_cu->m_die_array.begin();
+ DWARFDebugInfoEntry::const_iterator end = dwarf_cu->m_die_array.end();
for (pos = begin; pos != end; ++pos)
{
const DWARFDebugInfoEntry &die = *pos;
@@ -701,17 +809,17 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
continue;
}
- DWARFDebugInfoEntry::Attributes attributes;
+ DWARFAttributes attributes;
const char *name = NULL;
const char *mangled_cstr = NULL;
bool is_declaration = false;
//bool is_artificial = false;
bool has_address = false;
- bool has_location = false;
+ bool has_location_or_const_value = false;
bool is_global_or_static_variable = false;
- dw_offset_t specification_die_offset = DW_INVALID_OFFSET;
- const size_t num_attributes = die.GetAttributes(m_dwarf2Data, this, fixed_form_sizes, attributes);
+ DWARFFormValue specification_die_form;
+ const size_t num_attributes = die.GetAttributes(dwarf_cu, fixed_form_sizes, attributes);
if (num_attributes > 0)
{
for (uint32_t i=0; i<num_attributes; ++i)
@@ -721,24 +829,24 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
switch (attr)
{
case DW_AT_name:
- if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
- name = form_value.AsCString(debug_str);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ name = form_value.AsCString();
break;
case DW_AT_declaration:
- if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
is_declaration = form_value.Unsigned() != 0;
break;
// case DW_AT_artificial:
-// if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
+// if (attributes.ExtractFormValueAtIndex(i, form_value))
// is_artificial = form_value.Unsigned() != 0;
// break;
case DW_AT_MIPS_linkage_name:
case DW_AT_linkage_name:
- if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
- mangled_cstr = form_value.AsCString(debug_str);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ mangled_cstr = form_value.AsCString();
break;
case DW_AT_low_pc:
@@ -752,7 +860,8 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
break;
case DW_AT_location:
- has_location = true;
+ case DW_AT_const_value:
+ has_location_or_const_value = true;
if (tag == DW_TAG_variable)
{
const DWARFDebugInfoEntry* parent_die = die.GetParent();
@@ -800,8 +909,8 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
break;
case DW_AT_specification:
- if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
- specification_die_offset = form_value.Reference();
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ specification_die_form = form_value;
break;
}
}
@@ -814,24 +923,22 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
{
if (name)
{
- // Note, this check is also done in ParseMethodName, but since this is a hot loop, we do the
- // simple inlined check outside the call.
- ObjCLanguageRuntime::MethodName objc_method(name, true);
+ ObjCLanguage::MethodName objc_method(name, true);
if (objc_method.IsValid(true))
{
ConstString objc_class_name_with_category (objc_method.GetClassNameWithCategory());
ConstString objc_selector_name (objc_method.GetSelector());
ConstString objc_fullname_no_category_name (objc_method.GetFullNameWithoutCategory(true));
ConstString objc_class_name_no_category (objc_method.GetClassName());
- func_fullnames.Insert (ConstString(name), die.GetOffset());
+ func_fullnames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));
if (objc_class_name_with_category)
- objc_class_selectors.Insert(objc_class_name_with_category, die.GetOffset());
+ objc_class_selectors.Insert(objc_class_name_with_category, DIERef(cu_offset, die.GetOffset()));
if (objc_class_name_no_category && objc_class_name_no_category != objc_class_name_with_category)
- objc_class_selectors.Insert(objc_class_name_no_category, die.GetOffset());
+ objc_class_selectors.Insert(objc_class_name_no_category, DIERef(cu_offset, die.GetOffset()));
if (objc_selector_name)
- func_selectors.Insert (objc_selector_name, die.GetOffset());
+ func_selectors.Insert (objc_selector_name, DIERef(cu_offset, die.GetOffset()));
if (objc_fullname_no_category_name)
- func_fullnames.Insert (objc_fullname_no_category_name, die.GetOffset());
+ func_fullnames.Insert (objc_fullname_no_category_name, DIERef(cu_offset, die.GetOffset()));
}
// If we have a mangled name, then the DW_AT_name attribute
// is usually the method name without the class or any parameters
@@ -846,32 +953,23 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
}
else
{
- if (specification_die_offset != DW_INVALID_OFFSET)
+ if (specification_die_form.IsValid())
{
- const DWARFDebugInfoEntry *specification_die = m_dwarf2Data->DebugInfo()->GetDIEPtr (specification_die_offset, NULL);
- if (specification_die)
- {
- parent = specification_die->GetParent();
- if (parent)
- {
- parent_tag = parent->Tag();
-
- if (parent_tag == DW_TAG_class_type || parent_tag == DW_TAG_structure_type)
- is_method = true;
- }
- }
+ DWARFDIE specification_die = dwarf_cu->GetSymbolFileDWARF()->DebugInfo()->GetDIE (DIERef(specification_die_form));
+ if (specification_die.GetParent().IsStructOrClass())
+ is_method = true;
}
}
}
if (is_method)
- func_methods.Insert (ConstString(name), die.GetOffset());
+ func_methods.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));
else
- func_basenames.Insert (ConstString(name), die.GetOffset());
+ func_basenames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));
if (!is_method && !mangled_cstr && !objc_method.IsValid(true))
- func_fullnames.Insert (ConstString(name), die.GetOffset());
+ func_fullnames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));
}
if (mangled_cstr)
{
@@ -882,10 +980,10 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (name && ::strcmp(name, mangled_cstr) != 0)))
{
Mangled mangled (ConstString(mangled_cstr), true);
- func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset());
+ func_fullnames.Insert (mangled.GetMangledName(), DIERef(cu_offset, die.GetOffset()));
ConstString demangled = mangled.GetDemangledName(cu_language);
if (demangled)
- func_fullnames.Insert (demangled, die.GetOffset());
+ func_fullnames.Insert (demangled, DIERef(cu_offset, die.GetOffset()));
}
}
}
@@ -895,7 +993,7 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
if (has_address)
{
if (name)
- func_basenames.Insert (ConstString(name), die.GetOffset());
+ func_basenames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));
if (mangled_cstr)
{
// Make sure our mangled name isn't the same string table entry
@@ -905,14 +1003,14 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0)))
{
Mangled mangled (ConstString(mangled_cstr), true);
- func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset());
+ func_fullnames.Insert (mangled.GetMangledName(), DIERef(cu_offset, die.GetOffset()));
ConstString demangled = mangled.GetDemangledName(cu_language);
if (demangled)
- func_fullnames.Insert (demangled, die.GetOffset());
+ func_fullnames.Insert (demangled, DIERef(cu_offset, die.GetOffset()));
}
}
else
- func_fullnames.Insert (ConstString(name), die.GetOffset());
+ func_fullnames.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));
}
break;
@@ -928,19 +1026,19 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
case DW_TAG_unspecified_type:
if (name && is_declaration == false)
{
- types.Insert (ConstString(name), die.GetOffset());
+ types.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));
}
break;
case DW_TAG_namespace:
if (name)
- namespaces.Insert (ConstString(name), die.GetOffset());
+ namespaces.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));
break;
case DW_TAG_variable:
- if (name && has_location && is_global_or_static_variable)
+ if (name && has_location_or_const_value && is_global_or_static_variable)
{
- globals.Insert (ConstString(name), die.GetOffset());
+ globals.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset()));
// Be sure to include variables by their mangled and demangled
// names if they have any since a variable can have a basename
// "i", a mangled named "_ZN12_GLOBAL__N_11iE" and a demangled
@@ -953,10 +1051,10 @@ DWARFCompileUnit::Index (const uint32_t cu_idx,
if (mangled_cstr && name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0)))
{
Mangled mangled (ConstString(mangled_cstr), true);
- globals.Insert (mangled.GetMangledName(), die.GetOffset());
+ globals.Insert (mangled.GetMangledName(), DIERef(cu_offset, die.GetOffset()));
ConstString demangled = mangled.GetDemangledName(cu_language);
if (demangled)
- globals.Insert (demangled, die.GetOffset());
+ globals.Insert (demangled, DIERef(cu_offset, die.GetOffset()));
}
}
break;
@@ -1004,7 +1102,7 @@ DWARFCompileUnit::ParseProducerInfo ()
m_producer_version_minor = UINT32_MAX;
m_producer_version_update = UINT32_MAX;
- const DWARFDebugInfoEntry *die = GetCompileUnitDIEOnly();
+ const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly();
if (die)
{
@@ -1095,10 +1193,9 @@ DWARFCompileUnit::GetLanguageType()
if (m_language_type != eLanguageTypeUnknown)
return m_language_type;
- const DWARFDebugInfoEntry *die = GetCompileUnitDIEOnly();
+ const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly();
if (die)
- m_language_type = LanguageTypeFromDWARF(
- die->GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_language, 0));
+ m_language_type = LanguageTypeFromDWARF(die->GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_language, 0));
return m_language_type;
}
@@ -1108,3 +1205,57 @@ DWARFCompileUnit::IsDWARF64() const
return m_is_dwarf64;
}
+bool
+DWARFCompileUnit::GetIsOptimized ()
+{
+ if (m_is_optimized == eLazyBoolCalculate)
+ {
+ const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly();
+ if (die)
+ {
+ m_is_optimized = eLazyBoolNo;
+ if (die->GetAttributeValueAsUnsigned (m_dwarf2Data, this, DW_AT_APPLE_optimized, 0) == 1)
+ {
+ m_is_optimized = eLazyBoolYes;
+ }
+ }
+ }
+ if (m_is_optimized == eLazyBoolYes)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+DWARFFormValue::FixedFormSizes
+DWARFCompileUnit::GetFixedFormSizes ()
+{
+ return DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), IsDWARF64());
+}
+
+TypeSystem *
+DWARFCompileUnit::GetTypeSystem ()
+{
+ if (m_dwarf2Data)
+ return m_dwarf2Data->GetTypeSystemForLanguage(GetLanguageType());
+ else
+ return nullptr;
+}
+
+void
+DWARFCompileUnit::SetUserData(void *d)
+{
+ m_user_data = d;
+ if (m_dwo_symbol_file)
+ m_dwo_symbol_file->GetCompileUnit()->SetUserData(d);
+}
+
+void
+DWARFCompileUnit::SetAddrBase(dw_addr_t addr_base, dw_offset_t base_obj_offset)
+{
+ m_addr_base = addr_base;
+ m_base_obj_offset = base_obj_offset;
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
index 93c8df822dcc..0fcaaca09ed8 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
@@ -12,9 +12,11 @@
#include "lldb/lldb-enumerations.h"
#include "DWARFDebugInfoEntry.h"
-#include "SymbolFileDWARF.h"
+#include "DWARFDIE.h"
class NameToDIE;
+class SymbolFileDWARF;
+class SymbolFileDWARFDwo;
class DWARFCompileUnit
{
@@ -29,19 +31,17 @@ public:
};
DWARFCompileUnit(SymbolFileDWARF* dwarf2Data);
+ ~DWARFCompileUnit();
bool Extract(const lldb_private::DWARFDataExtractor &debug_info, lldb::offset_t *offset_ptr);
size_t ExtractDIEsIfNeeded (bool cu_die_only);
- bool LookupAddress(
- const dw_addr_t address,
- DWARFDebugInfoEntry** function_die,
- DWARFDebugInfoEntry** block_die);
-
+ DWARFDIE LookupAddress(const dw_addr_t address);
size_t AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& matching_dies, uint32_t depth = UINT32_MAX) const;
void Clear();
bool Verify(lldb_private::Stream *s) const;
void Dump(lldb_private::Stream *s) const;
dw_offset_t GetOffset() const { return m_offset; }
+ lldb::user_id_t GetID () const;
uint32_t Size() const { return m_is_dwarf64 ? 23 : 11; /* Size in bytes of the compile unit header */ }
bool ContainsDIEOffset(dw_offset_t die_offset) const { return die_offset >= GetFirstDIEOffset() && die_offset < GetNextCompileUnitOffset(); }
dw_offset_t GetFirstDIEOffset() const { return m_offset + Size(); }
@@ -53,32 +53,35 @@ public:
dw_offset_t GetAbbrevOffset() const;
uint8_t GetAddressByteSize() const { return m_addr_size; }
dw_addr_t GetBaseAddress() const { return m_base_addr; }
+ dw_addr_t GetAddrBase() const { return m_addr_base; }
+ void SetAddrBase(dw_addr_t addr_base, dw_offset_t base_obj_offset);
void ClearDIEs(bool keep_compile_unit_die);
void BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
DWARFDebugAranges* debug_aranges);
+
+ lldb_private::TypeSystem *
+ GetTypeSystem();
+
+ DWARFFormValue::FixedFormSizes
+ GetFixedFormSizes ();
+
void
SetBaseAddress(dw_addr_t base_addr)
{
m_base_addr = base_addr;
}
- const DWARFDebugInfoEntry*
+ DWARFDIE
GetCompileUnitDIEOnly()
{
- ExtractDIEsIfNeeded (true);
- if (m_die_array.empty())
- return NULL;
- return &m_die_array[0];
+ return DWARFDIE(this, GetCompileUnitDIEPtrOnly());
}
- const DWARFDebugInfoEntry*
- DIE()
+ DWARFDIE
+ DIE ()
{
- ExtractDIEsIfNeeded (false);
- if (m_die_array.empty())
- return NULL;
- return &m_die_array[0];
+ return DWARFDIE(this, DIEPtr());
}
void
@@ -97,6 +100,9 @@ public:
m_die_array.reserve(GetDebugInfoSize() / 24);
m_die_array.push_back(die);
}
+
+ void
+ AddCompileUnitDIE (DWARFDebugInfoEntry& die);
bool
HasDIEsParsed () const
@@ -104,17 +110,8 @@ public:
return m_die_array.size() > 1;
}
- DWARFDebugInfoEntry*
- GetDIEAtIndexUnchecked (uint32_t idx)
- {
- return &m_die_array[idx];
- }
-
- DWARFDebugInfoEntry*
- GetDIEPtr (dw_offset_t die_offset);
-
- const DWARFDebugInfoEntry*
- GetDIEPtrContainingOffset (dw_offset_t die_offset);
+ DWARFDIE
+ GetDIE (dw_offset_t die_offset);
static uint8_t
GetAddressByteSize(const DWARFCompileUnit* cu);
@@ -135,10 +132,7 @@ public:
}
void
- SetUserData(void *d)
- {
- m_user_data = d;
- }
+ SetUserData(void *d);
bool
Supports_DW_AT_APPLE_objc_complete_type ();
@@ -149,15 +143,8 @@ public:
bool
Supports_unnamed_objc_bitfields ();
-// void
-// AddGlobalDIEByIndex (uint32_t die_idx);
-//
-// void
-// AddGlobal (const DWARFDebugInfoEntry* die);
-//
void
- Index (const uint32_t cu_idx,
- NameToDIE& func_basenames,
+ Index (NameToDIE& func_basenames,
NameToDIE& func_fullnames,
NameToDIE& func_methods,
NameToDIE& func_selectors,
@@ -196,8 +183,24 @@ public:
bool
IsDWARF64() const;
+ bool
+ GetIsOptimized ();
+
+ SymbolFileDWARFDwo*
+ GetDwoSymbolFile() const
+ {
+ return m_dwo_symbol_file.get();
+ }
+
+ dw_offset_t
+ GetBaseObjOffset() const
+ {
+ return m_base_obj_offset;
+ }
+
protected:
SymbolFileDWARF* m_dwarf2Data;
+ std::unique_ptr<SymbolFileDWARFDwo> m_dwo_symbol_file;
const DWARFAbbreviationDeclarationSet *m_abbrevs;
void * m_user_data;
DWARFDebugInfoEntry::collection m_die_array; // The compile unit debug information entry item
@@ -213,10 +216,49 @@ protected:
uint32_t m_producer_version_update;
lldb::LanguageType m_language_type;
bool m_is_dwarf64;
-
+ lldb_private::LazyBool m_is_optimized;
+ dw_addr_t m_addr_base; // Value of DW_AT_addr_base
+ dw_offset_t m_base_obj_offset; // If this is a dwo compile unit this is the offset of
+ // the base compile unit in the main object file
+
void
ParseProducerInfo ();
+
+ static void
+ IndexPrivate (DWARFCompileUnit* dwarf_cu,
+ const lldb::LanguageType cu_language,
+ const DWARFFormValue::FixedFormSizes& fixed_form_sizes,
+ const dw_offset_t cu_offset,
+ NameToDIE& func_basenames,
+ NameToDIE& func_fullnames,
+ NameToDIE& func_methods,
+ NameToDIE& func_selectors,
+ NameToDIE& objc_class_selectors,
+ NameToDIE& globals,
+ NameToDIE& types,
+ NameToDIE& namespaces);
+
private:
+
+ const DWARFDebugInfoEntry*
+ GetCompileUnitDIEPtrOnly()
+ {
+ ExtractDIEsIfNeeded (true);
+ if (m_die_array.empty())
+ return NULL;
+ return &m_die_array[0];
+ }
+
+ const DWARFDebugInfoEntry*
+ DIEPtr()
+ {
+ ExtractDIEsIfNeeded (false);
+ if (m_die_array.empty())
+ return NULL;
+ return &m_die_array[0];
+ }
+
+
DISALLOW_COPY_AND_ASSIGN (DWARFCompileUnit);
};
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
new file mode 100644
index 000000000000..0564de9e5dd1
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -0,0 +1,543 @@
+//===-- DWARFDIE.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDIE.h"
+
+#include "DWARFCompileUnit.h"
+#include "DWARFDebugAbbrev.h"
+#include "DWARFDebugAranges.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFDebugInfoEntry.h"
+#include "DWARFDebugRanges.h"
+#include "DWARFDeclContext.h"
+#include "DWARFDIECollection.h"
+#include "DWARFFormValue.h"
+#include "SymbolFileDWARF.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/TypeSystem.h"
+
+using namespace lldb_private;
+
+DIERef
+DWARFDIE::GetDIERef() const
+{
+ if (!IsValid())
+ return DIERef();
+
+ dw_offset_t cu_offset = m_cu->GetOffset();
+ if (m_cu->GetBaseObjOffset() != DW_INVALID_OFFSET)
+ cu_offset = m_cu->GetBaseObjOffset();
+ return DIERef(cu_offset, m_die->GetOffset());
+}
+
+dw_tag_t
+DWARFDIE::Tag() const
+{
+ if (m_die)
+ return m_die->Tag();
+ else
+ return 0;
+}
+
+const char *
+DWARFDIE::GetTagAsCString () const
+{
+ return lldb_private::DW_TAG_value_to_name (Tag());
+}
+
+DWARFDIE
+DWARFDIE::GetParent () const
+{
+ if (IsValid())
+ return DWARFDIE(m_cu, m_die->GetParent());
+ else
+ return DWARFDIE();
+}
+
+DWARFDIE
+DWARFDIE::GetFirstChild () const
+{
+ if (IsValid())
+ return DWARFDIE(m_cu, m_die->GetFirstChild());
+ else
+ return DWARFDIE();
+}
+
+DWARFDIE
+DWARFDIE::GetSibling () const
+{
+ if (IsValid())
+ return DWARFDIE(m_cu, m_die->GetSibling());
+ else
+ return DWARFDIE();
+}
+
+DWARFDIE
+DWARFDIE::GetReferencedDIE (const dw_attr_t attr) const
+{
+ const dw_offset_t die_offset = GetAttributeValueAsReference (attr, DW_INVALID_OFFSET);
+ if (die_offset != DW_INVALID_OFFSET)
+ return GetDIE(die_offset);
+ else
+ return DWARFDIE();
+}
+
+DWARFDIE
+DWARFDIE::GetDIE (dw_offset_t die_offset) const
+{
+ if (IsValid())
+ return m_cu->GetDIE(die_offset);
+ else
+ return DWARFDIE();
+}
+
+const char *
+DWARFDIE::GetAttributeValueAsString (const dw_attr_t attr, const char *fail_value) const
+{
+ if (IsValid())
+ return m_die->GetAttributeValueAsString(GetDWARF(), GetCU(), attr, fail_value);
+ else
+ return fail_value;
+}
+
+uint64_t
+DWARFDIE::GetAttributeValueAsUnsigned (const dw_attr_t attr, uint64_t fail_value) const
+{
+ if (IsValid())
+ return m_die->GetAttributeValueAsUnsigned(GetDWARF(), GetCU(), attr, fail_value);
+ else
+ return fail_value;
+}
+
+int64_t
+DWARFDIE::GetAttributeValueAsSigned (const dw_attr_t attr, int64_t fail_value) const
+{
+ if (IsValid())
+ return m_die->GetAttributeValueAsSigned(GetDWARF(), GetCU(), attr, fail_value);
+ else
+ return fail_value;
+}
+
+uint64_t
+DWARFDIE::GetAttributeValueAsReference (const dw_attr_t attr, uint64_t fail_value) const
+{
+ if (IsValid())
+ return m_die->GetAttributeValueAsReference(GetDWARF(), GetCU(), attr, fail_value);
+ else
+ return fail_value;
+}
+
+uint64_t
+DWARFDIE::GetAttributeValueAsAddress (const dw_attr_t attr, uint64_t fail_value) const
+{
+ if (IsValid())
+ return m_die->GetAttributeValueAsAddress(GetDWARF(), GetCU(), attr, fail_value);
+ else
+ return fail_value;
+}
+
+
+DWARFDIE
+DWARFDIE::LookupDeepestBlock (lldb::addr_t file_addr) const
+{
+ if (IsValid())
+ {
+ SymbolFileDWARF *dwarf= GetDWARF();
+ DWARFCompileUnit *cu = GetCU();
+ DWARFDebugInfoEntry* function_die = nullptr;
+ DWARFDebugInfoEntry* block_die = nullptr;
+ if (m_die->LookupAddress (file_addr,
+ dwarf,
+ cu,
+ &function_die,
+ &block_die))
+ {
+ if (block_die && block_die != function_die)
+ {
+ if (cu->ContainsDIEOffset(block_die->GetOffset()))
+ return DWARFDIE(cu, block_die);
+ else
+ return DWARFDIE(dwarf->DebugInfo()->GetCompileUnitContainingDIE(DIERef(cu->GetOffset(), block_die->GetOffset())), block_die);
+ }
+ }
+ }
+ return DWARFDIE();
+}
+
+lldb::user_id_t
+DWARFDIE::GetID () const
+{
+ const dw_offset_t die_offset = GetOffset();
+ if (die_offset != DW_INVALID_OFFSET)
+ {
+ lldb::user_id_t id = 0;
+ SymbolFileDWARF *dwarf = GetDWARF();
+ if (dwarf)
+ id = dwarf->MakeUserID(die_offset);
+ else
+ id = die_offset;
+
+ if (m_cu)
+ {
+ lldb::user_id_t cu_id = m_cu->GetID()&0xffffffff00000000ull;
+ assert ((id&0xffffffff00000000ull) == 0 ||
+ (cu_id&0xffffffff00000000ll) == 0 ||
+ (id&0xffffffff00000000ull) == (cu_id&0xffffffff00000000ll));
+ id |= cu_id;
+ }
+ return id;
+ }
+ return LLDB_INVALID_UID;
+}
+
+const char *
+DWARFDIE::GetName () const
+{
+ if (IsValid())
+ return m_die->GetName (GetDWARF(), m_cu);
+ else
+ return nullptr;
+}
+
+const char *
+DWARFDIE::GetMangledName () const
+{
+ if (IsValid())
+ return m_die->GetMangledName (GetDWARF(), m_cu);
+ else
+ return nullptr;
+}
+
+const char *
+DWARFDIE::GetPubname () const
+{
+ if (IsValid())
+ return m_die->GetPubname (GetDWARF(), m_cu);
+ else
+ return nullptr;
+}
+
+const char *
+DWARFDIE::GetQualifiedName (std::string &storage) const
+{
+ if (IsValid())
+ return m_die->GetQualifiedName (GetDWARF(), m_cu, storage);
+ else
+ return nullptr;
+}
+
+lldb::LanguageType
+DWARFDIE::GetLanguage () const
+{
+ if (IsValid())
+ return m_cu->GetLanguageType();
+ else
+ return lldb::eLanguageTypeUnknown;
+}
+
+
+lldb::ModuleSP
+DWARFDIE::GetModule () const
+{
+ SymbolFileDWARF *dwarf = GetDWARF();
+ if (dwarf)
+ return dwarf->GetObjectFile()->GetModule();
+ else
+ return lldb::ModuleSP();
+}
+
+lldb_private::CompileUnit *
+DWARFDIE::GetLLDBCompileUnit () const
+{
+ if (IsValid())
+ return GetDWARF()->GetCompUnitForDWARFCompUnit(GetCU());
+ else
+ return nullptr;
+}
+
+lldb_private::Type *
+DWARFDIE::ResolveType () const
+{
+ if (IsValid())
+ return GetDWARF()->ResolveType(*this, true);
+ else
+ return nullptr;
+}
+
+lldb_private::Type *
+DWARFDIE::ResolveTypeUID (lldb::user_id_t uid) const
+{
+ SymbolFileDWARF *dwarf = GetDWARF();
+ if (dwarf)
+ return dwarf->ResolveTypeUID(uid);
+ else
+ return nullptr;
+}
+
+void
+DWARFDIE::GetDeclContextDIEs (DWARFDIECollection &decl_context_dies) const
+{
+ if (IsValid())
+ {
+ DWARFDIE parent_decl_ctx_die = m_die->GetParentDeclContextDIE (GetDWARF(), GetCU());
+ if (parent_decl_ctx_die && parent_decl_ctx_die.GetDIE() != GetDIE())
+ {
+ decl_context_dies.Append(parent_decl_ctx_die);
+ parent_decl_ctx_die.GetDeclContextDIEs (decl_context_dies);
+ }
+ }
+}
+
+void
+DWARFDIE::GetDWARFDeclContext (DWARFDeclContext &dwarf_decl_ctx) const
+{
+ if (IsValid())
+ {
+ m_die->GetDWARFDeclContext (GetDWARF(), GetCU(), dwarf_decl_ctx);
+ }
+ else
+ {
+ dwarf_decl_ctx.Clear();
+ }
+}
+
+void
+DWARFDIE::GetDWOContext (std::vector<CompilerContext> &context) const
+{
+ const dw_tag_t tag = Tag();
+ if (tag == DW_TAG_compile_unit)
+ return;
+ DWARFDIE parent = GetParent();
+ if (parent)
+ parent.GetDWOContext(context);
+ switch (tag)
+ {
+ case DW_TAG_module:
+ context.push_back(CompilerContext(CompilerContextKind::Module, ConstString(GetName())));
+ break;
+ case DW_TAG_namespace:
+ context.push_back(CompilerContext(CompilerContextKind::Namespace, ConstString(GetName())));
+ break;
+ case DW_TAG_structure_type:
+ context.push_back(CompilerContext(CompilerContextKind::Structure, ConstString(GetName())));
+ break;
+ case DW_TAG_union_type:
+ context.push_back(CompilerContext(CompilerContextKind::Union, ConstString(GetName())));
+ break;
+ case DW_TAG_class_type:
+ context.push_back(CompilerContext(CompilerContextKind::Class, ConstString(GetName())));
+ break;
+ case DW_TAG_enumeration_type:
+ context.push_back(CompilerContext(CompilerContextKind::Enumeration, ConstString(GetName())));
+ break;
+ case DW_TAG_subprogram:
+ context.push_back(CompilerContext(CompilerContextKind::Function, ConstString(GetPubname())));
+ break;
+ case DW_TAG_variable:
+ context.push_back(CompilerContext(CompilerContextKind::Variable, ConstString(GetPubname())));
+ break;
+ case DW_TAG_typedef:
+ context.push_back(CompilerContext(CompilerContextKind::Typedef, ConstString(GetName())));
+ break;
+ default:
+ break;
+ }
+}
+
+
+
+DWARFDIE
+DWARFDIE::GetParentDeclContextDIE () const
+{
+ if (IsValid())
+ return m_die->GetParentDeclContextDIE(GetDWARF(), m_cu);
+ else
+ return DWARFDIE();
+}
+
+
+dw_offset_t
+DWARFDIE::GetOffset () const
+{
+ if (IsValid())
+ return m_die->GetOffset();
+ else
+ return DW_INVALID_OFFSET;
+}
+
+dw_offset_t
+DWARFDIE::GetCompileUnitRelativeOffset () const
+{
+ if (IsValid())
+ return m_die->GetOffset() - m_cu->GetOffset();
+ else
+ return DW_INVALID_OFFSET;
+}
+
+SymbolFileDWARF *
+DWARFDIE::GetDWARF () const
+{
+ if (m_cu)
+ return m_cu->GetSymbolFileDWARF();
+ else
+ return nullptr;
+}
+
+lldb_private::TypeSystem *
+DWARFDIE::GetTypeSystem () const
+{
+ if (m_cu)
+ return m_cu->GetTypeSystem();
+ else
+ return nullptr;
+}
+
+DWARFASTParser *
+DWARFDIE::GetDWARFParser () const
+{
+ lldb_private::TypeSystem *type_system = GetTypeSystem ();
+ if (type_system)
+ return type_system->GetDWARFParser();
+ else
+ return nullptr;
+}
+
+bool
+DWARFDIE::IsStructOrClass () const
+{
+ const dw_tag_t tag = Tag();
+ return tag == DW_TAG_class_type || tag == DW_TAG_structure_type;
+}
+
+
+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)
+ 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::HasChildren () const
+{
+ if (m_die)
+ return m_die->HasChildren();
+ else
+ return false;
+}
+
+bool
+DWARFDIE::Supports_DW_AT_APPLE_objc_complete_type () const
+{
+ if (IsValid())
+ return GetDWARF()->Supports_DW_AT_APPLE_objc_complete_type(m_cu);
+ else
+ return false;
+}
+
+size_t
+DWARFDIE::GetAttributes (DWARFAttributes &attributes, uint32_t depth) const
+{
+ if (IsValid())
+ {
+ return m_die->GetAttributes (m_cu,
+ m_cu->GetFixedFormSizes(),
+ attributes,
+ depth);
+ }
+ if (depth == 0)
+ attributes.Clear();
+ return 0;
+}
+
+
+bool
+DWARFDIE::GetDIENamesAndRanges (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,
+ lldb_private::DWARFExpression *frame_base) const
+{
+ if (IsValid())
+ {
+ return m_die->GetDIENamesAndRanges (GetDWARF(),
+ GetCU(),
+ name,
+ mangled,
+ ranges,
+ decl_file,
+ decl_line,
+ decl_column,
+ call_file,
+ call_line,
+ call_column,
+ frame_base);
+ }
+ else
+ return false;
+}
+
+void
+DWARFDIE::Dump (lldb_private::Stream *s, const uint32_t recurse_depth) const
+{
+ if (s && IsValid())
+ m_die->Dump (GetDWARF(), GetCU(), *s, recurse_depth);
+}
+
+
+bool operator == (const DWARFDIE &lhs, const DWARFDIE &rhs)
+{
+ return lhs.GetDIE() == rhs.GetDIE() && lhs.GetCU() == rhs.GetCU();
+}
+
+bool operator != (const DWARFDIE &lhs, const DWARFDIE &rhs)
+{
+ return lhs.GetDIE() != rhs.GetDIE() || lhs.GetCU() != rhs.GetCU();
+}
+
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
new file mode 100644
index 000000000000..db37a45ad01a
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
@@ -0,0 +1,281 @@
+//===-- DWARFDIE.h ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFDIE_h_
+#define SymbolFileDWARF_DWARFDIE_h_
+
+#include "lldb/lldb-types.h"
+#include "lldb/Core/dwarf.h"
+
+struct DIERef;
+class DWARFASTParser;
+class DWARFAttributes;
+class DWARFCompileUnit;
+class DWARFDebugInfoEntry;
+class DWARFDeclContext;
+class DWARFDIECollection;
+class SymbolFileDWARF;
+
+class DWARFDIE
+{
+public:
+ DWARFDIE () :
+ m_cu (nullptr),
+ m_die (nullptr)
+ {
+ }
+
+ DWARFDIE (DWARFCompileUnit *cu, DWARFDebugInfoEntry *die) :
+ m_cu (cu),
+ m_die (die)
+ {
+ }
+
+ DWARFDIE (const DWARFCompileUnit *cu, DWARFDebugInfoEntry *die) :
+ m_cu (const_cast<DWARFCompileUnit *>(cu)),
+ m_die (die)
+ {
+ }
+
+ DWARFDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die) :
+ m_cu (cu),
+ m_die (const_cast<DWARFDebugInfoEntry *>(die))
+ {
+ }
+
+ DWARFDIE (const DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die) :
+ m_cu (const_cast<DWARFCompileUnit *>(cu)),
+ m_die (const_cast<DWARFDebugInfoEntry *>(die))
+ {
+ }
+
+ //----------------------------------------------------------------------
+ // Tests
+ //----------------------------------------------------------------------
+ operator bool () const
+ {
+ return IsValid();
+ }
+
+ bool
+ IsValid() const
+ {
+ return m_cu && m_die;
+ }
+
+ bool
+ IsStructOrClass () const;
+
+ bool
+ HasChildren () const;
+
+ bool
+ Supports_DW_AT_APPLE_objc_complete_type () const;
+
+ //----------------------------------------------------------------------
+ // Accessors
+ //----------------------------------------------------------------------
+ SymbolFileDWARF *
+ GetDWARF () const;
+
+ DWARFCompileUnit *
+ GetCU() const
+ {
+ return m_cu;
+ }
+
+ DWARFDebugInfoEntry *
+ GetDIE() const
+ {
+ return m_die;
+ }
+
+ DIERef
+ GetDIERef() const;
+
+ lldb_private::TypeSystem *
+ GetTypeSystem () const;
+
+ DWARFASTParser *
+ GetDWARFParser () const;
+
+ void
+ Set (DWARFCompileUnit *cu, DWARFDebugInfoEntry *die)
+ {
+ if (cu && die)
+ {
+ m_cu = cu;
+ m_die = die;
+ }
+ else
+ {
+ Clear();
+ }
+ }
+
+ void
+ Clear ()
+ {
+ m_cu = nullptr;
+ m_die = nullptr;
+ }
+
+ lldb::ModuleSP
+ GetContainingDWOModule () const;
+
+ DWARFDIE
+ GetContainingDWOModuleDIE () const;
+
+ //----------------------------------------------------------------------
+ // Accessing information about a DIE
+ //----------------------------------------------------------------------
+ dw_tag_t
+ Tag() const;
+
+ const char *
+ GetTagAsCString () const;
+
+ dw_offset_t
+ GetOffset () const;
+
+ dw_offset_t
+ GetCompileUnitRelativeOffset () const;
+
+ //----------------------------------------------------------------------
+ // Get the LLDB user ID for this DIE. This is often just the DIE offset,
+ // but it might have a SymbolFileDWARF::GetID() in the high 32 bits if
+ // we are doing Darwin DWARF in .o file, or DWARF stand alone debug
+ // info.
+ //----------------------------------------------------------------------
+ lldb::user_id_t
+ GetID() const;
+
+ const char *
+ GetName () const;
+
+ const char *
+ GetMangledName () const;
+
+ const char *
+ GetPubname () const;
+
+ const char *
+ GetQualifiedName (std::string &storage) const;
+
+ lldb::LanguageType
+ GetLanguage () const;
+
+ lldb::ModuleSP
+ GetModule () const;
+
+ lldb_private::CompileUnit *
+ GetLLDBCompileUnit () const;
+
+ lldb_private::Type *
+ ResolveType () const;
+
+ // Resolve a type by UID using this DIE's DWARF file
+ lldb_private::Type *
+ ResolveTypeUID (lldb::user_id_t uid) const;
+
+ //----------------------------------------------------------------------
+ // Functions for obtaining DIE relations and references
+ //----------------------------------------------------------------------
+
+ DWARFDIE
+ GetParent () const;
+
+ DWARFDIE
+ GetFirstChild () const;
+
+ DWARFDIE
+ GetSibling () const;
+
+ DWARFDIE
+ GetReferencedDIE (const dw_attr_t attr) const;
+
+ //----------------------------------------------------------------------
+ // Get a another DIE from the same DWARF file as this DIE. This will
+ // check the current DIE's compile unit first to see if "die_offset" is
+ // in the same compile unit, and fall back to checking the DWARF file.
+ //----------------------------------------------------------------------
+ DWARFDIE
+ GetDIE (dw_offset_t die_offset) const;
+
+ DWARFDIE
+ LookupDeepestBlock (lldb::addr_t file_addr) const;
+
+ DWARFDIE
+ GetParentDeclContextDIE () const;
+
+ //----------------------------------------------------------------------
+ // DeclContext related functions
+ //----------------------------------------------------------------------
+ void
+ GetDeclContextDIEs (DWARFDIECollection &decl_context_dies) const;
+
+ void
+ GetDWARFDeclContext (DWARFDeclContext &dwarf_decl_ctx) const;
+
+ void
+ GetDWOContext (std::vector<lldb_private::CompilerContext> &context) const;
+
+ //----------------------------------------------------------------------
+ // Getting attribute values from the DIE.
+ //
+ // GetAttributeValueAsXXX() functions should only be used if you are
+ // looking for one or two attributes on a DIE. If you are trying to
+ // parse all attributes, use GetAttributes (...) instead
+ //----------------------------------------------------------------------
+ const char *
+ GetAttributeValueAsString (const dw_attr_t attr, const char *fail_value) const;
+
+ uint64_t
+ GetAttributeValueAsUnsigned (const dw_attr_t attr, uint64_t fail_value) const;
+
+ int64_t
+ GetAttributeValueAsSigned (const dw_attr_t attr, int64_t fail_value) const;
+
+ uint64_t
+ GetAttributeValueAsReference (const dw_attr_t attr, uint64_t fail_value) const;
+
+ uint64_t
+ GetAttributeValueAsAddress (const dw_attr_t attr, uint64_t fail_value) const;
+
+ size_t
+ GetAttributes (DWARFAttributes &attributes, uint32_t depth = 0) const;
+
+ bool
+ GetDIENamesAndRanges (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,
+ lldb_private::DWARFExpression *frame_base) const;
+
+ //----------------------------------------------------------------------
+ // Pretty printing
+ //----------------------------------------------------------------------
+
+ void
+ Dump (lldb_private::Stream *s, const uint32_t recurse_depth) const;
+
+protected:
+ DWARFCompileUnit *m_cu;
+ DWARFDebugInfoEntry *m_die;
+};
+
+bool operator == (const DWARFDIE &lhs, const DWARFDIE &rhs);
+bool operator != (const DWARFDIE &lhs, const DWARFDIE &rhs);
+
+#endif // SymbolFileDWARF_DWARFDIE_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp
index 1beb75d33642..9e021c7185bd 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp
@@ -13,13 +13,11 @@
#include "lldb/Core/Stream.h"
-#include "DWARFDebugInfoEntry.h"
-
using namespace lldb_private;
using namespace std;
bool
-DWARFDIECollection::Insert(const DWARFDebugInfoEntry *die)
+DWARFDIECollection::Insert(const DWARFDIE &die)
{
iterator end_pos = m_dies.end();
iterator insert_pos = upper_bound(m_dies.begin(), end_pos, die);
@@ -30,17 +28,17 @@ DWARFDIECollection::Insert(const DWARFDebugInfoEntry *die)
}
void
-DWARFDIECollection::Append (const DWARFDebugInfoEntry *die)
+DWARFDIECollection::Append (const DWARFDIE &die)
{
m_dies.push_back (die);
}
-const DWARFDebugInfoEntry *
-DWARFDIECollection::GetDIEPtrAtIndex(uint32_t idx) const
+DWARFDIE
+DWARFDIECollection::GetDIEAtIndex(uint32_t idx) const
{
if (idx < m_dies.size())
return m_dies[idx];
- return NULL;
+ return DWARFDIE();
}
@@ -55,8 +53,6 @@ DWARFDIECollection::Dump(Stream *s, const char* title) const
{
if (title && title[0] != '\0')
s->Printf( "%s\n", title);
- const_iterator end_pos = m_dies.end();
- const_iterator pos;
- for (pos = m_dies.begin(); pos != end_pos; ++pos)
- s->Printf( "0x%8.8x\n", (*pos)->GetOffset());
+ for (const auto &die : m_dies)
+ s->Printf( "0x%8.8x\n", die.GetOffset());
}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h
index 173d0a5604d0..e39e1aa4ccda 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h
@@ -10,7 +10,7 @@
#ifndef SymbolFileDWARF_DWARFDIECollection_h_
#define SymbolFileDWARF_DWARFDIECollection_h_
-#include "SymbolFileDWARF.h"
+#include "DWARFDIE.h"
#include <vector>
class DWARFDIECollection
@@ -25,22 +25,22 @@ public:
}
void
- Append (const DWARFDebugInfoEntry *die);
+ Append (const DWARFDIE &die);
void
Dump(lldb_private::Stream *s, const char* title) const;
- const DWARFDebugInfoEntry*
- GetDIEPtrAtIndex(uint32_t idx) const;
+ DWARFDIE
+ GetDIEAtIndex (uint32_t idx) const;
bool
- Insert(const DWARFDebugInfoEntry *die);
+ Insert(const DWARFDIE &die);
size_t
Size() const;
protected:
- typedef std::vector<const DWARFDebugInfoEntry *> collection;
+ typedef std::vector<DWARFDIE> collection;
typedef collection::iterator iterator;
typedef collection::const_iterator const_iterator;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
index ba2e8ad08acc..0281b5ad5c89 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
@@ -19,10 +19,10 @@ namespace lldb_private {
class DWARFDataExtractor : public lldb_private::DataExtractor
{
public:
- DWARFDataExtractor() : DataExtractor(), m_is_dwarf64(false) { };
+ DWARFDataExtractor() : DataExtractor(), m_is_dwarf64(false) { }
DWARFDataExtractor (const DWARFDataExtractor& data, lldb::offset_t offset, lldb::offset_t length) :
- DataExtractor(data, offset, length), m_is_dwarf64(false) { };
+ DataExtractor(data, offset, length), m_is_dwarf64(false) { }
uint64_t
GetDWARFInitialLength(lldb::offset_t *offset_ptr) const;
@@ -43,4 +43,3 @@ protected:
}
#endif // liblldb_DWARFDataExtractor_h_
-
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
index 393434800c01..a1b00d1892e9 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -103,57 +103,6 @@ DWARFDebugInfo::GetCompileUnitAranges ()
return *m_cu_aranges_ap.get();
}
-
-//----------------------------------------------------------------------
-// LookupAddress
-//----------------------------------------------------------------------
-bool
-DWARFDebugInfo::LookupAddress
-(
- const dw_addr_t address,
- const dw_offset_t hint_die_offset,
- DWARFCompileUnitSP& cu_sp,
- DWARFDebugInfoEntry** function_die,
- DWARFDebugInfoEntry** block_die
-)
-{
-
- if (hint_die_offset != DW_INVALID_OFFSET)
- cu_sp = GetCompileUnit(hint_die_offset);
- else
- {
- DWARFDebugAranges &cu_aranges = GetCompileUnitAranges ();
- const dw_offset_t cu_offset = cu_aranges.FindAddress (address);
- cu_sp = GetCompileUnit(cu_offset);
- }
-
- if (cu_sp.get())
- {
- if (cu_sp->LookupAddress(address, function_die, block_die))
- return true;
- cu_sp.reset();
- }
- else
- {
- // The hint_die_offset may have been a pointer to the actual item that
- // we are looking for
- DWARFDebugInfoEntry* die_ptr = GetDIEPtr(hint_die_offset, &cu_sp);
- if (die_ptr)
- {
- if (cu_sp.get())
- {
- if (function_die || block_die)
- return die_ptr->LookupAddress(address, m_dwarf2Data, cu_sp.get(), function_die, block_die);
-
- // We only wanted the compile unit that contained this address
- return true;
- }
- }
- }
- return false;
-}
-
-
void
DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded()
{
@@ -213,19 +162,13 @@ DWARFDebugInfo::ContainsCompileUnit (const DWARFCompileUnit *cu) const
return false;
}
-static int
-CompareDWARFCompileUnitSPOffset (const void *key, const void *arrmem)
+bool
+DWARFDebugInfo::OffsetLessThanCompileUnitOffset (dw_offset_t offset, const DWARFCompileUnitSP& cu_sp)
{
- const dw_offset_t key_cu_offset = *(dw_offset_t*) key;
- const dw_offset_t cu_offset = ((DWARFCompileUnitSP *)arrmem)->get()->GetOffset();
- if (key_cu_offset < cu_offset)
- return -1;
- if (key_cu_offset > cu_offset)
- return 1;
- return 0;
+ return offset < cu_sp->GetOffset();
}
-DWARFCompileUnitSP
+DWARFCompileUnit *
DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr)
{
DWARFCompileUnitSP cu_sp;
@@ -234,41 +177,80 @@ DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr)
{
ParseCompileUnitHeadersIfNeeded();
- DWARFCompileUnitSP* match = (DWARFCompileUnitSP*)bsearch(&cu_offset, &m_compile_units[0], m_compile_units.size(), sizeof(DWARFCompileUnitSP), CompareDWARFCompileUnitSPOffset);
- if (match)
+ // Watch out for single compile unit executable as they are pretty common
+ const size_t num_cus = m_compile_units.size();
+ if (num_cus == 1)
{
- cu_sp = *match;
- cu_idx = match - &m_compile_units[0];
+ if (m_compile_units[0]->GetOffset() == cu_offset)
+ {
+ cu_sp = m_compile_units[0];
+ cu_idx = 0;
+ }
+ }
+ else if (num_cus)
+ {
+ CompileUnitColl::const_iterator end_pos = m_compile_units.end();
+ CompileUnitColl::const_iterator begin_pos = m_compile_units.begin();
+ CompileUnitColl::const_iterator pos = std::upper_bound(begin_pos, end_pos, cu_offset, OffsetLessThanCompileUnitOffset);
+ if (pos != begin_pos)
+ {
+ --pos;
+ if ((*pos)->GetOffset() == cu_offset)
+ {
+ cu_sp = *pos;
+ cu_idx = std::distance(begin_pos, pos);
+ }
+ }
}
}
if (idx_ptr)
*idx_ptr = cu_idx;
- return cu_sp;
+ return cu_sp.get();
}
-DWARFCompileUnitSP
-DWARFDebugInfo::GetCompileUnitContainingDIE(dw_offset_t die_offset)
+DWARFCompileUnit *
+DWARFDebugInfo::GetCompileUnitContainingDIE (const DIERef& die_ref)
{
+ dw_offset_t search_offset = die_ref.die_offset;
+ bool is_cu_offset = false;
+ if (m_dwarf2Data->GetID() == 0 && die_ref.cu_offset != DW_INVALID_OFFSET)
+ {
+ is_cu_offset = true;
+ search_offset = die_ref.cu_offset;
+ }
+
DWARFCompileUnitSP cu_sp;
- if (die_offset != DW_INVALID_OFFSET)
+ if (search_offset != DW_INVALID_OFFSET)
{
ParseCompileUnitHeadersIfNeeded();
- CompileUnitColl::const_iterator end_pos = m_compile_units.end();
- CompileUnitColl::const_iterator pos;
-
- for (pos = m_compile_units.begin(); pos != end_pos; ++pos)
+ // Watch out for single compile unit executable as they are pretty common
+ const size_t num_cus = m_compile_units.size();
+ if (num_cus == 1)
{
- dw_offset_t cu_start_offset = (*pos)->GetOffset();
- dw_offset_t cu_end_offset = (*pos)->GetNextCompileUnitOffset();
- if (cu_start_offset <= die_offset && die_offset < cu_end_offset)
+ if ((is_cu_offset && m_compile_units[0]->GetOffset() == search_offset) ||
+ (!is_cu_offset && m_compile_units[0]->ContainsDIEOffset(search_offset)))
{
- cu_sp = *pos;
- break;
+ cu_sp = m_compile_units[0];
+ }
+ }
+ else if (num_cus)
+ {
+ CompileUnitColl::const_iterator end_pos = m_compile_units.end();
+ CompileUnitColl::const_iterator begin_pos = m_compile_units.begin();
+ CompileUnitColl::const_iterator pos = std::upper_bound(begin_pos, end_pos, search_offset, OffsetLessThanCompileUnitOffset);
+ if (pos != begin_pos)
+ {
+ --pos;
+ if ((is_cu_offset && (*pos)->GetOffset() == search_offset) ||
+ (!is_cu_offset && (*pos)->ContainsDIEOffset(search_offset)))
+ {
+ cu_sp = *pos;
+ }
}
}
}
- return cu_sp;
+ return cu_sp.get();
}
//----------------------------------------------------------------------
@@ -276,73 +258,15 @@ DWARFDebugInfo::GetCompileUnitContainingDIE(dw_offset_t die_offset)
//
// Get the DIE (Debug Information Entry) with the specified offset.
//----------------------------------------------------------------------
-DWARFDebugInfoEntry*
-DWARFDebugInfo::GetDIEPtr(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr)
-{
- DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset));
- if (cu_sp_ptr)
- *cu_sp_ptr = cu_sp;
- if (cu_sp.get())
- return cu_sp->GetDIEPtr(die_offset);
- return NULL; // Not found in any compile units
-}
-
-DWARFDebugInfoEntry*
-DWARFDebugInfo::GetDIEPtrWithCompileUnitHint (dw_offset_t die_offset, DWARFCompileUnit**cu_handle)
-{
- assert (cu_handle);
- DWARFDebugInfoEntry* die = NULL;
- if (*cu_handle)
- die = (*cu_handle)->GetDIEPtr(die_offset);
-
- if (die == NULL)
- {
- DWARFCompileUnitSP cu_sp (GetCompileUnitContainingDIE(die_offset));
- if (cu_sp.get())
- {
- *cu_handle = cu_sp.get();
- die = cu_sp->GetDIEPtr(die_offset);
- }
- }
- if (die == NULL)
- *cu_handle = NULL;
- return die;
-}
-
-
-const DWARFDebugInfoEntry*
-DWARFDebugInfo::GetDIEPtrContainingOffset(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr)
-{
- DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset));
- if (cu_sp_ptr)
- *cu_sp_ptr = cu_sp;
- if (cu_sp.get())
- return cu_sp->GetDIEPtrContainingOffset(die_offset);
-
- return NULL; // Not found in any compile units
-
-}
-
-//----------------------------------------------------------------------
-// AddCompileUnit
-//----------------------------------------------------------------------
-void
-DWARFDebugInfo::AddCompileUnit(DWARFCompileUnitSP& cu)
+DWARFDIE
+DWARFDebugInfo::GetDIE(const DIERef& die_ref)
{
- m_compile_units.push_back(cu);
+ DWARFCompileUnit *cu = GetCompileUnitContainingDIE(die_ref);
+ if (cu)
+ return cu->GetDIE (die_ref.die_offset);
+ return DWARFDIE(); // Not found
}
-/*
-void
-DWARFDebugInfo::AddDIE(DWARFDebugInfoEntry& die)
-{
- m_die_array.push_back(die);
-}
-*/
-
-
-
-
//----------------------------------------------------------------------
// Parse
//
@@ -372,7 +296,7 @@ DWARFDebugInfo::Parse(SymbolFileDWARF* dwarf2Data, Callback callback, void* user
depth = 0;
// Call the callback function with no DIE pointer for the compile unit
// and get the offset that we are to continue to parse from
- offset = callback(dwarf2Data, cu, NULL, offset, depth, userData);
+ offset = callback(dwarf2Data, cu.get(), NULL, offset, depth, userData);
// Make sure we are within our compile unit
if (offset < next_cu_offset)
@@ -383,7 +307,7 @@ DWARFDebugInfo::Parse(SymbolFileDWARF* dwarf2Data, Callback callback, void* user
while (!done && die.Extract(dwarf2Data, cu.get(), &offset))
{
// Call the callback function with DIE pointer that falls within the compile unit
- offset = callback(dwarf2Data, cu, &die, offset, depth, userData);
+ offset = callback(dwarf2Data, cu.get(), &die, offset, depth, userData);
if (die.IsNULL())
{
@@ -450,7 +374,7 @@ typedef struct DumpInfo
static dw_offset_t DumpCallback
(
SymbolFileDWARF* dwarf2Data,
- DWARFCompileUnitSP& cu_sp,
+ DWARFCompileUnit* cu,
DWARFDebugInfoEntry* die,
const dw_offset_t next_offset,
const uint32_t curr_depth,
@@ -458,9 +382,6 @@ static dw_offset_t DumpCallback
)
{
DumpInfo* dumpInfo = (DumpInfo*)userData;
-
- const DWARFCompileUnit* cu = cu_sp.get();
-
Stream *s = dumpInfo->strm;
bool show_parents = s->GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowAncestors);
@@ -676,12 +597,12 @@ DWARFDebugInfo::Dump (Stream *s, const uint32_t die_offset, const uint32_t recur
ParseCompileUnitHeadersIfNeeded();
for (pos = m_compile_units.begin(); pos != m_compile_units.end(); ++pos)
{
- const DWARFCompileUnitSP& cu_sp = *pos;
- DumpCallback(m_dwarf2Data, (DWARFCompileUnitSP&)cu_sp, NULL, 0, curr_depth, &dumpInfo);
+ DWARFCompileUnit *cu = pos->get();
+ DumpCallback(m_dwarf2Data, cu, NULL, 0, curr_depth, &dumpInfo);
- const DWARFDebugInfoEntry* die = cu_sp->DIE();
+ const DWARFDIE die = cu->DIE();
if (die)
- die->Dump(m_dwarf2Data, cu_sp.get(), *s, recurse_depth);
+ die.Dump(s, recurse_depth);
}
}
@@ -707,7 +628,7 @@ typedef struct FindCallbackStringInfoTag
static dw_offset_t FindCallbackString
(
SymbolFileDWARF* dwarf2Data,
- DWARFCompileUnitSP& cu_sp,
+ DWARFCompileUnit* cu,
DWARFDebugInfoEntry* die,
const dw_offset_t next_offset,
const uint32_t curr_depth,
@@ -715,7 +636,6 @@ static dw_offset_t FindCallbackString
)
{
FindCallbackStringInfo* info = (FindCallbackStringInfo*)userData;
- const DWARFCompileUnit* cu = cu_sp.get();
if (die)
{
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
index 50a7ae76921f..ea2e204db702 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
@@ -16,19 +16,18 @@
#include "lldb/lldb-private.h"
#include "lldb/lldb-private.h"
#include "SymbolFileDWARF.h"
+#include "DWARFDIE.h"
typedef std::multimap<const char*, dw_offset_t, CStringCompareFunctionObject> CStringToDIEMap;
typedef CStringToDIEMap::iterator CStringToDIEMapIter;
typedef CStringToDIEMap::const_iterator CStringToDIEMapConstIter;
-typedef std::shared_ptr<DWARFCompileUnit> DWARFCompileUnitSP;
-
class DWARFDebugInfo
{
public:
typedef dw_offset_t (*Callback)(
SymbolFileDWARF* dwarf2Data,
- DWARFCompileUnitSP& cu_shared_ptr,
+ DWARFCompileUnit* cu,
DWARFDebugInfoEntry* die,
const dw_offset_t next_offset,
const uint32_t depth,
@@ -37,24 +36,13 @@ public:
DWARFDebugInfo();
void SetDwarfData(SymbolFileDWARF* dwarf2Data);
- bool LookupAddress(
- const dw_addr_t address,
- const dw_offset_t cu_offset, // Can be valid (find in .debug_aranges), or DW_INVALID_OFFSET if we need to search manually
- DWARFCompileUnitSP& cu_shared_ptr,
- DWARFDebugInfoEntry** function_die,
- DWARFDebugInfoEntry** block_die);
-
- void AddCompileUnit(DWARFCompileUnitSP& cu);
size_t GetNumCompileUnits();
bool ContainsCompileUnit (const DWARFCompileUnit *cu) const;
- DWARFCompileUnit* GetCompileUnitAtIndex(uint32_t idx);
- DWARFCompileUnitSP GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr = NULL);
- DWARFCompileUnitSP GetCompileUnitContainingDIE(dw_offset_t die_offset);
+ DWARFCompileUnit* GetCompileUnitAtIndex (uint32_t idx);
+ DWARFCompileUnit* GetCompileUnit (dw_offset_t cu_offset, uint32_t* idx_ptr = NULL);
+ DWARFCompileUnit* GetCompileUnitContainingDIE (const DIERef& die_ref);
- DWARFDebugInfoEntry* GetDIEPtr(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr);
- DWARFDebugInfoEntry* GetDIEPtrWithCompileUnitHint (dw_offset_t die_offset, DWARFCompileUnit**cu_handle);
-
- const DWARFDebugInfoEntry* GetDIEPtrContainingOffset(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr);
+ DWARFDIE GetDIE (const DIERef& die_ref);
void Dump(lldb_private::Stream *s, const uint32_t die_offset, const uint32_t recurse_depth);
static void Parse(SymbolFileDWARF* parser, Callback callback, void* userData);
@@ -74,8 +62,17 @@ public:
GetCompileUnitAranges ();
protected:
- SymbolFileDWARF* m_dwarf2Data;
+ typedef std::shared_ptr<DWARFCompileUnit> DWARFCompileUnitSP;
+
+ static bool
+ OffsetLessThanCompileUnitOffset (dw_offset_t offset, const DWARFCompileUnitSP& cu_sp);
+
typedef std::vector<DWARFCompileUnitSP> CompileUnitColl;
+
+ //----------------------------------------------------------------------
+ // Member variables
+ //----------------------------------------------------------------------
+ SymbolFileDWARF* m_dwarf2Data;
CompileUnitColl m_compile_units;
std::unique_ptr<DWARFDebugAranges> m_cu_aranges_ap; // A quick address to compile unit table
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
index 0ad1f1a3a95a..b9d825489aef 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -19,107 +19,26 @@
#include "lldb/Symbol/ObjectFile.h"
#include "DWARFCompileUnit.h"
-#include "SymbolFileDWARF.h"
#include "DWARFDebugAbbrev.h"
#include "DWARFDebugAranges.h"
#include "DWARFDebugInfo.h"
#include "DWARFDeclContext.h"
#include "DWARFDIECollection.h"
#include "DWARFFormValue.h"
-#include "DWARFLocationDescription.h"
-#include "DWARFLocationList.h"
#include "DWARFDebugRanges.h"
+#include "SymbolFileDWARF.h"
+#include "SymbolFileDWARFDwo.h"
using namespace lldb_private;
using namespace std;
extern int g_verbose;
-
-
-DWARFDebugInfoEntry::Attributes::Attributes() :
- m_infos()
-{
-}
-
-DWARFDebugInfoEntry::Attributes::~Attributes()
-{
-}
-
-
-uint32_t
-DWARFDebugInfoEntry::Attributes::FindAttributeIndex(dw_attr_t attr) const
-{
- collection::const_iterator end = m_infos.end();
- collection::const_iterator beg = m_infos.begin();
- collection::const_iterator pos;
- for (pos = beg; pos != end; ++pos)
- {
- if (pos->attr == attr)
- return std::distance(beg, pos);
- }
- return UINT32_MAX;
-}
-
-void
-DWARFDebugInfoEntry::Attributes::Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form)
-{
- Info info = { cu, attr_die_offset, attr, form };
- m_infos.push_back(info);
-}
-
-bool
-DWARFDebugInfoEntry::Attributes::ContainsAttribute(dw_attr_t attr) const
-{
- return FindAttributeIndex(attr) != UINT32_MAX;
-}
-
-bool
-DWARFDebugInfoEntry::Attributes::RemoveAttribute(dw_attr_t attr)
-{
- uint32_t attr_index = FindAttributeIndex(attr);
- if (attr_index != UINT32_MAX)
- {
- m_infos.erase(m_infos.begin() + attr_index);
- return true;
- }
- return false;
-}
-
-bool
-DWARFDebugInfoEntry::Attributes::ExtractFormValueAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, DWARFFormValue &form_value) const
-{
- form_value.SetCompileUnit(CompileUnitAtIndex(i));
- form_value.SetForm(FormAtIndex(i));
- lldb::offset_t offset = DIEOffsetAtIndex(i);
- return form_value.ExtractValue(dwarf2Data->get_debug_info_data(), &offset);
-}
-
-uint64_t
-DWARFDebugInfoEntry::Attributes::FormValueAsUnsigned (SymbolFileDWARF* dwarf2Data, dw_attr_t attr, uint64_t fail_value) const
-{
- const uint32_t attr_idx = FindAttributeIndex (attr);
- if (attr_idx != UINT32_MAX)
- return FormValueAsUnsignedAtIndex (dwarf2Data, attr_idx, fail_value);
- return fail_value;
-}
-
-uint64_t
-DWARFDebugInfoEntry::Attributes::FormValueAsUnsignedAtIndex(SymbolFileDWARF* dwarf2Data, uint32_t i, uint64_t fail_value) const
-{
- DWARFFormValue form_value;
- if (ExtractFormValueAtIndex(dwarf2Data, i, form_value))
- return form_value.Reference();
- return fail_value;
-}
-
-
-
bool
DWARFDebugInfoEntry::FastExtract
(
const DWARFDataExtractor& debug_info_data,
const DWARFCompileUnit* cu,
- const uint8_t *fixed_form_sizes,
+ const DWARFFormValue::FixedFormSizes& fixed_form_sizes,
lldb::offset_t *offset_ptr
)
{
@@ -158,7 +77,7 @@ DWARFDebugInfoEntry::FastExtract
{
form = abbrevDecl->GetFormByIndexUnchecked(i);
- const uint8_t fixed_skip_size = fixed_form_sizes [form];
+ const uint8_t fixed_skip_size = fixed_form_sizes.GetSize(form);
if (fixed_skip_size)
offset += fixed_skip_size;
else
@@ -226,9 +145,11 @@ DWARFDebugInfoEntry::FastExtract
break;
// signed or unsigned LEB 128 values
- case DW_FORM_sdata :
- case DW_FORM_udata :
- case DW_FORM_ref_udata :
+ case DW_FORM_sdata :
+ case DW_FORM_udata :
+ case DW_FORM_ref_udata :
+ case DW_FORM_GNU_addr_index:
+ case DW_FORM_GNU_str_index :
debug_info_data.Skip_LEB128 (&offset);
break;
@@ -306,7 +227,7 @@ DWARFDebugInfoEntry::Extract
bool isCompileUnitTag = m_tag == DW_TAG_compile_unit;
if (cu && isCompileUnitTag)
- ((DWARFCompileUnit*)cu)->SetBaseAddress(0);
+ const_cast<DWARFCompileUnit *>(cu)->SetBaseAddress(0);
// Skip all data in the .debug_info for the attributes
const uint32_t numAttributes = abbrevDecl->NumAttributes();
@@ -323,7 +244,7 @@ DWARFDebugInfoEntry::Extract
if (form_value.ExtractValue(debug_info_data, &offset))
{
if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc)
- ((DWARFCompileUnit*)cu)->SetBaseAddress(form_value.Unsigned());
+ const_cast<DWARFCompileUnit*>(cu)->SetBaseAddress(form_value.Address());
}
}
else
@@ -389,9 +310,11 @@ DWARFDebugInfoEntry::Extract
break;
// signed or unsigned LEB 128 values
- case DW_FORM_sdata :
- case DW_FORM_udata :
- case DW_FORM_ref_udata :
+ case DW_FORM_sdata :
+ case DW_FORM_udata :
+ case DW_FORM_ref_udata :
+ case DW_FORM_GNU_addr_index:
+ case DW_FORM_GNU_str_index :
debug_info_data.Skip_LEB128(&offset);
break;
@@ -456,276 +379,6 @@ DWARFDebugInfoEntry::DumpAncestry
}
//----------------------------------------------------------------------
-// Compare two DIE by comparing all their attributes values, and
-// following all DW_FORM_ref attributes and comparing their contents as
-// well (except for DW_AT_sibling attributes.
-//
-// DWARFDebugInfoEntry::CompareState compare_state;
-// int result = DWARFDebugInfoEntry::Compare(this, 0x00017ccb, 0x0001eb2b, compare_state, false, true);
-//----------------------------------------------------------------------
-//int
-//DWARFDebugInfoEntry::Compare
-//(
-// SymbolFileDWARF* dwarf2Data,
-// dw_offset_t a_die_offset,
-// dw_offset_t b_die_offset,
-// CompareState &compare_state,
-// bool compare_siblings,
-// bool compare_children
-//)
-//{
-// if (a_die_offset == b_die_offset)
-// return 0;
-//
-// DWARFCompileUnitSP a_cu_sp;
-// DWARFCompileUnitSP b_cu_sp;
-// const DWARFDebugInfoEntry* a_die = dwarf2Data->DebugInfo()->GetDIEPtr(a_die_offset, &a_cu_sp);
-// const DWARFDebugInfoEntry* b_die = dwarf2Data->DebugInfo()->GetDIEPtr(b_die_offset, &b_cu_sp);
-//
-// return Compare(dwarf2Data, a_cu_sp.get(), a_die, b_cu_sp.get(), b_die, compare_state, compare_siblings, compare_children);
-//}
-//
-//int
-//DWARFDebugInfoEntry::Compare
-//(
-// SymbolFileDWARF* dwarf2Data,
-// DWARFCompileUnit* a_cu, const DWARFDebugInfoEntry* a_die,
-// DWARFCompileUnit* b_cu, const DWARFDebugInfoEntry* b_die,
-// CompareState &compare_state,
-// bool compare_siblings,
-// bool compare_children
-//)
-//{
-// if (a_die == b_die)
-// return 0;
-//
-// if (!compare_state.AddTypePair(a_die->GetOffset(), b_die->GetOffset()))
-// {
-// // We are already comparing both of these types, so let
-// // compares complete for the real result
-// return 0;
-// }
-//
-// //printf("DWARFDebugInfoEntry::Compare(0x%8.8x, 0x%8.8x)\n", a_die->GetOffset(), b_die->GetOffset());
-//
-// // Do we have two valid DIEs?
-// if (a_die && b_die)
-// {
-// // Both DIE are valid
-// int result = 0;
-//
-// const dw_tag_t a_tag = a_die->Tag();
-// const dw_tag_t b_tag = b_die->Tag();
-// if (a_tag == 0 && b_tag == 0)
-// return 0;
-//
-// //printf(" comparing tags: %s and %s\n", DW_TAG_value_to_name(a_tag), DW_TAG_value_to_name(b_tag));
-//
-// if (a_tag < b_tag)
-// return -1;
-// else if (a_tag > b_tag)
-// return 1;
-//
-// DWARFDebugInfoEntry::Attributes a_attrs;
-// DWARFDebugInfoEntry::Attributes b_attrs;
-// size_t a_attr_count = a_die->GetAttributes(dwarf2Data, a_cu, a_attrs);
-// size_t b_attr_count = b_die->GetAttributes(dwarf2Data, b_cu, b_attrs);
-// if (a_attr_count != b_attr_count)
-// {
-// a_attrs.RemoveAttribute(DW_AT_sibling);
-// b_attrs.RemoveAttribute(DW_AT_sibling);
-// }
-//
-// a_attr_count = a_attrs.Size();
-// b_attr_count = b_attrs.Size();
-//
-// DWARFFormValue a_form_value;
-// DWARFFormValue b_form_value;
-//
-// if (a_attr_count != b_attr_count)
-// {
-// uint32_t is_decl_index = a_attrs.FindAttributeIndex(DW_AT_declaration);
-// uint32_t a_name_index = UINT32_MAX;
-// uint32_t b_name_index = UINT32_MAX;
-// if (is_decl_index != UINT32_MAX)
-// {
-// if (a_attr_count == 2)
-// {
-// a_name_index = a_attrs.FindAttributeIndex(DW_AT_name);
-// b_name_index = b_attrs.FindAttributeIndex(DW_AT_name);
-// }
-// }
-// else
-// {
-// is_decl_index = b_attrs.FindAttributeIndex(DW_AT_declaration);
-// if (is_decl_index != UINT32_MAX && a_attr_count == 2)
-// {
-// a_name_index = a_attrs.FindAttributeIndex(DW_AT_name);
-// b_name_index = b_attrs.FindAttributeIndex(DW_AT_name);
-// }
-// }
-// if (a_name_index != UINT32_MAX && b_name_index != UINT32_MAX)
-// {
-// if (a_attrs.ExtractFormValueAtIndex(dwarf2Data, a_name_index, a_form_value) &&
-// b_attrs.ExtractFormValueAtIndex(dwarf2Data, b_name_index, b_form_value))
-// {
-// result = DWARFFormValue::Compare (a_form_value, b_form_value, a_cu, b_cu, &dwarf2Data->get_debug_str_data());
-// if (result == 0)
-// {
-// a_attr_count = b_attr_count = 0;
-// compare_children = false;
-// }
-// }
-// }
-// }
-//
-// if (a_attr_count < b_attr_count)
-// return -1;
-// if (a_attr_count > b_attr_count)
-// return 1;
-//
-//
-// // The number of attributes are the same...
-// if (a_attr_count > 0)
-// {
-// const DWARFDataExtractor* debug_str_data_ptr = &dwarf2Data->get_debug_str_data();
-//
-// uint32_t i;
-// for (i=0; i<a_attr_count; ++i)
-// {
-// const dw_attr_t a_attr = a_attrs.AttributeAtIndex(i);
-// const dw_attr_t b_attr = b_attrs.AttributeAtIndex(i);
-// //printf(" comparing attributes\n\t\t0x%8.8x: %s %s\t\t0x%8.8x: %s %s\n",
-// // a_attrs.DIEOffsetAtIndex(i), DW_FORM_value_to_name(a_attrs.FormAtIndex(i)), DW_AT_value_to_name(a_attr),
-// // b_attrs.DIEOffsetAtIndex(i), DW_FORM_value_to_name(b_attrs.FormAtIndex(i)), DW_AT_value_to_name(b_attr));
-//
-// if (a_attr < b_attr)
-// return -1;
-// else if (a_attr > b_attr)
-// return 1;
-//
-// switch (a_attr)
-// {
-// // Since we call a form of GetAttributes which inlines the
-// // attributes from DW_AT_abstract_origin and DW_AT_specification
-// // we don't care if their values mismatch...
-// case DW_AT_abstract_origin:
-// case DW_AT_specification:
-// case DW_AT_sibling:
-// case DW_AT_containing_type:
-// //printf(" action = IGNORE\n");
-// result = 0;
-// break; // ignore
-//
-// default:
-// if (a_attrs.ExtractFormValueAtIndex(dwarf2Data, i, a_form_value) &&
-// b_attrs.ExtractFormValueAtIndex(dwarf2Data, i, b_form_value))
-// result = DWARFFormValue::Compare (a_form_value, b_form_value, a_cu, b_cu, debug_str_data_ptr);
-// break;
-// }
-//
-// //printf("\t result = %i\n", result);
-//
-// if (result != 0)
-// {
-// // Attributes weren't equal, lets see if we care?
-// switch (a_attr)
-// {
-// case DW_AT_decl_file:
-// // TODO: add the ability to compare files in two different compile units
-// if (a_cu == b_cu)
-// {
-// //printf(" action = RETURN RESULT\n");
-// return result; // Only return the compare results when the compile units are the same and the decl_file attributes can be compared
-// }
-// else
-// {
-// result = 0;
-// //printf(" action = IGNORE\n");
-// }
-// break;
-//
-// default:
-// switch (a_attrs.FormAtIndex(i))
-// {
-// case DW_FORM_ref1:
-// case DW_FORM_ref2:
-// case DW_FORM_ref4:
-// case DW_FORM_ref8:
-// case DW_FORM_ref_udata:
-// case DW_FORM_ref_addr:
-// //printf(" action = COMPARE DIEs 0x%8.8x 0x%8.8x\n", (dw_offset_t)a_form_value.Reference(a_cu), (dw_offset_t)b_form_value.Reference(b_cu));
-// // These attribute values refer to other DIEs, so lets compare those instead of their DIE offsets...
-// result = Compare(dwarf2Data, a_form_value.Reference(a_cu), b_form_value.Reference(b_cu), compare_state, false, true);
-// if (result != 0)
-// return result;
-// break;
-//
-// default:
-// // We do care that they were different, return this result...
-// //printf(" action = RETURN RESULT\n");
-// return result;
-// }
-// }
-// }
-// }
-// }
-// //printf(" SUCCESS\n\t\t0x%8.8x: %s\n\t\t0x%8.8x: %s\n", a_die->GetOffset(), DW_TAG_value_to_name(a_tag), b_die->GetOffset(), DW_TAG_value_to_name(b_tag));
-//
-// if (compare_children)
-// {
-// bool a_has_children = a_die->HasChildren();
-// bool b_has_children = b_die->HasChildren();
-// if (a_has_children == b_has_children)
-// {
-// // Both either have kids or don't
-// if (a_has_children)
-// result = Compare( dwarf2Data,
-// a_cu, a_die->GetFirstChild(),
-// b_cu, b_die->GetFirstChild(),
-// compare_state, true, compare_children);
-// else
-// result = 0;
-// }
-// else if (!a_has_children)
-// result = -1; // A doesn't have kids, but B does
-// else
-// result = 1; // A has kids, but B doesn't
-// }
-//
-// if (compare_siblings)
-// {
-// result = Compare( dwarf2Data,
-// a_cu, a_die->GetSibling(),
-// b_cu, b_die->GetSibling(),
-// compare_state, true, compare_children);
-// }
-//
-// return result;
-// }
-//
-// if (a_die == NULL)
-// return -1; // a_die is NULL, yet b_die is non-NULL
-// else
-// return 1; // a_die is non-NULL, yet b_die is NULL
-//
-//}
-//
-//
-//int
-//DWARFDebugInfoEntry::Compare
-//(
-// SymbolFileDWARF* dwarf2Data,
-// const DWARFCompileUnit* cu_a,
-// const DWARFDebugInfoEntry* die_a,
-// const DWARFCompileUnit* cu_a,
-// const DWARFDebugInfoEntry* die_b,
-// CompareState &compare_state
-//)
-//{
-//}
-
-//----------------------------------------------------------------------
// GetDIENamesAndRanges
//
// Gets the valid address ranges for a given DIE by looking for a
@@ -739,7 +392,7 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
const DWARFCompileUnit* cu,
const char * &name,
const char * &mangled,
- DWARFDebugRanges::RangeList& ranges,
+ DWARFRangeList& ranges,
int& decl_file,
int& decl_line,
int& decl_column,
@@ -749,12 +402,27 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
DWARFExpression *frame_base
) const
{
- if (dwarf2Data == NULL)
+ if (dwarf2Data == nullptr)
return false;
+ SymbolFileDWARFDwo* dwo_symbol_file = cu->GetDwoSymbolFile();
+ if (dwo_symbol_file)
+ return GetDIENamesAndRanges(dwo_symbol_file,
+ dwo_symbol_file->GetCompileUnit(),
+ name,
+ mangled,
+ ranges,
+ decl_file,
+ decl_line,
+ decl_column,
+ call_file,
+ call_line,
+ call_column,
+ frame_base);
+
dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
- std::vector<dw_offset_t> die_offsets;
+ std::vector<DIERef> die_refs;
bool set_frame_base_loclist_addr = false;
lldb::offset_t offset;
@@ -784,7 +452,7 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
switch (attr)
{
case DW_AT_low_pc:
- lo_pc = form_value.Unsigned();
+ lo_pc = form_value.Address();
if (do_offset)
hi_pc += lo_pc;
@@ -792,13 +460,18 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
break;
case DW_AT_entry_pc:
- lo_pc = form_value.Unsigned();
+ lo_pc = form_value.Address();
break;
case DW_AT_high_pc:
- hi_pc = form_value.Unsigned();
- if (form_value.Form() != DW_FORM_addr)
+ if (form_value.Form() == DW_FORM_addr ||
+ form_value.Form() == DW_FORM_GNU_addr_index)
{
+ hi_pc = form_value.Address();
+ }
+ else
+ {
+ hi_pc = form_value.Unsigned();
if (lo_pc == LLDB_INVALID_ADDRESS)
do_offset = hi_pc != LLDB_INVALID_ADDRESS;
else
@@ -819,21 +492,21 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
case DW_AT_name:
if (name == NULL)
- name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+ name = form_value.AsCString();
break;
case DW_AT_MIPS_linkage_name:
case DW_AT_linkage_name:
if (mangled == NULL)
- mangled = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+ mangled = form_value.AsCString();
break;
case DW_AT_abstract_origin:
- die_offsets.push_back(form_value.Reference());
+ die_refs.emplace_back(form_value);
break;
case DW_AT_specification:
- die_offsets.push_back(form_value.Reference());
+ die_refs.emplace_back(form_value);
break;
case DW_AT_decl_file:
@@ -880,7 +553,7 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
const DWARFDataExtractor &debug_loc_data = dwarf2Data->get_debug_loc_data();
const dw_offset_t debug_loc_offset = form_value.Unsigned();
- size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset);
+ size_t loc_list_length = DWARFExpression::LocationListSize(cu, debug_loc_data, debug_loc_offset);
if (loc_list_length > 0)
{
frame_base->SetOpcodeData(module, debug_loc_data, debug_loc_offset, loc_list_length);
@@ -910,9 +583,9 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
if (lo_pc != LLDB_INVALID_ADDRESS)
{
if (hi_pc != LLDB_INVALID_ADDRESS && hi_pc > lo_pc)
- ranges.Append(DWARFDebugRanges::Range (lo_pc, hi_pc - lo_pc));
+ ranges.Append(DWARFRangeList::Entry (lo_pc, hi_pc - lo_pc));
else
- ranges.Append(DWARFDebugRanges::Range (lo_pc, 0));
+ ranges.Append(DWARFRangeList::Entry (lo_pc, 0));
}
}
@@ -925,18 +598,13 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges
if (ranges.IsEmpty() || name == NULL || mangled == NULL)
{
- std::vector<dw_offset_t>::const_iterator pos;
- std::vector<dw_offset_t>::const_iterator end = die_offsets.end();
- for (pos = die_offsets.begin(); pos != end; ++pos)
+ for (const DIERef& die_ref : die_refs)
{
- DWARFCompileUnitSP cu_sp_ptr;
- const DWARFDebugInfoEntry* die = NULL;
- dw_offset_t die_offset = *pos;
- if (die_offset != DW_INVALID_OFFSET)
+ if (die_ref.die_offset != DW_INVALID_OFFSET)
{
- die = dwarf2Data->DebugInfo()->GetDIEPtr(die_offset, &cu_sp_ptr);
+ DWARFDIE die = dwarf2Data->DebugInfo()->GetDIE(die_ref);
if (die)
- die->GetDIENamesAndRanges(dwarf2Data, cu_sp_ptr.get(), name, mangled, ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column);
+ die.GetDIE()->GetDIENamesAndRanges(die.GetDWARF(), die.GetCU(), name, mangled, ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column);
}
}
}
@@ -1023,10 +691,10 @@ DWARFDebugInfoEntry::DumpLocation
Stream &s
) const
{
- const DWARFDebugInfoEntry *cu_die = cu->GetCompileUnitDIEOnly();
+ const DWARFDIE cu_die = cu->GetCompileUnitDIEOnly();
const char *cu_name = NULL;
- if (cu_die != NULL)
- cu_name = cu_die->GetName (dwarf2Data, cu);
+ if (cu_die)
+ cu_name = cu_die.GetName ();
const char *obj_file_name = NULL;
ObjectFile *obj_file = dwarf2Data->GetObjectFile();
if (obj_file)
@@ -1062,7 +730,6 @@ DWARFDebugInfoEntry::DumpAttribute
bool verbose = s.GetVerbose();
bool show_form = s.GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowForm);
- const DWARFDataExtractor* debug_str_data = dwarf2Data ? &dwarf2Data->get_debug_str_data() : NULL;
if (verbose)
s.Offset (*offset_ptr);
else
@@ -1094,7 +761,7 @@ DWARFDebugInfoEntry::DumpAttribute
// Always dump form value if verbose is enabled
if (verbose)
{
- form_value.Dump(s, debug_str_data);
+ form_value.Dump(s);
}
@@ -1127,12 +794,16 @@ DWARFDebugInfoEntry::DumpAttribute
if (blockData)
{
if (!verbose)
- form_value.Dump(s, debug_str_data);
+ form_value.Dump(s);
// Location description is inlined in data in the form value
DWARFDataExtractor locationData(debug_info_data, (*offset_ptr) - form_value.Unsigned(), form_value.Unsigned());
if ( verbose ) s.PutCString(" ( ");
- print_dwarf_expression (s, locationData, DWARFCompileUnit::GetAddressByteSize(cu), 4, false);
+ DWARFExpression::PrintDWARFExpression(s,
+ locationData,
+ DWARFCompileUnit::GetAddressByteSize(cu),
+ 4,
+ false);
if ( verbose ) s.PutCString(" )");
}
else
@@ -1144,13 +815,16 @@ DWARFDebugInfoEntry::DumpAttribute
if (dwarf2Data)
{
if ( !verbose )
- form_value.Dump(s, debug_str_data);
- DWARFLocationList::Dump(s, cu, dwarf2Data->get_debug_loc_data(), debug_loc_offset);
+ form_value.Dump(s);
+ DWARFExpression::PrintDWARFLocationList(s,
+ cu,
+ dwarf2Data->get_debug_loc_data(),
+ debug_loc_offset);
}
else
{
if ( !verbose )
- form_value.Dump(s, NULL);
+ form_value.Dump(s);
}
}
}
@@ -1160,7 +834,7 @@ DWARFDebugInfoEntry::DumpAttribute
case DW_AT_specification:
{
uint64_t abstract_die_offset = form_value.Reference();
- form_value.Dump(s, debug_str_data);
+ form_value.Dump(s);
// *ostrm_ptr << HEX32 << abstract_die_offset << " ( ";
if ( verbose ) s.PutCString(" ( ");
GetName(dwarf2Data, cu, abstract_die_offset, s);
@@ -1172,7 +846,7 @@ DWARFDebugInfoEntry::DumpAttribute
{
uint64_t type_die_offset = form_value.Reference();
if (!verbose)
- form_value.Dump(s, debug_str_data);
+ form_value.Dump(s);
s.PutCString(" ( ");
AppendTypeName(dwarf2Data, cu, type_die_offset, s);
s.PutCString(" )");
@@ -1182,7 +856,7 @@ DWARFDebugInfoEntry::DumpAttribute
case DW_AT_ranges:
{
if ( !verbose )
- form_value.Dump(s, debug_str_data);
+ form_value.Dump(s);
lldb::offset_t ranges_offset = form_value.Unsigned();
dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0;
if (dwarf2Data)
@@ -1192,7 +866,7 @@ DWARFDebugInfoEntry::DumpAttribute
default:
if ( !verbose )
- form_value.Dump(s, debug_str_data);
+ form_value.Dump(s);
break;
}
@@ -1206,24 +880,37 @@ DWARFDebugInfoEntry::DumpAttribute
// take precedence (this can happen for declaration attributes).
//----------------------------------------------------------------------
size_t
-DWARFDebugInfoEntry::GetAttributes
-(
- SymbolFileDWARF* dwarf2Data,
- const DWARFCompileUnit* cu,
- const uint8_t *fixed_form_sizes,
- DWARFDebugInfoEntry::Attributes& attributes,
- uint32_t curr_depth
-) const
+DWARFDebugInfoEntry::GetAttributes (const DWARFCompileUnit* cu,
+ DWARFFormValue::FixedFormSizes fixed_form_sizes,
+ DWARFAttributes& attributes,
+ uint32_t curr_depth) const
{
- lldb::offset_t offset;
- const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset);
+ SymbolFileDWARF* dwarf2Data = nullptr;
+ const DWARFAbbreviationDeclaration* abbrevDecl = nullptr;
+ lldb::offset_t offset = 0;
+ if (cu)
+ {
+ if (m_tag != DW_TAG_compile_unit)
+ {
+ SymbolFileDWARFDwo* dwo_symbol_file = cu->GetDwoSymbolFile();
+ if (dwo_symbol_file)
+ return GetAttributes(dwo_symbol_file->GetCompileUnit(),
+ fixed_form_sizes,
+ attributes,
+ curr_depth);
+ }
+
+ dwarf2Data = cu->GetSymbolFileDWARF();
+ abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset);
+ }
if (abbrevDecl)
{
const DWARFDataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
- if (fixed_form_sizes == NULL)
- fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize(cu->GetAddressByteSize(), cu->IsDWARF64());
+ if (fixed_form_sizes.Empty())
+ fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize(
+ cu->GetAddressByteSize(), cu->IsDWARF64());
const uint32_t num_attributes = abbrevDecl->NumAttributes();
uint32_t i;
@@ -1258,26 +945,15 @@ DWARFDebugInfoEntry::GetAttributes
DWARFFormValue form_value (cu, form);
if (form_value.ExtractValue(debug_info_data, &offset))
{
- const DWARFDebugInfoEntry* die = NULL;
dw_offset_t die_offset = form_value.Reference();
- if (cu->ContainsDIEOffset(die_offset))
- {
- die = const_cast<DWARFCompileUnit*>(cu)->GetDIEPtr(die_offset);
- if (die)
- die->GetAttributes(dwarf2Data, cu, fixed_form_sizes, attributes, curr_depth + 1);
- }
- else
- {
- DWARFCompileUnitSP cu_sp_ptr;
- die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(die_offset, &cu_sp_ptr);
- if (die)
- die->GetAttributes(dwarf2Data, cu_sp_ptr.get(), fixed_form_sizes, attributes, curr_depth + 1);
- }
+ DWARFDIE spec_die = const_cast<DWARFCompileUnit*>(cu)->GetDIE(die_offset);
+ if (spec_die)
+ spec_die.GetAttributes(attributes, curr_depth + 1);
}
}
else
{
- const uint8_t fixed_skip_size = fixed_form_sizes [form];
+ const uint8_t fixed_skip_size = fixed_form_sizes.GetSize(form);
if (fixed_skip_size)
offset += fixed_skip_size;
else
@@ -1308,9 +984,19 @@ DWARFDebugInfoEntry::GetAttributeValue
const DWARFCompileUnit* cu,
const dw_attr_t attr,
DWARFFormValue& form_value,
- dw_offset_t* end_attr_offset_ptr
+ dw_offset_t* end_attr_offset_ptr,
+ bool check_specification_or_abstract_origin
) const
{
+ SymbolFileDWARFDwo* dwo_symbol_file = cu->GetDwoSymbolFile();
+ if (dwo_symbol_file && m_tag != DW_TAG_compile_unit)
+ return GetAttributeValue(dwo_symbol_file,
+ dwo_symbol_file->GetCompileUnit(),
+ attr,
+ form_value,
+ end_attr_offset_ptr,
+ check_specification_or_abstract_origin);
+
lldb::offset_t offset;
const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset);
@@ -1338,7 +1024,58 @@ DWARFDebugInfoEntry::GetAttributeValue
}
}
- return 0;
+ if (check_specification_or_abstract_origin)
+ {
+ if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value))
+ {
+ DWARFDIE die = const_cast<DWARFCompileUnit*>(cu)->GetDIE(form_value.Reference());
+ if (die)
+ {
+ dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(die.GetDWARF(),
+ die.GetCU(),
+ attr,
+ form_value,
+ end_attr_offset_ptr,
+ false);
+ if (die_offset)
+ return die_offset;
+ }
+ }
+
+ if (GetAttributeValue(dwarf2Data, cu, DW_AT_abstract_origin, form_value))
+ {
+ DWARFDIE die = const_cast<DWARFCompileUnit*>(cu)->GetDIE(form_value.Reference());
+ if (die)
+ {
+ dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(die.GetDWARF(),
+ die.GetCU(),
+ attr,
+ form_value,
+ end_attr_offset_ptr,
+ false);
+ if (die_offset)
+ return die_offset;
+ }
+ }
+ }
+
+ if (!dwo_symbol_file)
+ return 0;
+
+ DWARFCompileUnit* dwo_cu = dwo_symbol_file->GetCompileUnit();
+ if (!dwo_cu)
+ return 0;
+
+ DWARFDIE dwo_cu_die = dwo_cu->GetCompileUnitDIEOnly();
+ if (!dwo_cu_die.IsValid())
+ return 0;
+
+ return dwo_cu_die.GetDIE()->GetAttributeValue(dwo_symbol_file,
+ dwo_cu,
+ attr,
+ form_value,
+ end_attr_offset_ptr,
+ check_specification_or_abstract_origin);
}
//----------------------------------------------------------------------
@@ -1355,11 +1092,12 @@ DWARFDebugInfoEntry::GetAttributeValueAsString
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
const dw_attr_t attr,
- const char* fail_value) const
+ const char* fail_value,
+ bool check_specification_or_abstract_origin) const
{
DWARFFormValue form_value;
- if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
- return form_value.AsCString(&dwarf2Data->get_debug_str_data());
+ if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin))
+ return form_value.AsCString();
return fail_value;
}
@@ -1374,11 +1112,12 @@ DWARFDebugInfoEntry::GetAttributeValueAsUnsigned
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
const dw_attr_t attr,
- uint64_t fail_value
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin
) const
{
DWARFFormValue form_value;
- if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
+ if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin))
return form_value.Unsigned();
return fail_value;
}
@@ -1394,11 +1133,12 @@ DWARFDebugInfoEntry::GetAttributeValueAsSigned
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
const dw_attr_t attr,
- int64_t fail_value
+ int64_t fail_value,
+ bool check_specification_or_abstract_origin
) const
{
DWARFFormValue form_value;
- if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
+ if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin))
return form_value.Signed();
return fail_value;
}
@@ -1415,15 +1155,32 @@ DWARFDebugInfoEntry::GetAttributeValueAsReference
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
const dw_attr_t attr,
- uint64_t fail_value
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin
) const
{
DWARFFormValue form_value;
- if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
+ if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin))
return form_value.Reference();
return fail_value;
}
+uint64_t
+DWARFDebugInfoEntry::GetAttributeValueAsAddress
+(
+ SymbolFileDWARF* dwarf2Data,
+ const DWARFCompileUnit* cu,
+ const dw_attr_t attr,
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin
+) const
+{
+ DWARFFormValue form_value;
+ if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr, check_specification_or_abstract_origin))
+ return form_value.Address();
+ return fail_value;
+}
+
//----------------------------------------------------------------------
// GetAttributeHighPC
//
@@ -1438,17 +1195,19 @@ DWARFDebugInfoEntry::GetAttributeHighPC
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
dw_addr_t lo_pc,
- uint64_t fail_value
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin
) const
{
DWARFFormValue form_value;
-
- if (GetAttributeValue(dwarf2Data, cu, DW_AT_high_pc, form_value))
+ if (GetAttributeValue(dwarf2Data, cu, DW_AT_high_pc, form_value, nullptr, check_specification_or_abstract_origin))
{
- dw_addr_t hi_pc = form_value.Unsigned();
- if (form_value.Form() != DW_FORM_addr)
- hi_pc += lo_pc; // DWARF4 can specify the hi_pc as an <offset-from-lowpc>
- return hi_pc;
+ dw_form_t form = form_value.Form();
+ if (form == DW_FORM_addr || form == DW_FORM_GNU_addr_index)
+ return form_value.Address();
+
+ // DWARF4 can specify the hi_pc as an <offset-from-lowpc>
+ return lo_pc + form_value.Unsigned();
}
return fail_value;
}
@@ -1468,13 +1227,14 @@ DWARFDebugInfoEntry::GetAttributeAddressRange
const DWARFCompileUnit* cu,
dw_addr_t& lo_pc,
dw_addr_t& hi_pc,
- uint64_t fail_value
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin
) const
{
- lo_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, fail_value);
+ lo_pc = GetAttributeValueAsAddress(dwarf2Data, cu, DW_AT_low_pc, fail_value, check_specification_or_abstract_origin);
if (lo_pc != fail_value)
{
- hi_pc = GetAttributeHighPC(dwarf2Data, cu, lo_pc, fail_value);
+ hi_pc = GetAttributeHighPC(dwarf2Data, cu, lo_pc, fail_value, check_specification_or_abstract_origin);
if (hi_pc != fail_value)
return true;
}
@@ -1484,89 +1244,40 @@ DWARFDebugInfoEntry::GetAttributeAddressRange
}
size_t
-DWARFDebugInfoEntry::GetAttributeAddressRanges(SymbolFileDWARF* dwarf2Data,
- const DWARFCompileUnit* cu,
- DWARFDebugRanges::RangeList &ranges,
- bool check_hi_lo_pc) const
+DWARFDebugInfoEntry::GetAttributeAddressRanges (SymbolFileDWARF* dwarf2Data,
+ const DWARFCompileUnit* cu,
+ DWARFRangeList &ranges,
+ bool check_hi_lo_pc,
+ bool check_specification_or_abstract_origin) const
{
ranges.Clear();
- dw_offset_t ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET);
- if (ranges_offset != DW_INVALID_OFFSET)
+ dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data,
+ cu,
+ DW_AT_ranges,
+ DW_INVALID_OFFSET,
+ check_specification_or_abstract_origin);
+ if (debug_ranges_offset != DW_INVALID_OFFSET)
{
- dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET);
- if (debug_ranges_offset != DW_INVALID_OFFSET)
- {
- DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges();
-
- debug_ranges->FindRanges(debug_ranges_offset, ranges);
- ranges.Slide (cu->GetBaseAddress());
- }
+ DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges();
+
+ debug_ranges->FindRanges(debug_ranges_offset, ranges);
+ ranges.Slide (cu->GetBaseAddress());
}
else if (check_hi_lo_pc)
{
dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
- if (GetAttributeAddressRange (dwarf2Data, cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS))
+ if (GetAttributeAddressRange (dwarf2Data, cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS, check_specification_or_abstract_origin))
{
if (lo_pc < hi_pc)
- ranges.Append(DWARFDebugRanges::RangeList::Entry(lo_pc, hi_pc - lo_pc));
+ ranges.Append(DWARFRangeList::Entry(lo_pc, hi_pc - lo_pc));
}
}
return ranges.GetSize();
}
//----------------------------------------------------------------------
-// GetAttributeValueAsLocation
-//
-// Get the value of an attribute as reference and fix up and compile
-// unit relative offsets as needed.
-//----------------------------------------------------------------------
-dw_offset_t
-DWARFDebugInfoEntry::GetAttributeValueAsLocation
-(
- SymbolFileDWARF* dwarf2Data,
- const DWARFCompileUnit* cu,
- const dw_attr_t attr,
- DWARFDataExtractor& location_data,
- uint32_t &block_size
-) const
-{
- block_size = 0;
- DWARFFormValue form_value;
-
- // Empty out data in case we don't find anything
- location_data.Clear();
- dw_offset_t end_addr_offset = DW_INVALID_OFFSET;
- const dw_offset_t attr_offset = GetAttributeValue(dwarf2Data, cu, attr, form_value, &end_addr_offset);
- if (attr_offset)
- {
- const uint8_t* blockData = form_value.BlockData();
- if (blockData)
- {
- // We have an inlined location list in the .debug_info section
- const DWARFDataExtractor& debug_info = dwarf2Data->get_debug_info_data();
- dw_offset_t block_offset = blockData - debug_info.GetDataStart();
- block_size = (end_addr_offset - attr_offset) - form_value.Unsigned();
- location_data.SetData(debug_info, block_offset, block_size);
- }
- else
- {
- // 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
- lldb::offset_t debug_loc_offset = form_value.Unsigned();
- if (dwarf2Data)
- {
- assert(dwarf2Data->get_debug_loc_data().GetAddressByteSize() == cu->GetAddressByteSize());
- return DWARFLocationList::Extract(dwarf2Data->get_debug_loc_data(), &debug_loc_offset, location_data);
- }
- }
- }
- return attr_offset;
-}
-
-//----------------------------------------------------------------------
// GetName
//
// Get value of the DW_AT_name attribute and return it if one exists,
@@ -1579,27 +1290,9 @@ DWARFDebugInfoEntry::GetName
const DWARFCompileUnit* cu
) const
{
- DWARFFormValue form_value;
- if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
- return form_value.AsCString(&dwarf2Data->get_debug_str_data());
- else if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value))
- {
- DWARFCompileUnitSP cu_sp_ptr;
- const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(), &cu_sp_ptr);
- if (die)
- return die->GetName(dwarf2Data, cu_sp_ptr.get());
- }
- else if (GetAttributeValue(dwarf2Data, cu, DW_AT_abstract_origin, form_value))
- {
- DWARFCompileUnitSP cu_sp_ptr;
- const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(), &cu_sp_ptr);
- if (die)
- return die->GetName(dwarf2Data, cu_sp_ptr.get());
- }
- return nullptr;
+ return GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true);
}
-
//----------------------------------------------------------------------
// GetMangledName
//
@@ -1614,20 +1307,20 @@ DWARFDebugInfoEntry::GetMangledName
bool substitute_name_allowed
) const
{
- const char* name = NULL;
- DWARFFormValue form_value;
+ const char* name = nullptr;
- if (GetAttributeValue(dwarf2Data, cu, DW_AT_MIPS_linkage_name, form_value))
- name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+ name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_MIPS_linkage_name, nullptr, true);
+ if (name)
+ return name;
- if (GetAttributeValue(dwarf2Data, cu, DW_AT_linkage_name, form_value))
- name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+ name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_linkage_name, nullptr, true);
+ if (name)
+ return name;
- if (substitute_name_allowed && name == NULL)
- {
- if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
- name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
- }
+ if (!substitute_name_allowed)
+ return nullptr;
+
+ name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true);
return name;
}
@@ -1645,27 +1338,19 @@ DWARFDebugInfoEntry::GetPubname
const DWARFCompileUnit* cu
) const
{
- const char* name = NULL;
+ const char* name = nullptr;
if (!dwarf2Data)
return name;
-
- DWARFFormValue form_value;
- if (GetAttributeValue(dwarf2Data, cu, DW_AT_MIPS_linkage_name, form_value))
- name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
- else if (GetAttributeValue(dwarf2Data, cu, DW_AT_linkage_name, form_value))
- name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
- else if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
- name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
- else if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value))
- {
- // The specification DIE may be in another compile unit so we need
- // to get a die and its compile unit.
- DWARFCompileUnitSP cu_sp_ptr;
- const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(), &cu_sp_ptr);
- if (die)
- return die->GetPubname(dwarf2Data, cu_sp_ptr.get());
- }
+ name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_MIPS_linkage_name, nullptr, true);
+ if (name)
+ return name;
+
+ name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_linkage_name, nullptr, true);
+ if (name)
+ return name;
+
+ name = GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true);
return name;
}
@@ -1705,15 +1390,11 @@ DWARFDebugInfoEntry::GetName
}
else
{
- DWARFFormValue form_value;
- if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
+ const char* name = die.GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, nullptr, true);
+ if (name)
{
- const char* name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
- if (name)
- {
- s.PutCString(name);
- return true;
- }
+ s.PutCString(name);
+ return true;
}
}
}
@@ -1755,8 +1436,6 @@ DWARFDebugInfoEntry::AppendTypeName
else
{
const char* name = die.GetPubname(dwarf2Data, cu);
- // if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
- // name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
if (name)
s.PutCString(name);
else
@@ -1909,16 +1588,12 @@ DWARFDebugInfoEntry::BuildFunctionAddressRangeTable
}
void
-DWARFDebugInfoEntry::GetDeclContextDIEs (SymbolFileDWARF* dwarf2Data,
- DWARFCompileUnit* cu,
+DWARFDebugInfoEntry::GetDeclContextDIEs (DWARFCompileUnit* cu,
DWARFDIECollection &decl_context_dies) const
{
- const DWARFDebugInfoEntry *parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu);
- if (parent_decl_ctx_die && parent_decl_ctx_die != this)
- {
- decl_context_dies.Append(parent_decl_ctx_die);
- parent_decl_ctx_die->GetDeclContextDIEs (dwarf2Data, cu, decl_context_dies);
- }
+
+ DWARFDIE die (cu, const_cast<DWARFDebugInfoEntry *>(this));
+ die.GetDeclContextDIEs(decl_context_dies);
}
void
@@ -1930,11 +1605,11 @@ DWARFDebugInfoEntry::GetDWARFDeclContext (SymbolFileDWARF* dwarf2Data,
if (tag != DW_TAG_compile_unit)
{
dwarf_decl_ctx.AppendDeclContext(tag, GetName(dwarf2Data, cu));
- const DWARFDebugInfoEntry *parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu);
- if (parent_decl_ctx_die && parent_decl_ctx_die != this)
+ DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu);
+ if (parent_decl_ctx_die && parent_decl_ctx_die.GetDIE() != this)
{
- if (parent_decl_ctx_die->Tag() != DW_TAG_compile_unit)
- parent_decl_ctx_die->GetDWARFDeclContext (dwarf2Data, cu, dwarf_decl_ctx);
+ if (parent_decl_ctx_die.Tag() != DW_TAG_compile_unit)
+ parent_decl_ctx_die.GetDIE()->GetDWARFDeclContext (parent_decl_ctx_die.GetDWARF(), parent_decl_ctx_die.GetCU(), dwarf_decl_ctx);
}
}
}
@@ -1951,30 +1626,30 @@ DWARFDebugInfoEntry::MatchesDWARFDeclContext (SymbolFileDWARF* dwarf2Data,
return this_dwarf_decl_ctx == dwarf_decl_ctx;
}
-const DWARFDebugInfoEntry *
+DWARFDIE
DWARFDebugInfoEntry::GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,
DWARFCompileUnit* cu) const
{
- DWARFDebugInfoEntry::Attributes attributes;
- GetAttributes(dwarf2Data, cu, NULL, attributes);
+ DWARFAttributes attributes;
+ GetAttributes(cu, DWARFFormValue::FixedFormSizes(), attributes);
return GetParentDeclContextDIE (dwarf2Data, cu, attributes);
}
-const DWARFDebugInfoEntry *
+DWARFDIE
DWARFDebugInfoEntry::GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,
DWARFCompileUnit* cu,
- const DWARFDebugInfoEntry::Attributes& attributes) const
+ const DWARFAttributes& attributes) const
{
- const DWARFDebugInfoEntry * die = this;
-
- while (die != NULL)
+ DWARFDIE die (cu, const_cast<DWARFDebugInfoEntry *>(this));
+
+ while (die)
{
// If this is the original DIE that we are searching for a declaration
// for, then don't look in the cache as we don't want our own decl
// context to be our decl context...
- if (die != this)
+ if (die.GetDIE() != this)
{
- switch (die->Tag())
+ switch (die.Tag())
{
case DW_TAG_compile_unit:
case DW_TAG_namespace:
@@ -1990,33 +1665,33 @@ DWARFDebugInfoEntry::GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,
dw_offset_t die_offset;
- die_offset = attributes.FormValueAsUnsigned(dwarf2Data, DW_AT_specification, DW_INVALID_OFFSET);
+ die_offset = attributes.FormValueAsUnsigned(DW_AT_specification, DW_INVALID_OFFSET);
if (die_offset != DW_INVALID_OFFSET)
{
- const DWARFDebugInfoEntry *spec_die = cu->GetDIEPtr (die_offset);
+ DWARFDIE spec_die = cu->GetDIE (die_offset);
if (spec_die)
- {
- const DWARFDebugInfoEntry *spec_die_decl_ctx_die = spec_die->GetParentDeclContextDIE (dwarf2Data, cu);
- if (spec_die_decl_ctx_die)
- return spec_die_decl_ctx_die;
- }
+ {
+ DWARFDIE decl_ctx_die = spec_die.GetParentDeclContextDIE();
+ if (decl_ctx_die)
+ return decl_ctx_die;
+ }
}
- die_offset = attributes.FormValueAsUnsigned(dwarf2Data, DW_AT_abstract_origin, DW_INVALID_OFFSET);
+ die_offset = attributes.FormValueAsUnsigned(DW_AT_abstract_origin, DW_INVALID_OFFSET);
if (die_offset != DW_INVALID_OFFSET)
{
- const DWARFDebugInfoEntry *abs_die = cu->GetDIEPtr (die_offset);
+ DWARFDIE abs_die = cu->GetDIE (die_offset);
if (abs_die)
{
- const DWARFDebugInfoEntry *abs_die_decl_ctx_die = abs_die->GetParentDeclContextDIE (dwarf2Data, cu);
- if (abs_die_decl_ctx_die)
- return abs_die_decl_ctx_die;
+ DWARFDIE decl_ctx_die = abs_die.GetParentDeclContextDIE();
+ if (decl_ctx_die)
+ return decl_ctx_die;
}
}
- die = die->GetParent();
+ die = die.GetParent();
}
- return NULL;
+ return DWARFDIE();
}
@@ -2025,15 +1700,15 @@ DWARFDebugInfoEntry::GetQualifiedName (SymbolFileDWARF* dwarf2Data,
DWARFCompileUnit* cu,
std::string &storage) const
{
- DWARFDebugInfoEntry::Attributes attributes;
- GetAttributes(dwarf2Data, cu, NULL, attributes);
+ DWARFAttributes attributes;
+ GetAttributes(cu, DWARFFormValue::FixedFormSizes(), attributes);
return GetQualifiedName (dwarf2Data, cu, attributes, storage);
}
const char*
DWARFDebugInfoEntry::GetQualifiedName (SymbolFileDWARF* dwarf2Data,
DWARFCompileUnit* cu,
- const DWARFDebugInfoEntry::Attributes& attributes,
+ const DWARFAttributes& attributes,
std::string &storage) const
{
@@ -2041,47 +1716,47 @@ DWARFDebugInfoEntry::GetQualifiedName (SymbolFileDWARF* dwarf2Data,
if (name)
{
- const DWARFDebugInfoEntry *parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu);
+ DWARFDIE parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu);
storage.clear();
// TODO: change this to get the correct decl context parent....
while (parent_decl_ctx_die)
{
- const dw_tag_t parent_tag = parent_decl_ctx_die->Tag();
+ const dw_tag_t parent_tag = parent_decl_ctx_die.Tag();
switch (parent_tag)
{
case DW_TAG_namespace:
- {
- const char *namespace_name = parent_decl_ctx_die->GetName (dwarf2Data, cu);
- if (namespace_name)
- {
- storage.insert (0, "::");
- storage.insert (0, namespace_name);
- }
- else
- {
- storage.insert (0, "(anonymous namespace)::");
- }
- parent_decl_ctx_die = parent_decl_ctx_die->GetParentDeclContextDIE(dwarf2Data, cu);
- }
+ {
+ const char *namespace_name = parent_decl_ctx_die.GetName ();
+ if (namespace_name)
+ {
+ storage.insert (0, "::");
+ storage.insert (0, namespace_name);
+ }
+ else
+ {
+ storage.insert (0, "(anonymous namespace)::");
+ }
+ parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE();
+ }
break;
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
- {
- const char *class_union_struct_name = parent_decl_ctx_die->GetName (dwarf2Data, cu);
-
- if (class_union_struct_name)
- {
- storage.insert (0, "::");
- storage.insert (0, class_union_struct_name);
- }
- parent_decl_ctx_die = parent_decl_ctx_die->GetParentDeclContextDIE(dwarf2Data, cu);
- }
+ {
+ const char *class_union_struct_name = parent_decl_ctx_die.GetName ();
+
+ if (class_union_struct_name)
+ {
+ storage.insert (0, "::");
+ storage.insert (0, class_union_struct_name);
+ }
+ parent_decl_ctx_die = parent_decl_ctx_die.GetParentDeclContextDIE();
+ }
break;
default:
- parent_decl_ctx_die = NULL;
+ parent_decl_ctx_die.Clear();
break;
}
}
@@ -2179,7 +1854,7 @@ DWARFDebugInfoEntry::LookupAddress
if (match_addr_range)
{
- dw_addr_t lo_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
+ dw_addr_t lo_pc = GetAttributeValueAsAddress(dwarf2Data, cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
if (lo_pc != LLDB_INVALID_ADDRESS)
{
dw_addr_t hi_pc = GetAttributeHighPC(dwarf2Data, cu, lo_pc, LLDB_INVALID_ADDRESS);
@@ -2229,7 +1904,7 @@ DWARFDebugInfoEntry::LookupAddress
dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET);
if (debug_ranges_offset != DW_INVALID_OFFSET)
{
- DWARFDebugRanges::RangeList ranges;
+ DWARFRangeList ranges;
DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges();
debug_ranges->FindRanges(debug_ranges_offset, ranges);
// All DW_AT_ranges are relative to the base address of the
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
index 3949ad339dd8..02bbff8defc0 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
@@ -57,56 +57,6 @@ public:
typedef offset_collection::iterator offset_collection_iterator;
typedef offset_collection::const_iterator offset_collection_const_iterator;
- class Attributes
- {
- public:
- Attributes();
- ~Attributes();
-
- void Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form);
- const DWARFCompileUnit * CompileUnitAtIndex(uint32_t i) const { return m_infos[i].cu; }
- dw_offset_t DIEOffsetAtIndex(uint32_t i) const { return m_infos[i].die_offset; }
- dw_attr_t AttributeAtIndex(uint32_t i) const { return m_infos[i].attr; }
- dw_attr_t FormAtIndex(uint32_t i) const { return m_infos[i].form; }
- bool ExtractFormValueAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, DWARFFormValue &form_value) const;
- uint64_t FormValueAsUnsignedAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, uint64_t fail_value) const;
- uint64_t FormValueAsUnsigned (SymbolFileDWARF* dwarf2Data, dw_attr_t attr, uint64_t fail_value) const;
- uint32_t FindAttributeIndex(dw_attr_t attr) const;
- bool ContainsAttribute(dw_attr_t attr) const;
- bool RemoveAttribute(dw_attr_t attr);
- void Clear() { m_infos.clear(); }
- size_t Size() const { return m_infos.size(); }
-
- protected:
- struct Info
- {
- const DWARFCompileUnit *cu; // Keep the compile unit with each attribute in case we have DW_FORM_ref_addr values
- dw_offset_t die_offset;
- dw_attr_t attr;
- dw_form_t form;
- };
-
- typedef llvm::SmallVector<Info, 8> collection;
- collection m_infos;
- };
-
- struct CompareState
- {
- CompareState() :
- die_offset_pairs()
- {
- assert(sizeof(dw_offset_t)*2 == sizeof(uint64_t));
- }
-
- bool AddTypePair(dw_offset_t a, dw_offset_t b)
- {
- uint64_t a_b_offsets = (uint64_t)a << 32 | (uint64_t)b;
- // Return true if this type was inserted, false otherwise
- return die_offset_pairs.insert(a_b_offsets).second;
- }
- std::set< uint64_t > die_offset_pairs;
- };
-
DWARFDebugInfoEntry():
m_offset (DW_INVALID_OFFSET),
m_parent_idx (0),
@@ -144,7 +94,7 @@ public:
bool FastExtract(
const lldb_private::DWARFDataExtractor& debug_info_data,
const DWARFCompileUnit* cu,
- const uint8_t *fixed_form_sizes,
+ const DWARFFormValue::FixedFormSizes& fixed_form_sizes,
lldb::offset_t* offset_ptr);
bool Extract(
@@ -160,68 +110,67 @@ public:
DWARFDebugInfoEntry** block_die);
size_t GetAttributes(
- SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
- const uint8_t *fixed_form_sizes,
- DWARFDebugInfoEntry::Attributes& attrs,
+ DWARFFormValue::FixedFormSizes fixed_form_sizes,
+ DWARFAttributes& attrs,
uint32_t curr_depth = 0) const; // "curr_depth" for internal use only, don't set this yourself!!!
- dw_offset_t GetAttributeValue(
- SymbolFileDWARF* dwarf2Data,
- const DWARFCompileUnit* cu,
- const dw_attr_t attr,
- DWARFFormValue& formValue,
- dw_offset_t* end_attr_offset_ptr = NULL) const;
-
const char* GetAttributeValueAsString(
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
const dw_attr_t attr,
- const char* fail_value) const;
+ const char* fail_value,
+ bool check_specification_or_abstract_origin = false) const;
uint64_t GetAttributeValueAsUnsigned(
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
const dw_attr_t attr,
- uint64_t fail_value) const;
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin = false) const;
uint64_t GetAttributeValueAsReference(
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
const dw_attr_t attr,
- uint64_t fail_value) const;
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin = false) const;
int64_t GetAttributeValueAsSigned(
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
const dw_attr_t attr,
- int64_t fail_value) const;
+ int64_t fail_value,
+ bool check_specification_or_abstract_origin = false) const;
+
+ uint64_t GetAttributeValueAsAddress(
+ SymbolFileDWARF* dwarf2Data,
+ const DWARFCompileUnit* cu,
+ const dw_attr_t attr,
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin = false) const;
dw_addr_t GetAttributeHighPC(
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
dw_addr_t lo_pc,
- uint64_t fail_value) const;
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin = false) const;
bool GetAttributeAddressRange(
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
dw_addr_t& lo_pc,
dw_addr_t& hi_pc,
- uint64_t fail_value) const;
+ uint64_t fail_value,
+ bool check_specification_or_abstract_origin = false) const;
size_t GetAttributeAddressRanges (
SymbolFileDWARF* dwarf2Data,
const DWARFCompileUnit* cu,
- DWARFDebugRanges::RangeList &ranges,
- bool check_hi_lo_pc) const;
-
- dw_offset_t GetAttributeValueAsLocation(
- SymbolFileDWARF* dwarf2Data,
- const DWARFCompileUnit* cu,
- const dw_attr_t attr,
- lldb_private::DWARFDataExtractor& data,
- uint32_t &block_size) const;
+ DWARFRangeList &ranges,
+ bool check_hi_lo_pc,
+ bool check_specification_or_abstract_origin = false) const;
const char* GetName(
SymbolFileDWARF* dwarf2Data,
@@ -256,25 +205,9 @@ public:
const char * GetQualifiedName (
SymbolFileDWARF* dwarf2Data,
DWARFCompileUnit* cu,
- const DWARFDebugInfoEntry::Attributes& attributes,
+ const DWARFAttributes& attributes,
std::string &storage) const;
-// static int Compare(
-// SymbolFileDWARF* dwarf2Data,
-// dw_offset_t a_die_offset,
-// dw_offset_t b_die_offset,
-// CompareState &compare_state,
-// bool compare_siblings,
-// bool compare_children);
-//
-// static int Compare(
-// SymbolFileDWARF* dwarf2Data,
-// DWARFCompileUnit* a_cu, const DWARFDebugInfoEntry* a_die,
-// DWARFCompileUnit* b_cu, const DWARFDebugInfoEntry* b_die,
-// CompareState &compare_state,
-// bool compare_siblings,
-// bool compare_children);
-
static bool OffsetLessThan (
const DWARFDebugInfoEntry& a,
const DWARFDebugInfoEntry& b);
@@ -311,7 +244,7 @@ public:
const DWARFCompileUnit* cu,
const char * &name,
const char * &mangled,
- DWARFDebugRanges::RangeList& rangeList,
+ DWARFRangeList& rangeList,
int& decl_file,
int& decl_line,
int& decl_column,
@@ -376,8 +309,7 @@ public:
const DWARFDebugInfoEntry* GetFirstChild() const { return (HasChildren() && !m_empty_children) ? this + 1 : NULL; }
- void GetDeclContextDIEs (SymbolFileDWARF* dwarf2Data,
- DWARFCompileUnit* cu,
+ void GetDeclContextDIEs (DWARFCompileUnit* cu,
DWARFDIECollection &decl_context_dies) const;
void GetDWARFDeclContext (SymbolFileDWARF* dwarf2Data,
@@ -389,11 +321,11 @@ public:
DWARFCompileUnit* cu,
const DWARFDeclContext &dwarf_decl_ctx) const;
- const DWARFDebugInfoEntry* GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,
+ DWARFDIE GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,
DWARFCompileUnit* cu) const;
- const DWARFDebugInfoEntry* GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,
+ DWARFDIE GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data,
DWARFCompileUnit* cu,
- const DWARFDebugInfoEntry::Attributes& attributes) const;
+ const DWARFAttributes& attributes) const;
void
SetParent (DWARFDebugInfoEntry* parent)
@@ -450,6 +382,13 @@ public:
DWARFDebugInfoEntry::collection &die_collection);
protected:
+ dw_offset_t GetAttributeValue(SymbolFileDWARF* dwarf2Data,
+ const DWARFCompileUnit* cu,
+ const dw_attr_t attr,
+ DWARFFormValue& formValue,
+ dw_offset_t* end_attr_offset_ptr = nullptr,
+ bool check_specification_or_abstract_origin = false) const;
+
dw_offset_t m_offset; // Offset within the .debug_info of the start of this entry
uint32_t m_parent_idx; // How many to subtract from "this" to get the parent. If zero this die has no parent
uint32_t m_sibling_idx:31, // How many to add to "this" to get the sibling.
@@ -457,7 +396,6 @@ protected:
uint32_t m_abbr_idx:DIE_ABBR_IDX_BITSIZE,
m_has_children:1, // Set to 1 if this DIE has children
m_tag:16; // A copy of the DW_TAG value so we don't have to go through the compile unit abbrev table
-
};
#endif // SymbolFileDWARF_DWARFDebugInfoEntry_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
index 48e11bd80089..84c2142e8419 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
@@ -249,7 +249,7 @@ DWARFDebugLine::DumpStatementOpcodes(Log *log, const DWARFDataExtractor& debug_l
fileEntry.length = debug_line_data.GetULEB128(&offset);
log->Printf( "0x%8.8x: DW_LNE_define_file('%s', dir=%i, mod_time=0x%8.8x, length=%i )",
op_offset,
- fileEntry.name.c_str(),
+ fileEntry.name,
fileEntry.dir_idx,
fileEntry.mod_time,
fileEntry.length);
@@ -486,65 +486,25 @@ DWARFDebugLine::ParseSupportFiles (const lldb::ModuleSP &module_sp,
FileSpecList &support_files)
{
lldb::offset_t offset = stmt_list;
- // Skip the total length
- (void)debug_line_data.GetDWARFInitialLength(&offset);
- uint32_t version = debug_line_data.GetU16(&offset);
- if (version < 2 || version > 4)
- return false;
- const dw_offset_t end_prologue_offset = debug_line_data.GetDWARFOffset(&offset) + offset;
- // Skip instruction length, default is stmt, line base, line range
- offset += 4;
- // For DWARF4, skip maximum operations per instruction
- if (version >= 4)
- offset += 1;
- // Skip opcode base, and all opcode lengths
- const uint8_t opcode_base = debug_line_data.GetU8(&offset);
- offset += opcode_base - 1;
- std::vector<FileSpec> include_directories{{}}; // Directory at index zero doesn't exist
- while (offset < end_prologue_offset)
+ Prologue prologue;
+ if (!ParsePrologue(debug_line_data, &offset, &prologue))
{
- FileSpec dir{debug_line_data.GetCStr(&offset), false};
- if (dir)
- include_directories.emplace_back(std::move(dir));
- else
- break;
+ Host::SystemLog (Host::eSystemLogError, "error: parsing line table prologue at 0x%8.8x (parsing ended around 0x%8.8" PRIx64 "\n", stmt_list, offset);
+ return false;
}
- while (offset < end_prologue_offset)
- {
- FileSpec file_spec{debug_line_data.GetCStr(&offset), false};
- if (file_spec)
- {
- uint32_t dir_idx = debug_line_data.GetULEB128(&offset);
- debug_line_data.Skip_LEB128(&offset); // Skip mod_time
- debug_line_data.Skip_LEB128(&offset); // Skip length
- if (file_spec.IsRelative())
- {
- if (0 < dir_idx && dir_idx < include_directories.size())
- {
- const FileSpec &dir = include_directories[dir_idx];
- file_spec.PrependPathComponent(dir);
- }
- if (file_spec.IsRelative())
- file_spec.PrependPathComponent(cu_comp_dir);
- }
- std::string remapped_file;
- if (module_sp->RemapSourceFile(file_spec.GetCString(), remapped_file))
- file_spec.SetFile(remapped_file, false);
- support_files.Append(file_spec);
- }
- }
+ FileSpec file_spec;
+ std::string remapped_file;
- if (offset != end_prologue_offset)
+ for (uint32_t file_idx = 1; prologue.GetFile(file_idx, cu_comp_dir, file_spec); ++file_idx)
{
- Host::SystemLog (Host::eSystemLogError,
- "warning: parsing line table prologue at 0x%8.8x should have ended at 0x%8.8x but it ended at 0x%8.8" PRIx64 "\n",
- stmt_list,
- end_prologue_offset,
- offset);
+ if (module_sp->RemapSourceFile(file_spec.GetCString(), remapped_file))
+ file_spec.SetFile(remapped_file, false);
+ support_files.Append(file_spec);
+
}
- return end_prologue_offset;
+ return true;
}
//----------------------------------------------------------------------
@@ -900,7 +860,7 @@ DWARFDebugLine::Prologue::Dump(Log *log)
{
for (i=0; i<include_directories.size(); ++i)
{
- log->Printf( "include_directories[%3u] = '%s'", i+1, include_directories[i].c_str());
+ log->Printf( "include_directories[%3u] = '%s'", i+1, include_directories[i]);
}
}
@@ -916,7 +876,7 @@ DWARFDebugLine::Prologue::Dump(Log *log)
fileEntry.dir_idx,
fileEntry.mod_time,
fileEntry.length,
- fileEntry.name.c_str());
+ fileEntry.name);
}
}
}
@@ -959,17 +919,28 @@ DWARFDebugLine::Prologue::Dump(Log *log)
//}
-bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, std::string& path, std::string& directory) const
+bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, const char *comp_dir, FileSpec &file) const
{
uint32_t idx = file_idx - 1; // File indexes are 1 based...
if (idx < file_names.size())
{
- path = file_names[idx].name;
- uint32_t dir_idx = file_names[idx].dir_idx - 1;
- if (dir_idx < include_directories.size())
- directory = include_directories[dir_idx];
- else
- directory.clear();
+ file.SetFile(file_names[idx].name, false);
+ if (file.IsRelative())
+ {
+ if (file_names[idx].dir_idx > 0)
+ {
+ const uint32_t dir_idx = file_names[idx].dir_idx - 1;
+ if (dir_idx < include_directories.size())
+ {
+ file.PrependPathComponent(include_directories[dir_idx]);
+ if (!file.IsRelative())
+ return true;
+ }
+ }
+
+ if (comp_dir && comp_dir[0])
+ file.PrependPathComponent(comp_dir);
+ }
return true;
}
return false;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
index 7da0e76a22be..9f2219b01812 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
@@ -20,7 +20,6 @@
#include "DWARFDefines.h"
class SymbolFileDWARF;
-class DWARFDebugInfoEntry;
//----------------------------------------------------------------------
// DWARFDebugLine
@@ -34,14 +33,14 @@ public:
struct FileNameEntry
{
FileNameEntry() :
- name(),
+ name(nullptr),
dir_idx(0),
mod_time(0),
length(0)
{
}
- std::string name;
+ const char* name;
dw_sleb128_t dir_idx;
dw_sleb128_t mod_time;
dw_sleb128_t length;
@@ -81,7 +80,7 @@ public:
uint8_t line_range; // This parameter affects the meaning of the special opcodes. See below.
uint8_t opcode_base; // The number assigned to the first special opcode.
std::vector<uint8_t> standard_opcode_lengths;
- std::vector<std::string> include_directories;
+ std::vector<const char *> include_directories;
std::vector<FileNameEntry> file_names;
int32_t MaxLineIncrementForSpecialOpcode() const { return line_base + (int8_t)line_range - 1; }
@@ -96,7 +95,7 @@ public:
include_directories.clear();
file_names.clear();
}
- bool GetFile(uint32_t file_idx, std::string& file, std::string& dir) const;
+ bool GetFile(uint32_t file_idx, const char *comp_dir, lldb_private::FileSpec &file) const;
};
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp
new file mode 100644
index 000000000000..75c812e6e79d
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp
@@ -0,0 +1,128 @@
+//===-- DWARFDebugMacro.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugMacro.h"
+#include "SymbolFileDWARF.h"
+
+#include "lldb/Symbol/DebugMacros.h"
+
+#include "DWARFDataExtractor.h"
+
+using namespace lldb_private;
+
+DWARFDebugMacroHeader
+DWARFDebugMacroHeader::ParseHeader(const DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset)
+{
+ DWARFDebugMacroHeader header;
+
+ // Skip over the version field in header.
+ header.m_version = debug_macro_data.GetU16(offset);
+
+ uint8_t flags = debug_macro_data.GetU8(offset);
+ header.m_offset_is_64_bit = flags & OFFSET_SIZE_MASK ? true : false;
+
+ if (flags & DEBUG_LINE_OFFSET_MASK)
+ {
+ if (header.m_offset_is_64_bit)
+ header.m_debug_line_offset = debug_macro_data.GetU64(offset);
+ else
+ header.m_debug_line_offset = debug_macro_data.GetU32(offset);
+ }
+
+ // Skip over the operands table if it is present.
+ if (flags & OPCODE_OPERANDS_TABLE_MASK)
+ SkipOperandTable(debug_macro_data, offset);
+
+ return header;
+}
+
+void
+DWARFDebugMacroHeader::SkipOperandTable(const DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset)
+{
+ uint8_t entry_count = debug_macro_data.GetU8(offset);
+ for (uint8_t i = 0; i < entry_count; i++)
+ {
+ // Skip over the opcode number.
+ debug_macro_data.GetU8(offset);
+
+ uint64_t operand_count = debug_macro_data.GetULEB128(offset);
+
+ for (uint64_t j = 0; j < operand_count; j++)
+ {
+ // Skip over the operand form
+ debug_macro_data.GetU8(offset);
+ }
+ }
+}
+
+void
+DWARFDebugMacroEntry::ReadMacroEntries(const DWARFDataExtractor &debug_macro_data,
+ const DWARFDataExtractor &debug_str_data,
+ const bool offset_is_64_bit,
+ lldb::offset_t *offset,
+ SymbolFileDWARF *sym_file_dwarf,
+ DebugMacrosSP &debug_macros_sp)
+{
+ llvm::dwarf::MacroEntryType type = static_cast<llvm::dwarf::MacroEntryType>(debug_macro_data.GetU8(offset));
+ while (type != 0)
+ {
+ lldb::offset_t new_offset = 0, str_offset = 0;
+ uint32_t line = 0;
+ const char *macro_str = nullptr;
+ uint32_t debug_line_file_idx = 0;
+
+ switch (type)
+ {
+ case DW_MACRO_define:
+ case DW_MACRO_undef:
+ line = debug_macro_data.GetULEB128(offset);
+ macro_str = debug_macro_data.GetCStr(offset);
+ if (type == DW_MACRO_define)
+ debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateDefineEntry(line, macro_str));
+ else
+ debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateUndefEntry(line, macro_str));
+ break;
+ case DW_MACRO_define_indirect:
+ case DW_MACRO_undef_indirect:
+ line = debug_macro_data.GetULEB128(offset);
+ if (offset_is_64_bit)
+ str_offset = debug_macro_data.GetU64(offset);
+ else
+ str_offset = debug_macro_data.GetU32(offset);
+ macro_str = debug_str_data.GetCStr(&str_offset);
+ if (type == DW_MACRO_define_indirect)
+ debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateDefineEntry(line, macro_str));
+ else
+ debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateUndefEntry(line, macro_str));
+ break;
+ case DW_MACRO_start_file:
+ line = debug_macro_data.GetULEB128(offset);
+ debug_line_file_idx = debug_macro_data.GetULEB128(offset);
+ debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateStartFileEntry(line, debug_line_file_idx));
+ break;
+ case DW_MACRO_end_file:
+ // This operation has no operands.
+ debug_macros_sp->AddMacroEntry(DebugMacroEntry::CreateEndFileEntry());
+ break;
+ case DW_MACRO_transparent_include:
+ if (offset_is_64_bit)
+ new_offset = debug_macro_data.GetU64(offset);
+ else
+ new_offset = debug_macro_data.GetU32(offset);
+ debug_macros_sp->AddMacroEntry(
+ DebugMacroEntry::CreateIndirectEntry(sym_file_dwarf->ParseDebugMacros(&new_offset)));
+ break;
+ default:
+ // TODO: Add support for other standard operations.
+ // TODO: Provide mechanism to hook handling of non-standard/extension operands.
+ return;
+ }
+ type = static_cast<llvm::dwarf::MacroEntryType>(debug_macro_data.GetU8(offset));
+ }
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h
new file mode 100644
index 000000000000..c60b9749b005
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h
@@ -0,0 +1,68 @@
+//===-- DWARFDebugMacro.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFDebugMacro_h_
+#define SymbolFileDWARF_DWARFDebugMacro_h_
+
+#include <map>
+
+#include "lldb/lldb-types.h"
+#include "lldb/Core/dwarf.h"
+#include "lldb/Symbol/DebugMacros.h"
+
+namespace lldb_private
+{
+
+class DWARFDataExtractor;
+
+} // namespace lldb_private
+
+class SymbolFileDWARF;
+
+class DWARFDebugMacroHeader
+{
+public:
+ enum HeaderFlagMask
+ {
+ OFFSET_SIZE_MASK = 0x1,
+ DEBUG_LINE_OFFSET_MASK = 0x2,
+ OPCODE_OPERANDS_TABLE_MASK = 0x4
+ };
+
+ static DWARFDebugMacroHeader
+ ParseHeader(const lldb_private::DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset);
+
+ bool
+ OffsetIs64Bit() const
+ {
+ return m_offset_is_64_bit;
+ }
+
+private:
+ static void
+ SkipOperandTable(const lldb_private::DWARFDataExtractor &debug_macro_data, lldb::offset_t *offset);
+
+ uint16_t m_version;
+ bool m_offset_is_64_bit;
+ uint64_t m_debug_line_offset;
+};
+
+class DWARFDebugMacroEntry
+{
+public:
+ static void
+ ReadMacroEntries(const lldb_private::DWARFDataExtractor &debug_macro_data,
+ const lldb_private::DWARFDataExtractor &debug_str_data,
+ const bool offset_is_64_bit,
+ lldb::offset_t *sect_offset,
+ SymbolFileDWARF *sym_file_dwarf,
+ lldb_private::DebugMacrosSP &debug_macros_sp);
+};
+
+#endif // SymbolFileDWARF_DWARFDebugMacro_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
index 8469b78d0dd5..547bd0cd1a5a 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
@@ -77,9 +77,6 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
if (debug_info)
{
-
- const DWARFDataExtractor* debug_str = &dwarf2Data->get_debug_str_data();
-
uint32_t cu_idx = 0;
const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
@@ -87,7 +84,9 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize(), cu->IsDWARF64());
+ DWARFFormValue::FixedFormSizes fixed_form_sizes =
+ DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize(),
+ cu->IsDWARF64());
bool clear_dies = cu->ExtractDIEsIfNeeded (false) > 1;
@@ -101,17 +100,17 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
size_t die_idx;
for (die_idx = 0; die_idx < die_count; ++die_idx)
{
- const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx);
- DWARFDebugInfoEntry::Attributes attributes;
+ DWARFDIE die = dies.GetDIEAtIndex(die_idx);
+ DWARFAttributes attributes;
const char *name = NULL;
const char *mangled = NULL;
bool add_die = false;
- const size_t num_attributes = die->GetAttributes(dwarf2Data, cu, fixed_form_sizes, attributes);
+ const size_t num_attributes = die.GetDIE()->GetAttributes(die.GetCU(), fixed_form_sizes, attributes);
if (num_attributes > 0)
{
uint32_t i;
- dw_tag_t tag = die->Tag();
+ dw_tag_t tag = die.Tag();
for (i=0; i<num_attributes; ++i)
{
@@ -120,14 +119,14 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
switch (attr)
{
case DW_AT_name:
- if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
- name = form_value.AsCString(debug_str);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ name = form_value.AsCString();
break;
case DW_AT_MIPS_linkage_name:
case DW_AT_linkage_name:
- if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
- mangled = form_value.AsCString(debug_str);
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
+ mangled = form_value.AsCString();
break;
case DW_AT_low_pc:
@@ -140,10 +139,10 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
case DW_AT_location:
if (tag == DW_TAG_variable)
{
- const DWARFDebugInfoEntry* parent_die = die->GetParent();
- while ( parent_die != NULL )
+ DWARFDIE parent_die = die.GetParent();
+ while ( parent_die )
{
- switch (parent_die->Tag())
+ switch (parent_die.Tag())
{
case DW_TAG_subprogram:
case DW_TAG_lexical_block:
@@ -153,31 +152,16 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
// if the location describes a hard coded address, but we don't want the performance
// penalty of that right now.
add_die = false;
-// if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
-// {
-// // If we have valid block data, then we have location expression bytes
-// // that are fixed (not a location list).
-// const uint8_t *block_data = form_value.BlockData();
-// if (block_data)
-// {
-// uint32_t block_length = form_value.Unsigned();
-// if (block_length == 1 + attributes.CompileUnitAtIndex(i)->GetAddressByteSize())
-// {
-// if (block_data[0] == DW_OP_addr)
-// add_die = true;
-// }
-// }
-// }
- parent_die = NULL; // Terminate the while loop.
+ parent_die.Clear(); // Terminate the while loop.
break;
case DW_TAG_compile_unit:
add_die = true;
- parent_die = NULL; // Terminate the while loop.
+ parent_die.Clear(); // Terminate the while loop.
break;
default:
- parent_die = parent_die->GetParent(); // Keep going in the while loop.
+ parent_die = parent_die.GetParent(); // Keep going in the while loop.
break;
}
}
@@ -189,7 +173,7 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
if (add_die && (name || mangled))
{
- pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, mangled ? mangled : name);
+ pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), mangled ? mangled : name);
}
}
@@ -231,13 +215,11 @@ DWARFDebugPubnames::GeneratePubBaseTypes(SymbolFileDWARF* dwarf2Data)
size_t die_idx;
for (die_idx = 0; die_idx < die_count; ++die_idx)
{
- const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx);
- const char *name = die->GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, NULL);
+ DWARFDIE die = dies.GetDIEAtIndex (die_idx);
+ const char *name = die.GetName();
if (name)
- {
- pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, name);
- }
+ pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), name);
}
if (pubnames_set.NumDescriptors() > 0)
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
index 0953554ffd7d..fc2831f22438 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
@@ -27,7 +27,7 @@ DWARFDebugRanges::~DWARFDebugRanges()
void
DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data)
{
- RangeList range_list;
+ DWARFRangeList range_list;
lldb::offset_t offset = 0;
dw_offset_t debug_ranges_offset = offset;
while (Extract(dwarf2Data, &offset, range_list))
@@ -38,52 +38,8 @@ DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data)
}
}
-//void
-//DWARFDebugRanges::RangeList::AddOffset(dw_addr_t offset)
-//{
-// if (!ranges.empty())
-// {
-// Range::iterator pos = ranges.begin();
-// Range::iterator end_pos = ranges.end();
-// for (pos = ranges.begin(); pos != end_pos; ++pos)
-// {
-// // assert for unsigned overflows
-// assert (~pos->begin_offset >= offset);
-// assert (~pos->end_offset >= offset);
-// pos->begin_offset += offset;
-// pos->end_offset += offset;
-// }
-// }
-//}
-//
-//void
-//DWARFDebugRanges::RangeList::SubtractOffset(dw_addr_t offset)
-//{
-// if (!ranges.empty())
-// {
-// Range::iterator pos = ranges.begin();
-// Range::iterator end_pos = ranges.end();
-// for (pos = ranges.begin(); pos != end_pos; ++pos)
-// {
-// assert (pos->begin_offset >= offset);
-// assert (pos->end_offset >= offset);
-// pos->begin_offset -= offset;
-// pos->end_offset -= offset;
-// }
-// }
-//}
-//
-//
-//const DWARFDebugRanges::Range*
-//DWARFDebugRanges::RangeList::RangeAtIndex(size_t i) const
-//{
-// if (i < ranges.size())
-// return &ranges[i];
-// return NULL;
-//}
-
bool
-DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data, lldb::offset_t *offset_ptr, RangeList &range_list)
+DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data, lldb::offset_t *offset_ptr, DWARFRangeList &range_list)
{
range_list.Clear();
@@ -118,13 +74,13 @@ DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data, lldb::offset_t *offset_pt
break;
default:
- assert(!"DWARFDebugRanges::RangeList::Extract() unsupported address size.");
+ assert(!"DWARFRangeList::Extract() unsupported address size.");
break;
}
// Filter out empty ranges
if (begin < end)
- range_list.Append(Range(begin, end - begin));
+ range_list.Append(DWARFRangeList::Entry(begin, end - begin));
}
// Make sure we consumed at least something
@@ -178,7 +134,7 @@ DWARFDebugRanges::Dump(Stream &s, const DWARFDataExtractor& debug_ranges_data, l
}
bool
-DWARFDebugRanges::FindRanges(dw_offset_t debug_ranges_offset, RangeList& range_list) const
+DWARFDebugRanges::FindRanges(dw_offset_t debug_ranges_offset, DWARFRangeList& range_list) const
{
range_map_const_iterator pos = m_range_map.find(debug_ranges_offset);
if (pos != m_range_map.end())
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
index 50af91d41009..3ff4ea3502c9 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
@@ -11,34 +11,30 @@
#define SymbolFileDWARF_DWARFDebugRanges_h_
#include "SymbolFileDWARF.h"
+#include "DWARFDIE.h"
#include <map>
-#include <vector>
-
-#include "lldb/Core/RangeMap.h"
class DWARFDebugRanges
{
public:
- typedef lldb_private::RangeArray<dw_addr_t, dw_addr_t, 2> RangeList;
- typedef RangeList::Entry Range;
DWARFDebugRanges();
~DWARFDebugRanges();
void Extract(SymbolFileDWARF* dwarf2Data);
static void Dump(lldb_private::Stream &s, const lldb_private::DWARFDataExtractor& debug_ranges_data, lldb::offset_t *offset_ptr, dw_addr_t cu_base_addr);
- bool FindRanges(dw_offset_t debug_ranges_offset, DWARFDebugRanges::RangeList& range_list) const;
+ bool FindRanges(dw_offset_t debug_ranges_offset, DWARFRangeList& range_list) const;
protected:
bool
Extract (SymbolFileDWARF* dwarf2Data,
lldb::offset_t *offset_ptr,
- RangeList &range_list);
+ DWARFRangeList &range_list);
- typedef std::map<dw_offset_t, RangeList> range_map;
- typedef range_map::iterator range_map_iterator;
- typedef range_map::const_iterator range_map_const_iterator;
+ typedef std::map<dw_offset_t, DWARFRangeList> range_map;
+ typedef range_map::iterator range_map_iterator;
+ typedef range_map::const_iterator range_map_const_iterator;
range_map m_range_map;
};
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
index 3a99d2b33878..4c29447b47bb 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
@@ -108,6 +108,13 @@ public:
return lldb_private::ConstString (GetQualifiedName ());
}
+ void
+ Clear()
+ {
+ m_entries.clear();
+ m_qualified_name.clear();
+ }
+
protected:
typedef std::vector<Entry> collection;
collection m_entries;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
index c733832e4f4d..a0ed9731a565 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -136,21 +136,21 @@ g_form_sizes_addr8_dwarf64[] =
8, // 0x20 DW_FORM_ref_sig8
};
-const uint8_t *
+DWARFFormValue::FixedFormSizes
DWARFFormValue::GetFixedFormSizesForAddressSize (uint8_t addr_size, bool is_dwarf64)
{
if (!is_dwarf64) {
switch (addr_size)
{
- case 4: return g_form_sizes_addr4;
- case 8: return g_form_sizes_addr8;
+ case 4: return FixedFormSizes(g_form_sizes_addr4, sizeof(g_form_sizes_addr4));
+ case 8: return FixedFormSizes(g_form_sizes_addr8, sizeof(g_form_sizes_addr8));
}
} else {
if (addr_size == 8)
- return g_form_sizes_addr8_dwarf64;
+ return FixedFormSizes(g_form_sizes_addr8_dwarf64, sizeof(g_form_sizes_addr8_dwarf64));
// is_dwarf64 && addr_size == 4 : no provider does this.
}
- return NULL;
+ return FixedFormSizes();
}
DWARFFormValue::DWARFFormValue() :
@@ -187,11 +187,7 @@ DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* off
case DW_FORM_data2: m_value.value.uval = data.GetU16(offset_ptr); break;
case DW_FORM_data4: m_value.value.uval = data.GetU32(offset_ptr); break;
case DW_FORM_data8: m_value.value.uval = data.GetU64(offset_ptr); break;
- case DW_FORM_string: m_value.value.cstr = data.GetCStr(offset_ptr);
- // Set the string value to also be the data for inlined cstr form values only
- // so we can tell the difference between DW_FORM_string and DW_FORM_strp form
- // values;
- m_value.data = (const uint8_t*)m_value.value.cstr; break;
+ case DW_FORM_string: m_value.value.cstr = data.GetCStr(offset_ptr); break;
case DW_FORM_exprloc:
case DW_FORM_block: m_value.value.uval = data.GetULEB128(offset_ptr); is_block = true; break;
case DW_FORM_block1: m_value.value.uval = data.GetU8(offset_ptr); is_block = true; break;
@@ -219,10 +215,12 @@ DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* off
indirect = true;
break;
- case DW_FORM_sec_offset: assert(m_cu);
- m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4); break;
- case DW_FORM_flag_present: m_value.value.uval = 1; break;
- case DW_FORM_ref_sig8: m_value.value.uval = data.GetU64(offset_ptr); break;
+ case DW_FORM_sec_offset: assert(m_cu);
+ m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::IsDWARF64(m_cu) ? 8 : 4); break;
+ case DW_FORM_flag_present: m_value.value.uval = 1; break;
+ case DW_FORM_ref_sig8: m_value.value.uval = data.GetU64(offset_ptr); break;
+ case DW_FORM_GNU_str_index: m_value.value.uval = data.GetULEB128(offset_ptr); break;
+ case DW_FORM_GNU_addr_index: m_value.value.uval = data.GetULEB128(offset_ptr); break;
default:
return false;
break;
@@ -322,6 +320,8 @@ DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor& debug_info_d
case DW_FORM_sdata:
case DW_FORM_udata:
case DW_FORM_ref_udata:
+ case DW_FORM_GNU_addr_index:
+ case DW_FORM_GNU_str_index:
debug_info_data.Skip_LEB128(offset_ptr);
return true;
@@ -342,7 +342,7 @@ DWARFFormValue::SkipValue(dw_form_t form, const DWARFDataExtractor& debug_info_d
void
-DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data) const
+DWARFFormValue::Dump(Stream &s) const
{
uint64_t uvalue = Unsigned();
bool cu_relative_offset = false;
@@ -353,13 +353,13 @@ DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data) const
{
case DW_FORM_addr: s.Address(uvalue, sizeof (uint64_t)); break;
case DW_FORM_flag:
- case DW_FORM_data1: s.PutHex8(uvalue); break;
+ case DW_FORM_data1: s.PutHex8(uvalue); break;
case DW_FORM_data2: s.PutHex16(uvalue); break;
case DW_FORM_sec_offset:
case DW_FORM_data4: s.PutHex32(uvalue); break;
case DW_FORM_ref_sig8:
case DW_FORM_data8: s.PutHex64(uvalue); break;
- case DW_FORM_string: s.QuotedCString(AsCString(NULL)); break;
+ case DW_FORM_string: s.QuotedCString(AsCString()); break;
case DW_FORM_exprloc:
case DW_FORM_block:
case DW_FORM_block1:
@@ -395,18 +395,18 @@ DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data) const
case DW_FORM_sdata: s.PutSLEB128(uvalue); break;
case DW_FORM_udata: s.PutULEB128(uvalue); break;
case DW_FORM_strp:
- if (debug_str_data)
{
- if (verbose)
- s.Printf(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
-
- const char* dbg_str = AsCString(debug_str_data);
+ const char* dbg_str = AsCString();
if (dbg_str)
+ {
+ if (verbose)
+ s.Printf(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
s.QuotedCString(dbg_str);
- }
- else
- {
- s.PutHex32(uvalue);
+ }
+ else
+ {
+ s.PutHex32(uvalue);
+ }
}
break;
@@ -444,13 +444,52 @@ DWARFFormValue::Dump(Stream &s, const DWARFDataExtractor* debug_str_data) const
}
const char*
-DWARFFormValue::AsCString(const DWARFDataExtractor* debug_str_data_ptr) const
+DWARFFormValue::AsCString() const
{
- if (IsInlinedCStr())
+ SymbolFileDWARF* symbol_file = m_cu->GetSymbolFileDWARF();
+
+ if (m_form == DW_FORM_string)
+ {
return m_value.value.cstr;
- else if (debug_str_data_ptr)
- return debug_str_data_ptr->PeekCStr(m_value.value.uval);
- return NULL;
+ }
+ else if (m_form == DW_FORM_strp)
+ {
+ if (!symbol_file)
+ return nullptr;
+
+ return symbol_file->get_debug_str_data().PeekCStr(m_value.value.uval);
+ }
+ else if (m_form == DW_FORM_GNU_str_index)
+ {
+ if (!symbol_file)
+ return nullptr;
+
+ uint32_t index_size = m_cu->IsDWARF64() ? 8 : 4;
+ lldb::offset_t offset = m_value.value.uval * index_size;
+ dw_offset_t str_offset = symbol_file->get_debug_str_offsets_data().GetMaxU64(&offset, index_size);
+ return symbol_file->get_debug_str_data().PeekCStr(str_offset);
+ }
+ return nullptr;
+}
+
+dw_addr_t
+DWARFFormValue::Address() const
+{
+ SymbolFileDWARF* symbol_file = m_cu->GetSymbolFileDWARF();
+
+ if (m_form == DW_FORM_addr)
+ return Unsigned();
+
+ assert(m_cu);
+ assert(m_form == DW_FORM_GNU_addr_index);
+
+ if (!symbol_file)
+ return 0;
+
+ uint32_t index_size = m_cu->GetAddressByteSize();
+ dw_offset_t addr_base = m_cu->GetAddrBase();
+ lldb::offset_t offset = addr_base + m_value.value.uval * index_size;
+ return symbol_file->get_debug_addr_data().GetMaxU64(&offset, index_size);
}
uint64_t
@@ -500,9 +539,7 @@ DWARFFormValue::Reference (dw_offset_t base_offset) const
const uint8_t*
DWARFFormValue::BlockData() const
{
- if (!IsInlinedCStr())
- return m_value.data;
- return NULL;
+ return m_value.data;
}
@@ -537,7 +574,8 @@ DWARFFormValue::IsDataForm(const dw_form_t form)
}
int
-DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_value, const DWARFDataExtractor* debug_str_data_ptr)
+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();
@@ -558,6 +596,7 @@ DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_
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();
@@ -581,9 +620,10 @@ DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_
case DW_FORM_string:
case DW_FORM_strp:
+ case DW_FORM_GNU_str_index:
{
- const char *a_string = a_value.AsCString(debug_str_data_ptr);
- const char *b_string = b_value.AsCString(debug_str_data_ptr);
+ 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)
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
index 392df26a088e..b10f4d3a0ac9 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
@@ -35,6 +35,34 @@ public:
} value;
const uint8_t* data;
} ValueType;
+
+ class FixedFormSizes
+ {
+ public:
+ FixedFormSizes() :
+ m_fix_sizes(nullptr), m_size(0)
+ {}
+
+ FixedFormSizes(const uint8_t* fix_sizes, size_t size) :
+ m_fix_sizes(fix_sizes), m_size(size)
+ {}
+
+ uint8_t
+ GetSize(uint32_t index) const
+ {
+ return index < m_size ? m_fix_sizes[index] : 0;
+ }
+
+ bool
+ Empty() const
+ {
+ return m_size == 0;
+ }
+
+ private:
+ const uint8_t* m_fix_sizes;
+ size_t m_size;
+ };
enum
{
@@ -52,10 +80,9 @@ public:
dw_form_t Form() const { return m_form; }
void SetForm(dw_form_t form) { m_form = form; }
const ValueType& Value() const { return m_value; }
- void Dump(lldb_private::Stream &s, const lldb_private::DWARFDataExtractor* debug_str_data) const;
+ void Dump(lldb_private::Stream &s) const;
bool ExtractValue(const lldb_private::DWARFDataExtractor& data,
lldb::offset_t* offset_ptr);
- bool IsInlinedCStr() const { return (m_value.data != NULL) && m_value.data == (const uint8_t*)m_value.value.cstr; }
const uint8_t* BlockData() const;
uint64_t Reference() const;
uint64_t Reference (dw_offset_t offset) const;
@@ -64,13 +91,16 @@ public:
void SetUnsigned(uint64_t uval) { m_value.value.uval = uval; }
int64_t Signed() const { return m_value.value.sval; }
void SetSigned(int64_t sval) { m_value.value.sval = sval; }
- const char* AsCString(const lldb_private::DWARFDataExtractor* debug_str_data_ptr) const;
+ const char* AsCString() const;
+ dw_addr_t Address() const;
+ bool IsValid() const { return m_form != 0; }
bool SkipValue(const lldb_private::DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr) const;
static bool SkipValue(const dw_form_t form, const lldb_private::DWARFDataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu);
static bool IsBlockForm(const dw_form_t form);
static bool IsDataForm(const dw_form_t form);
- static const uint8_t * GetFixedFormSizesForAddressSize (uint8_t addr_size, bool is_dwarf64);
- static int Compare (const DWARFFormValue& a, const DWARFFormValue& b, const lldb_private::DWARFDataExtractor* debug_str_data_ptr);
+ static FixedFormSizes GetFixedFormSizesForAddressSize (uint8_t addr_size, bool is_dwarf64);
+ static int Compare (const DWARFFormValue& a,
+ const DWARFFormValue& b);
protected:
const DWARFCompileUnit* m_cu; // Compile unit for this form
dw_form_t m_form; // Form for this value
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp b/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp
deleted file mode 100644
index d79ae79822b0..000000000000
--- a/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-//===-- DWARFLocationDescription.cpp ----------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "DWARFLocationDescription.h"
-#include "DWARFDefines.h"
-#include "lldb/lldb-private.h"
-#include "lldb/Core/Stream.h"
-
-
-using namespace lldb_private;
-
-static int print_dwarf_exp_op (Stream &s, const DWARFDataExtractor& data, lldb::offset_t *offset_ptr, int address_size, int dwarf_ref_size);
-
-int
-print_dwarf_expression (Stream &s,
- const DWARFDataExtractor& data,
- int address_size,
- int dwarf_ref_size,
- bool location_expression)
-{
- int op_count = 0;
- lldb::offset_t offset = 0;
- while (data.ValidOffset(offset))
- {
- if (location_expression && op_count > 0)
- {
- // err (baton, "Dwarf location expressions may only have one operand!");
- return 1;
- }
- if (op_count > 0)
- {
- s.PutCString(", ");
- }
- if (print_dwarf_exp_op (s, data, &offset, address_size, dwarf_ref_size) == 1)
- return 1;
- op_count++;
- }
-
- return 0;
-}
-
-static int
-print_dwarf_exp_op (Stream &s,
- const DWARFDataExtractor& data,
- lldb::offset_t *offset_ptr,
- int address_size,
- int dwarf_ref_size)
-{
- uint8_t opcode = data.GetU8(offset_ptr);
- DRC_class opcode_class;
- uint64_t uint;
- int64_t sint;
-
- int size;
-
- opcode_class = DW_OP_value_to_class (opcode) & (~DRC_DWARFv3);
-
- s.Printf("%s ", DW_OP_value_to_name (opcode));
-
- /* Does this take zero parameters? If so we can shortcut this function. */
- if (opcode_class == DRC_ZEROOPERANDS)
- return 0;
-
- if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_bregx)
- {
- uint = data.GetULEB128(offset_ptr);
- sint = data.GetSLEB128(offset_ptr);
- s.Printf("%" PRIu64 " %" PRIi64, uint, sint);
- return 0;
- }
- if (opcode_class != DRC_ONEOPERAND)
- {
- s.Printf("UNKNOWN OP %u", opcode);
- return 1;
- }
-
- switch (opcode)
- {
- case DW_OP_addr: size = address_size; break;
- case DW_OP_const1u: size = 1; break;
- case DW_OP_const1s: size = -1; break;
- case DW_OP_const2u: size = 2; break;
- case DW_OP_const2s: size = -2; break;
- case DW_OP_const4u: size = 4; break;
- case DW_OP_const4s: size = -4; break;
- case DW_OP_const8u: size = 8; break;
- case DW_OP_const8s: size = -8; break;
- case DW_OP_constu: size = 128; break;
- case DW_OP_consts: size = -128; break;
- case DW_OP_fbreg: size = -128; break;
- case DW_OP_breg0:
- case DW_OP_breg1:
- case DW_OP_breg2:
- case DW_OP_breg3:
- case DW_OP_breg4:
- case DW_OP_breg5:
- case DW_OP_breg6:
- case DW_OP_breg7:
- case DW_OP_breg8:
- case DW_OP_breg9:
- case DW_OP_breg10:
- case DW_OP_breg11:
- case DW_OP_breg12:
- case DW_OP_breg13:
- case DW_OP_breg14:
- case DW_OP_breg15:
- case DW_OP_breg16:
- case DW_OP_breg17:
- case DW_OP_breg18:
- case DW_OP_breg19:
- case DW_OP_breg20:
- case DW_OP_breg21:
- case DW_OP_breg22:
- case DW_OP_breg23:
- case DW_OP_breg24:
- case DW_OP_breg25:
- case DW_OP_breg26:
- case DW_OP_breg27:
- case DW_OP_breg28:
- case DW_OP_breg29:
- case DW_OP_breg30:
- case DW_OP_breg31:
- size = -128; break;
- case DW_OP_pick:
- size = 1; break;
- case DW_OP_deref_size:
- size = 1; break;
- case DW_OP_xderef_size:
- size = 1; break;
- case DW_OP_plus_uconst:
- size = 128; break;
- case DW_OP_skip:
- size = -2; break;
- case DW_OP_bra:
- size = -2; break;
- case DW_OP_call2:
- size = 2; break;
- case DW_OP_call4:
- size = 4; break;
- case DW_OP_call_ref:
- size = dwarf_ref_size; break;
- case DW_OP_piece:
- size = 128; break;
- case DW_OP_regx:
- size = 128; break;
- default:
- s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode);
- return 1;
- }
-
- switch (size)
- {
- case -1: sint = (int8_t) data.GetU8(offset_ptr); s.Printf("%+" PRIi64, sint); break;
- case -2: sint = (int16_t) data.GetU16(offset_ptr); s.Printf("%+" PRIi64, sint); break;
- case -4: sint = (int32_t) data.GetU32(offset_ptr); s.Printf("%+" PRIi64, sint); break;
- case -8: sint = (int64_t) data.GetU64(offset_ptr); s.Printf("%+" PRIi64, sint); break;
- case -128: sint = data.GetSLEB128(offset_ptr); s.Printf("%+" PRIi64, sint); break;
- case 1: uint = data.GetU8(offset_ptr); s.Printf("0x%2.2" PRIx64, uint); break;
- case 2: uint = data.GetU16(offset_ptr); s.Printf("0x%4.4" PRIx64, uint); break;
- case 4: uint = data.GetU32(offset_ptr); s.Printf("0x%8.8" PRIx64, uint); break;
- case 8: uint = data.GetU64(offset_ptr); s.Printf("0x%16.16" PRIx64, uint); break;
- case 128: uint = data.GetULEB128(offset_ptr); s.Printf("0x%" PRIx64, uint); break;
- }
-
- return 0;
-}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h b/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h
deleted file mode 100644
index 69cc0c15969c..000000000000
--- a/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h
+++ /dev/null
@@ -1,24 +0,0 @@
-//===-- DWARFLocationDescription.h ------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SymbolFileDWARF_DWARFLocationDescription_h_
-#define SymbolFileDWARF_DWARFLocationDescription_h_
-
-#include "SymbolFileDWARF.h"
-
-int
-print_dwarf_expression (lldb_private::Stream &s,
- const lldb_private::DWARFDataExtractor& data,
- int address_size,
- int dwarf_ref_size,
- bool location_expression);
-
-
-
-#endif // SymbolFileDWARF_DWARFLocationDescription_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp b/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp
deleted file mode 100644
index 26768f060ef1..000000000000
--- a/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-//===-- DWARFLocationList.cpp -----------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "DWARFLocationList.h"
-
-#include "lldb/Core/Stream.h"
-
-#include "DWARFCompileUnit.h"
-#include "DWARFDebugInfo.h"
-#include "DWARFLocationDescription.h"
-
-using namespace lldb_private;
-
-dw_offset_t
-DWARFLocationList::Dump(Stream &s, const DWARFCompileUnit* cu, const DWARFDataExtractor& debug_loc_data, lldb::offset_t offset)
-{
- uint64_t start_addr, end_addr;
- uint32_t addr_size = DWARFCompileUnit::GetAddressByteSize(cu);
- s.SetAddressByteSize(DWARFCompileUnit::GetAddressByteSize(cu));
- dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0;
- while (debug_loc_data.ValidOffset(offset))
- {
- start_addr = debug_loc_data.GetMaxU64(&offset,addr_size);
- end_addr = debug_loc_data.GetMaxU64(&offset,addr_size);
-
- if (start_addr == 0 && end_addr == 0)
- break;
-
- s.PutCString("\n ");
- s.Indent();
- if (cu)
- s.AddressRange (start_addr + base_addr,
- end_addr + base_addr,
- cu->GetAddressByteSize(),
- NULL,
- ": ");
- uint32_t loc_length = debug_loc_data.GetU16(&offset);
-
- DWARFDataExtractor locationData(debug_loc_data, offset, loc_length);
- // if ( dump_flags & DWARFDebugInfo::eDumpFlag_Verbose ) *ostrm_ptr << " ( ";
- print_dwarf_expression (s, locationData, addr_size, 4, false);
- offset += loc_length;
- }
-
- return offset;
-}
-
-bool
-DWARFLocationList::Extract(const DWARFDataExtractor& debug_loc_data, lldb::offset_t* offset_ptr, DWARFDataExtractor& location_list_data)
-{
- // Initialize with no data just in case we don't find anything
- location_list_data.Clear();
-
- size_t loc_list_length = Size(debug_loc_data, *offset_ptr);
- if (loc_list_length > 0)
- {
- location_list_data.SetData(debug_loc_data, *offset_ptr, loc_list_length);
- *offset_ptr += loc_list_length;
- return true;
- }
-
- return false;
-}
-
-size_t
-DWARFLocationList::Size(const DWARFDataExtractor& debug_loc_data, lldb::offset_t offset)
-{
- const dw_offset_t debug_loc_offset = offset;
-
- while (debug_loc_data.ValidOffset(offset))
- {
- dw_addr_t start_addr = debug_loc_data.GetAddress(&offset);
- dw_addr_t end_addr = debug_loc_data.GetAddress(&offset);
-
- if (start_addr == 0 && end_addr == 0)
- break;
-
- uint16_t loc_length = debug_loc_data.GetU16(&offset);
- offset += loc_length;
- }
-
- if (offset > debug_loc_offset)
- return offset - debug_loc_offset;
- return 0;
-}
-
-
-
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h b/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h
deleted file mode 100644
index 6dcc0d74e441..000000000000
--- a/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//===-- DWARFLocationList.h -------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SymbolFileDWARF_DWARFLocationList_h_
-#define SymbolFileDWARF_DWARFLocationList_h_
-
-#include "SymbolFileDWARF.h"
-
-class DWARFLocationList
-{
-public:
- static dw_offset_t
- Dump (lldb_private::Stream &s,
- const DWARFCompileUnit* cu,
- const lldb_private::DWARFDataExtractor& debug_loc_data,
- lldb::offset_t offset);
-
- static bool
- Extract (const lldb_private::DWARFDataExtractor& debug_loc_data,
- lldb::offset_t* offset_ptr,
- lldb_private::DWARFDataExtractor& location_list_data);
-
- static size_t
- Size (const lldb_private::DWARFDataExtractor& debug_loc_data,
- lldb::offset_t offset);
-
-};
-#endif // SymbolFileDWARF_DWARFLocationList_h_
diff --git a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
new file mode 100644
index 000000000000..0db416054ae8
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
@@ -0,0 +1,747 @@
+//===-- HashedNameToDIE.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "HashedNameToDIE.h"
+
+void
+DWARFMappedHash::ExtractDIEArray (const DIEInfoArray &die_info_array, DIEArray &die_offsets)
+{
+ const size_t count = die_info_array.size();
+ for (size_t i=0; i<count; ++i)
+ die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset);
+}
+
+void
+DWARFMappedHash::ExtractDIEArray (const DIEInfoArray &die_info_array,
+ const dw_tag_t tag,
+ DIEArray &die_offsets)
+{
+ if (tag == 0)
+ {
+ ExtractDIEArray (die_info_array, die_offsets);
+ }
+ else
+ {
+ const size_t count = die_info_array.size();
+ for (size_t i=0; i<count; ++i)
+ {
+ const dw_tag_t die_tag = die_info_array[i].tag;
+ bool tag_matches = die_tag == 0 || tag == die_tag;
+ if (!tag_matches)
+ {
+ if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
+ tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
+ }
+ if (tag_matches)
+ die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset);
+ }
+ }
+}
+
+void
+DWARFMappedHash::ExtractDIEArray (const DIEInfoArray &die_info_array,
+ const dw_tag_t tag,
+ const uint32_t qualified_name_hash,
+ DIEArray &die_offsets)
+{
+ if (tag == 0)
+ {
+ ExtractDIEArray (die_info_array, die_offsets);
+ }
+ else
+ {
+ const size_t count = die_info_array.size();
+ for (size_t i=0; i<count; ++i)
+ {
+ if (qualified_name_hash != die_info_array[i].qualified_name_hash)
+ continue;
+ const dw_tag_t die_tag = die_info_array[i].tag;
+ bool tag_matches = die_tag == 0 || tag == die_tag;
+ if (!tag_matches)
+ {
+ if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
+ tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
+ }
+ if (tag_matches)
+ die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset);
+ }
+ }
+}
+
+void
+DWARFMappedHash::ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array,
+ bool return_implementation_only_if_available,
+ DIEArray &die_offsets)
+{
+ const size_t count = die_info_array.size();
+ for (size_t i=0; i<count; ++i)
+ {
+ const dw_tag_t die_tag = die_info_array[i].tag;
+ if (die_tag == 0 || die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
+ {
+ if (die_info_array[i].type_flags & eTypeFlagClassIsImplementation)
+ {
+ if (return_implementation_only_if_available)
+ {
+ // We found the one true definition for this class, so
+ // only return that
+ die_offsets.clear();
+ die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset);
+ return;
+ }
+ else
+ {
+ // Put the one true definition as the first entry so it
+ // matches first
+ die_offsets.emplace(die_offsets.begin(), die_info_array[i].cu_offset, die_info_array[i].offset);
+ }
+ }
+ else
+ {
+ die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset);
+ }
+ }
+ }
+}
+
+void
+DWARFMappedHash::ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array,
+ uint32_t type_flag_mask,
+ uint32_t type_flag_value,
+ DIEArray &die_offsets)
+{
+ const size_t count = die_info_array.size();
+ for (size_t i=0; i<count; ++i)
+ {
+ if ((die_info_array[i].type_flags & type_flag_mask) == type_flag_value)
+ die_offsets.emplace_back(die_info_array[i].cu_offset, die_info_array[i].offset);
+ }
+}
+
+const char *
+DWARFMappedHash::GetAtomTypeName (uint16_t atom)
+{
+ switch (atom)
+ {
+ case eAtomTypeNULL: return "NULL";
+ case eAtomTypeDIEOffset: return "die-offset";
+ case eAtomTypeCUOffset: return "cu-offset";
+ case eAtomTypeTag: return "die-tag";
+ case eAtomTypeNameFlags: return "name-flags";
+ case eAtomTypeTypeFlags: return "type-flags";
+ case eAtomTypeQualNameHash: return "qualified-name-hash";
+ }
+ return "<invalid>";
+}
+
+DWARFMappedHash::DIEInfo::DIEInfo () :
+ cu_offset (DW_INVALID_OFFSET),
+ offset (DW_INVALID_OFFSET),
+ tag (0),
+ type_flags (0),
+ qualified_name_hash (0)
+{
+}
+
+DWARFMappedHash::DIEInfo::DIEInfo (dw_offset_t c,
+ dw_offset_t o,
+ dw_tag_t t,
+ uint32_t f,
+ uint32_t h) :
+ cu_offset (c),
+ offset (o),
+ tag (t),
+ type_flags (f),
+ qualified_name_hash (h)
+{
+}
+
+DWARFMappedHash::Prologue::Prologue (dw_offset_t _die_base_offset) :
+ die_base_offset (_die_base_offset),
+ atoms(),
+ atom_mask (0),
+ min_hash_data_byte_size(0),
+ hash_data_has_fixed_byte_size(true)
+{
+ // Define an array of DIE offsets by first defining an array,
+ // and then define the atom type for the array, in this case
+ // we have an array of DIE offsets
+ AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4);
+}
+
+void
+DWARFMappedHash::Prologue::ClearAtoms ()
+{
+ hash_data_has_fixed_byte_size = true;
+ min_hash_data_byte_size = 0;
+ atom_mask = 0;
+ atoms.clear();
+}
+
+bool
+DWARFMappedHash::Prologue::ContainsAtom (AtomType atom_type) const
+{
+ return (atom_mask & (1u << atom_type)) != 0;
+}
+
+void
+DWARFMappedHash::Prologue::Clear ()
+{
+ die_base_offset = 0;
+ ClearAtoms ();
+}
+
+void
+DWARFMappedHash::Prologue::AppendAtom (AtomType type, dw_form_t form)
+{
+ atoms.push_back ({type, form});
+ atom_mask |= 1u << type;
+ switch (form)
+ {
+ case DW_FORM_indirect:
+ case DW_FORM_exprloc:
+ case DW_FORM_flag_present:
+ case DW_FORM_ref_sig8:
+ assert (!"Unhandled atom form");
+ break;
+
+ case DW_FORM_string:
+ case DW_FORM_block:
+ case DW_FORM_block1:
+ case DW_FORM_sdata:
+ case DW_FORM_udata:
+ case DW_FORM_ref_udata:
+ case DW_FORM_GNU_addr_index:
+ case DW_FORM_GNU_str_index:
+ hash_data_has_fixed_byte_size = false;
+ // Fall through to the cases below...
+ case DW_FORM_flag:
+ case DW_FORM_data1:
+ case DW_FORM_ref1:
+ case DW_FORM_sec_offset:
+ min_hash_data_byte_size += 1;
+ break;
+
+ case DW_FORM_block2:
+ hash_data_has_fixed_byte_size = false;
+ // Fall through to the cases below...
+ case DW_FORM_data2:
+ case DW_FORM_ref2:
+ min_hash_data_byte_size += 2;
+ break;
+
+ case DW_FORM_block4:
+ hash_data_has_fixed_byte_size = false;
+ // Fall through to the cases below...
+ case DW_FORM_data4:
+ case DW_FORM_ref4:
+ case DW_FORM_addr:
+ case DW_FORM_ref_addr:
+ case DW_FORM_strp:
+ min_hash_data_byte_size += 4;
+ break;
+
+ case DW_FORM_data8:
+ case DW_FORM_ref8:
+ min_hash_data_byte_size += 8;
+ break;
+
+ }
+}
+
+lldb::offset_t
+DWARFMappedHash::Prologue::Read (const lldb_private::DataExtractor &data,
+ lldb::offset_t offset)
+{
+ ClearAtoms ();
+
+ die_base_offset = data.GetU32 (&offset);
+
+ const uint32_t atom_count = data.GetU32 (&offset);
+ if (atom_count == 0x00060003u)
+ {
+ // Old format, deal with contents of old pre-release format
+ while (data.GetU32(&offset))
+ /* do nothing */;
+
+ // Hardcode to the only known value for now.
+ AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4);
+ }
+ else
+ {
+ for (uint32_t i=0; i<atom_count; ++i)
+ {
+ AtomType type = (AtomType)data.GetU16 (&offset);
+ dw_form_t form = (dw_form_t)data.GetU16 (&offset);
+ AppendAtom (type, form);
+ }
+ }
+ return offset;
+}
+
+size_t
+DWARFMappedHash::Prologue::GetByteSize () const
+{
+ // Add an extra count to the atoms size for the zero termination Atom that gets
+ // written to disk
+ return sizeof(die_base_offset) + sizeof(uint32_t) + atoms.size() * sizeof(Atom);
+}
+
+size_t
+DWARFMappedHash::Prologue::GetMinimumHashDataByteSize () const
+{
+ return min_hash_data_byte_size;
+}
+
+bool
+DWARFMappedHash::Prologue::HashDataHasFixedByteSize() const
+{
+ return hash_data_has_fixed_byte_size;
+}
+
+size_t
+DWARFMappedHash::Header::GetByteSize (const HeaderData &header_data)
+{
+ return header_data.GetByteSize();
+}
+
+lldb::offset_t
+DWARFMappedHash::Header::Read (lldb_private::DataExtractor &data, lldb::offset_t offset)
+{
+ offset = MappedHash::Header<Prologue>::Read (data, offset);
+ if (offset != UINT32_MAX)
+ {
+ offset = header_data.Read (data, offset);
+ }
+ return offset;
+}
+
+bool
+DWARFMappedHash::Header::Read (const lldb_private::DWARFDataExtractor &data,
+ lldb::offset_t *offset_ptr,
+ DIEInfo &hash_data) const
+{
+ const size_t num_atoms = header_data.atoms.size();
+ if (num_atoms == 0)
+ return false;
+
+ for (size_t i=0; i<num_atoms; ++i)
+ {
+ DWARFFormValue form_value (NULL, header_data.atoms[i].form);
+
+ if (!form_value.ExtractValue(data, offset_ptr))
+ return false;
+
+ switch (header_data.atoms[i].type)
+ {
+ case eAtomTypeDIEOffset: // DIE offset, check form for encoding
+ hash_data.offset = (dw_offset_t)form_value.Reference (header_data.die_base_offset);
+ break;
+
+ case eAtomTypeTag: // DW_TAG value for the DIE
+ hash_data.tag = (dw_tag_t)form_value.Unsigned ();
+
+ case eAtomTypeTypeFlags: // Flags from enum TypeFlags
+ hash_data.type_flags = (uint32_t)form_value.Unsigned ();
+ break;
+
+ case eAtomTypeQualNameHash: // Flags from enum TypeFlags
+ hash_data.qualified_name_hash = form_value.Unsigned ();
+ break;
+
+ default:
+ // We can always skip atoms we don't know about
+ break;
+ }
+ }
+ return true;
+}
+
+void
+DWARFMappedHash::Header::Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const
+{
+ const size_t num_atoms = header_data.atoms.size();
+ for (size_t i=0; i<num_atoms; ++i)
+ {
+ if (i > 0)
+ strm.PutCString (", ");
+
+ DWARFFormValue form_value (NULL, header_data.atoms[i].form);
+ switch (header_data.atoms[i].type)
+ {
+ case eAtomTypeDIEOffset: // DIE offset, check form for encoding
+ strm.Printf ("{0x%8.8x}", hash_data.offset);
+ break;
+
+ case eAtomTypeTag: // DW_TAG value for the DIE
+ {
+ const char *tag_cstr = lldb_private::DW_TAG_value_to_name (hash_data.tag);
+ if (tag_cstr)
+ strm.PutCString (tag_cstr);
+ else
+ strm.Printf ("DW_TAG_(0x%4.4x)", hash_data.tag);
+ }
+ break;
+
+ case eAtomTypeTypeFlags: // Flags from enum TypeFlags
+ strm.Printf ("0x%2.2x", hash_data.type_flags);
+ if (hash_data.type_flags)
+ {
+ strm.PutCString (" (");
+ if (hash_data.type_flags & eTypeFlagClassIsImplementation)
+ strm.PutCString (" implementation");
+ strm.PutCString (" )");
+ }
+ break;
+
+ case eAtomTypeQualNameHash: // Flags from enum TypeFlags
+ strm.Printf ("0x%8.8x", hash_data.qualified_name_hash);
+ break;
+
+ default:
+ strm.Printf ("AtomType(0x%x)", header_data.atoms[i].type);
+ break;
+ }
+ }
+}
+
+DWARFMappedHash::MemoryTable::MemoryTable (lldb_private::DWARFDataExtractor &table_data,
+ const lldb_private::DWARFDataExtractor &string_table,
+ const char *name) :
+ MappedHash::MemoryTable<uint32_t, Header, DIEInfoArray> (table_data),
+ m_data (table_data),
+ m_string_table (string_table),
+ m_name (name)
+{
+}
+
+const char *
+DWARFMappedHash::MemoryTable::GetStringForKeyType (KeyType key) const
+{
+ // The key in the DWARF table is the .debug_str offset for the string
+ return m_string_table.PeekCStr (key);
+}
+
+bool
+DWARFMappedHash::MemoryTable::ReadHashData (uint32_t hash_data_offset, HashData &hash_data) const
+{
+ lldb::offset_t offset = hash_data_offset;
+ offset += 4; // Skip string table offset that contains offset of hash name in .debug_str
+ const uint32_t count = m_data.GetU32 (&offset);
+ if (count > 0)
+ {
+ hash_data.resize(count);
+ for (uint32_t i=0; i<count; ++i)
+ {
+ if (!m_header.Read(m_data, &offset, hash_data[i]))
+ return false;
+ }
+ }
+ else
+ hash_data.clear();
+ return true;
+}
+
+DWARFMappedHash::MemoryTable::Result
+DWARFMappedHash::MemoryTable::GetHashDataForName (const char *name,
+ lldb::offset_t* hash_data_offset_ptr,
+ Pair &pair) const
+{
+ pair.key = m_data.GetU32 (hash_data_offset_ptr);
+ pair.value.clear();
+
+ // If the key is zero, this terminates our chain of HashData objects
+ // for this hash value.
+ if (pair.key == 0)
+ return eResultEndOfHashData;
+
+ // There definitely should be a string for this string offset, if
+ // there isn't, there is something wrong, return and error
+ const char *strp_cstr = m_string_table.PeekCStr (pair.key);
+ if (strp_cstr == NULL)
+ {
+ *hash_data_offset_ptr = UINT32_MAX;
+ return eResultError;
+ }
+
+ const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
+ const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize();
+ if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
+ {
+ // We have at least one HashData entry, and we have enough
+ // data to parse at least "count" HashData entries.
+
+ // First make sure the entire C string matches...
+ const bool match = strcmp (name, strp_cstr) == 0;
+
+ if (!match && m_header.header_data.HashDataHasFixedByteSize())
+ {
+ // If the string doesn't match and we have fixed size data,
+ // we can just add the total byte size of all HashData objects
+ // to the hash data offset and be done...
+ *hash_data_offset_ptr += min_total_hash_data_size;
+ }
+ else
+ {
+ // If the string does match, or we don't have fixed size data
+ // then we need to read the hash data as a stream. If the
+ // string matches we also append all HashData objects to the
+ // value array.
+ for (uint32_t i=0; i<count; ++i)
+ {
+ DIEInfo die_info;
+ if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
+ {
+ // Only happened if the HashData of the string matched...
+ if (match)
+ pair.value.push_back (die_info);
+ }
+ else
+ {
+ // Something went wrong while reading the data
+ *hash_data_offset_ptr = UINT32_MAX;
+ return eResultError;
+ }
+ }
+ }
+ // Return the correct response depending on if the string matched
+ // or not...
+ if (match)
+ return eResultKeyMatch; // The key (cstring) matches and we have lookup results!
+ else
+ return eResultKeyMismatch; // The key doesn't match, this function will get called
+ // again for the next key/value or the key terminator
+ // which in our case is a zero .debug_str offset.
+ }
+ else
+ {
+ *hash_data_offset_ptr = UINT32_MAX;
+ return eResultError;
+ }
+}
+
+DWARFMappedHash::MemoryTable::Result
+DWARFMappedHash::MemoryTable::AppendHashDataForRegularExpression (
+ const lldb_private::RegularExpression& regex,
+ lldb::offset_t* hash_data_offset_ptr,
+ Pair &pair) const
+{
+ pair.key = m_data.GetU32 (hash_data_offset_ptr);
+ // If the key is zero, this terminates our chain of HashData objects
+ // for this hash value.
+ if (pair.key == 0)
+ return eResultEndOfHashData;
+
+ // There definitely should be a string for this string offset, if
+ // there isn't, there is something wrong, return and error
+ const char *strp_cstr = m_string_table.PeekCStr (pair.key);
+ if (strp_cstr == NULL)
+ return eResultError;
+
+ const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
+ const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize();
+ if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
+ {
+ const bool match = regex.Execute(strp_cstr);
+
+ if (!match && m_header.header_data.HashDataHasFixedByteSize())
+ {
+ // If the regex doesn't match and we have fixed size data,
+ // we can just add the total byte size of all HashData objects
+ // to the hash data offset and be done...
+ *hash_data_offset_ptr += min_total_hash_data_size;
+ }
+ else
+ {
+ // If the string does match, or we don't have fixed size data
+ // then we need to read the hash data as a stream. If the
+ // string matches we also append all HashData objects to the
+ // value array.
+ for (uint32_t i=0; i<count; ++i)
+ {
+ DIEInfo die_info;
+ if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
+ {
+ // Only happened if the HashData of the string matched...
+ if (match)
+ pair.value.push_back (die_info);
+ }
+ else
+ {
+ // Something went wrong while reading the data
+ *hash_data_offset_ptr = UINT32_MAX;
+ return eResultError;
+ }
+ }
+ }
+ // Return the correct response depending on if the string matched
+ // or not...
+ if (match)
+ return eResultKeyMatch; // The key (cstring) matches and we have lookup results!
+ else
+ return eResultKeyMismatch; // The key doesn't match, this function will get called
+ // again for the next key/value or the key terminator
+ // which in our case is a zero .debug_str offset.
+ }
+ else
+ {
+ *hash_data_offset_ptr = UINT32_MAX;
+ return eResultError;
+ }
+}
+
+size_t
+DWARFMappedHash::MemoryTable::AppendAllDIEsThatMatchingRegex (
+ const lldb_private::RegularExpression& regex,
+ DIEInfoArray &die_info_array) const
+{
+ const uint32_t hash_count = m_header.hashes_count;
+ Pair pair;
+ for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
+ {
+ lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx);
+ while (hash_data_offset != UINT32_MAX)
+ {
+ const lldb::offset_t prev_hash_data_offset = hash_data_offset;
+ Result hash_result = AppendHashDataForRegularExpression (regex, &hash_data_offset, pair);
+ if (prev_hash_data_offset == hash_data_offset)
+ break;
+
+ // Check the result of getting our hash data
+ switch (hash_result)
+ {
+ case eResultKeyMatch:
+ case eResultKeyMismatch:
+ // Whether we matches or not, it doesn't matter, we
+ // keep looking.
+ break;
+
+ case eResultEndOfHashData:
+ case eResultError:
+ hash_data_offset = UINT32_MAX;
+ break;
+ }
+ }
+ }
+ die_info_array.swap (pair.value);
+ return die_info_array.size();
+}
+
+size_t
+DWARFMappedHash::MemoryTable::AppendAllDIEsInRange (const uint32_t die_offset_start,
+ const uint32_t die_offset_end,
+ DIEInfoArray &die_info_array) const
+{
+ const uint32_t hash_count = m_header.hashes_count;
+ for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
+ {
+ bool done = false;
+ lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx);
+ while (!done && hash_data_offset != UINT32_MAX)
+ {
+ KeyType key = m_data.GetU32 (&hash_data_offset);
+ // If the key is zero, this terminates our chain of HashData objects
+ // for this hash value.
+ if (key == 0)
+ break;
+
+ const uint32_t count = m_data.GetU32 (&hash_data_offset);
+ for (uint32_t i=0; i<count; ++i)
+ {
+ DIEInfo die_info;
+ if (m_header.Read(m_data, &hash_data_offset, die_info))
+ {
+ if (die_info.offset == 0)
+ done = true;
+ if (die_offset_start <= die_info.offset && die_info.offset < die_offset_end)
+ die_info_array.push_back(die_info);
+ }
+ }
+ }
+ }
+ return die_info_array.size();
+}
+
+size_t
+DWARFMappedHash::MemoryTable::FindByName (const char *name, DIEArray &die_offsets)
+{
+ DIEInfoArray die_info_array;
+ if (FindByName(name, die_info_array))
+ DWARFMappedHash::ExtractDIEArray (die_info_array, die_offsets);
+ return die_info_array.size();
+}
+
+size_t
+DWARFMappedHash::MemoryTable::FindByNameAndTag (const char *name,
+ const dw_tag_t tag,
+ DIEArray &die_offsets)
+{
+ DIEInfoArray die_info_array;
+ if (FindByName(name, die_info_array))
+ DWARFMappedHash::ExtractDIEArray (die_info_array, tag, die_offsets);
+ return die_info_array.size();
+}
+
+size_t
+DWARFMappedHash::MemoryTable::FindByNameAndTagAndQualifiedNameHash (const char *name,
+ const dw_tag_t tag,
+ const uint32_t qualified_name_hash,
+ DIEArray &die_offsets)
+{
+ DIEInfoArray die_info_array;
+ if (FindByName(name, die_info_array))
+ DWARFMappedHash::ExtractDIEArray (die_info_array, tag, qualified_name_hash, die_offsets);
+ return die_info_array.size();
+}
+
+size_t
+DWARFMappedHash::MemoryTable::FindCompleteObjCClassByName (const char *name,
+ DIEArray &die_offsets,
+ bool must_be_implementation)
+{
+ DIEInfoArray die_info_array;
+ if (FindByName(name, die_info_array))
+ {
+ if (must_be_implementation && GetHeader().header_data.ContainsAtom (eAtomTypeTypeFlags))
+ {
+ // If we have two atoms, then we have the DIE offset and
+ // the type flags so we can find the objective C class
+ // efficiently.
+ DWARFMappedHash::ExtractTypesFromDIEArray (die_info_array,
+ UINT32_MAX,
+ eTypeFlagClassIsImplementation,
+ die_offsets);
+ }
+ else
+ {
+ // We don't only want the one true definition, so try and see
+ // what we can find, and only return class or struct DIEs.
+ // If we do have the full implementation, then return it alone,
+ // else return all possible matches.
+ const bool return_implementation_only_if_available = true;
+ DWARFMappedHash::ExtractClassOrStructDIEArray (die_info_array,
+ return_implementation_only_if_available,
+ die_offsets);
+ }
+ }
+ return die_offsets.size();
+}
+
+size_t
+DWARFMappedHash::MemoryTable::FindByName (const char *name, DIEInfoArray &die_info_array)
+{
+ Pair kv_pair;
+ size_t old_size = die_info_array.size();
+ if (Find (name, kv_pair))
+ {
+ die_info_array.swap(kv_pair.value);
+ return die_info_array.size() - old_size;
+ }
+ return 0;
+}
diff --git a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
index f8a8cc60467d..bcde558ae449 100644
--- a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
+++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
@@ -12,139 +12,36 @@
#include <vector>
-#include "DWARFDefines.h"
-#include "DWARFFormValue.h"
-
#include "lldb/lldb-defines.h"
#include "lldb/Core/dwarf.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/MappedHash.h"
+#include "DWARFDefines.h"
+#include "DWARFFormValue.h"
+#include "NameToDIE.h"
class SymbolFileDWARF;
class DWARFCompileUnit;
class DWARFDebugInfoEntry;
-struct DWARFMappedHash
+class DWARFMappedHash
{
- struct DIEInfo
- {
- dw_offset_t offset; // The DIE offset
- dw_tag_t tag;
- uint32_t type_flags; // Any flags for this DIEInfo
- uint32_t qualified_name_hash; // A 32 bit hash of the fully qualified name
-
- DIEInfo () :
- offset (DW_INVALID_OFFSET),
- tag (0),
- type_flags (0),
- qualified_name_hash (0)
- {
- }
-
- DIEInfo (dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h) :
- offset(o),
- tag (t),
- type_flags (f),
- qualified_name_hash (h)
- {
- }
-
- void
- Clear()
- {
- offset = DW_INVALID_OFFSET;
- tag = 0;
- type_flags = 0;
- qualified_name_hash = 0;
- }
- };
-
- typedef std::vector<DIEInfo> DIEInfoArray;
- typedef std::vector<uint32_t> DIEArray;
-
- static void
- ExtractDIEArray (const DIEInfoArray &die_info_array,
- DIEArray &die_offsets)
- {
- const size_t count = die_info_array.size();
- for (size_t i=0; i<count; ++i)
- {
- die_offsets.push_back (die_info_array[i].offset);
- }
- }
-
- static void
- ExtractDIEArray (const DIEInfoArray &die_info_array,
- const dw_tag_t tag,
- DIEArray &die_offsets)
- {
- if (tag == 0)
- {
- ExtractDIEArray (die_info_array, die_offsets);
- }
- else
- {
- const size_t count = die_info_array.size();
- for (size_t i=0; i<count; ++i)
- {
- const dw_tag_t die_tag = die_info_array[i].tag;
- bool tag_matches = die_tag == 0 || tag == die_tag;
- if (!tag_matches)
- {
- if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
- tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
- }
- if (tag_matches)
- die_offsets.push_back (die_info_array[i].offset);
- }
- }
- }
-
- static void
- ExtractDIEArray (const DIEInfoArray &die_info_array,
- const dw_tag_t tag,
- const uint32_t qualified_name_hash,
- DIEArray &die_offsets)
- {
- if (tag == 0)
- {
- ExtractDIEArray (die_info_array, die_offsets);
- }
- else
- {
- const size_t count = die_info_array.size();
- for (size_t i=0; i<count; ++i)
- {
- if (qualified_name_hash != die_info_array[i].qualified_name_hash)
- continue;
- const dw_tag_t die_tag = die_info_array[i].tag;
- bool tag_matches = die_tag == 0 || tag == die_tag;
- if (!tag_matches)
- {
- if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
- tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
- }
- if (tag_matches)
- die_offsets.push_back (die_info_array[i].offset);
- }
- }
- }
-
- enum AtomType
+public:
+ enum AtomType : uint16_t
{
- eAtomTypeNULL = 0u,
- eAtomTypeDIEOffset = 1u, // DIE offset, check form for encoding
- eAtomTypeCUOffset = 2u, // DIE offset of the compiler unit header that contains the item in question
- eAtomTypeTag = 3u, // DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed 255) or DW_FORM_data2
- eAtomTypeNameFlags = 4u, // Flags from enum NameFlags
- eAtomTypeTypeFlags = 5u, // Flags from enum TypeFlags,
+ eAtomTypeNULL = 0u,
+ eAtomTypeDIEOffset = 1u, // DIE offset, check form for encoding
+ eAtomTypeCUOffset = 2u, // DIE offset of the compiler unit header that contains the item in question
+ eAtomTypeTag = 3u, // DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed 255) or DW_FORM_data2
+ eAtomTypeNameFlags = 4u, // Flags from enum NameFlags
+ eAtomTypeTypeFlags = 5u, // Flags from enum TypeFlags,
eAtomTypeQualNameHash = 6u // A 32 bit hash of the full qualified name (since all hash entries are basename only)
// For example a type like "std::vector<int>::iterator" would have a name of "iterator"
// and a 32 bit hash for "std::vector<int>::iterator" to allow us to not have to pull
// in debug info for a type when we know the fully qualified name.
};
-
+
// Bit definitions for the eAtomTypeTypeFlags flags
enum TypeFlags
{
@@ -152,782 +49,171 @@ struct DWARFMappedHash
// @implementation for class
eTypeFlagClassIsImplementation = ( 1u << 1 )
};
-
- static void
- ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array,
- bool return_implementation_only_if_available,
- DIEArray &die_offsets)
+ struct DIEInfo
{
- const size_t count = die_info_array.size();
- for (size_t i=0; i<count; ++i)
- {
- const dw_tag_t die_tag = die_info_array[i].tag;
- if (die_tag == 0 || die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
- {
- if (die_info_array[i].type_flags & eTypeFlagClassIsImplementation)
- {
- if (return_implementation_only_if_available)
- {
- // We found the one true definition for this class, so
- // only return that
- die_offsets.clear();
- die_offsets.push_back (die_info_array[i].offset);
- return;
- }
- else
- {
- // Put the one true definition as the first entry so it
- // matches first
- die_offsets.insert (die_offsets.begin(), die_info_array[i].offset);
- }
- }
- else
- {
- die_offsets.push_back (die_info_array[i].offset);
- }
- }
- }
- }
+ dw_offset_t cu_offset;
+ dw_offset_t offset; // The DIE offset
+ dw_tag_t tag;
+ uint32_t type_flags; // Any flags for this DIEInfo
+ uint32_t qualified_name_hash; // A 32 bit hash of the fully qualified name
- static void
- ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array,
- uint32_t type_flag_mask,
- uint32_t type_flag_value,
- DIEArray &die_offsets)
- {
- const size_t count = die_info_array.size();
- for (size_t i=0; i<count; ++i)
- {
- if ((die_info_array[i].type_flags & type_flag_mask) == type_flag_value)
- die_offsets.push_back (die_info_array[i].offset);
- }
- }
+ DIEInfo ();
+ DIEInfo (dw_offset_t c, dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h);
+ };
struct Atom
{
- uint16_t type;
+ AtomType type;
dw_form_t form;
-
- Atom (uint16_t t = eAtomTypeNULL, dw_form_t f = 0) :
- type (t),
- form (f)
- {
- }
};
-
+
+ typedef std::vector<DIEInfo> DIEInfoArray;
typedef std::vector<Atom> AtomArray;
-
- static uint32_t
- GetTypeFlags (SymbolFileDWARF *dwarf2Data,
- const DWARFCompileUnit* cu,
- const DWARFDebugInfoEntry* die);
-
- static const char *
- GetAtomTypeName (uint16_t atom)
- {
- switch (atom)
- {
- case eAtomTypeNULL: return "NULL";
- case eAtomTypeDIEOffset: return "die-offset";
- case eAtomTypeCUOffset: return "cu-offset";
- case eAtomTypeTag: return "die-tag";
- case eAtomTypeNameFlags: return "name-flags";
- case eAtomTypeTypeFlags: return "type-flags";
- case eAtomTypeQualNameHash: return "qualified-name-hash";
- }
- return "<invalid>";
- }
- struct Prologue
+ class Prologue
{
- // DIE offset base so die offsets in hash_data can be CU relative
- dw_offset_t die_base_offset;
- AtomArray atoms;
- uint32_t atom_mask;
- size_t min_hash_data_byte_size;
- bool hash_data_has_fixed_byte_size;
-
- Prologue (dw_offset_t _die_base_offset = 0) :
- die_base_offset (_die_base_offset),
- atoms(),
- atom_mask (0),
- min_hash_data_byte_size(0),
- hash_data_has_fixed_byte_size(true)
- {
- // Define an array of DIE offsets by first defining an array,
- // and then define the atom type for the array, in this case
- // we have an array of DIE offsets
- AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4);
- }
-
- virtual ~Prologue()
- {
- }
+ public:
+ Prologue (dw_offset_t _die_base_offset = 0);
void
- ClearAtoms ()
- {
- hash_data_has_fixed_byte_size = true;
- min_hash_data_byte_size = 0;
- atom_mask = 0;
- atoms.clear();
- }
+ ClearAtoms ();
bool
- ContainsAtom (AtomType atom_type) const
- {
- return (atom_mask & (1u << atom_type)) != 0;
- }
-
- virtual void
- Clear ()
- {
- die_base_offset = 0;
- ClearAtoms ();
- }
-
+ ContainsAtom (AtomType atom_type) const;
+
void
- AppendAtom (AtomType type, dw_form_t form)
- {
- atoms.push_back (Atom(type, form));
- atom_mask |= 1u << type;
- switch (form)
- {
- case DW_FORM_indirect:
- case DW_FORM_exprloc:
- case DW_FORM_flag_present:
- case DW_FORM_ref_sig8:
- assert (!"Unhandled atom form");
- break;
-
- case DW_FORM_string:
- case DW_FORM_block:
- case DW_FORM_block1:
- case DW_FORM_sdata:
- case DW_FORM_udata:
- case DW_FORM_ref_udata:
- hash_data_has_fixed_byte_size = false;
- // Fall through to the cases below...
- case DW_FORM_flag:
- case DW_FORM_data1:
- case DW_FORM_ref1:
- case DW_FORM_sec_offset:
- min_hash_data_byte_size += 1;
- break;
-
- case DW_FORM_block2:
- hash_data_has_fixed_byte_size = false;
- // Fall through to the cases below...
- case DW_FORM_data2:
- case DW_FORM_ref2:
- min_hash_data_byte_size += 2;
- break;
-
- case DW_FORM_block4:
- hash_data_has_fixed_byte_size = false;
- // Fall through to the cases below...
- case DW_FORM_data4:
- case DW_FORM_ref4:
- case DW_FORM_addr:
- case DW_FORM_ref_addr:
- case DW_FORM_strp:
- min_hash_data_byte_size += 4;
- break;
-
- case DW_FORM_data8:
- case DW_FORM_ref8:
- min_hash_data_byte_size += 8;
- break;
-
- }
- }
-
-// void
-// Dump (std::ostream* ostrm_ptr);
-
+ Clear ();
+
+ void
+ AppendAtom (AtomType type, dw_form_t form);
+
lldb::offset_t
- Read (const lldb_private::DataExtractor &data,
- lldb::offset_t offset)
- {
- ClearAtoms ();
-
- die_base_offset = data.GetU32 (&offset);
-
- const uint32_t atom_count = data.GetU32 (&offset);
- if (atom_count == 0x00060003u)
- {
- // Old format, deal with contents of old pre-release format
- while (data.GetU32(&offset))
- /* do nothing */;
-
- // Hardcode to the only known value for now.
- AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4);
- }
- else
- {
- for (uint32_t i=0; i<atom_count; ++i)
- {
- AtomType type = (AtomType)data.GetU16 (&offset);
- dw_form_t form = (dw_form_t)data.GetU16 (&offset);
- AppendAtom (type, form);
- }
- }
- return offset;
- }
-
-// virtual void
-// Write (BinaryStreamBuf &s);
-
+ Read (const lldb_private::DataExtractor &data, lldb::offset_t offset);
+
size_t
- GetByteSize () const
- {
- // Add an extra count to the atoms size for the zero termination Atom that gets
- // written to disk
- return sizeof(die_base_offset) + sizeof(uint32_t) + atoms.size() * sizeof(Atom);
- }
-
+ GetByteSize () const;
+
size_t
- GetMinimumHashDataByteSize () const
- {
- return min_hash_data_byte_size;
- }
+ GetMinimumHashDataByteSize () const;
bool
- HashDataHasFixedByteSize() const
- {
- return hash_data_has_fixed_byte_size;
- }
+ HashDataHasFixedByteSize() const;
+
+ // DIE offset base so die offsets in hash_data can be CU relative
+ dw_offset_t die_base_offset;
+ AtomArray atoms;
+ uint32_t atom_mask;
+ size_t min_hash_data_byte_size;
+ bool hash_data_has_fixed_byte_size;
};
- struct Header : public MappedHash::Header<Prologue>
+ class Header : public MappedHash::Header<Prologue>
{
- Header (dw_offset_t _die_base_offset = 0)
- {
- }
-
- virtual
- ~Header()
- {
- }
-
- virtual size_t
- GetByteSize (const HeaderData &header_data)
- {
- return header_data.GetByteSize();
- }
-
- // virtual void
- // Dump (std::ostream* ostrm_ptr);
- //
- virtual lldb::offset_t
- Read (lldb_private::DataExtractor &data, lldb::offset_t offset)
- {
- offset = MappedHash::Header<Prologue>::Read (data, offset);
- if (offset != UINT32_MAX)
- {
- offset = header_data.Read (data, offset);
- }
- return offset;
- }
-
+ public:
+ size_t
+ GetByteSize (const HeaderData &header_data) override;
+
+ lldb::offset_t
+ Read (lldb_private::DataExtractor &data, lldb::offset_t offset) override;
+
bool
Read (const lldb_private::DWARFDataExtractor &data,
lldb::offset_t *offset_ptr,
- DIEInfo &hash_data) const
- {
- const size_t num_atoms = header_data.atoms.size();
- if (num_atoms == 0)
- return false;
-
- for (size_t i=0; i<num_atoms; ++i)
- {
- DWARFFormValue form_value (NULL, header_data.atoms[i].form);
-
- if (!form_value.ExtractValue(data, offset_ptr))
- return false;
-
- switch (header_data.atoms[i].type)
- {
- case eAtomTypeDIEOffset: // DIE offset, check form for encoding
- hash_data.offset = (dw_offset_t)form_value.Reference (header_data.die_base_offset);
- break;
-
- case eAtomTypeTag: // DW_TAG value for the DIE
- hash_data.tag = (dw_tag_t)form_value.Unsigned ();
-
- case eAtomTypeTypeFlags: // Flags from enum TypeFlags
- hash_data.type_flags = (uint32_t)form_value.Unsigned ();
- break;
-
- case eAtomTypeQualNameHash: // Flags from enum TypeFlags
- hash_data.qualified_name_hash = form_value.Unsigned ();
- break;
-
- default:
- // We can always skip atoms we don't know about
- break;
- }
- }
- return true;
- }
-
+ DIEInfo &hash_data) const;
+
void
- Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const
- {
- const size_t num_atoms = header_data.atoms.size();
- for (size_t i=0; i<num_atoms; ++i)
- {
- if (i > 0)
- strm.PutCString (", ");
-
- DWARFFormValue form_value (NULL, header_data.atoms[i].form);
- switch (header_data.atoms[i].type)
- {
- case eAtomTypeDIEOffset: // DIE offset, check form for encoding
- strm.Printf ("{0x%8.8x}", hash_data.offset);
- break;
-
- case eAtomTypeTag: // DW_TAG value for the DIE
- {
- const char *tag_cstr = lldb_private::DW_TAG_value_to_name (hash_data.tag);
- if (tag_cstr)
- strm.PutCString (tag_cstr);
- else
- strm.Printf ("DW_TAG_(0x%4.4x)", hash_data.tag);
- }
- break;
-
- case eAtomTypeTypeFlags: // Flags from enum TypeFlags
- strm.Printf ("0x%2.2x", hash_data.type_flags);
- if (hash_data.type_flags)
- {
- strm.PutCString (" (");
- if (hash_data.type_flags & eTypeFlagClassIsImplementation)
- strm.PutCString (" implementation");
- strm.PutCString (" )");
- }
- break;
-
- case eAtomTypeQualNameHash: // Flags from enum TypeFlags
- strm.Printf ("0x%8.8x", hash_data.qualified_name_hash);
- break;
-
- default:
- strm.Printf ("AtomType(0x%x)", header_data.atoms[i].type);
- break;
- }
- }
- }
+ Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const;
};
-
-// class ExportTable
-// {
-// public:
-// ExportTable ();
-//
-// void
-// AppendNames (DWARFDebugPubnamesSet &pubnames_set,
-// StringTable &string_table);
-//
-// void
-// AppendNamesEntry (SymbolFileDWARF *dwarf2Data,
-// const DWARFCompileUnit* cu,
-// const DWARFDebugInfoEntry* die,
-// StringTable &string_table);
-//
-// void
-// AppendTypesEntry (DWARFData *dwarf2Data,
-// const DWARFCompileUnit* cu,
-// const DWARFDebugInfoEntry* die,
-// StringTable &string_table);
-//
-// size_t
-// Save (BinaryStreamBuf &names_data, const StringTable &string_table);
-//
-// void
-// AppendName (const char *name,
-// uint32_t die_offset,
-// StringTable &string_table,
-// dw_offset_t name_debug_str_offset = DW_INVALID_OFFSET); // If "name" has already been looked up, then it can be supplied
-// void
-// AppendType (const char *name,
-// uint32_t die_offset,
-// StringTable &string_table);
-//
-//
-// protected:
-// struct Entry
-// {
-// uint32_t hash;
-// uint32_t str_offset;
-// uint32_t die_offset;
-// };
-//
-// // Map uniqued .debug_str offset to the corresponding DIE offsets
-// typedef std::map<uint32_t, DIEInfoArray> NameInfo;
-// // Map a name hash to one or more name infos
-// typedef std::map<uint32_t, NameInfo> BucketEntry;
-//
-// static uint32_t
-// GetByteSize (const NameInfo &name_info);
-//
-// typedef std::vector<BucketEntry> BucketEntryColl;
-// typedef std::vector<Entry> EntryColl;
-// EntryColl m_entries;
-//
-// };
-
-
+
// A class for reading and using a saved hash table from a block of data
// in memory
class MemoryTable : public MappedHash::MemoryTable<uint32_t, DWARFMappedHash::Header, DIEInfoArray>
{
public:
-
MemoryTable (lldb_private::DWARFDataExtractor &table_data,
const lldb_private::DWARFDataExtractor &string_table,
- const char *name) :
- MappedHash::MemoryTable<uint32_t, Header, DIEInfoArray> (table_data),
- m_data (table_data),
- m_string_table (string_table),
- m_name (name)
- {
- }
-
- virtual
- ~MemoryTable ()
- {
- }
-
- virtual const char *
- GetStringForKeyType (KeyType key) const
- {
- // The key in the DWARF table is the .debug_str offset for the string
- return m_string_table.PeekCStr (key);
- }
+ const char *name);
+
+ const char *
+ GetStringForKeyType (KeyType key) const override;
- virtual bool
- ReadHashData (uint32_t hash_data_offset,
- HashData &hash_data) const
- {
- lldb::offset_t offset = hash_data_offset;
- offset += 4; // Skip string table offset that contains offset of hash name in .debug_str
- const uint32_t count = m_data.GetU32 (&offset);
- if (count > 0)
- {
- hash_data.resize(count);
- for (uint32_t i=0; i<count; ++i)
- {
- if (!m_header.Read(m_data, &offset, hash_data[i]))
- return false;
- }
- }
- else
- hash_data.clear();
- return true;
- }
-
- virtual Result
- GetHashDataForName (const char *name,
- lldb::offset_t* hash_data_offset_ptr,
- Pair &pair) const
- {
- pair.key = m_data.GetU32 (hash_data_offset_ptr);
- pair.value.clear();
-
- // If the key is zero, this terminates our chain of HashData objects
- // for this hash value.
- if (pair.key == 0)
- return eResultEndOfHashData;
-
- // There definitely should be a string for this string offset, if
- // there isn't, there is something wrong, return and error
- const char *strp_cstr = m_string_table.PeekCStr (pair.key);
- if (strp_cstr == NULL)
- {
- *hash_data_offset_ptr = UINT32_MAX;
- return eResultError;
- }
-
- const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
- const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize();
- if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
- {
- // We have at least one HashData entry, and we have enough
- // data to parse at least "count" HashData entries.
-
- // First make sure the entire C string matches...
- const bool match = strcmp (name, strp_cstr) == 0;
-
- if (!match && m_header.header_data.HashDataHasFixedByteSize())
- {
- // If the string doesn't match and we have fixed size data,
- // we can just add the total byte size of all HashData objects
- // to the hash data offset and be done...
- *hash_data_offset_ptr += min_total_hash_data_size;
- }
- else
- {
- // If the string does match, or we don't have fixed size data
- // then we need to read the hash data as a stream. If the
- // string matches we also append all HashData objects to the
- // value array.
- for (uint32_t i=0; i<count; ++i)
- {
- DIEInfo die_info;
- if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
- {
- // Only happened if the HashData of the string matched...
- if (match)
- pair.value.push_back (die_info);
- }
- else
- {
- // Something went wrong while reading the data
- *hash_data_offset_ptr = UINT32_MAX;
- return eResultError;
- }
- }
- }
- // Return the correct response depending on if the string matched
- // or not...
- if (match)
- return eResultKeyMatch; // The key (cstring) matches and we have lookup results!
- else
- return eResultKeyMismatch; // The key doesn't match, this function will get called
- // again for the next key/value or the key terminator
- // which in our case is a zero .debug_str offset.
- }
- else
- {
- *hash_data_offset_ptr = UINT32_MAX;
- return eResultError;
- }
- }
-
- virtual Result
- AppendHashDataForRegularExpression (const lldb_private::RegularExpression& regex,
- lldb::offset_t* hash_data_offset_ptr,
- Pair &pair) const
- {
- pair.key = m_data.GetU32 (hash_data_offset_ptr);
- // If the key is zero, this terminates our chain of HashData objects
- // for this hash value.
- if (pair.key == 0)
- return eResultEndOfHashData;
-
- // There definitely should be a string for this string offset, if
- // there isn't, there is something wrong, return and error
- const char *strp_cstr = m_string_table.PeekCStr (pair.key);
- if (strp_cstr == NULL)
- return eResultError;
-
- const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
- const size_t min_total_hash_data_size = count * m_header.header_data.GetMinimumHashDataByteSize();
- if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
- {
- const bool match = regex.Execute(strp_cstr);
-
- if (!match && m_header.header_data.HashDataHasFixedByteSize())
- {
- // If the regex doesn't match and we have fixed size data,
- // we can just add the total byte size of all HashData objects
- // to the hash data offset and be done...
- *hash_data_offset_ptr += min_total_hash_data_size;
- }
- else
- {
- // If the string does match, or we don't have fixed size data
- // then we need to read the hash data as a stream. If the
- // string matches we also append all HashData objects to the
- // value array.
- for (uint32_t i=0; i<count; ++i)
- {
- DIEInfo die_info;
- if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
- {
- // Only happened if the HashData of the string matched...
- if (match)
- pair.value.push_back (die_info);
- }
- else
- {
- // Something went wrong while reading the data
- *hash_data_offset_ptr = UINT32_MAX;
- return eResultError;
- }
- }
- }
- // Return the correct response depending on if the string matched
- // or not...
- if (match)
- return eResultKeyMatch; // The key (cstring) matches and we have lookup results!
- else
- return eResultKeyMismatch; // The key doesn't match, this function will get called
- // again for the next key/value or the key terminator
- // which in our case is a zero .debug_str offset.
- }
- else
- {
- *hash_data_offset_ptr = UINT32_MAX;
- return eResultError;
- }
- }
+ bool
+ ReadHashData (uint32_t hash_data_offset, HashData &hash_data) const override;
size_t
AppendAllDIEsThatMatchingRegex (const lldb_private::RegularExpression& regex,
- DIEInfoArray &die_info_array) const
- {
- const uint32_t hash_count = m_header.hashes_count;
- Pair pair;
- for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
- {
- lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx);
- while (hash_data_offset != UINT32_MAX)
- {
- const lldb::offset_t prev_hash_data_offset = hash_data_offset;
- Result hash_result = AppendHashDataForRegularExpression (regex, &hash_data_offset, pair);
- if (prev_hash_data_offset == hash_data_offset)
- break;
-
- // Check the result of getting our hash data
- switch (hash_result)
- {
- case eResultKeyMatch:
- case eResultKeyMismatch:
- // Whether we matches or not, it doesn't matter, we
- // keep looking.
- break;
-
- case eResultEndOfHashData:
- case eResultError:
- hash_data_offset = UINT32_MAX;
- break;
- }
- }
- }
- die_info_array.swap (pair.value);
- return die_info_array.size();
- }
-
+ DIEInfoArray &die_info_array) const;
+
size_t
AppendAllDIEsInRange (const uint32_t die_offset_start,
const uint32_t die_offset_end,
- DIEInfoArray &die_info_array) const
- {
- const uint32_t hash_count = m_header.hashes_count;
- for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
- {
- bool done = false;
- lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx);
- while (!done && hash_data_offset != UINT32_MAX)
- {
- KeyType key = m_data.GetU32 (&hash_data_offset);
- // If the key is zero, this terminates our chain of HashData objects
- // for this hash value.
- if (key == 0)
- break;
-
- const uint32_t count = m_data.GetU32 (&hash_data_offset);
- for (uint32_t i=0; i<count; ++i)
- {
- DIEInfo die_info;
- if (m_header.Read(m_data, &hash_data_offset, die_info))
- {
- if (die_info.offset == 0)
- done = true;
- if (die_offset_start <= die_info.offset && die_info.offset < die_offset_end)
- die_info_array.push_back(die_info);
- }
- }
- }
- }
- return die_info_array.size();
- }
+ DIEInfoArray &die_info_array) const;
size_t
- FindByName (const char *name, DIEArray &die_offsets)
- {
- DIEInfoArray die_info_array;
- if (FindByName(name, die_info_array))
- DWARFMappedHash::ExtractDIEArray (die_info_array, die_offsets);
- return die_info_array.size();
- }
+ FindByName (const char *name, DIEArray &die_offsets);
size_t
- FindByNameAndTag (const char *name,
- const dw_tag_t tag,
- DIEArray &die_offsets)
- {
- DIEInfoArray die_info_array;
- if (FindByName(name, die_info_array))
- DWARFMappedHash::ExtractDIEArray (die_info_array, tag, die_offsets);
- return die_info_array.size();
- }
+ FindByNameAndTag (const char *name, const dw_tag_t tag, DIEArray &die_offsets);
size_t
FindByNameAndTagAndQualifiedNameHash (const char *name,
const dw_tag_t tag,
const uint32_t qualified_name_hash,
- DIEArray &die_offsets)
- {
- DIEInfoArray die_info_array;
- if (FindByName(name, die_info_array))
- DWARFMappedHash::ExtractDIEArray (die_info_array, tag, qualified_name_hash, die_offsets);
- return die_info_array.size();
- }
+ DIEArray &die_offsets);
size_t
- FindCompleteObjCClassByName (const char *name, DIEArray &die_offsets, bool must_be_implementation)
- {
- DIEInfoArray die_info_array;
- if (FindByName(name, die_info_array))
- {
- if (must_be_implementation && GetHeader().header_data.ContainsAtom (eAtomTypeTypeFlags))
- {
- // If we have two atoms, then we have the DIE offset and
- // the type flags so we can find the objective C class
- // efficiently.
- DWARFMappedHash::ExtractTypesFromDIEArray (die_info_array,
- UINT32_MAX,
- eTypeFlagClassIsImplementation,
- die_offsets);
- }
- else
- {
- // We don't only want the one true definition, so try and see
- // what we can find, and only return class or struct DIEs.
- // If we do have the full implementation, then return it alone,
- // else return all possible matches.
- const bool return_implementation_only_if_available = true;
- DWARFMappedHash::ExtractClassOrStructDIEArray (die_info_array,
- return_implementation_only_if_available,
- die_offsets);
- }
- }
- return die_offsets.size();
- }
+ FindCompleteObjCClassByName (const char *name,
+ DIEArray &die_offsets,
+ bool must_be_implementation);
- size_t
- FindByName (const char *name, DIEInfoArray &die_info_array)
- {
- Pair kv_pair;
- size_t old_size = die_info_array.size();
- if (Find (name, kv_pair))
- {
- die_info_array.swap(kv_pair.value);
- return die_info_array.size() - old_size;
- }
- return 0;
- }
-
protected:
+ Result
+ AppendHashDataForRegularExpression (const lldb_private::RegularExpression& regex,
+ lldb::offset_t* hash_data_offset_ptr,
+ Pair &pair) const;
+
+ size_t
+ FindByName (const char *name, DIEInfoArray &die_info_array);
+
+ Result
+ GetHashDataForName (const char *name,
+ lldb::offset_t* hash_data_offset_ptr,
+ Pair &pair) const override;
+
const lldb_private::DWARFDataExtractor &m_data;
const lldb_private::DWARFDataExtractor &m_string_table;
std::string m_name;
};
-};
+ static void
+ ExtractDIEArray (const DIEInfoArray &die_info_array, DIEArray &die_offsets);
+
+protected:
+ static void
+ ExtractDIEArray (const DIEInfoArray &die_info_array,
+ const dw_tag_t tag,
+ DIEArray &die_offsets);
+
+ static void
+ ExtractDIEArray (const DIEInfoArray &die_info_array,
+ const dw_tag_t tag,
+ const uint32_t qualified_name_hash,
+ DIEArray &die_offsets);
+
+ static void
+ ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array,
+ bool return_implementation_only_if_available,
+ DIEArray &die_offsets);
+
+ static void
+ ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array,
+ uint32_t type_flag_mask,
+ uint32_t type_flag_value,
+ DIEArray &die_offsets);
+
+ static const char *
+ GetAtomTypeName (uint16_t atom);
+};
#endif // SymbolFileDWARF_HashedNameToDIE_h_
diff --git a/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h b/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
index 2091a8414f58..24fa7d148cd3 100644
--- a/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
+++ b/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
@@ -1,4 +1,4 @@
-//===-- LogChannelDWARF.h --------------------------------------*- C++ -*-===//
+//===-- LogChannelDWARF.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,7 +13,6 @@
// C Includes
// C++ Includes
// Other libraries and framework includes
-
// Project includes
#include "lldb/Core/Log.h"
@@ -34,8 +33,7 @@ class LogChannelDWARF : public lldb_private::LogChannel
public:
LogChannelDWARF ();
- virtual
- ~LogChannelDWARF ();
+ ~LogChannelDWARF() override;
static void
Initialize();
@@ -52,26 +50,26 @@ public:
static lldb_private::LogChannel *
CreateInstance ();
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
- virtual void
- Disable (const char** categories, lldb_private::Stream *feedback_strm);
+ void
+ Disable(const char** categories, lldb_private::Stream *feedback_strm) override;
void
Delete ();
- virtual bool
- Enable (lldb::StreamSP &log_stream_sp,
- uint32_t log_options,
- lldb_private::Stream *feedback_strm, // Feedback stream for argument errors etc
- const char **categories); // The categories to enable within this logging stream, if empty, enable default set
+ bool
+ Enable(lldb::StreamSP &log_stream_sp,
+ uint32_t log_options,
+ lldb_private::Stream *feedback_strm, // Feedback stream for argument errors etc
+ const char **categories) override; // The categories to enable within this logging stream, if empty, enable default set
- virtual void
- ListCategories (lldb_private::Stream *strm);
+ void
+ ListCategories(lldb_private::Stream *strm) override;
static lldb_private::Log *
GetLog ();
@@ -86,4 +84,4 @@ public:
LogIf (uint32_t mask, const char *format, ...);
};
-#endif // SymbolFileDWARF_LogChannelDWARF_h_
+#endif // SymbolFileDWARF_LogChannelDWARF_h_
diff --git a/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
index c49237b8fbbc..775bb6718b8a 100644
--- a/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
+++ b/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
@@ -18,6 +18,7 @@
#include "DWARFDebugInfo.h"
#include "DWARFDebugInfoEntry.h"
#include "SymbolFileDWARF.h"
+
using namespace lldb;
using namespace lldb_private;
@@ -29,9 +30,9 @@ NameToDIE::Finalize()
}
void
-NameToDIE::Insert (const ConstString& name, uint32_t die_offset)
+NameToDIE::Insert (const ConstString& name, const DIERef& die_ref)
{
- m_map.Append(name.GetCString(), die_offset);
+ m_map.Append(name.GetCString(), die_ref);
}
size_t
@@ -47,17 +48,15 @@ NameToDIE::Find (const RegularExpression& regex, DIEArray &info_array) const
}
size_t
-NameToDIE::FindAllEntriesForCompileUnit (uint32_t cu_offset,
- uint32_t cu_end_offset,
- DIEArray &info_array) const
+NameToDIE::FindAllEntriesForCompileUnit (dw_offset_t cu_offset, DIEArray &info_array) const
{
const size_t initial_size = info_array.size();
const uint32_t size = m_map.GetSize();
for (uint32_t i=0; i<size; ++i)
{
- const uint32_t die_offset = m_map.GetValueAtIndexUnchecked(i);
- if (cu_offset < die_offset && die_offset < cu_end_offset)
- info_array.push_back (die_offset);
+ const DIERef& die_ref = m_map.GetValueAtIndexUnchecked(i);
+ if (cu_offset == die_ref.cu_offset)
+ info_array.push_back (die_ref);
}
return info_array.size() - initial_size;
}
@@ -69,18 +68,29 @@ NameToDIE::Dump (Stream *s)
for (uint32_t i=0; i<size; ++i)
{
const char *cstr = m_map.GetCStringAtIndex(i);
- s->Printf("%p: {0x%8.8x} \"%s\"\n", (const void *)cstr, m_map.GetValueAtIndexUnchecked(i), cstr);
+ const DIERef& die_ref = m_map.GetValueAtIndexUnchecked(i);
+ s->Printf("%p: {0x%8.8x/0x%8.8x} \"%s\"\n", cstr, die_ref.cu_offset, die_ref.die_offset, cstr);
}
}
void
-NameToDIE::ForEach (std::function <bool(const char *name, uint32_t die_offset)> const &callback) const
+NameToDIE::ForEach (std::function <bool(const char *name, const DIERef& die_ref)> const &callback) const
{
const uint32_t size = m_map.GetSize();
for (uint32_t i=0; i<size; ++i)
{
- if (!callback(m_map.GetCStringAtIndexUnchecked(i),
- m_map.GetValueAtIndexUnchecked (i)))
+ if (!callback(m_map.GetCStringAtIndexUnchecked(i), m_map.GetValueAtIndexUnchecked (i)))
break;
}
}
+
+void
+NameToDIE::Append (const NameToDIE& other)
+{
+ const uint32_t size = other.m_map.GetSize();
+ for (uint32_t i = 0; i < size; ++i)
+ {
+ m_map.Append(other.m_map.GetCStringAtIndexUnchecked (i),
+ other.m_map.GetValueAtIndexUnchecked (i));
+ }
+}
diff --git a/source/Plugins/SymbolFile/DWARF/NameToDIE.h b/source/Plugins/SymbolFile/DWARF/NameToDIE.h
index f9a12736bf9e..7fc66138f51e 100644
--- a/source/Plugins/SymbolFile/DWARF/NameToDIE.h
+++ b/source/Plugins/SymbolFile/DWARF/NameToDIE.h
@@ -10,56 +10,53 @@
#ifndef SymbolFileDWARF_NameToDIE_h_
#define SymbolFileDWARF_NameToDIE_h_
-#include "lldb/Core/UniqueCStringMap.h"
-
#include <functional>
+#include "lldb/Core/dwarf.h"
+#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/lldb-defines.h"
+#include "DIERef.h"
class SymbolFileDWARF;
-typedef std::vector<uint32_t> DIEArray;
-
class NameToDIE
{
public:
- NameToDIE () :
+ NameToDIE () :
m_map()
{
}
-
+
~NameToDIE ()
{
}
-
+
void
Dump (lldb_private::Stream *s);
void
- Insert (const lldb_private::ConstString& name, uint32_t die_offset);
+ Insert (const lldb_private::ConstString& name, const DIERef& die_ref);
+
+ void
+ Append (const NameToDIE& other);
void
Finalize();
size_t
- Find (const lldb_private::ConstString &name,
- DIEArray &info_array) const;
+ Find (const lldb_private::ConstString &name, DIEArray &info_array) const;
size_t
- Find (const lldb_private::RegularExpression& regex,
- DIEArray &info_array) const;
+ Find (const lldb_private::RegularExpression& regex, DIEArray &info_array) const;
size_t
- FindAllEntriesForCompileUnit (uint32_t cu_offset,
- uint32_t cu_end_offset,
- DIEArray &info_array) const;
+ FindAllEntriesForCompileUnit (dw_offset_t cu_offset, DIEArray &info_array) const;
void
- ForEach (std::function <bool(const char *name, uint32_t die_offset)> const &callback) const;
+ ForEach (std::function <bool(const char *name, const DIERef& die_ref)> const &callback) const;
protected:
- lldb_private::UniqueCStringMap<uint32_t> m_map;
-
+ lldb_private::UniqueCStringMap<DIERef> m_map;
};
#endif // SymbolFileDWARF_NameToDIE_h_
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index ea8aedcc2be0..0ed4d05be5c2 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -10,20 +10,6 @@
#include "SymbolFileDWARF.h"
// Other libraries and framework includes
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclGroup.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/DeclTemplate.h"
-#include "clang/Basic/Builtins.h"
-#include "clang/Basic/IdentifierTable.h"
-#include "clang/Basic/LangOptions.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/Specifiers.h"
-#include "clang/Sema/DeclSpec.h"
-
#include "llvm/Support/Casting.h"
#include "lldb/Core/ArchSpec.h"
@@ -39,34 +25,48 @@
#include "lldb/Core/Timer.h"
#include "lldb/Core/Value.h"
-#include "lldb/Expression/ClangModulesDeclVendor.h"
+#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
+#include "lldb/Interpreter/OptionValueFileSpecList.h"
+#include "lldb/Interpreter/OptionValueProperties.h"
+
#include "lldb/Symbol/Block.h"
-#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/CompilerDecl.h"
+#include "lldb/Symbol/CompilerDeclContext.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/DebugMacros.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Symbol/VariableList.h"
+#include "lldb/Symbol/TypeMap.h"
+
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
+#include "Plugins/Language/ObjC/ObjCLanguage.h"
+
+#include "lldb/Target/Language.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
-#include "lldb/Target/CPPLanguageRuntime.h"
+#include "lldb/Utility/TaskPool.h"
+#include "DWARFASTParser.h"
#include "DWARFCompileUnit.h"
#include "DWARFDebugAbbrev.h"
#include "DWARFDebugAranges.h"
#include "DWARFDebugInfo.h"
-#include "DWARFDebugInfoEntry.h"
#include "DWARFDebugLine.h"
+#include "DWARFDebugMacro.h"
#include "DWARFDebugPubnames.h"
#include "DWARFDebugRanges.h"
#include "DWARFDeclContext.h"
#include "DWARFDIECollection.h"
#include "DWARFFormValue.h"
-#include "DWARFLocationList.h"
#include "LogChannelDWARF.h"
+#include "SymbolFileDWARFDwo.h"
#include "SymbolFileDWARFDebugMap.h"
#include <map>
@@ -83,8 +83,6 @@
#define DEBUG_PRINTF(fmt, ...)
#endif
-#define DIE_IS_BEING_PARSED ((lldb_private::Type*)1)
-
using namespace lldb;
using namespace lldb_private;
@@ -105,18 +103,58 @@ using namespace lldb_private;
// return false;
//}
//
-static AccessType
-DW_ACCESS_to_AccessType (uint32_t dwarf_accessibility)
-{
- switch (dwarf_accessibility)
+
+namespace {
+
+ PropertyDefinition
+ g_properties[] =
+ {
+ { "comp-dir-symlink-paths" , OptionValue::eTypeFileSpecList, true, 0 , nullptr, nullptr, "If the DW_AT_comp_dir matches any of these paths the symbolic links will be resolved at DWARF parse time." },
+ { nullptr , OptionValue::eTypeInvalid , false, 0, nullptr, nullptr, nullptr }
+ };
+
+ enum
+ {
+ ePropertySymLinkPaths
+ };
+
+
+ class PluginProperties : public Properties
{
- case DW_ACCESS_public: return eAccessPublic;
- case DW_ACCESS_private: return eAccessPrivate;
- case DW_ACCESS_protected: return eAccessProtected;
- default: break;
+ public:
+ static ConstString
+ GetSettingName()
+ {
+ return SymbolFileDWARF::GetPluginNameStatic();
+ }
+
+ PluginProperties()
+ {
+ m_collection_sp.reset (new OptionValueProperties(GetSettingName()));
+ m_collection_sp->Initialize(g_properties);
+ }
+
+ FileSpecList&
+ GetSymLinkPaths()
+ {
+ OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(nullptr, true, ePropertySymLinkPaths);
+ assert(option_value);
+ return option_value->GetCurrentValue();
+ }
+
+ };
+
+ typedef std::shared_ptr<PluginProperties> SymbolFileDWARFPropertiesSP;
+
+ static const SymbolFileDWARFPropertiesSP&
+ GetGlobalPluginProperties()
+ {
+ static const auto g_settings_sp(std::make_shared<PluginProperties>());
+ return g_settings_sp;
}
- return eAccessNone;
-}
+
+} // anonymous namespace end
+
static const char*
removeHostnameFromPathname(const char* path_from_dwarf)
@@ -125,9 +163,15 @@ removeHostnameFromPathname(const char* path_from_dwarf)
{
return path_from_dwarf;
}
-
+
const char *colon_pos = strchr(path_from_dwarf, ':');
- if (!colon_pos)
+ if (nullptr == colon_pos)
+ {
+ return path_from_dwarf;
+ }
+
+ const char *slash_pos = strchr(path_from_dwarf, '/');
+ if (slash_pos && (slash_pos < colon_pos))
{
return path_from_dwarf;
}
@@ -142,89 +186,42 @@ removeHostnameFromPathname(const char* path_from_dwarf)
{
return path_from_dwarf;
}
-
+
return colon_pos + 1;
}
-#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
-
-class DIEStack
+static const char*
+resolveCompDir(const char* path_from_dwarf)
{
-public:
-
- void Push (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
- {
- m_dies.push_back (DIEInfo(cu, die));
- }
+ if (!path_from_dwarf)
+ return nullptr;
-
- void LogDIEs (Log *log, SymbolFileDWARF *dwarf)
- {
- 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++)
- {
- DWARFCompileUnit *cu = m_dies[i].cu;
- const DWARFDebugInfoEntry *die = m_dies[i].die;
- std::string qualified_name;
- die->GetQualifiedName(dwarf, cu, qualified_name);
- log_strm.Printf ("[%" PRIu64 "] 0x%8.8x: %s name='%s'\n",
- (uint64_t)i,
- die->GetOffset(),
- DW_TAG_value_to_name(die->Tag()),
- 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 (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
- {
- m_valid = true;
- m_die_stack.Push (cu, die);
- }
-
- ~ScopedPopper ()
- {
- if (m_valid)
- m_die_stack.Pop();
- }
-
-
-
- protected:
- DIEStack &m_die_stack;
- bool m_valid;
- };
+ // DWARF2/3 suggests the form hostname:pathname for compilation directory.
+ // Remove the host part if present.
+ const char* local_path = removeHostnameFromPathname(path_from_dwarf);
+ if (!local_path)
+ return nullptr;
+
+ bool is_symlink = false;
+ FileSpec local_path_spec(local_path, false);
+ const auto& file_specs = GetGlobalPluginProperties()->GetSymLinkPaths();
+ for (size_t i = 0; i < file_specs.GetSize() && !is_symlink; ++i)
+ is_symlink = FileSpec::Equal(file_specs.GetFileSpecAtIndex(i), local_path_spec, true);
+
+ if (!is_symlink)
+ return local_path;
+
+ if (!local_path_spec.IsSymbolicLink())
+ return local_path;
+
+ FileSpec resolved_local_path_spec;
+ const auto error = FileSystem::Readlink(local_path_spec, resolved_local_path_spec);
+ if (error.Success())
+ return resolved_local_path_spec.GetCString();
+
+ return nullptr;
+}
-protected:
- struct DIEInfo {
- DIEInfo (DWARFCompileUnit *c, const DWARFDebugInfoEntry *d) :
- cu(c),
- die(d)
- {
- }
- DWARFCompileUnit *cu;
- const DWARFDebugInfoEntry *die;
- };
- typedef std::vector<DIEInfo> Stack;
- Stack m_dies;
-};
-#endif
void
SymbolFileDWARF::Initialize()
@@ -232,7 +229,21 @@ SymbolFileDWARF::Initialize()
LogChannelDWARF::Initialize();
PluginManager::RegisterPlugin (GetPluginNameStatic(),
GetPluginDescriptionStatic(),
- CreateInstance);
+ CreateInstance,
+ DebuggerInitialize);
+}
+
+void
+SymbolFileDWARF::DebuggerInitialize(Debugger &debugger)
+{
+ if (!PluginManager::GetSettingForSymbolFilePlugin(debugger, PluginProperties::GetSettingName()))
+ {
+ const bool is_global_setting = true;
+ PluginManager::CreateSettingForSymbolFilePlugin(debugger,
+ GetGlobalPluginProperties()->GetValueProperties(),
+ ConstString ("Properties for the dwarf symbol-file plug-in."),
+ is_global_setting);
+ }
}
void
@@ -272,65 +283,61 @@ SymbolFileDWARF::GetTypeList ()
}
void
-SymbolFileDWARF::GetTypes (DWARFCompileUnit* cu,
- const DWARFDebugInfoEntry *die,
+SymbolFileDWARF::GetTypes (const DWARFDIE &die,
dw_offset_t min_die_offset,
dw_offset_t max_die_offset,
uint32_t type_mask,
TypeSet &type_set)
{
- if (cu)
+ if (die)
{
- if (die)
+ const dw_offset_t die_offset = die.GetOffset();
+
+ if (die_offset >= max_die_offset)
+ return;
+
+ if (die_offset >= min_die_offset)
{
- const dw_offset_t die_offset = die->GetOffset();
-
- if (die_offset >= max_die_offset)
- return;
+ const dw_tag_t tag = die.Tag();
- if (die_offset >= min_die_offset)
- {
- const dw_tag_t tag = die->Tag();
-
- bool add_type = false;
+ bool add_type = false;
- switch (tag)
- {
- case DW_TAG_array_type: add_type = (type_mask & eTypeClassArray ) != 0; break;
- case DW_TAG_unspecified_type:
- case DW_TAG_base_type: add_type = (type_mask & eTypeClassBuiltin ) != 0; break;
- case DW_TAG_class_type: add_type = (type_mask & eTypeClassClass ) != 0; break;
- case DW_TAG_structure_type: add_type = (type_mask & eTypeClassStruct ) != 0; break;
- case DW_TAG_union_type: add_type = (type_mask & eTypeClassUnion ) != 0; break;
- case DW_TAG_enumeration_type: add_type = (type_mask & eTypeClassEnumeration ) != 0; break;
- case DW_TAG_subroutine_type:
- case DW_TAG_subprogram:
- case DW_TAG_inlined_subroutine: add_type = (type_mask & eTypeClassFunction ) != 0; break;
- case DW_TAG_pointer_type: add_type = (type_mask & eTypeClassPointer ) != 0; break;
- case DW_TAG_rvalue_reference_type:
- case DW_TAG_reference_type: add_type = (type_mask & eTypeClassReference ) != 0; break;
- case DW_TAG_typedef: add_type = (type_mask & eTypeClassTypedef ) != 0; break;
- case DW_TAG_ptr_to_member_type: add_type = (type_mask & eTypeClassMemberPointer ) != 0; break;
- }
+ switch (tag)
+ {
+ case DW_TAG_array_type: add_type = (type_mask & eTypeClassArray ) != 0; break;
+ case DW_TAG_unspecified_type:
+ case DW_TAG_base_type: add_type = (type_mask & eTypeClassBuiltin ) != 0; break;
+ case DW_TAG_class_type: add_type = (type_mask & eTypeClassClass ) != 0; break;
+ case DW_TAG_structure_type: add_type = (type_mask & eTypeClassStruct ) != 0; break;
+ case DW_TAG_union_type: add_type = (type_mask & eTypeClassUnion ) != 0; break;
+ case DW_TAG_enumeration_type: add_type = (type_mask & eTypeClassEnumeration ) != 0; break;
+ case DW_TAG_subroutine_type:
+ case DW_TAG_subprogram:
+ case DW_TAG_inlined_subroutine: add_type = (type_mask & eTypeClassFunction ) != 0; break;
+ case DW_TAG_pointer_type: add_type = (type_mask & eTypeClassPointer ) != 0; break;
+ case DW_TAG_rvalue_reference_type:
+ case DW_TAG_reference_type: add_type = (type_mask & eTypeClassReference ) != 0; break;
+ case DW_TAG_typedef: add_type = (type_mask & eTypeClassTypedef ) != 0; break;
+ case DW_TAG_ptr_to_member_type: add_type = (type_mask & eTypeClassMemberPointer ) != 0; break;
+ }
- if (add_type)
+ if (add_type)
+ {
+ const bool assert_not_being_parsed = true;
+ Type *type = ResolveTypeUID (die, assert_not_being_parsed);
+ if (type)
{
- const bool assert_not_being_parsed = true;
- Type *type = ResolveTypeUID (cu, die, assert_not_being_parsed);
- if (type)
- {
- if (type_set.find(type) == type_set.end())
- type_set.insert(type);
- }
+ if (type_set.find(type) == type_set.end())
+ type_set.insert(type);
}
}
-
- for (const DWARFDebugInfoEntry *child_die = die->GetFirstChild();
- child_die != NULL;
- child_die = child_die->GetSibling())
- {
- GetTypes (cu, child_die, min_die_offset, max_die_offset, type_mask, type_set);
- }
+ }
+
+ for (DWARFDIE child_die = die.GetFirstChild();
+ child_die.IsValid();
+ child_die = child_die.GetSibling())
+ {
+ GetTypes (child_die, min_die_offset, max_die_offset, type_mask, type_set);
}
}
}
@@ -353,8 +360,7 @@ SymbolFileDWARF::GetTypes (SymbolContextScope *sc_scope,
dwarf_cu = GetDWARFCompileUnit(comp_unit);
if (dwarf_cu == 0)
return 0;
- GetTypes (dwarf_cu,
- dwarf_cu->DIE(),
+ GetTypes (dwarf_cu->DIE(),
dwarf_cu->GetOffset(),
dwarf_cu->GetNextCompileUnitOffset(),
type_mask,
@@ -371,8 +377,7 @@ SymbolFileDWARF::GetTypes (SymbolContextScope *sc_scope,
dwarf_cu = info->GetCompileUnitAtIndex(cu_idx);
if (dwarf_cu)
{
- GetTypes (dwarf_cu,
- dwarf_cu->DIE(),
+ GetTypes (dwarf_cu->DIE(),
0,
UINT32_MAX,
type_mask,
@@ -381,76 +386,15 @@ SymbolFileDWARF::GetTypes (SymbolContextScope *sc_scope,
}
}
}
-// if (m_using_apple_tables)
-// {
-// DWARFMappedHash::MemoryTable *apple_types = m_apple_types_ap.get();
-// if (apple_types)
-// {
-// apple_types->ForEach([this, &type_set, apple_types, type_mask](const DWARFMappedHash::DIEInfoArray &die_info_array) -> bool {
-//
-// for (auto die_info: die_info_array)
-// {
-// bool add_type = TagMatchesTypeMask (type_mask, 0);
-// if (!add_type)
-// {
-// dw_tag_t tag = die_info.tag;
-// if (tag == 0)
-// {
-// const DWARFDebugInfoEntry *die = DebugInfo()->GetDIEPtr(die_info.offset, NULL);
-// tag = die->Tag();
-// }
-// add_type = TagMatchesTypeMask (type_mask, tag);
-// }
-// if (add_type)
-// {
-// Type *type = ResolveTypeUID(die_info.offset);
-//
-// if (type_set.find(type) == type_set.end())
-// type_set.insert(type);
-// }
-// }
-// return true; // Keep iterating
-// });
-// }
-// }
-// else
-// {
-// if (!m_indexed)
-// Index ();
-//
-// m_type_index.ForEach([this, &type_set, type_mask](const char *name, uint32_t die_offset) -> bool {
-//
-// bool add_type = TagMatchesTypeMask (type_mask, 0);
-//
-// if (!add_type)
-// {
-// const DWARFDebugInfoEntry *die = DebugInfo()->GetDIEPtr(die_offset, NULL);
-// if (die)
-// {
-// const dw_tag_t tag = die->Tag();
-// add_type = TagMatchesTypeMask (type_mask, tag);
-// }
-// }
-//
-// if (add_type)
-// {
-// Type *type = ResolveTypeUID(die_offset);
-//
-// if (type_set.find(type) == type_set.end())
-// type_set.insert(type);
-// }
-// return true; // Keep iterating
-// });
-// }
-
- std::set<ClangASTType> clang_type_set;
+
+ std::set<CompilerType> compiler_type_set;
size_t num_types_added = 0;
for (Type *type : type_set)
{
- ClangASTType clang_type = type->GetClangForwardType();
- if (clang_type_set.find(clang_type) == clang_type_set.end())
+ CompilerType compiler_type = type->GetForwardCompilerType ();
+ if (compiler_type_set.find(compiler_type) == compiler_type_set.end())
{
- clang_type_set.insert(clang_type);
+ compiler_type_set.insert(compiler_type);
type_list.Insert (type->shared_from_this());
++num_types_added;
}
@@ -463,13 +407,13 @@ SymbolFileDWARF::GetTypes (SymbolContextScope *sc_scope,
// Gets the first parent that is a lexical block, function or inlined
// subroutine, or compile unit.
//----------------------------------------------------------------------
-static const DWARFDebugInfoEntry *
-GetParentSymbolContextDIE(const DWARFDebugInfoEntry *child_die)
+DWARFDIE
+SymbolFileDWARF::GetParentSymbolContextDIE(const DWARFDIE &child_die)
{
- const DWARFDebugInfoEntry *die;
- for (die = child_die->GetParent(); die != NULL; die = die->GetParent())
+ DWARFDIE die;
+ for (die = child_die.GetParent(); die; die = die.GetParent())
{
- dw_tag_t tag = die->Tag();
+ dw_tag_t tag = die.Tag();
switch (tag)
{
@@ -480,7 +424,7 @@ GetParentSymbolContextDIE(const DWARFDebugInfoEntry *child_die)
return die;
}
}
- return NULL;
+ return DWARFDIE();
}
@@ -489,13 +433,12 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) :
UserID (0), // Used by SymbolFileDWARFDebugMap to when this class parses .o files to contain the .o file index/ID
m_debug_map_module_wp (),
m_debug_map_symfile (NULL),
- m_clang_tu_decl (NULL),
- m_flags(),
m_data_debug_abbrev (),
m_data_debug_aranges (),
m_data_debug_frame (),
m_data_debug_info (),
m_data_debug_line (),
+ m_data_debug_macro (),
m_data_debug_loc (),
m_data_debug_ranges (),
m_data_debug_str (),
@@ -518,7 +461,6 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) :
m_type_index(),
m_namespace_index(),
m_indexed (false),
- m_is_external_ast_source (false),
m_using_apple_tables (false),
m_fetched_external_modules (false),
m_supports_DW_AT_APPLE_objc_complete_type (eLazyBoolCalculate),
@@ -529,12 +471,6 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) :
SymbolFileDWARF::~SymbolFileDWARF()
{
- if (m_is_external_ast_source)
- {
- ModuleSP module_sp (m_obj_file->GetModule());
- if (module_sp)
- module_sp->GetClangASTContext().RemoveExternalSource ();
- }
}
static const ConstString &
@@ -552,36 +488,31 @@ SymbolFileDWARF::GetUniqueDWARFASTTypeMap ()
return m_unique_ast_type_map;
}
-ClangASTContext &
-SymbolFileDWARF::GetClangASTContext ()
+TypeSystem *
+SymbolFileDWARF::GetTypeSystemForLanguage (LanguageType language)
{
- if (GetDebugMapSymfile ())
- return m_debug_map_symfile->GetClangASTContext ();
-
- ClangASTContext &ast = m_obj_file->GetModule()->GetClangASTContext();
- if (!m_is_external_ast_source)
+ SymbolFileDWARFDebugMap * debug_map_symfile = GetDebugMapSymfile ();
+ TypeSystem *type_system;
+ if (debug_map_symfile)
{
- m_is_external_ast_source = true;
- llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_ap (
- new ClangExternalASTSourceCallbacks (SymbolFileDWARF::CompleteTagDecl,
- SymbolFileDWARF::CompleteObjCInterfaceDecl,
- SymbolFileDWARF::FindExternalVisibleDeclsByName,
- SymbolFileDWARF::LayoutRecordType,
- this));
- ast.SetExternalSource (ast_source_ap);
+ type_system = debug_map_symfile->GetTypeSystemForLanguage(language);
}
- return ast;
+ else
+ {
+ type_system = m_obj_file->GetModule()->GetTypeSystemForLanguage(language);
+ if (type_system)
+ type_system->SetSymbolFile(this);
+ }
+ return type_system;
}
void
SymbolFileDWARF::InitializeObject()
{
- // Install our external AST source callbacks so we can complete Clang types.
ModuleSP module_sp (m_obj_file->GetModule());
if (module_sp)
{
const SectionList *section_list = module_sp->GetSectionList();
-
const Section* section = section_list->FindSectionByName(GetDWARFMachOSegmentName ()).get();
// Memory map the DWARF mach-o segment so we have everything mmap'ed
@@ -589,19 +520,24 @@ SymbolFileDWARF::InitializeObject()
if (section)
m_obj_file->MemoryMapSectionData(section, m_dwarf_data);
}
+
get_apple_names_data();
- if (m_data_apple_names.GetByteSize() > 0)
+ if (m_data_apple_names.m_data.GetByteSize() > 0)
{
- m_apple_names_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_names, get_debug_str_data(), ".apple_names"));
+ m_apple_names_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_names.m_data,
+ get_debug_str_data(),
+ ".apple_names"));
if (m_apple_names_ap->IsValid())
m_using_apple_tables = true;
else
m_apple_names_ap.reset();
}
get_apple_types_data();
- if (m_data_apple_types.GetByteSize() > 0)
+ if (m_data_apple_types.m_data.GetByteSize() > 0)
{
- m_apple_types_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_types, get_debug_str_data(), ".apple_types"));
+ m_apple_types_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_types.m_data,
+ get_debug_str_data(),
+ ".apple_types"));
if (m_apple_types_ap->IsValid())
m_using_apple_tables = true;
else
@@ -609,9 +545,11 @@ SymbolFileDWARF::InitializeObject()
}
get_apple_namespaces_data();
- if (m_data_apple_namespaces.GetByteSize() > 0)
+ if (m_data_apple_namespaces.m_data.GetByteSize() > 0)
{
- m_apple_namespaces_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_namespaces, get_debug_str_data(), ".apple_namespaces"));
+ m_apple_namespaces_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_namespaces.m_data,
+ get_debug_str_data(),
+ ".apple_namespaces"));
if (m_apple_namespaces_ap->IsValid())
m_using_apple_tables = true;
else
@@ -619,9 +557,11 @@ SymbolFileDWARF::InitializeObject()
}
get_apple_objc_data();
- if (m_data_apple_objc.GetByteSize() > 0)
+ if (m_data_apple_objc.m_data.GetByteSize() > 0)
{
- m_apple_objc_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_objc, get_debug_str_data(), ".apple_objc"));
+ m_apple_objc_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_objc.m_data,
+ get_debug_str_data(),
+ ".apple_objc"));
if (m_apple_objc_ap->IsValid())
m_using_apple_tables = true;
else
@@ -663,46 +603,10 @@ SymbolFileDWARF::CalculateAbilities ()
section = section_list->FindSectionByType (eSectionTypeDWARFDebugAbbrev, true).get();
if (section)
debug_abbrev_file_size = section->GetFileSize();
- else
- m_flags.Set (flagsGotDebugAbbrevData);
-
- section = section_list->FindSectionByType (eSectionTypeDWARFDebugAranges, true).get();
- if (!section)
- m_flags.Set (flagsGotDebugArangesData);
-
- section = section_list->FindSectionByType (eSectionTypeDWARFDebugFrame, true).get();
- if (!section)
- m_flags.Set (flagsGotDebugFrameData);
section = section_list->FindSectionByType (eSectionTypeDWARFDebugLine, true).get();
if (section)
debug_line_file_size = section->GetFileSize();
- else
- m_flags.Set (flagsGotDebugLineData);
-
- section = section_list->FindSectionByType (eSectionTypeDWARFDebugLoc, true).get();
- if (!section)
- m_flags.Set (flagsGotDebugLocData);
-
- section = section_list->FindSectionByType (eSectionTypeDWARFDebugMacInfo, true).get();
- if (!section)
- m_flags.Set (flagsGotDebugMacInfoData);
-
- section = section_list->FindSectionByType (eSectionTypeDWARFDebugPubNames, true).get();
- if (!section)
- m_flags.Set (flagsGotDebugPubNamesData);
-
- section = section_list->FindSectionByType (eSectionTypeDWARFDebugPubTypes, true).get();
- if (!section)
- m_flags.Set (flagsGotDebugPubTypesData);
-
- section = section_list->FindSectionByType (eSectionTypeDWARFDebugRanges, true).get();
- if (!section)
- m_flags.Set (flagsGotDebugRangesData);
-
- section = section_list->FindSectionByType (eSectionTypeDWARFDebugStr, true).get();
- if (!section)
- m_flags.Set (flagsGotDebugStrData);
}
else
{
@@ -737,104 +641,128 @@ SymbolFileDWARF::CalculateAbilities ()
}
const DWARFDataExtractor&
-SymbolFileDWARF::GetCachedSectionData (uint32_t got_flag, SectionType sect_type, DWARFDataExtractor &data)
+SymbolFileDWARF::GetCachedSectionData (lldb::SectionType sect_type, DWARFDataSegment& data_segment)
{
- if (m_flags.IsClear (got_flag))
+ std::call_once(data_segment.m_flag,
+ &SymbolFileDWARF::LoadSectionData,
+ this,
+ sect_type,
+ std::ref(data_segment.m_data));
+ return data_segment.m_data;
+}
+
+void
+SymbolFileDWARF::LoadSectionData (lldb::SectionType sect_type, DWARFDataExtractor& data)
+{
+ ModuleSP module_sp (m_obj_file->GetModule());
+ const SectionList *section_list = module_sp->GetSectionList();
+ if (section_list)
{
- ModuleSP module_sp (m_obj_file->GetModule());
- m_flags.Set (got_flag);
- const SectionList *section_list = module_sp->GetSectionList();
- if (section_list)
+ SectionSP section_sp (section_list->FindSectionByType(sect_type, true));
+ if (section_sp)
{
- SectionSP section_sp (section_list->FindSectionByType(sect_type, true));
- if (section_sp)
+ // See if we memory mapped the DWARF segment?
+ if (m_dwarf_data.GetByteSize())
{
- // See if we memory mapped the DWARF segment?
- if (m_dwarf_data.GetByteSize())
- {
- data.SetData(m_dwarf_data, section_sp->GetOffset (), section_sp->GetFileSize());
- }
- else
- {
- if (m_obj_file->ReadSectionData (section_sp.get(), data) == 0)
- data.Clear();
- }
+ data.SetData(m_dwarf_data, section_sp->GetOffset(), section_sp->GetFileSize());
+ }
+ else
+ {
+ if (m_obj_file->ReadSectionData(section_sp.get(), data) == 0)
+ data.Clear();
}
}
}
- return data;
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_abbrev_data()
{
- return GetCachedSectionData (flagsGotDebugAbbrevData, eSectionTypeDWARFDebugAbbrev, m_data_debug_abbrev);
+ return GetCachedSectionData (eSectionTypeDWARFDebugAbbrev, m_data_debug_abbrev);
+}
+
+const DWARFDataExtractor&
+SymbolFileDWARF::get_debug_addr_data()
+{
+ return GetCachedSectionData (eSectionTypeDWARFDebugAddr, m_data_debug_addr);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_aranges_data()
{
- return GetCachedSectionData (flagsGotDebugArangesData, eSectionTypeDWARFDebugAranges, m_data_debug_aranges);
+ return GetCachedSectionData (eSectionTypeDWARFDebugAranges, m_data_debug_aranges);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_frame_data()
{
- return GetCachedSectionData (flagsGotDebugFrameData, eSectionTypeDWARFDebugFrame, m_data_debug_frame);
+ return GetCachedSectionData (eSectionTypeDWARFDebugFrame, m_data_debug_frame);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_info_data()
{
- return GetCachedSectionData (flagsGotDebugInfoData, eSectionTypeDWARFDebugInfo, m_data_debug_info);
+ return GetCachedSectionData (eSectionTypeDWARFDebugInfo, m_data_debug_info);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_line_data()
{
- return GetCachedSectionData (flagsGotDebugLineData, eSectionTypeDWARFDebugLine, m_data_debug_line);
+ return GetCachedSectionData (eSectionTypeDWARFDebugLine, m_data_debug_line);
+}
+
+const DWARFDataExtractor&
+SymbolFileDWARF::get_debug_macro_data()
+{
+ return GetCachedSectionData (eSectionTypeDWARFDebugMacro, m_data_debug_macro);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_loc_data()
{
- return GetCachedSectionData (flagsGotDebugLocData, eSectionTypeDWARFDebugLoc, m_data_debug_loc);
+ return GetCachedSectionData (eSectionTypeDWARFDebugLoc, m_data_debug_loc);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_ranges_data()
{
- return GetCachedSectionData (flagsGotDebugRangesData, eSectionTypeDWARFDebugRanges, m_data_debug_ranges);
+ return GetCachedSectionData (eSectionTypeDWARFDebugRanges, m_data_debug_ranges);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_debug_str_data()
{
- return GetCachedSectionData (flagsGotDebugStrData, eSectionTypeDWARFDebugStr, m_data_debug_str);
+ return GetCachedSectionData (eSectionTypeDWARFDebugStr, m_data_debug_str);
+}
+
+const DWARFDataExtractor&
+SymbolFileDWARF::get_debug_str_offsets_data()
+{
+ return GetCachedSectionData (eSectionTypeDWARFDebugStrOffsets, m_data_debug_str_offsets);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_apple_names_data()
{
- return GetCachedSectionData (flagsGotAppleNamesData, eSectionTypeDWARFAppleNames, m_data_apple_names);
+ return GetCachedSectionData (eSectionTypeDWARFAppleNames, m_data_apple_names);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_apple_types_data()
{
- return GetCachedSectionData (flagsGotAppleTypesData, eSectionTypeDWARFAppleTypes, m_data_apple_types);
+ return GetCachedSectionData (eSectionTypeDWARFAppleTypes, m_data_apple_types);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_apple_namespaces_data()
{
- return GetCachedSectionData (flagsGotAppleNamespacesData, eSectionTypeDWARFAppleNamespaces, m_data_apple_namespaces);
+ return GetCachedSectionData (eSectionTypeDWARFAppleNamespaces, m_data_apple_namespaces);
}
const DWARFDataExtractor&
SymbolFileDWARF::get_apple_objc_data()
{
- return GetCachedSectionData (flagsGotAppleObjCData, eSectionTypeDWARFAppleObjC, m_data_apple_objc);
+ return GetCachedSectionData (eSectionTypeDWARFAppleObjC, m_data_apple_objc);
}
@@ -889,6 +817,9 @@ SymbolFileDWARF::DebugInfo() const
DWARFCompileUnit*
SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit)
{
+ if (!comp_unit)
+ return nullptr;
+
DWARFDebugInfo* info = DebugInfo();
if (info)
{
@@ -900,7 +831,7 @@ SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit)
// TODO: modify to support LTO .o files where each .o file might
// have multiple DW_TAG_compile_unit tags.
- DWARFCompileUnit *dwarf_cu = info->GetCompileUnit(0).get();
+ DWARFCompileUnit *dwarf_cu = info->GetCompileUnit(0);
if (dwarf_cu && dwarf_cu->GetUserData() == NULL)
dwarf_cu->SetUserData(comp_unit);
return dwarf_cu;
@@ -910,7 +841,7 @@ SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit)
// Just a normal DWARF file whose user ID for the compile unit is
// the DWARF offset itself
- DWARFCompileUnit *dwarf_cu = info->GetCompileUnit((dw_offset_t)comp_unit->GetID()).get();
+ DWARFCompileUnit *dwarf_cu = info->GetCompileUnit((dw_offset_t)comp_unit->GetID());
if (dwarf_cu && dwarf_cu->GetUserData() == NULL)
dwarf_cu->SetUserData(comp_unit);
return dwarf_cu;
@@ -958,7 +889,11 @@ SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx)
}
else
{
- if (GetDebugMapSymfile ())
+ if (dwarf_cu->GetSymbolFileDWARF() != this)
+ {
+ return dwarf_cu->GetSymbolFileDWARF()->ParseCompileUnit(dwarf_cu, cu_idx);
+ }
+ else if (GetDebugMapSymfile ())
{
// Let the debug map create the compile unit
cu_sp = m_debug_map_symfile->GetCompileUnit(this);
@@ -969,20 +904,18 @@ SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx)
ModuleSP module_sp (m_obj_file->GetModule());
if (module_sp)
{
- const DWARFDebugInfoEntry * cu_die = dwarf_cu->GetCompileUnitDIEOnly ();
+ const DWARFDIE cu_die = dwarf_cu->GetCompileUnitDIEOnly ();
if (cu_die)
{
- FileSpec cu_file_spec{cu_die->GetName(this, dwarf_cu), false};
+ FileSpec cu_file_spec{cu_die.GetName(), false};
if (cu_file_spec)
{
// If we have a full path to the compile unit, we don't need to resolve
// the file. This can be expensive e.g. when the source files are NFS mounted.
if (cu_file_spec.IsRelative())
{
- // DWARF2/3 suggests the form hostname:pathname for compilation directory.
- // Remove the host part if present.
- const char *cu_comp_dir{cu_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_comp_dir, nullptr)};
- cu_file_spec.PrependPathComponent(removeHostnameFromPathname(cu_comp_dir));
+ const char *cu_comp_dir{cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr)};
+ cu_file_spec.PrependPathComponent(resolveCompDir(cu_comp_dir));
}
std::string remapped_file;
@@ -990,13 +923,15 @@ SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx)
cu_file_spec.SetFile(remapped_file, false);
}
- LanguageType cu_language = DWARFCompileUnit::LanguageTypeFromDWARF(cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_language, 0));
+ LanguageType cu_language = DWARFCompileUnit::LanguageTypeFromDWARF(cu_die.GetAttributeValueAsUnsigned(DW_AT_language, 0));
+ bool is_optimized = dwarf_cu->GetIsOptimized ();
cu_sp.reset(new CompileUnit (module_sp,
dwarf_cu,
cu_file_spec,
- MakeUserID(dwarf_cu->GetOffset()),
- cu_language));
+ dwarf_cu->GetID(),
+ cu_language,
+ is_optimized));
if (cu_sp)
{
// If we just created a compile unit with an invalid file spec, try and get the
@@ -1053,137 +988,20 @@ SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx)
}
Function *
-SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die)
+SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, const DWARFDIE &die)
{
- DWARFDebugRanges::RangeList func_ranges;
- const char *name = NULL;
- const char *mangled = NULL;
- int decl_file = 0;
- int decl_line = 0;
- int decl_column = 0;
- int call_file = 0;
- int call_line = 0;
- int call_column = 0;
- DWARFExpression frame_base;
-
- assert (die->Tag() == DW_TAG_subprogram);
-
- if (die->Tag() != DW_TAG_subprogram)
- return NULL;
-
- if (die->GetDIENamesAndRanges (this,
- dwarf_cu,
- name,
- mangled,
- func_ranges,
- decl_file,
- decl_line,
- decl_column,
- call_file,
- call_line,
- call_column,
- &frame_base))
+ if (die.IsValid())
{
- // Union of all ranges in the function DIE (if the function is discontiguous)
- AddressRange func_range;
- lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase (0);
- lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd (0);
- if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr)
- {
- ModuleSP module_sp (m_obj_file->GetModule());
- func_range.GetBaseAddress().ResolveAddressUsingFileSections (lowest_func_addr, module_sp->GetSectionList());
- if (func_range.GetBaseAddress().IsValid())
- func_range.SetByteSize(highest_func_addr - lowest_func_addr);
- }
+ TypeSystem *type_system = GetTypeSystemForLanguage(die.GetCU()->GetLanguageType());
- if (func_range.GetBaseAddress().IsValid())
+ if (type_system)
{
- Mangled func_name;
- if (mangled)
- func_name.SetValue(ConstString(mangled), true);
- else if (die->GetParent()->Tag() == DW_TAG_compile_unit &&
- LanguageRuntime::LanguageIsCPlusPlus(dwarf_cu->GetLanguageType()) &&
- name && strcmp(name, "main") != 0)
- {
- // If the mangled name is not present in the DWARF, generate the demangled name
- // using the decl context. We skip if the function is "main" as its name is
- // never mangled.
- bool is_static = false;
- bool is_variadic = false;
- unsigned type_quals = 0;
- std::vector<ClangASTType> param_types;
- std::vector<clang::ParmVarDecl*> param_decls;
- const DWARFDebugInfoEntry *decl_ctx_die = NULL;
- DWARFDeclContext decl_ctx;
- StreamString sstr;
-
- die->GetDWARFDeclContext(this, dwarf_cu, decl_ctx);
- sstr << decl_ctx.GetQualifiedName();
-
- clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE(dwarf_cu,
- die,
- &decl_ctx_die);
- ParseChildParameters(sc,
- containing_decl_ctx,
- dwarf_cu,
- die,
- true,
- is_static,
- is_variadic,
- param_types,
- param_decls,
- type_quals);
- sstr << "(";
- for (size_t i = 0; i < param_types.size(); i++)
- {
- if (i > 0)
- sstr << ", ";
- sstr << param_types[i].GetTypeName();
- }
- if (is_variadic)
- sstr << ", ...";
- sstr << ")";
- if (type_quals & clang::Qualifiers::Const)
- sstr << " const";
-
- func_name.SetValue(ConstString(sstr.GetData()), false);
- }
- else
- func_name.SetValue(ConstString(name), false);
-
- FunctionSP func_sp;
- std::unique_ptr<Declaration> decl_ap;
- if (decl_file != 0 || decl_line != 0 || decl_column != 0)
- decl_ap.reset(new Declaration (sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file),
- decl_line,
- decl_column));
-
- // Supply the type _only_ if it has already been parsed
- Type *func_type = m_die_to_type.lookup (die);
-
- assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED);
-
- if (FixupAddress (func_range.GetBaseAddress()))
- {
- const user_id_t func_user_id = MakeUserID(die->GetOffset());
- func_sp.reset(new Function (sc.comp_unit,
- MakeUserID(func_user_id), // UserID is the DIE offset
- MakeUserID(func_user_id),
- func_name,
- func_type,
- func_range)); // first address range
-
- if (func_sp.get() != NULL)
- {
- if (frame_base.IsValid())
- func_sp->GetFrameBaseExpression() = frame_base;
- sc.comp_unit->AddFunction(func_sp);
- return func_sp.get();
- }
- }
+ DWARFASTParser *dwarf_ast = type_system->GetDWARFParser();
+ if (dwarf_ast)
+ return dwarf_ast->ParseFunctionFromDWARF(sc, die);
}
}
- return NULL;
+ return nullptr;
}
bool
@@ -1203,12 +1021,9 @@ SymbolFileDWARF::ParseCompileUnitLanguage (const SymbolContext& sc)
assert (sc.comp_unit);
DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu)
- {
- const DWARFDebugInfoEntry *die = dwarf_cu->GetCompileUnitDIEOnly();
- if (die)
- return DWARFCompileUnit::LanguageTypeFromDWARF(die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_language, 0));
- }
- return eLanguageTypeUnknown;
+ return dwarf_cu->GetLanguageType();
+ else
+ return eLanguageTypeUnknown;
}
size_t
@@ -1224,10 +1039,10 @@ SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc)
size_t func_idx;
for (func_idx = 0; func_idx < num_functions; ++func_idx)
{
- const DWARFDebugInfoEntry *die = function_dies.GetDIEPtrAtIndex(func_idx);
- if (sc.comp_unit->FindFunctionByUID (MakeUserID(die->GetOffset())).get() == NULL)
+ DWARFDIE die = function_dies.GetDIEAtIndex(func_idx);
+ if (sc.comp_unit->FindFunctionByUID (die.GetID()).get() == NULL)
{
- if (ParseCompileUnitFunction(sc, dwarf_cu, die))
+ if (ParseCompileUnitFunction(sc, die))
++functions_added;
}
}
@@ -1243,17 +1058,13 @@ SymbolFileDWARF::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpec
DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu)
{
- const DWARFDebugInfoEntry * cu_die = dwarf_cu->GetCompileUnitDIEOnly();
+ const DWARFDIE cu_die = dwarf_cu->GetCompileUnitDIEOnly();
if (cu_die)
{
- const char * cu_comp_dir = cu_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_comp_dir, NULL);
-
- // DWARF2/3 suggests the form hostname:pathname for compilation directory.
- // Remove the host part if present.
- cu_comp_dir = removeHostnameFromPathname(cu_comp_dir);
+ const char * cu_comp_dir = resolveCompDir(cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr));
- dw_offset_t stmt_list = cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_stmt_list, DW_INVALID_OFFSET);
+ const dw_offset_t stmt_list = cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list, DW_INVALID_OFFSET);
// All file indexes in DWARF are one based and a file of index zero is
// supposed to be the compile unit itself.
@@ -1275,9 +1086,9 @@ SymbolFileDWARF::ParseImportedModules (const lldb_private::SymbolContext &sc, st
if (ClangModulesDeclVendor::LanguageSupportsClangModules(sc.comp_unit->GetLanguage()))
{
UpdateExternalModuleListIfNeeded();
- for (const std::pair<uint64_t, const ClangModuleInfo> &external_type_module : m_external_type_modules)
+ for (const auto &pair : m_external_type_modules)
{
- imported_modules.push_back(external_type_module.second.m_name);
+ imported_modules.push_back(pair.first);
}
}
}
@@ -1288,6 +1099,7 @@ struct ParseDWARFLineTableCallbackInfo
{
LineTable* line_table;
std::unique_ptr<LineSequence> sequence_ap;
+ lldb::addr_t addr_mask;
};
//----------------------------------------------------------------------
@@ -1317,7 +1129,7 @@ ParseDWARFLineTableCallback(dw_offset_t offset, const DWARFDebugLine::State& sta
assert(info->sequence_ap.get());
}
line_table->AppendLineEntryToSequence (info->sequence_ap.get(),
- state.address,
+ state.address & info->addr_mask,
state.line,
state.column,
state.file,
@@ -1346,10 +1158,10 @@ SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc)
DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu)
{
- const DWARFDebugInfoEntry *dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly();
+ const DWARFDIE dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly();
if (dwarf_cu_die)
{
- const dw_offset_t cu_line_offset = dwarf_cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_stmt_list, DW_INVALID_OFFSET);
+ const dw_offset_t cu_line_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list, DW_INVALID_OFFSET);
if (cu_line_offset != DW_INVALID_OFFSET)
{
std::unique_ptr<LineTable> line_table_ap(new LineTable(sc.comp_unit));
@@ -1357,6 +1169,28 @@ SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc)
{
ParseDWARFLineTableCallbackInfo info;
info.line_table = line_table_ap.get();
+
+ /*
+ * MIPS:
+ * The SymbolContext may not have a valid target, thus we may not be able
+ * to call Address::GetOpcodeLoadAddress() which would clear the bit #0
+ * for MIPS. Use ArchSpec to clear the bit #0.
+ */
+ ArchSpec arch;
+ GetObjectFile()->GetArchitecture(arch);
+ switch (arch.GetMachine())
+ {
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ info.addr_mask = ~((lldb::addr_t)1);
+ break;
+ default:
+ info.addr_mask = ~((lldb::addr_t)0);
+ break;
+ }
+
lldb::offset_t offset = cu_line_offset;
DWARFDebugLine::ParseStatementTable(get_debug_line_data(), &offset, ParseDWARFLineTableCallback, &info);
if (m_debug_map_symfile)
@@ -1379,21 +1213,63 @@ SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc)
return false;
}
+lldb_private::DebugMacrosSP
+SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset)
+{
+ auto iter = m_debug_macros_map.find(*offset);
+ if (iter != m_debug_macros_map.end())
+ return iter->second;
+
+ const DWARFDataExtractor &debug_macro_data = get_debug_macro_data();
+ if (debug_macro_data.GetByteSize() == 0)
+ return DebugMacrosSP();
+
+ lldb_private::DebugMacrosSP debug_macros_sp(new lldb_private::DebugMacros());
+ m_debug_macros_map[*offset] = debug_macros_sp;
+
+ const DWARFDebugMacroHeader &header = DWARFDebugMacroHeader::ParseHeader(debug_macro_data, offset);
+ DWARFDebugMacroEntry::ReadMacroEntries(
+ debug_macro_data, get_debug_str_data(), header.OffsetIs64Bit(), offset, this, debug_macros_sp);
+
+ return debug_macros_sp;
+}
+
+bool
+SymbolFileDWARF::ParseCompileUnitDebugMacros(const SymbolContext& sc)
+{
+ assert (sc.comp_unit);
+
+ DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ if (dwarf_cu == nullptr)
+ return false;
+
+ const DWARFDIE dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly();
+ if (!dwarf_cu_die)
+ return false;
+
+ lldb::offset_t sect_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_macros, DW_INVALID_OFFSET);
+ if (sect_offset == DW_INVALID_OFFSET)
+ sect_offset = dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_macros, DW_INVALID_OFFSET);
+ if (sect_offset == DW_INVALID_OFFSET)
+ return false;
+
+ sc.comp_unit->SetDebugMacros(ParseDebugMacros(&sect_offset));
+
+ return true;
+}
+
size_t
-SymbolFileDWARF::ParseFunctionBlocks
-(
- const SymbolContext& sc,
- Block *parent_block,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
- addr_t subprogram_low_pc,
- uint32_t depth
-)
+SymbolFileDWARF::ParseFunctionBlocks (const SymbolContext& sc,
+ Block *parent_block,
+ const DWARFDIE &orig_die,
+ addr_t subprogram_low_pc,
+ uint32_t depth)
{
size_t blocks_added = 0;
- while (die != NULL)
+ DWARFDIE die = orig_die;
+ while (die)
{
- dw_tag_t tag = die->Tag();
+ dw_tag_t tag = die.Tag();
switch (tag)
{
@@ -1415,11 +1291,11 @@ SymbolFileDWARF::ParseFunctionBlocks
}
else
{
- BlockSP block_sp(new Block (MakeUserID(die->GetOffset())));
+ BlockSP block_sp(new Block (die.GetID()));
parent_block->AddChild(block_sp);
block = block_sp.get();
}
- DWARFDebugRanges::RangeList ranges;
+ DWARFRangeList ranges;
const char *name = NULL;
const char *mangled_name = NULL;
@@ -1429,13 +1305,11 @@ SymbolFileDWARF::ParseFunctionBlocks
int call_file = 0;
int call_line = 0;
int call_column = 0;
- if (die->GetDIENamesAndRanges (this,
- dwarf_cu,
- name,
- mangled_name,
- ranges,
- decl_file, decl_line, decl_column,
- call_file, call_line, call_column))
+ if (die.GetDIENamesAndRanges (name,
+ mangled_name,
+ ranges,
+ decl_file, decl_line, decl_column,
+ call_file, call_line, call_column, nullptr))
{
if (tag == DW_TAG_subprogram)
{
@@ -1461,7 +1335,7 @@ SymbolFileDWARF::ParseFunctionBlocks
const size_t num_ranges = ranges.GetSize();
for (size_t i = 0; i<num_ranges; ++i)
{
- const DWARFDebugRanges::Range &range = ranges.GetEntryRef (i);
+ const DWARFRangeList::Entry &range = ranges.GetEntryRef (i);
const addr_t range_base = range.GetRangeBase();
if (range_base >= subprogram_low_pc)
block->AddRange(Block::Range (range_base - subprogram_low_pc, range.GetByteSize()));
@@ -1493,12 +1367,11 @@ SymbolFileDWARF::ParseFunctionBlocks
++blocks_added;
- if (die->HasChildren())
+ if (die.HasChildren())
{
blocks_added += ParseFunctionBlocks (sc,
block,
- dwarf_cu,
- die->GetFirstChild(),
+ die.GetFirstChild(),
subprogram_low_pc,
depth + 1);
}
@@ -1514,278 +1387,21 @@ SymbolFileDWARF::ParseFunctionBlocks
// DW_TAG_subprogram DIE
if (depth == 0)
- die = NULL;
+ die.Clear();
else
- die = die->GetSibling();
+ die = die.GetSibling();
}
return blocks_added;
}
bool
-SymbolFileDWARF::ParseTemplateDIE (DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
- ClangASTContext::TemplateParameterInfos &template_param_infos)
-{
- const dw_tag_t tag = die->Tag();
-
- switch (tag)
- {
- case DW_TAG_template_type_parameter:
- case DW_TAG_template_value_parameter:
- {
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
-
- DWARFDebugInfoEntry::Attributes attributes;
- const size_t num_attributes = die->GetAttributes (this,
- dwarf_cu,
- fixed_form_sizes,
- attributes);
- const char *name = NULL;
- Type *lldb_type = NULL;
- ClangASTType clang_type;
- uint64_t uval64 = 0;
- bool uval64_valid = false;
- if (num_attributes > 0)
- {
- DWARFFormValue form_value;
- for (size_t i=0; i<num_attributes; ++i)
- {
- const dw_attr_t attr = attributes.AttributeAtIndex(i);
-
- switch (attr)
- {
- case DW_AT_name:
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- name = form_value.AsCString(&get_debug_str_data());
- break;
-
- case DW_AT_type:
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- const dw_offset_t type_die_offset = form_value.Reference();
- lldb_type = ResolveTypeUID(type_die_offset);
- if (lldb_type)
- clang_type = lldb_type->GetClangForwardType();
- }
- break;
-
- case DW_AT_const_value:
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- uval64_valid = true;
- uval64 = form_value.Unsigned();
- }
- break;
- default:
- break;
- }
- }
-
- clang::ASTContext *ast = GetClangASTContext().getASTContext();
- if (!clang_type)
- clang_type = GetClangASTContext().GetBasicType(eBasicTypeVoid);
-
- if (clang_type)
- {
- bool is_signed = false;
- if (name && name[0])
- template_param_infos.names.push_back(name);
- else
- template_param_infos.names.push_back(NULL);
-
- if (tag == DW_TAG_template_value_parameter &&
- lldb_type != NULL &&
- clang_type.IsIntegerType (is_signed) &&
- uval64_valid)
- {
- llvm::APInt apint (lldb_type->GetByteSize() * 8, uval64, is_signed);
- template_param_infos.args.push_back (clang::TemplateArgument (*ast,
- llvm::APSInt(apint),
- clang_type.GetQualType()));
- }
- else
- {
- template_param_infos.args.push_back (clang::TemplateArgument (clang_type.GetQualType()));
- }
- }
- else
- {
- return false;
- }
-
- }
- }
- return true;
-
- default:
- break;
- }
- return false;
-}
-
-bool
-SymbolFileDWARF::ParseTemplateParameterInfos (DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die,
- ClangASTContext::TemplateParameterInfos &template_param_infos)
-{
-
- if (parent_die == NULL)
- return false;
-
- Args template_parameter_names;
- for (const DWARFDebugInfoEntry *die = parent_die->GetFirstChild();
- die != NULL;
- die = die->GetSibling())
- {
- const dw_tag_t tag = die->Tag();
-
- switch (tag)
- {
- case DW_TAG_template_type_parameter:
- case DW_TAG_template_value_parameter:
- ParseTemplateDIE (dwarf_cu, die, template_param_infos);
- break;
-
- default:
- break;
- }
- }
- if (template_param_infos.args.empty())
- return false;
- return template_param_infos.args.size() == template_param_infos.names.size();
-}
-
-clang::ClassTemplateDecl *
-SymbolFileDWARF::ParseClassTemplateDecl (clang::DeclContext *decl_ctx,
- lldb::AccessType access_type,
- const char *parent_name,
- int tag_decl_kind,
- const ClangASTContext::TemplateParameterInfos &template_param_infos)
-{
- if (template_param_infos.IsValid())
- {
- std::string template_basename(parent_name);
- template_basename.erase (template_basename.find('<'));
- ClangASTContext &ast = GetClangASTContext();
-
- return ast.CreateClassTemplateDecl (decl_ctx,
- access_type,
- template_basename.c_str(),
- tag_decl_kind,
- template_param_infos);
- }
- return NULL;
-}
-
-class SymbolFileDWARF::DelayedAddObjCClassProperty
-{
-public:
- DelayedAddObjCClassProperty
- (
- const ClangASTType &class_opaque_type,
- const char *property_name,
- const ClangASTType &property_opaque_type, // The property type is only required if you don't have an ivar decl
- clang::ObjCIvarDecl *ivar_decl,
- const char *property_setter_name,
- const char *property_getter_name,
- uint32_t property_attributes,
- const ClangASTMetadata *metadata
- ) :
- m_class_opaque_type (class_opaque_type),
- m_property_name (property_name),
- m_property_opaque_type (property_opaque_type),
- m_ivar_decl (ivar_decl),
- m_property_setter_name (property_setter_name),
- m_property_getter_name (property_getter_name),
- m_property_attributes (property_attributes)
- {
- if (metadata != NULL)
- {
- m_metadata_ap.reset(new ClangASTMetadata());
- *m_metadata_ap = *metadata;
- }
- }
-
- DelayedAddObjCClassProperty (const DelayedAddObjCClassProperty &rhs)
- {
- *this = rhs;
- }
-
- DelayedAddObjCClassProperty& operator= (const DelayedAddObjCClassProperty &rhs)
- {
- m_class_opaque_type = rhs.m_class_opaque_type;
- m_property_name = rhs.m_property_name;
- m_property_opaque_type = rhs.m_property_opaque_type;
- m_ivar_decl = rhs.m_ivar_decl;
- m_property_setter_name = rhs.m_property_setter_name;
- m_property_getter_name = rhs.m_property_getter_name;
- m_property_attributes = rhs.m_property_attributes;
-
- if (rhs.m_metadata_ap.get())
- {
- m_metadata_ap.reset (new ClangASTMetadata());
- *m_metadata_ap = *rhs.m_metadata_ap;
- }
- return *this;
- }
-
- bool
- Finalize()
- {
- return m_class_opaque_type.AddObjCClassProperty (m_property_name,
- m_property_opaque_type,
- m_ivar_decl,
- m_property_setter_name,
- m_property_getter_name,
- m_property_attributes,
- m_metadata_ap.get());
- }
-private:
- ClangASTType m_class_opaque_type;
- const char *m_property_name;
- ClangASTType m_property_opaque_type;
- clang::ObjCIvarDecl *m_ivar_decl;
- const char *m_property_setter_name;
- const char *m_property_getter_name;
- uint32_t m_property_attributes;
- std::unique_ptr<ClangASTMetadata> m_metadata_ap;
-};
-
-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 ()
- {
- return (bit_size != LLDB_INVALID_ADDRESS) &&
- (bit_offset != LLDB_INVALID_ADDRESS);
- }
-};
-
-
-bool
-SymbolFileDWARF::ClassOrStructIsVirtual (DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die)
+SymbolFileDWARF::ClassOrStructIsVirtual (const DWARFDIE &parent_die)
{
if (parent_die)
{
- for (const DWARFDebugInfoEntry *die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
+ for (DWARFDIE die = parent_die.GetFirstChild(); die; die = die.GetSibling())
{
- dw_tag_t tag = die->Tag();
+ dw_tag_t tag = die.Tag();
bool check_virtuality = false;
switch (tag)
{
@@ -1798,7 +1414,7 @@ SymbolFileDWARF::ClassOrStructIsVirtual (DWARFCompileUnit* dwarf_cu,
}
if (check_virtuality)
{
- if (die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_virtuality, 0) != 0)
+ if (die.GetAttributeValueAsUnsigned(DW_AT_virtuality, 0) != 0)
return true;
}
}
@@ -1806,602 +1422,79 @@ SymbolFileDWARF::ClassOrStructIsVirtual (DWARFCompileUnit* dwarf_cu,
return false;
}
-size_t
-SymbolFileDWARF::ParseChildMembers
-(
- const SymbolContext& sc,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die,
- ClangASTType &class_clang_type,
- const LanguageType class_language,
- std::vector<clang::CXXBaseSpecifier *>& base_classes,
- std::vector<int>& member_accessibilities,
- DWARFDIECollection& member_function_dies,
- DelayedPropertyList& delayed_properties,
- AccessType& default_accessibility,
- bool &is_a_class,
- LayoutInfo &layout_info
-)
+void
+SymbolFileDWARF::ParseDeclsForContext (CompilerDeclContext decl_ctx)
{
- if (parent_die == NULL)
- return 0;
+ TypeSystem *type_system = decl_ctx.GetTypeSystem();
+ DWARFASTParser *ast_parser = type_system->GetDWARFParser();
+ std::vector<DWARFDIE> decl_ctx_die_list = ast_parser->GetDIEForDeclContext(decl_ctx);
- size_t count = 0;
- const DWARFDebugInfoEntry *die;
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
- uint32_t member_idx = 0;
- BitfieldInfo last_field_info;
- ModuleSP module = GetObjectFile()->GetModule();
+ for (DWARFDIE decl_ctx_die : decl_ctx_die_list)
+ for (DWARFDIE decl = decl_ctx_die.GetFirstChild(); decl; decl = decl.GetSibling())
+ ast_parser->GetDeclForUIDFromDWARF(decl);
+}
- for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
+CompilerDecl
+SymbolFileDWARF::GetDeclForUID (lldb::user_id_t type_uid)
+{
+ if (UserIDMatches(type_uid))
{
- dw_tag_t tag = die->Tag();
-
- switch (tag)
+ DWARFDebugInfo* debug_info = DebugInfo();
+ if (debug_info)
{
- case DW_TAG_member:
- case DW_TAG_APPLE_property:
- {
- DWARFDebugInfoEntry::Attributes attributes;
- const size_t num_attributes = die->GetAttributes (this,
- dwarf_cu,
- fixed_form_sizes,
- attributes);
- if (num_attributes > 0)
- {
- Declaration decl;
- //DWARFExpression location;
- const char *name = NULL;
- const char *prop_name = NULL;
- const char *prop_getter_name = NULL;
- const char *prop_setter_name = NULL;
- uint32_t prop_attributes = 0;
-
-
- bool is_artificial = false;
- lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
- AccessType accessibility = eAccessNone;
- uint32_t member_byte_offset = UINT32_MAX;
- size_t byte_size = 0;
- size_t bit_offset = 0;
- 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(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
- case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
- case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break;
- case DW_AT_type: encoding_uid = form_value.Reference(); break;
- case DW_AT_bit_offset: bit_offset = form_value.Unsigned(); 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_member_location:
- if (form_value.BlockData())
- {
- Value initialValue(0);
- Value memberOffset(0);
- const DWARFDataExtractor& debug_info_data = get_debug_info_data();
- uint32_t block_length = form_value.Unsigned();
- uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
- if (DWARFExpression::Evaluate(NULL, // ExecutionContext *
- NULL, // ClangExpressionVariableList *
- NULL, // ClangExpressionDeclMap *
- NULL, // RegisterContext *
- module,
- debug_info_data,
- block_offset,
- block_length,
- eRegisterKindDWARF,
- &initialValue,
- memberOffset,
- NULL))
- {
- member_byte_offset = memberOffset.ResolveValue(NULL).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(&get_debug_str_data()); break;
- case DW_AT_APPLE_property_getter: prop_getter_name = form_value.AsCString(&get_debug_str_data()); break;
- case DW_AT_APPLE_property_setter: prop_setter_name = form_value.AsCString(&get_debug_str_data()); 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;
- }
- }
- }
-
- 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] == '-')
- {
- ObjCLanguageRuntime::MethodName prop_getter_method(prop_getter_name, true);
- prop_getter_name = prop_getter_method.GetSelector().GetCString();
- }
-
- if (prop_setter_name && prop_setter_name[0] == '-')
- {
- ObjCLanguageRuntime::MethodName prop_setter_method(prop_setter_name, true);
- prop_setter_name = prop_setter_method.GetSelector().GetCString();
- }
-
- // If the names haven't been provided, they need to be
- // filled in.
-
- if (!prop_getter_name)
- {
- prop_getter_name = prop_name;
- }
- if (!prop_setter_name && prop_name[0] && !(prop_attributes & DW_APPLE_PROPERTY_readonly))
- {
- StreamString ss;
-
- ss.Printf("set%c%s:",
- toupper(prop_name[0]),
- &prop_name[1]);
-
- fixed_setter.SetCString(ss.GetData());
- prop_setter_name = fixed_setter.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 (bit_offset > 128)
- {
- 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;
-
- if (member_idx == 0 && !is_artificial && name && (strstr (name, "_vptr$") == name))
- {
- // Not all compilers will mark the vtable pointer
- // member as artificial (llvm-gcc). We can't have
- // the virtual members in our classes otherwise it
- // throws off all child offsets since we end up
- // having and extra pointer sized member in our
- // class layouts.
- is_artificial = true;
- }
-
- // Handle static members
- if (is_external && member_byte_offset == UINT32_MAX)
- {
- Type *var_type = ResolveTypeUID(encoding_uid);
-
- if (var_type)
- {
- if (accessibility == eAccessNone)
- accessibility = eAccessPublic;
- class_clang_type.AddVariableToRecordType (name,
- var_type->GetClangLayoutType(),
- accessibility);
- }
- break;
- }
-
- if (is_artificial == false)
- {
- Type *member_type = ResolveTypeUID(encoding_uid);
-
- clang::FieldDecl *field_decl = NULL;
- 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 (byte_size == 0)
- byte_size = member_type->GetByteSize();
-
- if (GetObjectFile()->GetByteOrder() == eByteOrderLittle)
- {
- this_field_info.bit_offset += byte_size * 8;
- this_field_info.bit_offset -= (bit_offset + bit_size);
- }
- else
- {
- this_field_info.bit_offset += bit_offset;
- }
-
- // 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 = dwarf_cu->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;
- }
- }
- }
-
- if (anon_field_info.IsValid())
- {
- clang::FieldDecl *unnamed_bitfield_decl = class_clang_type.AddFieldToRecordType (NULL,
- GetClangASTContext().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();
- }
-
- ClangASTType member_clang_type = member_type->GetClangLayoutType();
-
- {
- // 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].
-
- ClangASTType 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(this, dwarf_cu, DW_AT_byte_size, UINT64_MAX);
-
- if (member_byte_offset >= parent_byte_size)
- {
- if (member_array_size != 1)
- {
- GetObjectFile()->GetModule()->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 " which extends beyond the bounds of 0x%8.8" PRIx64,
- MakeUserID(die->GetOffset()),
- name,
- encoding_uid,
- MakeUserID(parent_die->GetOffset()));
- }
-
- member_clang_type = GetClangASTContext().CreateArrayType(member_array_element_type, 0, false);
- }
- }
- }
-
- field_decl = class_clang_type.AddFieldToRecordType (name,
- member_clang_type,
- accessibility,
- bit_size);
-
- GetClangASTContext().SetMetadataAsUserID (field_decl, MakeUserID(die->GetOffset()));
-
- layout_info.field_offsets.insert(std::make_pair(field_decl, field_bit_offset));
- }
- else
- {
- if (name)
- GetObjectFile()->GetModule()->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 " which was unable to be parsed",
- MakeUserID(die->GetOffset()),
- name,
- encoding_uid);
- else
- GetObjectFile()->GetModule()->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member refers to type 0x%8.8" PRIx64 " which was unable to be parsed",
- MakeUserID(die->GetOffset()),
- encoding_uid);
- }
- }
-
- if (prop_name != NULL && member_type)
- {
- clang::ObjCIvarDecl *ivar_decl = NULL;
-
- if (field_decl)
- {
- ivar_decl = clang::dyn_cast<clang::ObjCIvarDecl>(field_decl);
- assert (ivar_decl != NULL);
- }
-
- ClangASTMetadata metadata;
- metadata.SetUserID (MakeUserID(die->GetOffset()));
- delayed_properties.push_back(DelayedAddObjCClassProperty(class_clang_type,
- prop_name,
- member_type->GetClangLayoutType(),
- ivar_decl,
- prop_setter_name,
- prop_getter_name,
- prop_attributes,
- &metadata));
-
- if (ivar_decl)
- GetClangASTContext().SetMetadataAsUserID (ivar_decl, MakeUserID(die->GetOffset()));
- }
- }
- }
- ++member_idx;
- }
- break;
-
- case DW_TAG_subprogram:
- // Let the type parsing code handle this one for us.
- member_function_dies.Append (die);
- break;
-
- case DW_TAG_inheritance:
+ DWARFDIE die = debug_info->GetDIE(DIERef(type_uid));
+ if (die)
{
- is_a_class = true;
- if (default_accessibility == eAccessNone)
- default_accessibility = eAccessPrivate;
- // TODO: implement DW_TAG_inheritance type parsing
- DWARFDebugInfoEntry::Attributes attributes;
- const size_t num_attributes = die->GetAttributes (this,
- dwarf_cu,
- fixed_form_sizes,
- attributes);
- if (num_attributes > 0)
- {
- Declaration decl;
- DWARFExpression location;
- lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
- AccessType accessibility = default_accessibility;
- bool is_virtual = false;
- bool is_base_of_class = true;
- off_t member_byte_offset = 0;
- uint32_t i;
- for (i=0; i<num_attributes; ++i)
- {
- const dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
- case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
- case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_type: encoding_uid = form_value.Reference(); break;
- case DW_AT_data_member_location:
- if (form_value.BlockData())
- {
- Value initialValue(0);
- Value memberOffset(0);
- const DWARFDataExtractor& debug_info_data = get_debug_info_data();
- uint32_t block_length = form_value.Unsigned();
- uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
- if (DWARFExpression::Evaluate (NULL,
- NULL,
- NULL,
- NULL,
- module,
- debug_info_data,
- block_offset,
- block_length,
- eRegisterKindDWARF,
- &initialValue,
- memberOffset,
- NULL))
- {
- member_byte_offset = memberOffset.ResolveValue(NULL).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_virtuality:
- is_virtual = form_value.Boolean();
- break;
-
- case DW_AT_sibling:
- break;
-
- default:
- break;
- }
- }
- }
-
- Type *base_class_type = ResolveTypeUID(encoding_uid);
- if (base_class_type == NULL)
- {
- GetObjectFile()->GetModule()->ReportError("0x%8.8x: DW_TAG_inheritance failed to resolve the base class at 0x%8.8" PRIx64 " from enclosing type 0x%8.8x. \nPlease file a bug and attach the file at the start of this error message",
- die->GetOffset(),
- encoding_uid,
- parent_die->GetOffset());
- break;
- }
-
- ClangASTType base_class_clang_type = base_class_type->GetClangFullType();
- assert (base_class_clang_type);
- if (class_language == eLanguageTypeObjC)
- {
- class_clang_type.SetObjCSuperClass(base_class_clang_type);
- }
- else
- {
- base_classes.push_back (base_class_clang_type.CreateBaseClassSpecifier (accessibility,
- is_virtual,
- is_base_of_class));
-
- if (is_virtual)
- {
- // Do not specify any offset for virtual inheritance. The DWARF produced by clang doesn't
- // give us a constant offset, but gives us a DWARF expressions that requires an actual object
- // in memory. the DW_AT_data_member_location for a virtual base class looks like:
- // DW_AT_data_member_location( DW_OP_dup, DW_OP_deref, DW_OP_constu(0x00000018), DW_OP_minus, DW_OP_deref, DW_OP_plus )
- // Given this, there is really no valid response we can give to clang for virtual base
- // class offsets, and this should eventually be removed from LayoutRecordType() in the external
- // AST source in clang.
- }
- else
- {
- layout_info.base_offsets.insert(
- std::make_pair(base_class_clang_type.GetAsCXXRecordDecl(),
- clang::CharUnits::fromQuantity(member_byte_offset)));
- }
- }
- }
+ DWARFASTParser *dwarf_ast = die.GetDWARFParser();
+ if (dwarf_ast)
+ return dwarf_ast->GetDeclForUIDFromDWARF(die);
}
- break;
-
- default:
- break;
}
}
-
- return count;
+ return CompilerDecl();
}
-
-clang::DeclContext*
-SymbolFileDWARF::GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid)
+CompilerDeclContext
+SymbolFileDWARF::GetDeclContextForUID (lldb::user_id_t type_uid)
{
- DWARFDebugInfo* debug_info = DebugInfo();
- if (debug_info && UserIDMatches(type_uid))
+ if (UserIDMatches(type_uid))
{
- DWARFCompileUnitSP cu_sp;
- const DWARFDebugInfoEntry* die = debug_info->GetDIEPtr(type_uid, &cu_sp);
- if (die)
- return GetClangDeclContextContainingDIE (cu_sp.get(), die, NULL);
+ DWARFDebugInfo* debug_info = DebugInfo();
+ if (debug_info)
+ {
+ DWARFDIE die = debug_info->GetDIE(DIERef(type_uid));
+ if (die)
+ {
+ DWARFASTParser *dwarf_ast = die.GetDWARFParser();
+ if (dwarf_ast)
+ return dwarf_ast->GetDeclContextForUIDFromDWARF(die);
+ }
+ }
}
- return NULL;
+ return CompilerDeclContext();
}
-clang::DeclContext*
-SymbolFileDWARF::GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid)
+CompilerDeclContext
+SymbolFileDWARF::GetDeclContextContainingUID (lldb::user_id_t type_uid)
{
if (UserIDMatches(type_uid))
- return GetClangDeclContextForDIEOffset (sc, type_uid);
- return NULL;
+ {
+ DWARFDebugInfo* debug_info = DebugInfo();
+ if (debug_info)
+ {
+ DWARFDIE die = debug_info->GetDIE(DIERef(type_uid));
+ if (die)
+ {
+ DWARFASTParser *dwarf_ast = die.GetDWARFParser();
+ if (dwarf_ast)
+ return dwarf_ast->GetDeclContextContainingUIDFromDWARF(die);
+ }
+ }
+ }
+ return CompilerDeclContext();
}
+
Type*
SymbolFileDWARF::ResolveTypeUID (lldb::user_id_t type_uid)
{
@@ -2410,418 +1503,143 @@ SymbolFileDWARF::ResolveTypeUID (lldb::user_id_t type_uid)
DWARFDebugInfo* debug_info = DebugInfo();
if (debug_info)
{
- DWARFCompileUnitSP cu_sp;
- const DWARFDebugInfoEntry* type_die = debug_info->GetDIEPtr(type_uid, &cu_sp);
- const bool assert_not_being_parsed = true;
- return ResolveTypeUID (cu_sp.get(), type_die, assert_not_being_parsed);
+ DWARFDIE type_die = debug_info->GetDIE (DIERef(type_uid));
+ if (type_die)
+ {
+ const bool assert_not_being_parsed = true;
+ return ResolveTypeUID (type_die, assert_not_being_parsed);
+ }
}
}
return NULL;
}
Type*
-SymbolFileDWARF::ResolveTypeUID (DWARFCompileUnit* cu, const DWARFDebugInfoEntry* die, bool assert_not_being_parsed)
+SymbolFileDWARF::ResolveTypeUID (const DWARFDIE &die, bool assert_not_being_parsed)
{
- if (die != NULL)
+ if (die)
{
Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
if (log)
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s'",
- die->GetOffset(),
- DW_TAG_value_to_name(die->Tag()),
- die->GetName(this, cu));
+ die.GetOffset(),
+ die.GetTagAsCString(),
+ die.GetName());
// We might be coming in in the middle of a type tree (a class
// withing a class, an enum within a class), so parse any needed
// parent DIEs before we get to this one...
- const DWARFDebugInfoEntry *decl_ctx_die = GetDeclContextDIEContainingDIE (cu, die);
- switch (decl_ctx_die->Tag())
+ DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE (die);
+ if (decl_ctx_die)
{
- case DW_TAG_structure_type:
- case DW_TAG_union_type:
- case DW_TAG_class_type:
+ if (log)
{
- // Get the type, which could be a forward declaration
- if (log)
- GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent forward type for 0x%8.8x",
- die->GetOffset(),
- DW_TAG_value_to_name(die->Tag()),
- die->GetName(this, cu),
- decl_ctx_die->GetOffset());
-//
-// Type *parent_type = ResolveTypeUID (cu, decl_ctx_die, assert_not_being_parsed);
-// if (child_requires_parent_class_union_or_struct_to_be_completed(die->Tag()))
-// {
-// if (log)
-// GetObjectFile()->GetModule()->LogMessage (log,
-// "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent full type for 0x%8.8x since die is a function",
-// die->GetOffset(),
-// DW_TAG_value_to_name(die->Tag()),
-// die->GetName(this, cu),
-// decl_ctx_die->GetOffset());
-// // Ask the type to complete itself if it already hasn't since if we
-// // want a function (method or static) from a class, the class must
-// // create itself and add it's own methods and class functions.
-// if (parent_type)
-// parent_type->GetClangFullType();
-// }
- }
- break;
+ switch (decl_ctx_die.Tag())
+ {
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_class_type:
+ {
+ // Get the type, which could be a forward declaration
+ if (log)
+ GetObjectFile()->GetModule()->LogMessage (log,
+ "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent forward type for 0x%8.8x",
+ die.GetOffset(),
+ die.GetTagAsCString(),
+ die.GetName(),
+ decl_ctx_die.GetOffset());
+ }
+ break;
- default:
- break;
+ default:
+ break;
+ }
+ }
}
- return ResolveType (cu, die);
+ return ResolveType (die);
}
return NULL;
}
// This function is used when SymbolFileDWARFDebugMap owns a bunch of
// SymbolFileDWARF objects to detect if this DWARF file is the one that
-// can resolve a clang_type.
+// can resolve a compiler_type.
bool
-SymbolFileDWARF::HasForwardDeclForClangType (const ClangASTType &clang_type)
+SymbolFileDWARF::HasForwardDeclForClangType (const CompilerType &compiler_type)
{
- ClangASTType clang_type_no_qualifiers = clang_type.RemoveFastQualifiers();
- const DWARFDebugInfoEntry* die = m_forward_decl_clang_type_to_die.lookup (clang_type_no_qualifiers.GetOpaqueQualType());
- return die != NULL;
+ CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type);
+ if (GetForwardDeclClangTypeToDie().count (compiler_type_no_qualifiers.GetOpaqueQualType()))
+ {
+ return true;
+ }
+ TypeSystem *type_system = compiler_type.GetTypeSystem();
+ if (type_system)
+ {
+ DWARFASTParser *dwarf_ast = type_system->GetDWARFParser();
+ if (dwarf_ast)
+ return dwarf_ast->CanCompleteType(compiler_type);
+ }
+ return false;
}
bool
-SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
+SymbolFileDWARF::CompleteType (CompilerType &compiler_type)
{
+ TypeSystem *type_system = compiler_type.GetTypeSystem();
+ if (type_system)
+ {
+ DWARFASTParser *dwarf_ast = type_system->GetDWARFParser();
+ if (dwarf_ast && dwarf_ast->CanCompleteType(compiler_type))
+ return dwarf_ast->CompleteType(compiler_type);
+ }
+
// We have a struct/union/class/enum that needs to be fully resolved.
- ClangASTType clang_type_no_qualifiers = clang_type.RemoveFastQualifiers();
- const DWARFDebugInfoEntry* die = m_forward_decl_clang_type_to_die.lookup (clang_type_no_qualifiers.GetOpaqueQualType());
- if (die == NULL)
+ CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type);
+ auto die_it = GetForwardDeclClangTypeToDie().find (compiler_type_no_qualifiers.GetOpaqueQualType());
+ if (die_it == GetForwardDeclClangTypeToDie().end())
{
// We have already resolved this type...
return true;
}
+
+ DWARFDebugInfo* debug_info = DebugInfo();
+ DWARFDIE dwarf_die = debug_info->GetDIE(die_it->getSecond());
+
+ assert(UserIDMatches(die_it->getSecond().GetUID()) && "CompleteType called on the wrong SymbolFile");
+
// Once we start resolving this type, remove it from the forward declaration
// map in case anyone child members or other types require this type to get resolved.
// The type will get resolved when all of the calls to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition
// are done.
- m_forward_decl_clang_type_to_die.erase (clang_type_no_qualifiers.GetOpaqueQualType());
-
- // Disable external storage for this type so we don't get anymore
- // clang::ExternalASTSource queries for this type.
- clang_type.SetHasExternalStorage (false);
-
- DWARFDebugInfo* debug_info = DebugInfo();
+ GetForwardDeclClangTypeToDie().erase (die_it);
- DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitContainingDIE (die->GetOffset()).get();
- Type *type = m_die_to_type.lookup (die);
-
- const dw_tag_t tag = die->Tag();
+ Type *type = GetDIEToType().lookup (dwarf_die.GetDIE());
Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION));
if (log)
GetObjectFile()->GetModule()->LogMessageVerboseBacktrace (log,
"0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...",
- MakeUserID(die->GetOffset()),
- DW_TAG_value_to_name(tag),
+ dwarf_die.GetID(),
+ dwarf_die.GetTagAsCString(),
type->GetName().AsCString());
- assert (clang_type);
- DWARFDebugInfoEntry::Attributes attributes;
-
- switch (tag)
- {
- case DW_TAG_structure_type:
- case DW_TAG_union_type:
- case DW_TAG_class_type:
- {
- LayoutInfo layout_info;
-
- {
- if (die->HasChildren())
- {
- LanguageType class_language = eLanguageTypeUnknown;
- if (clang_type.IsObjCObjectOrInterfaceType())
- {
- class_language = eLanguageTypeObjC;
- // For objective C we don't start the definition when
- // the class is created.
- clang_type.StartTagDeclarationDefinition ();
- }
-
- 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;
- }
-
- SymbolContext sc(GetCompUnitForDWARFCompUnit(dwarf_cu));
- std::vector<clang::CXXBaseSpecifier *> base_classes;
- std::vector<int> member_accessibilities;
- bool is_a_class = false;
- // Parse members and base classes first
- DWARFDIECollection member_function_dies;
-
- DelayedPropertyList delayed_properties;
- ParseChildMembers (sc,
- dwarf_cu,
- die,
- clang_type,
- class_language,
- base_classes,
- member_accessibilities,
- member_function_dies,
- delayed_properties,
- default_accessibility,
- is_a_class,
- layout_info);
-
- // Now parse any methods if there were any...
- size_t num_functions = member_function_dies.Size();
- if (num_functions > 0)
- {
- for (size_t i=0; i<num_functions; ++i)
- {
- ResolveType(dwarf_cu, member_function_dies.GetDIEPtrAtIndex(i));
- }
- }
-
- if (class_language == eLanguageTypeObjC)
- {
- ConstString class_name (clang_type.GetTypeName());
- if (class_name)
- {
- DIEArray method_die_offsets;
- if (m_using_apple_tables)
- {
- if (m_apple_objc_ap.get())
- m_apple_objc_ap->FindByName(class_name.GetCString(), method_die_offsets);
- }
- else
- {
- if (!m_indexed)
- Index ();
-
- m_objc_class_selectors_index.Find (class_name, method_die_offsets);
- }
-
- if (!method_die_offsets.empty())
- {
- DWARFDebugInfo* debug_info = DebugInfo();
-
- DWARFCompileUnit* method_cu = NULL;
- const size_t num_matches = method_die_offsets.size();
- for (size_t i=0; i<num_matches; ++i)
- {
- const dw_offset_t die_offset = method_die_offsets[i];
- DWARFDebugInfoEntry *method_die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &method_cu);
-
- if (method_die)
- ResolveType (method_cu, method_die);
- else
- {
- if (m_using_apple_tables)
- {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_objc accelerator table had bad die 0x%8.8x for '%s')\n",
- die_offset, class_name.GetCString());
- }
- }
- }
- }
-
- 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)
- clang_type.SetTagTypeKind (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.
- clang_type.SetDefaultAccessForRecordFields (eAccessPrivate,
- &member_accessibilities.front(),
- member_accessibilities.size());
- }
-
- if (!base_classes.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.SetBaseClassesForClassType()
- bool base_class_error = false;
- for (auto &base_class : base_classes)
- {
- clang::TypeSourceInfo *type_source_info = base_class->getTypeSourceInfo();
- if (type_source_info)
- {
- ClangASTType base_class_type (GetClangASTContext().getASTContext(), type_source_info->getType());
- if (base_class_type.GetCompleteType() == false)
- {
- if (!base_class_error)
- {
- GetObjectFile()->GetModule()->ReportError ("DWARF DIE at 0x%8.8x for class '%s' has a base class '%s' 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(),
- die->GetName(this, dwarf_cu),
- base_class_type.GetTypeName().GetCString(),
- sc.comp_unit ? sc.comp_unit->GetPath().c_str() : "the source file");
- }
- // 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.SetBaseClassesForClassType()"
- // 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.
- base_class_type.StartTagDeclarationDefinition ();
- base_class_type.CompleteTagDeclarationDefinition ();
- }
- }
- }
- clang_type.SetBaseClassesForClassType (&base_classes.front(),
- base_classes.size());
-
- // Clang will copy each CXXBaseSpecifier in "base_classes"
- // so we have to free them all.
- ClangASTType::DeleteBaseClassSpecifiers (&base_classes.front(),
- base_classes.size());
- }
- }
- }
-
- clang_type.BuildIndirectFields ();
- clang_type.CompleteTagDeclarationDefinition ();
-
- if (!layout_info.field_offsets.empty() ||
- !layout_info.base_offsets.empty() ||
- !layout_info.vbase_offsets.empty() )
- {
- if (type)
- layout_info.bit_size = type->GetByteSize() * 8;
- if (layout_info.bit_size == 0)
- layout_info.bit_size = die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_byte_size, 0) * 8;
-
- clang::CXXRecordDecl *record_decl = clang_type.GetAsCXXRecordDecl();
- if (record_decl)
- {
- if (log)
- {
- GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (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)
- {
- GetObjectFile()->GetModule()->LogMessage(
- log, "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (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)
- {
- GetObjectFile()->GetModule()->LogMessage(
- log, "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (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)
- {
- GetObjectFile()->GetModule()->LogMessage(
- log, "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (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());
- }
- }
- }
- m_record_decl_to_layout_map.insert(std::make_pair(record_decl, layout_info));
- }
- }
- }
-
- return (bool)clang_type;
-
- case DW_TAG_enumeration_type:
- clang_type.StartTagDeclarationDefinition ();
- if (die->HasChildren())
- {
- SymbolContext sc(GetCompUnitForDWARFCompUnit(dwarf_cu));
- bool is_signed = false;
- clang_type.IsIntegerType(is_signed);
- ParseChildEnumerators(sc, clang_type, is_signed, type->GetByteSize(), dwarf_cu, die);
- }
- clang_type.CompleteTagDeclarationDefinition ();
- return (bool)clang_type;
-
- default:
- assert(false && "not a forward clang type decl!");
- break;
- }
+ assert (compiler_type);
+ DWARFASTParser *dwarf_ast = dwarf_die.GetDWARFParser();
+ if (dwarf_ast)
+ return dwarf_ast->CompleteTypeFromDWARF (dwarf_die, type, compiler_type);
return false;
}
Type*
-SymbolFileDWARF::ResolveType (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* type_die, bool assert_not_being_parsed)
+SymbolFileDWARF::ResolveType (const DWARFDIE &die, bool assert_not_being_parsed, bool resolve_function_context)
{
- if (type_die != NULL)
+ if (die)
{
- Type *type = m_die_to_type.lookup (type_die);
+ Type *type = GetDIEToType().lookup (die.GetDIE());
if (type == NULL)
- type = GetTypeForDIE (dwarf_cu, type_die).get();
+ type = GetTypeForDIE (die, resolve_function_context).get();
if (assert_not_being_parsed)
{
@@ -2829,15 +1647,15 @@ SymbolFileDWARF::ResolveType (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEn
return type;
GetObjectFile()->GetModule()->ReportError ("Parsing a die that is being parsed die: 0x%8.8x: %s %s",
- type_die->GetOffset(),
- DW_TAG_value_to_name(type_die->Tag()),
- type_die->GetName(this, dwarf_cu));
+ die.GetOffset(),
+ die.GetTagAsCString(),
+ die.GetName());
}
else
return type;
}
- return NULL;
+ return nullptr;
}
CompileUnit*
@@ -2853,26 +1671,60 @@ SymbolFileDWARF::GetCompUnitForDWARFCompUnit (DWARFCompileUnit* dwarf_cu, uint32
return (CompileUnit*)dwarf_cu->GetUserData();
}
+size_t
+SymbolFileDWARF::GetObjCMethodDIEOffsets (ConstString class_name, DIEArray &method_die_offsets)
+{
+ method_die_offsets.clear();
+ if (m_using_apple_tables)
+ {
+ if (m_apple_objc_ap.get())
+ m_apple_objc_ap->FindByName(class_name.GetCString(), method_die_offsets);
+ }
+ else
+ {
+ if (!m_indexed)
+ Index ();
+
+ m_objc_class_selectors_index.Find (class_name, method_die_offsets);
+ }
+ return method_die_offsets.size();
+}
+
bool
-SymbolFileDWARF::GetFunction (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* func_die, SymbolContext& sc)
+SymbolFileDWARF::GetFunction (const DWARFDIE &die, SymbolContext& sc)
{
sc.Clear(false);
- // Check if the symbol vendor already knows about this compile unit?
- sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX);
- sc.function = sc.comp_unit->FindFunctionByUID (MakeUserID(func_die->GetOffset())).get();
- if (sc.function == NULL)
- sc.function = ParseCompileUnitFunction(sc, dwarf_cu, func_die);
-
- if (sc.function)
- {
- sc.module_sp = sc.function->CalculateSymbolContextModule();
- return true;
+ if (die)
+ {
+ // Check if the symbol vendor already knows about this compile unit?
+ sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX);
+
+ sc.function = sc.comp_unit->FindFunctionByUID (die.GetID()).get();
+ if (sc.function == NULL)
+ sc.function = ParseCompileUnitFunction(sc, die);
+
+ if (sc.function)
+ {
+ sc.module_sp = sc.function->CalculateSymbolContextModule();
+ return true;
+ }
}
return false;
}
+lldb::ModuleSP
+SymbolFileDWARF::GetDWOModule (ConstString name)
+{
+ UpdateExternalModuleListIfNeeded();
+ const auto &pos = m_external_type_modules.find(name);
+ if (pos != m_external_type_modules.end())
+ return pos->second;
+ else
+ return lldb::ModuleSP();
+}
+
void
SymbolFileDWARF::UpdateExternalModuleListIfNeeded()
{
@@ -2881,47 +1733,33 @@ SymbolFileDWARF::UpdateExternalModuleListIfNeeded()
m_fetched_external_modules = true;
DWARFDebugInfo * debug_info = DebugInfo();
- debug_info->GetNumCompileUnits();
-
+
const uint32_t num_compile_units = GetNumCompileUnits();
for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
{
DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
- const DWARFDebugInfoEntry *die = dwarf_cu->GetCompileUnitDIEOnly();
- if (die && die->HasChildren() == false)
+ const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly();
+ if (die && die.HasChildren() == false)
{
- const uint64_t name_strp = die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_name, UINT64_MAX);
- const uint64_t dwo_path_strp = die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_GNU_dwo_name, UINT64_MAX);
-
- if (name_strp != UINT64_MAX)
+ const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr);
+
+ if (name)
{
- if (m_external_type_modules.find(dwo_path_strp) == m_external_type_modules.end())
+ ConstString const_name(name);
+ if (m_external_type_modules.find(const_name) == m_external_type_modules.end())
{
- const char *name = get_debug_str_data().PeekCStr(name_strp);
- const char *dwo_path = get_debug_str_data().PeekCStr(dwo_path_strp);
- if (name || dwo_path)
+ ModuleSP module_sp;
+ const char *dwo_path = die.GetAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr);
+ if (dwo_path)
{
- ModuleSP module_sp;
- if (dwo_path)
- {
- ModuleSpec dwo_module_spec;
- dwo_module_spec.GetFileSpec().SetFile(dwo_path, false);
- dwo_module_spec.GetArchitecture() = m_obj_file->GetModule()->GetArchitecture();
- //printf ("Loading dwo = '%s'\n", dwo_path);
- Error error = ModuleList::GetSharedModule (dwo_module_spec, module_sp, NULL, NULL, NULL);
- }
-
- if (dwo_path_strp != LLDB_INVALID_UID)
- {
- m_external_type_modules[dwo_path_strp] = ClangModuleInfo { ConstString(name), module_sp };
- }
- else
- {
- // This hack should be removed promptly once clang emits both.
- m_external_type_modules[name_strp] = ClangModuleInfo { ConstString(name), module_sp };
- }
+ ModuleSpec dwo_module_spec;
+ dwo_module_spec.GetFileSpec().SetFile(dwo_path, false);
+ dwo_module_spec.GetArchitecture() = m_obj_file->GetModule()->GetArchitecture();
+ //printf ("Loading dwo = '%s'\n", dwo_path);
+ Error error = ModuleList::GetSharedModule (dwo_module_spec, module_sp, NULL, NULL, NULL);
}
+ m_external_type_modules[const_name] = module_sp;
}
}
}
@@ -3025,7 +1863,7 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_
else
{
uint32_t cu_idx = DW_INVALID_INDEX;
- DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnit(cu_offset, &cu_idx).get();
+ DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnit(cu_offset, &cu_idx);
if (dwarf_cu)
{
sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx);
@@ -3036,22 +1874,16 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_
bool force_check_line_table = false;
if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock))
{
- DWARFDebugInfoEntry *function_die = NULL;
- DWARFDebugInfoEntry *block_die = NULL;
- if (resolve_scope & eSymbolContextBlock)
- {
- dwarf_cu->LookupAddress(file_vm_addr, &function_die, &block_die);
- }
- else
- {
- dwarf_cu->LookupAddress(file_vm_addr, &function_die, NULL);
- }
-
- if (function_die != NULL)
+ DWARFDIE function_die = dwarf_cu->LookupAddress(file_vm_addr);
+ DWARFDIE block_die;
+ if (function_die)
{
- sc.function = sc.comp_unit->FindFunctionByUID (MakeUserID(function_die->GetOffset())).get();
+ sc.function = sc.comp_unit->FindFunctionByUID (function_die.GetID()).get();
if (sc.function == NULL)
- sc.function = ParseCompileUnitFunction(sc, dwarf_cu, function_die);
+ sc.function = ParseCompileUnitFunction(sc, function_die);
+
+ if (sc.function && (resolve_scope & eSymbolContextBlock))
+ block_die = function_die.LookupDeepestBlock(file_vm_addr);
}
else
{
@@ -3072,10 +1904,10 @@ SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_
{
Block& block = sc.function->GetBlock (true);
- if (block_die != NULL)
- sc.block = block.FindBlockByID (MakeUserID(block_die->GetOffset()));
+ if (block_die)
+ sc.block = block.FindBlockByID (block_die.GetID());
else
- sc.block = block.FindBlockByID (MakeUserID(function_die->GetOffset()));
+ sc.block = block.FindBlockByID (function_die.GetID());
if (sc.block)
resolved |= eSymbolContextBlock;
}
@@ -3190,25 +2022,26 @@ SymbolFileDWARF::ResolveSymbolContext(const FileSpec& file_spec, uint32_t line,
const lldb::addr_t file_vm_addr = sc.line_entry.range.GetBaseAddress().GetFileAddress();
if (file_vm_addr != LLDB_INVALID_ADDRESS)
{
- DWARFDebugInfoEntry *function_die = NULL;
- DWARFDebugInfoEntry *block_die = NULL;
- dwarf_cu->LookupAddress(file_vm_addr, &function_die, resolve_scope & eSymbolContextBlock ? &block_die : NULL);
-
- if (function_die != NULL)
+ DWARFDIE function_die = dwarf_cu->LookupAddress(file_vm_addr);
+ DWARFDIE block_die;
+ if (function_die)
{
- sc.function = sc.comp_unit->FindFunctionByUID (MakeUserID(function_die->GetOffset())).get();
+ sc.function = sc.comp_unit->FindFunctionByUID (function_die.GetID()).get();
if (sc.function == NULL)
- sc.function = ParseCompileUnitFunction(sc, dwarf_cu, function_die);
+ sc.function = ParseCompileUnitFunction(sc, function_die);
+
+ if (sc.function && (resolve_scope & eSymbolContextBlock))
+ block_die = function_die.LookupDeepestBlock(file_vm_addr);
}
if (sc.function != NULL)
{
Block& block = sc.function->GetBlock (true);
- if (block_die != NULL)
- sc.block = block.FindBlockByID (MakeUserID(block_die->GetOffset()));
- else if (function_die != NULL)
- sc.block = block.FindBlockByID (MakeUserID(function_die->GetOffset()));
+ if (block_die)
+ sc.block = block.FindBlockByID (block_die.GetID());
+ else if (function_die)
+ sc.block = block.FindBlockByID (function_die.GetID());
}
}
}
@@ -3255,38 +2088,77 @@ SymbolFileDWARF::Index ()
DWARFDebugInfo* debug_info = DebugInfo();
if (debug_info)
{
- uint32_t cu_idx = 0;
const uint32_t num_compile_units = GetNumCompileUnits();
- for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
+ std::vector<NameToDIE> function_basename_index(num_compile_units);
+ std::vector<NameToDIE> function_fullname_index(num_compile_units);
+ std::vector<NameToDIE> function_method_index(num_compile_units);
+ std::vector<NameToDIE> function_selector_index(num_compile_units);
+ std::vector<NameToDIE> objc_class_selectors_index(num_compile_units);
+ std::vector<NameToDIE> global_index(num_compile_units);
+ std::vector<NameToDIE> type_index(num_compile_units);
+ std::vector<NameToDIE> namespace_index(num_compile_units);
+
+ auto parser_fn = [this,
+ debug_info,
+ &function_basename_index,
+ &function_fullname_index,
+ &function_method_index,
+ &function_selector_index,
+ &objc_class_selectors_index,
+ &global_index,
+ &type_index,
+ &namespace_index](uint32_t cu_idx)
{
DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+ bool clear_dies = dwarf_cu->ExtractDIEsIfNeeded(false) > 1;
+
+ dwarf_cu->Index(function_basename_index[cu_idx],
+ function_fullname_index[cu_idx],
+ function_method_index[cu_idx],
+ function_selector_index[cu_idx],
+ objc_class_selectors_index[cu_idx],
+ global_index[cu_idx],
+ type_index[cu_idx],
+ namespace_index[cu_idx]);
- bool clear_dies = dwarf_cu->ExtractDIEsIfNeeded (false) > 1;
-
- dwarf_cu->Index (cu_idx,
- m_function_basename_index,
- m_function_fullname_index,
- m_function_method_index,
- m_function_selector_index,
- m_objc_class_selectors_index,
- m_global_index,
- m_type_index,
- m_namespace_index);
-
// Keep memory down by clearing DIEs if this generate function
// caused them to be parsed
if (clear_dies)
- dwarf_cu->ClearDIEs (true);
+ dwarf_cu->ClearDIEs(true);
+
+ return cu_idx;
+ };
+
+ TaskRunner<uint32_t> task_runner;
+ for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
+ task_runner.AddTask(parser_fn, cu_idx);
+
+ while (true)
+ {
+ std::future<uint32_t> f = task_runner.WaitForNextCompletedTask();
+ if (!f.valid())
+ break;
+ uint32_t cu_idx = f.get();
+
+ m_function_basename_index.Append(function_basename_index[cu_idx]);
+ m_function_fullname_index.Append(function_fullname_index[cu_idx]);
+ m_function_method_index.Append(function_method_index[cu_idx]);
+ m_function_selector_index.Append(function_selector_index[cu_idx]);
+ m_objc_class_selectors_index.Append(objc_class_selectors_index[cu_idx]);
+ m_global_index.Append(global_index[cu_idx]);
+ m_type_index.Append(type_index[cu_idx]);
+ m_namespace_index.Append(namespace_index[cu_idx]);
}
-
- m_function_basename_index.Finalize();
- m_function_fullname_index.Finalize();
- m_function_method_index.Finalize();
- m_function_selector_index.Finalize();
- m_objc_class_selectors_index.Finalize();
- m_global_index.Finalize();
- m_type_index.Finalize();
- m_namespace_index.Finalize();
+
+ TaskPool::RunTasks(
+ [&]() { m_function_basename_index.Finalize(); },
+ [&]() { m_function_fullname_index.Finalize(); },
+ [&]() { m_function_method_index.Finalize(); },
+ [&]() { m_function_selector_index.Finalize(); },
+ [&]() { m_objc_class_selectors_index.Finalize(); },
+ [&]() { m_global_index.Finalize(); },
+ [&]() { m_type_index.Finalize(); },
+ [&]() { m_namespace_index.Finalize(); });
#if defined (ENABLE_DEBUG_PRINTF)
StreamFile s(stdout, false);
@@ -3299,30 +2171,26 @@ SymbolFileDWARF::Index ()
s.Printf("\nObjective C class selectors:\n"); m_objc_class_selectors_index.Dump (&s);
s.Printf("\nGlobals and statics:\n"); m_global_index.Dump (&s);
s.Printf("\nTypes:\n"); m_type_index.Dump (&s);
- s.Printf("\nNamepaces:\n"); m_namespace_index.Dump (&s);
+ s.Printf("\nNamespaces:\n") m_namespace_index.Dump (&s);
#endif
}
}
bool
-SymbolFileDWARF::NamespaceDeclMatchesThisSymbolFile (const ClangNamespaceDecl *namespace_decl)
+SymbolFileDWARF::DeclContextMatchesThisSymbolFile (const lldb_private::CompilerDeclContext *decl_ctx)
{
- if (namespace_decl == NULL)
+ if (decl_ctx == nullptr || !decl_ctx->IsValid())
{
// Invalid namespace decl which means we aren't matching only things
// in this symbol file, so return true to indicate it matches this
// symbol file.
return true;
}
-
- clang::ASTContext *namespace_ast = namespace_decl->GetASTContext();
-
- if (namespace_ast == NULL)
- return true; // No AST in the "namespace_decl", return true since it
- // could then match any symbol file, including this one
- if (namespace_ast == GetClangASTContext().getASTContext())
- return true; // The ASTs match, return true
+ TypeSystem *decl_ctx_type_system = decl_ctx->GetTypeSystem();
+ TypeSystem *type_system = GetTypeSystemForLanguage(decl_ctx_type_system->GetMinimumLanguage(nullptr));
+ if (decl_ctx_type_system == type_system)
+ return true; // The type systems match, return true
// The namespace AST was valid, and it does not match...
Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
@@ -3333,66 +2201,19 @@ SymbolFileDWARF::NamespaceDeclMatchesThisSymbolFile (const ClangNamespaceDecl *n
return false;
}
-bool
-SymbolFileDWARF::DIEIsInNamespace (const ClangNamespaceDecl *namespace_decl,
- DWARFCompileUnit* cu,
- const DWARFDebugInfoEntry* die)
-{
- // No namespace specified, so the answer is
- if (namespace_decl == NULL)
- return true;
-
- Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
-
- const DWARFDebugInfoEntry *decl_ctx_die = NULL;
- clang::DeclContext *die_clang_decl_ctx = GetClangDeclContextContainingDIE (cu, die, &decl_ctx_die);
- if (decl_ctx_die)
- {
- clang::NamespaceDecl *clang_namespace_decl = namespace_decl->GetNamespaceDecl();
-
- if (clang_namespace_decl)
- {
- if (decl_ctx_die->Tag() != DW_TAG_namespace)
- {
- if (log)
- GetObjectFile()->GetModule()->LogMessage(log, "Found a match, but its parent is not a namespace");
- return false;
- }
-
- if (clang_namespace_decl == die_clang_decl_ctx)
- return true;
- else
- return false;
- }
- else
- {
- // We have a namespace_decl that was not NULL but it contained
- // a NULL "clang::NamespaceDecl", so this means the global namespace
- // So as long the contained decl context DIE isn't a namespace
- // we should be ok.
- if (decl_ctx_die->Tag() != DW_TAG_namespace)
- return true;
- }
- }
-
- if (log)
- GetObjectFile()->GetModule()->LogMessage(log, "Found a match, but its parent doesn't exist");
-
- return false;
-}
uint32_t
-SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables)
+SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, VariableList& variables)
{
Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
if (log)
GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", namespace_decl=%p, append=%u, max_matches=%u, variables)",
+ "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", parent_decl_ctx=%p, append=%u, max_matches=%u, variables)",
name.GetCString(),
- static_cast<const void*>(namespace_decl),
+ static_cast<const void*>(parent_decl_ctx),
append, max_matches);
- if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl))
+ if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
return 0;
DWARFDebugInfo* info = DebugInfo();
@@ -3417,7 +2238,7 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat
llvm::StringRef basename;
llvm::StringRef context;
- if (!CPPLanguageRuntime::ExtractContextAndIdentifier(name_cstr, context, basename))
+ if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, basename))
basename = name_cstr;
m_apple_names_ap->FindByName (basename.data(), die_offsets);
@@ -3440,17 +2261,15 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat
assert (sc.module_sp);
DWARFDebugInfo* debug_info = DebugInfo();
- DWARFCompileUnit* dwarf_cu = NULL;
- const DWARFDebugInfoEntry* die = NULL;
bool done = false;
for (size_t i=0; i<num_die_matches && !done; ++i)
{
- const dw_offset_t die_offset = die_offsets[i];
- die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE die = debug_info->GetDIE (die_ref);
if (die)
{
- switch (die->Tag())
+ switch (die.Tag())
{
default:
case DW_TAG_subprogram:
@@ -3461,12 +2280,20 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat
case DW_TAG_variable:
{
- sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX);
+ sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX);
- if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
- continue;
+ if (parent_decl_ctx)
+ {
+ DWARFASTParser *dwarf_ast = die.GetDWARFParser();
+ if (dwarf_ast)
+ {
+ CompilerDeclContext actual_parent_decl_ctx = dwarf_ast->GetDeclContextContainingUIDFromDWARF (die);
+ if (!actual_parent_decl_ctx || actual_parent_decl_ctx != *parent_decl_ctx)
+ continue;
+ }
+ }
- ParseVariables(sc, dwarf_cu, LLDB_INVALID_ADDRESS, die, false, false, &variables);
+ ParseVariables(sc, die, LLDB_INVALID_ADDRESS, false, false, &variables);
if (variables.GetSize() - original_size >= max_matches)
done = true;
@@ -3479,7 +2306,7 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat
if (m_using_apple_tables)
{
GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')\n",
- die_offset, name.GetCString());
+ die_ref.die_offset, name.GetCString());
}
}
}
@@ -3490,9 +2317,9 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_privat
if (log && num_matches > 0)
{
GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", namespace_decl=%p, append=%u, max_matches=%u, variables) => %u",
+ "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", parent_decl_ctx=%p, append=%u, max_matches=%u, variables) => %u",
name.GetCString(),
- static_cast<const void*>(namespace_decl),
+ static_cast<const void*>(parent_decl_ctx),
append, max_matches,
num_matches);
}
@@ -3525,7 +2352,7 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append
const uint32_t original_size = variables.GetSize();
DIEArray die_offsets;
-
+
if (m_using_apple_tables)
{
if (m_apple_names_ap.get())
@@ -3548,22 +2375,20 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append
sc.module_sp = m_obj_file->GetModule();
assert (sc.module_sp);
- DWARFCompileUnit* dwarf_cu = NULL;
- const DWARFDebugInfoEntry* die = NULL;
const size_t num_matches = die_offsets.size();
if (num_matches)
{
DWARFDebugInfo* debug_info = DebugInfo();
for (size_t i=0; i<num_matches; ++i)
{
- const dw_offset_t die_offset = die_offsets[i];
- die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE die = debug_info->GetDIE (die_ref);
if (die)
{
- sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX);
+ sc.comp_unit = GetCompUnitForDWARFCompUnit(die.GetCU(), UINT32_MAX);
- ParseVariables(sc, dwarf_cu, LLDB_INVALID_ADDRESS, die, false, false, &variables);
+ ParseVariables(sc, die, LLDB_INVALID_ADDRESS, false, false, &variables);
if (variables.GetSize() - original_size >= max_matches)
break;
@@ -3573,7 +2398,7 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append
if (m_using_apple_tables)
{
GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for regex '%s')\n",
- die_offset, regex.GetText());
+ die_ref.die_offset, regex.GetText());
}
}
}
@@ -3585,53 +2410,59 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append
bool
-SymbolFileDWARF::ResolveFunction (dw_offset_t die_offset,
- DWARFCompileUnit *&dwarf_cu,
+SymbolFileDWARF::ResolveFunction (const DIERef& die_ref,
bool include_inlines,
SymbolContextList& sc_list)
{
- const DWARFDebugInfoEntry *die = DebugInfo()->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
- return ResolveFunction (dwarf_cu, die, include_inlines, sc_list);
+ DWARFDIE die = DebugInfo()->GetDIE (die_ref);
+ return ResolveFunction (die, include_inlines, sc_list);
}
bool
-SymbolFileDWARF::ResolveFunction (DWARFCompileUnit *cu,
- const DWARFDebugInfoEntry *die,
+SymbolFileDWARF::ResolveFunction (const DWARFDIE &orig_die,
bool include_inlines,
SymbolContextList& sc_list)
{
SymbolContext sc;
- if (die == NULL)
+ if (!orig_die)
return false;
// If we were passed a die that is not a function, just return false...
- if (! (die->Tag() == DW_TAG_subprogram || (include_inlines && die->Tag() == DW_TAG_inlined_subroutine)))
+ if (!(orig_die.Tag() == DW_TAG_subprogram || (include_inlines && orig_die.Tag() == DW_TAG_inlined_subroutine)))
return false;
-
- const DWARFDebugInfoEntry* inlined_die = NULL;
- if (die->Tag() == DW_TAG_inlined_subroutine)
+
+ DWARFDIE die = orig_die;
+ DWARFDIE inlined_die;
+ if (die.Tag() == DW_TAG_inlined_subroutine)
{
inlined_die = die;
- while ((die = die->GetParent()) != NULL)
+ while (1)
{
- if (die->Tag() == DW_TAG_subprogram)
+ die = die.GetParent();
+
+ if (die)
+ {
+ if (die.Tag() == DW_TAG_subprogram)
+ break;
+ }
+ else
break;
}
}
- assert (die && die->Tag() == DW_TAG_subprogram);
- if (GetFunction (cu, die, sc))
+ assert (die && die.Tag() == DW_TAG_subprogram);
+ if (GetFunction (die, sc))
{
Address addr;
// Parse all blocks if needed
if (inlined_die)
{
Block &function_block = sc.function->GetBlock (true);
- sc.block = function_block.FindBlockByID (MakeUserID(inlined_die->GetOffset()));
+ sc.block = function_block.FindBlockByID (inlined_die.GetID());
if (sc.block == NULL)
- sc.block = function_block.FindBlockByID (inlined_die->GetOffset());
+ sc.block = function_block.FindBlockByID (inlined_die.GetOffset());
if (sc.block == NULL || sc.block->GetStartAddress (addr) == false)
addr.Clear();
}
@@ -3702,131 +2533,37 @@ SymbolFileDWARF::ParseFunctions (const DIEArray &die_offsets,
const size_t num_matches = die_offsets.size();
if (num_matches)
{
- DWARFCompileUnit* dwarf_cu = NULL;
for (size_t i=0; i<num_matches; ++i)
- {
- const dw_offset_t die_offset = die_offsets[i];
- ResolveFunction (die_offset, dwarf_cu, include_inlines, sc_list);
- }
+ ResolveFunction (die_offsets[i], include_inlines, sc_list);
}
}
bool
-SymbolFileDWARF::FunctionDieMatchesPartialName (const DWARFDebugInfoEntry* die,
- const DWARFCompileUnit *dwarf_cu,
- uint32_t name_type_mask,
- const char *partial_name,
- const char *base_name_start,
- const char *base_name_end)
+SymbolFileDWARF::DIEInDeclContext (const CompilerDeclContext *decl_ctx,
+ const DWARFDIE &die)
{
- // If we are looking only for methods, throw away all the ones that are or aren't in C++ classes:
- if (name_type_mask == eFunctionNameTypeMethod || name_type_mask == eFunctionNameTypeBase)
- {
- clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIEOffset(die->GetOffset());
- if (!containing_decl_ctx)
- return false;
-
- bool is_cxx_method = DeclKindIsCXXClass(containing_decl_ctx->getDeclKind());
-
- if (name_type_mask == eFunctionNameTypeMethod)
- {
- if (is_cxx_method == false)
- return false;
- }
-
- if (name_type_mask == eFunctionNameTypeBase)
- {
- if (is_cxx_method == true)
- return false;
- }
- }
+ // If we have no parent decl context to match this DIE matches, and if the parent
+ // decl context isn't valid, we aren't trying to look for any particular decl
+ // context so any die matches.
+ if (decl_ctx == nullptr || !decl_ctx->IsValid())
+ return true;
- // Now we need to check whether the name we got back for this type matches the extra specifications
- // that were in the name we're looking up:
- if (base_name_start != partial_name || *base_name_end != '\0')
+ if (die)
{
- // First see if the stuff to the left matches the full name. To do that let's see if
- // we can pull out the mips linkage name attribute:
-
- Mangled best_name;
- DWARFDebugInfoEntry::Attributes attributes;
- DWARFFormValue form_value;
- die->GetAttributes(this, dwarf_cu, NULL, attributes);
- uint32_t idx = attributes.FindAttributeIndex(DW_AT_MIPS_linkage_name);
- if (idx == UINT32_MAX)
- idx = attributes.FindAttributeIndex(DW_AT_linkage_name);
- if (idx != UINT32_MAX)
+ DWARFASTParser *dwarf_ast = die.GetDWARFParser();
+ if (dwarf_ast)
{
- if (attributes.ExtractFormValueAtIndex(this, idx, form_value))
- {
- const char *mangled_name = form_value.AsCString(&get_debug_str_data());
- if (mangled_name)
- best_name.SetValue (ConstString(mangled_name), true);
- }
- }
-
- if (!best_name)
- {
- idx = attributes.FindAttributeIndex(DW_AT_name);
- if (idx != UINT32_MAX && attributes.ExtractFormValueAtIndex(this, idx, form_value))
- {
- const char *name = form_value.AsCString(&get_debug_str_data());
- best_name.SetValue (ConstString(name), false);
- }
- }
-
- const LanguageType cu_language = const_cast<DWARFCompileUnit *>(dwarf_cu)->GetLanguageType();
- if (best_name.GetDemangledName(cu_language))
- {
- const char *demangled = best_name.GetDemangledName(cu_language).GetCString();
- if (demangled)
- {
- std::string name_no_parens(partial_name, base_name_end - partial_name);
- const char *partial_in_demangled = strstr (demangled, name_no_parens.c_str());
- if (partial_in_demangled == NULL)
- return false;
- else
- {
- // Sort out the case where our name is something like "Process::Destroy" and the match is
- // "SBProcess::Destroy" - that shouldn't be a match. We should really always match on
- // namespace boundaries...
-
- if (partial_name[0] == ':' && partial_name[1] == ':')
- {
- // The partial name was already on a namespace boundary so all matches are good.
- return true;
- }
- else if (partial_in_demangled == demangled)
- {
- // They both start the same, so this is an good match.
- return true;
- }
- else
- {
- if (partial_in_demangled - demangled == 1)
- {
- // Only one character difference, can't be a namespace boundary...
- return false;
- }
- else if (*(partial_in_demangled - 1) == ':' && *(partial_in_demangled - 2) == ':')
- {
- // We are on a namespace boundary, so this is also good.
- return true;
- }
- else
- return false;
- }
- }
- }
+ CompilerDeclContext actual_decl_ctx = dwarf_ast->GetDeclContextContainingUIDFromDWARF (die);
+ if (actual_decl_ctx)
+ return actual_decl_ctx == *decl_ctx;
}
}
-
- return true;
+ return false;
}
uint32_t
-SymbolFileDWARF::FindFunctions (const ConstString &name,
- const lldb_private::ClangNamespaceDecl *namespace_decl,
+SymbolFileDWARF::FindFunctions (const ConstString &name,
+ const CompilerDeclContext *parent_decl_ctx,
uint32_t name_type_mask,
bool include_inlines,
bool append,
@@ -3854,7 +2591,7 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
if (!append)
sc_list.Clear();
- if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl))
+ if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
return 0;
// If name is empty then we won't find anything.
@@ -3872,7 +2609,6 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
if (info == NULL)
return 0;
- DWARFCompileUnit *dwarf_cu = NULL;
std::set<const DWARFDebugInfoEntry *> resolved_dies;
if (m_using_apple_tables)
{
@@ -3891,30 +2627,30 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets);
for (uint32_t i = 0; i < num_matches; i++)
{
- const dw_offset_t die_offset = die_offsets[i];
- const DWARFDebugInfoEntry *die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE die = info->GetDIE (die_ref);
if (die)
{
- if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
- continue;
-
- if (resolved_dies.find(die) == resolved_dies.end())
+ if (!DIEInDeclContext(parent_decl_ctx, die))
+ continue; // The containing decl contexts don't match
+
+ if (resolved_dies.find(die.GetDIE()) == resolved_dies.end())
{
- if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list))
- resolved_dies.insert(die);
+ if (ResolveFunction (die, include_inlines, sc_list))
+ resolved_dies.insert(die.GetDIE());
}
}
else
{
GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')",
- die_offset, name_cstr);
+ die_ref.die_offset, name_cstr);
}
}
}
if (name_type_mask & eFunctionNameTypeSelector)
{
- if (namespace_decl && *namespace_decl)
+ if (parent_decl_ctx && parent_decl_ctx->IsValid())
return 0; // no selectors in namespaces
num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets);
@@ -3923,30 +2659,30 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
for (uint32_t i = 0; i < num_matches; i++)
{
- const dw_offset_t die_offset = die_offsets[i];
- const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE die = info->GetDIE (die_ref);
if (die)
{
- const char *die_name = die->GetName(this, dwarf_cu);
- if (ObjCLanguageRuntime::IsPossibleObjCMethodName(die_name))
+ const char *die_name = die.GetName();
+ if (ObjCLanguage::IsPossibleObjCMethodName(die_name))
{
- if (resolved_dies.find(die) == resolved_dies.end())
+ if (resolved_dies.find(die.GetDIE()) == resolved_dies.end())
{
- if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list))
- resolved_dies.insert(die);
+ if (ResolveFunction (die, include_inlines, sc_list))
+ resolved_dies.insert(die.GetDIE());
}
}
}
else
{
GetObjectFile()->GetModule()->ReportError ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')",
- die_offset, name_cstr);
+ die_ref.die_offset, name_cstr);
}
}
die_offsets.clear();
}
- if (((name_type_mask & eFunctionNameTypeMethod) && !namespace_decl) || name_type_mask & eFunctionNameTypeBase)
+ if (((name_type_mask & eFunctionNameTypeMethod) && !parent_decl_ctx) || name_type_mask & eFunctionNameTypeBase)
{
// The apple_names table stores just the "base name" of C++ methods in the table. So we have to
// extract the base name, look that up, and if there is any other information in the name we were
@@ -3957,16 +2693,16 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
for (uint32_t i = 0; i < num_matches; i++)
{
- const dw_offset_t die_offset = die_offsets[i];
- const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE die = info->GetDIE (die_ref);
if (die)
{
- if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
- continue;
+ if (!DIEInDeclContext(parent_decl_ctx, die))
+ continue; // The containing decl contexts don't match
+
// If we get to here, the die is good, and we should add it:
- if (resolved_dies.find(die) == resolved_dies.end())
- if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list))
+ if (resolved_dies.find(die.GetDIE()) == resolved_dies.end() && ResolveFunction (die, include_inlines, sc_list))
{
bool keep_die = true;
if ((name_type_mask & (eFunctionNameTypeBase|eFunctionNameTypeMethod)) != (eFunctionNameTypeBase|eFunctionNameTypeMethod))
@@ -3986,8 +2722,8 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
if (type)
{
- clang::DeclContext* decl_ctx = GetClangDeclContextContainingTypeUID (type->GetID());
- if (decl_ctx->isRecord())
+ CompilerDeclContext decl_ctx = GetDeclContextContainingUID (type->GetID());
+ if (decl_ctx.IsStructUnionOrClass())
{
if (name_type_mask & eFunctionNameTypeBase)
{
@@ -4007,19 +2743,19 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
else
{
GetObjectFile()->GetModule()->ReportWarning ("function at die offset 0x%8.8x had no function type",
- die_offset);
+ die_ref.die_offset);
}
}
}
}
if (keep_die)
- resolved_dies.insert(die);
+ resolved_dies.insert(die.GetDIE());
}
}
else
{
GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')",
- die_offset, name_cstr);
+ die_ref.die_offset, name_cstr);
}
}
die_offsets.clear();
@@ -4046,10 +2782,10 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
// TODO: The arch in the object file isn't correct for MSVC
// binaries on windows, we should find a way to make it
// correct and handle those symbols as well.
- if (sc_list.GetSize() == 0)
+ if (sc_list.GetSize() == original_size)
{
ArchSpec arch;
- if (!namespace_decl &&
+ if (!parent_decl_ctx &&
GetObjectFile()->GetArchitecture(arch) &&
(arch.GetTriple().isOSFreeBSD() || arch.GetTriple().isOSLinux() ||
arch.GetMachine() == llvm::Triple::hexagon))
@@ -4076,24 +2812,22 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
}
}
DIEArray die_offsets;
- DWARFCompileUnit *dwarf_cu = NULL;
-
if (name_type_mask & eFunctionNameTypeBase)
{
uint32_t num_base = m_function_basename_index.Find(name, die_offsets);
for (uint32_t i = 0; i < num_base; i++)
{
- const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offsets[i], &dwarf_cu);
+ DWARFDIE die = info->GetDIE (die_offsets[i]);
if (die)
{
- if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
- continue;
-
+ if (!DIEInDeclContext(parent_decl_ctx, die))
+ continue; // The containing decl contexts don't match
+
// If we get to here, the die is good, and we should add it:
- if (resolved_dies.find(die) == resolved_dies.end())
+ if (resolved_dies.find(die.GetDIE()) == resolved_dies.end())
{
- if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list))
- resolved_dies.insert(die);
+ if (ResolveFunction (die, include_inlines, sc_list))
+ resolved_dies.insert(die.GetDIE());
}
}
}
@@ -4102,21 +2836,21 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
if (name_type_mask & eFunctionNameTypeMethod)
{
- if (namespace_decl && *namespace_decl)
+ if (parent_decl_ctx && parent_decl_ctx->IsValid())
return 0; // no methods in namespaces
uint32_t num_base = m_function_method_index.Find(name, die_offsets);
{
for (uint32_t i = 0; i < num_base; i++)
{
- const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offsets[i], &dwarf_cu);
+ DWARFDIE die = info->GetDIE (die_offsets[i]);
if (die)
{
// If we get to here, the die is good, and we should add it:
- if (resolved_dies.find(die) == resolved_dies.end())
+ if (resolved_dies.find(die.GetDIE()) == resolved_dies.end())
{
- if (ResolveFunction (dwarf_cu, die, include_inlines, sc_list))
- resolved_dies.insert(die);
+ if (ResolveFunction (die, include_inlines, sc_list))
+ resolved_dies.insert(die.GetDIE());
}
}
}
@@ -4124,7 +2858,7 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
die_offsets.clear();
}
- if ((name_type_mask & eFunctionNameTypeSelector) && (!namespace_decl || !*namespace_decl))
+ if ((name_type_mask & eFunctionNameTypeSelector) && (!parent_decl_ctx || !parent_decl_ctx->IsValid()))
{
FindFunctions (name, m_function_selector_index, include_inlines, sc_list);
}
@@ -4196,10 +2930,10 @@ SymbolFileDWARF::FindFunctions(const RegularExpression& regex, bool include_inli
uint32_t
SymbolFileDWARF::FindTypes (const SymbolContext& sc,
const ConstString &name,
- const lldb_private::ClangNamespaceDecl *namespace_decl,
+ const CompilerDeclContext *parent_decl_ctx,
bool append,
uint32_t max_matches,
- TypeList& types)
+ TypeMap& types)
{
DWARFDebugInfo* info = DebugInfo();
if (info == NULL)
@@ -4209,16 +2943,16 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
if (log)
{
- if (namespace_decl)
+ if (parent_decl_ctx)
GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(%p) \"%s\", append=%u, max_matches=%u, type_list)",
+ "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = %p (\"%s\"), append=%u, max_matches=%u, type_list)",
name.GetCString(),
- static_cast<void*>(namespace_decl->GetNamespaceDecl()),
- namespace_decl->GetQualifiedName().c_str(),
+ static_cast<const void*>(parent_decl_ctx),
+ parent_decl_ctx->GetName().AsCString("<NULL>"),
append, max_matches);
else
GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(NULL), append=%u, max_matches=%u, type_list)",
+ "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = NULL, append=%u, max_matches=%u, type_list)",
name.GetCString(), append,
max_matches);
}
@@ -4227,7 +2961,7 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
if (!append)
types.Clear();
- if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl))
+ if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
return 0;
DIEArray die_offsets;
@@ -4253,20 +2987,18 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
if (num_die_matches)
{
const uint32_t initial_types_size = types.GetSize();
- DWARFCompileUnit* dwarf_cu = NULL;
- const DWARFDebugInfoEntry* die = NULL;
DWARFDebugInfo* debug_info = DebugInfo();
for (size_t i=0; i<num_die_matches; ++i)
{
- const dw_offset_t die_offset = die_offsets[i];
- die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE die = debug_info->GetDIE (die_ref);
if (die)
{
- if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
- continue;
+ if (!DIEInDeclContext(parent_decl_ctx, die))
+ continue; // The containing decl contexts don't match
- Type *matching_type = ResolveType (dwarf_cu, die);
+ Type *matching_type = ResolveType (die, true, true);
if (matching_type)
{
// We found a type pointer, now find the shared pointer form our type list
@@ -4280,7 +3012,7 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
if (m_using_apple_tables)
{
GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n",
- die_offset, name.GetCString());
+ die_ref.die_offset, name.GetCString());
}
}
@@ -4288,20 +3020,20 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
const uint32_t num_matches = types.GetSize() - initial_types_size;
if (log && num_matches)
{
- if (namespace_decl)
+ if (parent_decl_ctx)
{
GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(%p) \"%s\", append=%u, max_matches=%u, type_list) => %u",
+ "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = %p (\"%s\"), append=%u, max_matches=%u, type_list) => %u",
name.GetCString(),
- static_cast<void*>(namespace_decl->GetNamespaceDecl()),
- namespace_decl->GetQualifiedName().c_str(),
+ static_cast<const void*>(parent_decl_ctx),
+ parent_decl_ctx->GetName().AsCString("<NULL>"),
append, max_matches,
num_matches);
}
else
{
GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(NULL), append=%u, max_matches=%u, type_list) => %u",
+ "SymbolFileDWARF::FindTypes (sc, name=\"%s\", parent_decl_ctx = NULL, append=%u, max_matches=%u, type_list) => %u",
name.GetCString(),
append, max_matches,
num_matches);
@@ -4309,14 +3041,112 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc,
}
return num_matches;
}
+ else
+ {
+ UpdateExternalModuleListIfNeeded();
+
+ for (const auto &pair : m_external_type_modules)
+ {
+ ModuleSP external_module_sp = pair.second;
+ if (external_module_sp)
+ {
+ SymbolVendor *sym_vendor = external_module_sp->GetSymbolVendor();
+ if (sym_vendor)
+ {
+ const uint32_t num_external_matches = sym_vendor->FindTypes (sc,
+ name,
+ parent_decl_ctx,
+ append,
+ max_matches,
+ types);
+ if (num_external_matches)
+ return num_external_matches;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+size_t
+SymbolFileDWARF::FindTypes (const std::vector<CompilerContext> &context,
+ bool append,
+ TypeMap& types)
+{
+ if (!append)
+ types.Clear();
+
+ if (context.empty())
+ return 0;
+
+ DIEArray die_offsets;
+
+ ConstString name = context.back().name;
+
+ if (m_using_apple_tables)
+ {
+ if (m_apple_types_ap.get())
+ {
+ const char *name_cstr = name.GetCString();
+ m_apple_types_ap->FindByName (name_cstr, die_offsets);
+ }
+ }
+ else
+ {
+ if (!m_indexed)
+ Index ();
+
+ m_type_index.Find (name, die_offsets);
+ }
+
+ const size_t num_die_matches = die_offsets.size();
+
+ if (num_die_matches)
+ {
+ size_t num_matches = 0;
+ DWARFDebugInfo* debug_info = DebugInfo();
+ for (size_t i=0; i<num_die_matches; ++i)
+ {
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE die = debug_info->GetDIE (die_ref);
+
+ if (die)
+ {
+ std::vector<CompilerContext> die_context;
+ die.GetDWOContext(die_context);
+ if (die_context != context)
+ continue;
+
+ Type *matching_type = ResolveType (die, true, true);
+ if (matching_type)
+ {
+ // We found a type pointer, now find the shared pointer form our type list
+ types.InsertUnique (matching_type->shared_from_this());
+ ++num_matches;
+ }
+ }
+ else
+ {
+ if (m_using_apple_tables)
+ {
+ GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n",
+ die_ref.die_offset, name.GetCString());
+ }
+ }
+
+ }
+ return num_matches;
+ }
return 0;
}
-ClangNamespaceDecl
+CompilerDeclContext
SymbolFileDWARF::FindNamespace (const SymbolContext& sc,
const ConstString &name,
- const lldb_private::ClangNamespaceDecl *parent_namespace_decl)
+ const CompilerDeclContext *parent_decl_ctx)
{
Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
@@ -4326,11 +3156,13 @@ SymbolFileDWARF::FindNamespace (const SymbolContext& sc,
"SymbolFileDWARF::FindNamespace (sc, name=\"%s\")",
name.GetCString());
}
-
- if (!NamespaceDeclMatchesThisSymbolFile(parent_namespace_decl))
- return ClangNamespaceDecl();
- ClangNamespaceDecl namespace_decl;
+ CompilerDeclContext namespace_decl_ctx;
+
+ if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
+ return namespace_decl_ctx;
+
+
DWARFDebugInfo* info = DebugInfo();
if (info)
{
@@ -4354,28 +3186,26 @@ SymbolFileDWARF::FindNamespace (const SymbolContext& sc,
m_namespace_index.Find (name, die_offsets);
}
- DWARFCompileUnit* dwarf_cu = NULL;
- const DWARFDebugInfoEntry* die = NULL;
const size_t num_matches = die_offsets.size();
if (num_matches)
{
DWARFDebugInfo* debug_info = DebugInfo();
for (size_t i=0; i<num_matches; ++i)
{
- const dw_offset_t die_offset = die_offsets[i];
- die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
-
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE die = debug_info->GetDIE (die_ref);
+
if (die)
{
- if (parent_namespace_decl && !DIEIsInNamespace (parent_namespace_decl, dwarf_cu, die))
- continue;
+ if (!DIEInDeclContext (parent_decl_ctx, die))
+ continue; // The containing decl contexts don't match
- clang::NamespaceDecl *clang_namespace_decl = ResolveNamespaceDIE (dwarf_cu, die);
- if (clang_namespace_decl)
+ DWARFASTParser *dwarf_ast = die.GetDWARFParser();
+ if (dwarf_ast)
{
- namespace_decl.SetASTContext (GetClangASTContext().getASTContext());
- namespace_decl.SetNamespaceDecl (clang_namespace_decl);
- break;
+ namespace_decl_ctx = dwarf_ast->GetDeclContextForUIDFromDWARF (die);
+ if (namespace_decl_ctx)
+ break;
}
}
else
@@ -4383,421 +3213,50 @@ SymbolFileDWARF::FindNamespace (const SymbolContext& sc,
if (m_using_apple_tables)
{
GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_namespaces accelerator table had bad die 0x%8.8x for '%s')\n",
- die_offset, name.GetCString());
+ die_ref.die_offset, name.GetCString());
}
}
}
}
}
- if (log && namespace_decl.GetNamespaceDecl())
+ if (log && namespace_decl_ctx)
{
GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => clang::NamespaceDecl(%p) \"%s\"",
+ "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => CompilerDeclContext(%p/%p) \"%s\"",
name.GetCString(),
- static_cast<const void*>(namespace_decl.GetNamespaceDecl()),
- namespace_decl.GetQualifiedName().c_str());
- }
-
- return namespace_decl;
-}
-
-uint32_t
-SymbolFileDWARF::FindTypes(std::vector<dw_offset_t> die_offsets, uint32_t max_matches, TypeList& types)
-{
- // Remember how many sc_list are in the list before we search in case
- // we are appending the results to a variable list.
- uint32_t original_size = types.GetSize();
-
- const uint32_t num_die_offsets = die_offsets.size();
- // Parse all of the types we found from the pubtypes matches
- uint32_t i;
- uint32_t num_matches = 0;
- for (i = 0; i < num_die_offsets; ++i)
- {
- Type *matching_type = ResolveTypeUID (die_offsets[i]);
- if (matching_type)
- {
- // We found a type pointer, now find the shared pointer form our type list
- types.InsertUnique (matching_type->shared_from_this());
- ++num_matches;
- if (num_matches >= max_matches)
- break;
- }
- }
-
- // Return the number of variable that were appended to the list
- return types.GetSize() - original_size;
-}
-
-
-size_t
-SymbolFileDWARF::ParseChildParameters (const SymbolContext& sc,
- clang::DeclContext *containing_decl_ctx,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die,
- bool skip_artificial,
- bool &is_static,
- bool &is_variadic,
- std::vector<ClangASTType>& function_param_types,
- std::vector<clang::ParmVarDecl*>& function_param_decls,
- unsigned &type_quals) // ,
- // ClangASTContext::TemplateParameterInfos &template_param_infos))
-{
- if (parent_die == NULL)
- return 0;
-
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
-
- size_t arg_idx = 0;
- const DWARFDebugInfoEntry *die;
- for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
- {
- dw_tag_t tag = die->Tag();
- switch (tag)
- {
- case DW_TAG_formal_parameter:
- {
- DWARFDebugInfoEntry::Attributes attributes;
- const size_t num_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes);
- if (num_attributes > 0)
- {
- const char *name = NULL;
- Declaration decl;
- dw_offset_t param_type_die_offset = DW_INVALID_OFFSET;
- bool is_artificial = false;
- // one of None, Auto, Register, Extern, Static, PrivateExtern
-
- clang::StorageClass storage = clang::SC_None;
- uint32_t i;
- for (i=0; i<num_attributes; ++i)
- {
- const dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
- case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
- case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break;
- case DW_AT_type: param_type_die_offset = form_value.Reference(); break;
- case DW_AT_artificial: is_artificial = form_value.Boolean(); break;
- case DW_AT_location:
- // if (form_value.BlockData())
- // {
- // const DWARFDataExtractor& debug_info_data = debug_info();
- // uint32_t block_length = form_value.Unsigned();
- // DWARFDataExtractor location(debug_info_data, form_value.BlockData() - debug_info_data.GetDataStart(), block_length);
- // }
- // else
- // {
- // }
- // break;
- case DW_AT_const_value:
- case DW_AT_default_value:
- case DW_AT_description:
- case DW_AT_endianity:
- case DW_AT_is_optional:
- case DW_AT_segment:
- case DW_AT_variable_parameter:
- default:
- case DW_AT_abstract_origin:
- case DW_AT_sibling:
- break;
- }
- }
- }
-
- bool skip = false;
- if (skip_artificial)
- {
- if (is_artificial)
- {
- // In order to determine if a C++ member function is
- // "const" we have to look at the const-ness of "this"...
- // Ugly, but that
- if (arg_idx == 0)
- {
- if (DeclKindIsCXXClass(containing_decl_ctx->getDeclKind()))
- {
- // Often times compilers omit the "this" name for the
- // specification DIEs, so we can't rely upon the name
- // being in the formal parameter DIE...
- if (name == NULL || ::strcmp(name, "this")==0)
- {
- Type *this_type = ResolveTypeUID (param_type_die_offset);
- if (this_type)
- {
- uint32_t encoding_mask = this_type->GetEncodingMask();
- if (encoding_mask & Type::eEncodingIsPointerUID)
- {
- is_static = false;
-
- if (encoding_mask & (1u << Type::eEncodingIsConstUID))
- type_quals |= clang::Qualifiers::Const;
- if (encoding_mask & (1u << Type::eEncodingIsVolatileUID))
- type_quals |= clang::Qualifiers::Volatile;
- }
- }
- }
- }
- }
- skip = true;
- }
- else
- {
-
- // HACK: Objective C formal parameters "self" and "_cmd"
- // are not marked as artificial in the DWARF...
- CompileUnit *comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX);
- if (comp_unit)
- {
- switch (comp_unit->GetLanguage())
- {
- case eLanguageTypeObjC:
- case eLanguageTypeObjC_plus_plus:
- if (name && name[0] && (strcmp (name, "self") == 0 || strcmp (name, "_cmd") == 0))
- skip = true;
- break;
- default:
- break;
- }
- }
- }
- }
-
- if (!skip)
- {
- Type *type = ResolveTypeUID(param_type_die_offset);
- if (type)
- {
- function_param_types.push_back (type->GetClangForwardType());
-
- clang::ParmVarDecl *param_var_decl = GetClangASTContext().CreateParameterDeclaration (name,
- type->GetClangForwardType(),
- storage);
- assert(param_var_decl);
- function_param_decls.push_back(param_var_decl);
-
- GetClangASTContext().SetMetadataAsUserID (param_var_decl, MakeUserID(die->GetOffset()));
- }
- }
- }
- arg_idx++;
- }
- break;
-
- case DW_TAG_unspecified_parameters:
- is_variadic = true;
- break;
-
- case DW_TAG_template_type_parameter:
- case DW_TAG_template_value_parameter:
- // The one caller of this was never using the template_param_infos,
- // and the local variable was taking up a large amount of stack space
- // in SymbolFileDWARF::ParseType() so this was removed. If we ever need
- // the template params back, we can add them back.
- // ParseTemplateDIE (dwarf_cu, die, template_param_infos);
- break;
-
- default:
- break;
- }
- }
- return arg_idx;
-}
-
-size_t
-SymbolFileDWARF::ParseChildEnumerators
-(
- const SymbolContext& sc,
- lldb_private::ClangASTType &clang_type,
- bool is_signed,
- uint32_t enumerator_byte_size,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die
-)
-{
- if (parent_die == NULL)
- return 0;
-
- size_t enumerators_added = 0;
- const DWARFDebugInfoEntry *die;
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
-
- for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
- {
- const dw_tag_t tag = die->Tag();
- if (tag == DW_TAG_enumerator)
- {
- DWARFDebugInfoEntry::Attributes attributes;
- const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes);
- if (num_child_attributes > 0)
- {
- const char *name = NULL;
- bool got_value = false;
- int64_t enum_value = 0;
- Declaration decl;
-
- uint32_t i;
- for (i=0; i<num_child_attributes; ++i)
- {
- const dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_const_value:
- got_value = true;
- if (is_signed)
- enum_value = form_value.Signed();
- else
- enum_value = form_value.Unsigned();
- break;
-
- case DW_AT_name:
- name = form_value.AsCString(&get_debug_str_data());
- break;
-
- case DW_AT_description:
- default:
- case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
- case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
- case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_sibling:
- break;
- }
- }
- }
-
- if (name && name[0] && got_value)
- {
- clang_type.AddEnumerationValueToEnumerationType (clang_type.GetEnumerationIntegerType(),
- decl,
- name,
- enum_value,
- enumerator_byte_size * 8);
- ++enumerators_added;
- }
- }
- }
+ static_cast<const void*>(namespace_decl_ctx.GetTypeSystem()),
+ static_cast<const void*>(namespace_decl_ctx.GetOpaqueDeclContext()),
+ namespace_decl_ctx.GetName().AsCString("<NULL>"));
}
- return enumerators_added;
-}
-
-void
-SymbolFileDWARF::ParseChildArrayInfo
-(
- const SymbolContext& sc,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die,
- int64_t& first_index,
- std::vector<uint64_t>& element_orders,
- uint32_t& byte_stride,
- uint32_t& bit_stride
-)
-{
- if (parent_die == NULL)
- return;
-
- const DWARFDebugInfoEntry *die;
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize(), dwarf_cu->IsDWARF64());
- for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
- {
- const dw_tag_t tag = die->Tag();
- switch (tag)
- {
- case DW_TAG_subrange_type:
- {
- DWARFDebugInfoEntry::Attributes attributes;
- const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes);
- if (num_child_attributes > 0)
- {
- uint64_t num_elements = 0;
- uint64_t lower_bound = 0;
- uint64_t upper_bound = 0;
- bool upper_bound_valid = false;
- uint32_t i;
- for (i=0; i<num_child_attributes; ++i)
- {
- const dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_name:
- break;
-
- case DW_AT_count:
- num_elements = form_value.Unsigned();
- break;
-
- case DW_AT_bit_stride:
- bit_stride = form_value.Unsigned();
- break;
-
- case DW_AT_byte_stride:
- byte_stride = form_value.Unsigned();
- break;
-
- case DW_AT_lower_bound:
- lower_bound = form_value.Unsigned();
- break;
-
- case DW_AT_upper_bound:
- upper_bound_valid = true;
- upper_bound = form_value.Unsigned();
- break;
-
- default:
- case DW_AT_abstract_origin:
- case DW_AT_accessibility:
- case DW_AT_allocated:
- case DW_AT_associated:
- case DW_AT_data_location:
- case DW_AT_declaration:
- case DW_AT_description:
- case DW_AT_sibling:
- case DW_AT_threads_scaled:
- case DW_AT_type:
- case DW_AT_visibility:
- break;
- }
- }
- }
- if (num_elements == 0)
- {
- if (upper_bound_valid && upper_bound >= lower_bound)
- num_elements = upper_bound - lower_bound + 1;
- }
-
- element_orders.push_back (num_elements);
- }
- }
- break;
- }
- }
+ return namespace_decl_ctx;
}
TypeSP
-SymbolFileDWARF::GetTypeForDIE (DWARFCompileUnit *dwarf_cu, const DWARFDebugInfoEntry* die)
+SymbolFileDWARF::GetTypeForDIE (const DWARFDIE &die, bool resolve_function_context)
{
TypeSP type_sp;
- if (die != NULL)
+ if (die)
{
- assert(dwarf_cu != NULL);
- Type *type_ptr = m_die_to_type.lookup (die);
+ Type *type_ptr = GetDIEToType().lookup (die.GetDIE());
if (type_ptr == NULL)
{
- CompileUnit* lldb_cu = GetCompUnitForDWARFCompUnit(dwarf_cu);
+ CompileUnit* lldb_cu = GetCompUnitForDWARFCompUnit(die.GetCU());
assert (lldb_cu);
SymbolContext sc(lldb_cu);
- type_sp = ParseType(sc, dwarf_cu, die, NULL);
+ const DWARFDebugInfoEntry* parent_die = die.GetParent().GetDIE();
+ while (parent_die != nullptr)
+ {
+ if (parent_die->Tag() == DW_TAG_subprogram)
+ break;
+ parent_die = parent_die->GetParent();
+ }
+ SymbolContext sc_backup = sc;
+ if (resolve_function_context && parent_die != nullptr && !GetFunction(DWARFDIE(die.GetCU(),parent_die), sc))
+ sc = sc_backup;
+
+ type_sp = ParseType(sc, die, NULL);
}
else if (type_ptr != DIE_IS_BEING_PARSED)
{
@@ -4809,215 +3268,57 @@ SymbolFileDWARF::GetTypeForDIE (DWARFCompileUnit *dwarf_cu, const DWARFDebugInfo
return type_sp;
}
-clang::DeclContext *
-SymbolFileDWARF::GetClangDeclContextContainingDIEOffset (dw_offset_t die_offset)
-{
- if (die_offset != DW_INVALID_OFFSET)
- {
- DWARFCompileUnitSP cu_sp;
- const DWARFDebugInfoEntry* die = DebugInfo()->GetDIEPtr(die_offset, &cu_sp);
- return GetClangDeclContextContainingDIE (cu_sp.get(), die, NULL);
- }
- return NULL;
-}
-
-clang::DeclContext *
-SymbolFileDWARF::GetClangDeclContextForDIEOffset (const SymbolContext &sc, dw_offset_t die_offset)
-{
- if (die_offset != DW_INVALID_OFFSET)
- {
- DWARFDebugInfo* debug_info = DebugInfo();
- if (debug_info)
- {
- DWARFCompileUnitSP cu_sp;
- const DWARFDebugInfoEntry* die = debug_info->GetDIEPtr(die_offset, &cu_sp);
- if (die)
- return GetClangDeclContextForDIE (sc, cu_sp.get(), die);
- }
- }
- return NULL;
-}
-
-clang::NamespaceDecl *
-SymbolFileDWARF::ResolveNamespaceDIE (DWARFCompileUnit *dwarf_cu, const DWARFDebugInfoEntry *die)
-{
- if (die && die->Tag() == DW_TAG_namespace)
- {
- // See if we already parsed this namespace DIE and associated it with a
- // uniqued namespace declaration
- clang::NamespaceDecl *namespace_decl = static_cast<clang::NamespaceDecl *>(m_die_to_decl_ctx[die]);
- if (namespace_decl)
- return namespace_decl;
- else
- {
- const char *namespace_name = die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_name, NULL);
- clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die, NULL);
- namespace_decl = GetClangASTContext().GetUniqueNamespaceDeclaration (namespace_name, containing_decl_ctx);
- Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
- if (log)
- {
- if (namespace_name)
- {
- 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*>(GetClangASTContext().getASTContext()),
- MakeUserID(die->GetOffset()),
- namespace_name,
- static_cast<void*>(namespace_decl),
- static_cast<void*>(namespace_decl->getOriginalNamespace()));
- }
- else
- {
- GetObjectFile()->GetModule()->LogMessage (log,
- "ASTContext => %p: 0x%8.8" PRIx64 ": DW_TAG_namespace (anonymous) => clang::NamespaceDecl *%p (original = %p)",
- static_cast<void*>(GetClangASTContext().getASTContext()),
- MakeUserID(die->GetOffset()),
- static_cast<void*>(namespace_decl),
- static_cast<void*>(namespace_decl->getOriginalNamespace()));
- }
- }
-
- if (namespace_decl)
- LinkDeclContextToDIE((clang::DeclContext*)namespace_decl, die);
- return namespace_decl;
- }
- }
- return NULL;
-}
-
-clang::DeclContext *
-SymbolFileDWARF::GetClangDeclContextForDIE (const SymbolContext &sc, DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
-{
- clang::DeclContext *clang_decl_ctx = GetCachedClangDeclContextForDIE (die);
- if (clang_decl_ctx)
- return clang_decl_ctx;
- // If this DIE has a specification, or an abstract origin, then trace to those.
-
- dw_offset_t die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_specification, DW_INVALID_OFFSET);
- if (die_offset != DW_INVALID_OFFSET)
- return GetClangDeclContextForDIEOffset (sc, die_offset);
-
- die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_abstract_origin, DW_INVALID_OFFSET);
- if (die_offset != DW_INVALID_OFFSET)
- return GetClangDeclContextForDIEOffset (sc, die_offset);
-
- Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
- if (log)
- GetObjectFile()->GetModule()->LogMessage(log, "SymbolFileDWARF::GetClangDeclContextForDIE (die = 0x%8.8x) %s '%s'", die->GetOffset(), DW_TAG_value_to_name(die->Tag()), die->GetName(this, cu));
- // This is the DIE we want. Parse it, then query our map.
- bool assert_not_being_parsed = true;
- ResolveTypeUID (cu, die, assert_not_being_parsed);
-
- clang_decl_ctx = GetCachedClangDeclContextForDIE (die);
-
- return clang_decl_ctx;
-}
-
-clang::DeclContext *
-SymbolFileDWARF::GetClangDeclContextContainingDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die, const DWARFDebugInfoEntry **decl_ctx_die_copy)
-{
- if (m_clang_tu_decl == NULL)
- m_clang_tu_decl = GetClangASTContext().getASTContext()->getTranslationUnitDecl();
-
- const DWARFDebugInfoEntry *decl_ctx_die = GetDeclContextDIEContainingDIE (cu, die);
-
- if (decl_ctx_die_copy)
- *decl_ctx_die_copy = decl_ctx_die;
-
- if (decl_ctx_die)
- {
-
- DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find (decl_ctx_die);
- if (pos != m_die_to_decl_ctx.end())
- return pos->second;
-
- switch (decl_ctx_die->Tag())
- {
- case DW_TAG_compile_unit:
- return m_clang_tu_decl;
-
- case DW_TAG_namespace:
- return ResolveNamespaceDIE (cu, decl_ctx_die);
- break;
-
- case DW_TAG_structure_type:
- case DW_TAG_union_type:
- case DW_TAG_class_type:
- {
- Type* type = ResolveType (cu, decl_ctx_die);
- if (type)
- {
- clang::DeclContext *decl_ctx = type->GetClangForwardType().GetDeclContextForType ();
- if (decl_ctx)
- {
- LinkDeclContextToDIE (decl_ctx, decl_ctx_die);
- if (decl_ctx)
- return decl_ctx;
- }
- }
- }
- break;
-
- default:
- break;
- }
- }
- return m_clang_tu_decl;
-}
-
-const DWARFDebugInfoEntry *
-SymbolFileDWARF::GetDeclContextDIEContainingDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
+DWARFDIE
+SymbolFileDWARF::GetDeclContextDIEContainingDIE (const DWARFDIE &orig_die)
{
- if (cu && die)
+ if (orig_die)
{
- const DWARFDebugInfoEntry * const decl_die = die;
+ DWARFDIE die = orig_die;
- while (die != NULL)
+ while (die)
{
// If this is the original DIE that we are searching for a declaration
// for, then don't look in the cache as we don't want our own decl
// context to be our decl context...
- if (decl_die != die)
+ if (orig_die != die)
{
- switch (die->Tag())
+ switch (die.Tag())
{
case DW_TAG_compile_unit:
case DW_TAG_namespace:
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_class_type:
+ case DW_TAG_lexical_block:
+ case DW_TAG_subprogram:
return die;
default:
break;
}
}
-
- dw_offset_t die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_specification, DW_INVALID_OFFSET);
- if (die_offset != DW_INVALID_OFFSET)
+
+ DWARFDIE spec_die = die.GetReferencedDIE(DW_AT_specification);
+ if (spec_die)
{
- DWARFCompileUnit *spec_cu = cu;
- const DWARFDebugInfoEntry *spec_die = DebugInfo()->GetDIEPtrWithCompileUnitHint (die_offset, &spec_cu);
- const DWARFDebugInfoEntry *spec_die_decl_ctx_die = GetDeclContextDIEContainingDIE (spec_cu, spec_die);
- if (spec_die_decl_ctx_die)
- return spec_die_decl_ctx_die;
+ DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE(spec_die);
+ if (decl_ctx_die)
+ return decl_ctx_die;
}
-
- die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_abstract_origin, DW_INVALID_OFFSET);
- if (die_offset != DW_INVALID_OFFSET)
+
+ DWARFDIE abs_die = die.GetReferencedDIE(DW_AT_abstract_origin);
+ if (abs_die)
{
- DWARFCompileUnit *abs_cu = cu;
- const DWARFDebugInfoEntry *abs_die = DebugInfo()->GetDIEPtrWithCompileUnitHint (die_offset, &abs_cu);
- const DWARFDebugInfoEntry *abs_die_decl_ctx_die = GetDeclContextDIEContainingDIE (abs_cu, abs_die);
- if (abs_die_decl_ctx_die)
- return abs_die_decl_ctx_die;
+ DWARFDIE decl_ctx_die = GetDeclContextDIEContainingDIE(abs_die);
+ if (decl_ctx_die)
+ return decl_ctx_die;
}
-
- die = die->GetParent();
+
+ die = die.GetParent();
}
}
- return NULL;
+ return DWARFDIE();
}
@@ -5075,7 +3376,7 @@ SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type (DWARFCompileUnit *cu)
// This function can be used when a DIE is found that is a forward declaration
// DIE and we want to try and find a type that has the complete definition.
TypeSP
-SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry *die,
+SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDIE &die,
const ConstString &type_name,
bool must_be_implementation)
{
@@ -5105,15 +3406,13 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry
const size_t num_matches = die_offsets.size();
- DWARFCompileUnit* type_cu = NULL;
- const DWARFDebugInfoEntry* type_die = NULL;
if (num_matches)
{
DWARFDebugInfo* debug_info = DebugInfo();
for (size_t i=0; i<num_matches; ++i)
{
- const dw_offset_t die_offset = die_offsets[i];
- type_die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &type_cu);
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE type_die = debug_info->GetDIE (die_ref);
if (type_die)
{
@@ -5122,7 +3421,7 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry
// Don't try and resolve the DIE we are looking for with the DIE itself!
if (type_die != die)
{
- switch (type_die->Tag())
+ switch (type_die.Tag())
{
case DW_TAG_class_type:
case DW_TAG_structure_type:
@@ -5135,22 +3434,22 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry
if (try_resolving_type)
{
- if (must_be_implementation && type_cu->Supports_DW_AT_APPLE_objc_complete_type())
- try_resolving_type = type_die->GetAttributeValueAsUnsigned (this, type_cu, DW_AT_APPLE_objc_complete_type, 0);
+ if (must_be_implementation && type_die.Supports_DW_AT_APPLE_objc_complete_type())
+ try_resolving_type = type_die.GetAttributeValueAsUnsigned (DW_AT_APPLE_objc_complete_type, 0);
if (try_resolving_type)
{
- Type *resolved_type = ResolveType (type_cu, type_die, false);
+ Type *resolved_type = ResolveType (type_die, false, true);
if (resolved_type && resolved_type != DIE_IS_BEING_PARSED)
{
DEBUG_PRINTF ("resolved 0x%8.8" PRIx64 " from %s to 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ")\n",
- MakeUserID(die->GetOffset()),
+ die.GetID(),
m_obj_file->GetFileSpec().GetFilename().AsCString("<Unknown>"),
- MakeUserID(type_die->GetOffset()),
- MakeUserID(type_cu->GetOffset()));
+ type_die.GetID(),
+ type_cu->GetID());
if (die)
- m_die_to_type[die] = resolved_type;
+ GetDIEToType()[die.GetDIE()] = resolved_type;
type_sp = resolved_type->shared_from_this();
break;
}
@@ -5162,7 +3461,7 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry
if (m_using_apple_tables)
{
GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n",
- die_offset, type_name.GetCString());
+ die_ref.die_offset, type_name.GetCString());
}
}
@@ -5185,19 +3484,12 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry
// when they don't.
//----------------------------------------------------------------------
bool
-SymbolFileDWARF::DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugInfoEntry *die1,
- DWARFCompileUnit* cu2, const DWARFDebugInfoEntry *die2)
+SymbolFileDWARF::DIEDeclContextsMatch (const DWARFDIE &die1,
+ const DWARFDIE &die2)
{
if (die1 == die2)
return true;
-#if defined (LLDB_CONFIGURATION_DEBUG)
- // You can't and shouldn't call this function with a compile unit from
- // two different SymbolFileDWARF instances.
- assert (DebugInfo()->ContainsCompileUnit (cu1));
- assert (DebugInfo()->ContainsCompileUnit (cu2));
-#endif
-
DWARFDIECollection decl_ctx_1;
DWARFDIECollection decl_ctx_2;
//The declaration DIE stack is a stack of the declaration context
@@ -5215,8 +3507,8 @@ SymbolFileDWARF::DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugIn
// all the way back to the compiler unit.
// First lets grab the decl contexts for both DIEs
- die1->GetDeclContextDIEs (this, cu1, decl_ctx_1);
- die2->GetDeclContextDIEs (this, cu2, decl_ctx_2);
+ die1.GetDeclContextDIEs (decl_ctx_1);
+ die2.GetDeclContextDIEs (decl_ctx_2);
// Make sure the context arrays have the same size, otherwise
// we are done
const size_t count1 = decl_ctx_1.Size();
@@ -5226,32 +3518,32 @@ SymbolFileDWARF::DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugIn
// Make sure the DW_TAG values match all the way back up the
// compile unit. If they don't, then we are done.
- const DWARFDebugInfoEntry *decl_ctx_die1;
- const DWARFDebugInfoEntry *decl_ctx_die2;
+ DWARFDIE decl_ctx_die1;
+ DWARFDIE decl_ctx_die2;
size_t i;
for (i=0; i<count1; i++)
{
- decl_ctx_die1 = decl_ctx_1.GetDIEPtrAtIndex (i);
- decl_ctx_die2 = decl_ctx_2.GetDIEPtrAtIndex (i);
- if (decl_ctx_die1->Tag() != decl_ctx_die2->Tag())
+ decl_ctx_die1 = decl_ctx_1.GetDIEAtIndex (i);
+ decl_ctx_die2 = decl_ctx_2.GetDIEAtIndex (i);
+ if (decl_ctx_die1.Tag() != decl_ctx_die2.Tag())
return false;
}
#if defined LLDB_CONFIGURATION_DEBUG
// Make sure the top item in the decl context die array is always
// DW_TAG_compile_unit. If it isn't then something went wrong in
- // the DWARFDebugInfoEntry::GetDeclContextDIEs() function...
- assert (decl_ctx_1.GetDIEPtrAtIndex (count1 - 1)->Tag() == DW_TAG_compile_unit);
+ // the DWARFDIE::GetDeclContextDIEs() function...
+ assert (decl_ctx_1.GetDIEAtIndex (count1 - 1).Tag() == DW_TAG_compile_unit);
#endif
// Always skip the compile unit when comparing by only iterating up to
// "count - 1". Here we compare the names as we go.
for (i=0; i<count1 - 1; i++)
{
- decl_ctx_die1 = decl_ctx_1.GetDIEPtrAtIndex (i);
- decl_ctx_die2 = decl_ctx_2.GetDIEPtrAtIndex (i);
- const char *name1 = decl_ctx_die1->GetName(this, cu1);
- const char *name2 = decl_ctx_die2->GetName(this, cu2);
+ decl_ctx_die1 = decl_ctx_1.GetDIEAtIndex (i);
+ decl_ctx_die2 = decl_ctx_2.GetDIEAtIndex (i);
+ const char *name1 = decl_ctx_die1.GetName();
+ const char *name2 = decl_ctx_die2.GetName();
// If the string was from a DW_FORM_strp, then the pointer will often
// be the same!
if (name1 == name2)
@@ -5338,22 +3630,20 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &
const size_t num_matches = die_offsets.size();
- DWARFCompileUnit* type_cu = NULL;
- const DWARFDebugInfoEntry* type_die = NULL;
if (num_matches)
{
DWARFDebugInfo* debug_info = DebugInfo();
for (size_t i=0; i<num_matches; ++i)
{
- const dw_offset_t die_offset = die_offsets[i];
- type_die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &type_cu);
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE type_die = debug_info->GetDIE (die_ref);
if (type_die)
{
bool try_resolving_type = false;
// Don't try and resolve the DIE we are looking for with the DIE itself!
- const dw_tag_t type_tag = type_die->Tag();
+ const dw_tag_t type_tag = type_die.Tag();
// Make sure the tags match
if (type_tag == tag)
{
@@ -5386,7 +3676,7 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &
if (try_resolving_type)
{
DWARFDeclContext type_dwarf_decl_ctx;
- type_die->GetDWARFDeclContext (this, type_cu, type_dwarf_decl_ctx);
+ type_die.GetDWARFDeclContext (type_dwarf_decl_ctx);
if (log)
{
@@ -5394,14 +3684,14 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &
"SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%s, qualified-name='%s') trying die=0x%8.8x (%s)",
DW_TAG_value_to_name(dwarf_decl_ctx[0].tag),
dwarf_decl_ctx.GetQualifiedName(),
- type_die->GetOffset(),
+ type_die.GetOffset(),
type_dwarf_decl_ctx.GetQualifiedName());
}
// Make sure the decl contexts match all the way up
if (dwarf_decl_ctx == type_dwarf_decl_ctx)
{
- Type *resolved_type = ResolveType (type_cu, type_die, false);
+ Type *resolved_type = ResolveType (type_die, false);
if (resolved_type && resolved_type != DIE_IS_BEING_PARSED)
{
type_sp = resolved_type->shared_from_this();
@@ -5414,12 +3704,12 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &
if (log)
{
std::string qualified_name;
- type_die->GetQualifiedName(this, type_cu, qualified_name);
+ type_die.GetQualifiedName(qualified_name);
GetObjectFile()->GetModule()->LogMessage (log,
"SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%s, qualified-name='%s') ignoring die=0x%8.8x (%s)",
DW_TAG_value_to_name(dwarf_decl_ctx[0].tag),
dwarf_decl_ctx.GetQualifiedName(),
- type_die->GetOffset(),
+ type_die.GetOffset(),
qualified_name.c_str());
}
}
@@ -5429,7 +3719,7 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &
if (m_using_apple_tables)
{
GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n",
- die_offset, type_name.GetCString());
+ die_ref.die_offset, type_name.GetCString());
}
}
@@ -5440,1744 +3730,32 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &
return type_sp;
}
-bool
-SymbolFileDWARF::CopyUniqueClassMethodTypes (SymbolFileDWARF *src_symfile,
- Type *class_type,
- DWARFCompileUnit* src_cu,
- const DWARFDebugInfoEntry *src_class_die,
- DWARFCompileUnit* dst_cu,
- const DWARFDebugInfoEntry *dst_class_die,
- DWARFDIECollection &failures)
-{
- if (!class_type || !src_cu || !src_class_die || !dst_cu || !dst_class_die)
- return false;
- if (src_class_die->Tag() != dst_class_die->Tag())
- return false;
-
- // We need to complete the class type so we can get all of the method types
- // parsed so we can then unique those types to their equivalent counterparts
- // in "dst_cu" and "dst_class_die"
- class_type->GetClangFullType();
-
- const DWARFDebugInfoEntry *src_die;
- const DWARFDebugInfoEntry *dst_die;
- UniqueCStringMap<const DWARFDebugInfoEntry *> src_name_to_die;
- UniqueCStringMap<const DWARFDebugInfoEntry *> dst_name_to_die;
- UniqueCStringMap<const DWARFDebugInfoEntry *> src_name_to_die_artificial;
- UniqueCStringMap<const DWARFDebugInfoEntry *> dst_name_to_die_artificial;
- for (src_die = src_class_die->GetFirstChild(); src_die != NULL; src_die = src_die->GetSibling())
- {
- if (src_die->Tag() == DW_TAG_subprogram)
- {
- // Make sure this is a declaration and not a concrete instance by looking
- // for DW_AT_declaration set to 1. Sometimes concrete function instances
- // are placed inside the class definitions and shouldn't be included in
- // the list of things are are tracking here.
- if (src_die->GetAttributeValueAsUnsigned(src_symfile, src_cu, DW_AT_declaration, 0) == 1)
- {
- const char *src_name = src_die->GetMangledName (src_symfile, src_cu);
- if (src_name)
- {
- ConstString src_const_name(src_name);
- if (src_die->GetAttributeValueAsUnsigned(src_symfile, src_cu, DW_AT_artificial, 0))
- src_name_to_die_artificial.Append(src_const_name.GetCString(), src_die);
- else
- src_name_to_die.Append(src_const_name.GetCString(), src_die);
- }
- }
- }
- }
- for (dst_die = dst_class_die->GetFirstChild(); dst_die != NULL; dst_die = dst_die->GetSibling())
- {
- if (dst_die->Tag() == DW_TAG_subprogram)
- {
- // Make sure this is a declaration and not a concrete instance by looking
- // for DW_AT_declaration set to 1. Sometimes concrete function instances
- // are placed inside the class definitions and shouldn't be included in
- // the list of things are are tracking here.
- if (dst_die->GetAttributeValueAsUnsigned(this, dst_cu, DW_AT_declaration, 0) == 1)
- {
- const char *dst_name = dst_die->GetMangledName (this, dst_cu);
- if (dst_name)
- {
- ConstString dst_const_name(dst_name);
- if (dst_die->GetAttributeValueAsUnsigned(this, dst_cu, DW_AT_artificial, 0))
- dst_name_to_die_artificial.Append(dst_const_name.GetCString(), dst_die);
- else
- dst_name_to_die.Append(dst_const_name.GetCString(), dst_die);
- }
- }
- }
- }
- const uint32_t src_size = src_name_to_die.GetSize ();
- const uint32_t dst_size = dst_name_to_die.GetSize ();
- Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_TYPE_COMPLETION));
-
- // Is everything kosher so we can go through the members at top speed?
- bool fast_path = true;
-
- if (src_size != dst_size)
- {
- if (src_size != 0 && dst_size != 0)
- {
- if (log)
- log->Printf("warning: trying to unique class DIE 0x%8.8x to 0x%8.8x, but they didn't have the same size (src=%d, dst=%d)",
- src_class_die->GetOffset(),
- dst_class_die->GetOffset(),
- src_size,
- dst_size);
- }
-
- fast_path = false;
- }
-
- uint32_t idx;
-
- if (fast_path)
- {
- for (idx = 0; idx < src_size; ++idx)
- {
- src_die = src_name_to_die.GetValueAtIndexUnchecked (idx);
- dst_die = dst_name_to_die.GetValueAtIndexUnchecked (idx);
-
- if (src_die->Tag() != dst_die->Tag())
- {
- if (log)
- log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) tags didn't match 0x%8.8x (%s)",
- src_class_die->GetOffset(),
- dst_class_die->GetOffset(),
- src_die->GetOffset(),
- DW_TAG_value_to_name(src_die->Tag()),
- dst_die->GetOffset(),
- DW_TAG_value_to_name(src_die->Tag()));
- fast_path = false;
- }
-
- const char *src_name = src_die->GetMangledName (src_symfile, src_cu);
- const char *dst_name = dst_die->GetMangledName (this, dst_cu);
-
- // Make sure the names match
- if (src_name == dst_name || (strcmp (src_name, dst_name) == 0))
- continue;
-
- if (log)
- log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) names didn't match 0x%8.8x (%s)",
- src_class_die->GetOffset(),
- dst_class_die->GetOffset(),
- src_die->GetOffset(),
- src_name,
- dst_die->GetOffset(),
- dst_name);
-
- fast_path = false;
- }
- }
-
- // Now do the work of linking the DeclContexts and Types.
- if (fast_path)
- {
- // We can do this quickly. Just run across the tables index-for-index since
- // we know each node has matching names and tags.
- for (idx = 0; idx < src_size; ++idx)
- {
- src_die = src_name_to_die.GetValueAtIndexUnchecked (idx);
- dst_die = dst_name_to_die.GetValueAtIndexUnchecked (idx);
-
- clang::DeclContext *src_decl_ctx = src_symfile->m_die_to_decl_ctx[src_die];
- if (src_decl_ctx)
- {
- if (log)
- log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x",
- static_cast<void*>(src_decl_ctx),
- src_die->GetOffset(), dst_die->GetOffset());
- LinkDeclContextToDIE (src_decl_ctx, dst_die);
- }
- else
- {
- if (log)
- log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found",
- src_die->GetOffset(), dst_die->GetOffset());
- }
-
- Type *src_child_type = m_die_to_type[src_die];
- if (src_child_type)
- {
- if (log)
- log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x",
- static_cast<void*>(src_child_type),
- src_child_type->GetID(),
- src_die->GetOffset(), dst_die->GetOffset());
- m_die_to_type[dst_die] = src_child_type;
- }
- else
- {
- if (log)
- log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset());
- }
- }
- }
- else
- {
- // We must do this slowly. For each member of the destination, look
- // up a member in the source with the same name, check its tag, and
- // unique them if everything matches up. Report failures.
-
- if (!src_name_to_die.IsEmpty() && !dst_name_to_die.IsEmpty())
- {
- src_name_to_die.Sort();
-
- for (idx = 0; idx < dst_size; ++idx)
- {
- const char *dst_name = dst_name_to_die.GetCStringAtIndex(idx);
- dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx);
- src_die = src_name_to_die.Find(dst_name, NULL);
-
- if (src_die && (src_die->Tag() == dst_die->Tag()))
- {
- clang::DeclContext *src_decl_ctx = src_symfile->m_die_to_decl_ctx[src_die];
- if (src_decl_ctx)
- {
- if (log)
- log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x",
- static_cast<void*>(src_decl_ctx),
- src_die->GetOffset(),
- dst_die->GetOffset());
- LinkDeclContextToDIE (src_decl_ctx, dst_die);
- }
- else
- {
- if (log)
- log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset());
- }
-
- Type *src_child_type = m_die_to_type[src_die];
- if (src_child_type)
- {
- if (log)
- log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x",
- static_cast<void*>(src_child_type),
- src_child_type->GetID(),
- src_die->GetOffset(),
- dst_die->GetOffset());
- m_die_to_type[dst_die] = src_child_type;
- }
- else
- {
- if (log)
- log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset());
- }
- }
- else
- {
- if (log)
- log->Printf ("warning: couldn't find a match for 0x%8.8x", dst_die->GetOffset());
-
- failures.Append(dst_die);
- }
- }
- }
- }
-
- const uint32_t src_size_artificial = src_name_to_die_artificial.GetSize ();
- const uint32_t dst_size_artificial = dst_name_to_die_artificial.GetSize ();
-
- UniqueCStringMap<const DWARFDebugInfoEntry *> name_to_die_artificial_not_in_src;
-
- if (src_size_artificial && dst_size_artificial)
- {
- dst_name_to_die_artificial.Sort();
-
- for (idx = 0; idx < src_size_artificial; ++idx)
- {
- const char *src_name_artificial = src_name_to_die_artificial.GetCStringAtIndex(idx);
- src_die = src_name_to_die_artificial.GetValueAtIndexUnchecked (idx);
- dst_die = dst_name_to_die_artificial.Find(src_name_artificial, NULL);
-
- if (dst_die)
- {
- // Both classes have the artificial types, link them
- clang::DeclContext *src_decl_ctx = m_die_to_decl_ctx[src_die];
- if (src_decl_ctx)
- {
- if (log)
- log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x",
- static_cast<void*>(src_decl_ctx),
- src_die->GetOffset(), dst_die->GetOffset());
- LinkDeclContextToDIE (src_decl_ctx, dst_die);
- }
- else
- {
- if (log)
- log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset());
- }
-
- Type *src_child_type = m_die_to_type[src_die];
- if (src_child_type)
- {
- if (log)
- log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x",
- static_cast<void*>(src_child_type),
- src_child_type->GetID(),
- src_die->GetOffset(), dst_die->GetOffset());
- m_die_to_type[dst_die] = src_child_type;
- }
- else
- {
- if (log)
- log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset());
- }
- }
- }
- }
-
- if (dst_size_artificial)
- {
- for (idx = 0; idx < dst_size_artificial; ++idx)
- {
- const char *dst_name_artificial = dst_name_to_die_artificial.GetCStringAtIndex(idx);
- dst_die = dst_name_to_die_artificial.GetValueAtIndexUnchecked (idx);
- if (log)
- log->Printf ("warning: need to create artificial method for 0x%8.8x for method '%s'", dst_die->GetOffset(), dst_name_artificial);
-
- failures.Append(dst_die);
- }
- }
-
- return (failures.Size() != 0);
-}
-
TypeSP
-SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool *type_is_new_ptr)
+SymbolFileDWARF::ParseType (const SymbolContext& sc, const DWARFDIE &die, bool *type_is_new_ptr)
{
TypeSP type_sp;
- if (type_is_new_ptr)
- *type_is_new_ptr = false;
-
-#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
- static DIEStack g_die_stack;
- DIEStack::ScopedPopper scoped_die_logger(g_die_stack);
-#endif
-
- AccessType accessibility = eAccessNone;
- if (die != NULL)
+ if (die)
{
- Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
- if (log)
- {
- const DWARFDebugInfoEntry *context_die;
- clang::DeclContext *context = GetClangDeclContextContainingDIE (dwarf_cu, die, &context_die);
-
- GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x, decl_ctx = %p (die 0x%8.8x)) %s name = '%s')",
- die->GetOffset(),
- static_cast<void*>(context),
- context_die->GetOffset(),
- DW_TAG_value_to_name(die->Tag()),
- die->GetName(this, dwarf_cu));
-
-#if defined(LLDB_CONFIGURATION_DEBUG) || defined(LLDB_CONFIGURATION_RELEASE)
- scoped_die_logger.Push (dwarf_cu, die);
- g_die_stack.LogDIEs(log, this);
-#endif
- }
-//
-// Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
-// if (log && dwarf_cu)
-// {
-// StreamString s;
-// die->DumpLocation (this, dwarf_cu, s);
-// GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDwarf::%s %s", __FUNCTION__, s.GetData());
-//
-// }
-
- Type *type_ptr = m_die_to_type.lookup (die);
- TypeList* type_list = GetTypeList();
- if (type_ptr == NULL)
- {
- ClangASTContext &ast = GetClangASTContext();
- if (type_is_new_ptr)
- *type_is_new_ptr = true;
-
- const dw_tag_t tag = die->Tag();
-
- bool is_forward_declaration = false;
- DWARFDebugInfoEntry::Attributes attributes;
- const char *type_name_cstr = NULL;
- ConstString type_name_const_str;
- Type::ResolveState resolve_state = Type::eResolveStateUnresolved;
- uint64_t byte_size = 0;
- Declaration decl;
-
- Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
- ClangASTType clang_type;
- DWARFFormValue form_value;
-
- dw_attr_t attr;
-
- switch (tag)
- {
- case DW_TAG_base_type:
- case DW_TAG_pointer_type:
- case DW_TAG_reference_type:
- case DW_TAG_rvalue_reference_type:
- case DW_TAG_typedef:
- case DW_TAG_const_type:
- case DW_TAG_restrict_type:
- case DW_TAG_volatile_type:
- case DW_TAG_unspecified_type:
- {
- // Set a bit that lets us know that we are currently parsing this
- m_die_to_type[die] = DIE_IS_BEING_PARSED;
-
- const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
- uint32_t encoding = 0;
- lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
-
- if (num_attributes > 0)
- {
- uint32_t i;
- for (i=0; i<num_attributes; ++i)
- {
- attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
- case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
- case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_name:
-
- type_name_cstr = form_value.AsCString(&get_debug_str_data());
- // Work around a bug in llvm-gcc where they give a name to a reference type which doesn't
- // include the "&"...
- if (tag == DW_TAG_reference_type)
- {
- if (strchr (type_name_cstr, '&') == NULL)
- type_name_cstr = NULL;
- }
- if (type_name_cstr)
- type_name_const_str.SetCString(type_name_cstr);
- break;
- case DW_AT_byte_size: byte_size = form_value.Unsigned(); break;
- case DW_AT_encoding: encoding = form_value.Unsigned(); break;
- case DW_AT_type: encoding_uid = form_value.Reference(); break;
- default:
- case DW_AT_sibling:
- break;
- }
- }
- }
- }
-
- DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr, encoding_uid);
-
- switch (tag)
- {
- default:
- break;
-
- case DW_TAG_unspecified_type:
- if (strcmp(type_name_cstr, "nullptr_t") == 0 ||
- strcmp(type_name_cstr, "decltype(nullptr)") == 0 )
- {
- resolve_state = Type::eResolveStateFull;
- clang_type = ast.GetBasicType(eBasicTypeNullPtr);
- break;
- }
- // Fall through to base type below in case we can handle the type there...
-
- case DW_TAG_base_type:
- resolve_state = Type::eResolveStateFull;
- clang_type = ast.GetBuiltinTypeForDWARFEncodingAndBitSize (type_name_cstr,
- encoding,
- byte_size * 8);
- 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;
- }
-
- if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID || encoding_data_type == Type::eEncodingIsTypedefUID) && sc.comp_unit != NULL)
- {
- bool translation_unit_is_objc = (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus);
-
- if (translation_unit_is_objc)
- {
- if (type_name_cstr != NULL)
- {
- 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 (type_name_const_str == g_objc_type_name_id)
- {
- if (log)
- GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'id' built-in type.",
- die->GetOffset(),
- DW_TAG_value_to_name(die->Tag()),
- die->GetName(this, dwarf_cu));
- clang_type = ast.GetBasicType(eBasicTypeObjCID);
- encoding_data_type = Type::eEncodingIsUID;
- encoding_uid = LLDB_INVALID_UID;
- resolve_state = Type::eResolveStateFull;
-
- }
- else if (type_name_const_str == g_objc_type_name_Class)
- {
- if (log)
- GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'Class' built-in type.",
- die->GetOffset(),
- DW_TAG_value_to_name(die->Tag()),
- die->GetName(this, dwarf_cu));
- clang_type = ast.GetBasicType(eBasicTypeObjCClass);
- encoding_data_type = Type::eEncodingIsUID;
- encoding_uid = LLDB_INVALID_UID;
- resolve_state = Type::eResolveStateFull;
- }
- else if (type_name_const_str == g_objc_type_name_selector)
- {
- if (log)
- GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'selector' built-in type.",
- die->GetOffset(),
- DW_TAG_value_to_name(die->Tag()),
- die->GetName(this, dwarf_cu));
- clang_type = ast.GetBasicType(eBasicTypeObjCSel);
- encoding_data_type = Type::eEncodingIsUID;
- encoding_uid = LLDB_INVALID_UID;
- resolve_state = Type::eResolveStateFull;
- }
- }
- else if (encoding_data_type == Type::eEncodingIsPointerUID && encoding_uid != LLDB_INVALID_UID)
- {
- // Clang sometimes erroneously emits id as objc_object*. In that case we fix up the type to "id".
-
- DWARFDebugInfoEntry* encoding_die = dwarf_cu->GetDIEPtr(encoding_uid);
-
- if (encoding_die && encoding_die->Tag() == DW_TAG_structure_type)
- {
- if (const char *struct_name = encoding_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_name, NULL))
- {
- if (!strcmp(struct_name, "objc_object"))
- {
- if (log)
- GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is 'objc_object*', which we overrode to 'id'.",
- die->GetOffset(),
- DW_TAG_value_to_name(die->Tag()),
- die->GetName(this, dwarf_cu));
- clang_type = ast.GetBasicType(eBasicTypeObjCID);
- encoding_data_type = Type::eEncodingIsUID;
- encoding_uid = LLDB_INVALID_UID;
- resolve_state = Type::eResolveStateFull;
- }
- }
- }
- }
- }
- }
-
- type_sp.reset( new Type (MakeUserID(die->GetOffset()),
- this,
- type_name_const_str,
- byte_size,
- NULL,
- encoding_uid,
- encoding_data_type,
- &decl,
- clang_type,
- resolve_state));
-
- m_die_to_type[die] = type_sp.get();
-
-// Type* encoding_type = GetUniquedTypeForDIEOffset(encoding_uid, type_sp, NULL, 0, 0, false);
-// if (encoding_type != NULL)
-// {
-// if (encoding_type != DIE_IS_BEING_PARSED)
-// type_sp->SetEncodingType(encoding_type);
-// else
-// m_indirect_fixups.push_back(type_sp.get());
-// }
- }
- break;
-
- case DW_TAG_structure_type:
- case DW_TAG_union_type:
- case DW_TAG_class_type:
- {
- // Set a bit that lets us know that we are currently parsing this
- m_die_to_type[die] = DIE_IS_BEING_PARSED;
- bool byte_size_valid = false;
-
- LanguageType class_language = eLanguageTypeUnknown;
- bool is_complete_objc_class = false;
- //bool struct_is_class = false;
- const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
- if (num_attributes > 0)
- {
- uint32_t i;
- for (i=0; i<num_attributes; ++i)
- {
- attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_decl_file:
- if (dwarf_cu->DW_AT_decl_file_attributes_are_invalid())
- {
- // llvm-gcc outputs invalid DW_AT_decl_file attributes that always
- // point to the compile unit file, so we clear this invalid value
- // so that we can still unique types efficiently.
- decl.SetFile(FileSpec ("<invalid>", false));
- }
- else
- decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned()));
- break;
-
- case DW_AT_decl_line:
- decl.SetLine(form_value.Unsigned());
- break;
-
- case DW_AT_decl_column:
- decl.SetColumn(form_value.Unsigned());
- break;
-
- case DW_AT_name:
- type_name_cstr = form_value.AsCString(&get_debug_str_data());
- type_name_const_str.SetCString(type_name_cstr);
- break;
-
- case DW_AT_byte_size:
- byte_size = form_value.Unsigned();
- byte_size_valid = true;
- break;
-
- case DW_AT_accessibility:
- accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());
- break;
-
- case DW_AT_declaration:
- is_forward_declaration = form_value.Boolean();
- break;
-
- case DW_AT_APPLE_runtime_class:
- class_language = (LanguageType)form_value.Signed();
- break;
-
- case DW_AT_APPLE_objc_complete_type:
- is_complete_objc_class = form_value.Signed();
- break;
-
- case DW_AT_allocated:
- case DW_AT_associated:
- case DW_AT_data_location:
- case DW_AT_description:
- case DW_AT_start_scope:
- case DW_AT_visibility:
- default:
- case DW_AT_sibling:
- break;
- }
- }
- }
- }
-
- // UniqueDWARFASTType is large, so don't create a local variables on the
- // stack, put it on the heap. This function is often called recursively
- // and clang isn't good and sharing the stack space for variables in different blocks.
- std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(new UniqueDWARFASTType());
-
- // Only try and unique the type if it has a name.
- if (type_name_const_str &&
- GetUniqueDWARFASTTypeMap().Find (type_name_const_str,
- this,
- dwarf_cu,
- die,
- decl,
- byte_size_valid ? byte_size : -1,
- *unique_ast_entry_ap))
- {
- // We have already parsed this type or from another
- // compile unit. GCC loves to use the "one definition
- // rule" which can result in multiple definitions
- // of the same class over and over in each compile
- // unit.
- type_sp = unique_ast_entry_ap->m_type_sp;
- if (type_sp)
- {
- m_die_to_type[die] = type_sp.get();
- return type_sp;
- }
- }
-
- DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr);
-
- 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;
- }
-
- if (byte_size_valid && byte_size == 0 && type_name_cstr &&
- die->HasChildren() == false &&
- sc.comp_unit->GetLanguage() == eLanguageTypeObjC)
- {
- // Work around an issue with clang at the moment where
- // forward declarations for objective C classes are emitted
- // as:
- // DW_TAG_structure_type [2]
- // DW_AT_name( "ForwardObjcClass" )
- // DW_AT_byte_size( 0x00 )
- // DW_AT_decl_file( "..." )
- // DW_AT_decl_line( 1 )
- //
- // Note that there is no DW_AT_declaration and there are
- // no children, and the byte size is zero.
- is_forward_declaration = true;
- }
-
- if (class_language == eLanguageTypeObjC ||
- class_language == eLanguageTypeObjC_plus_plus)
- {
- if (!is_complete_objc_class && Supports_DW_AT_APPLE_objc_complete_type(dwarf_cu))
- {
- // We have a valid eSymbolTypeObjCClass class symbol whose
- // name matches the current objective C class that we
- // are trying to find and this DIE isn't the complete
- // definition (we checked is_complete_objc_class above and
- // know it is false), so the real definition is in here somewhere
- type_sp = FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true);
-
- if (!type_sp && GetDebugMapSymfile ())
- {
- // We weren't able to find a full declaration in
- // this DWARF, see if we have a declaration anywhere
- // else...
- type_sp = m_debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true);
- }
-
- if (type_sp)
- {
- if (log)
- {
- GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an incomplete objc type, complete type is 0x%8.8" PRIx64,
- static_cast<void*>(this),
- die->GetOffset(),
- DW_TAG_value_to_name(tag),
- type_name_cstr,
- type_sp->GetID());
- }
-
- // 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
- m_die_to_type[die] = type_sp.get();
- return type_sp;
- }
- }
- }
-
-
- if (is_forward_declaration)
- {
- // We have a forward declaration to a type and we need
- // to try and find a full declaration. We look in the
- // current type index just in case we have a forward
- // declaration followed by an actual declarations in the
- // DWARF. If this fails, we need to look elsewhere...
- if (log)
- {
- GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, trying to find complete type",
- static_cast<void*>(this),
- die->GetOffset(),
- DW_TAG_value_to_name(tag),
- type_name_cstr);
- }
-
- DWARFDeclContext die_decl_ctx;
- die->GetDWARFDeclContext(this, dwarf_cu, die_decl_ctx);
-
- //type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, type_name_const_str);
- type_sp = FindDefinitionTypeForDWARFDeclContext (die_decl_ctx);
-
- if (!type_sp && GetDebugMapSymfile ())
- {
- // We weren't able to find a full declaration in
- // this DWARF, see if we have a declaration anywhere
- // else...
- type_sp = m_debug_map_symfile->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx);
- }
-
- if (type_sp)
- {
- if (log)
- {
- 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),
- type_name_cstr,
- type_sp->GetID());
- }
-
- // 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
- m_die_to_type[die] = type_sp.get();
- return type_sp;
- }
- }
- assert (tag_decl_kind != -1);
- bool clang_type_was_created = false;
- clang_type.SetClangType(ast.getASTContext(), m_forward_decl_die_to_clang_type.lookup (die));
- if (!clang_type)
- {
- const DWARFDebugInfoEntry *decl_ctx_die;
-
- clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die, &decl_ctx_die);
- if (accessibility == eAccessNone && decl_ctx)
- {
- // Check the decl context that contains this class/struct/union.
- // If it is a class we must give it an accessibility.
- const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind();
- if (DeclKindIsCXXClass (containing_decl_kind))
- accessibility = default_accessibility;
- }
-
- ClangASTMetadata metadata;
- metadata.SetUserID(MakeUserID(die->GetOffset()));
- metadata.SetIsDynamicCXXType(ClassOrStructIsVirtual (dwarf_cu, die));
-
- if (type_name_cstr && strchr (type_name_cstr, '<'))
- {
- ClangASTContext::TemplateParameterInfos template_param_infos;
- if (ParseTemplateParameterInfos (dwarf_cu, die, template_param_infos))
- {
- clang::ClassTemplateDecl *class_template_decl = ParseClassTemplateDecl (decl_ctx,
- accessibility,
- type_name_cstr,
- tag_decl_kind,
- template_param_infos);
-
- clang::ClassTemplateSpecializationDecl *class_specialization_decl = ast.CreateClassTemplateSpecializationDecl (decl_ctx,
- class_template_decl,
- tag_decl_kind,
- template_param_infos);
- clang_type = ast.CreateClassTemplateSpecializationType (class_specialization_decl);
- clang_type_was_created = true;
-
- GetClangASTContext().SetMetadata (class_template_decl, metadata);
- GetClangASTContext().SetMetadata (class_specialization_decl, metadata);
- }
- }
-
- if (!clang_type_was_created)
- {
- clang_type_was_created = true;
- clang_type = ast.CreateRecordType (decl_ctx,
- accessibility,
- type_name_cstr,
- tag_decl_kind,
- class_language,
- &metadata);
- }
- }
-
- // Store a forward declaration to this class type in case any
- // parameters in any class methods need it for the clang
- // types for function prototypes.
- LinkDeclContextToDIE(clang_type.GetDeclContextForType(), die);
- type_sp.reset (new Type (MakeUserID(die->GetOffset()),
- this,
- type_name_const_str,
- byte_size,
- NULL,
- LLDB_INVALID_UID,
- Type::eEncodingIsUID,
- &decl,
- clang_type,
- Type::eResolveStateForward));
-
- type_sp->SetIsCompleteObjCClass(is_complete_objc_class);
-
-
- // Add our type to the unique type map so we don't
- // end up creating many copies of the same type over
- // and over in the ASTContext for our module
- unique_ast_entry_ap->m_type_sp = type_sp;
- unique_ast_entry_ap->m_symfile = this;
- unique_ast_entry_ap->m_cu = dwarf_cu;
- unique_ast_entry_ap->m_die = die;
- unique_ast_entry_ap->m_declaration = decl;
- unique_ast_entry_ap->m_byte_size = byte_size;
- GetUniqueDWARFASTTypeMap().Insert (type_name_const_str,
- *unique_ast_entry_ap);
-
- if (is_forward_declaration && die->HasChildren())
- {
- // Check to see if the DIE actually has a definition, some version of GCC will
- // emit DIEs with DW_AT_declaration set to true, but yet still have subprogram,
- // members, or inheritance, so we can't trust it
- const DWARFDebugInfoEntry *child_die = die->GetFirstChild();
- while (child_die)
- {
- switch (child_die->Tag())
- {
- case DW_TAG_inheritance:
- case DW_TAG_subprogram:
- case DW_TAG_member:
- case DW_TAG_APPLE_property:
- case DW_TAG_class_type:
- case DW_TAG_structure_type:
- case DW_TAG_enumeration_type:
- case DW_TAG_typedef:
- case DW_TAG_union_type:
- child_die = NULL;
- is_forward_declaration = false;
- break;
- default:
- child_die = child_die->GetSibling();
- break;
- }
- }
- }
-
- if (!is_forward_declaration)
- {
- // Always start the definition for a class type so that
- // if the class has child classes or types that require
- // the class to be created for use as their decl contexts
- // the class will be ready to accept these child definitions.
- if (die->HasChildren() == false)
- {
- // No children for this struct/union/class, lets finish it
- clang_type.StartTagDeclarationDefinition ();
- clang_type.CompleteTagDeclarationDefinition ();
-
- if (tag == DW_TAG_structure_type) // this only applies in C
- {
- clang::RecordDecl *record_decl = clang_type.GetAsRecordDecl();
-
- if (record_decl)
- m_record_decl_to_layout_map.insert(std::make_pair(record_decl, LayoutInfo()));
- }
- }
- else if (clang_type_was_created)
- {
- // Start the definition if the class is not objective C since
- // the underlying decls respond to isCompleteDefinition(). Objective
- // C decls don't respond to isCompleteDefinition() so we can't
- // start the declaration definition right away. For C++ class/union/structs
- // we want to start the definition in case the class is needed as the
- // declaration context for a contained class or type without the need
- // to complete that type..
-
- if (class_language != eLanguageTypeObjC &&
- class_language != eLanguageTypeObjC_plus_plus)
- clang_type.StartTagDeclarationDefinition ();
-
- // Leave this as a forward declaration until we need
- // to know the details of the type. lldb_private::Type
- // will automatically call the SymbolFile virtual function
- // "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition(Type *)"
- // When the definition needs to be defined.
- m_forward_decl_die_to_clang_type[die] = clang_type.GetOpaqueQualType();
- m_forward_decl_clang_type_to_die[clang_type.RemoveFastQualifiers().GetOpaqueQualType()] = die;
- clang_type.SetHasExternalStorage (true);
- }
- }
-
- }
- break;
-
- case DW_TAG_enumeration_type:
- {
- // Set a bit that lets us know that we are currently parsing this
- m_die_to_type[die] = DIE_IS_BEING_PARSED;
-
- lldb::user_id_t encoding_uid = DW_INVALID_OFFSET;
-
- const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
- if (num_attributes > 0)
- {
- uint32_t i;
-
- for (i=0; i<num_attributes; ++i)
- {
- attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
- case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
- case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_name:
- type_name_cstr = form_value.AsCString(&get_debug_str_data());
- type_name_const_str.SetCString(type_name_cstr);
- break;
- case DW_AT_type: encoding_uid = form_value.Reference(); break;
- case DW_AT_byte_size: byte_size = form_value.Unsigned(); break;
- case DW_AT_accessibility: break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
- case DW_AT_declaration: break; //is_forward_declaration = form_value.Boolean(); break;
- case DW_AT_allocated:
- case DW_AT_associated:
- case DW_AT_bit_stride:
- case DW_AT_byte_stride:
- case DW_AT_data_location:
- case DW_AT_description:
- case DW_AT_start_scope:
- case DW_AT_visibility:
- case DW_AT_specification:
- case DW_AT_abstract_origin:
- case DW_AT_sibling:
- break;
- }
- }
- }
-
- DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr);
-
- ClangASTType enumerator_clang_type;
- clang_type.SetClangType (ast.getASTContext(), m_forward_decl_die_to_clang_type.lookup (die));
- if (!clang_type)
- {
- if (encoding_uid != DW_INVALID_OFFSET)
- {
- Type *enumerator_type = ResolveTypeUID(encoding_uid);
- if (enumerator_type)
- enumerator_clang_type = enumerator_type->GetClangFullType();
- }
-
- if (!enumerator_clang_type)
- enumerator_clang_type = ast.GetBuiltinTypeForDWARFEncodingAndBitSize (NULL,
- DW_ATE_signed,
- byte_size * 8);
-
- clang_type = ast.CreateEnumerationType (type_name_cstr,
- GetClangDeclContextContainingDIE (dwarf_cu, die, NULL),
- decl,
- enumerator_clang_type);
- }
- else
- {
- enumerator_clang_type = clang_type.GetEnumerationIntegerType ();
- }
-
- LinkDeclContextToDIE(clang_type.GetDeclContextForType(), die);
-
- type_sp.reset( new Type (MakeUserID(die->GetOffset()),
- this,
- type_name_const_str,
- byte_size,
- NULL,
- encoding_uid,
- Type::eEncodingIsUID,
- &decl,
- clang_type,
- Type::eResolveStateForward));
-
- clang_type.StartTagDeclarationDefinition ();
- if (die->HasChildren())
- {
- SymbolContext cu_sc(GetCompUnitForDWARFCompUnit(dwarf_cu));
- bool is_signed = false;
- enumerator_clang_type.IsIntegerType(is_signed);
- ParseChildEnumerators(cu_sc, clang_type, is_signed, type_sp->GetByteSize(), dwarf_cu, die);
- }
- clang_type.CompleteTagDeclarationDefinition ();
- }
- }
- break;
-
- case DW_TAG_inlined_subroutine:
- case DW_TAG_subprogram:
- case DW_TAG_subroutine_type:
- {
- // Set a bit that lets us know that we are currently parsing this
- m_die_to_type[die] = DIE_IS_BEING_PARSED;
-
- //const char *mangled = NULL;
- dw_offset_t type_die_offset = DW_INVALID_OFFSET;
- bool is_variadic = false;
- bool is_inline = false;
- bool is_static = false;
- bool is_virtual = false;
- bool is_explicit = false;
- bool is_artificial = false;
- dw_offset_t specification_die_offset = DW_INVALID_OFFSET;
- dw_offset_t abstract_origin_die_offset = DW_INVALID_OFFSET;
- dw_offset_t object_pointer_die_offset = DW_INVALID_OFFSET;
-
- unsigned type_quals = 0;
- clang::StorageClass storage = clang::SC_None;//, Extern, Static, PrivateExtern
-
-
- const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
- if (num_attributes > 0)
- {
- uint32_t i;
- for (i=0; i<num_attributes; ++i)
- {
- attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
- case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
- case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_name:
- type_name_cstr = form_value.AsCString(&get_debug_str_data());
- type_name_const_str.SetCString(type_name_cstr);
- break;
-
- case DW_AT_linkage_name:
- case DW_AT_MIPS_linkage_name: break; // mangled = form_value.AsCString(&get_debug_str_data()); break;
- case DW_AT_type: type_die_offset = form_value.Reference(); break;
- case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
- case DW_AT_declaration: break; // is_forward_declaration = form_value.Boolean(); break;
- case DW_AT_inline: is_inline = form_value.Boolean(); break;
- case DW_AT_virtuality: is_virtual = form_value.Boolean(); break;
- case DW_AT_explicit: is_explicit = form_value.Boolean(); break;
- case DW_AT_artificial: is_artificial = form_value.Boolean(); break;
-
-
- case DW_AT_external:
- if (form_value.Unsigned())
- {
- if (storage == clang::SC_None)
- storage = clang::SC_Extern;
- else
- storage = clang::SC_PrivateExtern;
- }
- break;
-
- case DW_AT_specification:
- specification_die_offset = form_value.Reference();
- break;
-
- case DW_AT_abstract_origin:
- abstract_origin_die_offset = form_value.Reference();
- break;
-
- case DW_AT_object_pointer:
- object_pointer_die_offset = form_value.Reference();
- break;
-
- case DW_AT_allocated:
- case DW_AT_associated:
- case DW_AT_address_class:
- case DW_AT_calling_convention:
- case DW_AT_data_location:
- case DW_AT_elemental:
- case DW_AT_entry_pc:
- case DW_AT_frame_base:
- case DW_AT_high_pc:
- case DW_AT_low_pc:
- case DW_AT_prototyped:
- case DW_AT_pure:
- case DW_AT_ranges:
- case DW_AT_recursive:
- case DW_AT_return_addr:
- case DW_AT_segment:
- case DW_AT_start_scope:
- case DW_AT_static_link:
- case DW_AT_trampoline:
- case DW_AT_visibility:
- case DW_AT_vtable_elem_location:
- case DW_AT_description:
- case DW_AT_sibling:
- break;
- }
- }
- }
- }
-
- std::string object_pointer_name;
- if (object_pointer_die_offset != DW_INVALID_OFFSET)
- {
- // Get the name from the object pointer die
- StreamString s;
- if (DWARFDebugInfoEntry::GetName (this, dwarf_cu, object_pointer_die_offset, s))
- {
- object_pointer_name.assign(s.GetData());
- }
- }
-
- DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr);
-
- ClangASTType return_clang_type;
- Type *func_type = NULL;
-
- if (type_die_offset != DW_INVALID_OFFSET)
- func_type = ResolveTypeUID(type_die_offset);
-
- if (func_type)
- return_clang_type = func_type->GetClangForwardType();
- else
- return_clang_type = ast.GetBasicType(eBasicTypeVoid);
-
-
- std::vector<ClangASTType> function_param_types;
- std::vector<clang::ParmVarDecl*> function_param_decls;
-
- // Parse the function children for the parameters
-
- const DWARFDebugInfoEntry *decl_ctx_die = NULL;
- clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die, &decl_ctx_die);
- const clang::Decl::Kind containing_decl_kind = containing_decl_ctx->getDeclKind();
-
- const 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 (sc,
- containing_decl_ctx,
- dwarf_cu,
- die,
- skip_artificial,
- is_static,
- is_variadic,
- function_param_types,
- function_param_decls,
- type_quals);
- }
-
- // clang_type will get the function prototype clang type after this call
- clang_type = ast.CreateFunctionType (return_clang_type,
- function_param_types.data(),
- function_param_types.size(),
- is_variadic,
- type_quals);
-
- bool ignore_containing_context = false;
-
- if (type_name_cstr)
- {
- bool type_handled = false;
- if (tag == DW_TAG_subprogram)
- {
- ObjCLanguageRuntime::MethodName objc_method (type_name_cstr, true);
- if (objc_method.IsValid(true))
- {
- ClangASTType class_opaque_type;
- ConstString class_name(objc_method.GetClassName());
- if (class_name)
- {
- TypeSP complete_objc_class_type_sp (FindCompleteObjCDefinitionTypeForDIE (NULL, class_name, false));
-
- if (complete_objc_class_type_sp)
- {
- ClangASTType type_clang_forward_type = complete_objc_class_type_sp->GetClangForwardType();
- if (type_clang_forward_type.IsObjCObjectOrInterfaceType ())
- class_opaque_type = type_clang_forward_type;
- }
- }
-
- if (class_opaque_type)
- {
- // If accessibility isn't set to anything valid, assume public for
- // now...
- if (accessibility == eAccessNone)
- accessibility = eAccessPublic;
-
- clang::ObjCMethodDecl *objc_method_decl = class_opaque_type.AddMethodToObjCObjectType (type_name_cstr,
- clang_type,
- accessibility,
- is_artificial);
- type_handled = objc_method_decl != NULL;
- if (type_handled)
- {
- LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(objc_method_decl), die);
- GetClangASTContext().SetMetadataAsUserID (objc_method_decl, MakeUserID(die->GetOffset()));
- }
- else
- {
- 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 = ResolveType (dwarf_cu, decl_ctx_die);
- if (class_type)
- {
- if (class_type->GetID() != MakeUserID(decl_ctx_die->GetOffset()))
- {
- // 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"...
- SymbolFileDWARF *class_symfile = NULL;
- DWARFCompileUnitSP class_type_cu_sp;
- const DWARFDebugInfoEntry *class_type_die = NULL;
-
- SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
- if (debug_map_symfile)
- {
- class_symfile = debug_map_symfile->GetSymbolFileByOSOIndex(SymbolFileDWARFDebugMap::GetOSOIndexFromUserID(class_type->GetID()));
- class_type_die = class_symfile->DebugInfo()->GetDIEPtr(class_type->GetID(), &class_type_cu_sp);
- }
- else
- {
- class_symfile = this;
- class_type_die = DebugInfo()->GetDIEPtr(class_type->GetID(), &class_type_cu_sp);
- }
- if (class_type_die)
- {
- DWARFDIECollection failures;
-
- CopyUniqueClassMethodTypes (class_symfile,
- class_type,
- class_type_cu_sp.get(),
- class_type_die,
- dwarf_cu,
- decl_ctx_die,
- 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 = m_die_to_type[die];
- if (type_ptr && type_ptr != DIE_IS_BEING_PARSED)
- {
- type_sp = type_ptr->shared_from_this();
- break;
- }
- }
- }
-
- if (specification_die_offset != DW_INVALID_OFFSET)
- {
- // 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->GetClangForwardType();
- // If we have a specification, then the function type should have been
- // made with the specification and not with this die.
- DWARFCompileUnitSP spec_cu_sp;
- const DWARFDebugInfoEntry* spec_die = DebugInfo()->GetDIEPtr(specification_die_offset, &spec_cu_sp);
- clang::DeclContext *spec_clang_decl_ctx = GetClangDeclContextForDIE (sc, dwarf_cu, spec_die);
- if (spec_clang_decl_ctx)
- {
- LinkDeclContextToDIE(spec_clang_decl_ctx, die);
- }
- else
- {
- GetObjectFile()->GetModule()->ReportWarning ("0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8x) has no decl\n",
- MakeUserID(die->GetOffset()),
- specification_die_offset);
- }
- type_handled = true;
- }
- else if (abstract_origin_die_offset != DW_INVALID_OFFSET)
- {
- // 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->GetClangForwardType();
-
- DWARFCompileUnitSP abs_cu_sp;
- const DWARFDebugInfoEntry* abs_die = DebugInfo()->GetDIEPtr(abstract_origin_die_offset, &abs_cu_sp);
- clang::DeclContext *abs_clang_decl_ctx = GetClangDeclContextForDIE (sc, dwarf_cu, abs_die);
- if (abs_clang_decl_ctx)
- {
- LinkDeclContextToDIE (abs_clang_decl_ctx, die);
- }
- else
- {
- GetObjectFile()->GetModule()->ReportWarning ("0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8x) has no decl\n",
- MakeUserID(die->GetOffset()),
- abstract_origin_die_offset);
- }
- type_handled = true;
- }
- else
- {
- ClangASTType class_opaque_type = class_type->GetClangForwardType();
- if (class_opaque_type.IsCXXClassType ())
- {
- if (class_opaque_type.IsBeingDefined ())
- {
- // Neither GCC 4.2 nor clang++ currently set a valid accessibility
- // in the DWARF for C++ methods... Default to public for now...
- if (accessibility == eAccessNone)
- accessibility = eAccessPublic;
-
- 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
- {
- clang::CXXMethodDecl *cxx_method_decl;
- // REMOVE THE CRASH DESCRIPTION BELOW
- Host::SetCrashDescriptionWithFormat ("SymbolFileDWARF::ParseType() is adding a method %s to class %s in DIE 0x%8.8" PRIx64 " from %s",
- type_name_cstr,
- class_type->GetName().GetCString(),
- MakeUserID(die->GetOffset()),
- m_obj_file->GetFileSpec().GetPath().c_str());
-
- const bool is_attr_used = false;
-
- cxx_method_decl = class_opaque_type.AddMethodToCXXRecordType (type_name_cstr,
- clang_type,
- accessibility,
- is_virtual,
- is_static,
- is_inline,
- is_explicit,
- is_attr_used,
- is_artificial);
-
- type_handled = cxx_method_decl != NULL;
-
- if (type_handled)
- {
- LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(cxx_method_decl), die);
-
- Host::SetCrashDescription (NULL);
-
-
- ClangASTMetadata metadata;
- metadata.SetUserID(MakeUserID(die->GetOffset()));
-
- if (!object_pointer_name.empty())
- {
- metadata.SetObjectPtrName(object_pointer_name.c_str());
- if (log)
- log->Printf ("Setting object pointer name: %s on method object %p.\n",
- object_pointer_name.c_str(),
- static_cast<void*>(cxx_method_decl));
- }
- GetClangASTContext().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 m_die_to_type map. First
- // we need to modify the m_die_to_type so it doesn't think we are
- // trying to parse this DIE anymore...
- m_die_to_type[die] = 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->GetClangFullType();
-
- // The type for this DIE should have been filled in the function call above
- type_ptr = m_die_to_type[die];
- 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;
- }
- }
- }
- }
- }
- }
-
- if (!type_handled)
- {
- // We just have a function that isn't part of a class
- clang::FunctionDecl *function_decl = ast.CreateFunctionDeclaration (ignore_containing_context ? GetClangASTContext().GetTranslationUnitDecl() : containing_decl_ctx,
- type_name_cstr,
- clang_type,
- storage,
- is_inline);
-
-// if (template_param_infos.GetSize() > 0)
-// {
-// clang::FunctionTemplateDecl *func_template_decl = ast.CreateFunctionTemplateDecl (containing_decl_ctx,
-// function_decl,
-// type_name_cstr,
-// template_param_infos);
-//
-// ast.CreateFunctionTemplateSpecializationInfo (function_decl,
-// func_template_decl,
-// template_param_infos);
-// }
- // Add the decl to our DIE to decl context map
- assert (function_decl);
- LinkDeclContextToDIE(function_decl, die);
- if (!function_param_decls.empty())
- ast.SetFunctionParameters (function_decl,
- &function_param_decls.front(),
- function_param_decls.size());
-
- ClangASTMetadata metadata;
- metadata.SetUserID(MakeUserID(die->GetOffset()));
-
- if (!object_pointer_name.empty())
- {
- metadata.SetObjectPtrName(object_pointer_name.c_str());
- if (log)
- log->Printf ("Setting object pointer name: %s on function object %p.",
- object_pointer_name.c_str(),
- static_cast<void*>(function_decl));
- }
- GetClangASTContext().SetMetadata (function_decl, metadata);
- }
- }
- type_sp.reset( new Type (MakeUserID(die->GetOffset()),
- this,
- type_name_const_str,
- 0,
- NULL,
- LLDB_INVALID_UID,
- Type::eEncodingIsUID,
- &decl,
- clang_type,
- Type::eResolveStateFull));
- assert(type_sp.get());
- }
- break;
-
- case DW_TAG_array_type:
- {
- // Set a bit that lets us know that we are currently parsing this
- m_die_to_type[die] = DIE_IS_BEING_PARSED;
-
- lldb::user_id_t type_die_offset = DW_INVALID_OFFSET;
- int64_t first_index = 0;
- uint32_t byte_stride = 0;
- uint32_t bit_stride = 0;
- bool is_vector = false;
- const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
-
- if (num_attributes > 0)
- {
- uint32_t i;
- for (i=0; i<num_attributes; ++i)
- {
- attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
- case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
- case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_name:
- type_name_cstr = form_value.AsCString(&get_debug_str_data());
- type_name_const_str.SetCString(type_name_cstr);
- break;
-
- case DW_AT_type: type_die_offset = form_value.Reference(); break;
- case DW_AT_byte_size: break; // byte_size = form_value.Unsigned(); break;
- case DW_AT_byte_stride: byte_stride = form_value.Unsigned(); break;
- case DW_AT_bit_stride: bit_stride = form_value.Unsigned(); break;
- case DW_AT_GNU_vector: is_vector = form_value.Boolean(); break;
- case DW_AT_accessibility: break; // accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
- case DW_AT_declaration: break; // is_forward_declaration = form_value.Boolean(); break;
- case DW_AT_allocated:
- case DW_AT_associated:
- case DW_AT_data_location:
- case DW_AT_description:
- case DW_AT_ordering:
- case DW_AT_start_scope:
- case DW_AT_visibility:
- case DW_AT_specification:
- case DW_AT_abstract_origin:
- case DW_AT_sibling:
- break;
- }
- }
- }
-
- DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr);
-
- Type *element_type = ResolveTypeUID(type_die_offset);
-
- if (element_type)
- {
- std::vector<uint64_t> element_orders;
- ParseChildArrayInfo(sc, dwarf_cu, die, first_index, element_orders, byte_stride, bit_stride);
- if (byte_stride == 0 && bit_stride == 0)
- byte_stride = element_type->GetByteSize();
- ClangASTType array_element_type = element_type->GetClangForwardType();
- uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride;
- if (element_orders.size() > 0)
- {
- uint64_t num_elements = 0;
- std::vector<uint64_t>::const_reverse_iterator pos;
- std::vector<uint64_t>::const_reverse_iterator end = element_orders.rend();
- for (pos = element_orders.rbegin(); pos != end; ++pos)
- {
- num_elements = *pos;
- clang_type = ast.CreateArrayType (array_element_type,
- num_elements,
- 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 = ast.CreateArrayType (array_element_type, 0, is_vector);
- }
- ConstString empty_name;
- type_sp.reset( new Type (MakeUserID(die->GetOffset()),
- this,
- empty_name,
- array_element_bit_stride / 8,
- NULL,
- type_die_offset,
- Type::eEncodingIsUID,
- &decl,
- clang_type,
- Type::eResolveStateFull));
- type_sp->SetEncodingType (element_type);
- }
- }
- }
- break;
+ TypeSystem *type_system = GetTypeSystemForLanguage(die.GetCU()->GetLanguageType());
- case DW_TAG_ptr_to_member_type:
- {
- dw_offset_t type_die_offset = DW_INVALID_OFFSET;
- dw_offset_t containing_type_die_offset = DW_INVALID_OFFSET;
-
- const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
-
- if (num_attributes > 0) {
- uint32_t i;
- for (i=0; i<num_attributes; ++i)
- {
- attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
- {
- switch (attr)
- {
- case DW_AT_type:
- type_die_offset = form_value.Reference(); break;
- case DW_AT_containing_type:
- containing_type_die_offset = form_value.Reference(); break;
- }
- }
- }
-
- Type *pointee_type = ResolveTypeUID(type_die_offset);
- Type *class_type = ResolveTypeUID(containing_type_die_offset);
-
- ClangASTType pointee_clang_type = pointee_type->GetClangForwardType();
- ClangASTType class_clang_type = class_type->GetClangLayoutType();
-
- clang_type = pointee_clang_type.CreateMemberPointerType(class_clang_type);
-
- byte_size = clang_type.GetByteSize(nullptr);
-
- type_sp.reset( new Type (MakeUserID(die->GetOffset()),
- this,
- type_name_const_str,
- byte_size,
- NULL,
- LLDB_INVALID_UID,
- Type::eEncodingIsUID,
- NULL,
- clang_type,
- Type::eResolveStateForward));
- }
-
- break;
- }
- default:
- 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 (type_sp.get())
+ if (type_system)
+ {
+ DWARFASTParser *dwarf_ast = type_system->GetDWARFParser();
+ if (dwarf_ast)
{
- const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(die);
- dw_tag_t sc_parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0;
-
- SymbolContextScope * symbol_context_scope = NULL;
- if (sc_parent_tag == DW_TAG_compile_unit)
+ Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
+ type_sp = dwarf_ast->ParseTypeFromDWARF (sc, die, log, type_is_new_ptr);
+ if (type_sp)
{
- symbol_context_scope = sc.comp_unit;
+ TypeList* type_list = GetTypeList();
+ if (type_list)
+ type_list->Insert(type_sp);
}
- else if (sc.function != NULL && sc_parent_die)
- {
- symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(MakeUserID(sc_parent_die->GetOffset()));
- if (symbol_context_scope == NULL)
- symbol_context_scope = sc.function;
- }
-
- if (symbol_context_scope != NULL)
- {
- type_sp->SetSymbolContextScope(symbol_context_scope);
- }
-
- // We are ready to put this type into the uniqued list up at the module level
- type_list->Insert (type_sp);
-
- m_die_to_type[die] = type_sp.get();
}
}
- else if (type_ptr != DIE_IS_BEING_PARSED)
- {
- type_sp = type_ptr->shared_from_this();
- }
}
+
return type_sp;
}
@@ -7185,38 +3763,38 @@ size_t
SymbolFileDWARF::ParseTypes
(
const SymbolContext& sc,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
+ const DWARFDIE &orig_die,
bool parse_siblings,
bool parse_children
)
{
size_t types_added = 0;
- while (die != NULL)
+ DWARFDIE die = orig_die;
+ while (die)
{
bool type_is_new = false;
- if (ParseType(sc, dwarf_cu, die, &type_is_new).get())
+ if (ParseType(sc, die, &type_is_new).get())
{
if (type_is_new)
++types_added;
}
- if (parse_children && die->HasChildren())
+ if (parse_children && die.HasChildren())
{
- if (die->Tag() == DW_TAG_subprogram)
+ if (die.Tag() == DW_TAG_subprogram)
{
SymbolContext child_sc(sc);
- child_sc.function = sc.comp_unit->FindFunctionByUID(MakeUserID(die->GetOffset())).get();
- types_added += ParseTypes(child_sc, dwarf_cu, die->GetFirstChild(), true, true);
+ child_sc.function = sc.comp_unit->FindFunctionByUID(die.GetID()).get();
+ types_added += ParseTypes(child_sc, die.GetFirstChild(), true, true);
}
else
- types_added += ParseTypes(sc, dwarf_cu, die->GetFirstChild(), true, true);
+ types_added += ParseTypes(sc, die.GetFirstChild(), true, true);
}
if (parse_siblings)
- die = die->GetSibling();
+ die = die.GetSibling();
else
- die = NULL;
+ die.Clear();
}
return types_added;
}
@@ -7230,11 +3808,11 @@ SymbolFileDWARF::ParseFunctionBlocks (const SymbolContext &sc)
DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu)
{
- dw_offset_t function_die_offset = sc.function->GetID();
- const DWARFDebugInfoEntry *function_die = dwarf_cu->GetDIEPtr(function_die_offset);
+ const dw_offset_t function_die_offset = sc.function->GetID();
+ DWARFDIE function_die = dwarf_cu->GetDIE (function_die_offset);
if (function_die)
{
- ParseFunctionBlocks(sc, &sc.function->GetBlock (false), dwarf_cu, function_die, LLDB_INVALID_ADDRESS, 0);
+ ParseFunctionBlocks(sc, &sc.function->GetBlock (false), function_die, LLDB_INVALID_ADDRESS, 0);
}
}
@@ -7254,18 +3832,18 @@ SymbolFileDWARF::ParseTypes (const SymbolContext &sc)
if (sc.function)
{
dw_offset_t function_die_offset = sc.function->GetID();
- const DWARFDebugInfoEntry *func_die = dwarf_cu->GetDIEPtr(function_die_offset);
- if (func_die && func_die->HasChildren())
+ DWARFDIE func_die = dwarf_cu->GetDIE(function_die_offset);
+ if (func_die && func_die.HasChildren())
{
- types_added = ParseTypes(sc, dwarf_cu, func_die->GetFirstChild(), true, true);
+ types_added = ParseTypes(sc, func_die.GetFirstChild(), true, true);
}
}
else
{
- const DWARFDebugInfoEntry *dwarf_cu_die = dwarf_cu->DIE();
- if (dwarf_cu_die && dwarf_cu_die->HasChildren())
+ DWARFDIE dwarf_cu_die = dwarf_cu->DIE();
+ if (dwarf_cu_die && dwarf_cu_die.HasChildren())
{
- types_added = ParseTypes(sc, dwarf_cu, dwarf_cu_die->GetFirstChild(), true, true);
+ types_added = ParseTypes(sc, dwarf_cu_die.GetFirstChild(), true, true);
}
}
}
@@ -7284,17 +3862,12 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
if (sc.function)
{
- DWARFCompileUnit* dwarf_cu = info->GetCompileUnitContainingDIE(sc.function->GetID()).get();
+ DWARFDIE function_die = info->GetDIE(DIERef(sc.function->GetID()));
- if (dwarf_cu == NULL)
- return 0;
-
- const DWARFDebugInfoEntry *function_die = dwarf_cu->GetDIEPtr(sc.function->GetID());
-
- dw_addr_t func_lo_pc = function_die->GetAttributeValueAsUnsigned (this, dwarf_cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
+ const dw_addr_t func_lo_pc = function_die.GetAttributeValueAsAddress (DW_AT_low_pc, LLDB_INVALID_ADDRESS);
if (func_lo_pc != LLDB_INVALID_ADDRESS)
{
- const size_t num_variables = ParseVariables(sc, dwarf_cu, func_lo_pc, function_die->GetFirstChild(), true, true);
+ const size_t num_variables = ParseVariables(sc, function_die.GetFirstChild(), func_lo_pc, true, true);
// Let all blocks know they have parse all their variables
sc.function->GetBlock (false).SetDidParseVariables (true, true);
@@ -7303,7 +3876,7 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
}
else if (sc.comp_unit)
{
- DWARFCompileUnit* dwarf_cu = info->GetCompileUnit(sc.comp_unit->GetID()).get();
+ DWARFCompileUnit* dwarf_cu = info->GetCompileUnit(sc.comp_unit->GetID());
if (dwarf_cu == NULL)
return 0;
@@ -7316,8 +3889,6 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
variables.reset(new VariableList());
sc.comp_unit->SetVariableList(variables);
- DWARFCompileUnit* match_dwarf_cu = NULL;
- const DWARFDebugInfoEntry* die = NULL;
DIEArray die_offsets;
if (m_using_apple_tables)
{
@@ -7340,7 +3911,6 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
Index ();
m_global_index.FindAllEntriesForCompileUnit (dwarf_cu->GetOffset(),
- dwarf_cu->GetNextCompileUnitOffset(),
die_offsets);
}
@@ -7350,11 +3920,11 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
DWARFDebugInfo* debug_info = DebugInfo();
for (size_t i=0; i<num_matches; ++i)
{
- const dw_offset_t die_offset = die_offsets[i];
- die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &match_dwarf_cu);
+ const DIERef& die_ref = die_offsets[i];
+ DWARFDIE die = debug_info->GetDIE (die_ref);
if (die)
{
- VariableSP var_sp (ParseVariableDIE(sc, dwarf_cu, die, LLDB_INVALID_ADDRESS));
+ VariableSP var_sp (ParseVariableDIE(sc, die, LLDB_INVALID_ADDRESS));
if (var_sp)
{
variables->AddVariableIfUnique (var_sp);
@@ -7365,7 +3935,7 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
{
if (m_using_apple_tables)
{
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x)\n", die_offset);
+ GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x)\n", die_ref.die_offset);
}
}
@@ -7378,37 +3948,43 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
return 0;
}
-
VariableSP
SymbolFileDWARF::ParseVariableDIE
(
const SymbolContext& sc,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
+ const DWARFDIE &die,
const lldb::addr_t func_low_pc
)
{
- VariableSP var_sp (m_die_to_variable_sp[die]);
+ if (die.GetDWARF() != this)
+ return die.GetDWARF()->ParseVariableDIE(sc, die, func_low_pc);
+
+ VariableSP var_sp;
+ if (!die)
+ return var_sp;
+
+ var_sp = GetDIEToVariable()[die.GetDIE()];
if (var_sp)
return var_sp; // Already been parsed!
- const dw_tag_t tag = die->Tag();
+ const dw_tag_t tag = die.Tag();
ModuleSP module = GetObjectFile()->GetModule();
if ((tag == DW_TAG_variable) ||
(tag == DW_TAG_constant) ||
(tag == DW_TAG_formal_parameter && sc.function))
{
- DWARFDebugInfoEntry::Attributes attributes;
- const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
+ DWARFAttributes attributes;
+ const size_t num_attributes = die.GetAttributes(attributes);
+ DWARFDIE spec_die;
if (num_attributes > 0)
{
const char *name = NULL;
const char *mangled = NULL;
Declaration decl;
uint32_t i;
- lldb::user_id_t type_uid = LLDB_INVALID_UID;
- DWARFExpression location;
+ DWARFFormValue type_die_form;
+ DWARFExpression location(die.GetCU());
bool is_external = false;
bool is_artificial = false;
bool location_is_const_value_data = false;
@@ -7421,17 +3997,17 @@ SymbolFileDWARF::ParseVariableDIE
dw_attr_t attr = attributes.AttributeAtIndex(i);
DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+ if (attributes.ExtractFormValueAtIndex(i, form_value))
{
switch (attr)
{
case DW_AT_decl_file: decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
case DW_AT_decl_line: decl.SetLine(form_value.Unsigned()); break;
case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
- case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break;
+ case DW_AT_name: name = form_value.AsCString(); break;
case DW_AT_linkage_name:
- case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(&get_debug_str_data()); break;
- case DW_AT_type: type_uid = form_value.Reference(); break;
+ case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(); break;
+ case DW_AT_type: type_die_form = form_value; break;
case DW_AT_external: is_external = form_value.Boolean(); break;
case DW_AT_const_value:
// If we have already found a DW_AT_location attribute, ignore this attribute.
@@ -7450,9 +4026,12 @@ SymbolFileDWARF::ParseVariableDIE
else if (DWARFFormValue::IsDataForm(form_value.Form()))
{
// Retrieve the value as a data expression.
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), attributes.CompileUnitAtIndex(i)->IsDWARF64());
+ DWARFFormValue::FixedFormSizes fixed_form_sizes =
+ DWARFFormValue::GetFixedFormSizesForAddressSize (
+ attributes.CompileUnitAtIndex(i)->GetAddressByteSize(),
+ attributes.CompileUnitAtIndex(i)->IsDWARF64());
uint32_t data_offset = attributes.DIEOffsetAtIndex(i);
- uint32_t data_length = fixed_form_sizes[form_value.Form()];
+ uint32_t data_length = fixed_form_sizes.GetSize(form_value.Form());
if (data_length == 0)
{
const uint8_t *data_pointer = form_value.BlockData();
@@ -7474,14 +4053,17 @@ SymbolFileDWARF::ParseVariableDIE
// Retrieve the value as a string expression.
if (form_value.Form() == DW_FORM_strp)
{
- const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (attributes.CompileUnitAtIndex(i)->GetAddressByteSize(), attributes.CompileUnitAtIndex(i)->IsDWARF64());
+ DWARFFormValue::FixedFormSizes fixed_form_sizes =
+ DWARFFormValue::GetFixedFormSizesForAddressSize (
+ attributes.CompileUnitAtIndex(i)->GetAddressByteSize(),
+ attributes.CompileUnitAtIndex(i)->IsDWARF64());
uint32_t data_offset = attributes.DIEOffsetAtIndex(i);
- uint32_t data_length = fixed_form_sizes[form_value.Form()];
+ uint32_t data_length = fixed_form_sizes.GetSize(form_value.Form());
location.CopyOpcodeData(module, debug_info_data, data_offset, data_length);
}
else
{
- const char *str = form_value.AsCString(&debug_info_data);
+ const char *str = form_value.AsCString();
uint32_t string_offset = str - (const char *)debug_info_data.GetDataStart();
uint32_t string_length = strlen(str) + 1;
location.CopyOpcodeData(module, debug_info_data, string_offset, string_length);
@@ -7503,10 +4085,10 @@ SymbolFileDWARF::ParseVariableDIE
}
else
{
- const DWARFDataExtractor& debug_loc_data = get_debug_loc_data();
+ const DWARFDataExtractor& debug_loc_data = get_debug_loc_data();
const dw_offset_t debug_loc_offset = form_value.Unsigned();
- size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset);
+ size_t loc_list_length = DWARFExpression::LocationListSize(die.GetCU(), debug_loc_data, debug_loc_offset);
if (loc_list_length > 0)
{
location.CopyOpcodeData(module, debug_loc_data, debug_loc_offset, loc_list_length);
@@ -7516,7 +4098,13 @@ SymbolFileDWARF::ParseVariableDIE
}
}
break;
-
+ case DW_AT_specification:
+ {
+ DWARFDebugInfo* debug_info = DebugInfo();
+ if (debug_info)
+ spec_die = debug_info->GetDIE(DIERef(form_value));
+ break;
+ }
case DW_AT_artificial: is_artificial = form_value.Boolean(); break;
case DW_AT_accessibility: break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
case DW_AT_declaration:
@@ -7528,16 +4116,18 @@ SymbolFileDWARF::ParseVariableDIE
default:
case DW_AT_abstract_origin:
case DW_AT_sibling:
- case DW_AT_specification:
break;
}
}
}
+ const DWARFDIE parent_context_die = GetDeclContextDIEContainingDIE(die);
+ const dw_tag_t parent_tag = die.GetParent().Tag();
+ bool is_static_member = parent_tag == DW_TAG_compile_unit && (parent_context_die.Tag() == DW_TAG_class_type || parent_context_die.Tag() == DW_TAG_structure_type);
+
ValueType scope = eValueTypeInvalid;
- const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(die);
- dw_tag_t parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0;
+ const DWARFDIE sc_parent_die = GetParentSymbolContextDIE(die);
SymbolContextScope * symbol_context_scope = NULL;
if (!mangled)
@@ -7548,12 +4138,12 @@ SymbolFileDWARF::ParseVariableDIE
// B which in turn is contained in a namespace A, the command "frame var j" returns
// "(int) A::B::j = 4". If the compiler does not emit a linkage name, we should be able
// to generate a fully qualified name from the declaration context.
- if (die->GetParent()->Tag() == DW_TAG_compile_unit &&
- LanguageRuntime::LanguageIsCPlusPlus(dwarf_cu->GetLanguageType()))
+ if (parent_tag == DW_TAG_compile_unit &&
+ Language::LanguageIsCPlusPlus(die.GetLanguage()))
{
DWARFDeclContext decl_ctx;
- die->GetDWARFDeclContext(this, dwarf_cu, decl_ctx);
+ die.GetDWARFDeclContext(decl_ctx);
mangled = decl_ctx.GetQualifiedNameAsConstString().GetCString();
}
}
@@ -7582,7 +4172,7 @@ SymbolFileDWARF::ParseVariableDIE
{
StreamString strm;
location.DumpLocationForAddress (&strm, eDescriptionLevelFull, 0, 0, NULL);
- GetObjectFile()->GetModule()->ReportError ("0x%8.8x: %s has an invalid location: %s", die->GetOffset(), DW_TAG_value_to_name(die->Tag()), strm.GetString().c_str());
+ GetObjectFile()->GetModule()->ReportError ("0x%8.8x: %s has an invalid location: %s", die.GetOffset(), die.GetTagAsCString(), strm.GetString().c_str());
}
}
@@ -7670,7 +4260,10 @@ SymbolFileDWARF::ParseVariableDIE
}
else
{
- scope = eValueTypeVariableLocal;
+ if (location_is_const_value_data)
+ scope = eValueTypeVariableStatic;
+ else
+ scope = eValueTypeVariableLocal;
}
}
@@ -7683,7 +4276,7 @@ SymbolFileDWARF::ParseVariableDIE
case DW_TAG_lexical_block:
if (sc.function)
{
- symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(MakeUserID(sc_parent_die->GetOffset()));
+ symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
if (symbol_context_scope == NULL)
symbol_context_scope = sc.function;
}
@@ -7697,12 +4290,12 @@ SymbolFileDWARF::ParseVariableDIE
if (symbol_context_scope)
{
- SymbolFileTypeSP type_sp(new SymbolFileType(*this, type_uid));
+ SymbolFileTypeSP type_sp(new SymbolFileType(*this, DIERef(type_die_form).GetUID()));
if (const_value.Form() && type_sp && type_sp->GetType())
- location.CopyOpcodeData(const_value.Unsigned(), type_sp->GetType()->GetByteSize(), dwarf_cu->GetAddressByteSize());
+ location.CopyOpcodeData(const_value.Unsigned(), type_sp->GetType()->GetByteSize(), die.GetCU()->GetAddressByteSize());
- var_sp.reset (new Variable (MakeUserID(die->GetOffset()),
+ var_sp.reset (new Variable (die.GetID(),
name,
mangled,
type_sp,
@@ -7711,7 +4304,8 @@ SymbolFileDWARF::ParseVariableDIE
&decl,
location,
is_external,
- is_artificial));
+ is_artificial,
+ is_static_member));
var_sp->SetLocationIsConstantValueData (location_is_const_value_data);
}
@@ -7727,57 +4321,42 @@ SymbolFileDWARF::ParseVariableDIE
// was missing vital information to be able to be displayed in the debugger
// (missing location due to optimization, etc)) so we don't re-parse
// this DIE over and over later...
- m_die_to_variable_sp[die] = var_sp;
+ GetDIEToVariable()[die.GetDIE()] = var_sp;
+ if (spec_die)
+ GetDIEToVariable()[spec_die.GetDIE()] = var_sp;
}
return var_sp;
}
-const DWARFDebugInfoEntry *
-SymbolFileDWARF::FindBlockContainingSpecification (dw_offset_t func_die_offset,
- dw_offset_t spec_block_die_offset,
- DWARFCompileUnit **result_die_cu_handle)
+DWARFDIE
+SymbolFileDWARF::FindBlockContainingSpecification (const DIERef& func_die_ref,
+ dw_offset_t spec_block_die_offset)
{
// Give the concrete function die specified by "func_die_offset", find the
// concrete block whose DW_AT_specification or DW_AT_abstract_origin points
// to "spec_block_die_offset"
- DWARFDebugInfo* info = DebugInfo();
-
- const DWARFDebugInfoEntry *die = info->GetDIEPtrWithCompileUnitHint(func_die_offset, result_die_cu_handle);
- if (die)
- {
- assert (*result_die_cu_handle);
- return FindBlockContainingSpecification (*result_die_cu_handle, die, spec_block_die_offset, result_die_cu_handle);
- }
- return NULL;
+ return FindBlockContainingSpecification (DebugInfo()->GetDIE (func_die_ref), spec_block_die_offset);
}
-const DWARFDebugInfoEntry *
-SymbolFileDWARF::FindBlockContainingSpecification(DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
- dw_offset_t spec_block_die_offset,
- DWARFCompileUnit **result_die_cu_handle)
+DWARFDIE
+SymbolFileDWARF::FindBlockContainingSpecification(const DWARFDIE &die,
+ dw_offset_t spec_block_die_offset)
{
if (die)
{
- switch (die->Tag())
+ switch (die.Tag())
{
case DW_TAG_subprogram:
case DW_TAG_inlined_subroutine:
case DW_TAG_lexical_block:
{
- if (die->GetAttributeValueAsReference (this, dwarf_cu, DW_AT_specification, DW_INVALID_OFFSET) == spec_block_die_offset)
- {
- *result_die_cu_handle = dwarf_cu;
+ if (die.GetAttributeValueAsReference (DW_AT_specification, DW_INVALID_OFFSET) == spec_block_die_offset)
return die;
- }
- if (die->GetAttributeValueAsReference (this, dwarf_cu, DW_AT_abstract_origin, DW_INVALID_OFFSET) == spec_block_die_offset)
- {
- *result_die_cu_handle = dwarf_cu;
+ if (die.GetAttributeValueAsReference (DW_AT_abstract_origin, DW_INVALID_OFFSET) == spec_block_die_offset)
return die;
- }
}
break;
}
@@ -7785,49 +4364,42 @@ SymbolFileDWARF::FindBlockContainingSpecification(DWARFCompileUnit* dwarf_cu,
// Give the concrete function die specified by "func_die_offset", find the
// concrete block whose DW_AT_specification or DW_AT_abstract_origin points
// to "spec_block_die_offset"
- for (const DWARFDebugInfoEntry *child_die = die->GetFirstChild(); child_die != NULL; child_die = child_die->GetSibling())
+ for (DWARFDIE child_die = die.GetFirstChild(); child_die; child_die = child_die.GetSibling())
{
- const DWARFDebugInfoEntry *result_die = FindBlockContainingSpecification (dwarf_cu,
- child_die,
- spec_block_die_offset,
- result_die_cu_handle);
+ DWARFDIE result_die = FindBlockContainingSpecification (child_die, spec_block_die_offset);
if (result_die)
return result_die;
}
}
- *result_die_cu_handle = NULL;
- return NULL;
+ return DWARFDIE();
}
size_t
-SymbolFileDWARF::ParseVariables
-(
- const SymbolContext& sc,
- DWARFCompileUnit* dwarf_cu,
- const lldb::addr_t func_low_pc,
- const DWARFDebugInfoEntry *orig_die,
- bool parse_siblings,
- bool parse_children,
- VariableList* cc_variable_list
-)
+SymbolFileDWARF::ParseVariables (const SymbolContext& sc,
+ const DWARFDIE &orig_die,
+ const lldb::addr_t func_low_pc,
+ bool parse_siblings,
+ bool parse_children,
+ VariableList* cc_variable_list)
{
- if (orig_die == NULL)
+ if (!orig_die)
return 0;
VariableListSP variable_list_sp;
size_t vars_added = 0;
- const DWARFDebugInfoEntry *die = orig_die;
- while (die != NULL)
+ DWARFDIE die = orig_die;
+ while (die)
{
- dw_tag_t tag = die->Tag();
+ dw_tag_t tag = die.Tag();
// Check to see if we have already parsed this variable or constant?
- if (m_die_to_variable_sp[die])
+ VariableSP var_sp = GetDIEToVariable()[die.GetDIE()];
+ if (var_sp)
{
if (cc_variable_list)
- cc_variable_list->AddVariableIfUnique (m_die_to_variable_sp[die]);
+ cc_variable_list->AddVariableIfUnique (var_sp);
}
else
{
@@ -7838,8 +4410,8 @@ SymbolFileDWARF::ParseVariables
{
if (variable_list_sp.get() == NULL)
{
- const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(orig_die);
- dw_tag_t parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0;
+ DWARFDIE sc_parent_die = GetParentSymbolContextDIE(orig_die);
+ dw_tag_t parent_tag = sc_parent_die.Tag();
switch (parent_tag)
{
case DW_TAG_compile_unit:
@@ -7855,10 +4427,10 @@ SymbolFileDWARF::ParseVariables
else
{
GetObjectFile()->GetModule()->ReportError ("parent 0x%8.8" PRIx64 " %s with no valid compile unit in symbol context for 0x%8.8" PRIx64 " %s.\n",
- MakeUserID(sc_parent_die->GetOffset()),
- DW_TAG_value_to_name (parent_tag),
- MakeUserID(orig_die->GetOffset()),
- DW_TAG_value_to_name (orig_die->Tag()));
+ sc_parent_die.GetID(),
+ sc_parent_die.GetTagAsCString(),
+ orig_die.GetID(),
+ orig_die.GetTagAsCString());
}
break;
@@ -7869,19 +4441,17 @@ SymbolFileDWARF::ParseVariables
{
// Check to see if we already have parsed the variables for the given scope
- Block *block = sc.function->GetBlock(true).FindBlockByID(MakeUserID(sc_parent_die->GetOffset()));
+ Block *block = sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
if (block == NULL)
{
// This must be a specification or abstract origin with
// a concrete block counterpart in the current function. We need
// to find the concrete block so we can correctly add the
// variable to it
- DWARFCompileUnit *concrete_block_die_cu = dwarf_cu;
- const DWARFDebugInfoEntry *concrete_block_die = FindBlockContainingSpecification (sc.function->GetID(),
- sc_parent_die->GetOffset(),
- &concrete_block_die_cu);
+ const DWARFDIE concrete_block_die = FindBlockContainingSpecification (DIERef(sc.function->GetID()),
+ sc_parent_die.GetOffset());
if (concrete_block_die)
- block = sc.function->GetBlock(true).FindBlockByID(MakeUserID(concrete_block_die->GetOffset()));
+ block = sc.function->GetBlock(true).FindBlockByID(concrete_block_die.GetID());
}
if (block != NULL)
@@ -7899,15 +4469,15 @@ SymbolFileDWARF::ParseVariables
default:
GetObjectFile()->GetModule()->ReportError ("didn't find appropriate parent DIE for variable list for 0x%8.8" PRIx64 " %s.\n",
- MakeUserID(orig_die->GetOffset()),
- DW_TAG_value_to_name (orig_die->Tag()));
+ orig_die.GetID(),
+ orig_die.GetTagAsCString());
break;
}
}
if (variable_list_sp)
{
- VariableSP var_sp (ParseVariableDIE(sc, dwarf_cu, die, func_low_pc));
+ VariableSP var_sp (ParseVariableDIE(sc, die, func_low_pc));
if (var_sp)
{
variable_list_sp->AddVariableIfUnique (var_sp);
@@ -7921,15 +4491,15 @@ SymbolFileDWARF::ParseVariables
bool skip_children = (sc.function == NULL && tag == DW_TAG_subprogram);
- if (!skip_children && parse_children && die->HasChildren())
+ if (!skip_children && parse_children && die.HasChildren())
{
- vars_added += ParseVariables(sc, dwarf_cu, func_low_pc, die->GetFirstChild(), true, true, cc_variable_list);
+ vars_added += ParseVariables(sc, die.GetFirstChild(), func_low_pc, true, true, cc_variable_list);
}
if (parse_siblings)
- die = die->GetSibling();
+ die = die.GetSibling();
else
- die = NULL;
+ die.Clear();
}
return vars_added;
}
@@ -7950,24 +4520,6 @@ SymbolFileDWARF::GetPluginVersion()
}
void
-SymbolFileDWARF::CompleteTagDecl (void *baton, clang::TagDecl *decl)
-{
- SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton;
- ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl);
- if (clang_type)
- symbol_file_dwarf->ResolveClangOpaqueTypeDefinition (clang_type);
-}
-
-void
-SymbolFileDWARF::CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *decl)
-{
- SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton;
- ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl);
- if (clang_type)
- symbol_file_dwarf->ResolveClangOpaqueTypeDefinition (clang_type);
-}
-
-void
SymbolFileDWARF::DumpIndexes ()
{
StreamFile s(stdout, false);
@@ -7982,147 +4534,7 @@ SymbolFileDWARF::DumpIndexes ()
s.Printf("\nObjective C class selectors:\n"); m_objc_class_selectors_index.Dump (&s);
s.Printf("\nGlobals and statics:\n"); m_global_index.Dump (&s);
s.Printf("\nTypes:\n"); m_type_index.Dump (&s);
- s.Printf("\nNamepaces:\n"); m_namespace_index.Dump (&s);
-}
-
-void
-SymbolFileDWARF::SearchDeclContext (const clang::DeclContext *decl_context,
- const char *name,
- llvm::SmallVectorImpl <clang::NamedDecl *> *results)
-{
- DeclContextToDIEMap::iterator iter = m_decl_ctx_to_die.find(decl_context);
-
- if (iter == m_decl_ctx_to_die.end())
- return;
-
- for (DIEPointerSet::iterator pos = iter->second.begin(), end = iter->second.end(); pos != end; ++pos)
- {
- const DWARFDebugInfoEntry *context_die = *pos;
-
- if (!results)
- return;
-
- DWARFDebugInfo* info = DebugInfo();
-
- DIEArray die_offsets;
-
- DWARFCompileUnit* dwarf_cu = NULL;
- const DWARFDebugInfoEntry* die = NULL;
-
- if (m_using_apple_tables)
- {
- if (m_apple_types_ap.get())
- m_apple_types_ap->FindByName (name, die_offsets);
- }
- else
- {
- if (!m_indexed)
- Index ();
-
- m_type_index.Find (ConstString(name), die_offsets);
- }
-
- const size_t num_matches = die_offsets.size();
-
- if (num_matches)
- {
- for (size_t i = 0; i < num_matches; ++i)
- {
- const dw_offset_t die_offset = die_offsets[i];
- die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
-
- if (die->GetParent() != context_die)
- continue;
-
- Type *matching_type = ResolveType (dwarf_cu, die);
-
- clang::QualType qual_type = matching_type->GetClangForwardType().GetQualType();
-
- if (const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr()))
- {
- clang::TagDecl *tag_decl = tag_type->getDecl();
- results->push_back(tag_decl);
- }
- else if (const clang::TypedefType *typedef_type = llvm::dyn_cast<clang::TypedefType>(qual_type.getTypePtr()))
- {
- clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl();
- results->push_back(typedef_decl);
- }
- }
- }
- }
-}
-
-void
-SymbolFileDWARF::FindExternalVisibleDeclsByName (void *baton,
- const clang::DeclContext *decl_context,
- clang::DeclarationName decl_name,
- llvm::SmallVectorImpl <clang::NamedDecl *> *results)
-{
-
- switch (decl_context->getDeclKind())
- {
- case clang::Decl::Namespace:
- case clang::Decl::TranslationUnit:
- {
- SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton;
- symbol_file_dwarf->SearchDeclContext (decl_context, decl_name.getAsString().c_str(), results);
- }
- break;
- default:
- break;
- }
-}
-
-bool
-SymbolFileDWARF::LayoutRecordType(void *baton, const clang::RecordDecl *record_decl, uint64_t &size,
- uint64_t &alignment,
- llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets)
-{
- SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton;
- return symbol_file_dwarf->LayoutRecordType (record_decl, size, alignment, field_offsets, base_offsets, vbase_offsets);
-}
-
-bool
-SymbolFileDWARF::LayoutRecordType(const clang::RecordDecl *record_decl, uint64_t &bit_size, uint64_t &alignment,
- llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets)
-{
- Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
- RecordDeclToLayoutMap::iterator pos = m_record_decl_to_layout_map.find (record_decl);
- bool success = false;
- base_offsets.clear();
- vbase_offsets.clear();
- if (pos != m_record_decl_to_layout_map.end())
- {
- bit_size = pos->second.bit_size;
- alignment = pos->second.alignment;
- field_offsets.swap(pos->second.field_offsets);
- base_offsets.swap (pos->second.base_offsets);
- vbase_offsets.swap (pos->second.vbase_offsets);
- m_record_decl_to_layout_map.erase(pos);
- success = true;
- }
- else
- {
- bit_size = 0;
- alignment = 0;
- field_offsets.clear();
- }
-
- if (log)
- GetObjectFile()->GetModule()->LogMessage (log,
- "SymbolFileDWARF::LayoutRecordType (record_decl = %p, bit_size = %" PRIu64 ", alignment = %" PRIu64 ", field_offsets[%u],base_offsets[%u], vbase_offsets[%u]) success = %i",
- static_cast<const void*>(record_decl),
- bit_size, alignment,
- static_cast<uint32_t>(field_offsets.size()),
- static_cast<uint32_t>(base_offsets.size()),
- static_cast<uint32_t>(vbase_offsets.size()),
- success);
- return success;
+ s.Printf("\nNamespaces:\n"); m_namespace_index.Dump (&s);
}
@@ -8142,4 +4554,8 @@ SymbolFileDWARF::GetDebugMapSymfile ()
return m_debug_map_symfile;
}
-
+DWARFExpression::LocationListFormat
+SymbolFileDWARF::GetLocationListFormat() const
+{
+ return DWARFExpression::RegularLocationList;
+}
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 2f0b3f05b153..c2e78a417b7a 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -14,24 +14,22 @@
// C++ Includes
#include <list>
#include <map>
+#include <mutex>
#include <set>
+#include <unordered_map>
#include <vector>
// Other libraries and framework includes
-#include "clang/AST/CharUnits.h"
-#include "clang/AST/ExternalASTSource.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/SmallVector.h"
#include "lldb/lldb-private.h"
-#include "lldb/Core/ClangForward.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/dwarf.h"
#include "lldb/Core/Flags.h"
#include "lldb/Core/RangeMap.h"
#include "lldb/Core/UniqueCStringMap.h"
-#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Symbol/DebugMacros.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -61,12 +59,18 @@ class DWARFDIECollection;
class DWARFFormValue;
class SymbolFileDWARFDebugMap;
+#define DIE_IS_BEING_PARSED ((lldb_private::Type*)1)
+
class SymbolFileDWARF : public lldb_private::SymbolFile, public lldb_private::UserID
{
public:
friend class SymbolFileDWARFDebugMap;
+ friend class SymbolFileDWARFDwo;
friend class DebugMapModule;
friend class DWARFCompileUnit;
+ friend class DWARFASTParserClang;
+ friend class DWARFASTParserGo;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
@@ -76,6 +80,9 @@ public:
static void
Terminate();
+ static void
+ DebuggerInitialize(lldb_private::Debugger &debugger);
+
static lldb_private::ConstString
GetPluginNameStatic();
@@ -84,481 +91,419 @@ public:
static lldb_private::SymbolFile*
CreateInstance (lldb_private::ObjectFile* obj_file);
+
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
- SymbolFileDWARF(lldb_private::ObjectFile* ofile);
- virtual ~SymbolFileDWARF();
- virtual uint32_t CalculateAbilities ();
- virtual void InitializeObject();
+ SymbolFileDWARF(lldb_private::ObjectFile* ofile);
+
+ ~SymbolFileDWARF() override;
+
+ uint32_t
+ CalculateAbilities () override;
+
+ void
+ InitializeObject() override;
//------------------------------------------------------------------
// Compile Unit function calls
//------------------------------------------------------------------
- virtual uint32_t GetNumCompileUnits();
- virtual lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index);
-
- virtual lldb::LanguageType ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc);
- virtual size_t ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc);
- virtual bool ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc);
- virtual bool ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList& support_files);
- virtual bool ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector<lldb_private::ConstString> &imported_modules);
- virtual size_t ParseFunctionBlocks (const lldb_private::SymbolContext& sc);
- virtual size_t ParseTypes (const lldb_private::SymbolContext& sc);
- virtual size_t ParseVariablesForContext (const lldb_private::SymbolContext& sc);
-
- virtual lldb_private::Type* ResolveTypeUID(lldb::user_id_t type_uid);
- virtual bool ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_type);
-
- virtual lldb_private::Type* ResolveType (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* type_die, bool assert_not_being_parsed = true);
- virtual clang::DeclContext* GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid);
- virtual clang::DeclContext* GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid);
-
- virtual uint32_t ResolveSymbolContext (const lldb_private::Address& so_addr, uint32_t resolve_scope, lldb_private::SymbolContext& sc);
- virtual uint32_t ResolveSymbolContext (const lldb_private::FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, lldb_private::SymbolContextList& sc_list);
- virtual uint32_t FindGlobalVariables(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
- virtual uint32_t FindGlobalVariables(const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
- virtual uint32_t FindFunctions(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list);
- virtual uint32_t FindFunctions(const lldb_private::RegularExpression& regex, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list);
- virtual uint32_t FindTypes (const lldb_private::SymbolContext& sc, const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::TypeList& types);
- virtual lldb_private::TypeList *
- GetTypeList ();
- virtual size_t GetTypes (lldb_private::SymbolContextScope *sc_scope,
- uint32_t type_mask,
- lldb_private::TypeList &type_list);
-
- virtual lldb_private::ClangASTContext &
- GetClangASTContext ();
-
- virtual lldb_private::ClangNamespaceDecl
- FindNamespace (const lldb_private::SymbolContext& sc,
- const lldb_private::ConstString &name,
- const lldb_private::ClangNamespaceDecl *parent_namespace_decl);
+ uint32_t
+ GetNumCompileUnits() override;
- //------------------------------------------------------------------
- // ClangASTContext callbacks for external source lookups.
- //------------------------------------------------------------------
- static void
- CompleteTagDecl (void *baton, clang::TagDecl *);
-
- static void
- CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *);
+ lldb::CompUnitSP
+ ParseCompileUnitAtIndex(uint32_t index) override;
+
+ lldb::LanguageType
+ ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc) override;
+
+ size_t
+ ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc) override;
+
+ bool
+ ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc) override;
+
+ bool
+ ParseCompileUnitDebugMacros (const lldb_private::SymbolContext& sc) override;
+
+ bool
+ ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc,
+ lldb_private::FileSpecList& support_files) override;
+
+ bool
+ ParseImportedModules (const lldb_private::SymbolContext &sc,
+ std::vector<lldb_private::ConstString> &imported_modules) override;
+
+ size_t
+ ParseFunctionBlocks (const lldb_private::SymbolContext& sc) override;
+
+ size_t
+ ParseTypes (const lldb_private::SymbolContext& sc) override;
+
+ size_t
+ ParseVariablesForContext (const lldb_private::SymbolContext& sc) override;
+
+ lldb_private::Type *
+ ResolveTypeUID(lldb::user_id_t type_uid) override;
+
+ bool
+ CompleteType (lldb_private::CompilerType& compiler_type) override;
+
+ lldb_private::Type *
+ ResolveType (const DWARFDIE &die,
+ bool assert_not_being_parsed = true,
+ bool resolve_function_context = false);
+
+ lldb_private::CompilerDecl
+ GetDeclForUID (lldb::user_id_t uid) override;
+
+ lldb_private::CompilerDeclContext
+ GetDeclContextForUID (lldb::user_id_t uid) override;
+
+ lldb_private::CompilerDeclContext
+ GetDeclContextContainingUID (lldb::user_id_t uid) override;
+
+ void
+ ParseDeclsForContext (lldb_private::CompilerDeclContext decl_ctx) override;
- static void
- FindExternalVisibleDeclsByName (void *baton,
- const clang::DeclContext *DC,
- clang::DeclarationName Name,
- llvm::SmallVectorImpl <clang::NamedDecl *> *results);
-
- static bool LayoutRecordType(void *baton, const clang::RecordDecl *record_decl, uint64_t &size, uint64_t &alignment,
- llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets);
-
- bool LayoutRecordType(const clang::RecordDecl *record_decl, uint64_t &size, uint64_t &alignment,
- llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets);
-
- struct LayoutInfo
- {
- LayoutInfo () :
- bit_size(0),
- alignment(0),
- field_offsets(),
- base_offsets(),
- vbase_offsets()
- {
- }
- uint64_t bit_size;
- uint64_t alignment;
- llvm::DenseMap<const clang::FieldDecl *, uint64_t> field_offsets;
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> base_offsets;
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> vbase_offsets;
- };
+
+ uint32_t
+ ResolveSymbolContext (const lldb_private::Address& so_addr,
+ uint32_t resolve_scope,
+ lldb_private::SymbolContext& sc) override;
+
+ uint32_t
+ ResolveSymbolContext (const lldb_private::FileSpec& file_spec,
+ uint32_t line,
+ bool check_inlines,
+ uint32_t resolve_scope,
+ lldb_private::SymbolContextList& sc_list) override;
+
+ uint32_t
+ FindGlobalVariables (const lldb_private::ConstString &name,
+ const lldb_private::CompilerDeclContext *parent_decl_ctx,
+ bool append,
+ uint32_t max_matches,
+ lldb_private::VariableList& variables) override;
+
+ uint32_t
+ FindGlobalVariables (const lldb_private::RegularExpression& regex,
+ bool append,
+ uint32_t max_matches,
+ lldb_private::VariableList& variables) override;
+
+ uint32_t
+ FindFunctions (const lldb_private::ConstString &name,
+ const lldb_private::CompilerDeclContext *parent_decl_ctx,
+ uint32_t name_type_mask,
+ bool include_inlines,
+ bool append,
+ lldb_private::SymbolContextList& sc_list) override;
+
+ uint32_t
+ FindFunctions (const lldb_private::RegularExpression& regex,
+ bool include_inlines,
+ bool append,
+ lldb_private::SymbolContextList& sc_list) override;
+
+ uint32_t
+ FindTypes (const lldb_private::SymbolContext& sc,
+ const lldb_private::ConstString &name,
+ const lldb_private::CompilerDeclContext *parent_decl_ctx,
+ bool append,
+ uint32_t max_matches,
+ lldb_private::TypeMap& types) override;
+
+ size_t
+ FindTypes (const std::vector<lldb_private::CompilerContext> &context,
+ bool append,
+ lldb_private::TypeMap& types) override;
+
+ lldb_private::TypeList *
+ GetTypeList () override;
+
+ size_t
+ GetTypes (lldb_private::SymbolContextScope *sc_scope,
+ uint32_t type_mask,
+ lldb_private::TypeList &type_list) override;
+
+ lldb_private::TypeSystem *
+ GetTypeSystemForLanguage (lldb::LanguageType language) override;
+
+ lldb_private::CompilerDeclContext
+ FindNamespace (const lldb_private::SymbolContext& sc,
+ const lldb_private::ConstString &name,
+ const lldb_private::CompilerDeclContext *parent_decl_ctx) override;
+
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
-
- virtual uint32_t
- GetPluginVersion();
+ lldb_private::ConstString
+ GetPluginName() override;
- // Approach 2 - count + accessor
- // Index compile units would scan the initial compile units and register
- // them with the module. This would only be done on demand if and only if
- // the compile units were needed.
- //virtual size_t GetCompUnitCount() = 0;
- //virtual CompUnitSP GetCompUnitAtIndex(size_t cu_idx) = 0;
+ uint32_t
+ GetPluginVersion() override;
const lldb_private::DWARFDataExtractor& get_debug_abbrev_data ();
+ const lldb_private::DWARFDataExtractor& get_debug_addr_data ();
const lldb_private::DWARFDataExtractor& get_debug_aranges_data ();
const lldb_private::DWARFDataExtractor& get_debug_frame_data ();
const lldb_private::DWARFDataExtractor& get_debug_info_data ();
const lldb_private::DWARFDataExtractor& get_debug_line_data ();
+ const lldb_private::DWARFDataExtractor& get_debug_macro_data ();
const lldb_private::DWARFDataExtractor& get_debug_loc_data ();
const lldb_private::DWARFDataExtractor& get_debug_ranges_data ();
const lldb_private::DWARFDataExtractor& get_debug_str_data ();
+ const lldb_private::DWARFDataExtractor& get_debug_str_offsets_data ();
const lldb_private::DWARFDataExtractor& get_apple_names_data ();
const lldb_private::DWARFDataExtractor& get_apple_types_data ();
const lldb_private::DWARFDataExtractor& get_apple_namespaces_data ();
const lldb_private::DWARFDataExtractor& get_apple_objc_data ();
- DWARFDebugAbbrev* DebugAbbrev();
- const DWARFDebugAbbrev* DebugAbbrev() const;
+ DWARFDebugAbbrev*
+ DebugAbbrev();
- DWARFDebugInfo* DebugInfo();
- const DWARFDebugInfo* DebugInfo() const;
+ const DWARFDebugAbbrev*
+ DebugAbbrev() const;
- DWARFDebugRanges* DebugRanges();
- const DWARFDebugRanges* DebugRanges() const;
+ DWARFDebugInfo*
+ DebugInfo();
- const lldb_private::DWARFDataExtractor&
- GetCachedSectionData (uint32_t got_flag,
- lldb::SectionType sect_type,
- lldb_private::DWARFDataExtractor &data);
+ const DWARFDebugInfo*
+ DebugInfo() const;
+
+ DWARFDebugRanges*
+ DebugRanges();
+
+ const DWARFDebugRanges*
+ DebugRanges() const;
static bool
SupportedVersion(uint16_t version);
- clang::DeclContext *
- GetCachedClangDeclContextForDIE (const DWARFDebugInfoEntry *die)
- {
- DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die);
- if (pos != m_die_to_decl_ctx.end())
- return pos->second;
- else
- return NULL;
- }
+ DWARFDIE
+ GetDeclContextDIEContainingDIE (const DWARFDIE &die);
- clang::DeclContext *
- GetClangDeclContextForDIE (const lldb_private::SymbolContext &sc, DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die);
-
- clang::DeclContext *
- GetClangDeclContextForDIEOffset (const lldb_private::SymbolContext &sc, dw_offset_t die_offset);
-
- clang::DeclContext *
- GetClangDeclContextContainingDIE (DWARFCompileUnit *cu,
- const DWARFDebugInfoEntry *die,
- const DWARFDebugInfoEntry **decl_ctx_die);
-
- clang::DeclContext *
- GetClangDeclContextContainingDIEOffset (dw_offset_t die_offset);
+ bool
+ HasForwardDeclForClangType (const lldb_private::CompilerType &compiler_type);
- const DWARFDebugInfoEntry *
- GetDeclContextDIEContainingDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die);
+ lldb_private::CompileUnit*
+ GetCompUnitForDWARFCompUnit(DWARFCompileUnit* dwarf_cu,
+ uint32_t cu_idx = UINT32_MAX);
- void
- SearchDeclContext (const clang::DeclContext *decl_context,
- const char *name,
- llvm::SmallVectorImpl <clang::NamedDecl *> *results);
-
- lldb_private::Flags&
- GetFlags ()
+ lldb::user_id_t
+ MakeUserID (dw_offset_t die_offset) const
{
- return m_flags;
+ return GetID() | die_offset;
}
- const lldb_private::Flags&
- GetFlags () const
- {
- return m_flags;
- }
+ size_t
+ GetObjCMethodDIEOffsets (lldb_private::ConstString class_name,
+ DIEArray &method_die_offsets);
bool
- HasForwardDeclForClangType (const lldb_private::ClangASTType &clang_type);
+ Supports_DW_AT_APPLE_objc_complete_type (DWARFCompileUnit *cu);
+
+ lldb_private::DebugMacrosSP
+ ParseDebugMacros(lldb::offset_t *offset);
+
+ static DWARFDIE
+ GetParentSymbolContextDIE(const DWARFDIE &die);
+
+ virtual lldb::CompUnitSP
+ ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx);
+
+ virtual lldb_private::DWARFExpression::LocationListFormat
+ GetLocationListFormat() const;
+
+ lldb::ModuleSP
+ GetDWOModule (lldb_private::ConstString name);
protected:
+ typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr;
+ typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP> DIEToVariableSP;
+ typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::opaque_compiler_type_t> DIEToClangType;
+ typedef llvm::DenseMap<lldb::opaque_compiler_type_t, DIERef> ClangTypeToDIE;
- enum
+ struct DWARFDataSegment
{
- flagsGotDebugAbbrevData = (1 << 0),
- flagsGotDebugArangesData = (1 << 1),
- flagsGotDebugFrameData = (1 << 2),
- flagsGotDebugInfoData = (1 << 3),
- flagsGotDebugLineData = (1 << 4),
- flagsGotDebugLocData = (1 << 5),
- flagsGotDebugMacInfoData = (1 << 6),
- flagsGotDebugPubNamesData = (1 << 7),
- flagsGotDebugPubTypesData = (1 << 8),
- flagsGotDebugRangesData = (1 << 9),
- flagsGotDebugStrData = (1 << 10),
- flagsGotAppleNamesData = (1 << 11),
- flagsGotAppleTypesData = (1 << 12),
- flagsGotAppleNamespacesData = (1 << 13),
- flagsGotAppleObjCData = (1 << 14)
+ std::once_flag m_flag;
+ lldb_private::DWARFDataExtractor m_data;
};
-
- bool NamespaceDeclMatchesThisSymbolFile (const lldb_private::ClangNamespaceDecl *namespace_decl);
-
- bool DIEIsInNamespace (const lldb_private::ClangNamespaceDecl *namespace_decl,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry* die);
DISALLOW_COPY_AND_ASSIGN (SymbolFileDWARF);
- lldb::CompUnitSP ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx);
- DWARFCompileUnit* GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit);
- DWARFCompileUnit* GetNextUnparsedDWARFCompileUnit(DWARFCompileUnit* prev_cu);
- lldb_private::CompileUnit* GetCompUnitForDWARFCompUnit(DWARFCompileUnit* dwarf_cu, uint32_t cu_idx = UINT32_MAX);
- bool GetFunction (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* func_die, lldb_private::SymbolContext& sc);
- lldb_private::Function * ParseCompileUnitFunction (const lldb_private::SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die);
- size_t ParseFunctionBlocks (const lldb_private::SymbolContext& sc,
- lldb_private::Block *parent_block,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
- lldb::addr_t subprogram_low_pc,
- uint32_t depth);
- size_t ParseTypes (const lldb_private::SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool parse_siblings, bool parse_children);
- lldb::TypeSP ParseType (const lldb_private::SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool *type_is_new);
- lldb_private::Type* ResolveTypeUID (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* die, bool assert_not_being_parsed);
-
- lldb::VariableSP ParseVariableDIE(
- const lldb_private::SymbolContext& sc,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
- const lldb::addr_t func_low_pc);
-
- size_t ParseVariables(
- const lldb_private::SymbolContext& sc,
- DWARFCompileUnit* dwarf_cu,
- const lldb::addr_t func_low_pc,
- const DWARFDebugInfoEntry *die,
- bool parse_siblings,
- bool parse_children,
- lldb_private::VariableList* cc_variable_list = NULL);
-
- class DelayedAddObjCClassProperty;
- typedef std::vector <DelayedAddObjCClassProperty> DelayedPropertyList;
-
- bool ClassOrStructIsVirtual (
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die);
-
- size_t ParseChildMembers(
- const lldb_private::SymbolContext& sc,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
- lldb_private::ClangASTType &class_clang_type,
- const lldb::LanguageType class_language,
- std::vector<clang::CXXBaseSpecifier *>& base_classes,
- std::vector<int>& member_accessibilities,
- DWARFDIECollection& member_function_dies,
- DelayedPropertyList& delayed_properties,
- lldb::AccessType &default_accessibility,
- bool &is_a_class,
- LayoutInfo &layout_info);
-
- size_t ParseChildParameters(
- const lldb_private::SymbolContext& sc,
- clang::DeclContext *containing_decl_ctx,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die,
- bool skip_artificial,
- bool &is_static,
- bool &is_variadic,
- std::vector<lldb_private::ClangASTType>& function_args,
- std::vector<clang::ParmVarDecl*>& function_param_decls,
- unsigned &type_quals);
- // lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos); // not currently needed
-
-
- size_t ParseChildEnumerators(
- const lldb_private::SymbolContext& sc,
- lldb_private::ClangASTType &clang_type,
- bool is_signed,
- uint32_t enumerator_byte_size,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *enum_die);
-
- void ParseChildArrayInfo(
- const lldb_private::SymbolContext& sc,
- DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die,
- int64_t& first_index,
- std::vector<uint64_t>& element_orders,
- uint32_t& byte_stride,
- uint32_t& bit_stride);
-
- // Given a die_offset, figure out the symbol context representing that die.
- bool ResolveFunction (dw_offset_t offset,
- DWARFCompileUnit *&dwarf_cu,
- bool include_inlines,
- lldb_private::SymbolContextList& sc_list);
-
- bool ResolveFunction (DWARFCompileUnit *cu,
- const DWARFDebugInfoEntry *die,
- bool include_inlines,
- lldb_private::SymbolContextList& sc_list);
-
- bool FunctionDieMatchesPartialName (
- const DWARFDebugInfoEntry* die,
- const DWARFCompileUnit *dwarf_cu,
- uint32_t name_type_mask,
- const char *partial_name,
- const char *base_name_start,
- const char *base_name_end);
-
- void FindFunctions(
- const lldb_private::ConstString &name,
- const NameToDIE &name_to_die,
- bool include_inlines,
- lldb_private::SymbolContextList& sc_list);
-
- void FindFunctions (
- const lldb_private::RegularExpression &regex,
- const NameToDIE &name_to_die,
- bool include_inlines,
- lldb_private::SymbolContextList& sc_list);
-
- void FindFunctions (
- const lldb_private::RegularExpression &regex,
- const DWARFMappedHash::MemoryTable &memory_table,
- bool include_inlines,
- lldb_private::SymbolContextList& sc_list);
-
- lldb::TypeSP FindDefinitionTypeForDWARFDeclContext (
- const DWARFDeclContext &die_decl_ctx);
-
- lldb::TypeSP FindCompleteObjCDefinitionTypeForDIE (
- const DWARFDebugInfoEntry *die,
- const lldb_private::ConstString &type_name,
- bool must_be_implementation);
-
- bool Supports_DW_AT_APPLE_objc_complete_type (DWARFCompileUnit *cu);
-
- lldb::TypeSP FindCompleteObjCDefinitionType (const lldb_private::ConstString &type_name,
- bool header_definition_ok);
-
- lldb_private::Symbol * GetObjCClassSymbol (const lldb_private::ConstString &objc_class_name);
-
- void ParseFunctions (const DIEArray &die_offsets,
- bool include_inlines,
- lldb_private::SymbolContextList& sc_list);
- lldb::TypeSP GetTypeForDIE (DWARFCompileUnit *cu,
- const DWARFDebugInfoEntry* die);
-
- uint32_t FindTypes(std::vector<dw_offset_t> die_offsets, uint32_t max_matches, lldb_private::TypeList& types);
-
- void Index();
-
- void DumpIndexes();
- void SetDebugMapModule (const lldb::ModuleSP &module_sp)
- {
- m_debug_map_module_wp = module_sp;
- }
+ const lldb_private::DWARFDataExtractor&
+ GetCachedSectionData (lldb::SectionType sect_type, DWARFDataSegment& data_segment);
+
+ virtual void
+ LoadSectionData (lldb::SectionType sect_type, lldb_private::DWARFDataExtractor& data);
+
+ bool
+ DeclContextMatchesThisSymbolFile (const lldb_private::CompilerDeclContext *decl_ctx);
+
+ bool
+ DIEInDeclContext (const lldb_private::CompilerDeclContext *parent_decl_ctx,
+ const DWARFDIE &die);
+
+ virtual DWARFCompileUnit*
+ GetDWARFCompileUnit (lldb_private::CompileUnit *comp_unit);
+
+ DWARFCompileUnit*
+ GetNextUnparsedDWARFCompileUnit (DWARFCompileUnit* prev_cu);
+
+ bool
+ GetFunction (const DWARFDIE &die,
+ lldb_private::SymbolContext& sc);
+
+ lldb_private::Function *
+ ParseCompileUnitFunction (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &die);
+
+ size_t
+ ParseFunctionBlocks (const lldb_private::SymbolContext& sc,
+ lldb_private::Block *parent_block,
+ const DWARFDIE &die,
+ lldb::addr_t subprogram_low_pc,
+ uint32_t depth);
+
+ size_t
+ ParseTypes (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &die,
+ bool parse_siblings,
+ bool parse_children);
+
+ lldb::TypeSP
+ ParseType (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &die,
+ bool *type_is_new);
+
+ lldb_private::Type *
+ ResolveTypeUID (const DWARFDIE &die,
+ bool assert_not_being_parsed);
+
+ lldb::VariableSP
+ ParseVariableDIE(const lldb_private::SymbolContext& sc,
+ const DWARFDIE &die,
+ const lldb::addr_t func_low_pc);
+
+ size_t
+ ParseVariables (const lldb_private::SymbolContext& sc,
+ const DWARFDIE &orig_die,
+ const lldb::addr_t func_low_pc,
+ bool parse_siblings,
+ bool parse_children,
+ lldb_private::VariableList* cc_variable_list = NULL);
+
+ bool
+ ClassOrStructIsVirtual (const DWARFDIE &die);
+
+ // Given a die_offset, figure out the symbol context representing that die.
+ bool
+ ResolveFunction (const DIERef& die_ref,
+ bool include_inlines,
+ lldb_private::SymbolContextList& sc_list);
+
+ bool
+ ResolveFunction (const DWARFDIE &die,
+ bool include_inlines,
+ lldb_private::SymbolContextList& sc_list);
+
+ void
+ FindFunctions(const lldb_private::ConstString &name,
+ const NameToDIE &name_to_die,
+ bool include_inlines,
+ lldb_private::SymbolContextList& sc_list);
+
+ void
+ FindFunctions (const lldb_private::RegularExpression &regex,
+ const NameToDIE &name_to_die,
+ bool include_inlines,
+ lldb_private::SymbolContextList& sc_list);
+
+ void
+ FindFunctions (const lldb_private::RegularExpression &regex,
+ const DWARFMappedHash::MemoryTable &memory_table,
+ bool include_inlines,
+ lldb_private::SymbolContextList& sc_list);
+
+ virtual lldb::TypeSP
+ FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx);
+
+ lldb::TypeSP
+ FindCompleteObjCDefinitionTypeForDIE (const DWARFDIE &die,
+ const lldb_private::ConstString &type_name,
+ bool must_be_implementation);
+
+ lldb::TypeSP
+ FindCompleteObjCDefinitionType (const lldb_private::ConstString &type_name,
+ bool header_definition_ok);
+
+ lldb_private::Symbol *
+ GetObjCClassSymbol (const lldb_private::ConstString &objc_class_name);
+
+ void
+ ParseFunctions (const DIEArray &die_offsets,
+ bool include_inlines,
+ lldb_private::SymbolContextList& sc_list);
+
+ lldb::TypeSP
+ GetTypeForDIE (const DWARFDIE &die, bool resolve_function_context = false);
+
+ void
+ Index();
- SymbolFileDWARFDebugMap *
- GetDebugMapSymfile ();
+ void
+ DumpIndexes();
- const DWARFDebugInfoEntry *
- FindBlockContainingSpecification (dw_offset_t func_die_offset,
- dw_offset_t spec_block_die_offset,
- DWARFCompileUnit **dwarf_cu_handle);
+ void
+ SetDebugMapModule (const lldb::ModuleSP &module_sp)
+ {
+ m_debug_map_module_wp = module_sp;
+ }
+
+ SymbolFileDWARFDebugMap *
+ GetDebugMapSymfile ();
- const DWARFDebugInfoEntry *
- FindBlockContainingSpecification (DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
- dw_offset_t spec_block_die_offset,
- DWARFCompileUnit **dwarf_cu_handle);
+ DWARFDIE
+ FindBlockContainingSpecification (const DIERef& func_die_ref, dw_offset_t spec_block_die_offset);
- clang::NamespaceDecl *
- ResolveNamespaceDIE (DWARFCompileUnit *curr_cu, const DWARFDebugInfoEntry *die);
+ DWARFDIE
+ FindBlockContainingSpecification (const DWARFDIE &die, dw_offset_t spec_block_die_offset);
- UniqueDWARFASTTypeMap &
+ virtual UniqueDWARFASTTypeMap &
GetUniqueDWARFASTTypeMap ();
-
- void LinkDeclContextToDIE (clang::DeclContext *decl_ctx,
- const DWARFDebugInfoEntry *die)
- {
- m_die_to_decl_ctx[die] = decl_ctx;
- // There can be many DIEs for a single decl context
- m_decl_ctx_to_die[decl_ctx].insert(die);
- }
bool
UserIDMatches (lldb::user_id_t uid) const
{
const lldb::user_id_t high_uid = uid & 0xffffffff00000000ull;
- if (high_uid)
+ if (high_uid != 0 && GetID() != 0)
return high_uid == GetID();
return true;
}
- lldb::user_id_t
- MakeUserID (dw_offset_t die_offset) const
- {
- return GetID() | die_offset;
- }
-
- static bool
- DeclKindIsCXXClass (clang::Decl::Kind decl_kind)
- {
- switch (decl_kind)
- {
- case clang::Decl::CXXRecord:
- case clang::Decl::ClassTemplateSpecialization:
- return true;
- default:
- break;
- }
- return false;
- }
-
- bool
- ParseTemplateParameterInfos (DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *parent_die,
- lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos);
-
bool
- ParseTemplateDIE (DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
- lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos);
-
- clang::ClassTemplateDecl *
- ParseClassTemplateDecl (clang::DeclContext *decl_ctx,
- lldb::AccessType access_type,
- const char *parent_name,
- int tag_decl_kind,
- const lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos);
-
- bool
- DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugInfoEntry *die1,
- DWARFCompileUnit* cu2, const DWARFDebugInfoEntry *die2);
+ DIEDeclContextsMatch (const DWARFDIE &die1,
+ const DWARFDIE &die2);
bool
- ClassContainsSelector (DWARFCompileUnit *dwarf_cu,
- const DWARFDebugInfoEntry *class_die,
+ ClassContainsSelector (const DWARFDIE &class_die,
const lldb_private::ConstString &selector);
bool
- CopyUniqueClassMethodTypes (SymbolFileDWARF *class_symfile,
- lldb_private::Type *class_type,
- DWARFCompileUnit* src_cu,
- const DWARFDebugInfoEntry *src_class_die,
- DWARFCompileUnit* dst_cu,
- const DWARFDebugInfoEntry *dst_class_die,
- DWARFDIECollection &failures);
-
- bool
FixupAddress (lldb_private::Address &addr);
typedef std::set<lldb_private::Type *> TypeSet;
- typedef struct {
- lldb_private::ConstString m_name;
- lldb::ModuleSP m_module_sp;
- } ClangModuleInfo;
-
- typedef std::map<uint64_t, ClangModuleInfo> ExternalTypeModuleMap;
+ typedef std::map<lldb_private::ConstString, lldb::ModuleSP> ExternalTypeModuleMap;
void
- GetTypes (DWARFCompileUnit* dwarf_cu,
- const DWARFDebugInfoEntry *die,
+ GetTypes (const DWARFDIE &die,
dw_offset_t min_die_offset,
dw_offset_t max_die_offset,
uint32_t type_mask,
@@ -572,23 +517,37 @@ protected:
void
UpdateExternalModuleListIfNeeded();
+ virtual DIEToTypePtr&
+ GetDIEToType() { return m_die_to_type; }
+
+ virtual DIEToVariableSP&
+ GetDIEToVariable() { return m_die_to_variable_sp; }
+
+ virtual DIEToClangType&
+ GetForwardDeclDieToClangType() { return m_forward_decl_die_to_clang_type; }
+
+ virtual ClangTypeToDIE&
+ GetForwardDeclClangTypeToDie() { return m_forward_decl_clang_type_to_die; }
+
lldb::ModuleWP m_debug_map_module_wp;
SymbolFileDWARFDebugMap * m_debug_map_symfile;
- clang::TranslationUnitDecl * m_clang_tu_decl;
- lldb_private::Flags m_flags;
- lldb_private::DWARFDataExtractor m_dwarf_data;
- lldb_private::DWARFDataExtractor m_data_debug_abbrev;
- lldb_private::DWARFDataExtractor m_data_debug_aranges;
- lldb_private::DWARFDataExtractor m_data_debug_frame;
- lldb_private::DWARFDataExtractor m_data_debug_info;
- lldb_private::DWARFDataExtractor m_data_debug_line;
- lldb_private::DWARFDataExtractor m_data_debug_loc;
- lldb_private::DWARFDataExtractor m_data_debug_ranges;
- lldb_private::DWARFDataExtractor m_data_debug_str;
- lldb_private::DWARFDataExtractor m_data_apple_names;
- lldb_private::DWARFDataExtractor m_data_apple_types;
- lldb_private::DWARFDataExtractor m_data_apple_namespaces;
- lldb_private::DWARFDataExtractor m_data_apple_objc;
+ lldb_private::DWARFDataExtractor m_dwarf_data;
+
+ DWARFDataSegment m_data_debug_abbrev;
+ DWARFDataSegment m_data_debug_addr;
+ DWARFDataSegment m_data_debug_aranges;
+ DWARFDataSegment m_data_debug_frame;
+ DWARFDataSegment m_data_debug_info;
+ DWARFDataSegment m_data_debug_line;
+ DWARFDataSegment m_data_debug_macro;
+ DWARFDataSegment m_data_debug_loc;
+ DWARFDataSegment m_data_debug_ranges;
+ DWARFDataSegment m_data_debug_str;
+ DWARFDataSegment m_data_debug_str_offsets;
+ DWARFDataSegment m_data_apple_names;
+ DWARFDataSegment m_data_apple_types;
+ DWARFDataSegment m_data_apple_namespaces;
+ DWARFDataSegment m_data_apple_objc;
// The unique pointer items below are generated on demand if and when someone accesses
// them through a non const version of this class.
@@ -600,6 +559,10 @@ protected:
std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_namespaces_ap;
std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_objc_ap;
std::unique_ptr<GlobalVariableMap> m_global_aranges_ap;
+
+ typedef std::unordered_map<lldb::offset_t, lldb_private::DebugMacrosSP> DebugMacrosMap;
+ DebugMacrosMap m_debug_macros_map;
+
ExternalTypeModuleMap m_external_type_modules;
NameToDIE m_function_basename_index; // All concrete functions
NameToDIE m_function_fullname_index; // All concrete functions
@@ -610,28 +573,16 @@ protected:
NameToDIE m_type_index; // All type DIE offsets
NameToDIE m_namespace_index; // All type DIE offsets
bool m_indexed:1,
- m_is_external_ast_source:1,
m_using_apple_tables:1,
m_fetched_external_modules:1;
lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type;
std::unique_ptr<DWARFDebugRanges> m_ranges;
UniqueDWARFASTTypeMap m_unique_ast_type_map;
- typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet;
- typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap;
- typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> DeclContextToDIEMap;
- typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr;
- typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP> DIEToVariableSP;
- typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::clang_type_t> DIEToClangType;
- typedef llvm::DenseMap<lldb::clang_type_t, const DWARFDebugInfoEntry *> ClangTypeToDIE;
- typedef llvm::DenseMap<const clang::RecordDecl *, LayoutInfo> RecordDeclToLayoutMap;
- DIEToDeclContextMap m_die_to_decl_ctx;
- DeclContextToDIEMap m_decl_ctx_to_die;
DIEToTypePtr m_die_to_type;
DIEToVariableSP m_die_to_variable_sp;
DIEToClangType m_forward_decl_die_to_clang_type;
ClangTypeToDIE m_forward_decl_clang_type_to_die;
- RecordDeclToLayoutMap m_record_decl_to_layout_map;
};
#endif // SymbolFileDWARF_SymbolFileDWARF_h_
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index de972acd7ed7..be25dfc99dee 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -1,4 +1,4 @@
-//===-- SymbolFileDWARFDebugMap.cpp ----------------------------*- C++ -*-===//
+//===-- SymbolFileDWARFDebugMap.cpp -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,6 +7,10 @@
//
//===----------------------------------------------------------------------===//
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "SymbolFileDWARFDebugMap.h"
#include "DWARFDebugAranges.h"
@@ -24,11 +28,11 @@
#endif
#include "lldb/Core/Timer.h"
-#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/TypeMap.h"
#include "lldb/Symbol/VariableList.h"
#include "LogChannelDWARF.h"
@@ -41,9 +45,6 @@ using namespace lldb_private;
// (so we can fixup the object file sections) and also for "Module::GetSymbolVendor()"
// (so we can fixup the symbol file id.
-
-
-
const SymbolFileDWARFDebugMap::FileRangeMap &
SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMap *exe_symfile)
{
@@ -173,7 +174,6 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa
return file_range_map;
}
-
class DebugMapModule : public Module
{
public:
@@ -190,14 +190,10 @@ public:
{
}
- virtual
- ~DebugMapModule ()
- {
- }
+ ~DebugMapModule() override = default;
-
- virtual SymbolVendor*
- GetSymbolVendor(bool can_create = true, lldb_private::Stream *feedback_strm = NULL)
+ SymbolVendor*
+ GetSymbolVendor(bool can_create = true, lldb_private::Stream *feedback_strm = NULL) override
{
// Scope for locker
if (m_symfile_ap.get() || can_create == false)
@@ -259,7 +255,6 @@ SymbolFileDWARFDebugMap::Terminate()
PluginManager::UnregisterPlugin (CreateInstance);
}
-
lldb_private::ConstString
SymbolFileDWARFDebugMap::GetPluginNameStatic()
{
@@ -279,7 +274,6 @@ SymbolFileDWARFDebugMap::CreateInstance (ObjectFile* obj_file)
return new SymbolFileDWARFDebugMap (obj_file);
}
-
SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap (ObjectFile* ofile) :
SymbolFile(ofile),
m_flags(),
@@ -290,7 +284,6 @@ SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap (ObjectFile* ofile) :
{
}
-
SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap()
{
}
@@ -298,15 +291,6 @@ SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap()
void
SymbolFileDWARFDebugMap::InitializeObject()
{
- // Install our external AST source callbacks so we can complete Clang types.
- llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source_ap (
- new ClangExternalASTSourceCallbacks (SymbolFileDWARFDebugMap::CompleteTagDecl,
- SymbolFileDWARFDebugMap::CompleteObjCInterfaceDecl,
- NULL,
- SymbolFileDWARFDebugMap::LayoutRecordType,
- this));
-
- GetClangASTContext().SetExternalSource (ast_source_ap);
}
void
@@ -517,7 +501,6 @@ SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo (CompileUnitInfo *comp_unit_inf
return NULL;
}
-
bool
SymbolFileDWARFDebugMap::GetFileSpecForSO (uint32_t oso_idx, FileSpec &file_spec)
{
@@ -532,8 +515,6 @@ SymbolFileDWARFDebugMap::GetFileSpecForSO (uint32_t oso_idx, FileSpec &file_spec
return false;
}
-
-
ObjectFile *
SymbolFileDWARFDebugMap::GetObjectFileByOSOIndex (uint32_t oso_idx)
{
@@ -561,7 +542,6 @@ SymbolFileDWARFDebugMap::GetObjectFileByCompUnitInfo (CompileUnitInfo *comp_unit
return NULL;
}
-
uint32_t
SymbolFileDWARFDebugMap::GetCompUnitInfoIndex (const CompileUnitInfo *comp_unit_info)
{
@@ -637,7 +617,6 @@ SymbolFileDWARFDebugMap::GetNumCompileUnits()
return m_compile_unit_infos.size();
}
-
CompUnitSP
SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx)
{
@@ -660,7 +639,8 @@ SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx)
NULL,
so_file_spec,
cu_id,
- eLanguageTypeUnknown));
+ eLanguageTypeUnknown,
+ false));
if (m_compile_unit_infos[cu_idx].compile_unit_sp)
{
@@ -687,7 +667,6 @@ SymbolFileDWARFDebugMap::GetCompUnitInfo (const SymbolContext& sc)
return NULL;
}
-
size_t
SymbolFileDWARFDebugMap::GetCompUnitInfosForModule (const lldb_private::Module *module, std::vector<CompileUnitInfo *>& cu_infos)
{
@@ -728,6 +707,15 @@ SymbolFileDWARFDebugMap::ParseCompileUnitLineTable (const SymbolContext& sc)
}
bool
+SymbolFileDWARFDebugMap::ParseCompileUnitDebugMacros (const SymbolContext& sc)
+{
+ SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
+ if (oso_dwarf)
+ return oso_dwarf->ParseCompileUnitDebugMacros (sc);
+ return false;
+}
+
+bool
SymbolFileDWARFDebugMap::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files)
{
SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
@@ -754,7 +742,6 @@ SymbolFileDWARFDebugMap::ParseFunctionBlocks (const SymbolContext& sc)
return 0;
}
-
size_t
SymbolFileDWARFDebugMap::ParseTypes (const SymbolContext& sc)
{
@@ -764,7 +751,6 @@ SymbolFileDWARFDebugMap::ParseTypes (const SymbolContext& sc)
return 0;
}
-
size_t
SymbolFileDWARFDebugMap::ParseVariablesForContext (const SymbolContext& sc)
{
@@ -774,8 +760,6 @@ SymbolFileDWARFDebugMap::ParseVariablesForContext (const SymbolContext& sc)
return 0;
}
-
-
Type*
SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid)
{
@@ -787,10 +771,22 @@ SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid)
}
bool
-SymbolFileDWARFDebugMap::ResolveClangOpaqueTypeDefinition (ClangASTType& clang_type)
+SymbolFileDWARFDebugMap::CompleteType (CompilerType& compiler_type)
{
- // We have a struct/union/class/enum that needs to be fully resolved.
- return false;
+ bool success = false;
+ if (compiler_type)
+ {
+ ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
+ if (oso_dwarf->HasForwardDeclForClangType (compiler_type))
+ {
+ oso_dwarf->CompleteType (compiler_type);
+ success = true;
+ return true;
+ }
+ return false;
+ });
+ }
+ return success;
}
uint32_t
@@ -834,7 +830,6 @@ SymbolFileDWARFDebugMap::ResolveSymbolContext (const Address& exe_so_addr, uint3
return resolved_flags;
}
-
uint32_t
SymbolFileDWARFDebugMap::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
{
@@ -871,7 +866,7 @@ uint32_t
SymbolFileDWARFDebugMap::PrivateFindGlobalVariables
(
const ConstString &name,
- const ClangNamespaceDecl *namespace_decl,
+ const CompilerDeclContext *parent_decl_ctx,
const std::vector<uint32_t> &indexes, // Indexes into the symbol table that match "name"
uint32_t max_matches,
VariableList& variables
@@ -888,7 +883,7 @@ SymbolFileDWARFDebugMap::PrivateFindGlobalVariables
SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);
if (oso_dwarf)
{
- if (oso_dwarf->FindGlobalVariables(name, namespace_decl, true, max_matches, variables))
+ if (oso_dwarf->FindGlobalVariables(name, parent_decl_ctx, true, max_matches, variables))
if (variables.GetSize() > max_matches)
break;
}
@@ -898,7 +893,11 @@ SymbolFileDWARFDebugMap::PrivateFindGlobalVariables
}
uint32_t
-SymbolFileDWARFDebugMap::FindGlobalVariables (const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables)
+SymbolFileDWARFDebugMap::FindGlobalVariables (const ConstString &name,
+ const CompilerDeclContext *parent_decl_ctx,
+ bool append,
+ uint32_t max_matches,
+ VariableList& variables)
{
// If we aren't appending the results to this list, then clear the list
@@ -913,7 +912,7 @@ SymbolFileDWARFDebugMap::FindGlobalVariables (const ConstString &name, const Cla
ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
const uint32_t oso_matches = oso_dwarf->FindGlobalVariables (name,
- namespace_decl,
+ parent_decl_ctx,
true,
max_matches,
variables);
@@ -941,7 +940,6 @@ SymbolFileDWARFDebugMap::FindGlobalVariables (const ConstString &name, const Cla
return variables.GetSize() - original_size;
}
-
uint32_t
SymbolFileDWARFDebugMap::FindGlobalVariables (const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
{
@@ -983,7 +981,6 @@ SymbolFileDWARFDebugMap::FindGlobalVariables (const RegularExpression& regex, bo
return variables.GetSize() - original_size;
}
-
int
SymbolFileDWARFDebugMap::SymbolContainsSymbolWithIndex (uint32_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info)
{
@@ -998,7 +995,6 @@ SymbolFileDWARFDebugMap::SymbolContainsSymbolWithIndex (uint32_t *symbol_idx_ptr
return 1;
}
-
int
SymbolFileDWARFDebugMap::SymbolContainsSymbolWithID (user_id_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info)
{
@@ -1013,7 +1009,6 @@ SymbolFileDWARFDebugMap::SymbolContainsSymbolWithID (user_id_t *symbol_idx_ptr,
return 1;
}
-
SymbolFileDWARFDebugMap::CompileUnitInfo*
SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithIndex (uint32_t symbol_idx, uint32_t *oso_idx_ptr)
{
@@ -1062,7 +1057,6 @@ SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithID (user_id_t symbol_id,
return comp_unit_info;
}
-
static void
RemoveFunctionsWithModuleNotEqualTo (const ModuleSP &module_sp, SymbolContextList &sc_list, uint32_t start_idx)
{
@@ -1091,7 +1085,12 @@ RemoveFunctionsWithModuleNotEqualTo (const ModuleSP &module_sp, SymbolContextLis
}
uint32_t
-SymbolFileDWARFDebugMap::FindFunctions(const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list)
+SymbolFileDWARFDebugMap::FindFunctions(const ConstString &name,
+ const CompilerDeclContext *parent_decl_ctx,
+ uint32_t name_type_mask,
+ bool include_inlines,
+ bool append,
+ SymbolContextList& sc_list)
{
Timer scoped_timer (__PRETTY_FUNCTION__,
"SymbolFileDWARFDebugMap::FindFunctions (name = %s)",
@@ -1105,7 +1104,7 @@ SymbolFileDWARFDebugMap::FindFunctions(const ConstString &name, const ClangNames
ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
uint32_t sc_idx = sc_list.GetSize();
- if (oso_dwarf->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, true, sc_list))
+ if (oso_dwarf->FindFunctions(name, parent_decl_ctx, name_type_mask, include_inlines, true, sc_list))
{
RemoveFunctionsWithModuleNotEqualTo (m_obj_file->GetModule(), sc_list, sc_idx);
}
@@ -1115,7 +1114,6 @@ SymbolFileDWARFDebugMap::FindFunctions(const ConstString &name, const ClangNames
return sc_list.GetSize() - initial_size;
}
-
uint32_t
SymbolFileDWARFDebugMap::FindFunctions (const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list)
{
@@ -1150,8 +1148,7 @@ SymbolFileDWARFDebugMap::GetTypes (SymbolContextScope *sc_scope,
Timer scoped_timer (__PRETTY_FUNCTION__,
"SymbolFileDWARFDebugMap::GetTypes (type_mask = 0x%8.8x)",
type_mask);
-
-
+
uint32_t initial_size = type_list.GetSize();
SymbolFileDWARF *oso_dwarf = NULL;
if (sc_scope)
@@ -1177,7 +1174,6 @@ SymbolFileDWARFDebugMap::GetTypes (SymbolContextScope *sc_scope,
return type_list.GetSize() - initial_size;
}
-
TypeSP
SymbolFileDWARFDebugMap::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx)
{
@@ -1189,8 +1185,6 @@ SymbolFileDWARFDebugMap::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclC
return type_sp;
}
-
-
bool
SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type (SymbolFileDWARF *skip_dwarf_oso)
{
@@ -1210,7 +1204,7 @@ SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type (SymbolFileDWAR
}
TypeSP
-SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry *die,
+SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE (const DWARFDIE &die,
const ConstString &type_name,
bool must_be_implementation)
{
@@ -1280,10 +1274,10 @@ SymbolFileDWARFDebugMap::FindTypes
(
const SymbolContext& sc,
const ConstString &name,
- const ClangNamespaceDecl *namespace_decl,
- bool append,
+ const CompilerDeclContext *parent_decl_ctx,
+ bool append,
uint32_t max_matches,
- TypeList& types
+ TypeMap& types
)
{
if (!append)
@@ -1296,12 +1290,12 @@ SymbolFileDWARFDebugMap::FindTypes
{
oso_dwarf = GetSymbolFile (sc);
if (oso_dwarf)
- return oso_dwarf->FindTypes (sc, name, namespace_decl, append, max_matches, types);
+ return oso_dwarf->FindTypes (sc, name, parent_decl_ctx, append, max_matches, types);
}
else
{
ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
- oso_dwarf->FindTypes (sc, name, namespace_decl, append, max_matches, types);
+ oso_dwarf->FindTypes (sc, name, parent_decl_ctx, append, max_matches, types);
return false;
});
}
@@ -1320,24 +1314,24 @@ SymbolFileDWARFDebugMap::FindTypes
//}
-ClangNamespaceDecl
+CompilerDeclContext
SymbolFileDWARFDebugMap::FindNamespace (const lldb_private::SymbolContext& sc,
const lldb_private::ConstString &name,
- const ClangNamespaceDecl *parent_namespace_decl)
+ const CompilerDeclContext *parent_decl_ctx)
{
- ClangNamespaceDecl matching_namespace;
+ CompilerDeclContext matching_namespace;
SymbolFileDWARF *oso_dwarf;
if (sc.comp_unit)
{
oso_dwarf = GetSymbolFile (sc);
if (oso_dwarf)
- matching_namespace = oso_dwarf->FindNamespace (sc, name, parent_namespace_decl);
+ matching_namespace = oso_dwarf->FindNamespace (sc, name, parent_decl_ctx);
}
else
{
ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
- matching_namespace = oso_dwarf->FindNamespace (sc, name, parent_namespace_decl);
+ matching_namespace = oso_dwarf->FindNamespace (sc, name, parent_decl_ctx);
return (bool)matching_namespace;
});
@@ -1401,7 +1395,6 @@ SymbolFileDWARFDebugMap::GetCompileUnitInfo (SymbolFileDWARF *oso_dwarf)
return NULL;
}
-
void
SymbolFileDWARFDebugMap::SetCompileUnit (SymbolFileDWARF *oso_dwarf, const CompUnitSP &cu_sp)
{
@@ -1427,78 +1420,33 @@ SymbolFileDWARFDebugMap::SetCompileUnit (SymbolFileDWARF *oso_dwarf, const CompU
}
}
-
-void
-SymbolFileDWARFDebugMap::CompleteTagDecl (void *baton, clang::TagDecl *decl)
-{
- SymbolFileDWARFDebugMap *symbol_file_dwarf = (SymbolFileDWARFDebugMap *)baton;
- ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl);
- if (clang_type)
- {
- symbol_file_dwarf->ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
- if (oso_dwarf->HasForwardDeclForClangType (clang_type))
- {
- oso_dwarf->ResolveClangOpaqueTypeDefinition (clang_type);
- return true;
- }
- return false;
- });
- }
-}
-
-void
-SymbolFileDWARFDebugMap::CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *decl)
-{
- SymbolFileDWARFDebugMap *symbol_file_dwarf = (SymbolFileDWARFDebugMap *)baton;
- ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl);
- if (clang_type)
- {
- symbol_file_dwarf->ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
- if (oso_dwarf->HasForwardDeclForClangType (clang_type))
- {
- oso_dwarf->ResolveClangOpaqueTypeDefinition (clang_type);
- return true;
- }
- return false;
- });
- }
-}
-
-bool
-SymbolFileDWARFDebugMap::LayoutRecordType(void *baton, const clang::RecordDecl *record_decl, uint64_t &size,
- uint64_t &alignment,
- llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets)
-{
- SymbolFileDWARFDebugMap *symbol_file_dwarf = (SymbolFileDWARFDebugMap *)baton;
- bool laid_out = false;
- symbol_file_dwarf->ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
- return (laid_out = oso_dwarf->LayoutRecordType (record_decl, size, alignment, field_offsets, base_offsets, vbase_offsets));
- });
- return laid_out;
-}
-
-
-
-clang::DeclContext*
-SymbolFileDWARFDebugMap::GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid)
+CompilerDeclContext
+SymbolFileDWARFDebugMap::GetDeclContextForUID (lldb::user_id_t type_uid)
{
const uint64_t oso_idx = GetOSOIndexFromUserID (type_uid);
SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);
if (oso_dwarf)
- return oso_dwarf->GetClangDeclContextContainingTypeUID (type_uid);
- return NULL;
+ return oso_dwarf->GetDeclContextForUID (type_uid);
+ return CompilerDeclContext();
}
-clang::DeclContext*
-SymbolFileDWARFDebugMap::GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid)
+CompilerDeclContext
+SymbolFileDWARFDebugMap::GetDeclContextContainingUID (lldb::user_id_t type_uid)
{
const uint64_t oso_idx = GetOSOIndexFromUserID (type_uid);
SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);
if (oso_dwarf)
- return oso_dwarf->GetClangDeclContextForTypeUID (sc, type_uid);
- return NULL;
+ return oso_dwarf->GetDeclContextContainingUID (type_uid);
+ return CompilerDeclContext();
+}
+
+void
+SymbolFileDWARFDebugMap::ParseDeclsForContext (lldb_private::CompilerDeclContext decl_ctx)
+{
+ ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
+ oso_dwarf->ParseDeclsForContext (decl_ctx);
+ return true; // Keep iterating
+ });
}
bool
@@ -1613,7 +1561,6 @@ SymbolFileDWARFDebugMap::AddOSOARanges (SymbolFileDWARF* dwarf2Data, DWARFDebugA
const FileRangeMap::Entry* entry = file_range_map.GetEntryAtIndex(idx);
if (entry)
{
- printf ("[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", entry->GetRangeBase(), entry->GetRangeEnd());
debug_aranges->AppendRange(dwarf2Data->GetID(), entry->GetRangeBase(), entry->GetRangeEnd());
num_line_entries_added++;
}
@@ -1622,4 +1569,3 @@ SymbolFileDWARFDebugMap::AddOSOARanges (SymbolFileDWARF* dwarf2Data, DWARFDebugA
}
return num_line_entries_added;
}
-
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
index ce0cfd744f0b..1eb33c927bdf 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -14,19 +14,14 @@
#include <vector>
#include <bitset>
-#include "clang/AST/CharUnits.h"
-
#include "lldb/Core/RangeMap.h"
#include "lldb/Symbol/SymbolFile.h"
#include "UniqueDWARFASTType.h"
class SymbolFileDWARF;
-class DWARFCompileUnit;
class DWARFDebugAranges;
-class DWARFDebugInfoEntry;
class DWARFDeclContext;
-class DebugMapModule;
class SymbolFileDWARFDebugMap : public lldb_private::SymbolFile
{
@@ -57,7 +52,6 @@ public:
~SymbolFileDWARFDebugMap () override;
uint32_t CalculateAbilities () override;
-
void InitializeObject() override;
//------------------------------------------------------------------
@@ -69,6 +63,7 @@ public:
lldb::LanguageType ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc) override;
size_t ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc) override;
bool ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc) override;
+ bool ParseCompileUnitDebugMacros (const lldb_private::SymbolContext& sc) override;
bool ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList &support_files) override;
bool ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector<lldb_private::ConstString> &imported_modules) override;
size_t ParseFunctionBlocks (const lldb_private::SymbolContext& sc) override;
@@ -76,39 +71,26 @@ public:
size_t ParseVariablesForContext (const lldb_private::SymbolContext& sc) override;
lldb_private::Type* ResolveTypeUID (lldb::user_id_t type_uid) override;
- clang::DeclContext* GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid) override;
- clang::DeclContext* GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid) override;
- bool ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_type) override;
+ lldb_private::CompilerDeclContext GetDeclContextForUID (lldb::user_id_t uid) override;
+ lldb_private::CompilerDeclContext GetDeclContextContainingUID (lldb::user_id_t uid) override;
+ void ParseDeclsForContext (lldb_private::CompilerDeclContext decl_ctx) override;
+
+ bool CompleteType (lldb_private::CompilerType& compiler_type) override;
uint32_t ResolveSymbolContext (const lldb_private::Address& so_addr, uint32_t resolve_scope, lldb_private::SymbolContext& sc) override;
uint32_t ResolveSymbolContext (const lldb_private::FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, lldb_private::SymbolContextList& sc_list) override;
- uint32_t FindGlobalVariables (const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::VariableList& variables) override;
+ uint32_t FindGlobalVariables (const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, lldb_private::VariableList& variables) override;
uint32_t FindGlobalVariables (const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb_private::VariableList& variables) override;
- uint32_t FindFunctions (const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list) override;
+ uint32_t FindFunctions (const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx, uint32_t name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list) override;
uint32_t FindFunctions (const lldb_private::RegularExpression& regex, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list) override;
- uint32_t FindTypes (const lldb_private::SymbolContext& sc, const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::TypeList& types) override;
- lldb_private::ClangNamespaceDecl
+ uint32_t FindTypes (const lldb_private::SymbolContext& sc, const lldb_private::ConstString &name, const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, lldb_private::TypeMap& types) override;
+ lldb_private::CompilerDeclContext
FindNamespace (const lldb_private::SymbolContext& sc,
const lldb_private::ConstString &name,
- const lldb_private::ClangNamespaceDecl *parent_namespace_decl) override;
+ const lldb_private::CompilerDeclContext *parent_decl_ctx) override;
size_t GetTypes (lldb_private::SymbolContextScope *sc_scope,
uint32_t type_mask,
lldb_private::TypeList &type_list) override;
-
- //------------------------------------------------------------------
- // ClangASTContext callbacks for external source lookups.
- //------------------------------------------------------------------
- static void
- CompleteTagDecl (void *baton, clang::TagDecl *);
-
- static void
- CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *);
-
- static bool LayoutRecordType(void *baton, const clang::RecordDecl *record_decl, uint64_t &size, uint64_t &alignment,
- llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
- llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets);
-
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -128,6 +110,7 @@ protected:
friend class DWARFCompileUnit;
friend class SymbolFileDWARF;
friend class DebugMapModule;
+ friend class DWARFASTParserClang;
struct OSOInfo
{
lldb::ModuleSP module_sp;
@@ -259,7 +242,7 @@ protected:
uint32_t
PrivateFindGlobalVariables (const lldb_private::ConstString &name,
- const lldb_private::ClangNamespaceDecl *namespace_decl,
+ const lldb_private::CompilerDeclContext *parent_decl_ctx,
const std::vector<uint32_t> &name_symbol_indexes,
uint32_t max_matches,
lldb_private::VariableList& variables);
@@ -281,7 +264,7 @@ protected:
Supports_DW_AT_APPLE_objc_complete_type (SymbolFileDWARF *skip_dwarf_oso);
lldb::TypeSP
- FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry *die,
+ FindCompleteObjCDefinitionTypeForDIE (const DWARFDIE &die,
const lldb_private::ConstString &type_name,
bool must_be_implementation);
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
new file mode 100644
index 000000000000..326c397c83d5
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
@@ -0,0 +1,131 @@
+//===-- SymbolFileDWARFDwo.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolFileDWARFDwo.h"
+
+#include "lldb/Core/Section.h"
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Symbol/ObjectFile.h"
+
+#include "DWARFCompileUnit.h"
+#include "DWARFDebugInfo.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SymbolFileDWARFDwo::SymbolFileDWARFDwo(ObjectFileSP objfile, DWARFCompileUnit* dwarf_cu) :
+ SymbolFileDWARF(objfile.get()),
+ m_obj_file_sp(objfile),
+ m_base_dwarf_cu(dwarf_cu)
+{
+ SetID(((lldb::user_id_t)dwarf_cu->GetOffset())<<32);
+}
+
+void
+SymbolFileDWARFDwo::LoadSectionData (lldb::SectionType sect_type, DWARFDataExtractor& data)
+{
+ const SectionList* section_list = m_obj_file->GetSectionList(false /* update_module_section_list */);
+ if (section_list)
+ {
+ SectionSP section_sp (section_list->FindSectionByType(sect_type, true));
+ if (section_sp)
+ {
+ // See if we memory mapped the DWARF segment?
+ if (m_dwarf_data.GetByteSize())
+ {
+ data.SetData(m_dwarf_data, section_sp->GetOffset(), section_sp->GetFileSize());
+ return;
+ }
+
+ if (m_obj_file->ReadSectionData(section_sp.get(), data) != 0)
+ return;
+
+ data.Clear();
+ }
+ }
+
+ SymbolFileDWARF::LoadSectionData(sect_type, data);
+}
+
+lldb::CompUnitSP
+SymbolFileDWARFDwo::ParseCompileUnit(DWARFCompileUnit* dwarf_cu, uint32_t cu_idx)
+{
+ assert(GetCompileUnit() == dwarf_cu && "SymbolFileDWARFDwo::ParseCompileUnit called with incompatible compile unit");
+ return GetBaseSymbolFile()->ParseCompileUnit(m_base_dwarf_cu, UINT32_MAX);
+}
+
+DWARFCompileUnit*
+SymbolFileDWARFDwo::GetCompileUnit()
+{
+ // Only dwo files with 1 compile unit is supported
+ if (GetNumCompileUnits() == 1)
+ return DebugInfo()->GetCompileUnitAtIndex(0);
+ else
+ return nullptr;
+}
+
+DWARFCompileUnit*
+SymbolFileDWARFDwo::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit)
+{
+ return GetCompileUnit();
+}
+
+SymbolFileDWARF::DIEToTypePtr&
+SymbolFileDWARFDwo::GetDIEToType()
+{
+ return GetBaseSymbolFile()->GetDIEToType();
+}
+
+SymbolFileDWARF::DIEToVariableSP&
+SymbolFileDWARFDwo::GetDIEToVariable()
+{
+ return GetBaseSymbolFile()->GetDIEToVariable();
+}
+
+SymbolFileDWARF::DIEToClangType&
+SymbolFileDWARFDwo::GetForwardDeclDieToClangType()
+{
+ return GetBaseSymbolFile()->GetForwardDeclDieToClangType();
+}
+
+SymbolFileDWARF::ClangTypeToDIE&
+SymbolFileDWARFDwo::GetForwardDeclClangTypeToDie()
+{
+ return GetBaseSymbolFile()->GetForwardDeclClangTypeToDie();
+}
+
+UniqueDWARFASTTypeMap&
+SymbolFileDWARFDwo::GetUniqueDWARFASTTypeMap()
+{
+ return GetBaseSymbolFile()->GetUniqueDWARFASTTypeMap();
+}
+
+lldb::TypeSP
+SymbolFileDWARFDwo::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx)
+{
+ return GetBaseSymbolFile()->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx);
+}
+
+SymbolFileDWARF*
+SymbolFileDWARFDwo::GetBaseSymbolFile()
+{
+ return m_base_dwarf_cu->GetSymbolFileDWARF();
+}
+
+DWARFExpression::LocationListFormat
+SymbolFileDWARFDwo::GetLocationListFormat() const
+{
+ return DWARFExpression::SplitDwarfLocationList;
+}
+
+TypeSystem*
+SymbolFileDWARFDwo::GetTypeSystemForLanguage(LanguageType language)
+{
+ return GetBaseSymbolFile()->GetTypeSystemForLanguage(language);
+}
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
new file mode 100644
index 000000000000..39ed6502229b
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
@@ -0,0 +1,70 @@
+//===-- SymbolFileDWARFDwo.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARFDwo_SymbolFileDWARFDwo_h_
+#define SymbolFileDWARFDwo_SymbolFileDWARFDwo_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "SymbolFileDWARF.h"
+
+class SymbolFileDWARFDwo : public SymbolFileDWARF
+{
+public:
+ SymbolFileDWARFDwo(lldb::ObjectFileSP objfile, DWARFCompileUnit* dwarf_cu);
+
+ ~SymbolFileDWARFDwo() override = default;
+
+ lldb::CompUnitSP
+ ParseCompileUnit(DWARFCompileUnit* dwarf_cu, uint32_t cu_idx) override;
+
+ DWARFCompileUnit*
+ GetCompileUnit();
+
+ DWARFCompileUnit*
+ GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) override;
+
+ lldb_private::DWARFExpression::LocationListFormat
+ GetLocationListFormat() const override;
+
+ lldb_private::TypeSystem*
+ GetTypeSystemForLanguage(lldb::LanguageType language) override;
+
+protected:
+ void
+ LoadSectionData (lldb::SectionType sect_type, lldb_private::DWARFDataExtractor& data) override;
+
+ DIEToTypePtr&
+ GetDIEToType() override;
+
+ DIEToVariableSP&
+ GetDIEToVariable() override;
+
+ DIEToClangType&
+ GetForwardDeclDieToClangType() override;
+
+ ClangTypeToDIE&
+ GetForwardDeclClangTypeToDie() override;
+
+ UniqueDWARFASTTypeMap&
+ GetUniqueDWARFASTTypeMap() override;
+
+ lldb::TypeSP
+ FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx) override;
+
+ SymbolFileDWARF*
+ GetBaseSymbolFile();
+
+ lldb::ObjectFileSP m_obj_file_sp;
+ DWARFCompileUnit* m_base_dwarf_cu;
+};
+
+#endif // SymbolFileDWARFDwo_SymbolFileDWARFDwo_h_
diff --git a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
index 94044c0feb30..2ca407b9e48a 100644
--- a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
+++ b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
@@ -15,58 +15,51 @@
// Project includes
#include "lldb/Symbol/Declaration.h"
-#include "DWARFDebugInfoEntry.h"
-
bool
-UniqueDWARFASTTypeList::Find
-(
- SymbolFileDWARF *symfile,
- const DWARFCompileUnit *cu,
- const DWARFDebugInfoEntry *die,
- const lldb_private::Declaration &decl,
- const int32_t byte_size,
- UniqueDWARFASTType &entry
-) const
+UniqueDWARFASTTypeList::Find (const DWARFDIE &die,
+ const lldb_private::Declaration &decl,
+ const int32_t byte_size,
+ UniqueDWARFASTType &entry) const
{
- collection::const_iterator pos, end = m_collection.end();
- for (pos = m_collection.begin(); pos != end; ++pos)
+ for (const UniqueDWARFASTType &udt : m_collection)
{
// Make sure the tags match
- if (pos->m_die->Tag() == die->Tag())
+ if (udt.m_die.Tag() == die.Tag())
{
// Validate byte sizes of both types only if both are valid.
- if (pos->m_byte_size < 0 || byte_size < 0 || pos->m_byte_size == byte_size)
+ if (udt.m_byte_size < 0 || byte_size < 0 || udt.m_byte_size == byte_size)
{
// Make sure the file and line match
- if (pos->m_declaration == decl)
+ if (udt.m_declaration == decl)
{
// The type has the same name, and was defined on the same
// file and line. Now verify all of the parent DIEs match.
- const DWARFDebugInfoEntry *parent_arg_die = die->GetParent();
- const DWARFDebugInfoEntry *parend_pos_die = pos->m_die->GetParent();
+ DWARFDIE parent_arg_die = die.GetParent();
+ DWARFDIE parent_pos_die = udt.m_die.GetParent();
bool match = true;
bool done = false;
- while (!done && match && parent_arg_die && parend_pos_die)
+ while (!done && match && parent_arg_die && parent_pos_die)
{
- if (parent_arg_die->Tag() == parend_pos_die->Tag())
+ const dw_tag_t parent_arg_tag = parent_arg_die.Tag();
+ const dw_tag_t parent_pos_tag = parent_pos_die.Tag();
+ if (parent_arg_tag == parent_pos_tag)
{
- const dw_tag_t tag = parent_arg_die->Tag();
- switch (tag)
+ switch (parent_arg_tag)
{
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
case DW_TAG_namespace:
{
- const char *parent_arg_die_name = parent_arg_die->GetName(symfile, cu);
+ const char *parent_arg_die_name = parent_arg_die.GetName();
if (parent_arg_die_name == NULL) // Anonymous (i.e. no-name) struct
{
match = false;
}
else
{
- const char *parent_pos_die_name = parend_pos_die->GetName(pos->m_symfile, pos->m_cu);
- if (parent_pos_die_name == NULL || strcmp (parent_arg_die_name, parent_pos_die_name))
+ const char *parent_pos_die_name = parent_pos_die.GetName();
+ if (parent_pos_die_name == NULL || ((parent_arg_die_name != parent_pos_die_name) && strcmp (parent_arg_die_name, parent_pos_die_name)))
match = false;
}
}
@@ -77,13 +70,13 @@ UniqueDWARFASTTypeList::Find
break;
}
}
- parent_arg_die = parent_arg_die->GetParent();
- parend_pos_die = parend_pos_die->GetParent();
+ parent_arg_die = parent_arg_die.GetParent();
+ parent_pos_die = parent_pos_die.GetParent();
}
if (match)
{
- entry = *pos;
+ entry = udt;
return true;
}
}
diff --git a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
index c85e175235ca..b7b18efd8769 100644
--- a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
+++ b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
@@ -19,10 +19,7 @@
// Project includes
#include "lldb/Symbol/Declaration.h"
-
-class DWARFCompileUnit;
-class DWARFDebugInfoEntry;
-class SymbolFileDWARF;
+#include "DWARFDIE.h"
class UniqueDWARFASTType
{
@@ -32,23 +29,17 @@ public:
//------------------------------------------------------------------
UniqueDWARFASTType () :
m_type_sp (),
- m_symfile (NULL),
- m_cu (NULL),
- m_die (NULL),
+ m_die (),
m_declaration (),
m_byte_size (-1) // Set to negative value to make sure we have a valid value
{
}
UniqueDWARFASTType (lldb::TypeSP &type_sp,
- SymbolFileDWARF *symfile,
- DWARFCompileUnit *cu,
- DWARFDebugInfoEntry *die,
+ const DWARFDIE &die,
const lldb_private::Declaration &decl,
int32_t byte_size) :
m_type_sp (type_sp),
- m_symfile (symfile),
- m_cu (cu),
m_die (die),
m_declaration (decl),
m_byte_size (byte_size)
@@ -57,8 +48,6 @@ public:
UniqueDWARFASTType (const UniqueDWARFASTType &rhs) :
m_type_sp (rhs.m_type_sp),
- m_symfile (rhs.m_symfile),
- m_cu (rhs.m_cu),
m_die (rhs.m_die),
m_declaration (rhs.m_declaration),
m_byte_size (rhs.m_byte_size)
@@ -75,8 +64,6 @@ public:
if (this != &rhs)
{
m_type_sp = rhs.m_type_sp;
- m_symfile = rhs.m_symfile;
- m_cu = rhs.m_cu;
m_die = rhs.m_die;
m_declaration = rhs.m_declaration;
m_byte_size = rhs.m_byte_size;
@@ -85,9 +72,7 @@ public:
}
lldb::TypeSP m_type_sp;
- SymbolFileDWARF *m_symfile;
- const DWARFCompileUnit *m_cu;
- const DWARFDebugInfoEntry *m_die;
+ DWARFDIE m_die;
lldb_private::Declaration m_declaration;
int32_t m_byte_size;
};
@@ -117,9 +102,7 @@ public:
}
bool
- Find (SymbolFileDWARF *symfile,
- const DWARFCompileUnit *cu,
- const DWARFDebugInfoEntry *die,
+ Find (const DWARFDIE &die,
const lldb_private::Declaration &decl,
const int32_t byte_size,
UniqueDWARFASTType &entry) const;
@@ -149,10 +132,8 @@ public:
}
bool
- Find (const lldb_private::ConstString &name,
- SymbolFileDWARF *symfile,
- const DWARFCompileUnit *cu,
- const DWARFDebugInfoEntry *die,
+ Find (const lldb_private::ConstString &name,
+ const DWARFDIE &die,
const lldb_private::Declaration &decl,
const int32_t byte_size,
UniqueDWARFASTType &entry) const
@@ -161,7 +142,7 @@ public:
collection::const_iterator pos = m_collection.find (unique_name_cstr);
if (pos != m_collection.end())
{
- return pos->second.Find (symfile, cu, die, decl, byte_size, entry);
+ return pos->second.Find (die, decl, byte_size, entry);
}
return false;
}
diff --git a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
index 09b919782608..d3dd1ae923e0 100644
--- a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
+++ b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
@@ -12,7 +12,6 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/Timer.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -79,14 +78,6 @@ SymbolFileSymtab::~SymbolFileSymtab()
{
}
-ClangASTContext &
-SymbolFileSymtab::GetClangASTContext ()
-{
- ClangASTContext &ast = m_obj_file->GetModule()->GetClangASTContext();
-
- return ast;
-}
-
uint32_t
SymbolFileSymtab::CalculateAbilities ()
{
@@ -115,6 +106,7 @@ SymbolFileSymtab::CalculateAbilities ()
if (symtab->AppendSymbolIndexesWithType(eSymbolTypeCode, Symtab::eDebugNo, Symtab::eVisibilityAny, m_code_indexes))
{
symtab->SortSymbolIndexesByValue(m_code_indexes, true);
+ abilities |= Functions;
}
if (symtab->AppendSymbolIndexesWithType(eSymbolTypeData, m_data_indexes))
@@ -161,7 +153,7 @@ SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx)
{
const Symbol *cu_symbol = m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]);
if (cu_symbol)
- cu_sp.reset(new CompileUnit (m_obj_file->GetModule(), NULL, cu_symbol->GetName().AsCString(), 0, eLanguageTypeUnknown));
+ cu_sp.reset(new CompileUnit (m_obj_file->GetModule(), NULL, cu_symbol->GetName().AsCString(), 0, eLanguageTypeUnknown, false));
}
return cu_sp;
}
@@ -261,6 +253,12 @@ SymbolFileSymtab::ParseCompileUnitLineTable (const SymbolContext &sc)
}
bool
+SymbolFileSymtab::ParseCompileUnitDebugMacros (const SymbolContext &sc)
+{
+ return false;
+}
+
+bool
SymbolFileSymtab::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files)
{
return false;
@@ -299,17 +297,11 @@ SymbolFileSymtab::ResolveTypeUID(lldb::user_id_t type_uid)
}
bool
-SymbolFileSymtab::ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_opaque_type)
+SymbolFileSymtab::CompleteType (lldb_private::CompilerType& compiler_type)
{
return false;
}
-ClangNamespaceDecl
-SymbolFileSymtab::FindNamespace (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl)
-{
- return ClangNamespaceDecl();
-}
-
uint32_t
SymbolFileSymtab::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
{
@@ -326,63 +318,6 @@ SymbolFileSymtab::ResolveSymbolContext (const Address& so_addr, uint32_t resolve
return resolved_flags;
}
-uint32_t
-SymbolFileSymtab::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
-{
- return 0;
-}
-
-uint32_t
-SymbolFileSymtab::FindGlobalVariables(const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables)
-{
- return 0;
-}
-
-uint32_t
-SymbolFileSymtab::FindGlobalVariables(const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
-{
- return 0;
-}
-
-uint32_t
-SymbolFileSymtab::FindFunctions(const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list)
-{
- Timer scoped_timer (__PRETTY_FUNCTION__,
- "SymbolFileSymtab::FindFunctions (name = '%s')",
- name.GetCString());
- // If we ever support finding STABS or COFF debug info symbols,
- // we will need to add support here. We are not trying to find symbols
- // here, just "lldb_private::Function" objects that come from complete
- // debug information. Any symbol queries should go through the symbol
- // table itself in the module's object file.
- return 0;
-}
-
-uint32_t
-SymbolFileSymtab::FindFunctions(const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list)
-{
- Timer scoped_timer (__PRETTY_FUNCTION__,
- "SymbolFileSymtab::FindFunctions (regex = '%s')",
- regex.GetText());
- // If we ever support finding STABS or COFF debug info symbols,
- // we will need to add support here. We are not trying to find symbols
- // here, just "lldb_private::Function" objects that come from complete
- // debug information. Any symbol queries should go through the symbol
- // table itself in the module's object file.
- return 0;
-}
-
-uint32_t
-SymbolFileSymtab::FindTypes (const lldb_private::SymbolContext& sc,
- const lldb_private::ConstString &name,
- const ClangNamespaceDecl *namespace_decl,
- bool append,
- uint32_t max_matches,
- lldb_private::TypeList& types)
-{
- return 0;
-}
-
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
diff --git a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
index d606419a0d94..4648da49cb9f 100644
--- a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
+++ b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
@@ -10,14 +10,26 @@
#ifndef liblldb_SymbolFileSymtab_h_
#define liblldb_SymbolFileSymtab_h_
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/Symtab.h"
-#include <vector>
class SymbolFileSymtab : public lldb_private::SymbolFile
{
public:
//------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ SymbolFileSymtab(lldb_private::ObjectFile* obj_file);
+
+ ~SymbolFileSymtab() override;
+
+ //------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
static void
@@ -35,94 +47,71 @@ public:
static lldb_private::SymbolFile*
CreateInstance (lldb_private::ObjectFile* obj_file);
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
- SymbolFileSymtab(lldb_private::ObjectFile* obj_file);
-
- virtual
- ~SymbolFileSymtab();
-
- virtual uint32_t CalculateAbilities ();
+ uint32_t
+ CalculateAbilities() override;
//------------------------------------------------------------------
// Compile Unit function calls
//------------------------------------------------------------------
- virtual uint32_t
- GetNumCompileUnits();
-
- virtual lldb::CompUnitSP
- ParseCompileUnitAtIndex(uint32_t index);
-
- virtual lldb::LanguageType
- ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc);
-
- virtual size_t
- ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc);
-
- virtual bool
- ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc);
+ uint32_t
+ GetNumCompileUnits() override;
- virtual bool
- ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList &support_files);
-
- virtual bool
- ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector<lldb_private::ConstString> &imported_modules);
-
- virtual size_t
- ParseFunctionBlocks (const lldb_private::SymbolContext& sc);
-
- virtual size_t
- ParseTypes (const lldb_private::SymbolContext& sc);
+ lldb::CompUnitSP
+ ParseCompileUnitAtIndex(uint32_t index) override;
- virtual size_t
- ParseVariablesForContext (const lldb_private::SymbolContext& sc);
+ lldb::LanguageType
+ ParseCompileUnitLanguage(const lldb_private::SymbolContext& sc) override;
- virtual lldb_private::Type*
- ResolveTypeUID(lldb::user_id_t type_uid);
+ size_t
+ ParseCompileUnitFunctions(const lldb_private::SymbolContext& sc) override;
- virtual bool
- ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_type);
+ bool
+ ParseCompileUnitLineTable(const lldb_private::SymbolContext& sc) override;
- virtual uint32_t
- ResolveSymbolContext (const lldb_private::Address& so_addr, uint32_t resolve_scope, lldb_private::SymbolContext& sc);
+ bool
+ ParseCompileUnitDebugMacros(const lldb_private::SymbolContext& sc) override;
- virtual uint32_t
- ResolveSymbolContext (const lldb_private::FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, lldb_private::SymbolContextList& sc_list);
+ bool
+ ParseCompileUnitSupportFiles(const lldb_private::SymbolContext& sc,
+ lldb_private::FileSpecList &support_files) override;
+
+ bool
+ ParseImportedModules(const lldb_private::SymbolContext &sc,
+ std::vector<lldb_private::ConstString> &imported_modules) override;
- virtual uint32_t
- FindGlobalVariables(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
+ size_t
+ ParseFunctionBlocks(const lldb_private::SymbolContext& sc) override;
- virtual uint32_t
- FindGlobalVariables(const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
+ size_t
+ ParseTypes(const lldb_private::SymbolContext& sc) override;
- virtual uint32_t
- FindFunctions(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list);
+ size_t
+ ParseVariablesForContext(const lldb_private::SymbolContext& sc) override;
- virtual uint32_t
- FindFunctions(const lldb_private::RegularExpression& regex, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list);
+ lldb_private::Type*
+ ResolveTypeUID(lldb::user_id_t type_uid) override;
- virtual uint32_t
- FindTypes (const lldb_private::SymbolContext& sc,const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::TypeList& types);
+ bool
+ CompleteType(lldb_private::CompilerType& compiler_type) override;
- virtual size_t
- GetTypes (lldb_private::SymbolContextScope *sc_scope,
- uint32_t type_mask,
- lldb_private::TypeList &type_list);
+ uint32_t
+ ResolveSymbolContext(const lldb_private::Address& so_addr,
+ uint32_t resolve_scope,
+ lldb_private::SymbolContext& sc) override;
- virtual lldb_private::ClangNamespaceDecl
- FindNamespace (const lldb_private::SymbolContext& sc,
- const lldb_private::ConstString &name,
- const lldb_private::ClangNamespaceDecl *parent_namespace_decl);
+ size_t
+ GetTypes(lldb_private::SymbolContextScope *sc_scope,
+ uint32_t type_mask,
+ lldb_private::TypeList &type_list) override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
protected:
typedef std::map<lldb_private::ConstString, lldb::TypeSP> TypeMap;
@@ -133,13 +122,9 @@ protected:
lldb_private::Symtab::IndexCollection m_data_indexes;
lldb_private::Symtab::NameToIndexMap m_objc_class_name_to_index;
TypeMap m_objc_class_types;
-
- lldb_private::ClangASTContext &
- GetClangASTContext ();
private:
DISALLOW_COPY_AND_ASSIGN (SymbolFileSymtab);
};
-
-#endif // liblldb_SymbolFileSymtab_h_
+#endif // liblldb_SymbolFileSymtab_h_
diff --git a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
index a9f8f36e610e..3cd1b68d7b0f 100644
--- a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
+++ b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
@@ -142,17 +142,19 @@ SymbolVendorELF::CreateInstance (const lldb::ModuleSP &module_sp, lldb_private::
static const SectionType g_sections[] =
{
- eSectionTypeDWARFDebugAranges,
- eSectionTypeDWARFDebugInfo,
eSectionTypeDWARFDebugAbbrev,
+ eSectionTypeDWARFDebugAddr,
+ eSectionTypeDWARFDebugAranges,
eSectionTypeDWARFDebugFrame,
+ eSectionTypeDWARFDebugInfo,
eSectionTypeDWARFDebugLine,
- eSectionTypeDWARFDebugStr,
eSectionTypeDWARFDebugLoc,
eSectionTypeDWARFDebugMacInfo,
eSectionTypeDWARFDebugPubNames,
eSectionTypeDWARFDebugPubTypes,
eSectionTypeDWARFDebugRanges,
+ eSectionTypeDWARFDebugStr,
+ eSectionTypeDWARFDebugStrOffsets,
eSectionTypeELFSymbolTable,
};
for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]); ++idx)
diff --git a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h
index acd62b6cc3ab..425ff9efc59c 100644
--- a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h
+++ b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h
@@ -1,4 +1,4 @@
-//===-- SymbolVendorELF.h ------------------------------------*- C++ -*-===//
+//===-- SymbolVendorELF.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,6 +10,10 @@
#ifndef liblldb_SymbolVendorELF_h_
#define liblldb_SymbolVendorELF_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Symbol/SymbolVendor.h"
@@ -17,6 +21,13 @@ class SymbolVendorELF : public lldb_private::SymbolVendor
{
public:
//------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ SymbolVendorELF (const lldb::ModuleSP &module_sp);
+
+ ~SymbolVendorELF() override;
+
+ //------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
static void
@@ -35,24 +46,16 @@ public:
CreateInstance (const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm);
//------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
- SymbolVendorELF (const lldb::ModuleSP &module_sp);
-
- virtual
- ~SymbolVendorELF();
-
- //------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
private:
DISALLOW_COPY_AND_ASSIGN (SymbolVendorELF);
};
-#endif // liblldb_SymbolVendorELF_h_
+#endif // liblldb_SymbolVendorELF_h_
diff --git a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
index 8f5d92697501..eb5fec34fc20 100644
--- a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
+++ b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -117,21 +117,13 @@ UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange&
// cache the pc register number (in whatever register numbering this UnwindPlan uses) for
// quick reference during instruction parsing.
- uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
RegisterInfo pc_reg_info;
- if (m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info))
- pc_reg_num = pc_reg_info.kinds[unwind_plan.GetRegisterKind()];
- else
- pc_reg_num = LLDB_INVALID_REGNUM;
+ m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info);
// cache the return address register number (in whatever register numbering this UnwindPlan uses) for
// quick reference during instruction parsing.
- uint32_t ra_reg_num = LLDB_INVALID_REGNUM;
RegisterInfo ra_reg_info;
- if (m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, ra_reg_info))
- ra_reg_num = ra_reg_info.kinds[unwind_plan.GetRegisterKind()];
- else
- ra_reg_num = LLDB_INVALID_REGNUM;
+ m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, ra_reg_info);
for (size_t idx=0; idx<num_instructions; ++idx)
{
@@ -511,7 +503,8 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
log->PutCString(strm.GetData());
}
- SetRegisterValue (*reg_info, reg_value);
+ if (!instruction->IsInstructionConditional())
+ SetRegisterValue (*reg_info, reg_value);
switch (context.type)
{
@@ -573,18 +566,45 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
case EmulateInstruction::eContextPopRegisterOffStack:
{
- const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
- const uint32_t generic_regnum = reg_info->kinds[eRegisterKindGeneric];
- if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP)
+ if (!instruction->IsInstructionConditional())
{
- m_curr_row->SetRegisterLocationToSame (reg_num, /*must_replace*/ false);
- m_curr_row_modified = true;
+ const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
+ const uint32_t generic_regnum = reg_info->kinds[eRegisterKindGeneric];
+ if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP)
+ {
+ switch (context.info_type)
+ {
+ case EmulateInstruction::eInfoTypeAddress:
+ if (m_pushed_regs.find(reg_num) != m_pushed_regs.end() &&
+ context.info.address == m_pushed_regs[reg_num])
+ {
+ m_curr_row->SetRegisterLocationToSame(reg_num,
+ false /*must_replace*/);
+ m_curr_row_modified = true;
+ }
+ break;
+ case EmulateInstruction::eInfoTypeISA:
+ assert((generic_regnum == LLDB_REGNUM_GENERIC_PC ||
+ generic_regnum == LLDB_REGNUM_GENERIC_FLAGS) &&
+ "eInfoTypeISA used for poping a register other the the PC/FLAGS");
+ if (generic_regnum != LLDB_REGNUM_GENERIC_FLAGS)
+ {
+ m_curr_row->SetRegisterLocationToSame(reg_num,
+ false /*must_replace*/);
+ m_curr_row_modified = true;
+ }
+ break;
+ default:
+ assert(false && "unhandled case, add code to handle this!");
+ break;
+ }
+ }
}
}
break;
case EmulateInstruction::eContextSetFramePointer:
- if (!m_fp_is_cfa)
+ if (!m_fp_is_cfa && !instruction->IsInstructionConditional())
{
m_fp_is_cfa = true;
m_cfa_reg_info = *reg_info;
@@ -599,7 +619,7 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
case EmulateInstruction::eContextAdjustStackPointer:
// If we have created a frame using the frame pointer, don't follow
// subsequent adjustments to the stack pointer.
- if (!m_fp_is_cfa)
+ if (!m_fp_is_cfa && !instruction->IsInstructionConditional())
{
m_curr_row->GetCFAValue().SetIsRegisterPlusOffset(
m_curr_row->GetCFAValue().GetRegisterNumber(),
diff --git a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
index bf6d017370cc..61d3ece3f6c3 100644
--- a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
+++ b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
@@ -1,4 +1,4 @@
-//===-- UnwindAssemblyInstEmulation.h ----------------------------*- C++ -*-===//
+//===-- UnwindAssemblyInstEmulation.h ---------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,6 +10,10 @@
#ifndef liblldb_UnwindAssemblyInstEmulation_h_
#define liblldb_UnwindAssemblyInstEmulation_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Core/EmulateInstruction.h"
#include "lldb/Core/RegisterValue.h"
@@ -19,32 +23,28 @@
class UnwindAssemblyInstEmulation : public lldb_private::UnwindAssembly
{
public:
+ ~UnwindAssemblyInstEmulation() override = default;
- virtual
- ~UnwindAssemblyInstEmulation ()
- {
- }
-
- virtual bool
- GetNonCallSiteUnwindPlanFromAssembly (lldb_private::AddressRange& func,
- lldb_private::Thread& thread,
- lldb_private::UnwindPlan& unwind_plan);
+ bool
+ GetNonCallSiteUnwindPlanFromAssembly(lldb_private::AddressRange& func,
+ lldb_private::Thread& thread,
+ lldb_private::UnwindPlan& unwind_plan) override;
- virtual bool
- AugmentUnwindPlanFromCallSite (lldb_private::AddressRange& func,
- lldb_private::Thread& thread,
- lldb_private::UnwindPlan& unwind_plan);
+ bool
+ AugmentUnwindPlanFromCallSite(lldb_private::AddressRange& func,
+ lldb_private::Thread& thread,
+ lldb_private::UnwindPlan& unwind_plan) override;
- virtual bool
- GetFastUnwindPlan (lldb_private::AddressRange& func,
- lldb_private::Thread& thread,
- lldb_private::UnwindPlan &unwind_plan);
+ bool
+ GetFastUnwindPlan(lldb_private::AddressRange& func,
+ lldb_private::Thread& thread,
+ lldb_private::UnwindPlan &unwind_plan) override;
// thread may be NULL in which case we only use the Target (e.g. if this is called pre-process-launch).
- virtual bool
- FirstNonPrologueInsn (lldb_private::AddressRange& func,
- const lldb_private::ExecutionContext &exe_ctx,
- lldb_private::Address& first_non_prologue_insn);
+ bool
+ FirstNonPrologueInsn(lldb_private::AddressRange& func,
+ const lldb_private::ExecutionContext &exe_ctx,
+ lldb_private::Address& first_non_prologue_insn) override;
static lldb_private::UnwindAssembly *
CreateInstance (const lldb_private::ArchSpec &arch);
@@ -64,14 +64,36 @@ public:
static const char *
GetPluginDescriptionStatic();
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
private:
-
+ // Call CreateInstance to get an instance of this class
+ UnwindAssemblyInstEmulation(const lldb_private::ArchSpec &arch,
+ lldb_private::EmulateInstruction *inst_emulator) :
+ UnwindAssembly (arch),
+ m_inst_emulator_ap (inst_emulator),
+ m_range_ptr (NULL),
+ m_thread_ptr (NULL),
+ m_unwind_plan_ptr (NULL),
+ m_curr_row (),
+ m_cfa_reg_info (),
+ m_fp_is_cfa (false),
+ m_register_values (),
+ m_pushed_regs(),
+ m_curr_row_modified (false),
+ m_forward_branch_offset (0)
+ {
+ if (m_inst_emulator_ap.get())
+ {
+ m_inst_emulator_ap->SetBaton (this);
+ m_inst_emulator_ap->SetCallbacks (ReadMemory, WriteMemory, ReadRegister, WriteRegister);
+ }
+ }
+
static size_t
ReadMemory (lldb_private::EmulateInstruction *instruction,
void *baton,
@@ -101,7 +123,6 @@ private:
const lldb_private::RegisterInfo *reg_info,
const lldb_private::RegisterValue &reg_value);
-
// size_t
// ReadMemory (lldb_private::EmulateInstruction *instruction,
// const lldb_private::EmulateInstruction::Context &context,
@@ -127,29 +148,6 @@ private:
const lldb_private::RegisterInfo *reg_info,
const lldb_private::RegisterValue &reg_value);
- // Call CreateInstance to get an instance of this class
- UnwindAssemblyInstEmulation (const lldb_private::ArchSpec &arch,
- lldb_private::EmulateInstruction *inst_emulator) :
- UnwindAssembly (arch),
- m_inst_emulator_ap (inst_emulator),
- m_range_ptr (NULL),
- m_thread_ptr (NULL),
- m_unwind_plan_ptr (NULL),
- m_curr_row (),
- m_cfa_reg_info (),
- m_fp_is_cfa (false),
- m_register_values (),
- m_pushed_regs(),
- m_curr_row_modified (false),
- m_forward_branch_offset (0)
- {
- if (m_inst_emulator_ap.get())
- {
- m_inst_emulator_ap->SetBaton (this);
- m_inst_emulator_ap->SetCallbacks (ReadMemory, WriteMemory, ReadRegister, WriteRegister);
- }
- }
-
static uint64_t
MakeRegisterKindValuePair (const lldb_private::RegisterInfo &reg_info);
diff --git a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h
index 8a4fe7c09800..4d43a6e02b73 100644
--- a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h
+++ b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h
@@ -1,4 +1,4 @@
-//===-- UnwindAssembly-x86.h -------------------------------------*- C++ -*-===//
+//===-- UnwindAssembly-x86.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,42 +10,44 @@
#ifndef liblldb_UnwindAssembly_x86_h_
#define liblldb_UnwindAssembly_x86_h_
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
#include "llvm-c/Disassembler.h"
+// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Target/UnwindAssembly.h"
class UnwindAssembly_x86 : public lldb_private::UnwindAssembly
{
public:
+ ~UnwindAssembly_x86() override;
- ~UnwindAssembly_x86 ();
+ bool
+ GetNonCallSiteUnwindPlanFromAssembly(lldb_private::AddressRange& func,
+ lldb_private::Thread& thread,
+ lldb_private::UnwindPlan& unwind_plan) override;
- virtual bool
- GetNonCallSiteUnwindPlanFromAssembly (lldb_private::AddressRange& func,
- lldb_private::Thread& thread,
- lldb_private::UnwindPlan& unwind_plan);
+ bool
+ AugmentUnwindPlanFromCallSite(lldb_private::AddressRange& func,
+ lldb_private::Thread& thread,
+ lldb_private::UnwindPlan& unwind_plan) override;
- virtual bool
- AugmentUnwindPlanFromCallSite (lldb_private::AddressRange& func,
- lldb_private::Thread& thread,
- lldb_private::UnwindPlan& unwind_plan);
-
- virtual bool
- GetFastUnwindPlan (lldb_private::AddressRange& func,
- lldb_private::Thread& thread,
- lldb_private::UnwindPlan &unwind_plan);
+ bool
+ GetFastUnwindPlan(lldb_private::AddressRange& func,
+ lldb_private::Thread& thread,
+ lldb_private::UnwindPlan &unwind_plan) override;
// thread may be NULL in which case we only use the Target (e.g. if this is called pre-process-launch).
- virtual bool
- FirstNonPrologueInsn (lldb_private::AddressRange& func,
- const lldb_private::ExecutionContext &exe_ctx,
- lldb_private::Address& first_non_prologue_insn);
+ bool
+ FirstNonPrologueInsn(lldb_private::AddressRange& func,
+ const lldb_private::ExecutionContext &exe_ctx,
+ lldb_private::Address& first_non_prologue_insn) override;
static lldb_private::UnwindAssembly *
CreateInstance (const lldb_private::ArchSpec &arch);
-
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -61,11 +63,11 @@ public:
static const char *
GetPluginDescriptionStatic();
- virtual lldb_private::ConstString
- GetPluginName();
+ lldb_private::ConstString
+ GetPluginName() override;
- virtual uint32_t
- GetPluginVersion();
+ uint32_t
+ GetPluginVersion() override;
private:
UnwindAssembly_x86 (const lldb_private::ArchSpec &arch, int cpu);
@@ -74,5 +76,4 @@ private:
lldb_private::ArchSpec m_arch;
};
-
#endif // liblldb_UnwindAssembly_x86_h_