From f3fbd1c0586ff6ec7895991e6c28f61a503c36a8 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 23 Jul 2016 20:50:09 +0000 Subject: Vendor import of lldb release_39 branch r276489: https://llvm.org/svn/llvm-project/lldb/branches/release_39@276489 --- source/Plugins/ABI/CMakeLists.txt | 1 + source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp | 264 +- source/Plugins/ABI/MacOSX-arm/Makefile | 14 - .../Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp | 316 +-- source/Plugins/ABI/MacOSX-arm64/Makefile | 14 - source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp | 124 +- source/Plugins/ABI/MacOSX-i386/Makefile | 14 - source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp | 472 ++-- source/Plugins/ABI/SysV-arm/ABISysV_arm.h | 3 + source/Plugins/ABI/SysV-arm/Makefile | 14 - source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp | 318 +-- source/Plugins/ABI/SysV-arm64/Makefile | 14 - .../Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp | 193 +- source/Plugins/ABI/SysV-hexagon/Makefile | 14 - source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp | 49 +- source/Plugins/ABI/SysV-i386/Makefile | 14 - source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp | 226 +- source/Plugins/ABI/SysV-mips/ABISysV_mips.h | 3 + source/Plugins/ABI/SysV-mips/Makefile | 14 - source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp | 212 +- source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h | 3 + source/Plugins/ABI/SysV-mips64/Makefile | 14 - source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp | 142 +- source/Plugins/ABI/SysV-ppc/Makefile | 14 - source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp | 142 +- source/Plugins/ABI/SysV-ppc64/Makefile | 14 - source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp | 807 ++++++ source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h | 120 + source/Plugins/ABI/SysV-s390x/CMakeLists.txt | 3 + source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp | 209 +- source/Plugins/ABI/SysV-x86_64/Makefile | 14 - .../Disassembler/llvm/DisassemblerLLVMC.cpp | 542 ++-- .../Plugins/Disassembler/llvm/DisassemblerLLVMC.h | 8 +- source/Plugins/Disassembler/llvm/Makefile | 14 - .../Darwin-Kernel/DynamicLoaderDarwinKernel.cpp | 105 +- .../Darwin-Kernel/DynamicLoaderDarwinKernel.h | 12 +- .../Plugins/DynamicLoader/Darwin-Kernel/Makefile | 14 - .../Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp | 36 +- .../Hexagon-DYLD/DynamicLoaderHexagonDYLD.h | 10 +- source/Plugins/DynamicLoader/Hexagon-DYLD/Makefile | 14 - .../DynamicLoader/MacOSX-DYLD/CMakeLists.txt | 1 + .../MacOSX-DYLD/DynamicLoaderDarwin.cpp | 1143 +++++++++ .../MacOSX-DYLD/DynamicLoaderDarwin.h | 293 +++ .../MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp | 1018 +------- .../MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h | 226 +- source/Plugins/DynamicLoader/MacOSX-DYLD/Makefile | 14 - .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp | 15 +- .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.h | 2 +- source/Plugins/DynamicLoader/POSIX-DYLD/Makefile | 14 - .../DynamicLoader/Static/DynamicLoaderStatic.cpp | 4 +- .../DynamicLoader/Static/DynamicLoaderStatic.h | 1 - source/Plugins/DynamicLoader/Static/Makefile | 14 - source/Plugins/DynamicLoader/Windows-DYLD/Makefile | 14 - .../Plugins/ExpressionParser/Clang/ASTDumper.cpp | 3 +- .../Clang/ASTResultSynthesizer.cpp | 122 +- .../ExpressionParser/Clang/ASTResultSynthesizer.h | 51 +- .../ExpressionParser/Clang/ClangASTSource.cpp | 59 +- .../ExpressionParser/Clang/ClangASTSource.h | 2 + .../ExpressionParser/Clang/ClangDiagnostic.h | 60 + .../Clang/ClangExpressionDeclMap.cpp | 496 ++-- .../Clang/ClangExpressionDeclMap.h | 22 +- .../ExpressionParser/Clang/ClangExpressionHelper.h | 9 +- .../Clang/ClangExpressionParser.cpp | 620 ++++- .../ExpressionParser/Clang/ClangExpressionParser.h | 44 +- .../ExpressionParser/Clang/ClangFunctionCaller.cpp | 20 +- .../ExpressionParser/Clang/ClangFunctionCaller.h | 16 +- .../Clang/ClangModulesDeclVendor.cpp | 3 + .../Clang/ClangPersistentVariables.cpp | 24 +- .../Clang/ClangPersistentVariables.h | 15 +- .../ExpressionParser/Clang/ClangUserExpression.cpp | 257 +- .../ExpressionParser/Clang/ClangUserExpression.h | 42 +- .../Clang/ClangUtilityFunction.cpp | 48 +- .../ExpressionParser/Clang/ClangUtilityFunction.h | 8 +- .../Plugins/ExpressionParser/Clang/IRForTarget.cpp | 711 +----- .../Plugins/ExpressionParser/Clang/IRForTarget.h | 168 +- source/Plugins/ExpressionParser/Clang/Makefile | 14 - source/Plugins/ExpressionParser/Go/GoAST.h | 1 + .../ExpressionParser/Go/GoUserExpression.cpp | 29 +- .../Plugins/ExpressionParser/Go/GoUserExpression.h | 50 +- source/Plugins/ExpressionParser/Go/Makefile | 14 - .../Instruction/ARM/EmulateInstructionARM.cpp | 81 +- .../Instruction/ARM/EmulateInstructionARM.h | 4 +- .../Plugins/Instruction/ARM/EmulationStateARM.cpp | 116 +- source/Plugins/Instruction/ARM/EmulationStateARM.h | 10 +- source/Plugins/Instruction/ARM/Makefile | 14 - .../Instruction/ARM64/EmulateInstructionARM64.cpp | 2 +- source/Plugins/Instruction/ARM64/Makefile | 14 - .../Instruction/MIPS/EmulateInstructionMIPS.cpp | 46 +- source/Plugins/Instruction/MIPS/Makefile | 14 - .../MIPS64/EmulateInstructionMIPS64.cpp | 45 +- source/Plugins/Instruction/MIPS64/Makefile | 14 - .../AddressSanitizer/AddressSanitizerRuntime.cpp | 33 +- .../AddressSanitizer/Makefile | 14 - .../Plugins/InstrumentationRuntime/CMakeLists.txt | 1 + .../ThreadSanitizer/CMakeLists.txt | 3 + .../ThreadSanitizer/ThreadSanitizerRuntime.cpp | 887 +++++++ .../ThreadSanitizer/ThreadSanitizerRuntime.h | 119 + source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp | 99 +- source/Plugins/JITLoader/GDB/Makefile | 14 - source/Plugins/Language/CMakeLists.txt | 1 + source/Plugins/Language/CPlusPlus/BlockPointer.cpp | 225 ++ source/Plugins/Language/CPlusPlus/BlockPointer.h | 27 + source/Plugins/Language/CPlusPlus/CMakeLists.txt | 2 + .../Language/CPlusPlus/CPlusPlusLanguage.cpp | 162 +- .../Plugins/Language/CPlusPlus/CxxStringTypes.cpp | 22 +- source/Plugins/Language/CPlusPlus/LibCxx.cpp | 76 +- source/Plugins/Language/CPlusPlus/LibCxxAtomic.cpp | 121 + source/Plugins/Language/CPlusPlus/LibCxxAtomic.h | 29 + .../Language/CPlusPlus/LibCxxInitializerList.cpp | 27 +- source/Plugins/Language/CPlusPlus/LibCxxList.cpp | 46 +- source/Plugins/Language/CPlusPlus/LibCxxMap.cpp | 60 +- .../Language/CPlusPlus/LibCxxUnorderedMap.cpp | 31 +- source/Plugins/Language/CPlusPlus/LibCxxVector.cpp | 30 +- source/Plugins/Language/CPlusPlus/LibStdcpp.cpp | 191 +- source/Plugins/Language/CPlusPlus/LibStdcpp.h | 7 +- source/Plugins/Language/CPlusPlus/Makefile | 14 - source/Plugins/Language/Go/Makefile | 14 - source/Plugins/Language/Java/CMakeLists.txt | 4 + .../Language/Java/JavaFormatterFunctions.cpp | 186 ++ .../Plugins/Language/Java/JavaFormatterFunctions.h | 36 + source/Plugins/Language/Java/JavaLanguage.cpp | 112 + source/Plugins/Language/Java/JavaLanguage.h | 64 + source/Plugins/Language/ObjC/CF.cpp | 60 +- source/Plugins/Language/ObjC/Cocoa.cpp | 164 +- source/Plugins/Language/ObjC/Cocoa.h | 14 +- source/Plugins/Language/ObjC/Makefile | 14 - source/Plugins/Language/ObjC/NSArray.cpp | 262 +- source/Plugins/Language/ObjC/NSDictionary.cpp | 302 ++- source/Plugins/Language/ObjC/NSError.cpp | 63 +- source/Plugins/Language/ObjC/NSException.cpp | 8 +- source/Plugins/Language/ObjC/NSIndexPath.cpp | 207 +- source/Plugins/Language/ObjC/NSSet.cpp | 150 +- source/Plugins/Language/ObjC/ObjCLanguage.cpp | 22 +- source/Plugins/Language/ObjC/ObjCLanguage.h | 3 +- source/Plugins/Language/ObjCPlusPlus/Makefile | 14 - source/Plugins/LanguageRuntime/CMakeLists.txt | 1 + .../ItaniumABI/ItaniumABILanguageRuntime.cpp | 374 ++- .../ItaniumABI/ItaniumABILanguageRuntime.h | 29 +- .../LanguageRuntime/CPlusPlus/ItaniumABI/Makefile | 14 - .../LanguageRuntime/Go/GoLanguageRuntime.cpp | 3 + source/Plugins/LanguageRuntime/Go/Makefile | 14 - source/Plugins/LanguageRuntime/Java/CMakeLists.txt | 3 + .../LanguageRuntime/Java/JavaLanguageRuntime.cpp | 176 ++ .../LanguageRuntime/Java/JavaLanguageRuntime.h | 90 + .../AppleObjCClassDescriptorV2.cpp | 10 +- .../AppleObjCRuntime/AppleObjCClassDescriptorV2.h | 5 +- .../ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp | 50 +- .../ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp | 31 +- .../ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp | 1 + .../ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp | 576 +++-- .../ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h | 44 +- .../AppleObjCTrampolineHandler.cpp | 58 +- .../AppleObjCRuntime/AppleObjCTrampolineHandler.h | 6 +- .../AppleObjCTypeEncodingParser.cpp | 9 +- .../AppleThreadPlanStepThroughObjCTrampoline.cpp | 19 +- .../LanguageRuntime/ObjC/AppleObjCRuntime/Makefile | 14 - .../RenderScript/RenderScriptRuntime/Makefile | 14 - .../RenderScriptRuntime/RenderScriptRuntime.cpp | 2601 +++++++++++--------- .../RenderScriptRuntime/RenderScriptRuntime.h | 291 ++- source/Plugins/Makefile | 67 - source/Plugins/MemoryHistory/asan/Makefile | 14 - .../MemoryHistory/asan/MemoryHistoryASan.cpp | 109 +- .../Plugins/ObjectContainer/BSD-Archive/Makefile | 14 - .../BSD-Archive/ObjectContainerBSDArchive.cpp | 12 +- .../BSD-Archive/ObjectContainerBSDArchive.h | 6 +- .../ObjectContainer/Universal-Mach-O/Makefile | 14 - source/Plugins/ObjectFile/ELF/ELFHeader.cpp | 3 + source/Plugins/ObjectFile/ELF/Makefile | 14 - source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 458 +++- source/Plugins/ObjectFile/ELF/ObjectFileELF.h | 26 +- source/Plugins/ObjectFile/JIT/Makefile | 14 - source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp | 6 +- source/Plugins/ObjectFile/Mach-O/Makefile | 14 - .../Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp | 109 +- source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h | 5 +- source/Plugins/ObjectFile/PECOFF/Makefile | 14 - .../Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp | 35 +- .../Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h | 5 +- source/Plugins/OperatingSystem/Go/Makefile | 14 - .../OperatingSystem/Go/OperatingSystemGo.cpp | 19 +- source/Plugins/OperatingSystem/Python/Makefile | 14 - .../Python/OperatingSystemPython.cpp | 16 +- source/Plugins/Platform/Android/AdbClient.cpp | 414 ++-- source/Plugins/Platform/Android/AdbClient.h | 82 +- source/Plugins/Platform/Android/Makefile | 14 - .../Plugins/Platform/Android/PlatformAndroid.cpp | 57 +- source/Plugins/Platform/Android/PlatformAndroid.h | 6 + .../Android/PlatformAndroidRemoteGDBServer.cpp | 17 +- .../Android/PlatformAndroidRemoteGDBServer.h | 3 - source/Plugins/Platform/FreeBSD/Makefile | 14 - .../Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp | 77 +- source/Plugins/Platform/Kalimba/Makefile | 14 - source/Plugins/Platform/Linux/Makefile | 14 - source/Plugins/Platform/Linux/PlatformLinux.cpp | 99 +- source/Plugins/Platform/Linux/PlatformLinux.h | 4 - source/Plugins/Platform/MacOSX/Makefile | 34 - .../Platform/MacOSX/PlatformAppleSimulator.cpp | 2 +- .../Platform/MacOSX/PlatformAppleTVSimulator.cpp | 2 +- .../MacOSX/PlatformAppleWatchSimulator.cpp | 2 +- source/Plugins/Platform/MacOSX/PlatformDarwin.cpp | 57 +- source/Plugins/Platform/MacOSX/PlatformDarwin.h | 3 + .../Platform/MacOSX/PlatformDarwinKernel.cpp | 19 +- .../Platform/MacOSX/PlatformRemoteAppleTV.cpp | 156 +- .../Platform/MacOSX/PlatformRemoteAppleWatch.cpp | 155 +- .../Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp | 78 +- .../Platform/MacOSX/PlatformiOSSimulator.cpp | 2 +- source/Plugins/Platform/Makefile | 36 - source/Plugins/Platform/NetBSD/Makefile | 14 - source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp | 28 - source/Plugins/Platform/NetBSD/PlatformNetBSD.h | 4 - source/Plugins/Platform/POSIX/Makefile | 14 - source/Plugins/Platform/POSIX/PlatformPOSIX.cpp | 53 +- source/Plugins/Platform/POSIX/PlatformPOSIX.h | 7 +- source/Plugins/Platform/Windows/Makefile | 14 - .../Plugins/Platform/Windows/PlatformWindows.cpp | 38 +- source/Plugins/Platform/Windows/PlatformWindows.h | 4 - source/Plugins/Platform/gdb-server/Makefile | 14 - .../gdb-server/PlatformRemoteGDBServer.cpp | 22 +- .../Platform/gdb-server/PlatformRemoteGDBServer.h | 3 + source/Plugins/Process/FreeBSD/FreeBSDThread.cpp | 38 +- source/Plugins/Process/FreeBSD/Makefile | 17 - source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp | 28 +- source/Plugins/Process/FreeBSD/ProcessFreeBSD.h | 9 +- source/Plugins/Process/FreeBSD/ProcessMonitor.cpp | 17 +- source/Plugins/Process/FreeBSD/ProcessMonitor.h | 8 +- source/Plugins/Process/Linux/CMakeLists.txt | 2 + source/Plugins/Process/Linux/Makefile | 17 - .../Plugins/Process/Linux/NativeProcessLinux.cpp | 693 ++---- source/Plugins/Process/Linux/NativeProcessLinux.h | 69 +- .../Linux/NativeRegisterContextLinux_arm.cpp | 43 +- .../Process/Linux/NativeRegisterContextLinux_arm.h | 5 + .../Linux/NativeRegisterContextLinux_arm64.cpp | 44 +- .../Linux/NativeRegisterContextLinux_arm64.h | 5 + .../Linux/NativeRegisterContextLinux_mips64.cpp | 6 +- .../Linux/NativeRegisterContextLinux_s390x.cpp | 716 ++++++ .../Linux/NativeRegisterContextLinux_s390x.h | 141 ++ source/Plugins/Process/Linux/NativeThreadLinux.cpp | 143 +- source/Plugins/Process/Linux/NativeThreadLinux.h | 28 +- source/Plugins/Process/Linux/SingleStepCheck.cpp | 177 ++ source/Plugins/Process/Linux/SingleStepCheck.h | 41 + .../Process/MacOSX-Kernel/CommunicationKDP.cpp | 45 +- .../Process/MacOSX-Kernel/CommunicationKDP.h | 6 +- source/Plugins/Process/MacOSX-Kernel/Makefile | 14 - .../Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp | 24 +- source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h | 4 +- source/Plugins/Process/POSIX/Makefile | 32 - source/Plugins/Process/Utility/CMakeLists.txt | 3 + source/Plugins/Process/Utility/HistoryThread.cpp | 40 +- source/Plugins/Process/Utility/HistoryThread.h | 5 +- source/Plugins/Process/Utility/HistoryUnwind.cpp | 6 +- source/Plugins/Process/Utility/HistoryUnwind.h | 1 - .../Plugins/Process/Utility/InferiorCallPOSIX.cpp | 63 +- source/Plugins/Process/Utility/Makefile | 14 - .../Process/Utility/RegisterContextDarwin_arm.cpp | 2 + .../Process/Utility/RegisterContextDarwin_arm.h | 9 +- .../Process/Utility/RegisterContextLLDB.cpp | 97 +- .../Process/Utility/RegisterContextLinux_s390x.cpp | 98 + .../Process/Utility/RegisterContextLinux_s390x.h | 42 + .../Utility/RegisterContextNetBSD_x86_64.cpp | 357 +++ .../Process/Utility/RegisterContextNetBSD_x86_64.h | 35 + .../Process/Utility/RegisterContextPOSIX_s390x.cpp | 265 ++ .../Process/Utility/RegisterContextPOSIX_s390x.h | 103 + .../Process/Utility/RegisterContext_s390x.h | 93 + .../Plugins/Process/Utility/RegisterInfos_mips.h | 15 +- .../Plugins/Process/Utility/RegisterInfos_mips64.h | 11 +- .../Plugins/Process/Utility/RegisterInfos_s390x.h | 132 + .../Process/Utility/StopInfoMachException.cpp | 2 + .../Process/Utility/lldb-s390x-register-enums.h | 94 + .../Plugins/Process/Windows/Common/NtStructures.h | 32 + .../Process/Windows/Common/ProcessWindows.cpp | 4 +- .../Process/Windows/Common/ProcessWindows.h | 2 +- .../Common/x64/RegisterContextWindows_x64.cpp | 6 +- .../Common/x86/RegisterContextWindows_x86.cpp | 59 +- .../Common/x86/RegisterContextWindows_x86.h | 3 + .../Process/Windows/Live/DebuggerThread.cpp | 13 +- .../Process/Windows/Live/ProcessWindowsLive.cpp | 116 +- .../Process/Windows/Live/ProcessWindowsLive.h | 4 +- .../Windows/MiniDump/ProcessWinMiniDump.cpp | 638 +++-- .../Process/Windows/MiniDump/ProcessWinMiniDump.h | 46 +- source/Plugins/Process/elf-core/CMakeLists.txt | 1 + source/Plugins/Process/elf-core/Makefile | 14 - source/Plugins/Process/elf-core/ProcessElfCore.cpp | 92 +- source/Plugins/Process/elf-core/ProcessElfCore.h | 14 +- .../elf-core/RegisterContextPOSIXCore_s390x.cpp | 115 + .../elf-core/RegisterContextPOSIXCore_s390x.h | 65 + source/Plugins/Process/elf-core/ThreadElfCore.cpp | 10 + source/Plugins/Process/elf-core/ThreadElfCore.h | 2 + .../Process/gdb-remote/GDBRemoteCommunication.cpp | 17 +- .../gdb-remote/GDBRemoteCommunicationClient.cpp | 224 +- .../gdb-remote/GDBRemoteCommunicationClient.h | 5 +- .../GDBRemoteCommunicationServerCommon.h | 1 - .../GDBRemoteCommunicationServerLLGS.cpp | 47 +- .../gdb-remote/GDBRemoteCommunicationServerLLGS.h | 9 +- .../GDBRemoteCommunicationServerPlatform.cpp | 65 +- .../GDBRemoteCommunicationServerPlatform.h | 11 +- .../gdb-remote/GDBRemoteRegisterContext.cpp | 15 +- source/Plugins/Process/gdb-remote/Makefile | 14 - .../Process/gdb-remote/ProcessGDBRemote.cpp | 474 ++-- .../Plugins/Process/gdb-remote/ProcessGDBRemote.h | 23 +- source/Plugins/Process/mach-core/Makefile | 14 - .../Plugins/Process/mach-core/ProcessMachCore.cpp | 183 +- source/Plugins/Process/mach-core/ProcessMachCore.h | 13 +- source/Plugins/ScriptInterpreter/None/Makefile | 14 - source/Plugins/ScriptInterpreter/Python/Makefile | 14 - .../ScriptInterpreter/Python/PythonDataObjects.cpp | 138 +- .../ScriptInterpreter/Python/PythonDataObjects.h | 37 + .../Python/ScriptInterpreterPython.cpp | 205 +- .../Python/ScriptInterpreterPython.h | 5 + source/Plugins/SymbolFile/CMakeLists.txt | 1 + source/Plugins/SymbolFile/DWARF/CMakeLists.txt | 1 + source/Plugins/SymbolFile/DWARF/DIERef.cpp | 55 +- source/Plugins/SymbolFile/DWARF/DIERef.h | 20 +- source/Plugins/SymbolFile/DWARF/DWARFASTParser.h | 12 - .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 733 ++++-- .../Plugins/SymbolFile/DWARF/DWARFASTParserClang.h | 62 +- .../Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp | 42 +- .../SymbolFile/DWARF/DWARFASTParserJava.cpp | 555 +++++ .../Plugins/SymbolFile/DWARF/DWARFASTParserJava.h | 90 + .../Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp | 80 +- source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h | 2 + source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp | 75 +- source/Plugins/SymbolFile/DWARF/DWARFDIE.h | 18 +- .../SymbolFile/DWARF/DWARFDIECollection.cpp | 11 - .../Plugins/SymbolFile/DWARF/DWARFDIECollection.h | 3 - source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp | 75 +- source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h | 7 +- .../SymbolFile/DWARF/DWARFDebugInfoEntry.cpp | 22 +- .../Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h | 13 +- source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h | 16 +- source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp | 8 + source/Plugins/SymbolFile/DWARF/DWARFFormValue.h | 1 + .../Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp | 15 +- source/Plugins/SymbolFile/DWARF/Makefile | 14 - .../Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 616 +++-- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h | 45 +- .../SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp | 51 +- .../SymbolFile/DWARF/SymbolFileDWARFDebugMap.h | 10 +- .../SymbolFile/DWARF/SymbolFileDWARFDwo.cpp | 8 + .../Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h | 9 + source/Plugins/SymbolFile/PDB/CMakeLists.txt | 7 + source/Plugins/SymbolFile/PDB/PDBASTParser.cpp | 237 ++ source/Plugins/SymbolFile/PDB/PDBASTParser.h | 58 + source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp | 733 ++++++ source/Plugins/SymbolFile/PDB/SymbolFilePDB.h | 204 ++ source/Plugins/SymbolFile/Symtab/Makefile | 14 - .../Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp | 3 +- source/Plugins/SymbolVendor/ELF/Makefile | 14 - source/Plugins/SymbolVendor/MacOSX/Makefile | 14 - .../MacOSX/AppleGetItemInfoHandler.cpp | 73 +- .../SystemRuntime/MacOSX/AppleGetItemInfoHandler.h | 8 +- .../MacOSX/AppleGetPendingItemsHandler.cpp | 77 +- .../MacOSX/AppleGetPendingItemsHandler.h | 8 +- .../SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp | 75 +- .../SystemRuntime/MacOSX/AppleGetQueuesHandler.h | 8 +- .../MacOSX/AppleGetThreadItemInfoHandler.cpp | 75 +- .../MacOSX/AppleGetThreadItemInfoHandler.h | 8 +- source/Plugins/SystemRuntime/MacOSX/Makefile | 14 - .../SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp | 50 +- .../SystemRuntime/MacOSX/SystemRuntimeMacOSX.h | 6 +- .../Plugins/UnwindAssembly/InstEmulation/Makefile | 14 - .../InstEmulation/UnwindAssemblyInstEmulation.cpp | 128 +- source/Plugins/UnwindAssembly/x86/Makefile | 14 - 362 files changed, 21249 insertions(+), 11394 deletions(-) delete mode 100644 source/Plugins/ABI/MacOSX-arm/Makefile delete mode 100644 source/Plugins/ABI/MacOSX-arm64/Makefile delete mode 100644 source/Plugins/ABI/MacOSX-i386/Makefile delete mode 100644 source/Plugins/ABI/SysV-arm/Makefile delete mode 100644 source/Plugins/ABI/SysV-arm64/Makefile delete mode 100644 source/Plugins/ABI/SysV-hexagon/Makefile delete mode 100644 source/Plugins/ABI/SysV-i386/Makefile delete mode 100644 source/Plugins/ABI/SysV-mips/Makefile delete mode 100644 source/Plugins/ABI/SysV-mips64/Makefile delete mode 100644 source/Plugins/ABI/SysV-ppc/Makefile delete mode 100644 source/Plugins/ABI/SysV-ppc64/Makefile create mode 100644 source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp create mode 100644 source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h create mode 100644 source/Plugins/ABI/SysV-s390x/CMakeLists.txt delete mode 100644 source/Plugins/ABI/SysV-x86_64/Makefile delete mode 100644 source/Plugins/Disassembler/llvm/Makefile delete mode 100644 source/Plugins/DynamicLoader/Darwin-Kernel/Makefile delete mode 100644 source/Plugins/DynamicLoader/Hexagon-DYLD/Makefile create mode 100644 source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp create mode 100644 source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h delete mode 100644 source/Plugins/DynamicLoader/MacOSX-DYLD/Makefile delete mode 100644 source/Plugins/DynamicLoader/POSIX-DYLD/Makefile delete mode 100644 source/Plugins/DynamicLoader/Static/Makefile delete mode 100644 source/Plugins/DynamicLoader/Windows-DYLD/Makefile create mode 100644 source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h delete mode 100644 source/Plugins/ExpressionParser/Clang/Makefile delete mode 100644 source/Plugins/ExpressionParser/Go/Makefile delete mode 100644 source/Plugins/Instruction/ARM/Makefile delete mode 100644 source/Plugins/Instruction/ARM64/Makefile delete mode 100644 source/Plugins/Instruction/MIPS/Makefile delete mode 100644 source/Plugins/Instruction/MIPS64/Makefile delete mode 100644 source/Plugins/InstrumentationRuntime/AddressSanitizer/Makefile create mode 100644 source/Plugins/InstrumentationRuntime/ThreadSanitizer/CMakeLists.txt create mode 100644 source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp create mode 100644 source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.h delete mode 100644 source/Plugins/JITLoader/GDB/Makefile create mode 100644 source/Plugins/Language/CPlusPlus/BlockPointer.cpp create mode 100644 source/Plugins/Language/CPlusPlus/BlockPointer.h create mode 100644 source/Plugins/Language/CPlusPlus/LibCxxAtomic.cpp create mode 100644 source/Plugins/Language/CPlusPlus/LibCxxAtomic.h delete mode 100644 source/Plugins/Language/CPlusPlus/Makefile delete mode 100644 source/Plugins/Language/Go/Makefile create mode 100644 source/Plugins/Language/Java/CMakeLists.txt create mode 100644 source/Plugins/Language/Java/JavaFormatterFunctions.cpp create mode 100644 source/Plugins/Language/Java/JavaFormatterFunctions.h create mode 100644 source/Plugins/Language/Java/JavaLanguage.cpp create mode 100644 source/Plugins/Language/Java/JavaLanguage.h delete mode 100644 source/Plugins/Language/ObjC/Makefile delete mode 100644 source/Plugins/Language/ObjCPlusPlus/Makefile delete mode 100644 source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/Makefile delete mode 100644 source/Plugins/LanguageRuntime/Go/Makefile create mode 100644 source/Plugins/LanguageRuntime/Java/CMakeLists.txt create mode 100644 source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.cpp create mode 100644 source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.h delete mode 100644 source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/Makefile delete mode 100644 source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/Makefile delete mode 100644 source/Plugins/Makefile delete mode 100644 source/Plugins/MemoryHistory/asan/Makefile delete mode 100644 source/Plugins/ObjectContainer/BSD-Archive/Makefile delete mode 100644 source/Plugins/ObjectContainer/Universal-Mach-O/Makefile delete mode 100644 source/Plugins/ObjectFile/ELF/Makefile delete mode 100644 source/Plugins/ObjectFile/JIT/Makefile delete mode 100644 source/Plugins/ObjectFile/Mach-O/Makefile delete mode 100644 source/Plugins/ObjectFile/PECOFF/Makefile delete mode 100644 source/Plugins/OperatingSystem/Go/Makefile delete mode 100644 source/Plugins/OperatingSystem/Python/Makefile delete mode 100644 source/Plugins/Platform/Android/Makefile delete mode 100644 source/Plugins/Platform/FreeBSD/Makefile delete mode 100644 source/Plugins/Platform/Kalimba/Makefile delete mode 100644 source/Plugins/Platform/Linux/Makefile delete mode 100644 source/Plugins/Platform/MacOSX/Makefile delete mode 100644 source/Plugins/Platform/Makefile delete mode 100644 source/Plugins/Platform/NetBSD/Makefile delete mode 100644 source/Plugins/Platform/POSIX/Makefile delete mode 100644 source/Plugins/Platform/Windows/Makefile delete mode 100644 source/Plugins/Platform/gdb-server/Makefile delete mode 100644 source/Plugins/Process/FreeBSD/Makefile delete mode 100644 source/Plugins/Process/Linux/Makefile create mode 100644 source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp create mode 100644 source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h create mode 100644 source/Plugins/Process/Linux/SingleStepCheck.cpp create mode 100644 source/Plugins/Process/Linux/SingleStepCheck.h delete mode 100644 source/Plugins/Process/MacOSX-Kernel/Makefile delete mode 100644 source/Plugins/Process/POSIX/Makefile delete mode 100644 source/Plugins/Process/Utility/Makefile create mode 100644 source/Plugins/Process/Utility/RegisterContextLinux_s390x.cpp create mode 100644 source/Plugins/Process/Utility/RegisterContextLinux_s390x.h create mode 100644 source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp create mode 100644 source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h create mode 100644 source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp create mode 100644 source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h create mode 100644 source/Plugins/Process/Utility/RegisterContext_s390x.h create mode 100644 source/Plugins/Process/Utility/RegisterInfos_s390x.h create mode 100644 source/Plugins/Process/Utility/lldb-s390x-register-enums.h create mode 100644 source/Plugins/Process/Windows/Common/NtStructures.h delete mode 100644 source/Plugins/Process/elf-core/Makefile create mode 100644 source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp create mode 100644 source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h delete mode 100644 source/Plugins/Process/gdb-remote/Makefile delete mode 100644 source/Plugins/Process/mach-core/Makefile delete mode 100644 source/Plugins/ScriptInterpreter/None/Makefile delete mode 100644 source/Plugins/ScriptInterpreter/Python/Makefile create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.h delete mode 100644 source/Plugins/SymbolFile/DWARF/Makefile create mode 100644 source/Plugins/SymbolFile/PDB/CMakeLists.txt create mode 100644 source/Plugins/SymbolFile/PDB/PDBASTParser.cpp create mode 100644 source/Plugins/SymbolFile/PDB/PDBASTParser.h create mode 100644 source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp create mode 100644 source/Plugins/SymbolFile/PDB/SymbolFilePDB.h delete mode 100644 source/Plugins/SymbolFile/Symtab/Makefile delete mode 100644 source/Plugins/SymbolVendor/ELF/Makefile delete mode 100644 source/Plugins/SymbolVendor/MacOSX/Makefile delete mode 100644 source/Plugins/SystemRuntime/MacOSX/Makefile delete mode 100644 source/Plugins/UnwindAssembly/InstEmulation/Makefile delete mode 100644 source/Plugins/UnwindAssembly/x86/Makefile (limited to 'source/Plugins') diff --git a/source/Plugins/ABI/CMakeLists.txt b/source/Plugins/ABI/CMakeLists.txt index 08452c5dad62..9d7a79308d7b 100644 --- a/source/Plugins/ABI/CMakeLists.txt +++ b/source/Plugins/ABI/CMakeLists.txt @@ -5,6 +5,7 @@ add_subdirectory(SysV-ppc) add_subdirectory(SysV-ppc64) add_subdirectory(SysV-mips) add_subdirectory(SysV-mips64) +add_subdirectory(SysV-s390x) add_subdirectory(SysV-i386) add_subdirectory(SysV-x86_64) add_subdirectory(MacOSX-i386) diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp index 3b9b0f346072..ea906f613890 100644 --- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp +++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp @@ -1,4 +1,4 @@ -//===-- ABIMacOSX_arm.cpp --------------------------------------*- C++ -*-===// +//===-- ABIMacOSX_arm.cpp ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -9,6 +9,15 @@ #include "ABIMacOSX_arm.h" +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" + +// Project includes #include "lldb/Core/ConstString.h" #include "lldb/Core/Error.h" #include "lldb/Core/Module.h" @@ -23,15 +32,10 @@ #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/Triple.h" - #include "Utility/ARM_DWARF_Registers.h" #include "Utility/ARM_ehframe_Registers.h" #include "Plugins/Process/Utility/ARMDefines.h" -#include - using namespace lldb; using namespace lldb_private; @@ -39,111 +43,112 @@ static RegisterInfo g_register_infos[] = { // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS // ========== ======= == === ============= ============ ======================= =================== =========================== ======================= ====================== ========== =============== - { "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}, - { "r11_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r11_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r12_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r12_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r13_usr", "sp_usr", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r14_usr", "lr_usr", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r8_fiq", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r8_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r9_fiq", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r9_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r10_fiq", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r10_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r11_fiq", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r11_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r12_fiq", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r12_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r13_fiq", "sp_fiq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r14_fiq", "lr_fiq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r13_irq", "sp_irq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_irq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r14_irq", "lr_irq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_irq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r13_abt", "sp_abt", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_abt, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r14_abt", "lr_abt", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_abt, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r13_und", "sp_und", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_und, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r14_und", "lr_und", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_und, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r13_svc", "sp_svc", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_svc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r14_svc", "lr_svc", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_svc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 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 }, nullptr, nullptr }, + { "r1", "arg2", 4, 0, eEncodingUint , eFormatHex, { ehframe_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r2", "arg3", 4, 0, eEncodingUint , eFormatHex, { ehframe_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r3", "arg4", 4, 0, eEncodingUint , eFormatHex, { ehframe_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r4", nullptr, 4, 0, eEncodingUint , eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r5", nullptr, 4, 0, eEncodingUint , eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r6", nullptr, 4, 0, eEncodingUint , eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r7", nullptr, 4, 0, eEncodingUint , eFormatHex, { ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r8", nullptr, 4, 0, eEncodingUint , eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r9", nullptr, 4, 0, eEncodingUint , eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r10", nullptr, 4, 0, eEncodingUint , eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r11", nullptr, 4, 0, eEncodingUint , eFormatHex, { ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r12", nullptr, 4, 0, eEncodingUint , eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "sp", "r13", 4, 0, eEncodingUint , eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "lr", "r14", 4, 0, eEncodingUint , eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "pc", "r15", 4, 0, eEncodingUint , eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s0", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s1", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s2", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s3", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s4", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s5", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s6", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s7", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s8", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s9", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s10", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s11", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s12", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s13", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s14", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s15", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s16", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s17", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s18", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s19", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s20", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s21", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s22", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s23", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s24", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s25", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s26", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s27", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s28", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s29", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s30", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s31", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "fpscr", nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d0", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d1", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d2", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d3", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d4", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d5", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d6", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d7", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d8", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d9", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d10", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d11", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d12", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d13", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d14", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d15", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d16", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d17", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d18", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d19", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d20", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d21", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d22", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d23", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d24", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d25", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d26", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d27", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d28", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d29", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d30", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d31", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r8_usr", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r8_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r9_usr", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r9_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r10_usr", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r10_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r11_usr", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r11_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r12_usr", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r12_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r13_usr", "sp_usr", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r14_usr", "lr_usr", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r8_fiq", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r8_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r9_fiq", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r9_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r10_fiq", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r10_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r11_fiq", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r11_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r12_fiq", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r12_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r13_fiq", "sp_fiq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r14_fiq", "lr_fiq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r13_irq", "sp_irq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_irq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r14_irq", "lr_irq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_irq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r13_abt", "sp_abt", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_abt, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r14_abt", "lr_abt", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_abt, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r13_und", "sp_und", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_und, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r14_und", "lr_und", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_und, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r13_svc", "sp_svc", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_svc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r14_svc", "lr_svc", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_svc, 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); static bool g_register_info_names_constified = false; @@ -156,7 +161,7 @@ ABIMacOSX_arm::GetRegisterInfoArray (uint32_t &count) if (!g_register_info_names_constified) { g_register_info_names_constified = true; - for (uint32_t i=0; iConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + value_idx); if (arg_reg_num != LLDB_INVALID_REGNUM) @@ -455,7 +459,7 @@ ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread, // when reading data const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfoByName("r0", 0); - if (compiler_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerOrEnumerationType (is_signed)) { size_t bit_width = compiler_type.GetBitSize(&thread); @@ -594,7 +598,7 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) + if (compiler_type.IsIntegerOrEnumerationType (is_signed) || compiler_type.IsPointerType()) { DataExtractor data; Error data_error; @@ -843,6 +847,7 @@ ABIMacOSX_arm::RegisterIsVolatile (const RegisterInfo *reg_info) default: break; } + break; case '4': case '5': case '6': @@ -878,30 +883,14 @@ ABIMacOSX_arm::RegisterIsVolatile (const RegisterInfo *reg_info) break; case '2': - switch (name[2]) - { - case '\0': - return true; // s2 is volatile - default: - break; - } - break; - case '3': - switch (name[2]) - { - case '\0': - return true; // s3 is volatile - default: - break; - } case '4': case '5': case '6': case '7': case '8': case '9': - return name[2] == '\0'; // s4 - s9 are volatile + return name[2] == '\0'; // s2 - s9 are volatile default: break; @@ -926,7 +915,8 @@ ABIMacOSX_arm::RegisterIsVolatile (const RegisterInfo *reg_info) default: break; }; - case '0': + break; + case '0': case '2': case '3': return name[2] == '\0'; // q0-q3 are volatile @@ -967,6 +957,7 @@ ABIMacOSX_arm::GetPluginNameStatic() //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + lldb_private::ConstString ABIMacOSX_arm::GetPluginName() { @@ -978,4 +969,3 @@ ABIMacOSX_arm::GetPluginVersion() { return 1; } - diff --git a/source/Plugins/ABI/MacOSX-arm/Makefile b/source/Plugins/ABI/MacOSX-arm/Makefile deleted file mode 100644 index 18073266d34d..000000000000 --- a/source/Plugins/ABI/MacOSX-arm/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ABI/MacOSX-arm/Makefile ------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===--------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginABIMacOSX_arm -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp index 0e6f9d663ae8..ad3d8cb03b86 100644 --- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp +++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp @@ -9,6 +9,14 @@ #include "ABIMacOSX_arm64.h" +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" + #include "lldb/Core/ConstString.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" @@ -25,159 +33,153 @@ #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/Triple.h" - #include "Utility/ARM64_DWARF_Registers.h" -#include - using namespace lldb; using namespace lldb_private; static const char *pluginDesc = "Mac OS X ABI for arm64 targets"; - static RegisterInfo g_register_infos[] = { // 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 }, - { "x2", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x3", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x4", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x4, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x5", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x5, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x6", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x6, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x7", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x7, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x8", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x9", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x10", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x11", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x12", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x13", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x14", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x15", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x16", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x17", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x18", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x19", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x20", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x21", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x22", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x23", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x24", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x25", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x26", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x27", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x28", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "fp", "x29", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x29, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "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 }, - - { "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 }, - { "v2", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v3", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v4", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v5", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v6", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v7", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v8", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v9", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v10", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v11", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v12", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v13", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v14", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v15", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v16", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v17", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v18", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v19", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v20", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v21", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v22", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v23", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v24", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v25", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v26", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v27", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v28", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v29", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v30", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v31", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - - { "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 } + { "x0", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x1", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x2", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x3", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x4", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x4, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x5", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x5, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x6", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x6, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x7", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x7, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x8", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x9", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x10", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x11", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x12", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x13", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x14", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x15", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x16", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x17", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x18", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x19", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x20", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x21", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x22", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x23", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x24", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x25", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x26", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x27", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x28", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "fp", "x29", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x29, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "lr", "x30", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x30, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "sp", "x31", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x31, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "pc", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + + { "v0", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v1", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v2", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v3", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v4", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v5", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v6", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v7", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v8", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v9", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v10", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v11", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v12", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v13", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v14", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v15", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v16", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v17", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v18", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v19", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v20", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v21", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v22", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v23", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v24", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v25", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v26", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v27", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v28", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v29", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v30", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v31", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + + { "fpsr", nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "fpcr", nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + + { "s0", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s1", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s2", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s3", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s4", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s5", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s6", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s7", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s8", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s9", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s10", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s11", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s12", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s13", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s14", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s15", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s16", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s17", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s18", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s19", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s20", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s21", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s22", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s23", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s24", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s25", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s26", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s27", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s28", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s29", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s30", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s31", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + + { "d0", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d1", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d2", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d3", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d4", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d5", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d6", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d7", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d8", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d9", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d10", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d11", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d12", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d13", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d14", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d15", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d16", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d17", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d18", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d19", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d20", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d21", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d22", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d23", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d24", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d25", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d26", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d27", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d28", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d29", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d30", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d31", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 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); @@ -192,7 +194,7 @@ ABIMacOSX_arm64::GetRegisterInfoArray (uint32_t &count) if (!g_register_info_names_constified) { g_register_info_names_constified = true; - for (uint32_t i=0; iConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + value_idx); if (arg_reg_num != LLDB_INVALID_REGNUM) @@ -444,7 +446,7 @@ ABIMacOSX_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueO return error; } - const uint32_t type_flags = return_value_type.GetTypeInfo (NULL); + const uint32_t type_flags = return_value_type.GetTypeInfo(nullptr); if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) { @@ -670,6 +672,7 @@ ABIMacOSX_arm64::RegisterIsVolatile (const RegisterInfo *reg_info) case '3': // x30 aka lr treat as non-volatile if (name[2] == '0') return false; + break; default: return true; } @@ -734,12 +737,12 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, const size_t base_byte_size = base_type.GetByteSize(nullptr); uint32_t data_offset = 0; - for (uint32_t i=0; iGetRegisterInfoByName(v_name, 0); - if (reg_info == NULL) + if (reg_info == nullptr) return false; if (base_byte_size > reg_info->byte_size) @@ -788,7 +791,7 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, return false; const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num); - if (reg_info == NULL) + if (reg_info == nullptr) return false; RegisterValue reg_value; @@ -809,7 +812,7 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, } else { - const RegisterInfo *reg_info = NULL; + const RegisterInfo *reg_info = nullptr; if (is_return_value) { // We are assuming we are decoding this immediately after returning @@ -828,12 +831,12 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, if (reg_num == LLDB_INVALID_REGNUM) return false; reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num); - if (reg_info == NULL) + if (reg_info == nullptr) return false; ++NGRN; } - if (reg_info == NULL) + if (reg_info == nullptr) return false; const lldb::addr_t value_addr = reg_ctx->ReadRegisterAsUnsigned(reg_info, LLDB_INVALID_ADDRESS); @@ -863,7 +866,7 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_ Value value; ExecutionContext exe_ctx (thread.shared_from_this()); - if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL) + if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr) return return_valobj_sp; //value.SetContext (Value::eContextTypeClangType, return_compiler_type); @@ -875,7 +878,7 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_ const size_t byte_size = return_compiler_type.GetByteSize(nullptr); - const uint32_t type_flags = return_compiler_type.GetTypeInfo (NULL); + const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr); if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) { @@ -1010,7 +1013,6 @@ ABIMacOSX_arm64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_ return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); - } else if (type_flags & eTypeIsVector) { @@ -1084,6 +1086,7 @@ ABIMacOSX_arm64::Terminate() //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + ConstString ABIMacOSX_arm64::GetPluginNameStatic() { @@ -1096,4 +1099,3 @@ ABIMacOSX_arm64::GetPluginVersion() { return 1; } - diff --git a/source/Plugins/ABI/MacOSX-arm64/Makefile b/source/Plugins/ABI/MacOSX-arm64/Makefile deleted file mode 100644 index 7fc6909e43cc..000000000000 --- a/source/Plugins/ABI/MacOSX-arm64/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ABI/MacOSX-arm64/Makefile ------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginABIMacOSX_arm64 -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp index 75e5fb1558e6..70c7adb8e5b5 100644 --- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp +++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp @@ -9,6 +9,15 @@ #include "ABIMacOSX_i386.h" +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" + +// Project includes #include "lldb/Core/ConstString.h" #include "lldb/Core/Error.h" #include "lldb/Core/Module.h" @@ -22,11 +31,6 @@ #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/Triple.h" - -#include - using namespace lldb; using namespace lldb_private; @@ -82,60 +86,59 @@ enum dwarf_ymm7 = dwarf_xmm7 }; - static RegisterInfo g_register_infos[] = { // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS // ====== ======= == === ============= ============ ===================== ===================== ============================ ==================== ====================== ========== =============== - { "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} + { "eax", nullptr, 4, 0, eEncodingUint , eFormatHex , { ehframe_eax , dwarf_eax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "ebx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { ehframe_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "ecx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { ehframe_ecx , dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "edx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { ehframe_edx , dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "esi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { ehframe_esi , dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "edi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { ehframe_edi , dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { ehframe_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { ehframe_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { ehframe_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 }, + { "stmm0" , nullptr,10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "stmm1" , nullptr,10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "stmm2" , nullptr,10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "stmm3" , nullptr,10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "stmm4" , nullptr,10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "stmm5" , nullptr,10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "stmm6" , nullptr,10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "stmm7" , nullptr,10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm7 , 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); @@ -150,7 +153,7 @@ ABIMacOSX_i386::GetRegisterInfoArray (uint32_t &count) if (!g_register_info_names_constified) { g_register_info_names_constified = true; - for (uint32_t i=0; iGetScalar(), compiler_type.GetBitSize(&thread), @@ -359,7 +363,7 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) + if (compiler_type.IsIntegerOrEnumerationType (is_signed) || compiler_type.IsPointerType()) { DataExtractor data; Error data_error; @@ -432,7 +436,7 @@ ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread, bool is_signed; - if (compiler_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerOrEnumerationType (is_signed)) { size_t bit_width = compiler_type.GetBitSize(&thread); @@ -626,6 +630,7 @@ ABIMacOSX_i386::GetPluginNameStatic () //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + lldb_private::ConstString ABIMacOSX_i386::GetPluginName() { @@ -637,4 +642,3 @@ ABIMacOSX_i386::GetPluginVersion() { return 1; } - diff --git a/source/Plugins/ABI/MacOSX-i386/Makefile b/source/Plugins/ABI/MacOSX-i386/Makefile deleted file mode 100644 index d9bc73922563..000000000000 --- a/source/Plugins/ABI/MacOSX-i386/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ABI/MacOSX-i386/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginABIMacOSX_i386 -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp index ef625dece265..c23b41c11ccb 100644 --- a/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp +++ b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp @@ -1,4 +1,4 @@ -//===-- ABISysV_arm.cpp --------------------------------------*- C++ -*-===// +//===-- ABISysV_arm.cpp -----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -9,6 +9,15 @@ #include "ABISysV_arm.h" +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" + +// Project includes #include "lldb/Core/ConstString.h" #include "lldb/Core/Error.h" #include "lldb/Core/Module.h" @@ -23,15 +32,10 @@ #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/Triple.h" - #include "Utility/ARM_DWARF_Registers.h" #include "Utility/ARM_ehframe_Registers.h" #include "Plugins/Process/Utility/ARMDefines.h" -#include - using namespace lldb; using namespace lldb_private; @@ -39,111 +43,112 @@ static RegisterInfo g_register_infos[] = { // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS // ========== ======= == === ============= ============ ======================= =================== =========================== ======================= ====================== ========== =============== - { "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}, - { "r11_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r11_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r12_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r12_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r13_usr", "sp_usr", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r14_usr", "lr_usr", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r8_fiq", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r8_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r9_fiq", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r9_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r10_fiq", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r10_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r11_fiq", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r11_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r12_fiq", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r12_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r13_fiq", "sp_fiq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r14_fiq", "lr_fiq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r13_irq", "sp_irq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_irq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r14_irq", "lr_irq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_irq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r13_abt", "sp_abt", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_abt, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r14_abt", "lr_abt", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_abt, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r13_und", "sp_und", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_und, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r14_und", "lr_und", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_und, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r13_svc", "sp_svc", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_svc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r14_svc", "lr_svc", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_svc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 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 }, nullptr, nullptr }, + { "r1", "arg2", 4, 0, eEncodingUint , eFormatHex, { ehframe_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r2", "arg3", 4, 0, eEncodingUint , eFormatHex, { ehframe_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r3", "arg4", 4, 0, eEncodingUint , eFormatHex, { ehframe_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r4", nullptr, 4, 0, eEncodingUint , eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r5", nullptr, 4, 0, eEncodingUint , eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r6", nullptr, 4, 0, eEncodingUint , eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r7", nullptr, 4, 0, eEncodingUint , eFormatHex, { ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r8", nullptr, 4, 0, eEncodingUint , eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r9", nullptr, 4, 0, eEncodingUint , eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r10", nullptr, 4, 0, eEncodingUint , eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r11", nullptr, 4, 0, eEncodingUint , eFormatHex, { ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r12", nullptr, 4, 0, eEncodingUint , eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "sp", "r13", 4, 0, eEncodingUint , eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "lr", "r14", 4, 0, eEncodingUint , eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "pc", "r15", 4, 0, eEncodingUint , eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s0", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s1", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s2", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s3", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s4", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s5", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s6", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s7", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s8", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s9", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s10", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s11", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s12", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s13", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s14", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s15", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s16", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s17", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s18", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s19", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s20", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s21", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s22", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s23", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s24", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s25", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s26", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s27", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s28", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s29", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s30", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s31", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "fpscr", nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d0", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d1", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d2", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d3", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d4", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d5", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d6", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d7", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d8", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d9", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d10", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d11", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d12", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d13", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d14", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d15", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d16", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d17", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d18", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d19", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d20", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d21", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d22", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d23", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d24", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d25", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d26", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d27", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d28", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d29", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d30", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d31", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r8_usr", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r8_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r9_usr", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r9_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r10_usr", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r10_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r11_usr", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r11_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r12_usr", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r12_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r13_usr", "sp_usr", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r14_usr", "lr_usr", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r8_fiq", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r8_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r9_fiq", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r9_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r10_fiq", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r10_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r11_fiq", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r11_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r12_fiq", nullptr, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r12_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r13_fiq", "sp_fiq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r14_fiq", "lr_fiq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_fiq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r13_irq", "sp_irq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_irq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r14_irq", "lr_irq", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_irq, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r13_abt", "sp_abt", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_abt, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r14_abt", "lr_abt", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_abt, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r13_und", "sp_und", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_und, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r14_und", "lr_und", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_und, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r13_svc", "sp_svc", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r13_svc, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r14_svc", "lr_svc", 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r14_svc, 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); static bool g_register_info_names_constified = false; @@ -156,7 +161,7 @@ ABISysV_arm::GetRegisterInfoArray (uint32_t &count) if (!g_register_info_names_constified) { g_register_info_names_constified = true; - for (uint32_t i=0; iGetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + value_idx); if (arg_reg_info) { @@ -414,6 +418,20 @@ GetReturnValuePassedInMemory(Thread &thread, RegisterContext* reg_ctx, size_t by return true; } +bool +ABISysV_arm::IsArmHardFloat (Thread &thread) const +{ + ProcessSP process_sp (thread.GetProcess()); + if (process_sp) + { + const ArchSpec &arch (process_sp->GetTarget().GetArchitecture()); + + return (arch.GetFlags() & ArchSpec::eARM_abi_hard_float) != 0; + } + + return false; +} + ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl (Thread &thread, lldb_private::CompilerType &compiler_type) const @@ -434,14 +452,18 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread, bool is_signed; bool is_complex; uint32_t float_count; + bool is_vfp_candidate = false; + uint8_t vfp_count = 0; + uint8_t vfp_byte_size = 0; // Get the pointer to the first stack argument so we have a place to start // when reading data const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); size_t bit_width = compiler_type.GetBitSize(&thread); + size_t byte_size = compiler_type.GetByteSize(&thread); - if (compiler_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerOrEnumerationType (is_signed)) { switch (bit_width) { @@ -486,8 +508,13 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread, } else if (compiler_type.IsVectorType(nullptr, nullptr)) { - size_t byte_size = compiler_type.GetByteSize(&thread); - if (byte_size <= 16) + if (IsArmHardFloat(thread) && (byte_size == 8 || byte_size == 16)) + { + is_vfp_candidate = true; + vfp_byte_size = 8; + vfp_count = (byte_size == 8?1:2); + } + else if (byte_size <= 16) { DataBufferHeap buffer(16, 0); uint32_t* buffer_ptr = (uint32_t*)buffer.GetBytes(); @@ -516,39 +543,135 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread, case 64: { static_assert(sizeof(double) == sizeof(uint64_t), ""); - const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2); - uint64_t raw_value; - raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; - raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r1_reg_info, 0) & UINT32_MAX)) << 32; - value.GetScalar() = *reinterpret_cast(&raw_value); + + if (IsArmHardFloat(thread)) + { + RegisterValue reg_value; + const RegisterInfo *d0_reg_info = reg_ctx->GetRegisterInfoByName("d0", 0); + reg_ctx->ReadRegister(d0_reg_info, reg_value); + value.GetScalar() = reg_value.GetAsDouble(); + } + else + { + uint64_t raw_value; + const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2); + raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; + raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r1_reg_info, 0) & UINT32_MAX)) << 32; + value.GetScalar() = *reinterpret_cast(&raw_value); + } break; } case 16: // Half precision returned after a conversion to single precision case 32: { static_assert(sizeof(float) == sizeof(uint32_t), ""); - uint32_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; - value.GetScalar() = *reinterpret_cast(&raw_value); + + if (IsArmHardFloat(thread)) + { + RegisterValue reg_value; + const RegisterInfo *s0_reg_info = reg_ctx->GetRegisterInfoByName("s0", 0); + reg_ctx->ReadRegister(s0_reg_info, reg_value); + value.GetScalar() = reg_value.GetAsFloat(); + } + else + { + uint32_t raw_value; + raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; + value.GetScalar() = *reinterpret_cast(&raw_value); + } break; } } } - else + else if (is_complex && float_count == 2) { + if (IsArmHardFloat(thread)) + { + is_vfp_candidate = true; + vfp_byte_size = byte_size / 2; + vfp_count = 2; + } + else if (!GetReturnValuePassedInMemory(thread, reg_ctx, bit_width / 8, value)) + return return_valobj_sp; + } + else // not handled yet return return_valobj_sp; - } } else if (compiler_type.IsAggregateType()) { - size_t byte_size = compiler_type.GetByteSize(&thread); + if (IsArmHardFloat(thread)) + { + CompilerType base_type; + const uint32_t homogeneous_count = compiler_type.IsHomogeneousAggregate (&base_type); + + if (homogeneous_count > 0 && homogeneous_count <= 4) + { + if (base_type.IsVectorType(nullptr, nullptr)) + { + uint64_t base_byte_size = base_type.GetByteSize(nullptr); + if (base_byte_size == 8 || base_byte_size == 16) + { + is_vfp_candidate = true; + vfp_byte_size = 8; + vfp_count = (base_type.GetByteSize(nullptr) == 8 ? homogeneous_count : homogeneous_count * 2); + } + } + else if (base_type.IsFloatingPointType(float_count, is_complex)) + { + if (float_count == 1 && !is_complex) + { + is_vfp_candidate = true; + vfp_byte_size = base_type.GetByteSize(nullptr); + vfp_count = homogeneous_count; + } + } + } + else if (homogeneous_count == 0) + { + const uint32_t num_children = compiler_type.GetNumFields (); + + if (num_children > 0 && num_children <=2) + { + uint32_t index = 0; + for (index = 0; index < num_children; index++) + { + std::string name; + base_type = compiler_type.GetFieldAtIndex (index, name, NULL, NULL, NULL); + + if (base_type.IsFloatingPointType(float_count, is_complex)) + { + if (float_count == 2 && is_complex) + { + if (index != 0 && vfp_byte_size != base_type.GetByteSize(nullptr)) + break; + else + vfp_byte_size = base_type.GetByteSize(nullptr); + } + else + break; + } + else + break; + } + + if (index == num_children) + { + is_vfp_candidate = true; + vfp_byte_size = (vfp_byte_size >> 1); + vfp_count = (num_children << 1); + } + } + } + } + if (byte_size <= 4) { RegisterValue r0_reg_value; uint32_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; value.SetBytes(&raw_value, byte_size); } - else + else if (!is_vfp_candidate) { if (!GetReturnValuePassedInMemory(thread, reg_ctx, byte_size, value)) return return_valobj_sp; @@ -560,6 +683,64 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread, return return_valobj_sp; } + if (is_vfp_candidate) + { + ProcessSP process_sp (thread.GetProcess()); + ByteOrder byte_order = process_sp->GetByteOrder(); + + DataBufferSP data_sp (new DataBufferHeap(byte_size, 0)); + uint32_t data_offset = 0; + + for (uint32_t reg_index = 0; reg_index < vfp_count; reg_index++) + { + uint32_t regnum = 0; + + if (vfp_byte_size == 4) + regnum = dwarf_s0 + reg_index; + else if (vfp_byte_size == 8) + regnum = dwarf_d0 + reg_index; + else + break; + + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo (eRegisterKindDWARF, regnum); + if (reg_info == NULL) + break; + + RegisterValue reg_value; + if (!reg_ctx->ReadRegister(reg_info, reg_value)) + break; + + // Make sure we have enough room in "data_sp" + if ((data_offset + vfp_byte_size) <= data_sp->GetByteSize()) + { + Error error; + const size_t bytes_copied = reg_value.GetAsMemoryData (reg_info, + data_sp->GetBytes() + data_offset, + vfp_byte_size, + byte_order, + error); + if (bytes_copied != vfp_byte_size) + break; + + data_offset += bytes_copied; + } + } + + if (data_offset == byte_size) + { + DataExtractor data; + data.SetByteOrder(byte_order); + data.SetAddressByteSize(process_sp->GetAddressByteSize()); + data.SetData(data_sp); + + return ValueObjectConstResult::Create (&thread, compiler_type, ConstString(""), data); + } + else + { // Some error occurred while getting values from registers + return return_valobj_sp; + } + } + // If we get here, we have a valid Value, so make our ValueObject out of it: return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(), @@ -594,7 +775,7 @@ ABISysV_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) + if (compiler_type.IsIntegerOrEnumerationType (is_signed) || compiler_type.IsPointerType()) { DataExtractor data; Error data_error; @@ -802,6 +983,7 @@ ABISysV_arm::RegisterIsVolatile (const RegisterInfo *reg_info) default: break; } + break; case '4': case '5': case '6': @@ -837,30 +1019,14 @@ ABISysV_arm::RegisterIsVolatile (const RegisterInfo *reg_info) break; case '2': - switch (name[2]) - { - case '\0': - return true; // s2 is volatile - default: - break; - } - break; - case '3': - switch (name[2]) - { - case '\0': - return true; // s3 is volatile - default: - break; - } case '4': case '5': case '6': case '7': case '8': case '9': - return name[2] == '\0'; // s4 - s9 are volatile + return name[2] == '\0'; // s2 - s9 are volatile default: break; @@ -883,9 +1049,11 @@ ABISysV_arm::RegisterIsVolatile (const RegisterInfo *reg_info) case '5': return true; // q10-q15 are volatile default: - break; - }; - case '0': + return false; + } + break; + + case '0': case '2': case '3': return name[2] == '\0'; // q0-q3 are volatile @@ -926,6 +1094,7 @@ ABISysV_arm::GetPluginNameStatic() //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + lldb_private::ConstString ABISysV_arm::GetPluginName() { @@ -937,4 +1106,3 @@ ABISysV_arm::GetPluginVersion() { return 1; } - diff --git a/source/Plugins/ABI/SysV-arm/ABISysV_arm.h b/source/Plugins/ABI/SysV-arm/ABISysV_arm.h index e3b280296a64..11a2601501e4 100644 --- a/source/Plugins/ABI/SysV-arm/ABISysV_arm.h +++ b/source/Plugins/ABI/SysV-arm/ABISysV_arm.h @@ -79,6 +79,9 @@ public: const lldb_private::RegisterInfo * GetRegisterInfoArray (uint32_t &count) override; + bool + IsArmHardFloat (lldb_private::Thread &thread) const; + //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ diff --git a/source/Plugins/ABI/SysV-arm/Makefile b/source/Plugins/ABI/SysV-arm/Makefile deleted file mode 100644 index a1d95dc17320..000000000000 --- a/source/Plugins/ABI/SysV-arm/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ABI/SysV-arm/Makefile ------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===--------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginABISysV_arm -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp index bc6df235cb1e..e4ed523b9d0a 100644 --- a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp +++ b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp @@ -1,4 +1,4 @@ -//===-- ABISysV_arm64.cpp -------------------------------------*- C++ -*-===// +//===-- ABISysV_arm64.cpp ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -9,6 +9,15 @@ #include "ABISysV_arm64.h" +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" + +// Project includes #include "lldb/Core/ConstString.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" @@ -24,13 +33,8 @@ #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/Triple.h" - #include "Utility/ARM64_DWARF_Registers.h" -#include - using namespace lldb; using namespace lldb_private; @@ -38,142 +42,142 @@ static RegisterInfo g_register_infos[] = { // 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 }, - { "x2", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x3", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x4", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x4, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x5", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x5, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x6", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x6, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x7", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x7, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x8", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x9", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x10", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x11", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x12", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x13", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x14", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x15", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x16", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x17", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x18", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x19", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x20", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x21", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x22", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x23", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x24", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x25", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x26", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x27", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "x28", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "fp", "x29", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x29, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "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 }, - - { "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 }, - { "v2", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v3", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v4", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v5", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v6", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v7", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v8", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v9", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v10", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v11", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v12", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v13", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v14", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v15", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v16", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v17", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v18", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v19", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v20", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v21", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v22", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v23", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v24", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v25", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v26", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v27", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v28", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v29", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v30", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "v31", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - - { "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 } + { "x0", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x1", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x2", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x3", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x4", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x4, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x5", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x5, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x6", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x6, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x7", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x7, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x8", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x9", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x10", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x11", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x12", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x13", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x14", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x15", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x16", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x17", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x18", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x19", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x20", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x21", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x22", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x23", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x24", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x25", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x26", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x27", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "x28", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "fp", "x29", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x29, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "lr", "x30", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x30, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "sp", "x31", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x31, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "pc", nullptr, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + + { "v0", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v1", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v2", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v3", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v4", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v5", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v6", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v7", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v8", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v9", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v10", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v11", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v12", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v13", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v14", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v15", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v16", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v17", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v18", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v19", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v20", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v21", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v22", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v23", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v24", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v25", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v26", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v27", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v28", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v29", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v30", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "v31", nullptr, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + + { "fpsr", nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "fpcr", nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + + { "s0", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s1", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s2", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s3", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s4", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s5", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s6", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s7", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s8", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s9", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s10", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s11", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s12", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s13", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s14", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s15", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s16", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s17", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s18", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s19", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s20", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s21", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s22", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s23", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s24", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s25", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s26", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s27", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s28", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s29", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s30", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "s31", nullptr, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + + { "d0", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d1", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d2", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d3", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d4", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d5", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d6", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d7", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d8", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d9", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d10", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d11", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d12", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d13", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d14", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d15", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d16", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d17", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d18", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d19", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d20", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d21", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d22", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d23", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d24", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d25", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d26", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d27", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d28", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d29", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d30", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "d31", nullptr, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 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); @@ -209,6 +213,7 @@ ABISysV_arm64::GetRedZoneSize () const //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + ABISP ABISysV_arm64::CreateInstance (const ArchSpec &arch) { @@ -317,7 +322,7 @@ ABISysV_arm64::GetArgumentValues (Thread &thread, ValueList &values) const { bool is_signed = false; size_t bit_width = 0; - if (value_type.IsIntegerType (is_signed)) + if (value_type.IsIntegerOrEnumerationType (is_signed)) { bit_width = value_type.GetBitSize(&thread); } @@ -336,7 +341,7 @@ ABISysV_arm64::GetArgumentValues (Thread &thread, ValueList &values) const if (value_idx < 8) { // Arguments 1-8 are in x0-x7... - const RegisterInfo *reg_info = NULL; + const RegisterInfo *reg_info = nullptr; reg_info= reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + value_idx); if (reg_info) @@ -418,7 +423,7 @@ ABISysV_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj return error; } - const uint32_t type_flags = return_value_type.GetTypeInfo (NULL); + const uint32_t type_flags = return_value_type.GetTypeInfo(nullptr); if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) { @@ -648,6 +653,7 @@ ABISysV_arm64::RegisterIsVolatile (const RegisterInfo *reg_info) case '3': // x30 (lr) and x31 (sp) treat as non-volatile if (name[2] == '0' || name[2] == '1') return false; + break; default: return true; // all volatile cases not handled above fall here. } @@ -717,7 +723,7 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, char v_name[8]; ::snprintf (v_name, sizeof(v_name), "v%u", NSRN); const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(v_name, 0); - if (reg_info == NULL) + if (reg_info == nullptr) return false; if (base_byte_size > reg_info->byte_size) @@ -762,7 +768,7 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, return false; const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + NGRN); - if (reg_info == NULL) + if (reg_info == nullptr) return false; RegisterValue reg_value; @@ -783,7 +789,7 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, } else { - const RegisterInfo *reg_info = NULL; + const RegisterInfo *reg_info = nullptr; if (is_return_value) { // We are assuming we are decoding this immediately after returning @@ -799,12 +805,12 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, return false; reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + NGRN); - if (reg_info == NULL) + if (reg_info == nullptr) return false; ++NGRN; } - if (reg_info == NULL) + if (reg_info == nullptr) return false; const lldb::addr_t value_addr = reg_ctx->ReadRegisterAsUnsigned(reg_info, LLDB_INVALID_ADDRESS); @@ -834,7 +840,7 @@ ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_co Value value; ExecutionContext exe_ctx (thread.shared_from_this()); - if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL) + if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr) return return_valobj_sp; //value.SetContext (Value::eContextTypeClangType, return_compiler_type); @@ -846,7 +852,7 @@ ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_co const size_t byte_size = return_compiler_type.GetByteSize(nullptr); - const uint32_t type_flags = return_compiler_type.GetTypeInfo (NULL); + const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr); if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) { @@ -859,7 +865,7 @@ ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_co // Extract the register context so we can read arguments from registers if (byte_size <= 8) { - const RegisterInfo *x0_reg_info = NULL; + const RegisterInfo *x0_reg_info = nullptr; x0_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); if (x0_reg_info) { @@ -872,7 +878,7 @@ ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_co case 16: // uint128_t // In register x0 and x1 { - const RegisterInfo *x1_reg_info = NULL; + const RegisterInfo *x1_reg_info = nullptr; x1_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2); if (x1_reg_info) @@ -983,13 +989,11 @@ ABISysV_arm64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_co return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); - } else if (type_flags & eTypeIsVector) { if (byte_size > 0) { - const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0); if (v0_info) @@ -1064,6 +1068,7 @@ ABISysV_arm64::GetPluginNameStatic() //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + ConstString ABISysV_arm64::GetPluginName() { @@ -1075,4 +1080,3 @@ ABISysV_arm64::GetPluginVersion() { return 1; } - diff --git a/source/Plugins/ABI/SysV-arm64/Makefile b/source/Plugins/ABI/SysV-arm64/Makefile deleted file mode 100644 index a72ecd83404d..000000000000 --- a/source/Plugins/ABI/SysV-arm64/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ABI/SysV-arm64/Makefile ------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginABISysV_arm64 -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp index e0299b6f0b94..596f3dc1166a 100644 --- a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp +++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp @@ -1,4 +1,4 @@ -//===-- ABISysV_hexagon.cpp --------------------------------------*- C++ -*-===// +//===-- ABISysV_hexagon.cpp -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -9,6 +9,13 @@ #include "ABISysV_hexagon.h" +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "llvm/ADT/Triple.h" +#include "llvm/IR/DerivedTypes.h" + +// Project includes #include "lldb/Core/ConstString.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Error.h" @@ -27,111 +34,107 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Thread.h" -#include "llvm/ADT/Triple.h" - -#include "llvm/IR/DerivedTypes.h" - using namespace lldb; using namespace lldb_private; static RegisterInfo g_register_infos[] = { // hexagon-core.xml - { "r00" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 0, 0, LLDB_INVALID_REGNUM, 0, 0 }, NULL, NULL }, - { "r01" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 1, 1, LLDB_INVALID_REGNUM, 1, 1 }, NULL, NULL }, - { "r02" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 2, 2, LLDB_INVALID_REGNUM, 2, 2 }, NULL, NULL }, - { "r03" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 3, 3, LLDB_INVALID_REGNUM, 3, 3 }, NULL, NULL }, - { "r04" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 4, 4, LLDB_INVALID_REGNUM, 4, 4 }, NULL, NULL }, - { "r05" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 5, 5, LLDB_INVALID_REGNUM, 5, 5 }, NULL, NULL }, - { "r06" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 6, 6, LLDB_INVALID_REGNUM, 6, 6 }, NULL, NULL }, - { "r07" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 7, 7, LLDB_INVALID_REGNUM, 7, 7 }, NULL, NULL }, - { "r08" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 8, 8, LLDB_INVALID_REGNUM, 8, 8 }, NULL, NULL }, - { "r09" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 9, 9, LLDB_INVALID_REGNUM, 9, 9 }, NULL, NULL }, - { "r10" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 10, 10, LLDB_INVALID_REGNUM, 10, 10 }, NULL, NULL }, - { "r11" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 11, 11, LLDB_INVALID_REGNUM, 11, 11 }, NULL, NULL }, - { "r12" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 12, 12, LLDB_INVALID_REGNUM, 12, 12 }, NULL, NULL }, - { "r13" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 13, 13, LLDB_INVALID_REGNUM, 13, 13 }, NULL, NULL }, - { "r14" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 14, 14, LLDB_INVALID_REGNUM, 14, 14 }, NULL, NULL }, - { "r15" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 15, 15, LLDB_INVALID_REGNUM, 15, 15 }, NULL, NULL }, - { "r16" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 16, 16, LLDB_INVALID_REGNUM, 16, 16 }, NULL, NULL }, - { "r17" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 17, 17, LLDB_INVALID_REGNUM, 17, 17 }, NULL, NULL }, - { "r18" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 18, 18, LLDB_INVALID_REGNUM, 18, 18 }, NULL, NULL }, - { "r19" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 19, 19, LLDB_INVALID_REGNUM, 19, 19 }, NULL, NULL }, - { "r20" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 20, 20, LLDB_INVALID_REGNUM, 20, 20 }, NULL, NULL }, - { "r21" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 21, 21, LLDB_INVALID_REGNUM, 21, 21 }, NULL, NULL }, - { "r22" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 22, 22, LLDB_INVALID_REGNUM, 22, 22 }, NULL, NULL }, - { "r23" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 23, 23, LLDB_INVALID_REGNUM, 23, 23 }, NULL, NULL }, - { "r24" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 24, 24, LLDB_INVALID_REGNUM, 24, 24 }, NULL, NULL }, - { "r25" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 25, 25, LLDB_INVALID_REGNUM, 25, 25 }, NULL, NULL }, - { "r26" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 26, 26, LLDB_INVALID_REGNUM, 26, 26 }, NULL, NULL }, - { "r27" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 27, 27, LLDB_INVALID_REGNUM, 27, 27 }, NULL, NULL }, - { "r28" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 28, 28, LLDB_INVALID_REGNUM, 28, 28 }, NULL, NULL }, - { "sp" ,"r29", 4, 0, eEncodingUint, eFormatAddressInfo, { 29, 29, LLDB_REGNUM_GENERIC_SP, 29, 29 }, NULL, NULL }, - { "fp" ,"r30", 4, 0, eEncodingUint, eFormatAddressInfo, { 30, 30, LLDB_REGNUM_GENERIC_FP, 30, 30 }, NULL, NULL }, - { "lr" ,"r31", 4, 0, eEncodingUint, eFormatAddressInfo, { 31, 31, LLDB_REGNUM_GENERIC_RA, 31, 31 }, NULL, NULL }, - { "sa0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 32, 32, LLDB_INVALID_REGNUM, 32, 32 }, NULL, NULL }, - { "lc0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 33, 33, LLDB_INVALID_REGNUM, 33, 33 }, NULL, NULL }, - { "sa1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 34, 34, LLDB_INVALID_REGNUM, 34, 34 }, NULL, NULL }, - { "lc1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 35, 35, LLDB_INVALID_REGNUM, 35, 35 }, NULL, NULL }, + { "r00" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 0, 0, LLDB_INVALID_REGNUM, 0, 0 }, nullptr, nullptr }, + { "r01" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 1, 1, LLDB_INVALID_REGNUM, 1, 1 }, nullptr, nullptr }, + { "r02" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 2, 2, LLDB_INVALID_REGNUM, 2, 2 }, nullptr, nullptr }, + { "r03" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 3, 3, LLDB_INVALID_REGNUM, 3, 3 }, nullptr, nullptr }, + { "r04" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 4, 4, LLDB_INVALID_REGNUM, 4, 4 }, nullptr, nullptr }, + { "r05" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 5, 5, LLDB_INVALID_REGNUM, 5, 5 }, nullptr, nullptr }, + { "r06" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 6, 6, LLDB_INVALID_REGNUM, 6, 6 }, nullptr, nullptr }, + { "r07" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 7, 7, LLDB_INVALID_REGNUM, 7, 7 }, nullptr, nullptr }, + { "r08" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 8, 8, LLDB_INVALID_REGNUM, 8, 8 }, nullptr, nullptr }, + { "r09" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 9, 9, LLDB_INVALID_REGNUM, 9, 9 }, nullptr, nullptr }, + { "r10" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 10, 10, LLDB_INVALID_REGNUM, 10, 10 }, nullptr, nullptr }, + { "r11" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 11, 11, LLDB_INVALID_REGNUM, 11, 11 }, nullptr, nullptr }, + { "r12" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 12, 12, LLDB_INVALID_REGNUM, 12, 12 }, nullptr, nullptr }, + { "r13" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 13, 13, LLDB_INVALID_REGNUM, 13, 13 }, nullptr, nullptr }, + { "r14" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 14, 14, LLDB_INVALID_REGNUM, 14, 14 }, nullptr, nullptr }, + { "r15" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 15, 15, LLDB_INVALID_REGNUM, 15, 15 }, nullptr, nullptr }, + { "r16" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 16, 16, LLDB_INVALID_REGNUM, 16, 16 }, nullptr, nullptr }, + { "r17" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 17, 17, LLDB_INVALID_REGNUM, 17, 17 }, nullptr, nullptr }, + { "r18" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 18, 18, LLDB_INVALID_REGNUM, 18, 18 }, nullptr, nullptr }, + { "r19" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 19, 19, LLDB_INVALID_REGNUM, 19, 19 }, nullptr, nullptr }, + { "r20" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 20, 20, LLDB_INVALID_REGNUM, 20, 20 }, nullptr, nullptr }, + { "r21" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 21, 21, LLDB_INVALID_REGNUM, 21, 21 }, nullptr, nullptr }, + { "r22" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 22, 22, LLDB_INVALID_REGNUM, 22, 22 }, nullptr, nullptr }, + { "r23" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 23, 23, LLDB_INVALID_REGNUM, 23, 23 }, nullptr, nullptr }, + { "r24" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 24, 24, LLDB_INVALID_REGNUM, 24, 24 }, nullptr, nullptr }, + { "r25" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 25, 25, LLDB_INVALID_REGNUM, 25, 25 }, nullptr, nullptr }, + { "r26" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 26, 26, LLDB_INVALID_REGNUM, 26, 26 }, nullptr, nullptr }, + { "r27" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 27, 27, LLDB_INVALID_REGNUM, 27, 27 }, nullptr, nullptr }, + { "r28" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 28, 28, LLDB_INVALID_REGNUM, 28, 28 }, nullptr, nullptr }, + { "sp" ,"r29", 4, 0, eEncodingUint, eFormatAddressInfo, { 29, 29, LLDB_REGNUM_GENERIC_SP, 29, 29 }, nullptr, nullptr }, + { "fp" ,"r30", 4, 0, eEncodingUint, eFormatAddressInfo, { 30, 30, LLDB_REGNUM_GENERIC_FP, 30, 30 }, nullptr, nullptr }, + { "lr" ,"r31", 4, 0, eEncodingUint, eFormatAddressInfo, { 31, 31, LLDB_REGNUM_GENERIC_RA, 31, 31 }, nullptr, nullptr }, + { "sa0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 32, 32, LLDB_INVALID_REGNUM, 32, 32 }, nullptr, nullptr }, + { "lc0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 33, 33, LLDB_INVALID_REGNUM, 33, 33 }, nullptr, nullptr }, + { "sa1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 34, 34, LLDB_INVALID_REGNUM, 34, 34 }, nullptr, nullptr }, + { "lc1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 35, 35, LLDB_INVALID_REGNUM, 35, 35 }, nullptr, nullptr }, // --> hexagon-v4/5/55/56-sim.xml - { "p3_0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 36, 36, LLDB_INVALID_REGNUM, 36, 36 }, NULL, NULL }, + { "p3_0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 36, 36, LLDB_INVALID_REGNUM, 36, 36 }, nullptr, nullptr }, // PADDING { - { "p00" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 37, 37, LLDB_INVALID_REGNUM, 37, 37 }, NULL, NULL }, + { "p00" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 37, 37, LLDB_INVALID_REGNUM, 37, 37 }, nullptr, nullptr }, // } - { "m0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 38, 38, LLDB_INVALID_REGNUM, 38, 38 }, NULL, NULL }, - { "m1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 39, 39, LLDB_INVALID_REGNUM, 39, 39 }, NULL, NULL }, - { "usr" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 40, 40, LLDB_INVALID_REGNUM, 40, 40 }, NULL, NULL }, - { "pc" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 41, 41, LLDB_REGNUM_GENERIC_PC, 41, 41 }, NULL, NULL }, - { "ugp" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 42, 42, LLDB_INVALID_REGNUM, 42, 42 }, NULL, NULL }, - { "gp" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 43, 43, LLDB_INVALID_REGNUM, 43, 43 }, NULL, NULL }, - { "cs0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 44, 44, LLDB_INVALID_REGNUM, 44, 44 }, NULL, NULL }, - { "cs1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 45, 45, LLDB_INVALID_REGNUM, 45, 45 }, NULL, NULL }, + { "m0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 38, 38, LLDB_INVALID_REGNUM, 38, 38 }, nullptr, nullptr }, + { "m1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 39, 39, LLDB_INVALID_REGNUM, 39, 39 }, nullptr, nullptr }, + { "usr" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 40, 40, LLDB_INVALID_REGNUM, 40, 40 }, nullptr, nullptr }, + { "pc" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 41, 41, LLDB_REGNUM_GENERIC_PC, 41, 41 }, nullptr, nullptr }, + { "ugp" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 42, 42, LLDB_INVALID_REGNUM, 42, 42 }, nullptr, nullptr }, + { "gp" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 43, 43, LLDB_INVALID_REGNUM, 43, 43 }, nullptr, nullptr }, + { "cs0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 44, 44, LLDB_INVALID_REGNUM, 44, 44 }, nullptr, nullptr }, + { "cs1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 45, 45, LLDB_INVALID_REGNUM, 45, 45 }, nullptr, nullptr }, // PADDING { - { "p01" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 46, 46, LLDB_INVALID_REGNUM, 46, 46 }, NULL, NULL }, - { "p02" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 47, 47, LLDB_INVALID_REGNUM, 47, 47 }, NULL, NULL }, - { "p03" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 48, 48, LLDB_INVALID_REGNUM, 48, 48 }, NULL, NULL }, - { "p04" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 49, 49, LLDB_INVALID_REGNUM, 49, 49 }, NULL, NULL }, - { "p05" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 50, 50, LLDB_INVALID_REGNUM, 50, 50 }, NULL, NULL }, - { "p06" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 51, 51, LLDB_INVALID_REGNUM, 51, 51 }, NULL, NULL }, - { "p07" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 52, 52, LLDB_INVALID_REGNUM, 52, 52 }, NULL, NULL }, - { "p08" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 53, 53, LLDB_INVALID_REGNUM, 53, 53 }, NULL, NULL }, - { "p09" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 54, 54, LLDB_INVALID_REGNUM, 54, 54 }, NULL, NULL }, - { "p10" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 55, 55, LLDB_INVALID_REGNUM, 55, 55 }, NULL, NULL }, - { "p11" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 56, 56, LLDB_INVALID_REGNUM, 56, 56 }, NULL, NULL }, - { "p12" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 57, 57, LLDB_INVALID_REGNUM, 57, 57 }, NULL, NULL }, - { "p13" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 58, 58, LLDB_INVALID_REGNUM, 58, 58 }, NULL, NULL }, - { "p14" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 59, 59, LLDB_INVALID_REGNUM, 59, 59 }, NULL, NULL }, - { "p15" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 60, 60, LLDB_INVALID_REGNUM, 60, 60 }, NULL, NULL }, - { "p16" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 61, 61, LLDB_INVALID_REGNUM, 61, 61 }, NULL, NULL }, - { "p17" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 62, 62, LLDB_INVALID_REGNUM, 62, 62 }, NULL, NULL }, - { "p18" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 63, 63, LLDB_INVALID_REGNUM, 63, 63 }, NULL, NULL }, + { "p01" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 46, 46, LLDB_INVALID_REGNUM, 46, 46 }, nullptr, nullptr }, + { "p02" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 47, 47, LLDB_INVALID_REGNUM, 47, 47 }, nullptr, nullptr }, + { "p03" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 48, 48, LLDB_INVALID_REGNUM, 48, 48 }, nullptr, nullptr }, + { "p04" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 49, 49, LLDB_INVALID_REGNUM, 49, 49 }, nullptr, nullptr }, + { "p05" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 50, 50, LLDB_INVALID_REGNUM, 50, 50 }, nullptr, nullptr }, + { "p06" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 51, 51, LLDB_INVALID_REGNUM, 51, 51 }, nullptr, nullptr }, + { "p07" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 52, 52, LLDB_INVALID_REGNUM, 52, 52 }, nullptr, nullptr }, + { "p08" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 53, 53, LLDB_INVALID_REGNUM, 53, 53 }, nullptr, nullptr }, + { "p09" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 54, 54, LLDB_INVALID_REGNUM, 54, 54 }, nullptr, nullptr }, + { "p10" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 55, 55, LLDB_INVALID_REGNUM, 55, 55 }, nullptr, nullptr }, + { "p11" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 56, 56, LLDB_INVALID_REGNUM, 56, 56 }, nullptr, nullptr }, + { "p12" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 57, 57, LLDB_INVALID_REGNUM, 57, 57 }, nullptr, nullptr }, + { "p13" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 58, 58, LLDB_INVALID_REGNUM, 58, 58 }, nullptr, nullptr }, + { "p14" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 59, 59, LLDB_INVALID_REGNUM, 59, 59 }, nullptr, nullptr }, + { "p15" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 60, 60, LLDB_INVALID_REGNUM, 60, 60 }, nullptr, nullptr }, + { "p16" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 61, 61, LLDB_INVALID_REGNUM, 61, 61 }, nullptr, nullptr }, + { "p17" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 62, 62, LLDB_INVALID_REGNUM, 62, 62 }, nullptr, nullptr }, + { "p18" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 63, 63, LLDB_INVALID_REGNUM, 63, 63 }, nullptr, nullptr }, // } - { "sgp0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 64, 64, LLDB_INVALID_REGNUM, 64, 64 }, NULL, NULL }, + { "sgp0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 64, 64, LLDB_INVALID_REGNUM, 64, 64 }, nullptr, nullptr }, // PADDING { - { "p19" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 65, 65, LLDB_INVALID_REGNUM, 65, 65 }, NULL, NULL }, + { "p19" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 65, 65, LLDB_INVALID_REGNUM, 65, 65 }, nullptr, nullptr }, // } - { "stid" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 66, 66, LLDB_INVALID_REGNUM, 66, 66 }, NULL, NULL }, - { "elr" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 67, 67, LLDB_INVALID_REGNUM, 67, 67 }, NULL, NULL }, - { "badva0", "", 4, 0, eEncodingUint, eFormatAddressInfo, { 68, 68, LLDB_INVALID_REGNUM, 68, 68 }, NULL, NULL }, - { "badva1", "", 4, 0, eEncodingUint, eFormatAddressInfo, { 69, 69, LLDB_INVALID_REGNUM, 69, 69 }, NULL, NULL }, - { "ssr" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 70, 70, LLDB_INVALID_REGNUM, 70, 70 }, NULL, NULL }, - { "ccr" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 71, 71, LLDB_INVALID_REGNUM, 71, 71 }, NULL, NULL }, - { "htid" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 72, 72, LLDB_INVALID_REGNUM, 72, 72 }, NULL, NULL }, + { "stid" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 66, 66, LLDB_INVALID_REGNUM, 66, 66 }, nullptr, nullptr }, + { "elr" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 67, 67, LLDB_INVALID_REGNUM, 67, 67 }, nullptr, nullptr }, + { "badva0", "", 4, 0, eEncodingUint, eFormatAddressInfo, { 68, 68, LLDB_INVALID_REGNUM, 68, 68 }, nullptr, nullptr }, + { "badva1", "", 4, 0, eEncodingUint, eFormatAddressInfo, { 69, 69, LLDB_INVALID_REGNUM, 69, 69 }, nullptr, nullptr }, + { "ssr" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 70, 70, LLDB_INVALID_REGNUM, 70, 70 }, nullptr, nullptr }, + { "ccr" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 71, 71, LLDB_INVALID_REGNUM, 71, 71 }, nullptr, nullptr }, + { "htid" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 72, 72, LLDB_INVALID_REGNUM, 72, 72 }, nullptr, nullptr }, // PADDING { - { "p20" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 73, 73, LLDB_INVALID_REGNUM, 73, 73 }, NULL, NULL }, + { "p20" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 73, 73, LLDB_INVALID_REGNUM, 73, 73 }, nullptr, nullptr }, // } - { "imask" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 74, 74, LLDB_INVALID_REGNUM, 74, 74 }, NULL, NULL }, + { "imask" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 74, 74, LLDB_INVALID_REGNUM, 74, 74 }, nullptr, nullptr }, // PADDING { - { "p21" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 75, 75, LLDB_INVALID_REGNUM, 75, 75 }, NULL, NULL }, - { "p22" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 76, 76, LLDB_INVALID_REGNUM, 76, 76 }, NULL, NULL }, - { "p23" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 77, 77, LLDB_INVALID_REGNUM, 77, 77 }, NULL, NULL }, - { "p24" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 78, 78, LLDB_INVALID_REGNUM, 78, 78 }, NULL, NULL }, - { "p25" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 79, 79, LLDB_INVALID_REGNUM, 79, 79 }, NULL, NULL }, + { "p21" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 75, 75, LLDB_INVALID_REGNUM, 75, 75 }, nullptr, nullptr }, + { "p22" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 76, 76, LLDB_INVALID_REGNUM, 76, 76 }, nullptr, nullptr }, + { "p23" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 77, 77, LLDB_INVALID_REGNUM, 77, 77 }, nullptr, nullptr }, + { "p24" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 78, 78, LLDB_INVALID_REGNUM, 78, 78 }, nullptr, nullptr }, + { "p25" , "", 4, 0, eEncodingInvalid, eFormatInvalid, { 79, 79, LLDB_INVALID_REGNUM, 79, 79 }, nullptr, nullptr }, // } - { "g0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 80, 80, LLDB_INVALID_REGNUM, 80, 80 }, NULL, NULL }, - { "g1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 81, 81, LLDB_INVALID_REGNUM, 81, 81 }, NULL, NULL }, - { "g2" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 82, 82, LLDB_INVALID_REGNUM, 82, 82 }, NULL, NULL }, - { "g3" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 83, 83, LLDB_INVALID_REGNUM, 83, 83 }, NULL, NULL } + { "g0" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 80, 80, LLDB_INVALID_REGNUM, 80, 80 }, nullptr, nullptr }, + { "g1" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 81, 81, LLDB_INVALID_REGNUM, 81, 81 }, nullptr, nullptr }, + { "g2" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 82, 82, LLDB_INVALID_REGNUM, 82, 82 }, nullptr, nullptr }, + { "g3" , "", 4, 0, eEncodingUint, eFormatAddressInfo, { 83, 83, LLDB_INVALID_REGNUM, 83, 83 }, nullptr, nullptr } }; static const uint32_t k_num_register_infos = sizeof(g_register_infos)/sizeof(RegisterInfo); @@ -176,6 +179,7 @@ ABISysV_hexagon::GetRedZoneSize () const //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + ABISP ABISysV_hexagon::CreateInstance ( const ArchSpec &arch ) { @@ -273,7 +277,7 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread, sp -= argSize; // write this argument onto the stack of the host process - proc.get( )->WriteMemory( sp, arg.data_ap.get(), arg.size, error ); + proc->WriteMemory( sp, arg.data_ap.get(), arg.size, error ); if ( error.Fail( ) ) return false; @@ -463,7 +467,7 @@ ABISysV_hexagon::RegisterIsCalleeSaved ( const RegisterInfo *reg_info ) } void -ABISysV_hexagon::Initialize( void ) +ABISysV_hexagon::Initialize() { PluginManager::RegisterPlugin ( @@ -474,7 +478,7 @@ ABISysV_hexagon::Initialize( void ) } void -ABISysV_hexagon::Terminate( void ) +ABISysV_hexagon::Terminate() { PluginManager::UnregisterPlugin( CreateInstance ); } @@ -489,14 +493,15 @@ ABISysV_hexagon::GetPluginNameStatic() //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + lldb_private::ConstString -ABISysV_hexagon::GetPluginName( void ) +ABISysV_hexagon::GetPluginName() { return GetPluginNameStatic(); } uint32_t -ABISysV_hexagon::GetPluginVersion( void ) +ABISysV_hexagon::GetPluginVersion() { return 1; } diff --git a/source/Plugins/ABI/SysV-hexagon/Makefile b/source/Plugins/ABI/SysV-hexagon/Makefile deleted file mode 100644 index 23733c7e551e..000000000000 --- a/source/Plugins/ABI/SysV-hexagon/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ABI/SysV-hexagon/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginABISysV_hexagon -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp index 0a3779a2ce94..d23afe9956ba 100644 --- a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp +++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp @@ -8,6 +8,13 @@ #include "ABISysV_i386.h" +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" + +// Project includes #include "lldb/Core/ConstString.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Error.h" @@ -26,14 +33,9 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Thread.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/Triple.h" - using namespace lldb; using namespace lldb_private; - - // This source file uses the following document as a reference: //==================================================================== // System V Application Binary Interface @@ -51,8 +53,6 @@ using namespace lldb_private; // February 3, 2015 //==================================================================== - - // DWARF Register Number Mapping // See Table 2.14 of the reference document (specified on top of this file) // Comment: Table 2.14 is followed till 'mm' entries. @@ -107,7 +107,6 @@ enum dwarf_regnums dwarf_mm7 }; - static RegisterInfo g_register_infos[] = { // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS @@ -187,10 +186,10 @@ ABISysV_i386::GetRegisterInfoArray (uint32_t &count) return g_register_infos; } - //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + ABISP ABISysV_i386::CreateInstance (const ArchSpec &arch) { @@ -272,7 +271,6 @@ ABISysV_i386::PrepareTrivialCall (Thread &thread, return true; } - static bool ReadIntegerArgument (Scalar &scalar, unsigned int bit_width, @@ -294,7 +292,6 @@ ReadIntegerArgument (Scalar &scalar, return false; } - bool ABISysV_i386::GetArgumentValues (Thread &thread, ValueList &values) const @@ -328,7 +325,7 @@ ABISysV_i386::GetArgumentValues (Thread &thread, if (compiler_type) { bool is_signed; - if (compiler_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerOrEnumerationType (is_signed)) { ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread), @@ -349,8 +346,6 @@ ABISysV_i386::GetArgumentValues (Thread &thread, return true; } - - Error ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp) { @@ -496,12 +491,11 @@ ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje are yet to be implemented */ error.SetErrorString ("Currently only Integral and Floating Point clang types are supported."); } - if(!register_write_successful) + if (!register_write_successful) error.SetErrorString ("Register writing failed"); return error; } - ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, CompilerType &return_compiler_type) const @@ -523,21 +517,19 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB]; - // 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' { - uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff ; + uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff; value.SetValueType(Value::eValueTypeScalar); value.GetScalar() = ptr; return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } - else if ((type_flags & eTypeIsScalar) || (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point' { value.SetValueType(Value::eValueTypeScalar); @@ -547,7 +539,7 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, if (type_flags & eTypeIsInteger) // 'Integral' except enum { const bool is_signed = ((type_flags & eTypeIsSigned) != 0); - uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff ; + uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff; raw_value |= (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 0xffffffff) << 32; switch (byte_size) @@ -558,7 +550,7 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, case 16: // For clang::BuiltinType::UInt128 & Int128 // ToDo: Need to decide how to handle it - break ; + break; case 8: if (is_signed) @@ -598,17 +590,15 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, value, ConstString("")); } - else if (type_flags & eTypeIsEnumeration) // handles enum { - uint32_t enm = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff ; + uint32_t enm = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff; value.SetValueType(Value::eValueTypeScalar); value.GetScalar() = enm; return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } - else if (type_flags & eTypeIsFloat) // 'Floating Point' { if (byte_size <= 12) // handles float, double, long double, __float80 @@ -660,19 +650,16 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, return_compiler_type); } } - else // Neither 'Integral' nor 'Floating Point' { // If flow reaches here then check type_flags // This type_flags is unhandled } } - else if (type_flags & eTypeIsComplex) // 'Complex Floating Point' { // ToDo: Yet to be implemented } - else if (type_flags & eTypeIsVector) // 'Packed' { const size_t byte_size = return_compiler_type.GetByteSize(nullptr); @@ -754,7 +741,6 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, } } } - else // 'Decimal Floating Point' { //ToDo: Yet to be implemented @@ -762,7 +748,6 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, return return_valobj_sp; } - ValueObjectSP ABISysV_i386::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const { @@ -848,7 +833,6 @@ ABISysV_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) return true; } - // According to "Register Usage" in reference document (specified on top // of this source file) ebx, ebp, esi, edi and esp registers are preserved // i.e. non-volatile i.e. callee-saved on i386 @@ -893,7 +877,6 @@ ABISysV_i386::RegisterIsCalleeSaved (const RegisterInfo *reg_info) return false; } - void ABISysV_i386::Initialize() { @@ -902,17 +885,16 @@ ABISysV_i386::Initialize() CreateInstance); } - void ABISysV_i386::Terminate() { PluginManager::UnregisterPlugin (CreateInstance); } - //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + lldb_private::ConstString ABISysV_i386::GetPluginNameStatic() { @@ -920,7 +902,6 @@ ABISysV_i386::GetPluginNameStatic() return g_name; } - lldb_private::ConstString ABISysV_i386::GetPluginName() { diff --git a/source/Plugins/ABI/SysV-i386/Makefile b/source/Plugins/ABI/SysV-i386/Makefile deleted file mode 100644 index 0ac3cbee2d54..000000000000 --- a/source/Plugins/ABI/SysV-i386/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ABI/SysV-i386/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginABISysV_i386 -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp index 1b77946c1d1f..d6b57f9f3939 100644 --- a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp +++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp @@ -9,6 +9,13 @@ #include "ABISysV_mips.h" +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" + +// Project includes #include "lldb/Core/ConstString.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Error.h" @@ -27,9 +34,6 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Thread.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/Triple.h" - using namespace lldb; using namespace lldb_private; @@ -80,44 +84,44 @@ g_register_infos[] = { // 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}, + { "r0" , "zero", 4, 0, eEncodingUint, eFormatHex, { dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r1" , "AT", 4, 0, eEncodingUint, eFormatHex, { dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r2" , "v0", 4, 0, eEncodingUint, eFormatHex, { dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r3" , "v1", 4, 0, eEncodingUint, eFormatHex, { dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r4" , "arg1", 4, 0, eEncodingUint, eFormatHex, { dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r5" , "arg2", 4, 0, eEncodingUint, eFormatHex, { dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r6" , "arg3", 4, 0, eEncodingUint, eFormatHex, { dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r7" , "arg4", 4, 0, eEncodingUint, eFormatHex, { dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r8" , "arg5", 4, 0, eEncodingUint, eFormatHex, { dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r9" , "arg6", 4, 0, eEncodingUint, eFormatHex, { dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r10" , "arg7", 4, 0, eEncodingUint, eFormatHex, { dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r11" , "arg8", 4, 0, eEncodingUint, eFormatHex, { dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r12" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r13" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r14" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r15" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r16" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r17" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r18" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r19" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r20" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r21" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r22" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r23" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r24" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r25" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r26" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r27" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r28" , "gp", 4, 0, eEncodingUint, eFormatHex, { dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r29" , "sp", 4, 0, eEncodingUint, eFormatHex, { dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r30" , "fp", 4, 0, eEncodingUint, eFormatHex, { dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r31" , "ra", 4, 0, eEncodingUint, eFormatHex, { dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "sr" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "lo" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "hi" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "bad" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "cause" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "pc" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -138,6 +142,7 @@ ABISysV_mips::GetRedZoneSize () const //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + ABISP ABISysV_mips::CreateInstance (const ArchSpec &arch) { @@ -181,7 +186,7 @@ ABISysV_mips::PrepareTrivialCall (Thread &thread, if (!reg_ctx) return false; - const RegisterInfo *reg_info = NULL; + const RegisterInfo *reg_info = nullptr; RegisterValue reg_value; @@ -317,7 +322,7 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) + if (compiler_type.IsIntegerOrEnumerationType (is_signed) || compiler_type.IsPointerType()) { DataExtractor data; Error data_error; @@ -372,7 +377,6 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje return error; } - ValueObjectSP ABISysV_mips::GetReturnValueObjectSimple (Thread &thread, CompilerType &return_compiler_type) const { @@ -390,10 +394,14 @@ ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_com return return_valobj_sp; ExecutionContext exe_ctx (thread.shared_from_this()); - if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL) + if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr) return return_valobj_sp; + Target *target = exe_ctx.GetTargetPtr(); + const ArchSpec target_arch = target->GetArchitecture(); + ByteOrder target_byte_order = target_arch.GetByteOrder(); value.SetCompilerType(return_compiler_type); + uint32_t fp_flag = target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask; RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) @@ -405,9 +413,8 @@ ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_com // 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_compiler_type.IsIntegerType (is_signed)) + size_t bit_width = return_compiler_type.GetBitSize(&thread); + if (return_compiler_type.IsIntegerOrEnumerationType (is_signed)) { switch (bit_width) { @@ -455,45 +462,115 @@ ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_com // 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_valobj_sp = ValueObjectMemory::Create(&thread, + "", + Address(mem_address, nullptr), + 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) + if (IsSoftFloat (fp_flag)) { + uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0); + if (count != 1 && is_complex) + return return_valobj_sp; 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(&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(&raw_value); + value.GetScalar() = *((float *)(&raw_value)); + break; + case 64: + static_assert(sizeof(double) == sizeof(uint64_t), ""); + const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); + if (target_byte_order == eByteOrderLittle) + raw_value = ((reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0)) << 32) | raw_value; + else + raw_value = (raw_value << 32) | reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0); + value.GetScalar() = *((double *)(&raw_value)); break; - } } } + else { - // not handled yet - return return_valobj_sp; + const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0); + RegisterValue f0_value; + DataExtractor f0_data; + reg_ctx->ReadRegister (f0_info, f0_value); + f0_value.GetData(f0_data); + lldb::offset_t offset = 0; + + if (count == 1 && !is_complex) + { + switch (bit_width) + { + default: + return return_valobj_sp; + case 64: + { + static_assert(sizeof(double) == sizeof(uint64_t), ""); + const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); + RegisterValue f1_value; + DataExtractor f1_data; + reg_ctx->ReadRegister (f1_info, f1_value); + DataExtractor *copy_from_extractor = nullptr; + DataBufferSP data_sp (new DataBufferHeap(8, 0)); + DataExtractor return_ext (data_sp, + target_byte_order, + target->GetArchitecture().GetAddressByteSize()); + + if (target_byte_order == eByteOrderLittle) + { + copy_from_extractor = &f0_data; + copy_from_extractor->CopyByteOrderedData (offset, + 4, + data_sp->GetBytes(), + 4, + target_byte_order); + f1_value.GetData(f1_data); + copy_from_extractor = &f1_data; + copy_from_extractor->CopyByteOrderedData (offset, + 4, + data_sp->GetBytes() + 4, + 4, + target_byte_order); + } + else + { + copy_from_extractor = &f0_data; + copy_from_extractor->CopyByteOrderedData (offset, + 4, + data_sp->GetBytes() + 4, + 4, + target_byte_order); + f1_value.GetData(f1_data); + copy_from_extractor = &f1_data; + copy_from_extractor->CopyByteOrderedData (offset, + 4, + data_sp->GetBytes(), + 4, + target_byte_order); + } + value.GetScalar() = (double) return_ext.GetDouble(&offset); + break; + } + case 32: + { + static_assert(sizeof(float) == sizeof(uint32_t), ""); + value.GetScalar() = (float) f0_data.GetFloat(&offset); + break; + } + } + } + else + { + // not handled yet + return return_valobj_sp; + } } } else @@ -558,6 +635,12 @@ ABISysV_mips::RegisterIsVolatile (const RegisterInfo *reg_info) return !RegisterIsCalleeSaved (reg_info); } +bool +ABISysV_mips::IsSoftFloat(uint32_t fp_flags) const +{ + return (fp_flags == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT); +} + bool ABISysV_mips::RegisterIsCalleeSaved (const RegisterInfo *reg_info) { @@ -623,6 +706,7 @@ ABISysV_mips::GetPluginNameStatic() //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + lldb_private::ConstString ABISysV_mips::GetPluginName() { diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.h b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h index 709c3bfe3adf..388009d0fa00 100644 --- a/source/Plugins/ABI/SysV-mips/ABISysV_mips.h +++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h @@ -53,6 +53,9 @@ public: bool RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; + bool + IsSoftFloat(uint32_t fp_flag) const; + bool CallFrameAddressIsValid(lldb::addr_t cfa) override { diff --git a/source/Plugins/ABI/SysV-mips/Makefile b/source/Plugins/ABI/SysV-mips/Makefile deleted file mode 100644 index c61130628433..000000000000 --- a/source/Plugins/ABI/SysV-mips/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ABI/SysV-mips/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginABISysV_mips -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp index 8226ef15f494..f74871544b69 100644 --- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp +++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp @@ -1,4 +1,4 @@ -//===-- ABISysV_mips64.cpp ----------------------------------------*- C++ -*-===// +//===-- ABISysV_mips64.cpp --------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -9,6 +9,13 @@ #include "ABISysV_mips64.h" +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" + +// Project includes #include "lldb/Core/ConstString.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Error.h" @@ -27,9 +34,6 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Thread.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/Triple.h" - using namespace lldb; using namespace lldb_private; @@ -80,44 +84,44 @@ g_register_infos_mips64[] = { // 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}, + { "r0" , "zero", 8, 0, eEncodingUint, eFormatHex, { dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r1" , "AT", 8, 0, eEncodingUint, eFormatHex, { dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r2" , "v0", 8, 0, eEncodingUint, eFormatHex, { dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r3" , "v1", 8, 0, eEncodingUint, eFormatHex, { dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r4" , "arg1", 8, 0, eEncodingUint, eFormatHex, { dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r5" , "arg2", 8, 0, eEncodingUint, eFormatHex, { dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r6" , "arg3", 8, 0, eEncodingUint, eFormatHex, { dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r7" , "arg4", 8, 0, eEncodingUint, eFormatHex, { dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r8" , "arg5", 8, 0, eEncodingUint, eFormatHex, { dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r9" , "arg6", 8, 0, eEncodingUint, eFormatHex, { dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r10" , "arg7", 8, 0, eEncodingUint, eFormatHex, { dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r11" , "arg8", 8, 0, eEncodingUint, eFormatHex, { dwarf_r11, dwarf_r11, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r12" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r13" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r14" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r15" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r16" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r17" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r18" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r19" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r20" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r21" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r22" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r23" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r24" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r25" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r26" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r27" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r28" , "gp", 8, 0, eEncodingUint, eFormatHex, { dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r29" , "sp", 8, 0, eEncodingUint, eFormatHex, { dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r30" , "fp", 8, 0, eEncodingUint, eFormatHex, { dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r31" , "ra", 8, 0, eEncodingUint, eFormatHex, { dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "sr" , nullptr,4, 0, eEncodingUint, eFormatHex, { dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "lo" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "hi" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "bad" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "cause" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "pc" , nullptr,8, 0, eEncodingUint, eFormatHex, { dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos_mips64); @@ -138,6 +142,7 @@ ABISysV_mips64::GetRedZoneSize () const //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + ABISP ABISysV_mips64::CreateInstance (const ArchSpec &arch) { @@ -181,7 +186,7 @@ ABISysV_mips64::PrepareTrivialCall (Thread &thread, if (!reg_ctx) return false; - const RegisterInfo *reg_info = NULL; + const RegisterInfo *reg_info = nullptr; if (args.size() > 8) // TODO handle more than 8 arguments return false; @@ -289,7 +294,7 @@ ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb return error; } - const uint32_t type_flags = compiler_type.GetTypeInfo (NULL); + const uint32_t type_flags = compiler_type.GetTypeInfo(nullptr); if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) @@ -342,7 +347,6 @@ ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb return error; } - ValueObjectSP ABISysV_mips64::GetReturnValueObjectSimple (Thread &thread, CompilerType &return_compiler_type) const { @@ -358,7 +362,7 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c Error error; ExecutionContext exe_ctx (thread.shared_from_this()); - if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL) + if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr) return return_valobj_sp; value.SetCompilerType(return_compiler_type); @@ -368,9 +372,11 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c return return_valobj_sp; Target *target = exe_ctx.GetTargetPtr(); - ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder(); + const ArchSpec target_arch = target->GetArchitecture(); + ByteOrder target_byte_order = target_arch.GetByteOrder(); const size_t byte_size = return_compiler_type.GetByteSize(nullptr); - const uint32_t type_flags = return_compiler_type.GetTypeInfo (NULL); + const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr); + uint32_t fp_flag = target_arch.GetFlags () & lldb_private::ArchSpec::eMIPS_ABI_FP_mask; const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0); const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0); @@ -434,20 +440,52 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c { // Don't handle complex yet. } + else if (IsSoftFloat(fp_flag)) + { + uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0); + switch (byte_size) + { + case 4: + value.GetScalar() = *((float *)(&raw_value)); + success = true; + break; + case 8: + value.GetScalar() = *((double *)(&raw_value)); + success = true; + break; + case 16: + uint64_t result[2]; + if (target_byte_order == eByteOrderLittle) + { + result[0] = raw_value; + result[1] = reg_ctx->ReadRegisterAsUnsigned(r3_info, 0); + value.GetScalar() = *((long double *)(result)); + } + else + { + result[0] = reg_ctx->ReadRegisterAsUnsigned(r3_info, 0); + result[1] = raw_value; + value.GetScalar() = *((long double *)(result)); + } + success = true; + break; + } + + } 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; + + RegisterValue f0_value; + DataExtractor f0_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)) @@ -462,7 +500,11 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c } else if (byte_size == sizeof(long double)) { - DataExtractor *copy_from_extractor = NULL; + const RegisterInfo *f2_info = reg_ctx->GetRegisterInfoByName("f2", 0); + RegisterValue f2_value; + DataExtractor f2_data; + reg_ctx->ReadRegister (f2_info, f2_value); + DataExtractor *copy_from_extractor = nullptr; DataBufferSP data_sp (new DataBufferHeap(16, 0)); DataExtractor return_ext (data_sp, target_byte_order, @@ -470,27 +512,42 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c if (target_byte_order == eByteOrderLittle) { - f0_data.Append(f2_data); copy_from_extractor = &f0_data; + copy_from_extractor->CopyByteOrderedData (0, + 8, + data_sp->GetBytes(), + byte_size - 8, + target_byte_order); + f2_value.GetData(f2_data); + copy_from_extractor = &f2_data; + copy_from_extractor->CopyByteOrderedData (0, + 8, + data_sp->GetBytes() + 8, + byte_size - 8, + target_byte_order); } else { - f2_data.Append(f0_data); - copy_from_extractor = &f2_data; + copy_from_extractor = &f0_data; + copy_from_extractor->CopyByteOrderedData (0, + 8, + data_sp->GetBytes() + 8, + byte_size - 8, + target_byte_order); + f2_value.GetData(f2_data); + copy_from_extractor = &f2_data; + copy_from_extractor->CopyByteOrderedData (0, + 8, + data_sp->GetBytes(), + byte_size - 8, + target_byte_order); } - 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; - } } } @@ -535,7 +592,7 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c // 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); + CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(idx, name, &field_bit_offset, nullptr, nullptr); if (field_compiler_type.IsFloatingPointType (count, is_complex)) use_fp_regs = 1; @@ -559,10 +616,10 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c for (uint32_t idx = 0; idx < num_children; idx++) { - CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); + CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(idx, name, &field_bit_offset, nullptr, nullptr); const size_t field_byte_width = field_compiler_type.GetByteSize(nullptr); - DataExtractor *copy_from_extractor = NULL; + DataExtractor *copy_from_extractor = nullptr; if (idx == 0) { @@ -620,7 +677,7 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c bool is_signed; uint32_t padding; - CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); + CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(idx, name, &field_bit_offset, nullptr, nullptr); 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 @@ -629,7 +686,7 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c uint32_t field_byte_offset = field_bit_offset/8; - if (field_compiler_type.IsIntegerType (is_signed) + if (field_compiler_type.IsIntegerOrEnumerationType (is_signed) || field_compiler_type.IsPointerType () || field_compiler_type.IsFloatingPointType (count, is_complex)) { @@ -661,7 +718,7 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c 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. + // the overall size is not greater than 16 bytes. For now, return a nullptr return value object. return return_valobj_sp; } } @@ -720,10 +777,10 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c 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_valobj_sp = ValueObjectMemory::Create(&thread, + "", + Address(mem_address, nullptr), + return_compiler_type); } return return_valobj_sp; } @@ -776,6 +833,12 @@ ABISysV_mips64::RegisterIsVolatile (const RegisterInfo *reg_info) return !RegisterIsCalleeSaved (reg_info); } +bool +ABISysV_mips64::IsSoftFloat (uint32_t fp_flag) const +{ + return (fp_flag == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT); +} + bool ABISysV_mips64::RegisterIsCalleeSaved (const RegisterInfo *reg_info) { @@ -818,6 +881,7 @@ ABISysV_mips64::GetPluginNameStatic() //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + lldb_private::ConstString ABISysV_mips64::GetPluginName() { diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h index 3290331e05a0..9f1ea0922db3 100644 --- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h +++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h @@ -53,6 +53,9 @@ public: bool RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; + bool + IsSoftFloat(uint32_t fp_flag) const; + // 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 // code, we've seen that the stack pointer is often not aligned properly diff --git a/source/Plugins/ABI/SysV-mips64/Makefile b/source/Plugins/ABI/SysV-mips64/Makefile deleted file mode 100644 index b7e6dc615cb0..000000000000 --- a/source/Plugins/ABI/SysV-mips64/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ABI/SysV-mips64/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginABISysV_mips64 -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp index f0da18637ba8..20ff17d0b763 100644 --- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp +++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp @@ -1,4 +1,4 @@ -//===-- ABISysV_ppc.cpp --------------------------------------*- C++ -*-===// +//===-- ABISysV_ppc.cpp -----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -9,6 +9,13 @@ #include "ABISysV_ppc.h" +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" + +// Project includes #include "lldb/Core/ConstString.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Error.h" @@ -27,9 +34,6 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Thread.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/Triple.h" - using namespace lldb; using namespace lldb_private; @@ -111,49 +115,50 @@ enum dwarf_regnums // 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, \ - eFormatHex, { kind1, kind2, kind3, kind4}, NULL, NULL } + eFormatHex, { kind1, kind2, kind3, kind4}, nullptr, nullptr } + static const RegisterInfo g_register_infos[] = { // 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}, + DEFINE_GPR(r0, nullptr, 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, nullptr, 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, nullptr, dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r12, nullptr, dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r13, nullptr, dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r14, nullptr, dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r15, nullptr, dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r16, nullptr, dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r17, nullptr, dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r18, nullptr, dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r19, nullptr, dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r20, nullptr, dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r21, nullptr, dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r22, nullptr, dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r23, nullptr, dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r24, nullptr, dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r25, nullptr, dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r26, nullptr, dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r27, nullptr, dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r28, nullptr, dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r29, nullptr, dwarf_r29, dwarf_r29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r30, nullptr, dwarf_r30, dwarf_r30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r31, nullptr, 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), + { nullptr, nullptr, 8, 0, eEncodingUint, eFormatHex, { dwarf_cfa, dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr } }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -165,7 +170,6 @@ ABISysV_ppc::GetRegisterInfoArray (uint32_t &count) return g_register_infos; } - size_t ABISysV_ppc::GetRedZoneSize () const { @@ -175,6 +179,7 @@ ABISysV_ppc::GetRedZoneSize () const //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + ABISP ABISysV_ppc::CreateInstance (const ArchSpec &arch) { @@ -216,7 +221,7 @@ ABISysV_ppc::PrepareTrivialCall (Thread &thread, if (!reg_ctx) return false; - const RegisterInfo *reg_info = NULL; + const RegisterInfo *reg_info = nullptr; if (args.size() > 8) // TODO handle more than 8 arguments return false; @@ -398,7 +403,7 @@ ABISysV_ppc::GetArgumentValues (Thread &thread, return false; bool is_signed; - if (compiler_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerOrEnumerationType (is_signed)) { ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread), @@ -449,7 +454,7 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) + if (compiler_type.IsIntegerOrEnumerationType (is_signed) || compiler_type.IsPointerType()) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); @@ -473,7 +478,6 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec { error.SetErrorString("We don't support returning longer than 64 bit integer values at present."); } - } else if (compiler_type.IsFloatingPointType (count, is_complex)) { @@ -517,7 +521,6 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec return error; } - ValueObjectSP ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, CompilerType &return_compiler_type) const @@ -625,7 +628,6 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); - } else if (type_flags & eTypeIsPointer) { @@ -641,7 +643,6 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, const size_t byte_size = return_compiler_type.GetByteSize(nullptr); if (byte_size > 0) { - const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v2", 0); if (altivec_reg) { @@ -738,7 +739,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_comp bool is_complex; uint32_t count; - CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); + CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(idx, name, &field_bit_offset, nullptr, nullptr); const size_t field_bit_width = field_compiler_type.GetBitSize(&thread); // If there are any unaligned fields, this is stored in memory. @@ -751,11 +752,10 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_comp uint32_t field_byte_width = field_bit_width/8; uint32_t field_byte_offset = field_bit_offset/8; - - DataExtractor *copy_from_extractor = NULL; + DataExtractor *copy_from_extractor = nullptr; uint32_t copy_from_offset = 0; - if (field_compiler_type.IsIntegerType (is_signed) || field_compiler_type.IsPointerType ()) + if (field_compiler_type.IsIntegerOrEnumerationType (is_signed) || field_compiler_type.IsPointerType ()) { if (integer_bytes < 8) { @@ -772,7 +772,6 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_comp copy_from_extractor = &rdx_data; copy_from_offset = 0; integer_bytes = 8 + field_byte_width; - } } else if (integer_bytes + field_byte_width <= 16) @@ -784,7 +783,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_comp else { // The last field didn't fit. I can't see how that would happen w/o the overall size being - // greater than 16 bytes. For now, return a NULL return value object. + // greater than 16 bytes. For now, return a nullptr return value object. return return_valobj_sp; } } @@ -818,9 +817,9 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_comp CompilerType next_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx + 1, name, &next_field_bit_offset, - NULL, - NULL); - if (next_field_compiler_type.IsIntegerType (is_signed)) + nullptr, + nullptr); + if (next_field_compiler_type.IsIntegerOrEnumerationType (is_signed)) in_gpr = true; else { @@ -828,7 +827,6 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_comp in_gpr = false; } } - } else if (field_byte_offset % 4 == 0) { @@ -842,9 +840,9 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_comp CompilerType prev_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx - 1, name, &prev_field_bit_offset, - NULL, - NULL); - if (prev_field_compiler_type.IsIntegerType (is_signed)) + nullptr, + nullptr); + if (prev_field_compiler_type.IsIntegerOrEnumerationType (is_signed)) in_gpr = true; else { @@ -852,7 +850,6 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_comp in_gpr = false; } } - } else { @@ -909,7 +906,6 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_comp } } - // FIXME: This is just taking a guess, r3 may very well no longer hold the return storage location. // If we are going to do this right, when we make a new frame we should check to see if it uses a memory // return, and if we are at the first instruction and if so stash away the return location. Then we would @@ -919,10 +915,10 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_comp { unsigned r3_id = reg_ctx_sp->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB]; lldb::addr_t storage_addr = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0); - return_valobj_sp = ValueObjectMemory::Create (&thread, - "", - Address (storage_addr, NULL), - return_compiler_type); + return_valobj_sp = ValueObjectMemory::Create(&thread, + "", + Address(storage_addr, nullptr), + return_compiler_type); } } @@ -987,8 +983,6 @@ ABISysV_ppc::RegisterIsVolatile (const RegisterInfo *reg_info) return !RegisterIsCalleeSaved (reg_info); } - - // See "Register Usage" in the // "System V Application Binary Interface" // "64-bit PowerPC ELF Application Binary Interface Supplement" @@ -1034,8 +1028,6 @@ ABISysV_ppc::RegisterIsCalleeSaved (const RegisterInfo *reg_info) return false; } - - void ABISysV_ppc::Initialize() { @@ -1060,6 +1052,7 @@ ABISysV_ppc::GetPluginNameStatic() //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + lldb_private::ConstString ABISysV_ppc::GetPluginName() { @@ -1071,4 +1064,3 @@ ABISysV_ppc::GetPluginVersion() { return 1; } - diff --git a/source/Plugins/ABI/SysV-ppc/Makefile b/source/Plugins/ABI/SysV-ppc/Makefile deleted file mode 100644 index 7a6d38d68337..000000000000 --- a/source/Plugins/ABI/SysV-ppc/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ABI/SysV-hexagon/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginABISysV_ppc -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp index 96c54ce97eec..fea847dd17ee 100644 --- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp +++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp @@ -1,4 +1,4 @@ -//===-- ABISysV_ppc64.cpp --------------------------------------*- C++ -*-===// +//===-- ABISysV_ppc64.cpp ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -9,6 +9,13 @@ #include "ABISysV_ppc64.h" +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" + +// Project includes #include "lldb/Core/ConstString.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Error.h" @@ -27,9 +34,6 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Thread.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/Triple.h" - using namespace lldb; using namespace lldb_private; @@ -108,53 +112,53 @@ enum dwarf_regnums dwarf_cfa, }; - // 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, \ - eFormatHex, { kind1, kind2, kind3, kind4}, NULL, NULL } + eFormatHex, { kind1, kind2, kind3, kind4}, nullptr, nullptr } + static const RegisterInfo g_register_infos[] = { // 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}, + DEFINE_GPR(r0, nullptr, 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, nullptr, 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, nullptr, dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r12, nullptr, dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r13, nullptr, dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r14, nullptr, dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r15, nullptr, dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r16, nullptr, dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r17, nullptr, dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r18, nullptr, dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r19, nullptr, dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r20, nullptr, dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r21, nullptr, dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r22, nullptr, dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r23, nullptr, dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r24, nullptr, dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r25, nullptr, dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r26, nullptr, dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r27, nullptr, dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r28, nullptr, dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r29, nullptr, dwarf_r29, dwarf_r29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r30, nullptr, dwarf_r30, dwarf_r30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r31, nullptr, 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), + { nullptr, nullptr, 8, 0, eEncodingUint, eFormatHex, { dwarf_cfa, dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, nullptr, nullptr } }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -166,7 +170,6 @@ ABISysV_ppc64::GetRegisterInfoArray (uint32_t &count) return g_register_infos; } - size_t ABISysV_ppc64::GetRedZoneSize () const { @@ -176,6 +179,7 @@ ABISysV_ppc64::GetRedZoneSize () const //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + ABISP ABISysV_ppc64::CreateInstance (const ArchSpec &arch) { @@ -217,7 +221,7 @@ ABISysV_ppc64::PrepareTrivialCall (Thread &thread, if (!reg_ctx) return false; - const RegisterInfo *reg_info = NULL; + const RegisterInfo *reg_info = nullptr; if (args.size() > 8) // TODO handle more than 8 arguments return false; @@ -399,7 +403,7 @@ ABISysV_ppc64::GetArgumentValues (Thread &thread, return false; bool is_signed; - if (compiler_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerOrEnumerationType (is_signed)) { ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread), @@ -450,7 +454,7 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) + if (compiler_type.IsIntegerOrEnumerationType (is_signed) || compiler_type.IsPointerType()) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); @@ -474,7 +478,6 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj { error.SetErrorString("We don't support returning longer than 64 bit integer values at present."); } - } else if (compiler_type.IsFloatingPointType (count, is_complex)) { @@ -518,7 +521,6 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj return error; } - ValueObjectSP ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, CompilerType &return_compiler_type) const @@ -626,7 +628,6 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); - } else if (type_flags & eTypeIsPointer) { @@ -642,7 +643,6 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, const size_t byte_size = return_compiler_type.GetByteSize(nullptr); if (byte_size > 0) { - const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v2", 0); if (altivec_reg) { @@ -739,7 +739,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_co bool is_complex; uint32_t count; - CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); + CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(idx, name, &field_bit_offset, nullptr, nullptr); const size_t field_bit_width = field_compiler_type.GetBitSize(&thread); // If there are any unaligned fields, this is stored in memory. @@ -752,11 +752,10 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_co uint32_t field_byte_width = field_bit_width/8; uint32_t field_byte_offset = field_bit_offset/8; - - DataExtractor *copy_from_extractor = NULL; + DataExtractor *copy_from_extractor = nullptr; uint32_t copy_from_offset = 0; - if (field_compiler_type.IsIntegerType (is_signed) || field_compiler_type.IsPointerType ()) + if (field_compiler_type.IsIntegerOrEnumerationType (is_signed) || field_compiler_type.IsPointerType ()) { if (integer_bytes < 8) { @@ -785,7 +784,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_co else { // The last field didn't fit. I can't see how that would happen w/o the overall size being - // greater than 16 bytes. For now, return a NULL return value object. + // greater than 16 bytes. For now, return a nullptr return value object. return return_valobj_sp; } } @@ -819,9 +818,9 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_co CompilerType next_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx + 1, name, &next_field_bit_offset, - NULL, - NULL); - if (next_field_compiler_type.IsIntegerType (is_signed)) + nullptr, + nullptr); + if (next_field_compiler_type.IsIntegerOrEnumerationType (is_signed)) in_gpr = true; else { @@ -829,7 +828,6 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_co in_gpr = false; } } - } else if (field_byte_offset % 4 == 0) { @@ -843,9 +841,9 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_co CompilerType prev_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx - 1, name, &prev_field_bit_offset, - NULL, - NULL); - if (prev_field_compiler_type.IsIntegerType (is_signed)) + nullptr, + nullptr); + if (prev_field_compiler_type.IsIntegerOrEnumerationType (is_signed)) in_gpr = true; else { @@ -853,7 +851,6 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_co in_gpr = false; } } - } else { @@ -910,7 +907,6 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_co } } - // FIXME: This is just taking a guess, r3 may very well no longer hold the return storage location. // If we are going to do this right, when we make a new frame we should check to see if it uses a memory // return, and if we are at the first instruction and if so stash away the return location. Then we would @@ -920,10 +916,10 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_co { unsigned r3_id = reg_ctx_sp->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB]; lldb::addr_t storage_addr = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0); - return_valobj_sp = ValueObjectMemory::Create (&thread, - "", - Address (storage_addr, NULL), - return_compiler_type); + return_valobj_sp = ValueObjectMemory::Create(&thread, + "", + Address(storage_addr, nullptr), + return_compiler_type); } } @@ -989,8 +985,6 @@ ABISysV_ppc64::RegisterIsVolatile (const RegisterInfo *reg_info) return !RegisterIsCalleeSaved (reg_info); } - - // See "Register Usage" in the // "System V Application Binary Interface" // "64-bit PowerPC ELF Application Binary Interface Supplement" @@ -1039,8 +1033,6 @@ ABISysV_ppc64::RegisterIsCalleeSaved (const RegisterInfo *reg_info) return false; } - - void ABISysV_ppc64::Initialize() { @@ -1065,6 +1057,7 @@ ABISysV_ppc64::GetPluginNameStatic() //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + lldb_private::ConstString ABISysV_ppc64::GetPluginName() { @@ -1076,4 +1069,3 @@ ABISysV_ppc64::GetPluginVersion() { return 1; } - diff --git a/source/Plugins/ABI/SysV-ppc64/Makefile b/source/Plugins/ABI/SysV-ppc64/Makefile deleted file mode 100644 index 43fc41d42713..000000000000 --- a/source/Plugins/ABI/SysV-ppc64/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ABI/SysV-hexagon/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginABISysV_ppc64 -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp b/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp new file mode 100644 index 000000000000..055905523f81 --- /dev/null +++ b/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp @@ -0,0 +1,807 @@ +//===-- ABISysV_s390x.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ABISysV_s390x.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" + +// Project includes +#include "lldb/Core/ConstString.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectMemory.h" +#include "lldb/Core/ValueObjectRegister.h" +#include "lldb/Symbol/UnwindPlan.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" + +using namespace lldb; +using namespace lldb_private; + +enum dwarf_regnums +{ + // General Purpose Registers + dwarf_r0_s390x = 0, + dwarf_r1_s390x, + dwarf_r2_s390x, + dwarf_r3_s390x, + dwarf_r4_s390x, + dwarf_r5_s390x, + dwarf_r6_s390x, + dwarf_r7_s390x, + dwarf_r8_s390x, + dwarf_r9_s390x, + dwarf_r10_s390x, + dwarf_r11_s390x, + dwarf_r12_s390x, + dwarf_r13_s390x, + dwarf_r14_s390x, + dwarf_r15_s390x, + // Floating Point Registers / Vector Registers 0-15 + dwarf_f0_s390x = 16, + dwarf_f2_s390x, + dwarf_f4_s390x, + dwarf_f6_s390x, + dwarf_f1_s390x, + dwarf_f3_s390x, + dwarf_f5_s390x, + dwarf_f7_s390x, + dwarf_f8_s390x, + dwarf_f10_s390x, + dwarf_f12_s390x, + dwarf_f14_s390x, + dwarf_f9_s390x, + dwarf_f11_s390x, + dwarf_f13_s390x, + dwarf_f15_s390x, + // Access Registers + dwarf_acr0_s390x = 48, + dwarf_acr1_s390x, + dwarf_acr2_s390x, + dwarf_acr3_s390x, + dwarf_acr4_s390x, + dwarf_acr5_s390x, + dwarf_acr6_s390x, + dwarf_acr7_s390x, + dwarf_acr8_s390x, + dwarf_acr9_s390x, + dwarf_acr10_s390x, + dwarf_acr11_s390x, + dwarf_acr12_s390x, + dwarf_acr13_s390x, + dwarf_acr14_s390x, + dwarf_acr15_s390x, + // Program Status Word + dwarf_pswm_s390x = 64, + dwarf_pswa_s390x, + // Vector Registers 16-31 + dwarf_v16_s390x = 68, + dwarf_v18_s390x, + dwarf_v20_s390x, + dwarf_v22_s390x, + dwarf_v17_s390x, + dwarf_v19_s390x, + dwarf_v21_s390x, + dwarf_v23_s390x, + dwarf_v24_s390x, + dwarf_v26_s390x, + dwarf_v28_s390x, + dwarf_v30_s390x, + dwarf_v25_s390x, + dwarf_v27_s390x, + dwarf_v29_s390x, + dwarf_v31_s390x, +}; + +// RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB + +#define DEFINE_REG(name, size, alt, generic) \ + { \ + #name, alt, size, 0, eEncodingUint, eFormatHex, \ + { dwarf_##name##_s390x, dwarf_##name##_s390x, generic, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, \ + NULL, NULL, \ + } + +static RegisterInfo g_register_infos[] = +{ + DEFINE_REG(r0, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(r1, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(r2, 8, "arg1", LLDB_REGNUM_GENERIC_ARG1), + DEFINE_REG(r3, 8, "arg2", LLDB_REGNUM_GENERIC_ARG2), + DEFINE_REG(r4, 8, "arg3", LLDB_REGNUM_GENERIC_ARG3), + DEFINE_REG(r5, 8, "arg4", LLDB_REGNUM_GENERIC_ARG4), + DEFINE_REG(r6, 8, "arg5", LLDB_REGNUM_GENERIC_ARG5), + DEFINE_REG(r7, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(r8, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(r9, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(r10, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(r11, 8, "fp", LLDB_REGNUM_GENERIC_FP), + DEFINE_REG(r12, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(r13, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(r14, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(r15, 8, "sp", LLDB_REGNUM_GENERIC_SP), + DEFINE_REG(acr0, 4, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(acr1, 4, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(acr2, 4, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(acr3, 4, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(acr4, 4, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(acr5, 4, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(acr6, 4, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(acr7, 4, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(acr8, 4, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(acr9, 4, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(acr10, 4, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(acr11, 4, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(acr12, 4, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(acr13, 4, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(acr14, 4, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(acr15, 4, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(pswm, 8, "flags", LLDB_REGNUM_GENERIC_FLAGS), + DEFINE_REG(pswa, 8, "pc", LLDB_REGNUM_GENERIC_PC), + DEFINE_REG(f0, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(f1, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(f2, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(f3, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(f4, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(f5, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(f6, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(f7, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(f8, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(f9, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(f10, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(f11, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(f12, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(f13, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(f14, 8, nullptr, LLDB_INVALID_REGNUM), + DEFINE_REG(f15, 8, nullptr, LLDB_INVALID_REGNUM), +}; + +static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); +static bool g_register_info_names_constified = false; + +const lldb_private::RegisterInfo * +ABISysV_s390x::GetRegisterInfoArray(uint32_t &count) +{ + // Make the C-string names and alt_names for the register infos into const + // C-string values by having the ConstString unique the names in the global + // constant C-string pool. + if (!g_register_info_names_constified) + { + g_register_info_names_constified = true; + for (uint32_t i = 0; i < k_num_register_infos; ++i) + { + if (g_register_infos[i].name) + g_register_infos[i].name = ConstString(g_register_infos[i].name).GetCString(); + if (g_register_infos[i].alt_name) + g_register_infos[i].alt_name = ConstString(g_register_infos[i].alt_name).GetCString(); + } + } + count = k_num_register_infos; + return g_register_infos; +} + +size_t +ABISysV_s390x::GetRedZoneSize() const +{ + return 0; +} + +//------------------------------------------------------------------ +// Static Functions +//------------------------------------------------------------------ + +ABISP +ABISysV_s390x::CreateInstance(const ArchSpec &arch) +{ + static ABISP g_abi_sp; + if (arch.GetTriple().getArch() == llvm::Triple::systemz) + { + if (!g_abi_sp) + g_abi_sp.reset(new ABISysV_s390x); + return g_abi_sp; + } + return ABISP(); +} + +bool +ABISysV_s390x::PrepareTrivialCall(Thread &thread, addr_t sp, addr_t func_addr, addr_t return_addr, + llvm::ArrayRef args) const +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + { + StreamString s; + s.Printf("ABISysV_s390x::PrepareTrivialCall (tid = 0x%" PRIx64 ", sp = 0x%" PRIx64 + ", func_addr = 0x%" PRIx64 ", return_addr = 0x%" PRIx64, + thread.GetID(), (uint64_t)sp, (uint64_t)func_addr, (uint64_t)return_addr); + + for (size_t i = 0; i < args.size(); ++i) + s.Printf(", arg%" PRIu64 " = 0x%" PRIx64, static_cast(i + 1), args[i]); + s.PutCString(")"); + log->PutCString(s.GetString().c_str()); + } + + RegisterContext *reg_ctx = thread.GetRegisterContext().get(); + if (!reg_ctx) + return false; + + 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->GetRegisterInfoByName("r14", 0); + ProcessSP process_sp(thread.GetProcess()); + + // Allocate a new stack frame and space for stack arguments if necessary + + addr_t arg_pos = 0; + if (args.size() > 5) + { + sp -= 8 * (args.size() - 5); + arg_pos = sp; + } + + sp -= 160; + + // Process arguments + + for (size_t i = 0; i < args.size(); ++i) + { + if (i < 5) + { + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); + if (log) + log->Printf("About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", static_cast(i + 1), + args[i], reg_info->name); + if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i])) + return false; + } + else + { + Error error; + if (log) + log->Printf("About to write arg%" PRIu64 " (0x%" PRIx64 ") onto stack", static_cast(i + 1), + args[i]); + if (!process_sp->WritePointerToMemory(arg_pos, args[i], error)) + return false; + arg_pos += 8; + } + } + + // %r14 is set to the return address + + if (log) + log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr); + + if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr)) + return false; + + // %r15 is set to the actual stack value. + + if (log) + log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); + + if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp)) + return false; + + // %pc is set to the address of the called function. + + if (log) + log->Printf("Writing PC: 0x%" PRIx64, (uint64_t)func_addr); + + if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr)) + return false; + + return true; +} + +static bool +ReadIntegerArgument(Scalar &scalar, unsigned int bit_width, bool is_signed, Thread &thread, + uint32_t *argument_register_ids, unsigned int ¤t_argument_register, + addr_t ¤t_stack_argument) +{ + if (bit_width > 64) + return false; // Scalar can't hold large integer arguments + + if (current_argument_register < 5) + { + scalar = + thread.GetRegisterContext()->ReadRegisterAsUnsigned(argument_register_ids[current_argument_register], 0); + current_argument_register++; + if (is_signed) + scalar.SignExtend(bit_width); + } + else + { + uint32_t byte_size = (bit_width + (8 - 1)) / 8; + Error error; + if (thread.GetProcess()->ReadScalarIntegerFromMemory(current_stack_argument + 8 - byte_size, byte_size, + is_signed, scalar, error)) + { + current_stack_argument += 8; + return true; + } + return false; + } + return true; +} + +bool +ABISysV_s390x::GetArgumentValues(Thread &thread, ValueList &values) const +{ + unsigned int num_values = values.GetSize(); + unsigned int value_index; + + // Extract the register context so we can read arguments from registers + + RegisterContext *reg_ctx = thread.GetRegisterContext().get(); + + if (!reg_ctx) + return false; + + // Get the pointer to the first stack argument so we have a place to start + // when reading data + + addr_t sp = reg_ctx->GetSP(0); + + if (!sp) + return false; + + addr_t current_stack_argument = sp + 160; + + uint32_t argument_register_ids[5]; + + argument_register_ids[0] = + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1)->kinds[eRegisterKindLLDB]; + argument_register_ids[1] = + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2)->kinds[eRegisterKindLLDB]; + argument_register_ids[2] = + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG3)->kinds[eRegisterKindLLDB]; + argument_register_ids[3] = + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG4)->kinds[eRegisterKindLLDB]; + argument_register_ids[4] = + reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG5)->kinds[eRegisterKindLLDB]; + + unsigned int current_argument_register = 0; + + for (value_index = 0; value_index < num_values; ++value_index) + { + Value *value = values.GetValueAtIndex(value_index); + + if (!value) + return false; + + // We currently only support extracting values with Clang QualTypes. + // Do we care about others? + CompilerType compiler_type = value->GetCompilerType(); + if (!compiler_type) + return false; + bool is_signed; + + if (compiler_type.IsIntegerOrEnumerationType(is_signed)) + { + ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread), is_signed, thread, + argument_register_ids, current_argument_register, current_stack_argument); + } + else if (compiler_type.IsPointerType()) + { + ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread), false, thread, + argument_register_ids, current_argument_register, current_stack_argument); + } + } + + return true; +} + +Error +ABISysV_s390x::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp) +{ + Error error; + 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; + } + + Thread *thread = frame_sp->GetThread().get(); + + bool is_signed; + uint32_t count; + bool is_complex; + + RegisterContext *reg_ctx = thread->GetRegisterContext().get(); + + bool set_it_simple = false; + if (compiler_type.IsIntegerOrEnumerationType(is_signed) || compiler_type.IsPointerType()) + { + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r2", 0); + + DataExtractor data; + Error data_error; + size_t num_bytes = new_value_sp->GetData(data, data_error); + if (data_error.Fail()) + { + error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString()); + return error; + } + lldb::offset_t offset = 0; + if (num_bytes <= 8) + { + uint64_t raw_value = data.GetMaxU64(&offset, num_bytes); + + if (reg_ctx->WriteRegisterFromUnsigned(reg_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 (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 = compiler_type.GetBitSize(frame_sp.get()); + if (bit_width <= 64) + { + const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0); + RegisterValue f0_value; + DataExtractor data; + Error data_error; + size_t num_bytes = new_value_sp->GetData(data, data_error); + if (data_error.Fail()) + { + error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", + data_error.AsCString()); + return error; + } + + unsigned char buffer[8]; + ByteOrder byte_order = data.GetByteOrder(); + + data.CopyByteOrderedData(0, num_bytes, buffer, 8, byte_order); + f0_value.SetBytes(buffer, 8, byte_order); + reg_ctx->WriteRegister(f0_info, f0_value); + set_it_simple = true; + } + else + { + // FIXME - don't know how to do long doubles yet. + error.SetErrorString("We don't support returning float values > 64 bits at present"); + } + } + } + + if (!set_it_simple) + { + // Okay we've got a structure or something that doesn't fit in a simple register. + // We should figure out where it really goes, but we don't support this yet. + error.SetErrorString("We only support setting simple integer and float return types at present."); + } + + return error; +} + +ValueObjectSP +ABISysV_s390x::GetReturnValueObjectSimple(Thread &thread, CompilerType &return_compiler_type) const +{ + ValueObjectSP return_valobj_sp; + Value value; + + if (!return_compiler_type) + return return_valobj_sp; + + // value.SetContext (Value::eContextTypeClangType, return_value_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_compiler_type.GetTypeInfo(); + if (type_flags & eTypeIsScalar) + { + value.SetValueType(Value::eValueTypeScalar); + + bool success = false; + if (type_flags & eTypeIsInteger) + { + // Extract the register context so we can read arguments from registers + + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); + uint64_t raw_value = + thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0); + const bool is_signed = (type_flags & eTypeIsSigned) != 0; + switch (byte_size) + { + default: + break; + + case sizeof(uint64_t): + if (is_signed) + value.GetScalar() = (int64_t)(raw_value); + else + value.GetScalar() = (uint64_t)(raw_value); + success = true; + break; + + case sizeof(uint32_t): + if (is_signed) + value.GetScalar() = (int32_t)(raw_value & UINT32_MAX); + else + value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX); + success = true; + break; + + case sizeof(uint16_t): + if (is_signed) + value.GetScalar() = (int16_t)(raw_value & UINT16_MAX); + else + value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX); + success = true; + break; + + case sizeof(uint8_t): + if (is_signed) + value.GetScalar() = (int8_t)(raw_value & UINT8_MAX); + else + value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX); + success = true; + break; + } + } + else if (type_flags & eTypeIsFloat) + { + if (type_flags & eTypeIsComplex) + { + // Don't handle complex yet. + } + else + { + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); + if (byte_size <= sizeof(long double)) + { + const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0); + RegisterValue f0_value; + if (reg_ctx->ReadRegister(f0_info, f0_value)) + { + DataExtractor data; + if (f0_value.GetData(data)) + { + lldb::offset_t offset = 0; + if (byte_size == sizeof(float)) + { + value.GetScalar() = (float)data.GetFloat(&offset); + success = true; + } + else if (byte_size == sizeof(double)) + { + value.GetScalar() = (double)data.GetDouble(&offset); + success = true; + } + else if (byte_size == sizeof(long double)) + { + // Don't handle long double yet. + } + } + } + } + } + } + + if (success) + return_valobj_sp = + ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); + } + else if (type_flags & eTypeIsPointer) + { + unsigned r2_id = reg_ctx->GetRegisterInfoByName("r2", 0)->kinds[eRegisterKindLLDB]; + value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_id, 0); + value.SetValueType(Value::eValueTypeScalar); + return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); + } + + return return_valobj_sp; +} + +ValueObjectSP +ABISysV_s390x::GetReturnValueObjectImpl(Thread &thread, CompilerType &return_compiler_type) const +{ + ValueObjectSP return_valobj_sp; + + if (!return_compiler_type) + return return_valobj_sp; + + ExecutionContext exe_ctx(thread.shared_from_this()); + return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type); + if (return_valobj_sp) + return return_valobj_sp; + + RegisterContextSP reg_ctx_sp = thread.GetRegisterContext(); + if (!reg_ctx_sp) + return return_valobj_sp; + + if (return_compiler_type.IsAggregateType()) + { + // FIXME: This is just taking a guess, r2 may very well no longer hold the return storage location. + // If we are going to do this right, when we make a new frame we should check to see if it uses a memory + // return, and if we are at the first instruction and if so stash away the return location. Then we would + // only return the memory return value if we know it is valid. + + unsigned r2_id = reg_ctx_sp->GetRegisterInfoByName("r2", 0)->kinds[eRegisterKindLLDB]; + lldb::addr_t storage_addr = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_id, 0); + return_valobj_sp = ValueObjectMemory::Create(&thread, "", Address(storage_addr, nullptr), return_compiler_type); + } + + return return_valobj_sp; +} + +bool +ABISysV_s390x::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) +{ + unwind_plan.Clear(); + unwind_plan.SetRegisterKind(eRegisterKindDWARF); + + UnwindPlan::RowSP row(new UnwindPlan::Row); + + // Our Call Frame Address is the stack pointer value + 160 + row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r15_s390x, 160); + + // The previous PC is in r14 + row->SetRegisterLocationToRegister(dwarf_pswa_s390x, dwarf_r14_s390x, true); + + // All other registers are the same. + unwind_plan.AppendRow(row); + unwind_plan.SetSourceName("s390x at-func-entry default"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); + return true; +} + +bool +ABISysV_s390x::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) +{ + // There's really no default way to unwind on s390x. + // Trust the .eh_frame CFI, which should always be good. + return false; +} + +bool +ABISysV_s390x::GetFallbackRegisterLocation (const RegisterInfo *reg_info, + UnwindPlan::Row::RegisterLocation &unwind_regloc) +{ + // If a volatile register is being requested, we don't want to forward the next frame's register contents + // up the stack -- the register is not retrievable at this frame. + if (RegisterIsVolatile(reg_info)) + { + unwind_regloc.SetUndefined(); + return true; + } + + return false; +} + +bool +ABISysV_s390x::RegisterIsVolatile(const RegisterInfo *reg_info) +{ + return !RegisterIsCalleeSaved(reg_info); +} + +bool +ABISysV_s390x::RegisterIsCalleeSaved(const RegisterInfo *reg_info) +{ + if (reg_info) + { + // Preserved registers are : + // r6-r13, r15 + // f8-f15 + + const char *name = reg_info->name; + if (name[0] == 'r') + { + switch (name[1]) + { + case '6': // r6 + case '7': // r7 + case '8': // r8 + case '9': // r9 + return name[2] == '\0'; + + case '1': // r10, r11, r12, r13, r15 + if ((name[2] >= '0' && name[2] <= '3') || name[2] == '5') + return name[3] == '\0'; + break; + + default: + break; + } + } + if (name[0] == 'f') + { + switch (name[1]) + { + case '8': // r8 + case '9': // r9 + return name[2] == '\0'; + + case '1': // r10, r11, r12, r13, r14, r15 + if (name[2] >= '0' && name[2] <= '5') + return name[3] == '\0'; + break; + + default: + break; + } + } + + // Accept shorter-variant versions + if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp + return true; + if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp + return true; + if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0') // pc + return true; + } + return false; +} + +void +ABISysV_s390x::Initialize() +{ + PluginManager::RegisterPlugin(GetPluginNameStatic(), "System V ABI for s390x targets", CreateInstance); +} + +void +ABISysV_s390x::Terminate() +{ + PluginManager::UnregisterPlugin(CreateInstance); +} + +lldb_private::ConstString +ABISysV_s390x::GetPluginNameStatic() +{ + static ConstString g_name("sysv-s390x"); + return g_name; +} + +//------------------------------------------------------------------ +// PluginInterface protocol +//------------------------------------------------------------------ + +lldb_private::ConstString +ABISysV_s390x::GetPluginName() +{ + return GetPluginNameStatic(); +} + +uint32_t +ABISysV_s390x::GetPluginVersion() +{ + return 1; +} diff --git a/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h b/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h new file mode 100644 index 000000000000..3aba9c1917c6 --- /dev/null +++ b/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h @@ -0,0 +1,120 @@ +//===-- ABISysV_s390x.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_ABISysV_s390x_h_ +#define liblldb_ABISysV_s390x_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/Target/ABI.h" + +class ABISysV_s390x : public lldb_private::ABI +{ +public: + ~ABISysV_s390x() override = default; + + size_t + GetRedZoneSize() const override; + + bool + PrepareTrivialCall(lldb_private::Thread &thread, lldb::addr_t sp, lldb::addr_t functionAddress, + lldb::addr_t returnAddress, llvm::ArrayRef args) const override; + + bool + GetArgumentValues(lldb_private::Thread &thread, lldb_private::ValueList &values) const override; + + lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; + + lldb::ValueObjectSP + GetReturnValueObjectImpl(lldb_private::Thread &thread, lldb_private::CompilerType &type) const override; + + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; + + bool + CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; + + bool + RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; + + bool + GetFallbackRegisterLocation (const lldb_private::RegisterInfo *reg_info, + lldb_private::UnwindPlan::Row::RegisterLocation &unwind_regloc) override; + + bool + CallFrameAddressIsValid(lldb::addr_t cfa) override + { + // Make sure the stack call frame addresses are 8 byte aligned + if (cfa & (8ull - 1ull)) + return false; // Not 8 byte aligned + if (cfa == 0) + return false; // Zero is not a valid stack address + return true; + } + + bool + CodeAddressIsValid(lldb::addr_t pc) override + { + // Code addressed must be 2 byte aligned + if (pc & 1ull) + return false; + return true; + } + + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; + + //------------------------------------------------------------------ + // Static Functions + //------------------------------------------------------------------ + + static void + Initialize(); + + static void + Terminate(); + + static lldb::ABISP + CreateInstance(const lldb_private::ArchSpec &arch); + + static lldb_private::ConstString + GetPluginNameStatic(); + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + + 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_s390x() : lldb_private::ABI() + { + // Call CreateInstance instead. + } +}; + +#endif // liblldb_ABISysV_s390x_h_ diff --git a/source/Plugins/ABI/SysV-s390x/CMakeLists.txt b/source/Plugins/ABI/SysV-s390x/CMakeLists.txt new file mode 100644 index 000000000000..c3992db023e6 --- /dev/null +++ b/source/Plugins/ABI/SysV-s390x/CMakeLists.txt @@ -0,0 +1,3 @@ +add_lldb_library(lldbPluginABISysV_s390x + ABISysV_s390x.cpp + ) 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 11e383d269c3..136f46a1d259 100644 --- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp +++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp @@ -9,6 +9,13 @@ #include "ABISysV_x86_64.h" +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Triple.h" + +// Project includes #include "lldb/Core/ConstString.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Error.h" @@ -27,9 +34,6 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Thread.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/Triple.h" - using namespace lldb; using namespace lldb_private; @@ -98,79 +102,79 @@ static RegisterInfo g_register_infos[] = { // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS // ======== ======= == === ============= =================== ======================= ===================== =========================== ===================== ====================== ========== =============== - { "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} + { "rax" , nullptr, 8, 0, eEncodingUint , eFormatHex , { dwarf_rax , dwarf_rax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "rbx" , nullptr, 8, 0, eEncodingUint , eFormatHex , { dwarf_rbx , dwarf_rbx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "rcx" , "arg4", 8, 0, eEncodingUint , eFormatHex , { dwarf_rcx , dwarf_rcx , LLDB_REGNUM_GENERIC_ARG4 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "rdx" , "arg3", 8, 0, eEncodingUint , eFormatHex , { dwarf_rdx , dwarf_rdx , LLDB_REGNUM_GENERIC_ARG3 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "rsi" , "arg2", 8, 0, eEncodingUint , eFormatHex , { dwarf_rsi , dwarf_rsi , LLDB_REGNUM_GENERIC_ARG2 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "rdi" , "arg1", 8, 0, eEncodingUint , eFormatHex , { dwarf_rdi , dwarf_rdi , LLDB_REGNUM_GENERIC_ARG1 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "rbp" , "fp", 8, 0, eEncodingUint , eFormatHex , { dwarf_rbp , dwarf_rbp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "rsp" , "sp", 8, 0, eEncodingUint , eFormatHex , { dwarf_rsp , dwarf_rsp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r8" , "arg5", 8, 0, eEncodingUint , eFormatHex , { dwarf_r8 , dwarf_r8 , LLDB_REGNUM_GENERIC_ARG5 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r9" , "arg6", 8, 0, eEncodingUint , eFormatHex , { dwarf_r9 , dwarf_r9 , LLDB_REGNUM_GENERIC_ARG6 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r10" , nullptr, 8, 0, eEncodingUint , eFormatHex , { dwarf_r10 , dwarf_r10 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r11" , nullptr, 8, 0, eEncodingUint , eFormatHex , { dwarf_r11 , dwarf_r11 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r12" , nullptr, 8, 0, eEncodingUint , eFormatHex , { dwarf_r12 , dwarf_r12 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r13" , nullptr, 8, 0, eEncodingUint , eFormatHex , { dwarf_r13 , dwarf_r13 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r14" , nullptr, 8, 0, eEncodingUint , eFormatHex , { dwarf_r14 , dwarf_r14 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "r15" , nullptr, 8, 0, eEncodingUint , eFormatHex , { dwarf_r15 , dwarf_r15 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "rip" , "pc", 8, 0, eEncodingUint , eFormatHex , { dwarf_rip , dwarf_rip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "rflags", 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 }, + { "stmm0" , nullptr,10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm0 , dwarf_stmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "stmm1" , nullptr,10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm1 , dwarf_stmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "stmm2" , nullptr,10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm2 , dwarf_stmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "stmm3" , nullptr,10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm3 , dwarf_stmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "stmm4" , nullptr,10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm4 , dwarf_stmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "stmm5" , nullptr,10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm5 , dwarf_stmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "stmm6" , nullptr,10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm6 , dwarf_stmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "stmm7" , nullptr,10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm7 , dwarf_stmm7 , 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, { dwarf_xmm0 , dwarf_xmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "xmm1" , nullptr,16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm1 , dwarf_xmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "xmm2" , nullptr,16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm2 , dwarf_xmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "xmm3" , nullptr,16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm3 , dwarf_xmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "xmm4" , nullptr,16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm4 , dwarf_xmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "xmm5" , nullptr,16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm5 , dwarf_xmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "xmm6" , nullptr,16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm6 , dwarf_xmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "xmm7" , nullptr,16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm7 , dwarf_xmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "xmm8" , nullptr,16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm8 , dwarf_xmm8 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "xmm9" , nullptr,16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm9 , dwarf_xmm9 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "xmm10" , nullptr,16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm10 , dwarf_xmm10 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "xmm11" , nullptr,16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm11 , dwarf_xmm11 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "xmm12" , nullptr,16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm12 , dwarf_xmm12 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "xmm13" , nullptr,16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm13 , dwarf_xmm13 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "xmm14" , nullptr,16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm14 , dwarf_xmm14 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "xmm15" , nullptr,16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm15 , dwarf_xmm15 , 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, { dwarf_ymm0 , dwarf_ymm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "ymm1" , nullptr,32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm1 , dwarf_ymm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "ymm2" , nullptr,32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm2 , dwarf_ymm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "ymm3" , nullptr,32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm3 , dwarf_ymm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "ymm4" , nullptr,32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm4 , dwarf_ymm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "ymm5" , nullptr,32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm5 , dwarf_ymm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "ymm6" , nullptr,32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm6 , dwarf_ymm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "ymm7" , nullptr,32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm7 , dwarf_ymm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "ymm8" , nullptr,32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm8 , dwarf_ymm8 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "ymm9" , nullptr,32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm9 , dwarf_ymm9 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "ymm10" , nullptr,32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm10 , dwarf_ymm10 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "ymm11" , nullptr,32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm11 , dwarf_ymm11 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "ymm12" , nullptr,32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm12 , dwarf_ymm12 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "ymm13" , nullptr,32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm13 , dwarf_ymm13 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "ymm14" , nullptr,32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm14 , dwarf_ymm14 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr }, + { "ymm15" , nullptr,32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm15 , dwarf_ymm15 , 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); @@ -197,7 +201,6 @@ ABISysV_x86_64::GetRegisterInfoArray (uint32_t &count) return g_register_infos; } - size_t ABISysV_x86_64::GetRedZoneSize () const { @@ -207,6 +210,7 @@ ABISysV_x86_64::GetRedZoneSize () const //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + ABISP ABISysV_x86_64::CreateInstance (const ArchSpec &arch) { @@ -248,7 +252,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread, if (!reg_ctx) return false; - const RegisterInfo *reg_info = NULL; + const RegisterInfo *reg_info = nullptr; if (args.size() > 6) // TODO handle more than 6 arguments return false; @@ -428,7 +432,7 @@ ABISysV_x86_64::GetArgumentValues (Thread &thread, return false; bool is_signed; - if (compiler_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerOrEnumerationType (is_signed)) { ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread), @@ -479,7 +483,7 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) + if (compiler_type.IsIntegerOrEnumerationType (is_signed) || compiler_type.IsPointerType()) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("rax", 0); @@ -503,7 +507,6 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb { error.SetErrorString("We don't support returning longer than 64 bit integer values at present."); } - } else if (compiler_type.IsFloatingPointType (count, is_complex)) { @@ -551,7 +554,6 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb return error; } - ValueObjectSP ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, CompilerType &return_compiler_type) const @@ -663,7 +665,6 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); - } else if (type_flags & eTypeIsPointer) { @@ -823,7 +824,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c bool is_complex; uint32_t count; - CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); + CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(idx, name, &field_bit_offset, nullptr, nullptr); 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 @@ -839,12 +840,11 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c uint32_t field_byte_width = field_bit_width/8; uint32_t field_byte_offset = field_bit_offset/8; - - DataExtractor *copy_from_extractor = NULL; + DataExtractor *copy_from_extractor = nullptr; uint32_t copy_from_offset = 0; - if (field_compiler_type.IsIntegerType (is_signed) || field_compiler_type.IsPointerType ()) + if (field_compiler_type.IsIntegerOrEnumerationType (is_signed) || field_compiler_type.IsPointerType ()) { if (integer_bytes < 8) { @@ -861,7 +861,6 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c copy_from_extractor = &rdx_data; copy_from_offset = 0; integer_bytes = 8 + field_byte_width; - } } else if (integer_bytes + field_byte_width <= 16) @@ -873,7 +872,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c else { // The last field didn't fit. I can't see how that would happen w/o the overall size being - // greater than 16 bytes. For now, return a NULL return value object. + // greater than 16 bytes. For now, return a nullptr return value object. return return_valobj_sp; } } @@ -913,9 +912,9 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c CompilerType next_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx + 1, name, &next_field_bit_offset, - NULL, - NULL); - if (next_field_compiler_type.IsIntegerType (is_signed)) + nullptr, + nullptr); + if (next_field_compiler_type.IsIntegerOrEnumerationType (is_signed)) in_gpr = true; else { @@ -923,7 +922,6 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c in_gpr = false; } } - } else if (field_byte_offset % 4 == 0) { @@ -937,9 +935,9 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c CompilerType prev_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx - 1, name, &prev_field_bit_offset, - NULL, - NULL); - if (prev_field_compiler_type.IsIntegerType (is_signed)) + nullptr, + nullptr); + if (prev_field_compiler_type.IsIntegerOrEnumerationType (is_signed)) in_gpr = true; else { @@ -947,7 +945,6 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c in_gpr = false; } } - } else { @@ -1008,8 +1005,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c return_ext); } } - - + // FIXME: This is just taking a guess, rax may very well no longer hold the return storage location. // If we are going to do this right, when we make a new frame we should check to see if it uses a memory // return, and if we are at the first instruction and if so stash away the return location. Then we would @@ -1019,10 +1015,10 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_c { unsigned rax_id = reg_ctx_sp->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB]; lldb::addr_t storage_addr = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0); - return_valobj_sp = ValueObjectMemory::Create (&thread, - "", - Address (storage_addr, NULL), - return_compiler_type); + return_valobj_sp = ValueObjectMemory::Create(&thread, + "", + Address(storage_addr, nullptr), + return_compiler_type); } } @@ -1090,8 +1086,6 @@ ABISysV_x86_64::RegisterIsVolatile (const RegisterInfo *reg_info) return !RegisterIsCalleeSaved (reg_info); } - - // See "Register Usage" in the // "System V Application Binary Interface" // "AMD64 Architecture Processor Supplement" @@ -1145,7 +1139,6 @@ ABISysV_x86_64::RegisterIsCalleeSaved (const RegisterInfo *reg_info) if (name[2] == 'p') return name[3] == '\0'; break; - } } if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp @@ -1158,8 +1151,6 @@ ABISysV_x86_64::RegisterIsCalleeSaved (const RegisterInfo *reg_info) return false; } - - void ABISysV_x86_64::Initialize() { @@ -1184,6 +1175,7 @@ ABISysV_x86_64::GetPluginNameStatic() //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + lldb_private::ConstString ABISysV_x86_64::GetPluginName() { @@ -1195,4 +1187,3 @@ ABISysV_x86_64::GetPluginVersion() { return 1; } - diff --git a/source/Plugins/ABI/SysV-x86_64/Makefile b/source/Plugins/ABI/SysV-x86_64/Makefile deleted file mode 100644 index 32990a64f956..000000000000 --- a/source/Plugins/ABI/SysV-x86_64/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ABI/SysV-x86_64/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginABISysV_x86_64 -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp index 6d124b689341..4d24cf1ab6de 100644 --- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp +++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp @@ -11,20 +11,20 @@ // C++ Includes // Project includes #include "llvm-c/Disassembler.h" +#include "llvm/ADT/SmallString.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDisassembler.h" -#include "llvm/MC/MCExternalSymbolizer.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" +#include "llvm/MC/MCDisassembler/MCExternalSymbolizer.h" +#include "llvm/MC/MCDisassembler/MCRelocationInfo.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCRelocationInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" -#include "llvm/ADT/SmallString.h" // Other libraries and framework includes #include "DisassemblerLLVMC.h" @@ -53,7 +53,7 @@ public: const lldb_private::Address &address, AddressClass addr_class) : Instruction (address, addr_class), - m_disasm_sp (disasm.shared_from_this()), + m_disasm_wp (std::static_pointer_cast(disasm.shared_from_this())), m_does_branch (eLazyBoolCalculate), m_has_delay_slot (eLazyBoolCalculate), m_is_valid (false), @@ -68,34 +68,38 @@ public: { if (m_does_branch == eLazyBoolCalculate) { - GetDisassemblerLLVMC().Lock(this, NULL); - DataExtractor data; - if (m_opcode.GetData(data)) + std::shared_ptr disasm_sp(GetDisassembler()); + if (disasm_sp) { - 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); - // Be conservative, if we didn't understand the instruction, say it might branch... - if (inst_size == 0) - m_does_branch = eLazyBoolYes; - else + disasm_sp->Lock(this, NULL); + DataExtractor data; + if (m_opcode.GetData(data)) { - const bool can_branch = mc_disasm_ptr->CanBranch(inst); - if (can_branch) + 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); + // Be conservative, if we didn't understand the instruction, say it might branch... + if (inst_size == 0) m_does_branch = eLazyBoolYes; else - m_does_branch = eLazyBoolNo; + { + const bool can_branch = mc_disasm_ptr->CanBranch(inst); + if (can_branch) + m_does_branch = eLazyBoolYes; + else + m_does_branch = eLazyBoolNo; + } } + disasm_sp->Unlock(); } - GetDisassemblerLLVMC().Unlock(); } return m_does_branch == eLazyBoolYes; } @@ -105,34 +109,38 @@ public: { if (m_has_delay_slot == eLazyBoolCalculate) { - GetDisassemblerLLVMC().Lock(this, NULL); - DataExtractor data; - if (m_opcode.GetData(data)) + std::shared_ptr disasm_sp(GetDisassembler()); + if (disasm_sp) { - 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 + disasm_sp->Lock(this, NULL); + DataExtractor data; + if (m_opcode.GetData(data)) { - const bool has_delay_slot = mc_disasm_ptr->HasDelaySlot(inst); - if (has_delay_slot) - m_has_delay_slot = eLazyBoolYes; - else + 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; + } } + disasm_sp->Unlock(); } - GetDisassemblerLLVMC().Unlock(); } return m_has_delay_slot == eLazyBoolYes; } @@ -141,18 +149,22 @@ public: GetDisasmToUse (bool &is_alternate_isa) { is_alternate_isa = false; - DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC(); - if (llvm_disasm.m_alternate_disasm_ap.get() != NULL) + std::shared_ptr disasm_sp(GetDisassembler()); + if (disasm_sp) { - const AddressClass address_class = GetAddressClass (); - - if (address_class == eAddressClassCodeAlternateISA) + if (disasm_sp->m_alternate_disasm_ap.get() != NULL) { - is_alternate_isa = true; - return llvm_disasm.m_alternate_disasm_ap.get(); + const AddressClass address_class = GetAddressClass (); + + if (address_class == eAddressClassCodeAlternateISA) + { + is_alternate_isa = true; + return disasm_sp->m_alternate_disasm_ap.get(); + } } + return disasm_sp->m_disasm_ap.get(); } - return llvm_disasm.m_disasm_ap.get(); + return nullptr; } size_t @@ -163,101 +175,105 @@ public: // All we have to do is read the opcode which can be easy for some // architectures bool got_op = false; - DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC(); - const ArchSpec &arch = llvm_disasm.GetArchitecture(); - const lldb::ByteOrder byte_order = data.GetByteOrder(); - - const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize(); - const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize(); - if (min_op_byte_size == max_op_byte_size) + std::shared_ptr disasm_sp(GetDisassembler()); + if (disasm_sp) { - // Fixed size instructions, just read that amount of data. - if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size)) - return false; + const ArchSpec &arch = disasm_sp->GetArchitecture(); + const lldb::ByteOrder byte_order = data.GetByteOrder(); - switch (min_op_byte_size) + const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize(); + const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize(); + if (min_op_byte_size == max_op_byte_size) { - case 1: - m_opcode.SetOpcode8 (data.GetU8 (&data_offset), byte_order); - got_op = true; - break; - - case 2: - m_opcode.SetOpcode16 (data.GetU16 (&data_offset), byte_order); - got_op = true; - break; - - case 4: - m_opcode.SetOpcode32 (data.GetU32 (&data_offset), byte_order); - got_op = true; - break; - - case 8: - m_opcode.SetOpcode64 (data.GetU64 (&data_offset), byte_order); - got_op = true; - break; - - default: - m_opcode.SetOpcodeBytes(data.PeekData(data_offset, min_op_byte_size), min_op_byte_size); - got_op = true; - break; - } - } - if (!got_op) - { - bool is_alternate_isa = false; - DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa); + // Fixed size instructions, just read that amount of data. + if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size)) + return false; + + switch (min_op_byte_size) + { + case 1: + m_opcode.SetOpcode8 (data.GetU8 (&data_offset), byte_order); + got_op = true; + break; + + case 2: + m_opcode.SetOpcode16 (data.GetU16 (&data_offset), byte_order); + got_op = true; + break; + + case 4: + m_opcode.SetOpcode32 (data.GetU32 (&data_offset), byte_order); + got_op = true; + break; + + case 8: + m_opcode.SetOpcode64 (data.GetU64 (&data_offset), byte_order); + got_op = true; + break; - const llvm::Triple::ArchType machine = arch.GetMachine(); - if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb) + default: + m_opcode.SetOpcodeBytes(data.PeekData(data_offset, min_op_byte_size), min_op_byte_size); + got_op = true; + break; + } + } + if (!got_op) { - if (machine == llvm::Triple::thumb || is_alternate_isa) + bool is_alternate_isa = false; + DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa); + + const llvm::Triple::ArchType machine = arch.GetMachine(); + if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb) { - uint32_t thumb_opcode = data.GetU16(&data_offset); - if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0)) + if (machine == llvm::Triple::thumb || is_alternate_isa) { - m_opcode.SetOpcode16 (thumb_opcode, byte_order); - m_is_valid = true; + uint32_t thumb_opcode = data.GetU16(&data_offset); + if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0)) + { + m_opcode.SetOpcode16 (thumb_opcode, byte_order); + m_is_valid = true; + } + else + { + thumb_opcode <<= 16; + thumb_opcode |= data.GetU16(&data_offset); + m_opcode.SetOpcode16_2 (thumb_opcode, byte_order); + m_is_valid = true; + } } else { - thumb_opcode <<= 16; - thumb_opcode |= data.GetU16(&data_offset); - m_opcode.SetOpcode16_2 (thumb_opcode, byte_order); + m_opcode.SetOpcode32 (data.GetU32(&data_offset), byte_order); m_is_valid = true; } } else { - m_opcode.SetOpcode32 (data.GetU32(&data_offset), byte_order); - m_is_valid = true; - } - } - else - { - // The opcode isn't evenly sized, so we need to actually use the llvm - // disassembler to parse it and get the size. - uint8_t *opcode_data = const_cast(data.PeekData (data_offset, 1)); - const size_t opcode_data_len = data.BytesLeft(data_offset); - const addr_t pc = m_address.GetFileAddress(); - llvm::MCInst inst; - - llvm_disasm.Lock(this, NULL); - const size_t inst_size = mc_disasm_ptr->GetMCInst(opcode_data, - opcode_data_len, - pc, - inst); - llvm_disasm.Unlock(); - if (inst_size == 0) - m_opcode.Clear(); - else - { - m_opcode.SetOpcodeBytes(opcode_data, inst_size); - m_is_valid = true; + // The opcode isn't evenly sized, so we need to actually use the llvm + // disassembler to parse it and get the size. + uint8_t *opcode_data = const_cast(data.PeekData (data_offset, 1)); + const size_t opcode_data_len = data.BytesLeft(data_offset); + const addr_t pc = m_address.GetFileAddress(); + llvm::MCInst inst; + + disasm_sp->Lock(this, NULL); + const size_t inst_size = mc_disasm_ptr->GetMCInst(opcode_data, + opcode_data_len, + pc, + inst); + disasm_sp->Unlock(); + if (inst_size == 0) + m_opcode.Clear(); + else + { + m_opcode.SetOpcodeBytes(opcode_data, inst_size); + m_is_valid = true; + } } } + return m_opcode.GetByteSize(); } - return m_opcode.GetByteSize(); + return 0; } void @@ -283,146 +299,148 @@ public: std::string out_string; std::string comment_string; - DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC(); - - DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr; + std::shared_ptr disasm_sp(GetDisassembler()); + if (disasm_sp) + { + DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr; - if (address_class == eAddressClassCodeAlternateISA) - mc_disasm_ptr = llvm_disasm.m_alternate_disasm_ap.get(); - else - mc_disasm_ptr = llvm_disasm.m_disasm_ap.get(); + if (address_class == eAddressClassCodeAlternateISA) + mc_disasm_ptr = disasm_sp->m_alternate_disasm_ap.get(); + else + mc_disasm_ptr = disasm_sp->m_disasm_ap.get(); - lldb::addr_t pc = m_address.GetFileAddress(); - m_using_file_addr = true; + lldb::addr_t pc = m_address.GetFileAddress(); + m_using_file_addr = true; - const bool data_from_file = GetDisassemblerLLVMC().m_data_from_file; - bool use_hex_immediates = true; - Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC; + const bool data_from_file = disasm_sp->m_data_from_file; + bool use_hex_immediates = true; + Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC; - if (exe_ctx) - { - Target *target = exe_ctx->GetTargetPtr(); - if (target) + if (exe_ctx) { - use_hex_immediates = target->GetUseHexImmediates(); - hex_style = target->GetHexImmediateStyle(); - - if (!data_from_file) + Target *target = exe_ctx->GetTargetPtr(); + if (target) { - const lldb::addr_t load_addr = m_address.GetLoadAddress(target); - if (load_addr != LLDB_INVALID_ADDRESS) + use_hex_immediates = target->GetUseHexImmediates(); + hex_style = target->GetHexImmediateStyle(); + + if (!data_from_file) { - pc = load_addr; - m_using_file_addr = false; + const lldb::addr_t load_addr = m_address.GetLoadAddress(target); + if (load_addr != LLDB_INVALID_ADDRESS) + { + pc = load_addr; + m_using_file_addr = false; + } } } } - } - llvm_disasm.Lock(this, exe_ctx); + disasm_sp->Lock(this, exe_ctx); - const uint8_t *opcode_data = data.GetDataStart(); - const size_t opcode_data_len = data.GetByteSize(); - llvm::MCInst inst; - size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data, - opcode_data_len, - pc, - inst); + const uint8_t *opcode_data = data.GetDataStart(); + const size_t opcode_data_len = data.GetByteSize(); + llvm::MCInst inst; + size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data, + opcode_data_len, + pc, + inst); - if (inst_size > 0) - { - mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style); - mc_disasm_ptr->PrintMCInst(inst, out_string, comment_string); - - if (!comment_string.empty()) + if (inst_size > 0) { - AppendComment(comment_string); + mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style); + mc_disasm_ptr->PrintMCInst(inst, out_string, comment_string); + + if (!comment_string.empty()) + { + AppendComment(comment_string); + } } - } - llvm_disasm.Unlock(); + disasm_sp->Unlock(); - if (inst_size == 0) - { - m_comment.assign ("unknown opcode"); - inst_size = m_opcode.GetByteSize(); - StreamString mnemonic_strm; - lldb::offset_t offset = 0; - lldb::ByteOrder byte_order = data.GetByteOrder(); - switch (inst_size) + if (inst_size == 0) { - case 1: - { - const uint8_t uval8 = data.GetU8 (&offset); - m_opcode.SetOpcode8 (uval8, byte_order); - m_opcode_name.assign (".byte"); - mnemonic_strm.Printf("0x%2.2x", uval8); - } - break; - case 2: - { - const uint16_t uval16 = data.GetU16(&offset); - m_opcode.SetOpcode16(uval16, byte_order); - m_opcode_name.assign (".short"); - mnemonic_strm.Printf("0x%4.4x", uval16); - } - break; - case 4: - { - const uint32_t uval32 = data.GetU32(&offset); - m_opcode.SetOpcode32(uval32, byte_order); - m_opcode_name.assign (".long"); - mnemonic_strm.Printf("0x%8.8x", uval32); - } - break; - case 8: - { - const uint64_t uval64 = data.GetU64(&offset); - m_opcode.SetOpcode64(uval64, byte_order); - m_opcode_name.assign (".quad"); - mnemonic_strm.Printf("0x%16.16" PRIx64, uval64); - } - break; - default: - if (inst_size == 0) - return; - else - { - const uint8_t *bytes = data.PeekData(offset, inst_size); - if (bytes == NULL) + m_comment.assign ("unknown opcode"); + inst_size = m_opcode.GetByteSize(); + StreamString mnemonic_strm; + lldb::offset_t offset = 0; + lldb::ByteOrder byte_order = data.GetByteOrder(); + switch (inst_size) + { + case 1: + { + const uint8_t uval8 = data.GetU8 (&offset); + m_opcode.SetOpcode8 (uval8, byte_order); + m_opcode_name.assign (".byte"); + mnemonic_strm.Printf("0x%2.2x", uval8); + } + break; + case 2: + { + const uint16_t uval16 = data.GetU16(&offset); + m_opcode.SetOpcode16(uval16, byte_order); + m_opcode_name.assign (".short"); + mnemonic_strm.Printf("0x%4.4x", uval16); + } + break; + case 4: + { + const uint32_t uval32 = data.GetU32(&offset); + m_opcode.SetOpcode32(uval32, byte_order); + m_opcode_name.assign (".long"); + mnemonic_strm.Printf("0x%8.8x", uval32); + } + break; + case 8: + { + const uint64_t uval64 = data.GetU64(&offset); + m_opcode.SetOpcode64(uval64, byte_order); + m_opcode_name.assign (".quad"); + mnemonic_strm.Printf("0x%16.16" PRIx64, uval64); + } + break; + default: + if (inst_size == 0) return; - m_opcode_name.assign (".byte"); - m_opcode.SetOpcodeBytes(bytes, inst_size); - mnemonic_strm.Printf("0x%2.2x", bytes[0]); - for (uint32_t i=1; iCanBranch(inst); - if (can_branch) - m_does_branch = eLazyBoolYes; - else - m_does_branch = eLazyBoolNo; + if (m_does_branch == eLazyBoolCalculate) + { + const bool can_branch = mc_disasm_ptr->CanBranch(inst); + if (can_branch) + m_does_branch = eLazyBoolYes; + else + m_does_branch = eLazyBoolNo; + } } - } - static RegularExpression s_regex("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?"); + static RegularExpression s_regex("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?"); - RegularExpression::Match matches(3); + RegularExpression::Match matches(3); - if (s_regex.Execute(out_string.c_str(), &matches)) - { - matches.GetMatchAtIndex(out_string.c_str(), 1, m_opcode_name); - matches.GetMatchAtIndex(out_string.c_str(), 2, m_mnemonics); + if (s_regex.Execute(out_string.c_str(), &matches)) + { + matches.GetMatchAtIndex(out_string.c_str(), 1, m_opcode_name); + matches.GetMatchAtIndex(out_string.c_str(), 2, m_mnemonics); + } } } } @@ -444,14 +462,14 @@ public: return m_opcode.GetByteSize(); } - DisassemblerLLVMC & - GetDisassemblerLLVMC () + std::shared_ptr + GetDisassembler () { - return *(DisassemblerLLVMC *)m_disasm_sp.get(); + return m_disasm_wp.lock(); } protected: - DisassemblerSP m_disasm_sp; // for ownership + std::weak_ptr m_disasm_wp; LazyBool m_does_branch; LazyBool m_has_delay_slot; bool m_is_valid; @@ -633,7 +651,7 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s } else { - thumb_arch_name = "thumbv7"; + thumb_arch_name = "thumbv8.2a"; } thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name.c_str())); } @@ -643,22 +661,12 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s // 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"); + triple.setArchName("armv8.2a"); 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 ((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)) + // ARM Cortex M0-M7 devices only execute thumb instructions + if (arch.IsAlwaysThumbInstructions ()) { triple_str = thumb_arch.GetTriple().getTriple().c_str(); } diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h index 6359146d81d8..e8f09a4d3abb 100644 --- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h +++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h @@ -13,6 +13,7 @@ // C Includes // C++ Includes #include +#include #include // Other libraries and framework includes @@ -22,7 +23,6 @@ #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 @@ -147,7 +147,7 @@ protected: void Lock(InstructionLLVMC *inst, const lldb_private::ExecutionContext *exe_ctx) { - m_mutex.Lock(); + m_mutex.lock(); m_inst = inst; m_exe_ctx = exe_ctx; } @@ -156,12 +156,12 @@ protected: { m_inst = NULL; m_exe_ctx = NULL; - m_mutex.Unlock(); + m_mutex.unlock(); } const lldb_private::ExecutionContext *m_exe_ctx; InstructionLLVMC *m_inst; - lldb_private::Mutex m_mutex; + std::mutex m_mutex; bool m_data_from_file; std::unique_ptr m_disasm_ap; diff --git a/source/Plugins/Disassembler/llvm/Makefile b/source/Plugins/Disassembler/llvm/Makefile deleted file mode 100644 index a1309cdd081f..000000000000 --- a/source/Plugins/Disassembler/llvm/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Disassembler/llvm/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginDisassemblerLLVM -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp index 218b0b7a1eee..4021b44c96a9 100644 --- a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp +++ b/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp @@ -181,8 +181,8 @@ DynamicLoaderDarwinKernel::CreateInstance (Process* process, bool force) // At this point if there is an ExecutableModule, it is a kernel and the Target is some variant of an Apple system. // If the Process hasn't provided the kernel load address, we need to look around in memory to find it. - addr_t kernel_load_address = SearchForDarwinKernel (process); - if (kernel_load_address != LLDB_INVALID_ADDRESS) + const addr_t kernel_load_address = SearchForDarwinKernel (process); + if (CheckForKernelImageAtAddress (kernel_load_address, process).IsValid()) { process->SetCanRunCode(false); return new DynamicLoaderDarwinKernel (process, kernel_load_address); @@ -254,27 +254,29 @@ DynamicLoaderDarwinKernel::SearchForKernelWithDebugHints (Process *process) Error read_err; addr_t addr = LLDB_INVALID_ADDRESS; - if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 8) + addr_t kernel_addresses_64[] = { 0xffffff8000002010ULL, 0xffffff8000004010ULL, + 0xfffffff000002010ULL, 0xfffffff000004010ULL, + LLDB_INVALID_ADDRESS }; + addr_t kernel_addresses_32[] = { 0xffff0110, + LLDB_INVALID_ADDRESS }; + for (size_t i = 0; kernel_addresses_64[i] != LLDB_INVALID_ADDRESS; i++) { - addr = process->ReadUnsignedIntegerFromMemory (0xffffff8000002010ULL, 8, LLDB_INVALID_ADDRESS, read_err); - if (CheckForKernelImageAtAddress (addr, process).IsValid()) - { - return addr; - } - addr = process->ReadUnsignedIntegerFromMemory (0xffffff8000004010ULL, 8, LLDB_INVALID_ADDRESS, read_err); + addr = process->ReadUnsignedIntegerFromMemory (kernel_addresses_64[i], 8, LLDB_INVALID_ADDRESS, read_err); if (CheckForKernelImageAtAddress (addr, process).IsValid()) { return addr; } } - else + + for (size_t i = 0; kernel_addresses_32[i] != LLDB_INVALID_ADDRESS; i++) { - addr = process->ReadUnsignedIntegerFromMemory (0xffff0110, 4, LLDB_INVALID_ADDRESS, read_err); + addr = process->ReadUnsignedIntegerFromMemory (kernel_addresses_32[i], 4, LLDB_INVALID_ADDRESS, read_err); if (CheckForKernelImageAtAddress (addr, process).IsValid()) { return addr; } } + return LLDB_INVALID_ADDRESS; } @@ -301,28 +303,14 @@ DynamicLoaderDarwinKernel::SearchForKernelNearPC (Process *process) if (pc == LLDB_INVALID_ADDRESS) return LLDB_INVALID_ADDRESS; - addr_t kernel_range_low; - if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 8) - { - kernel_range_low = 1ULL << 63; - } - else - { - kernel_range_low = 1ULL << 31; - } - - // Outside the normal kernel address range, this is probably userland code running right now - if (pc < kernel_range_low) - return LLDB_INVALID_ADDRESS; - // The kernel will load at at one megabyte boundary (0x100000), or at that boundary plus - // an offset of one page (0x1000) or two, depending on the device. + // an offset of one page (0x1000) or two, or four (0x4000), depending on the device. // Round the current pc down to the nearest one megabyte boundary - the place where we will start searching. addr_t addr = pc & ~0xfffff; - int i = 0; - while (i < 32 && pc >= kernel_range_low) + // Search backwards 32 megabytes, looking for the start of the kernel at each one-megabyte boundary. + for (int i = 0; i < 32; i++, addr -= 0x100000) { if (CheckForKernelImageAtAddress (addr, process).IsValid()) return addr; @@ -332,8 +320,6 @@ DynamicLoaderDarwinKernel::SearchForKernelNearPC (Process *process) return addr + 0x2000; if (CheckForKernelImageAtAddress (addr + 0x4000, process).IsValid()) return addr + 0x4000; - i++; - addr -= 0x100000; } return LLDB_INVALID_ADDRESS; @@ -397,9 +383,13 @@ DynamicLoaderDarwinKernel::SearchForKernelViaExhaustiveSearch (Process *process) lldb_private::UUID DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress (lldb::addr_t addr, Process *process) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); if (addr == LLDB_INVALID_ADDRESS) return UUID(); + if (log) + log->Printf ("DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress: looking for kernel binary at 0x%" PRIx64, addr); + // First try a quick test -- read the first 4 bytes and see if there is a valid Mach-O magic field there // (the first field of the mach_header/mach_header_64 struct). @@ -415,19 +405,19 @@ DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress (lldb::addr_t addr, Proc // Read the mach header and see whether it looks like a kernel llvm::MachO::mach_header header; - if (process->DoReadMemory (addr, &header, sizeof(header), read_error) != sizeof(header)) + if (process->DoReadMemory (addr, &header, sizeof (header), read_error) != sizeof (header)) return UUID(); if (header.magic == llvm::MachO::MH_CIGAM || header.magic == llvm::MachO::MH_CIGAM_64) { - header.magic = llvm::ByteSwap_32(header.magic); - header.cputype = llvm::ByteSwap_32(header.cputype); - header.cpusubtype = llvm::ByteSwap_32(header.cpusubtype); - header.filetype = llvm::ByteSwap_32(header.filetype); - header.ncmds = llvm::ByteSwap_32(header.ncmds); - header.sizeofcmds = llvm::ByteSwap_32(header.sizeofcmds); - header.flags = llvm::ByteSwap_32(header.flags); + header.magic = llvm::ByteSwap_32 (header.magic); + header.cputype = llvm::ByteSwap_32 (header.cputype); + header.cpusubtype = llvm::ByteSwap_32 (header.cpusubtype); + header.filetype = llvm::ByteSwap_32 (header.filetype); + header.ncmds = llvm::ByteSwap_32 (header.ncmds); + header.sizeofcmds = llvm::ByteSwap_32 (header.sizeofcmds); + header.flags = llvm::ByteSwap_32 (header.flags); } // A kernel is an executable which does not have the dynamic link object flag set. @@ -450,6 +440,8 @@ DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress (lldb::addr_t addr, Proc { process->GetTarget().SetArchitecture (kernel_arch); } + if (log) + log->Printf ("DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress: kernel binary image found at 0x%" PRIx64, addr); return memory_module_sp->GetUUID(); } } @@ -460,16 +452,16 @@ DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress (lldb::addr_t addr, Proc //---------------------------------------------------------------------- // Constructor //---------------------------------------------------------------------- -DynamicLoaderDarwinKernel::DynamicLoaderDarwinKernel (Process* process, lldb::addr_t kernel_addr) : - DynamicLoader(process), - m_kernel_load_address (kernel_addr), - m_kernel(), - m_kext_summary_header_ptr_addr (), - m_kext_summary_header_addr (), - m_kext_summary_header (), - m_known_kexts (), - m_mutex(Mutex::eMutexTypeRecursive), - m_break_id (LLDB_INVALID_BREAK_ID) +DynamicLoaderDarwinKernel::DynamicLoaderDarwinKernel(Process *process, lldb::addr_t kernel_addr) + : DynamicLoader(process), + m_kernel_load_address(kernel_addr), + m_kernel(), + m_kext_summary_header_ptr_addr(), + m_kext_summary_header_addr(), + m_kext_summary_header(), + m_known_kexts(), + m_mutex(), + m_break_id(LLDB_INVALID_BREAK_ID) { Error error; PlatformSP platform_sp(Platform::Create(PlatformDarwinKernel::GetPluginNameStatic(), error)); @@ -478,7 +470,7 @@ DynamicLoaderDarwinKernel::DynamicLoaderDarwinKernel (Process* process, lldb::ad // shouldn't be done if kext loading is explicitly disabled. if (platform_sp.get() && GetGlobalProperties()->GetLoadKexts()) { - process->GetTarget().SetPlatform (platform_sp); + process->GetTarget().SetPlatform(platform_sp); } } @@ -529,7 +521,7 @@ DynamicLoaderDarwinKernel::DidLaunch () void DynamicLoaderDarwinKernel::Clear (bool clear_process) { - Mutex::Locker locker(m_mutex); + std::lock_guard guard(m_mutex); if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id)) m_process->ClearBreakpointSiteByID(m_break_id); @@ -1139,7 +1131,7 @@ DynamicLoaderDarwinKernel::BreakpointHit (StoppointCallbackContext *context, bool DynamicLoaderDarwinKernel::ReadKextSummaryHeader () { - Mutex::Locker locker(m_mutex); + std::lock_guard guard(m_mutex); // the all image infos is already valid for this process stop ID @@ -1224,8 +1216,8 @@ DynamicLoaderDarwinKernel::ParseKextSummaries (const Address &kext_summary_addr, Log *log(GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); if (log) log->Printf ("Kexts-changed breakpoint hit, there are %d kexts currently.\n", count); - - Mutex::Locker locker(m_mutex); + + std::lock_guard guard(m_mutex); if (!ReadKextSummaries (kext_summary_addr, count, kext_summaries)) return false; @@ -1446,8 +1438,8 @@ DynamicLoaderDarwinKernel::ReadKextSummaries (const Address &kext_summary_addr, bool DynamicLoaderDarwinKernel::ReadAllKextSummaries () { - Mutex::Locker locker(m_mutex); - + std::lock_guard guard(m_mutex); + if (ReadKextSummaryHeader ()) { if (m_kext_summary_header.entry_count > 0 && m_kext_summary_header_addr.IsValid()) @@ -1516,7 +1508,7 @@ DynamicLoaderDarwinKernel::PutToLog(Log *log) const if (log == NULL) return; - Mutex::Locker locker(m_mutex); + std::lock_guard guard(m_mutex); log->Printf("gLoadedKextSummaries = 0x%16.16" PRIx64 " { version=%u, entry_size=%u, entry_count=%u }", m_kext_summary_header_addr.GetFileAddress(), m_kext_summary_header.version, @@ -1559,6 +1551,7 @@ DynamicLoaderDarwinKernel::SetNotificationBreakpointIfNeeded () "OSKextLoadedKextSummariesUpdated", eFunctionNameTypeFull, eLanguageTypeUnknown, + 0, skip_prologue, internal_bp, hardware).get(); diff --git a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h b/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h index 7ebda48cec93..47fba086a4a9 100644 --- a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h +++ b/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h @@ -12,8 +12,9 @@ // C Includes // C++ Includes -#include +#include #include +#include // Other libraries and framework includes // Project includes @@ -21,7 +22,6 @@ #include "lldb/Host/FileSpec.h" #include "lldb/Host/TimeValue.h" #include "lldb/Core/UUID.h" -#include "lldb/Host/Mutex.h" #include "lldb/Target/Process.h" class DynamicLoaderDarwinKernel : public lldb_private::DynamicLoader @@ -52,6 +52,9 @@ public: static void DebuggerInitialize (lldb_private::Debugger &debugger); + static lldb::addr_t + SearchForDarwinKernel (lldb_private::Process *process); + //------------------------------------------------------------------ /// Called after attaching a process. /// @@ -336,9 +339,6 @@ protected: uint32_t image_infos_count, KextImageInfo::collection &image_infos); - static lldb::addr_t - SearchForDarwinKernel (lldb_private::Process *process); - static lldb::addr_t SearchForKernelAtSameLoadAddr (lldb_private::Process *process); @@ -361,7 +361,7 @@ protected: lldb_private::Address m_kext_summary_header_addr; OSKextLoadedKextSummaryHeader m_kext_summary_header; KextImageInfo::collection m_known_kexts; - mutable lldb_private::Mutex m_mutex; + mutable std::recursive_mutex m_mutex; lldb::user_id_t m_break_id; private: diff --git a/source/Plugins/DynamicLoader/Darwin-Kernel/Makefile b/source/Plugins/DynamicLoader/Darwin-Kernel/Makefile deleted file mode 100644 index d2342fd06772..000000000000 --- a/source/Plugins/DynamicLoader/Darwin-Kernel/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Disassembler/llvm/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginDynamicLoaderDarwinKernel -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp index 28493170ac36..1f77539ca8df 100644 --- a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp +++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp @@ -574,34 +574,6 @@ DynamicLoaderHexagonDYLD::LoadAllCurrentModules() m_process->GetTarget().ModulesDidLoad(module_list); } -/// 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, - bool base_addr_is_offset) -{ - Target &target = m_process->GetTarget(); - ModuleList &modules = target.GetImages(); - ModuleSP module_sp; - - ModuleSpec module_spec (file, target.GetArchitecture()); - - // check if module is currently loaded - if ((module_sp = modules.FindFirstModule (module_spec))) - { - 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, true); - } - - return module_sp; -} - /// Computes a value for m_load_offset returning the computed address on /// success and LLDB_INVALID_ADDRESS on failure. addr_t @@ -674,7 +646,8 @@ static int ReadInt(Process *process, addr_t addr) } lldb::addr_t -DynamicLoaderHexagonDYLD::GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread) +DynamicLoaderHexagonDYLD::GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread, + lldb::addr_t tls_file_addr) { auto it = m_loaded_modules.find (module); if (it == m_loaded_modules.end()) @@ -715,5 +688,8 @@ DynamicLoaderHexagonDYLD::GetThreadLocalData (const lldb::ModuleSP module, const "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 ", modid=%i, tls_block=0x%" PRIx64, mod->GetObjectName().AsCString(""), link_map, tp, modid, tls_block); - return tls_block; + if (tls_block == LLDB_INVALID_ADDRESS) + return LLDB_INVALID_ADDRESS; + else + return tls_block + tls_file_addr; } diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h index e10d4ee64209..67c32887d091 100644 --- a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h +++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h @@ -59,7 +59,7 @@ public: CanLoadImage() override; lldb::addr_t - GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread) override; + GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread, lldb::addr_t tls_file_addr) override; //------------------------------------------------------------------ // PluginInterface protocol @@ -123,14 +123,6 @@ protected: void 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, - bool base_addr_is_offset) override; - /// Callback routine invoked when we hit the breakpoint on process entry. /// /// This routine is responsible for resolving the load addresses of all diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/Makefile b/source/Plugins/DynamicLoader/Hexagon-DYLD/Makefile deleted file mode 100644 index 43334562ebb1..000000000000 --- a/source/Plugins/DynamicLoader/Hexagon-DYLD/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/DynamicLoader/Hexagon-DYLD/Makefile ----*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginDynamicLoaderHexagon -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt b/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt index 2c44877662f5..4d916b15f761 100644 --- a/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt +++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt @@ -1,3 +1,4 @@ add_lldb_library(lldbPluginDynamicLoaderMacOSXDYLD DynamicLoaderMacOSXDYLD.cpp + DynamicLoaderDarwin.cpp ) diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp new file mode 100644 index 000000000000..efca1bea4ad6 --- /dev/null +++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp @@ -0,0 +1,1143 @@ +//===-- DynamicLoaderDarwin.cpp -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Core/DataBuffer.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Section.h" +#include "lldb/Core/State.h" +#include "lldb/Expression/DiagnosticManager.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/ABI.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlanCallFunction.h" +#include "lldb/Target/ThreadPlanRunToAddress.h" + +#include "DynamicLoaderDarwin.h" + +//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN +#ifdef ENABLE_DEBUG_PRINTF +#include +#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else +#define DEBUG_PRINTF(fmt, ...) +#endif + +#ifndef __APPLE__ +#include "Utility/UuidCompatibility.h" +#else +#include +#endif + +using namespace lldb; +using namespace lldb_private; + + +//---------------------------------------------------------------------- +// Constructor +//---------------------------------------------------------------------- +DynamicLoaderDarwin::DynamicLoaderDarwin (Process* process) + : DynamicLoader(process), + m_dyld_module_wp(), + m_libpthread_module_wp(), + m_pthread_getspecific_addr(), + m_tid_to_tls_map(), + m_dyld_image_infos(), + m_dyld_image_infos_stop_id(UINT32_MAX), + m_dyld(), + m_mutex() +{ +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +DynamicLoaderDarwin::~DynamicLoaderDarwin() +{ +} + +//------------------------------------------------------------------ +/// Called after attaching a process. +/// +/// Allow DynamicLoader plug-ins to execute some code after +/// attaching to a process. +//------------------------------------------------------------------ +void +DynamicLoaderDarwin::DidAttach () +{ + PrivateInitialize(m_process); + DoInitialImageFetch (); + SetNotificationBreakpoint (); +} + +//------------------------------------------------------------------ +/// Called after attaching a process. +/// +/// Allow DynamicLoader plug-ins to execute some code after +/// attaching to a process. +//------------------------------------------------------------------ +void +DynamicLoaderDarwin::DidLaunch () +{ + PrivateInitialize(m_process); + DoInitialImageFetch (); + SetNotificationBreakpoint (); +} + + +//---------------------------------------------------------------------- +// Clear out the state of this class. +//---------------------------------------------------------------------- +void +DynamicLoaderDarwin::Clear (bool clear_process) +{ + std::lock_guard guard(m_mutex); + if (clear_process) + m_process = NULL; + m_dyld_image_infos.clear(); + m_dyld_image_infos_stop_id = UINT32_MAX; + m_dyld.Clear(false); +} + +ModuleSP +DynamicLoaderDarwin::FindTargetModuleForImageInfo (ImageInfo &image_info, bool can_create, bool *did_create_ptr) +{ + if (did_create_ptr) + *did_create_ptr = false; + + Target &target = m_process->GetTarget(); + const ModuleList &target_images = target.GetImages(); + ModuleSpec module_spec (image_info.file_spec); + module_spec.GetUUID() = image_info.uuid; + ModuleSP module_sp (target_images.FindFirstModule (module_spec)); + + if (module_sp && !module_spec.GetUUID().IsValid() && !module_sp->GetUUID().IsValid()) + { + // No UUID, we must rely upon the cached module modification + // time and the modification time of the file on disk + if (module_sp->GetModificationTime() != module_sp->GetFileSpec().GetModificationTime()) + module_sp.reset(); + } + + if (!module_sp) + { + if (can_create) + { + module_sp = target.GetSharedModule (module_spec); + if (!module_sp || module_sp->GetObjectFile() == NULL) + module_sp = m_process->ReadModuleFromMemory (image_info.file_spec, image_info.address); + + if (did_create_ptr) + *did_create_ptr = (bool) module_sp; + } + } + return module_sp; +} + +DynamicLoaderDarwin::ImageInfo * +DynamicLoaderDarwin::FindImageInfoForAddress (addr_t load_address) +{ + std::lock_guard guard(m_mutex); + const size_t image_count = m_dyld_image_infos.size(); + for (size_t i = 0; i < image_count; i++) + { + if (load_address == m_dyld_image_infos[i].address) + { + return &m_dyld_image_infos[i]; + } + } + return NULL; +} + +void +DynamicLoaderDarwin::UnloadImages (const std::vector &solib_addresses) +{ + std::lock_guard guard(m_mutex); + if (m_process->GetStopID() == m_dyld_image_infos_stop_id) + return; + + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); + Target &target = m_process->GetTarget(); + if (log) + log->Printf ("Removing %" PRId64 " modules.", (uint64_t) solib_addresses.size()); + + ModuleList unloaded_module_list; + + for (addr_t solib_addr : solib_addresses) + { + Address header; + if (header.SetLoadAddress (solib_addr, &target)) + { + if (header.GetOffset() == 0) + { + ModuleSP module_to_remove (header.GetModule()); + if (module_to_remove.get()) + { + if (log) + log->Printf ("Removing module at address 0x%" PRIx64, solib_addr); + // remove the sections from the Target + UnloadSections (module_to_remove); + // add this to the list of modules to remove + unloaded_module_list.AppendIfNeeded (module_to_remove); + // remove the entry from the m_dyld_image_infos + ImageInfo::collection::iterator pos, end = m_dyld_image_infos.end(); + for (pos = m_dyld_image_infos.begin(); pos != end; pos++) + { + if (solib_addr == (*pos).address) + { + m_dyld_image_infos.erase(pos); + break; + } + } + } + } + } + } + + if (unloaded_module_list.GetSize() > 0) + { + if (log) + { + log->PutCString("Unloaded:"); + unloaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderDarwin::UnloadModules"); + } + m_process->GetTarget().GetImages().Remove (unloaded_module_list); + m_dyld_image_infos_stop_id = m_process->GetStopID(); + } +} + +//---------------------------------------------------------------------- +// Update the load addresses for all segments in MODULE using the +// updated INFO that is passed in. +//---------------------------------------------------------------------- +bool +DynamicLoaderDarwin::UpdateImageLoadAddress (Module *module, ImageInfo& info) +{ + bool changed = false; + if (module) + { + ObjectFile *image_object_file = module->GetObjectFile(); + if (image_object_file) + { + SectionList *section_list = image_object_file->GetSectionList (); + if (section_list) + { + std::vector inaccessible_segment_indexes; + // We now know the slide amount, so go through all sections + // and update the load addresses with the correct values. + const size_t num_segments = info.segments.size(); + for (size_t i=0; iFindSectionByName(info.segments[i].name)); + + if (info.segments[i].maxprot == 0) + { + inaccessible_segment_indexes.push_back(i); + } + else + { + const addr_t new_section_load_addr = info.segments[i].vmaddr + info.slide; + static ConstString g_section_name_LINKEDIT ("__LINKEDIT"); + + if (section_sp) + { + // __LINKEDIT sections from files in the shared cache + // can overlap so check to see what the segment name is + // and pass "false" so we don't warn of overlapping + // "Section" objects, and "true" for all other sections. + const bool warn_multiple = section_sp->GetName() != g_section_name_LINKEDIT; + + changed = m_process->GetTarget().SetSectionLoadAddress (section_sp, new_section_load_addr, warn_multiple); + } + else + { + Host::SystemLog (Host::eSystemLogWarning, + "warning: unable to find and load segment named '%s' at 0x%" PRIx64 " in '%s' in macosx dynamic loader plug-in.\n", + info.segments[i].name.AsCString(""), + (uint64_t)new_section_load_addr, + image_object_file->GetFileSpec().GetPath().c_str()); + } + } + } + + // If the loaded the file (it changed) and we have segments that + // are not readable or writeable, add them to the invalid memory + // region cache for the process. This will typically only be + // the __PAGEZERO segment in the main executable. We might be able + // to apply this more generally to more sections that have no + // protections in the future, but for now we are going to just + // do __PAGEZERO. + if (changed && !inaccessible_segment_indexes.empty()) + { + for (uint32_t i=0; iFindSectionByName(info.segments[seg_idx].name)); + + if (section_sp) + { + static ConstString g_pagezero_section_name("__PAGEZERO"); + if (g_pagezero_section_name == section_sp->GetName()) + { + // __PAGEZERO never slides... + const lldb::addr_t vmaddr = info.segments[seg_idx].vmaddr; + const lldb::addr_t vmsize = info.segments[seg_idx].vmsize; + Process::LoadRange pagezero_range (vmaddr, vmsize); + m_process->AddInvalidMemoryRegion(pagezero_range); + } + } + } + } + } + } + } + // We might have an in memory image that was loaded as soon as it was created + if (info.load_stop_id == m_process->GetStopID()) + changed = true; + else if (changed) + { + // Update the stop ID when this library was updated + info.load_stop_id = m_process->GetStopID(); + } + return changed; +} + +//---------------------------------------------------------------------- +// Unload the segments in MODULE using the INFO that is passed in. +//---------------------------------------------------------------------- +bool +DynamicLoaderDarwin::UnloadModuleSections (Module *module, ImageInfo& info) +{ + bool changed = false; + if (module) + { + ObjectFile *image_object_file = module->GetObjectFile(); + if (image_object_file) + { + SectionList *section_list = image_object_file->GetSectionList (); + if (section_list) + { + const size_t num_segments = info.segments.size(); + for (size_t i=0; iFindSectionByName(info.segments[i].name)); + if (section_sp) + { + const addr_t old_section_load_addr = info.segments[i].vmaddr + info.slide; + if (m_process->GetTarget().SetSectionUnloaded (section_sp, old_section_load_addr)) + changed = true; + } + else + { + Host::SystemLog (Host::eSystemLogWarning, + "warning: unable to find and unload segment named '%s' in '%s' in macosx dynamic loader plug-in.\n", + info.segments[i].name.AsCString(""), + image_object_file->GetFileSpec().GetPath().c_str()); + } + } + } + } + } + return changed; +} + + +// Given a JSON dictionary (from debugserver, most likely) of binary images loaded in the inferior +// process, add the images to the ImageInfo collection. + +bool +DynamicLoaderDarwin::JSONImageInformationIntoImageInfo (StructuredData::ObjectSP image_details, ImageInfo::collection &image_infos) +{ + StructuredData::ObjectSP images_sp = image_details->GetAsDictionary()->GetValueForKey("images"); + if (images_sp.get() == nullptr) + return false; + + image_infos.resize (images_sp->GetAsArray()->GetSize()); + + for (size_t i = 0; i < image_infos.size(); i++) + { + StructuredData::ObjectSP image_sp = images_sp->GetAsArray()->GetItemAtIndex(i); + if (image_sp.get() == nullptr || image_sp->GetAsDictionary() == nullptr) + return false; + StructuredData::Dictionary *image = image_sp->GetAsDictionary(); + if (image->HasKey("load_address") == false + || image->HasKey("pathname") == false + || image->HasKey("mod_date") == false + || image->HasKey("mach_header") == false + || image->GetValueForKey("mach_header")->GetAsDictionary() == nullptr + || image->HasKey("segments") == false + || image->GetValueForKey("segments")->GetAsArray() == nullptr + || image->HasKey("uuid") == false ) + { + return false; + } + image_infos[i].address = image->GetValueForKey("load_address")->GetAsInteger()->GetValue(); + image_infos[i].mod_date = image->GetValueForKey("mod_date")->GetAsInteger()->GetValue(); + image_infos[i].file_spec.SetFile(image->GetValueForKey("pathname")->GetAsString()->GetValue().c_str(), false); + + StructuredData::Dictionary *mh = image->GetValueForKey("mach_header")->GetAsDictionary(); + image_infos[i].header.magic = mh->GetValueForKey("magic")->GetAsInteger()->GetValue(); + image_infos[i].header.cputype = mh->GetValueForKey("cputype")->GetAsInteger()->GetValue(); + image_infos[i].header.cpusubtype = mh->GetValueForKey("cpusubtype")->GetAsInteger()->GetValue(); + image_infos[i].header.filetype = mh->GetValueForKey("filetype")->GetAsInteger()->GetValue(); + + // Fields that aren't used by DynamicLoaderDarwin so debugserver doesn't currently send them + // in the reply. + + if (mh->HasKey("flags")) + image_infos[i].header.flags = mh->GetValueForKey("flags")->GetAsInteger()->GetValue(); + else + image_infos[i].header.flags = 0; + + if (mh->HasKey("ncmds")) + image_infos[i].header.ncmds = mh->GetValueForKey("ncmds")->GetAsInteger()->GetValue(); + else + image_infos[i].header.ncmds = 0; + + if (mh->HasKey("sizeofcmds")) + image_infos[i].header.sizeofcmds = mh->GetValueForKey("sizeofcmds")->GetAsInteger()->GetValue(); + else + image_infos[i].header.sizeofcmds = 0; + + StructuredData::Array *segments = image->GetValueForKey("segments")->GetAsArray(); + uint32_t segcount = segments->GetSize(); + for (size_t j = 0; j < segcount; j++) + { + Segment segment; + StructuredData::Dictionary *seg = segments->GetItemAtIndex(j)->GetAsDictionary(); + segment.name = ConstString(seg->GetValueForKey("name")->GetAsString()->GetValue().c_str()); + segment.vmaddr = seg->GetValueForKey("vmaddr")->GetAsInteger()->GetValue(); + segment.vmsize = seg->GetValueForKey("vmsize")->GetAsInteger()->GetValue(); + segment.fileoff = seg->GetValueForKey("fileoff")->GetAsInteger()->GetValue(); + segment.filesize = seg->GetValueForKey("filesize")->GetAsInteger()->GetValue(); + segment.maxprot = seg->GetValueForKey("maxprot")->GetAsInteger()->GetValue(); + + // Fields that aren't used by DynamicLoaderDarwin so debugserver doesn't currently send them + // in the reply. + + if (seg->HasKey("initprot")) + segment.initprot = seg->GetValueForKey("initprot")->GetAsInteger()->GetValue(); + else + segment.initprot = 0; + + if (seg->HasKey("flags")) + segment.flags = seg->GetValueForKey("flags")->GetAsInteger()->GetValue(); + else + segment.flags = 0; + + if (seg->HasKey("nsects")) + segment.nsects = seg->GetValueForKey("nsects")->GetAsInteger()->GetValue(); + else + segment.nsects = 0; + + image_infos[i].segments.push_back (segment); + } + + image_infos[i].uuid.SetFromCString (image->GetValueForKey("uuid")->GetAsString()->GetValue().c_str()); + + // All sections listed in the dyld image info structure will all + // either be fixed up already, or they will all be off by a single + // slide amount that is determined by finding the first segment + // that is at file offset zero which also has bytes (a file size + // that is greater than zero) in the object file. + + // Determine the slide amount (if any) + const size_t num_sections = image_infos[i].segments.size(); + for (size_t k = 0; k < num_sections; ++k) + { + // Iterate through the object file sections to find the + // first section that starts of file offset zero and that + // has bytes in the file... + if ((image_infos[i].segments[k].fileoff == 0 && image_infos[i].segments[k].filesize > 0) + || (image_infos[i].segments[k].name == ConstString("__TEXT"))) + { + image_infos[i].slide = image_infos[i].address - image_infos[i].segments[k].vmaddr; + // We have found the slide amount, so we can exit + // this for loop. + break; + } + } + } + + return true; +} + +void +DynamicLoaderDarwin::UpdateDYLDImageInfoFromNewImageInfos (ImageInfo::collection &image_infos) +{ + const size_t image_infos_size = image_infos.size(); + for (size_t i = 0; i < image_infos_size; i++) + { + if (image_infos[i].header.filetype == llvm::MachO::MH_DYLINKER) + { + UpdateDYLDImageInfoFromNewImageInfo (image_infos[i]); + break; // FIXME simulator debugging w/ multiple dylds + } + } +} + +void +DynamicLoaderDarwin::UpdateDYLDImageInfoFromNewImageInfo (ImageInfo &image_info) +{ + // FIXME simulator debugging w/ multiple dylds + if (image_info.header.filetype == llvm::MachO::MH_DYLINKER) + { + const bool can_create = true; + ModuleSP dyld_sp = FindTargetModuleForImageInfo (image_info, can_create, NULL); + if (dyld_sp.get()) + { + Target &target = m_process->GetTarget(); + target.GetImages().AppendIfNeeded (dyld_sp); + UpdateImageLoadAddress (dyld_sp.get(), image_info); + SetDYLDModule (dyld_sp); + } + } +} + +void +DynamicLoaderDarwin::AddExecutableModuleIfInImageInfos (ImageInfo::collection &image_infos) +{ + const size_t image_infos_size = image_infos.size(); + for (size_t i = 0; i < image_infos_size; i++) + { + if (image_infos[i].header.filetype == llvm::MachO::MH_EXECUTE) + { + Target &target = m_process->GetTarget(); + const bool can_create = true; + ModuleSP exe_module_sp (FindTargetModuleForImageInfo (image_infos[i], can_create, NULL)); + + if (exe_module_sp) + { + UpdateImageLoadAddress (exe_module_sp.get(), image_infos[i]); + + if (exe_module_sp.get() != target.GetExecutableModulePointer()) + { + // Don't load dependent images since we are in dyld where we will know + // and find out about all images that are loaded. Also when setting the + // executable module, it will clear the targets module list, and if we + // have an in memory dyld module, it will get removed from the list + // so we will need to add it back after setting the executable module, + // so we first try and see if we already have a weak pointer to the + // dyld module, make it into a shared pointer, then add the executable, + // then re-add it back to make sure it is always in the list. + + const bool get_dependent_images = false; + m_process->GetTarget().SetExecutableModule (exe_module_sp, + get_dependent_images); + + UpdateDYLDImageInfoFromNewImageInfos (image_infos); + } + } + } + } +} + +void +DynamicLoaderDarwin::SetDYLDModule (lldb::ModuleSP &dyld_module_sp) +{ + m_dyld_module_wp = dyld_module_sp; +} + +ModuleSP +DynamicLoaderDarwin::GetDYLDModule () +{ + ModuleSP dyld_sp (m_dyld_module_wp.lock()); + return dyld_sp; +} + +bool +DynamicLoaderDarwin::AddModulesUsingImageInfos (ImageInfo::collection &image_infos) +{ + std::lock_guard guard(m_mutex); + // Now add these images to the main list. + ModuleList loaded_module_list; + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); + Target &target = m_process->GetTarget(); + ModuleList& target_images = target.GetImages(); + + for (uint32_t idx = 0; idx < image_infos.size(); ++idx) + { + if (log) + { + log->Printf ("Adding new image at address=0x%16.16" PRIx64 ".", image_infos[idx].address); + image_infos[idx].PutToLog (log); + } + + m_dyld_image_infos.push_back(image_infos[idx]); + + ModuleSP image_module_sp (FindTargetModuleForImageInfo (image_infos[idx], true, NULL)); + + if (image_module_sp) + { + ObjectFile *objfile = image_module_sp->GetObjectFile (); + if (objfile) + { + SectionList *sections = objfile->GetSectionList(); + if (sections) + { + ConstString commpage_dbstr("__commpage"); + Section *commpage_section = sections->FindSectionByName(commpage_dbstr).get(); + if (commpage_section) + { + ModuleSpec module_spec (objfile->GetFileSpec(), image_infos[idx].GetArchitecture ()); + module_spec.GetObjectName() = commpage_dbstr; + ModuleSP commpage_image_module_sp(target_images.FindFirstModule (module_spec)); + if (!commpage_image_module_sp) + { + module_spec.SetObjectOffset (objfile->GetFileOffset() + commpage_section->GetFileOffset()); + module_spec.SetObjectSize (objfile->GetByteSize()); + commpage_image_module_sp = target.GetSharedModule (module_spec); + if (!commpage_image_module_sp || commpage_image_module_sp->GetObjectFile() == NULL) + { + commpage_image_module_sp = m_process->ReadModuleFromMemory (image_infos[idx].file_spec, + image_infos[idx].address); + // Always load a memory image right away in the target in case + // we end up trying to read the symbol table from memory... The + // __LINKEDIT will need to be mapped so we can figure out where + // the symbol table bits are... + bool changed = false; + UpdateImageLoadAddress (commpage_image_module_sp.get(), image_infos[idx]); + target.GetImages().Append(commpage_image_module_sp); + if (changed) + { + image_infos[idx].load_stop_id = m_process->GetStopID(); + loaded_module_list.AppendIfNeeded (commpage_image_module_sp); + } + } + } + } + } + } + + // UpdateImageLoadAddress will return true if any segments + // change load address. We need to check this so we don't + // mention that all loaded shared libraries are newly loaded + // each time we hit out dyld breakpoint since dyld will list all + // shared libraries each time. + if (UpdateImageLoadAddress (image_module_sp.get(), image_infos[idx])) + { + target_images.AppendIfNeeded(image_module_sp); + loaded_module_list.AppendIfNeeded (image_module_sp); + } + } + } + + if (loaded_module_list.GetSize() > 0) + { + if (log) + loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderDarwin::ModulesDidLoad"); + m_process->GetTarget().ModulesDidLoad (loaded_module_list); + } + return true; +} + + +//---------------------------------------------------------------------- +// On Mac OS X libobjc (the Objective-C runtime) has several critical dispatch +// functions written in hand-written assembly, and also have hand-written unwind +// information in the eh_frame section. Normally we prefer analyzing the +// assembly instructions of a currently executing frame to unwind from that frame -- +// but on hand-written functions this profiling can fail. We should use the +// eh_frame instructions for these functions all the time. +// +// As an aside, it would be better if the eh_frame entries had a flag (or were +// extensible so they could have an Apple-specific flag) which indicates that +// the instructions are asynchronous -- accurate at every instruction, instead +// of our normal default assumption that they are not. +//---------------------------------------------------------------------- + +bool +DynamicLoaderDarwin::AlwaysRelyOnEHUnwindInfo (SymbolContext &sym_ctx) +{ + ModuleSP module_sp; + if (sym_ctx.symbol) + { + module_sp = sym_ctx.symbol->GetAddressRef().GetModule(); + } + if (module_sp.get() == NULL && sym_ctx.function) + { + module_sp = sym_ctx.function->GetAddressRange().GetBaseAddress().GetModule(); + } + if (module_sp.get() == NULL) + return false; + + ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime(); + if (objc_runtime != NULL && objc_runtime->IsModuleObjCLibrary (module_sp)) + { + return true; + } + + return false; +} + + + +//---------------------------------------------------------------------- +// Dump a Segment to the file handle provided. +//---------------------------------------------------------------------- +void +DynamicLoaderDarwin::Segment::PutToLog (Log *log, lldb::addr_t slide) const +{ + if (log) + { + if (slide == 0) + log->Printf ("\t\t%16s [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")", + name.AsCString(""), + vmaddr + slide, + vmaddr + slide + vmsize); + else + log->Printf ("\t\t%16s [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ") slide = 0x%" PRIx64, + name.AsCString(""), + vmaddr + slide, + vmaddr + slide + vmsize, + slide); + } +} + +const DynamicLoaderDarwin::Segment * +DynamicLoaderDarwin::ImageInfo::FindSegment (const ConstString &name) const +{ + const size_t num_segments = segments.size(); + for (size_t i=0; iPrintf("\t modtime=0x%8.8" PRIx64 " uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s' (UNLOADED)", + mod_date, + u[ 0], u[ 1], u[ 2], u[ 3], + u[ 4], u[ 5], u[ 6], u[ 7], + u[ 8], u[ 9], u[10], u[11], + u[12], u[13], u[14], u[15], + file_spec.GetPath().c_str()); + } + else + log->Printf("\t modtime=0x%8.8" PRIx64 " path='%s' (UNLOADED)", + mod_date, + file_spec.GetPath().c_str()); + } + else + { + if (u) + { + log->Printf("\taddress=0x%16.16" PRIx64 " modtime=0x%8.8" PRIx64 " uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s'", + address, + mod_date, + u[ 0], u[ 1], u[ 2], u[ 3], + u[ 4], u[ 5], u[ 6], u[ 7], + u[ 8], u[ 9], u[10], u[11], + u[12], u[13], u[14], u[15], + file_spec.GetPath().c_str()); + } + else + { + log->Printf("\taddress=0x%16.16" PRIx64 " modtime=0x%8.8" PRIx64 " path='%s'", + address, + mod_date, + file_spec.GetPath().c_str()); + + } + for (uint32_t i=0; iGetState())); + Clear(true); + m_process = process; + m_process->GetTarget().ClearAllLoadedSections(); +} + +//---------------------------------------------------------------------- +// Member function that gets called when the process state changes. +//---------------------------------------------------------------------- +void +DynamicLoaderDarwin::PrivateProcessStateChanged (Process *process, StateType state) +{ + DEBUG_PRINTF("DynamicLoaderDarwin::%s(%s)\n", __FUNCTION__, StateAsCString(state)); + switch (state) + { + case eStateConnected: + case eStateAttaching: + case eStateLaunching: + case eStateInvalid: + case eStateUnloaded: + case eStateExited: + case eStateDetached: + Clear(false); + break; + + case eStateStopped: + // Keep trying find dyld and set our notification breakpoint each time + // we stop until we succeed + if (!DidSetNotificationBreakpoint () && m_process->IsAlive()) + { + if (NeedToDoInitialImageFetch ()) + DoInitialImageFetch (); + + SetNotificationBreakpoint (); + } + break; + + case eStateRunning: + case eStateStepping: + case eStateCrashed: + case eStateSuspended: + break; + } +} + +ThreadPlanSP +DynamicLoaderDarwin::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) +{ + ThreadPlanSP thread_plan_sp; + StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get(); + const SymbolContext ¤t_context = current_frame->GetSymbolContext(eSymbolContextSymbol); + Symbol *current_symbol = current_context.symbol; + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); + TargetSP target_sp (thread.CalculateTarget()); + + if (current_symbol != NULL) + { + std::vector
addresses; + + if (current_symbol->IsTrampoline()) + { + const ConstString &trampoline_name = current_symbol->GetMangled().GetName(current_symbol->GetLanguage(), Mangled::ePreferMangled); + + if (trampoline_name) + { + const ModuleList &images = target_sp->GetImages(); + + SymbolContextList code_symbols; + images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, code_symbols); + size_t num_code_symbols = code_symbols.GetSize(); + + if (num_code_symbols > 0) + { + for (uint32_t i = 0; i < num_code_symbols; i++) + { + SymbolContext context; + AddressRange addr_range; + if (code_symbols.GetContextAtIndex(i, context)) + { + context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range); + addresses.push_back(addr_range.GetBaseAddress()); + if (log) + { + addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(target_sp.get()); + + log->Printf ("Found a trampoline target symbol at 0x%" PRIx64 ".", load_addr); + } + } + } + } + + SymbolContextList reexported_symbols; + images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeReExported, reexported_symbols); + size_t num_reexported_symbols = reexported_symbols.GetSize(); + if (num_reexported_symbols > 0) + { + for (uint32_t i = 0; i < num_reexported_symbols; i++) + { + SymbolContext context; + if (reexported_symbols.GetContextAtIndex(i, context)) + { + if (context.symbol) + { + Symbol *actual_symbol = context.symbol->ResolveReExportedSymbol(*target_sp.get()); + if (actual_symbol) + { + const Address actual_symbol_addr = actual_symbol->GetAddress(); + if (actual_symbol_addr.IsValid()) + { + addresses.push_back(actual_symbol_addr); + if (log) + { + lldb::addr_t load_addr = actual_symbol_addr.GetLoadAddress(target_sp.get()); + log->Printf ("Found a re-exported symbol: %s at 0x%" PRIx64 ".", + actual_symbol->GetName().GetCString(), load_addr); + } + } + } + } + } + } + } + + SymbolContextList indirect_symbols; + images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeResolver, indirect_symbols); + size_t num_indirect_symbols = indirect_symbols.GetSize(); + if (num_indirect_symbols > 0) + { + for (uint32_t i = 0; i < num_indirect_symbols; i++) + { + SymbolContext context; + AddressRange addr_range; + if (indirect_symbols.GetContextAtIndex(i, context)) + { + context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range); + addresses.push_back(addr_range.GetBaseAddress()); + if (log) + { + addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(target_sp.get()); + + log->Printf ("Found an indirect target symbol at 0x%" PRIx64 ".", load_addr); + } + } + } + } + } + } + else if (current_symbol->GetType() == eSymbolTypeReExported) + { + // I am not sure we could ever end up stopped AT a re-exported symbol. But just in case: + + const Symbol *actual_symbol = current_symbol->ResolveReExportedSymbol(*(target_sp.get())); + if (actual_symbol) + { + Address target_addr(actual_symbol->GetAddress()); + if (target_addr.IsValid()) + { + if (log) + log->Printf ("Found a re-exported symbol: %s pointing to: %s at 0x%" PRIx64 ".", + current_symbol->GetName().GetCString(), + actual_symbol->GetName().GetCString(), + target_addr.GetLoadAddress(target_sp.get())); + addresses.push_back (target_addr.GetLoadAddress(target_sp.get())); + + } + } + } + + if (addresses.size() > 0) + { + // First check whether any of the addresses point to Indirect symbols, and if they do, resolve them: + std::vector load_addrs; + for (Address address : addresses) + { + Symbol *symbol = address.CalculateSymbolContextSymbol(); + if (symbol && symbol->IsIndirect()) + { + Error error; + Address symbol_address = symbol->GetAddress(); + addr_t resolved_addr = thread.GetProcess()->ResolveIndirectFunction(&symbol_address, error); + if (error.Success()) + { + load_addrs.push_back(resolved_addr); + if (log) + log->Printf("ResolveIndirectFunction found resolved target for %s at 0x%" PRIx64 ".", + symbol->GetName().GetCString(), resolved_addr); + } + } + else + { + load_addrs.push_back(address.GetLoadAddress(target_sp.get())); + } + + } + thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, load_addrs, stop_others)); + } + } + else + { + if (log) + log->Printf ("Could not find symbol for step through."); + } + + return thread_plan_sp; +} + +size_t +DynamicLoaderDarwin::FindEquivalentSymbols (lldb_private::Symbol *original_symbol, + lldb_private::ModuleList &images, + lldb_private::SymbolContextList &equivalent_symbols) +{ + const ConstString &trampoline_name = original_symbol->GetMangled().GetName(original_symbol->GetLanguage(), Mangled::ePreferMangled); + if (!trampoline_name) + return 0; + + size_t initial_size = equivalent_symbols.GetSize(); + + static const char *resolver_name_regex = "(_gc|_non_gc|\\$[A-Za-z0-9\\$]+)$"; + std::string equivalent_regex_buf("^"); + equivalent_regex_buf.append (trampoline_name.GetCString()); + equivalent_regex_buf.append (resolver_name_regex); + + RegularExpression equivalent_name_regex (equivalent_regex_buf.c_str()); + const bool append = true; + images.FindSymbolsMatchingRegExAndType (equivalent_name_regex, eSymbolTypeCode, equivalent_symbols, append); + + return equivalent_symbols.GetSize() - initial_size; +} + +lldb::ModuleSP +DynamicLoaderDarwin::GetPThreadLibraryModule() +{ + ModuleSP module_sp = m_libpthread_module_wp.lock(); + if (!module_sp) + { + SymbolContextList sc_list; + ModuleSpec module_spec; + module_spec.GetFileSpec().GetFilename().SetCString("libsystem_pthread.dylib"); + ModuleList module_list; + if (m_process->GetTarget().GetImages().FindModules(module_spec, module_list)) + { + if (module_list.GetSize() == 1) + { + module_sp = module_list.GetModuleAtIndex(0); + if (module_sp) + m_libpthread_module_wp = module_sp; + } + } + } + return module_sp; +} + +Address +DynamicLoaderDarwin::GetPthreadSetSpecificAddress() +{ + if (!m_pthread_getspecific_addr.IsValid()) + { + ModuleSP module_sp = GetPThreadLibraryModule(); + if (module_sp) + { + lldb_private::SymbolContextList sc_list; + module_sp->FindSymbolsWithNameAndType(ConstString("pthread_getspecific"), eSymbolTypeCode, sc_list); + SymbolContext sc; + if (sc_list.GetContextAtIndex(0, sc)) + { + if (sc.symbol) + m_pthread_getspecific_addr = sc.symbol->GetAddress(); + } + } + } + return m_pthread_getspecific_addr; +} + +lldb::addr_t +DynamicLoaderDarwin::GetThreadLocalData(const lldb::ModuleSP module_sp, const lldb::ThreadSP thread_sp, + lldb::addr_t tls_file_addr) +{ + if (!thread_sp || !module_sp) + return LLDB_INVALID_ADDRESS; + + std::lock_guard guard(m_mutex); + + const uint32_t addr_size = m_process->GetAddressByteSize(); + uint8_t buf[sizeof(lldb::addr_t) * 3]; + + lldb_private::Address tls_addr; + if (module_sp->ResolveFileAddress(tls_file_addr, tls_addr)) + { + Error error; + const size_t tsl_data_size = addr_size * 3; + Target &target = m_process->GetTarget(); + if (target.ReadMemory(tls_addr, false, buf, tsl_data_size, error) == tsl_data_size) + { + const ByteOrder byte_order = m_process->GetByteOrder(); + DataExtractor data(buf, sizeof(buf), byte_order, addr_size); + lldb::offset_t offset = addr_size; // Skip the first pointer + const lldb::addr_t pthread_key = data.GetAddress(&offset); + const lldb::addr_t tls_offset = data.GetAddress(&offset); + if (pthread_key != 0) + { + // First check to see if we have already figured out the location + // of TLS data for the pthread_key on a specific thread yet. If we + // have we can re-use it since its location will not change unless + // the process execs. + const tid_t tid = thread_sp->GetID(); + auto tid_pos = m_tid_to_tls_map.find(tid); + if (tid_pos != m_tid_to_tls_map.end()) + { + auto tls_pos = tid_pos->second.find(pthread_key); + if (tls_pos != tid_pos->second.end()) + { + return tls_pos->second + tls_offset; + } + } + StackFrameSP frame_sp = thread_sp->GetStackFrameAtIndex(0); + if (frame_sp) + { + ClangASTContext *clang_ast_context = target.GetScratchClangASTContext(); + + if (!clang_ast_context) + return LLDB_INVALID_ADDRESS; + + CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); + Address pthread_getspecific_addr = GetPthreadSetSpecificAddress(); + if (pthread_getspecific_addr.IsValid()) + { + EvaluateExpressionOptions options; + + lldb::ThreadPlanSP thread_plan_sp( + new ThreadPlanCallFunction(*thread_sp, pthread_getspecific_addr, clang_void_ptr_type, + llvm::ArrayRef(pthread_key), options)); + + DiagnosticManager execution_errors; + ExecutionContext exe_ctx(thread_sp); + lldb::ExpressionResults results = + m_process->RunThreadPlan(exe_ctx, thread_plan_sp, options, execution_errors); + + if (results == lldb::eExpressionCompleted) + { + lldb::ValueObjectSP result_valobj_sp = thread_plan_sp->GetReturnValueObject(); + if (result_valobj_sp) + { + const lldb::addr_t pthread_key_data = result_valobj_sp->GetValueAsUnsigned(0); + if (pthread_key_data) + { + m_tid_to_tls_map[tid].insert(std::make_pair(pthread_key, pthread_key_data)); + return pthread_key_data + tls_offset; + } + } + } + } + } + } + } + } + return LLDB_INVALID_ADDRESS; +} + diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h new file mode 100644 index 000000000000..b7dd51d288df --- /dev/null +++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h @@ -0,0 +1,293 @@ +//===-- DynamicLoaderDarwin.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_DynamicLoaderDarwin_h_ +#define liblldb_DynamicLoaderDarwin_h_ + +// C Includes +// C++ Includes +#include +#include +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/Target/DynamicLoader.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Core/StructuredData.h" +#include "lldb/Core/UUID.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Target/Process.h" +#include "lldb/Utility/SafeMachO.h" + +namespace lldb_private { + +class DynamicLoaderDarwin : public lldb_private::DynamicLoader +{ +public: + DynamicLoaderDarwin(lldb_private::Process *process); + + virtual ~DynamicLoaderDarwin() override; + + //------------------------------------------------------------------ + /// Called after attaching a process. + /// + /// Allow DynamicLoader plug-ins to execute some code after + /// attaching to a process. + //------------------------------------------------------------------ + void + DidAttach() override; + + void + DidLaunch() override; + + lldb::ThreadPlanSP + GetStepThroughTrampolinePlan(lldb_private::Thread &thread, + bool stop_others) override; + + size_t + FindEquivalentSymbols(lldb_private::Symbol *original_symbol, + lldb_private::ModuleList &module_list, + lldb_private::SymbolContextList &equivalent_symbols) override; + + lldb::addr_t + GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread, lldb::addr_t tls_file_addr) override; + + bool + AlwaysRelyOnEHUnwindInfo(lldb_private::SymbolContext &sym_ctx) override; + + virtual void + DoInitialImageFetch () = 0; + + virtual bool + NeedToDoInitialImageFetch () = 0; + +protected: + void + PrivateInitialize (lldb_private::Process *process); + + void + PrivateProcessStateChanged (lldb_private::Process *process, + lldb::StateType state); + + void + Clear (bool clear_process); + + // Clear method for classes derived from this one + virtual void + DoClear () = 0; + + void + SetDYLDModule (lldb::ModuleSP &dyld_module_sp); + + lldb::ModuleSP + GetDYLDModule (); + + class Segment + { + public: + Segment() : + name(), + vmaddr(LLDB_INVALID_ADDRESS), + vmsize(0), + fileoff(0), + filesize(0), + maxprot(0), + initprot(0), + nsects(0), + flags(0) + { + } + + lldb_private::ConstString name; + lldb::addr_t vmaddr; + lldb::addr_t vmsize; + lldb::addr_t fileoff; + lldb::addr_t filesize; + uint32_t maxprot; + uint32_t initprot; + uint32_t nsects; + uint32_t flags; + + bool + operator==(const Segment& rhs) const + { + return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize; + } + + void + PutToLog (lldb_private::Log *log, + lldb::addr_t slide) const; + + }; + + struct ImageInfo + { + lldb::addr_t address; // Address of mach header for this dylib + lldb::addr_t slide; // The amount to slide all segments by if there is a global slide. + lldb::addr_t mod_date; // Modification date for this dylib + lldb_private::FileSpec file_spec; // Resolved path for this dylib + lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros + llvm::MachO::mach_header header; // The mach header for this image + std::vector segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior) + uint32_t load_stop_id; // The process stop ID that the sections for this image were loaded + + ImageInfo() : + address(LLDB_INVALID_ADDRESS), + slide(0), + mod_date(0), + file_spec(), + uuid(), + header(), + segments(), + load_stop_id(0) + { + } + + void + Clear(bool load_cmd_data_only) + { + if (!load_cmd_data_only) + { + address = LLDB_INVALID_ADDRESS; + slide = 0; + mod_date = 0; + file_spec.Clear(); + ::memset (&header, 0, sizeof(header)); + } + uuid.Clear(); + segments.clear(); + load_stop_id = 0; + } + + bool + operator == (const ImageInfo& rhs) const + { + return address == rhs.address + && slide == rhs.slide + && mod_date == rhs.mod_date + && file_spec == rhs.file_spec + && uuid == rhs.uuid + && memcmp(&header, &rhs.header, sizeof(header)) == 0 + && segments == rhs.segments; + } + + bool + UUIDValid() const + { + return uuid.IsValid(); + } + + uint32_t + GetAddressByteSize () + { + if (header.cputype) + { + if (header.cputype & llvm::MachO::CPU_ARCH_ABI64) + return 8; + else + return 4; + } + return 0; + } + + lldb_private::ArchSpec + GetArchitecture () const + { + return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype); + } + + const Segment * + FindSegment (const lldb_private::ConstString &name) const; + + void + PutToLog (lldb_private::Log *log) const; + + typedef std::vector collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + }; + + bool + UpdateImageLoadAddress(lldb_private::Module *module, ImageInfo& info); + + bool + UnloadModuleSections (lldb_private::Module *module, ImageInfo& info); + + ImageInfo * + FindImageInfoForAddress (lldb::addr_t load_address); + + lldb::ModuleSP + FindTargetModuleForImageInfo (ImageInfo &image_info, + bool can_create, + bool *did_create_ptr); + + void + UnloadImages (const std::vector &solib_addresses); + + virtual bool + SetNotificationBreakpoint () = 0; + + virtual void + ClearNotificationBreakpoint () = 0; + + virtual bool + DidSetNotificationBreakpoint () = 0; + + typedef std::map PthreadKeyToTLSMap; + typedef std::map ThreadIDToTLSMap; + + std::recursive_mutex & + GetMutex () const + { + return m_mutex; + } + + lldb::ModuleSP + GetPThreadLibraryModule(); + + lldb_private::Address + GetPthreadSetSpecificAddress(); + + bool + JSONImageInformationIntoImageInfo (lldb_private::StructuredData::ObjectSP image_details, ImageInfo::collection &image_infos); + + // If image_infos contains / may contain dyld image, call this method + // to keep our internal record keeping of the special dyld binary up-to-date. + void + UpdateDYLDImageInfoFromNewImageInfos (ImageInfo::collection &image_infos); + + // if image_info is a dyld binary, call this method + void + UpdateDYLDImageInfoFromNewImageInfo (ImageInfo &image_info); + + // If image_infos contains / may contain executable image, call this method + // to keep our internal record keeping of the special dyld binary up-to-date. + void + AddExecutableModuleIfInImageInfos (ImageInfo::collection &image_infos); + + bool + AddModulesUsingImageInfos (ImageInfo::collection &image_infos); + + lldb::ModuleWP m_dyld_module_wp; + lldb::ModuleWP m_libpthread_module_wp; + lldb_private::Address m_pthread_getspecific_addr; + ThreadIDToTLSMap m_tid_to_tls_map; + ImageInfo::collection m_dyld_image_infos; // Current shared libraries information + uint32_t m_dyld_image_infos_stop_id; // The process stop ID that "m_dyld_image_infos" is valid for + ImageInfo m_dyld; + mutable std::recursive_mutex m_mutex; + +private: + DISALLOW_COPY_AND_ASSIGN (DynamicLoaderDarwin); +}; + +} // namespace lldb_private + +#endif // liblldb_DynamicLoaderDarwin_h_ diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp index fba11f6aea85..a8bc216fb17e 100644 --- a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp +++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp @@ -29,6 +29,7 @@ #include "lldb/Target/StackFrame.h" #include "DynamicLoaderMacOSXDYLD.h" +#include "DynamicLoaderDarwin.h" //#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN #ifdef ENABLE_DEBUG_PRINTF @@ -47,47 +48,6 @@ using namespace lldb; using namespace lldb_private; -/// FIXME - The ObjC Runtime trampoline handler doesn't really belong here. -/// I am putting it here so I can invoke it in the Trampoline code here, but -/// it should be moved to the ObjC Runtime support when it is set up. - - -DynamicLoaderMacOSXDYLD::DYLDImageInfo * -DynamicLoaderMacOSXDYLD::GetImageInfo (Module *module) -{ - const UUID &module_uuid = module->GetUUID(); - DYLDImageInfo::collection::iterator pos, end = m_dyld_image_infos.end(); - - // First try just by UUID as it is the safest. - if (module_uuid.IsValid()) - { - for (pos = m_dyld_image_infos.begin(); pos != end; ++pos) - { - if (pos->uuid == module_uuid) - return &(*pos); - } - - if (m_dyld.uuid == module_uuid) - return &m_dyld; - } - - // Next try by platform path only for things that don't have a valid UUID - // since if a file has a valid UUID in real life it should also in the - // dyld info. This is the next safest because the paths in the dyld info - // are platform paths, not local paths. For local debugging platform == local - // paths. - const FileSpec &platform_file_spec = module->GetPlatformFileSpec(); - for (pos = m_dyld_image_infos.begin(); pos != end; ++pos) - { - if (pos->file_spec == platform_file_spec && pos->uuid.IsValid() == false) - return &(*pos); - } - - if (m_dyld.file_spec == platform_file_spec && m_dyld.uuid.IsValid() == false) - return &m_dyld; - - return NULL; -} //---------------------------------------------------------------------- // Create an instance of this class. This function is filled into @@ -139,16 +99,12 @@ DynamicLoaderMacOSXDYLD::CreateInstance (Process* process, bool force) // Constructor //---------------------------------------------------------------------- DynamicLoaderMacOSXDYLD::DynamicLoaderMacOSXDYLD (Process* process) : - DynamicLoader(process), - m_dyld(), - m_dyld_module_wp(), + DynamicLoaderDarwin(process), m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS), m_dyld_all_image_infos(), m_dyld_all_image_infos_stop_id (UINT32_MAX), m_break_id(LLDB_INVALID_BREAK_ID), - m_dyld_image_infos(), - m_dyld_image_infos_stop_id (UINT32_MAX), - m_mutex(Mutex::eMutexTypeRecursive), + m_mutex(), m_process_image_addr_is_all_images_infos (false) { } @@ -158,40 +114,15 @@ DynamicLoaderMacOSXDYLD::DynamicLoaderMacOSXDYLD (Process* process) : //---------------------------------------------------------------------- DynamicLoaderMacOSXDYLD::~DynamicLoaderMacOSXDYLD() { - Clear(true); -} - -//------------------------------------------------------------------ -/// Called after attaching a process. -/// -/// Allow DynamicLoader plug-ins to execute some code after -/// attaching to a process. -//------------------------------------------------------------------ -void -DynamicLoaderMacOSXDYLD::DidAttach () -{ - PrivateInitialize(m_process); - LocateDYLD (); - SetNotificationBreakpoint (); -} - -//------------------------------------------------------------------ -/// Called after attaching a process. -/// -/// Allow DynamicLoader plug-ins to execute some code after -/// attaching to a process. -//------------------------------------------------------------------ -void -DynamicLoaderMacOSXDYLD::DidLaunch () -{ - PrivateInitialize(m_process); - LocateDYLD (); - SetNotificationBreakpoint (); + if (LLDB_BREAK_ID_IS_VALID(m_break_id)) + m_process->GetTarget().RemoveBreakpointByID (m_break_id); } bool DynamicLoaderMacOSXDYLD::ProcessDidExec () { + std::lock_guard baseclass_guard(GetMutex()); + bool did_exec = false; if (m_process) { // If we are stopped after an exec, we will have only one thread... @@ -205,76 +136,86 @@ DynamicLoaderMacOSXDYLD::ProcessDidExec () { // The image info address from the process is the 'dyld_all_image_infos' // address and it has changed. - return true; + did_exec = true; } - - if (m_process_image_addr_is_all_images_infos == false && shlib_addr == m_dyld.address) + else if (m_process_image_addr_is_all_images_infos == false && shlib_addr == m_dyld.address) { // The image info address from the process is the mach_header // address for dyld and it has changed. - return true; + did_exec = true; } - - // ASLR might be disabled and dyld could have ended up in the same - // location. We should try and detect if we are stopped at '_dyld_start' - ThreadSP thread_sp (m_process->GetThreadList().GetThreadAtIndex(0)); - if (thread_sp) + else { - lldb::StackFrameSP frame_sp (thread_sp->GetStackFrameAtIndex(0)); - if (frame_sp) + // ASLR might be disabled and dyld could have ended up in the same + // location. We should try and detect if we are stopped at '_dyld_start' + ThreadSP thread_sp(m_process->GetThreadList().GetThreadAtIndex(0)); + if (thread_sp) { - const Symbol *symbol = frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol; - if (symbol) + lldb::StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0)); + if (frame_sp) { - if (symbol->GetName() == ConstString("_dyld_start")) - return true; + const Symbol *symbol = frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol; + if (symbol) + { + if (symbol->GetName() == ConstString("_dyld_start")) + did_exec = true; + } } } } + + if (did_exec) + { + m_libpthread_module_wp.reset(); + m_pthread_getspecific_addr.Clear(); + } } } - return false; + return did_exec; } - - //---------------------------------------------------------------------- // Clear out the state of this class. //---------------------------------------------------------------------- void -DynamicLoaderMacOSXDYLD::Clear (bool clear_process) +DynamicLoaderMacOSXDYLD::DoClear () { - Mutex::Locker locker(m_mutex); + std::lock_guard guard(m_mutex); if (LLDB_BREAK_ID_IS_VALID(m_break_id)) m_process->GetTarget().RemoveBreakpointByID (m_break_id); - if (clear_process) - m_process = NULL; - m_dyld.Clear(false); m_dyld_all_image_infos_addr = LLDB_INVALID_ADDRESS; m_dyld_all_image_infos.Clear(); m_break_id = LLDB_INVALID_BREAK_ID; - m_dyld_image_infos.clear(); } //---------------------------------------------------------------------- // Check if we have found DYLD yet //---------------------------------------------------------------------- bool -DynamicLoaderMacOSXDYLD::DidSetNotificationBreakpoint() const +DynamicLoaderMacOSXDYLD::DidSetNotificationBreakpoint() { return LLDB_BREAK_ID_IS_VALID (m_break_id); } +void +DynamicLoaderMacOSXDYLD::ClearNotificationBreakpoint () +{ + if (LLDB_BREAK_ID_IS_VALID (m_break_id)) + { + m_process->GetTarget().RemoveBreakpointByID (m_break_id); + } +} + //---------------------------------------------------------------------- // Try and figure out where dyld is by first asking the Process // if it knows (which currently calls down in the lldb::Process // to get the DYLD info (available on SnowLeopard only). If that fails, // then check in the default addresses. //---------------------------------------------------------------------- -bool -DynamicLoaderMacOSXDYLD::LocateDYLD() +void +DynamicLoaderMacOSXDYLD::DoInitialImageFetch() { if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS) { @@ -299,7 +240,8 @@ DynamicLoaderMacOSXDYLD::LocateDYLD() case llvm::MachO::MH_CIGAM: case llvm::MachO::MH_CIGAM_64: m_process_image_addr_is_all_images_infos = false; - return ReadDYLDInfoFromMemoryAndSetNotificationCallback(shlib_addr); + ReadDYLDInfoFromMemoryAndSetNotificationCallback(shlib_addr); + return; default: break; @@ -316,9 +258,10 @@ DynamicLoaderMacOSXDYLD::LocateDYLD() if (ReadAllImageInfosStructure ()) { if (m_dyld_all_image_infos.dyldImageLoadAddress != LLDB_INVALID_ADDRESS) - return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos.dyldImageLoadAddress); + ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos.dyldImageLoadAddress); else - return ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos_addr & 0xfffffffffff00000ull); + ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos_addr & 0xfffffffffff00000ull); + return; } } @@ -330,53 +273,18 @@ DynamicLoaderMacOSXDYLD::LocateDYLD() const ArchSpec &exe_arch = executable->GetArchitecture(); if (exe_arch.GetAddressByteSize() == 8) { - return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x7fff5fc00000ull); + ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x7fff5fc00000ull); } else if (exe_arch.GetMachine() == llvm::Triple::arm || exe_arch.GetMachine() == llvm::Triple::thumb || exe_arch.GetMachine() == llvm::Triple::aarch64) { - return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x2fe00000); + ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x2fe00000); } else { - return ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x8fe00000); - } - } - return false; -} - -ModuleSP -DynamicLoaderMacOSXDYLD::FindTargetModuleForDYLDImageInfo (DYLDImageInfo &image_info, bool can_create, bool *did_create_ptr) -{ - if (did_create_ptr) - *did_create_ptr = false; - - Target &target = m_process->GetTarget(); - const ModuleList &target_images = target.GetImages(); - ModuleSpec module_spec (image_info.file_spec); - module_spec.GetUUID() = image_info.uuid; - ModuleSP module_sp (target_images.FindFirstModule (module_spec)); - - if (module_sp && !module_spec.GetUUID().IsValid() && !module_sp->GetUUID().IsValid()) - { - // No UUID, we must rely upon the cached module modification - // time and the modification time of the file on disk - if (module_sp->GetModificationTime() != module_sp->GetFileSpec().GetModificationTime()) - module_sp.reset(); - } - - if (!module_sp) - { - if (can_create) - { - module_sp = target.GetSharedModule (module_spec); - if (!module_sp || module_sp->GetObjectFile() == NULL) - module_sp = m_process->ReadModuleFromMemory (image_info.file_spec, image_info.address); - - if (did_create_ptr) - *did_create_ptr = (bool) module_sp; + ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x8fe00000); } } - return module_sp; + return; } //---------------------------------------------------------------------- @@ -386,6 +294,7 @@ DynamicLoaderMacOSXDYLD::FindTargetModuleForDYLDImageInfo (DYLDImageInfo &image_ bool DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::addr_t addr) { + std::lock_guard baseclass_guard(GetMutex()); DataExtractor data; // Load command data if (ReadMachHeader (addr, &m_dyld.header, &data)) { @@ -397,12 +306,11 @@ DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb:: { if (m_dyld.file_spec) { - dyld_module_sp = FindTargetModuleForDYLDImageInfo (m_dyld, true, NULL); + UpdateDYLDImageInfoFromNewImageInfo (m_dyld); - if (dyld_module_sp) - UpdateImageLoadAddress (dyld_module_sp.get(), m_dyld); } } + dyld_module_sp = GetDYLDModule(); Target &target = m_process->GetTarget(); @@ -430,7 +338,7 @@ DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb:: ModuleList modules; modules.Append(dyld_module_sp); target.ModulesDidLoad(modules); - m_dyld_module_wp = dyld_module_sp; + SetDYLDModule (dyld_module_sp); } return true; } @@ -439,151 +347,11 @@ DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb:: } bool -DynamicLoaderMacOSXDYLD::NeedToLocateDYLD () const +DynamicLoaderMacOSXDYLD::NeedToDoInitialImageFetch () { return m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS; } -//---------------------------------------------------------------------- -// Update the load addresses for all segments in MODULE using the -// updated INFO that is passed in. -//---------------------------------------------------------------------- -bool -DynamicLoaderMacOSXDYLD::UpdateImageLoadAddress (Module *module, DYLDImageInfo& info) -{ - bool changed = false; - if (module) - { - ObjectFile *image_object_file = module->GetObjectFile(); - if (image_object_file) - { - SectionList *section_list = image_object_file->GetSectionList (); - if (section_list) - { - std::vector inaccessible_segment_indexes; - // We now know the slide amount, so go through all sections - // and update the load addresses with the correct values. - const size_t num_segments = info.segments.size(); - for (size_t i=0; iFindSectionByName(info.segments[i].name)); - - if (info.segments[i].maxprot == 0) - { - inaccessible_segment_indexes.push_back(i); - } - else - { - const addr_t new_section_load_addr = info.segments[i].vmaddr + info.slide; - static ConstString g_section_name_LINKEDIT ("__LINKEDIT"); - - if (section_sp) - { - // __LINKEDIT sections from files in the shared cache - // can overlap so check to see what the segment name is - // and pass "false" so we don't warn of overlapping - // "Section" objects, and "true" for all other sections. - const bool warn_multiple = section_sp->GetName() != g_section_name_LINKEDIT; - - changed = m_process->GetTarget().SetSectionLoadAddress (section_sp, new_section_load_addr, warn_multiple); - } - else - { - Host::SystemLog (Host::eSystemLogWarning, - "warning: unable to find and load segment named '%s' at 0x%" PRIx64 " in '%s' in macosx dynamic loader plug-in.\n", - info.segments[i].name.AsCString(""), - (uint64_t)new_section_load_addr, - image_object_file->GetFileSpec().GetPath().c_str()); - } - } - } - - // If the loaded the file (it changed) and we have segments that - // are not readable or writeable, add them to the invalid memory - // region cache for the process. This will typically only be - // the __PAGEZERO segment in the main executable. We might be able - // to apply this more generally to more sections that have no - // protections in the future, but for now we are going to just - // do __PAGEZERO. - if (changed && !inaccessible_segment_indexes.empty()) - { - for (uint32_t i=0; iFindSectionByName(info.segments[seg_idx].name)); - - if (section_sp) - { - static ConstString g_pagezero_section_name("__PAGEZERO"); - if (g_pagezero_section_name == section_sp->GetName()) - { - // __PAGEZERO never slides... - const lldb::addr_t vmaddr = info.segments[seg_idx].vmaddr; - const lldb::addr_t vmsize = info.segments[seg_idx].vmsize; - Process::LoadRange pagezero_range (vmaddr, vmsize); - m_process->AddInvalidMemoryRegion(pagezero_range); - } - } - } - } - } - } - } - // We might have an in memory image that was loaded as soon as it was created - if (info.load_stop_id == m_process->GetStopID()) - changed = true; - else if (changed) - { - // Update the stop ID when this library was updated - info.load_stop_id = m_process->GetStopID(); - } - return changed; -} - -//---------------------------------------------------------------------- -// Update the load addresses for all segments in MODULE using the -// updated INFO that is passed in. -//---------------------------------------------------------------------- -bool -DynamicLoaderMacOSXDYLD::UnloadImageLoadAddress (Module *module, DYLDImageInfo& info) -{ - bool changed = false; - if (module) - { - ObjectFile *image_object_file = module->GetObjectFile(); - if (image_object_file) - { - SectionList *section_list = image_object_file->GetSectionList (); - if (section_list) - { - const size_t num_segments = info.segments.size(); - for (size_t i=0; iFindSectionByName(info.segments[i].name)); - if (section_sp) - { - const addr_t old_section_load_addr = info.segments[i].vmaddr + info.slide; - if (m_process->GetTarget().SetSectionUnloaded (section_sp, old_section_load_addr)) - changed = true; - } - else - { - Host::SystemLog (Host::eSystemLogWarning, - "warning: unable to find and unload segment named '%s' in '%s' in macosx dynamic loader plug-in.\n", - info.segments[i].name.AsCString(""), - image_object_file->GetFileSpec().GetPath().c_str()); - } - } - } - } - } - return changed; -} - - //---------------------------------------------------------------------- // Static callback function that gets called when our DYLD notification // breakpoint gets hit. We update all of our image infos and then @@ -683,7 +451,7 @@ DynamicLoaderMacOSXDYLD::NotifyBreakpointHit (void *baton, bool DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure () { - Mutex::Locker locker(m_mutex); + std::lock_guard guard(m_mutex); // the all image infos is already valid for this process stop ID if (m_process->GetStopID() == m_dyld_all_image_infos_stop_id) @@ -801,181 +569,16 @@ DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure () } -// This method is an amalgamation of code from -// ReadMachHeader() -// ParseLoadCommands() -// UpdateImageInfosHeaderAndLoadCommands() -// but written to extract everything from the JSON packet from debugserver, instead of using memory reads. - -bool -DynamicLoaderMacOSXDYLD::AddModulesUsingInfosFromDebugserver (StructuredData::ObjectSP image_details, DYLDImageInfo::collection &image_infos) -{ - StructuredData::ObjectSP images_sp = image_details->GetAsDictionary()->GetValueForKey("images"); - if (images_sp.get() == nullptr) - return false; - - image_infos.resize (images_sp->GetAsArray()->GetSize()); - - uint32_t exe_idx = UINT32_MAX; - - for (size_t i = 0; i < image_infos.size(); i++) - { - StructuredData::ObjectSP image_sp = images_sp->GetAsArray()->GetItemAtIndex(i); - if (image_sp.get() == nullptr || image_sp->GetAsDictionary() == nullptr) - return false; - StructuredData::Dictionary *image = image_sp->GetAsDictionary(); - if (image->HasKey("load_address") == false - || image->HasKey("pathname") == false - || image->HasKey("mod_date") == false - || image->HasKey("mach_header") == false - || image->GetValueForKey("mach_header")->GetAsDictionary() == nullptr - || image->HasKey("segments") == false - || image->GetValueForKey("segments")->GetAsArray() == nullptr - || image->HasKey("uuid") == false ) - { - return false; - } - image_infos[i].address = image->GetValueForKey("load_address")->GetAsInteger()->GetValue(); - image_infos[i].mod_date = image->GetValueForKey("mod_date")->GetAsInteger()->GetValue(); - image_infos[i].file_spec.SetFile(image->GetValueForKey("pathname")->GetAsString()->GetValue().c_str(), false); - - StructuredData::Dictionary *mh = image->GetValueForKey("mach_header")->GetAsDictionary(); - image_infos[i].header.magic = mh->GetValueForKey("magic")->GetAsInteger()->GetValue(); - image_infos[i].header.cputype = mh->GetValueForKey("cputype")->GetAsInteger()->GetValue(); - image_infos[i].header.cpusubtype = mh->GetValueForKey("cpusubtype")->GetAsInteger()->GetValue(); - image_infos[i].header.filetype = mh->GetValueForKey("filetype")->GetAsInteger()->GetValue(); - - // Fields that aren't used by DynamicLoaderMacOSXDYLD so debugserver doesn't currently send them - // in the reply. - - if (mh->HasKey("flags")) - image_infos[i].header.flags = mh->GetValueForKey("flags")->GetAsInteger()->GetValue(); - else - image_infos[i].header.flags = 0; - - if (mh->HasKey("ncmds")) - image_infos[i].header.ncmds = mh->GetValueForKey("ncmds")->GetAsInteger()->GetValue(); - else - image_infos[i].header.ncmds = 0; - - if (mh->HasKey("sizeofcmds")) - image_infos[i].header.sizeofcmds = mh->GetValueForKey("sizeofcmds")->GetAsInteger()->GetValue(); - else - image_infos[i].header.sizeofcmds = 0; - - if (image_infos[i].header.filetype == llvm::MachO::MH_EXECUTE) - exe_idx = i; - - StructuredData::Array *segments = image->GetValueForKey("segments")->GetAsArray(); - uint32_t segcount = segments->GetSize(); - for (size_t j = 0; j < segcount; j++) - { - Segment segment; - StructuredData::Dictionary *seg = segments->GetItemAtIndex(j)->GetAsDictionary(); - segment.name = ConstString(seg->GetValueForKey("name")->GetAsString()->GetValue().c_str()); - segment.vmaddr = seg->GetValueForKey("vmaddr")->GetAsInteger()->GetValue(); - segment.vmsize = seg->GetValueForKey("vmsize")->GetAsInteger()->GetValue(); - segment.fileoff = seg->GetValueForKey("fileoff")->GetAsInteger()->GetValue(); - segment.filesize = seg->GetValueForKey("filesize")->GetAsInteger()->GetValue(); - segment.maxprot = seg->GetValueForKey("maxprot")->GetAsInteger()->GetValue(); - - // Fields that aren't used by DynamicLoaderMacOSXDYLD so debugserver doesn't currently send them - // in the reply. - - if (seg->HasKey("initprot")) - segment.initprot = seg->GetValueForKey("initprot")->GetAsInteger()->GetValue(); - else - segment.initprot = 0; - - if (seg->HasKey("flags")) - segment.flags = seg->GetValueForKey("flags")->GetAsInteger()->GetValue(); - else - segment.flags = 0; - - if (seg->HasKey("nsects")) - segment.nsects = seg->GetValueForKey("nsects")->GetAsInteger()->GetValue(); - else - segment.nsects = 0; - - image_infos[i].segments.push_back (segment); - } - - image_infos[i].uuid.SetFromCString (image->GetValueForKey("uuid")->GetAsString()->GetValue().c_str()); - - // All sections listed in the dyld image info structure will all - // either be fixed up already, or they will all be off by a single - // slide amount that is determined by finding the first segment - // that is at file offset zero which also has bytes (a file size - // that is greater than zero) in the object file. - - // Determine the slide amount (if any) - const size_t num_sections = image_infos[i].segments.size(); - for (size_t k = 0; k < num_sections; ++k) - { - // Iterate through the object file sections to find the - // first section that starts of file offset zero and that - // has bytes in the file... - if ((image_infos[i].segments[k].fileoff == 0 && image_infos[i].segments[k].filesize > 0) - || (image_infos[i].segments[k].name == ConstString("__TEXT"))) - { - image_infos[i].slide = image_infos[i].address - image_infos[i].segments[k].vmaddr; - // We have found the slide amount, so we can exit - // this for loop. - break; - } - } - } - - Target &target = m_process->GetTarget(); - - if (exe_idx < image_infos.size()) - { - const bool can_create = true; - ModuleSP exe_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[exe_idx], can_create, NULL)); - - if (exe_module_sp) - { - UpdateImageLoadAddress (exe_module_sp.get(), image_infos[exe_idx]); - - if (exe_module_sp.get() != target.GetExecutableModulePointer()) - { - // Don't load dependent images since we are in dyld where we will know - // and find out about all images that are loaded. Also when setting the - // executable module, it will clear the targets module list, and if we - // have an in memory dyld module, it will get removed from the list - // so we will need to add it back after setting the executable module, - // so we first try and see if we already have a weak pointer to the - // dyld module, make it into a shared pointer, then add the executable, - // then re-add it back to make sure it is always in the list. - ModuleSP dyld_module_sp(m_dyld_module_wp.lock()); - - const bool get_dependent_images = false; - m_process->GetTarget().SetExecutableModule (exe_module_sp, - get_dependent_images); - - if (dyld_module_sp) - { - if(target.GetImages().AppendIfNeeded (dyld_module_sp)) - { - // Also add it to the section list. - UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld); - } - } - } - } - } - return true; -} - bool DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count) { - DYLDImageInfo::collection image_infos; + ImageInfo::collection image_infos; Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); if (log) log->Printf ("Adding %d modules.\n", image_infos_count); - Mutex::Locker locker(m_mutex); + std::lock_guard guard(m_mutex); + std::lock_guard baseclass_guard(GetMutex()); if (m_process->GetStopID() == m_dyld_image_infos_stop_id) return true; @@ -987,8 +590,9 @@ DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfosAddress (lldb::addr_t image_in && image_infos_json_sp->GetAsDictionary()->GetValueForKey("images")->GetAsArray()->GetSize() == image_infos_count) { bool return_value = false; - if (AddModulesUsingInfosFromDebugserver (image_infos_json_sp, image_infos)) + if (JSONImageInformationIntoImageInfo (image_infos_json_sp, image_infos)) { + AddExecutableModuleIfInImageInfos (image_infos); return_value = AddModulesUsingImageInfos (image_infos); } m_dyld_image_infos_stop_id = m_process->GetStopID(); @@ -1004,101 +608,14 @@ DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfosAddress (lldb::addr_t image_in return return_value; } -// Adds the modules in image_infos to m_dyld_image_infos. -// NB don't call this passing in m_dyld_image_infos. - -bool -DynamicLoaderMacOSXDYLD::AddModulesUsingImageInfos (DYLDImageInfo::collection &image_infos) -{ - // Now add these images to the main list. - ModuleList loaded_module_list; - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); - Target &target = m_process->GetTarget(); - ModuleList& target_images = target.GetImages(); - - for (uint32_t idx = 0; idx < image_infos.size(); ++idx) - { - if (log) - { - log->Printf ("Adding new image at address=0x%16.16" PRIx64 ".", image_infos[idx].address); - image_infos[idx].PutToLog (log); - } - - m_dyld_image_infos.push_back(image_infos[idx]); - - ModuleSP image_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[idx], true, NULL)); - - if (image_module_sp) - { - ObjectFile *objfile = image_module_sp->GetObjectFile (); - if (objfile) - { - SectionList *sections = objfile->GetSectionList(); - if (sections) - { - ConstString commpage_dbstr("__commpage"); - Section *commpage_section = sections->FindSectionByName(commpage_dbstr).get(); - if (commpage_section) - { - ModuleSpec module_spec (objfile->GetFileSpec(), image_infos[idx].GetArchitecture ()); - module_spec.GetObjectName() = commpage_dbstr; - ModuleSP commpage_image_module_sp(target_images.FindFirstModule (module_spec)); - if (!commpage_image_module_sp) - { - module_spec.SetObjectOffset (objfile->GetFileOffset() + commpage_section->GetFileOffset()); - module_spec.SetObjectSize (objfile->GetByteSize()); - commpage_image_module_sp = target.GetSharedModule (module_spec); - if (!commpage_image_module_sp || commpage_image_module_sp->GetObjectFile() == NULL) - { - commpage_image_module_sp = m_process->ReadModuleFromMemory (image_infos[idx].file_spec, - image_infos[idx].address); - // Always load a memory image right away in the target in case - // we end up trying to read the symbol table from memory... The - // __LINKEDIT will need to be mapped so we can figure out where - // the symbol table bits are... - bool changed = false; - UpdateImageLoadAddress (commpage_image_module_sp.get(), image_infos[idx]); - target.GetImages().Append(commpage_image_module_sp); - if (changed) - { - image_infos[idx].load_stop_id = m_process->GetStopID(); - loaded_module_list.AppendIfNeeded (commpage_image_module_sp); - } - } - } - } - } - } - - // UpdateImageLoadAddress will return true if any segments - // change load address. We need to check this so we don't - // mention that all loaded shared libraries are newly loaded - // each time we hit out dyld breakpoint since dyld will list all - // shared libraries each time. - if (UpdateImageLoadAddress (image_module_sp.get(), image_infos[idx])) - { - target_images.AppendIfNeeded(image_module_sp); - loaded_module_list.AppendIfNeeded (image_module_sp); - } - } - } - - if (loaded_module_list.GetSize() > 0) - { - if (log) - loaded_module_list.LogUUIDAndPaths (log, "DynamicLoaderMacOSXDYLD::ModulesDidLoad"); - m_process->GetTarget().ModulesDidLoad (loaded_module_list); - } - return true; -} - bool DynamicLoaderMacOSXDYLD::RemoveModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count) { - DYLDImageInfo::collection image_infos; + ImageInfo::collection image_infos; Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); - Mutex::Locker locker(m_mutex); + std::lock_guard guard(m_mutex); + std::lock_guard baseclass_guard(GetMutex()); if (m_process->GetStopID() == m_dyld_image_infos_stop_id) return true; @@ -1129,7 +646,7 @@ DynamicLoaderMacOSXDYLD::RemoveModulesUsingImageInfosAddress (lldb::addr_t image // Also copy over the uuid from the old entry to the removed entry so we can // use it to lookup the module in the module list. - DYLDImageInfo::collection::iterator pos, end = m_dyld_image_infos.end(); + ImageInfo::collection::iterator pos, end = m_dyld_image_infos.end(); for (pos = m_dyld_image_infos.begin(); pos != end; pos++) { if (image_infos[idx].address == (*pos).address) @@ -1139,12 +656,12 @@ DynamicLoaderMacOSXDYLD::RemoveModulesUsingImageInfosAddress (lldb::addr_t image // Add the module from this image_info to the "unloaded_module_list". We'll remove them all at // one go later on. - ModuleSP unload_image_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[idx], false, NULL)); + ModuleSP unload_image_module_sp (FindTargetModuleForImageInfo (image_infos[idx], false, NULL)); if (unload_image_module_sp.get()) { // When we unload, be sure to use the image info from the old list, // since that has sections correctly filled in. - UnloadImageLoadAddress (unload_image_module_sp.get(), *pos); + UnloadModuleSections (unload_image_module_sp.get(), *pos); unloaded_module_list.AppendIfNeeded (unload_image_module_sp); } else @@ -1188,9 +705,10 @@ DynamicLoaderMacOSXDYLD::RemoveModulesUsingImageInfosAddress (lldb::addr_t image bool DynamicLoaderMacOSXDYLD::ReadImageInfos (lldb::addr_t image_infos_addr, uint32_t image_infos_count, - DYLDImageInfo::collection &image_infos) + ImageInfo::collection &image_infos) { - const ByteOrder endian = m_dyld.GetByteOrder(); + std::lock_guard baseclass_guard(GetMutex()); + const ByteOrder endian = GetByteOrderFromMagic (m_dyld.header.magic); const uint32_t addr_size = m_dyld.GetAddressByteSize(); image_infos.resize(image_infos_count); @@ -1240,7 +758,8 @@ DynamicLoaderMacOSXDYLD::InitializeFromAllImageInfos () { Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER)); - Mutex::Locker locker(m_mutex); + std::lock_guard guard(m_mutex); + std::lock_guard baseclass_guard(GetMutex()); if (m_process->GetStopID() == m_dyld_image_infos_stop_id || m_dyld_image_infos.size() != 0) return false; @@ -1275,7 +794,7 @@ DynamicLoaderMacOSXDYLD::InitializeFromAllImageInfos () Target &target = m_process->GetTarget(); const ModuleList &target_modules = target.GetImages(); ModuleList not_loaded_modules; - Mutex::Locker modules_locker(target_modules.GetMutex()); + std::lock_guard guard(target_modules.GetMutex()); size_t num_modules = target_modules.GetSize(); for (size_t i = 0; i < num_modules; i++) @@ -1381,7 +900,7 @@ DynamicLoaderMacOSXDYLD::ReadMachHeader (lldb::addr_t addr, llvm::MachO::mach_he // Parse the load commands for an image //---------------------------------------------------------------------- uint32_t -DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, DYLDImageInfo& dylib_info, FileSpec *lc_id_dylinker) +DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, ImageInfo& dylib_info, FileSpec *lc_id_dylinker) { lldb::offset_t offset = 0; uint32_t cmd_idx; @@ -1478,7 +997,7 @@ DynamicLoaderMacOSXDYLD::ParseLoadCommands (const DataExtractor& data, DYLDImage //---------------------------------------------------------------------- void -DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::collection &image_infos, +DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(ImageInfo::collection &image_infos, uint32_t infos_count, bool update_executable) { @@ -1505,7 +1024,7 @@ DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::co if (exe_idx < image_infos.size()) { const bool can_create = true; - ModuleSP exe_module_sp (FindTargetModuleForDYLDImageInfo (image_infos[exe_idx], can_create, NULL)); + ModuleSP exe_module_sp (FindTargetModuleForImageInfo (image_infos[exe_idx], can_create, NULL)); if (exe_module_sp) { @@ -1521,7 +1040,7 @@ DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::co // so we first try and see if we already have a weak pointer to the // dyld module, make it into a shared pointer, then add the executable, // then re-add it back to make sure it is always in the list. - ModuleSP dyld_module_sp(m_dyld_module_wp.lock()); + ModuleSP dyld_module_sp(GetDYLDModule ()); const bool get_dependent_images = false; m_process->GetTarget().SetExecutableModule (exe_module_sp, @@ -1531,6 +1050,8 @@ DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::co { if(target.GetImages().AppendIfNeeded (dyld_module_sp)) { + std::lock_guard baseclass_guard(GetMutex()); + // Also add it to the section list. UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld); } @@ -1540,133 +1061,6 @@ DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::co } } -//---------------------------------------------------------------------- -// On Mac OS X libobjc (the Objective-C runtime) has several critical dispatch -// functions written in hand-written assembly, and also have hand-written unwind -// information in the eh_frame section. Normally we prefer analyzing the -// assembly instructions of a currently executing frame to unwind from that frame -- -// but on hand-written functions this profiling can fail. We should use the -// eh_frame instructions for these functions all the time. -// -// As an aside, it would be better if the eh_frame entries had a flag (or were -// extensible so they could have an Apple-specific flag) which indicates that -// the instructions are asynchronous -- accurate at every instruction, instead -// of our normal default assumption that they are not. -//---------------------------------------------------------------------- - -bool -DynamicLoaderMacOSXDYLD::AlwaysRelyOnEHUnwindInfo (SymbolContext &sym_ctx) -{ - ModuleSP module_sp; - if (sym_ctx.symbol) - { - module_sp = sym_ctx.symbol->GetAddressRef().GetModule(); - } - if (module_sp.get() == NULL && sym_ctx.function) - { - module_sp = sym_ctx.function->GetAddressRange().GetBaseAddress().GetModule(); - } - if (module_sp.get() == NULL) - return false; - - ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime(); - if (objc_runtime != NULL && objc_runtime->IsModuleObjCLibrary (module_sp)) - { - return true; - } - - return false; -} - - - -//---------------------------------------------------------------------- -// Dump a Segment to the file handle provided. -//---------------------------------------------------------------------- -void -DynamicLoaderMacOSXDYLD::Segment::PutToLog (Log *log, lldb::addr_t slide) const -{ - if (log) - { - if (slide == 0) - log->Printf ("\t\t%16s [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")", - name.AsCString(""), - vmaddr + slide, - vmaddr + slide + vmsize); - else - log->Printf ("\t\t%16s [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ") slide = 0x%" PRIx64, - name.AsCString(""), - vmaddr + slide, - vmaddr + slide + vmsize, - slide); - } -} - -const DynamicLoaderMacOSXDYLD::Segment * -DynamicLoaderMacOSXDYLD::DYLDImageInfo::FindSegment (const ConstString &name) const -{ - const size_t num_segments = segments.size(); - for (size_t i=0; iPrintf("\t modtime=0x%8.8" PRIx64 " uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s' (UNLOADED)", - mod_date, - u[ 0], u[ 1], u[ 2], u[ 3], - u[ 4], u[ 5], u[ 6], u[ 7], - u[ 8], u[ 9], u[10], u[11], - u[12], u[13], u[14], u[15], - file_spec.GetPath().c_str()); - } - else - log->Printf("\t modtime=0x%8.8" PRIx64 " path='%s' (UNLOADED)", - mod_date, - file_spec.GetPath().c_str()); - } - else - { - if (u) - { - log->Printf("\taddress=0x%16.16" PRIx64 " modtime=0x%8.8" PRIx64 " uuid=%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X path='%s'", - address, - mod_date, - u[ 0], u[ 1], u[ 2], u[ 3], - u[ 4], u[ 5], u[ 6], u[ 7], - u[ 8], u[ 9], u[10], u[11], - u[12], u[13], u[14], u[15], - file_spec.GetPath().c_str()); - } - else - { - log->Printf("\taddress=0x%16.16" PRIx64 " modtime=0x%8.8" PRIx64 " path='%s'", - address, - mod_date, - file_spec.GetPath().c_str()); - - } - for (uint32_t i=0; i guard(m_mutex); + std::lock_guard baseclass_guard(GetMutex()); log->Printf("dyld_all_image_infos = { version=%d, count=%d, addr=0x%8.8" PRIx64 ", notify=0x%8.8" PRIx64 " }", m_dyld_all_image_infos.version, m_dyld_all_image_infos.dylib_info_count, @@ -1694,15 +1089,6 @@ DynamicLoaderMacOSXDYLD::PutToLog(Log *log) const } } -void -DynamicLoaderMacOSXDYLD::PrivateInitialize(Process *process) -{ - DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s() process state = %s\n", __FUNCTION__, StateAsCString(m_process->GetState())); - Clear(true); - m_process = process; - m_process->GetTarget().ClearAllLoadedSections(); -} - bool DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint () { @@ -1722,6 +1108,8 @@ DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint () ModuleSP dyld_module_sp = m_dyld_module_wp.lock(); if (dyld_module_sp) { + std::lock_guard baseclass_guard(GetMutex()); + UpdateImageLoadAddress (dyld_module_sp.get(), m_dyld); resolved = m_process->GetTarget().ResolveLoadAddress(m_dyld_all_image_infos.notification, so_addr); } @@ -1739,229 +1127,6 @@ DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint () return m_break_id != LLDB_INVALID_BREAK_ID; } -//---------------------------------------------------------------------- -// Member function that gets called when the process state changes. -//---------------------------------------------------------------------- -void -DynamicLoaderMacOSXDYLD::PrivateProcessStateChanged (Process *process, StateType state) -{ - DEBUG_PRINTF("DynamicLoaderMacOSXDYLD::%s(%s)\n", __FUNCTION__, StateAsCString(state)); - switch (state) - { - case eStateConnected: - case eStateAttaching: - case eStateLaunching: - case eStateInvalid: - case eStateUnloaded: - case eStateExited: - case eStateDetached: - Clear(false); - break; - - case eStateStopped: - // Keep trying find dyld and set our notification breakpoint each time - // we stop until we succeed - if (!DidSetNotificationBreakpoint () && m_process->IsAlive()) - { - if (NeedToLocateDYLD ()) - LocateDYLD (); - - SetNotificationBreakpoint (); - } - break; - - case eStateRunning: - case eStateStepping: - case eStateCrashed: - case eStateSuspended: - break; - } -} - -ThreadPlanSP -DynamicLoaderMacOSXDYLD::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others) -{ - ThreadPlanSP thread_plan_sp; - StackFrame *current_frame = thread.GetStackFrameAtIndex(0).get(); - const SymbolContext ¤t_context = current_frame->GetSymbolContext(eSymbolContextSymbol); - Symbol *current_symbol = current_context.symbol; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - TargetSP target_sp (thread.CalculateTarget()); - - if (current_symbol != NULL) - { - std::vector
addresses; - - if (current_symbol->IsTrampoline()) - { - const ConstString &trampoline_name = current_symbol->GetMangled().GetName(current_symbol->GetLanguage(), Mangled::ePreferMangled); - - if (trampoline_name) - { - const ModuleList &images = target_sp->GetImages(); - - SymbolContextList code_symbols; - images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeCode, code_symbols); - size_t num_code_symbols = code_symbols.GetSize(); - - if (num_code_symbols > 0) - { - for (uint32_t i = 0; i < num_code_symbols; i++) - { - SymbolContext context; - AddressRange addr_range; - if (code_symbols.GetContextAtIndex(i, context)) - { - context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range); - addresses.push_back(addr_range.GetBaseAddress()); - if (log) - { - addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(target_sp.get()); - - log->Printf ("Found a trampoline target symbol at 0x%" PRIx64 ".", load_addr); - } - } - } - } - - SymbolContextList reexported_symbols; - images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeReExported, reexported_symbols); - size_t num_reexported_symbols = reexported_symbols.GetSize(); - if (num_reexported_symbols > 0) - { - for (uint32_t i = 0; i < num_reexported_symbols; i++) - { - SymbolContext context; - if (reexported_symbols.GetContextAtIndex(i, context)) - { - if (context.symbol) - { - Symbol *actual_symbol = context.symbol->ResolveReExportedSymbol(*target_sp.get()); - if (actual_symbol) - { - const Address actual_symbol_addr = actual_symbol->GetAddress(); - if (actual_symbol_addr.IsValid()) - { - addresses.push_back(actual_symbol_addr); - if (log) - { - lldb::addr_t load_addr = actual_symbol_addr.GetLoadAddress(target_sp.get()); - log->Printf ("Found a re-exported symbol: %s at 0x%" PRIx64 ".", - actual_symbol->GetName().GetCString(), load_addr); - } - } - } - } - } - } - } - - SymbolContextList indirect_symbols; - images.FindSymbolsWithNameAndType(trampoline_name, eSymbolTypeResolver, indirect_symbols); - size_t num_indirect_symbols = indirect_symbols.GetSize(); - if (num_indirect_symbols > 0) - { - for (uint32_t i = 0; i < num_indirect_symbols; i++) - { - SymbolContext context; - AddressRange addr_range; - if (indirect_symbols.GetContextAtIndex(i, context)) - { - context.GetAddressRange (eSymbolContextEverything, 0, false, addr_range); - addresses.push_back(addr_range.GetBaseAddress()); - if (log) - { - addr_t load_addr = addr_range.GetBaseAddress().GetLoadAddress(target_sp.get()); - - log->Printf ("Found an indirect target symbol at 0x%" PRIx64 ".", load_addr); - } - } - } - } - } - } - else if (current_symbol->GetType() == eSymbolTypeReExported) - { - // I am not sure we could ever end up stopped AT a re-exported symbol. But just in case: - - const Symbol *actual_symbol = current_symbol->ResolveReExportedSymbol(*(target_sp.get())); - if (actual_symbol) - { - Address target_addr(actual_symbol->GetAddress()); - if (target_addr.IsValid()) - { - if (log) - log->Printf ("Found a re-exported symbol: %s pointing to: %s at 0x%" PRIx64 ".", - current_symbol->GetName().GetCString(), - actual_symbol->GetName().GetCString(), - target_addr.GetLoadAddress(target_sp.get())); - addresses.push_back (target_addr.GetLoadAddress(target_sp.get())); - - } - } - } - - if (addresses.size() > 0) - { - // First check whether any of the addresses point to Indirect symbols, and if they do, resolve them: - std::vector load_addrs; - for (Address address : addresses) - { - Symbol *symbol = address.CalculateSymbolContextSymbol(); - if (symbol && symbol->IsIndirect()) - { - Error error; - Address symbol_address = symbol->GetAddress(); - addr_t resolved_addr = thread.GetProcess()->ResolveIndirectFunction(&symbol_address, error); - if (error.Success()) - { - load_addrs.push_back(resolved_addr); - if (log) - log->Printf("ResolveIndirectFunction found resolved target for %s at 0x%" PRIx64 ".", - symbol->GetName().GetCString(), resolved_addr); - } - } - else - { - load_addrs.push_back(address.GetLoadAddress(target_sp.get())); - } - - } - thread_plan_sp.reset (new ThreadPlanRunToAddress (thread, load_addrs, stop_others)); - } - } - else - { - if (log) - log->Printf ("Could not find symbol for step through."); - } - - return thread_plan_sp; -} - -size_t -DynamicLoaderMacOSXDYLD::FindEquivalentSymbols (lldb_private::Symbol *original_symbol, - lldb_private::ModuleList &images, - lldb_private::SymbolContextList &equivalent_symbols) -{ - const ConstString &trampoline_name = original_symbol->GetMangled().GetName(original_symbol->GetLanguage(), Mangled::ePreferMangled); - if (!trampoline_name) - return 0; - - size_t initial_size = equivalent_symbols.GetSize(); - - static const char *resolver_name_regex = "(_gc|_non_gc|\\$[A-Za-z0-9\\$]+)$"; - std::string equivalent_regex_buf("^"); - equivalent_regex_buf.append (trampoline_name.GetCString()); - equivalent_regex_buf.append (resolver_name_regex); - - RegularExpression equivalent_name_regex (equivalent_regex_buf.c_str()); - const bool append = true; - images.FindSymbolsMatchingRegExAndType (equivalent_name_regex, eSymbolTypeCode, equivalent_symbols, append); - - return equivalent_symbols.GetSize() - initial_size; -} - Error DynamicLoaderMacOSXDYLD::CanLoadImage () { @@ -2029,6 +1194,8 @@ DynamicLoaderMacOSXDYLD::GetPluginVersion() uint32_t DynamicLoaderMacOSXDYLD::AddrByteSize() { + std::lock_guard baseclass_guard(GetMutex()); + switch (m_dyld.header.magic) { case llvm::MachO::MH_MAGIC: @@ -2046,7 +1213,7 @@ DynamicLoaderMacOSXDYLD::AddrByteSize() } lldb::ByteOrder -DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic (uint32_t magic) +DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(uint32_t magic) { switch (magic) { @@ -2066,10 +1233,3 @@ DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic (uint32_t magic) } return lldb::eByteOrderInvalid; } - -lldb::ByteOrder -DynamicLoaderMacOSXDYLD::DYLDImageInfo::GetByteOrder() -{ - return DynamicLoaderMacOSXDYLD::GetByteOrderFromMagic(header.magic); -} - diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h index 8fd60d0b6ac7..637bd8640d24 100644 --- a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h +++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h @@ -13,6 +13,7 @@ // C Includes // C++ Includes #include +#include // Other libraries and framework includes // Project includes @@ -20,16 +21,17 @@ #include "lldb/Host/FileSpec.h" #include "lldb/Core/StructuredData.h" #include "lldb/Core/UUID.h" -#include "lldb/Host/Mutex.h" #include "lldb/Target/Process.h" #include "lldb/Utility/SafeMachO.h" -class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoader +#include "DynamicLoaderDarwin.h" + +class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoaderDarwin { public: DynamicLoaderMacOSXDYLD(lldb_private::Process *process); - ~DynamicLoaderMacOSXDYLD() override; + virtual ~DynamicLoaderMacOSXDYLD() override; //------------------------------------------------------------------ // Static Functions @@ -55,24 +57,9 @@ public: /// Allow DynamicLoader plug-ins to execute some code after /// attaching to a process. //------------------------------------------------------------------ - void - DidAttach() override; - - void - DidLaunch() override; - bool ProcessDidExec() override; - lldb::ThreadPlanSP - GetStepThroughTrampolinePlan(lldb_private::Thread &thread, - bool stop_others) override; - - size_t - FindEquivalentSymbols(lldb_private::Symbol *original_symbol, - lldb_private::ModuleList &module_list, - lldb_private::SymbolContextList &equivalent_symbols) override; - lldb_private::Error CanLoadImage() override; @@ -85,28 +72,21 @@ public: uint32_t GetPluginVersion() override; - bool - AlwaysRelyOnEHUnwindInfo(lldb_private::SymbolContext &sym_ctx) override; - protected: void - PrivateInitialize (lldb_private::Process *process); + PutToLog(lldb_private::Log *log) const; void - PrivateProcessStateChanged (lldb_private::Process *process, - lldb::StateType state); + DoInitialImageFetch () override; bool - LocateDYLD (); + NeedToDoInitialImageFetch () override; bool - DidSetNotificationBreakpoint () const; - - void - Clear (bool clear_process); + DidSetNotificationBreakpoint () override; void - PutToLog (lldb_private::Log *log) const; + DoClear () override; bool ReadDYLDInfoFromMemoryAndSetNotificationCallback (lldb::addr_t addr); @@ -120,141 +100,15 @@ protected: uint32_t AddrByteSize(); - static lldb::ByteOrder - GetByteOrderFromMagic (uint32_t magic); - bool ReadMachHeader (lldb::addr_t addr, llvm::MachO::mach_header *header, lldb_private::DataExtractor *load_command_data); - class Segment - { - public: - Segment() : - name(), - vmaddr(LLDB_INVALID_ADDRESS), - vmsize(0), - fileoff(0), - filesize(0), - maxprot(0), - initprot(0), - nsects(0), - flags(0) - { - } - - lldb_private::ConstString name; - lldb::addr_t vmaddr; - lldb::addr_t vmsize; - lldb::addr_t fileoff; - lldb::addr_t filesize; - uint32_t maxprot; - uint32_t initprot; - uint32_t nsects; - uint32_t flags; - - bool - operator==(const Segment& rhs) const - { - return name == rhs.name && vmaddr == rhs.vmaddr && vmsize == rhs.vmsize; - } - - void - PutToLog (lldb_private::Log *log, - lldb::addr_t slide) const; - - }; - - struct DYLDImageInfo - { - lldb::addr_t address; // Address of mach header for this dylib - lldb::addr_t slide; // The amount to slide all segments by if there is a global slide. - lldb::addr_t mod_date; // Modification date for this dylib - lldb_private::FileSpec file_spec; // Resolved path for this dylib - lldb_private::UUID uuid; // UUID for this dylib if it has one, else all zeros - llvm::MachO::mach_header header; // The mach header for this image - std::vector segments; // All segment vmaddr and vmsize pairs for this executable (from memory of inferior) - uint32_t load_stop_id; // The process stop ID that the sections for this image were loaded - - DYLDImageInfo() : - address(LLDB_INVALID_ADDRESS), - slide(0), - mod_date(0), - file_spec(), - uuid(), - header(), - segments(), - load_stop_id(0) - { - } - - void - Clear(bool load_cmd_data_only) - { - if (!load_cmd_data_only) - { - address = LLDB_INVALID_ADDRESS; - slide = 0; - mod_date = 0; - file_spec.Clear(); - ::memset (&header, 0, sizeof(header)); - } - uuid.Clear(); - segments.clear(); - load_stop_id = 0; - } - - bool - operator == (const DYLDImageInfo& rhs) const - { - return address == rhs.address - && slide == rhs.slide - && mod_date == rhs.mod_date - && file_spec == rhs.file_spec - && uuid == rhs.uuid - && memcmp(&header, &rhs.header, sizeof(header)) == 0 - && segments == rhs.segments; - } - - bool - UUIDValid() const - { - return uuid.IsValid(); - } - - uint32_t - GetAddressByteSize () - { - if (header.cputype) - { - if (header.cputype & llvm::MachO::CPU_ARCH_ABI64) - return 8; - else - return 4; - } - return 0; - } - - lldb::ByteOrder - GetByteOrder(); - - lldb_private::ArchSpec - GetArchitecture () const - { - return lldb_private::ArchSpec (lldb_private::eArchTypeMachO, header.cputype, header.cpusubtype); - } - - const Segment * - FindSegment (const lldb_private::ConstString &name) const; - - void - PutToLog (lldb_private::Log *log) const; - - typedef std::vector collection; - typedef collection::iterator iterator; - typedef collection::const_iterator const_iterator; - }; + uint32_t + ParseLoadCommands (const lldb_private::DataExtractor& data, + ImageInfo& dylib_info, + lldb_private::FileSpec *lc_id_dylinker); struct DYLDAllImageInfos { @@ -296,38 +150,14 @@ protected: } }; - void - RegisterNotificationCallbacks(); - - void - UnregisterNotificationCallbacks(); - - uint32_t - ParseLoadCommands (const lldb_private::DataExtractor& data, - DYLDImageInfo& dylib_info, - lldb_private::FileSpec *lc_id_dylinker); - - bool - UpdateImageLoadAddress(lldb_private::Module *module, - DYLDImageInfo& info); - - bool - UnloadImageLoadAddress (lldb_private::Module *module, - DYLDImageInfo& info); - - lldb::ModuleSP - FindTargetModuleForDYLDImageInfo (DYLDImageInfo &image_info, - bool can_create, - bool *did_create_ptr); - - DYLDImageInfo * - GetImageInfo (lldb_private::Module *module); + static lldb::ByteOrder + GetByteOrderFromMagic(uint32_t magic); bool - NeedToLocateDYLD () const; + SetNotificationBreakpoint () override; - bool - SetNotificationBreakpoint (); + void + ClearNotificationBreakpoint () override; // There is a little tricky bit where you might initially attach while dyld is updating // the all_image_infos, and you can't read the infos, so you have to continue and pick it @@ -343,39 +173,27 @@ protected: bool ReadAllImageInfosStructure (); - bool - AddModulesUsingInfosFromDebugserver (lldb_private::StructuredData::ObjectSP image_details, DYLDImageInfo::collection &image_infos); - bool AddModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count); - bool - AddModulesUsingImageInfos (DYLDImageInfo::collection &image_infos); - bool RemoveModulesUsingImageInfosAddress (lldb::addr_t image_infos_addr, uint32_t image_infos_count); void - UpdateImageInfosHeaderAndLoadCommands(DYLDImageInfo::collection &image_infos, + UpdateImageInfosHeaderAndLoadCommands(ImageInfo::collection &image_infos, uint32_t infos_count, bool update_executable); bool ReadImageInfos (lldb::addr_t image_infos_addr, uint32_t image_infos_count, - DYLDImageInfo::collection &image_infos); - + ImageInfo::collection &image_infos); - DYLDImageInfo m_dyld; // Info about the current dyld being used - lldb::ModuleWP m_dyld_module_wp; lldb::addr_t m_dyld_all_image_infos_addr; DYLDAllImageInfos m_dyld_all_image_infos; uint32_t m_dyld_all_image_infos_stop_id; lldb::user_id_t m_break_id; - DYLDImageInfo::collection m_dyld_image_infos; // Current shared libraries information - uint32_t m_dyld_image_infos_stop_id; // The process stop ID that "m_dyld_image_infos" is valid for - mutable lldb_private::Mutex m_mutex; - lldb_private::Process::Notifications m_notification_callbacks; + mutable std::recursive_mutex m_mutex; bool m_process_image_addr_is_all_images_infos; private: diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/Makefile b/source/Plugins/DynamicLoader/MacOSX-DYLD/Makefile deleted file mode 100644 index ffac3b457179..000000000000 --- a/source/Plugins/DynamicLoader/MacOSX-DYLD/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Disassembler/llvm/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginDynamicLoaderMacOSXDYLD -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index 6ba7b470d743..6515c02f37e0 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -599,9 +599,10 @@ DynamicLoaderPOSIXDYLD::GetEntryPoint() } lldb::addr_t -DynamicLoaderPOSIXDYLD::GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread) +DynamicLoaderPOSIXDYLD::GetThreadLocalData(const lldb::ModuleSP module_sp, const lldb::ThreadSP thread, + lldb::addr_t tls_file_addr) { - auto it = m_loaded_modules.find (module); + auto it = m_loaded_modules.find (module_sp); if (it == m_loaded_modules.end()) return LLDB_INVALID_ADDRESS; @@ -634,14 +635,16 @@ DynamicLoaderPOSIXDYLD::GetThreadLocalData (const lldb::ModuleSP module, const l addr_t dtv_slot = dtv + metadata.dtv_slot_size*modid; addr_t tls_block = ReadPointer (dtv_slot + metadata.tls_offset); - Module *mod = module.get(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); if (log) log->Printf("DynamicLoaderPOSIXDYLD::Performed TLS lookup: " "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 ", modid=%" PRId64 ", tls_block=0x%" PRIx64 "\n", - mod->GetObjectName().AsCString(""), link_map, tp, (int64_t)modid, tls_block); + module_sp->GetObjectName().AsCString(""), link_map, tp, (int64_t)modid, tls_block); - return tls_block; + if (tls_block == LLDB_INVALID_ADDRESS) + return LLDB_INVALID_ADDRESS; + else + return tls_block + tls_file_addr; } void @@ -656,7 +659,7 @@ DynamicLoaderPOSIXDYLD::ResolveExecutableModule (lldb::ModuleSP &module_sp) const auto platform_sp = target.GetPlatform (); ProcessInstanceInfo process_info; - if (!platform_sp->GetProcessInfo (m_process->GetID (), process_info)) + if (!m_process->GetProcessInfo(process_info)) { if (log) log->Printf ("DynamicLoaderPOSIXDYLD::%s - failed to get process info for pid %" PRIu64, diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h index cb97bbf43ba9..890808c5179c 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h @@ -61,7 +61,7 @@ public: CanLoadImage() override; lldb::addr_t - GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread) override; + GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread, lldb::addr_t tls_file_addr) override; //------------------------------------------------------------------ // PluginInterface protocol diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/Makefile b/source/Plugins/DynamicLoader/POSIX-DYLD/Makefile deleted file mode 100644 index 1c56366015d6..000000000000 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/DynamicLoader/POSIX-DYLD/Makefile ----*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginDynamicLoaderPosixDYLD -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp index 86cf45013a4d..daa21adf3a95 100644 --- a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp +++ b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp @@ -102,8 +102,8 @@ DynamicLoaderStatic::LoadAllImagesAtFileAddresses () // Disable JIT for static dynamic loader targets m_process->SetCanJIT(false); - Mutex::Locker mutex_locker(module_list.GetMutex()); - + std::lock_guard guard(module_list.GetMutex()); + const size_t num_modules = module_list.GetSize(); for (uint32_t idx = 0; idx < num_modules; ++idx) { diff --git a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h index a7fdf4d22165..67694c96025c 100644 --- a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h +++ b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h @@ -17,7 +17,6 @@ #include "lldb/Target/DynamicLoader.h" #include "lldb/Host/FileSpec.h" #include "lldb/Core/UUID.h" -#include "lldb/Host/Mutex.h" #include "lldb/Target/Process.h" class DynamicLoaderStatic : public lldb_private::DynamicLoader diff --git a/source/Plugins/DynamicLoader/Static/Makefile b/source/Plugins/DynamicLoader/Static/Makefile deleted file mode 100644 index 63972dfc5512..000000000000 --- a/source/Plugins/DynamicLoader/Static/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/DynamicLoader/Static/Makefile --------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginDynamicLoaderStatic -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/DynamicLoader/Windows-DYLD/Makefile b/source/Plugins/DynamicLoader/Windows-DYLD/Makefile deleted file mode 100644 index bf62aee30b2b..000000000000 --- a/source/Plugins/DynamicLoader/Windows-DYLD/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/DynamicLoader/Windows-DYLD/Makefile --*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginDynamicLoaderWindowsDYLD -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp b/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp index 976310610f51..0b8199481158 100644 --- a/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp +++ b/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp @@ -11,6 +11,7 @@ #include "lldb/Core/Log.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ClangUtil.h" #include "lldb/Symbol/CompilerType.h" #include "llvm/Support/raw_ostream.h" @@ -83,7 +84,7 @@ ASTDumper::ASTDumper (lldb::opaque_compiler_type_t type) ASTDumper::ASTDumper (const CompilerType &compiler_type) { - m_dump = ClangASTContext::GetQualType(compiler_type).getAsString(); + m_dump = ClangUtil::GetQualType(compiler_type).getAsString(); } diff --git a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp index 02505bde240c..f1231572e263 100644 --- a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp +++ b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp @@ -11,6 +11,11 @@ #include "ClangPersistentVariables.h" +#include "lldb/Core/Log.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ClangASTImporter.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/LLDBAssert.h" #include "stdlib.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" @@ -23,22 +28,18 @@ #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) +ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough, bool top_level, Target &target) + : m_ast_context(NULL), + m_passthrough(passthrough), + m_passthrough_sema(NULL), + m_target(target), + m_sema(NULL), + m_top_level(top_level) { if (!m_passthrough) return; @@ -76,6 +77,10 @@ ASTResultSynthesizer::TransformTopLevelDecl(Decl* D) log->Printf("TransformTopLevelDecl()"); } + if (m_top_level) + { + RecordPersistentDecl(named_decl); + } } if (LinkageSpecDecl *linkage_spec_decl = dyn_cast(D)) @@ -89,22 +94,23 @@ ASTResultSynthesizer::TransformTopLevelDecl(Decl* D) TransformTopLevelDecl(*decl_iterator); } } - else if (ObjCMethodDecl *method_decl = dyn_cast(D)) + else if (!m_top_level) { - if (m_ast_context && - !method_decl->getSelector().getAsString().compare("$__lldb_expr:")) + if (ObjCMethodDecl *method_decl = dyn_cast(D)) { - RecordPersistentTypes(method_decl); - SynthesizeObjCMethodResult(method_decl); + if (m_ast_context && !method_decl->getSelector().getAsString().compare("$__lldb_expr:")) + { + RecordPersistentTypes(method_decl); + SynthesizeObjCMethodResult(method_decl); + } } - } - else if (FunctionDecl *function_decl = dyn_cast(D)) - { - if (m_ast_context && - !function_decl->getNameInfo().getAsString().compare("$__lldb_expr")) + else if (FunctionDecl *function_decl = dyn_cast(D)) { - RecordPersistentTypes(function_decl); - SynthesizeFunctionResult(function_decl); + if (m_ast_context && !function_decl->getNameInfo().getAsString().compare("$__lldb_expr")) + { + RecordPersistentTypes(function_decl); + SynthesizeFunctionResult(function_decl); + } } } } @@ -365,8 +371,10 @@ ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body, 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); + if (address_of_expr.get()) + m_sema->AddInitializerToDecl(result_decl, address_of_expr.get(), true, false); + else + return false; } else { @@ -457,14 +465,66 @@ ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl *D) ConstString name_cs(name.str().c_str()); if (log) - log->Printf ("Recording persistent type %s\n", name_cs.GetCString()); + 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); + m_decls.push_back(D); +} - if (TypeDecl *TypeDecl_scratch = dyn_cast(D_scratch)) - llvm::cast(m_target.GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))->RegisterPersistentType(name_cs, TypeDecl_scratch); +void +ASTResultSynthesizer::RecordPersistentDecl(NamedDecl *D) +{ + lldbassert(m_top_level); + + if (!D->getIdentifier()) + return; + + StringRef name = D->getName(); + + if (name.size() == 0) + return; + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + ConstString name_cs(name.str().c_str()); + + if (log) + log->Printf("Recording persistent decl %s\n", name_cs.GetCString()); + + m_decls.push_back(D); +} + +void +ASTResultSynthesizer::CommitPersistentDecls() +{ + for (clang::NamedDecl *decl : m_decls) + { + StringRef name = decl->getName(); + ConstString name_cs(name.str().c_str()); + + Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl( + m_target.GetScratchClangASTContext()->getASTContext(), m_ast_context, decl); + + if (!D_scratch) + { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + { + std::string s; + llvm::raw_string_ostream ss(s); + decl->dump(ss); + ss.flush(); + + log->Printf("Couldn't commit persistent decl: %s\n", s.c_str()); + } + + continue; + } + + if (NamedDecl *NamedDecl_scratch = dyn_cast(D_scratch)) + llvm::cast(m_target.GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)) + ->RegisterPersistentDecl(name_cs, NamedDecl_scratch); + } } void diff --git a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h index 9f7bbe05b082..4556713e9933 100644 --- a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h +++ b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h @@ -41,13 +41,16 @@ public: /// pass to the next step in the chain after processing. Passthrough is /// the next ASTConsumer, or NULL if none is required. /// + /// @param[in] top_level + /// If true, register all top-level Decls and don't try to handle the + /// main function. + /// /// @param[in] target /// The target, which contains the persistent variable store and the /// AST importer. //---------------------------------------------------------------------- - ASTResultSynthesizer(clang::ASTConsumer *passthrough, - Target &target); - + ASTResultSynthesizer(clang::ASTConsumer *passthrough, bool top_level, Target &target); + //---------------------------------------------------------------------- /// Destructor //---------------------------------------------------------------------- @@ -106,11 +109,18 @@ public: /// 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; + void + ForgetSema() override; + + //---------------------------------------------------------------------- + /// The parse has succeeded, so record its persistent decls + //---------------------------------------------------------------------- + void + CommitPersistentDecls(); private: //---------------------------------------------------------------------- @@ -171,13 +181,30 @@ private: /// @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. + void + MaybeRecordPersistentType(clang::TypeDecl *D); + + //---------------------------------------------------------------------- + /// Given a NamedDecl, register it as a pointer type in the target's scratch + /// AST context. + /// + /// @param[in] Body + /// The body of the function. + //---------------------------------------------------------------------- + void + RecordPersistentDecl(clang::NamedDecl *D); + + clang::ASTContext *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. + + std::vector m_decls; ///< Persistent declarations to register assuming the expression succeeds. + + Target &m_target; ///< The target, which contains the persistent variable store and the + clang::Sema *m_sema; ///< The Sema to use. + bool m_top_level; }; } // namespace lldb_private diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index d2ea4390560a..def0d42d32dd 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -12,18 +12,20 @@ #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/ClangUtil.h" #include "lldb/Symbol/CompilerDeclContext.h" #include "lldb/Symbol/Function.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/TaggedASTType.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Target.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/RecordLayout.h" #include @@ -273,10 +275,10 @@ ClangASTSource::CompleteType (TagDecl *tag_decl) CompilerType clang_type (type->GetFullCompilerType ()); - if (!clang_type) + if (!ClangUtil::IsClangType(clang_type)) continue; - const TagType *tag_type = ClangASTContext::GetQualType(clang_type)->getAs(); + const TagType *tag_type = ClangUtil::GetQualType(clang_type)->getAs(); if (!tag_type) continue; @@ -299,7 +301,8 @@ ClangASTSource::CompleteType (TagDecl *tag_decl) const ModuleList &module_list = m_target->GetImages(); bool exact_match = false; - module_list.FindTypes (null_sc, name, exact_match, UINT32_MAX, types); + llvm::DenseSet searched_symbol_files; + module_list.FindTypes (null_sc, name, exact_match, UINT32_MAX, searched_symbol_files, types); for (uint32_t ti = 0, te = types.GetSize(); ti != te && !found; @@ -312,10 +315,10 @@ ClangASTSource::CompleteType (TagDecl *tag_decl) CompilerType clang_type (type->GetFullCompilerType ()); - if (!clang_type) + if (!ClangUtil::IsClangType(clang_type)) continue; - const TagType *tag_type = ClangASTContext::GetQualType(clang_type)->getAs(); + const TagType *tag_type = ClangUtil::GetQualType(clang_type)->getAs(); if (!tag_type) continue; @@ -705,7 +708,7 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, else { const ModuleList &target_images = m_target->GetImages(); - Mutex::Locker modules_locker (target_images.GetMutex()); + std::lock_guard guard(target_images.GetMutex()); for (size_t i = 0, e = target_images.GetSize(); i < e; ++i) { @@ -740,16 +743,17 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, do { + if (context.m_found.type) + break; + TypeList types; SymbolContext null_sc; const bool exact_match = false; - + llvm::DenseSet searched_symbol_files; 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; + m_target->GetImages().FindTypes(null_sc, name, exact_match, 1, searched_symbol_files, types); if (size_t num_types = types.GetSize()) { @@ -782,12 +786,12 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, context.AddTypeDecl(copied_clang_type); - found_a_type = true; + context.m_found.type = true; break; } } - if (!found_a_type) + if (!context.m_found.type) { // Try the modules next. @@ -832,13 +836,13 @@ ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, context.AddNamedDecl(copied_named_decl); - found_a_type = true; + context.m_found.type = true; } } } while (0); } - if (!found_a_type) + if (!context.m_found.type) { do { @@ -1378,7 +1382,7 @@ FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id, StringRef name(name_str.c_str()); IdentifierInfo &name_identifier(origin_iface_decl->getASTContext().Idents.get(name)); - DeclFromUser origin_property_decl(origin_iface_decl->FindPropertyDeclaration(&name_identifier)); + DeclFromUser origin_property_decl(origin_iface_decl->FindPropertyDeclaration(&name_identifier, ObjCPropertyQueryKind::OBJC_PR_query_instance)); bool found = false; @@ -1823,7 +1827,7 @@ ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespac else { const ModuleList &target_images = m_target->GetImages(); - Mutex::Locker modules_locker(target_images.GetMutex()); + std::lock_guard guard(target_images.GetMutex()); CompilerDeclContext null_namespace_decl; @@ -1903,7 +1907,8 @@ ClangASTSource::GuardedCopyType (const CompilerType &src_type) SetImportInProgress(true); - QualType copied_qual_type = m_ast_importer_sp->CopyType (m_ast_context, src_ast->getASTContext(), ClangASTContext::GetQualType(src_type)); + QualType copied_qual_type = + m_ast_importer_sp->CopyType(m_ast_context, src_ast->getASTContext(), ClangUtil::GetQualType(src_type)); SetImportInProgress(false); @@ -1931,14 +1936,8 @@ NameSearchContext::AddVarDecl(const CompilerType &type) clang::ASTContext *ast = lldb_ast->getASTContext(); - clang::NamedDecl *Decl = VarDecl::Create(*ast, - const_cast(m_decl_context), - SourceLocation(), - SourceLocation(), - ii, - ClangASTContext::GetQualType(type), - 0, - SC_Static); + clang::NamedDecl *Decl = VarDecl::Create(*ast, const_cast(m_decl_context), SourceLocation(), + SourceLocation(), ii, ClangUtil::GetQualType(type), 0, SC_Static); m_decls.push_back(Decl); return Decl; @@ -1961,7 +1960,7 @@ NameSearchContext::AddFunDecl (const CompilerType &type, bool extern_c) m_function_types.insert(type); - QualType qual_type (ClangASTContext::GetQualType(type)); + QualType qual_type(ClangUtil::GetQualType(type)); clang::ASTContext *ast = lldb_ast->getASTContext(); @@ -2055,9 +2054,9 @@ NameSearchContext::AddGenericFunDecl() clang::NamedDecl * NameSearchContext::AddTypeDecl(const CompilerType &clang_type) { - if (clang_type) + if (ClangUtil::IsClangType(clang_type)) { - QualType qual_type = ClangASTContext::GetQualType(clang_type); + QualType qual_type = ClangUtil::GetQualType(clang_type); if (const TypedefType *typedef_type = llvm::dyn_cast(qual_type)) { diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h index bb6384721f51..13791d7e627f 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangASTSource.h +++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h @@ -430,6 +430,8 @@ struct NameSearchContext { bool variable : 1; bool function_with_type_info : 1; bool function : 1; + bool local_vars_nsp : 1; + bool type : 1; } m_found; //------------------------------------------------------------------ diff --git a/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h b/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h new file mode 100644 index 000000000000..8273bca105cc --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangDiagnostic.h @@ -0,0 +1,60 @@ +//===-- ClangDiagnostic.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_ClangDiagnostic_h +#define lldb_ClangDiagnostic_h + +#include + +#include "clang/Basic/Diagnostic.h" + +#include "lldb/lldb-defines.h" +#include "lldb/lldb-types.h" + +#include "lldb/Expression/DiagnosticManager.h" + +namespace lldb_private +{ + + +class ClangDiagnostic : public Diagnostic +{ +public: + typedef std::vector FixItList; + + static inline bool classof(const ClangDiagnostic *) { return true; } + static inline bool classof(const Diagnostic *diag) { + return diag->getKind() == eDiagnosticOriginClang; + } + + ClangDiagnostic(const char *message, DiagnosticSeverity severity, uint32_t compiler_id) : + Diagnostic(message, severity, eDiagnosticOriginClang, compiler_id) + { + } + + virtual ~ClangDiagnostic() = default; + + bool HasFixIts () const override { return !m_fixit_vec.empty(); } + + void + AddFixitHint (const clang::FixItHint &fixit) + { + m_fixit_vec.push_back(fixit); + } + + const FixItList & + FixIts() const + { + return m_fixit_vec; + } + FixItList m_fixit_vec; +}; + +} // namespace lldb_private +#endif /* lldb_ClangDiagnostic_h */ diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index f4d6b195c7f0..7aeff6e964fe 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -57,6 +57,11 @@ using namespace lldb; using namespace lldb_private; using namespace clang; +namespace +{ + const char *g_lldb_local_vars_namespace_cstr = "$__lldb_local_vars"; +} // anonymous namespace + ClangExpressionDeclMap::ClangExpressionDeclMap (bool keep_result_in_memory, Materializer::PersistentVariableDelegate *result_delegate, ExecutionContext &exe_ctx) : @@ -510,248 +515,6 @@ ClangExpressionDeclMap::GetFunctionInfo 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; - } -} - -ConstString -FindBestAlternateMangledName -( - const ConstString &demangled, - const LanguageType &lang_type, - SymbolContext &sym_ctx -) -{ - CPlusPlusLanguage::MethodName cpp_name(demangled); - std::string scope_qualified_name = cpp_name.GetScopeQualifiedName(); - - if (!scope_qualified_name.size()) - return ConstString(); - - if (!sym_ctx.module_sp) - return ConstString(); - - SymbolVendor *sym_vendor = sym_ctx.module_sp->GetSymbolVendor(); - if (!sym_vendor) - return ConstString(); - - lldb_private::SymbolFile *sym_file = sym_vendor->GetSymbolFile(); - if (!sym_file) - return ConstString(); - - std::vector alternates; - sym_file->GetMangledNamesForFunction(scope_qualified_name, alternates); - - std::vector param_and_qual_matches; - std::vector param_matches; - for (size_t i = 0; i < alternates.size(); i++) - { - ConstString alternate_mangled_name = alternates[i]; - Mangled mangled(alternate_mangled_name, true); - ConstString demangled = mangled.GetDemangledName(lang_type); - - CPlusPlusLanguage::MethodName alternate_cpp_name(demangled); - if (!cpp_name.IsValid()) - continue; - - if (alternate_cpp_name.GetArguments() == cpp_name.GetArguments()) - { - if (alternate_cpp_name.GetQualifiers() == cpp_name.GetQualifiers()) - param_and_qual_matches.push_back(alternate_mangled_name); - else - param_matches.push_back(alternate_mangled_name); - } - } - - if (param_and_qual_matches.size()) - return param_and_qual_matches[0]; // It is assumed that there will be only one! - else if (param_matches.size()) - return param_matches[0]; // Return one of them as a best match - else - return ConstString(); -} - -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())) - { - Mangled mangled(name, true); - ConstString demangled = mangled.GetDemangledName(lang_type); - - if (demangled) - { - ConstString best_alternate_mangled_name = FindBestAlternateMangledName(demangled, lang_type, sc); - if (best_alternate_mangled_name) - { - FindCodeSymbolInContext( - best_alternate_mangled_name, m_parser_vars->m_sym_ctx, eFunctionNameTypeAuto, sc_list); - sc_list_size = sc_list.GetSize(); - } - - if (sc_list_size == 0) - { - 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; iGetAddressRange().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, @@ -1004,6 +767,24 @@ ClangExpressionDeclMap::FindGlobalVariable return VariableSP(); } +ClangASTContext * +ClangExpressionDeclMap::GetClangASTContext () +{ + StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); + if (frame == nullptr) + return nullptr; + + SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock); + if (sym_ctx.block == nullptr) + return nullptr; + + CompilerDeclContext frame_decl_context = sym_ctx.block->GetDeclContext(); + if (!frame_decl_context) + return nullptr; + + return llvm::dyn_cast_or_null(frame_decl_context.GetTypeSystem()); +} + // Interface for ClangASTSource void @@ -1039,6 +820,13 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context) if (const NamespaceDecl *namespace_context = dyn_cast(context.m_decl_context)) { + if (namespace_context->getName().str() == std::string(g_lldb_local_vars_namespace_cstr)) + { + CompilerDeclContext compiler_decl_ctx(GetClangASTContext(), const_cast(static_cast(context.m_decl_context))); + FindExternalVisibleDecls(context, lldb::ModuleSP(), compiler_decl_ctx, current_id); + return; + } + ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context); if (log && log->GetVerbose()) @@ -1078,7 +866,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context) current_id); } - if (!context.m_found.variable) + if (!context.m_found.variable && !context.m_found.local_vars_nsp) ClangASTSource::FindExternalVisibleDecls(context); } @@ -1089,6 +877,17 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, unsigned int current_id) { assert (m_ast_context); + + std::function MaybeRegisterFunctionBody = + [this](clang::FunctionDecl *copied_function_decl) + { + if (copied_function_decl->getBody() && m_parser_vars->m_code_gen) + { + DeclGroupRef decl_group_ref(copied_function_decl); + m_parser_vars->m_code_gen->HandleTopLevelDecl(decl_group_ref); + } + }; + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); @@ -1114,6 +913,52 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, SymbolContext sym_ctx; if (frame != nullptr) sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock); + + // Try the persistent decls, which take precedence over all else. + if (!namespace_decl) + { + do + { + if (!target) + break; + + 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; + + NamedDecl *persistent_decl = m_parser_vars->m_persistent_vars->GetPersistentDecl(name); + + if (!persistent_decl) + break; + + Decl *parser_persistent_decl = m_ast_importer_sp->CopyDecl(m_ast_context, scratch_ast_context, persistent_decl); + + if (!parser_persistent_decl) + break; + + NamedDecl *parser_named_decl = dyn_cast(parser_persistent_decl); + + if (!parser_named_decl) + break; + + if (clang::FunctionDecl *parser_function_decl = llvm::dyn_cast(parser_named_decl)) + { + MaybeRegisterFunctionBody(parser_function_decl); + } + + if (log) + log->Printf(" CEDM::FEVD[%u] Found persistent decl %s", current_id, name.GetCString()); + + context.AddNamedDecl(parser_named_decl); + } while (0); + } + if (name_unique_cstr[0] == '$' && !namespace_decl) { static ConstString g_lldb_class_name ("$__lldb_class"); @@ -1335,45 +1180,36 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, return; } - // any other $__lldb names should be weeded out now - if (!::strncmp(name_unique_cstr, "$__lldb", sizeof("$__lldb") - 1)) - return; - - do + if (name == ConstString(g_lldb_local_vars_namespace_cstr)) { - 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); + CompilerDeclContext frame_decl_context = sym_ctx.block != nullptr ? + sym_ctx.block->GetDeclContext() : + CompilerDeclContext(); - if (!parser_ptype_decl) - break; - - TypeDecl *parser_ptype_type_decl = dyn_cast(parser_ptype_decl); + if (frame_decl_context) + { + ClangASTContext *ast = llvm::dyn_cast_or_null(frame_decl_context.GetTypeSystem()); - if (!parser_ptype_type_decl) - break; + if (ast) + { + clang::NamespaceDecl *namespace_decl = ClangASTContext::GetUniqueNamespaceDeclaration( + m_ast_context, name_unique_cstr, nullptr); + if (namespace_decl) + { + context.AddNamedDecl(namespace_decl); + clang::DeclContext *clang_decl_ctx = clang::Decl::castToDeclContext(namespace_decl); + clang_decl_ctx->setHasExternalVisibleStorage(true); + context.m_found.local_vars_nsp = true; + } + } + } - if (log) - log->Printf(" CEDM::FEVD[%u] Found persistent type %s", current_id, name.GetCString()); + return; + } - context.AddNamedDecl(parser_ptype_type_decl); - } while (0); + // any other $__lldb names should be weeded out now + if (!::strncmp(name_unique_cstr, "$__lldb", sizeof("$__lldb") - 1)) + return; ExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariable(name)); @@ -1403,24 +1239,37 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, ValueObjectSP valobj; VariableSP var; - if (frame && !namespace_decl) + bool local_var_lookup = !namespace_decl || + (namespace_decl.GetName() == ConstString(g_lldb_local_vars_namespace_cstr)); + if (frame && local_var_lookup) { CompilerDeclContext compiler_decl_context = sym_ctx.block != nullptr ? sym_ctx.block->GetDeclContext() : CompilerDeclContext(); if (compiler_decl_context) { - // Make sure that the variables are parsed so that we have the declarations + // 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 found_decls = compiler_decl_context.FindDeclByName(name); + // Search for declarations matching the name. Do not include imported decls + // in the search if we are looking for decls in the artificial namespace + // $__lldb_local_vars. + std::vector found_decls = compiler_decl_context.FindDeclByName(name, namespace_decl.IsValid()); bool variable_found = false; for (CompilerDecl decl : found_decls) { - var = decl.GetAsVariable(); + for (size_t vi = 0, ve = vars->GetSize(); vi != ve; ++vi) + { + VariableSP candidate_var = vars->GetVariableAtIndex(vi); + if (candidate_var->GetDecl() == decl) + { + var = candidate_var; + break; + } + } + if (var) { variable_found = true; @@ -1663,9 +1512,12 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, { if (llvm::isa(decl)) { - clang::NamedDecl *copied_decl = llvm::cast(m_ast_importer_sp->CopyDecl(m_ast_context, &decl->getASTContext(), decl)); - context.AddNamedDecl(copied_decl); - context.m_found.function_with_type_info = true; + clang::NamedDecl *copied_decl = llvm::cast_or_null(m_ast_importer_sp->CopyDecl(m_ast_context, &decl->getASTContext(), decl)); + if (copied_decl) + { + context.AddNamedDecl(copied_decl); + context.m_found.function_with_type_info = true; + } } } } @@ -1726,11 +1578,7 @@ ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, 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); - } + MaybeRegisterFunctionBody(copied_function_decl); context.AddNamedDecl(copied_function_decl); @@ -2208,6 +2056,54 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, if (function) { Type *function_type = function->GetType(); + + const lldb::LanguageType comp_unit_language = function->GetCompileUnit()->GetLanguage(); + const bool extern_c = Language::LanguageIsC(comp_unit_language) || + (Language::LanguageIsObjC(comp_unit_language) && + !Language::LanguageIsCPlusPlus(comp_unit_language)); + + if (!extern_c) + { + TypeSystem *type_system = function->GetDeclContext().GetTypeSystem(); + if (ClangASTContext *src_ast = llvm::dyn_cast(type_system)) + { + clang::DeclContext *src_decl_context = (clang::DeclContext*)function->GetDeclContext().GetOpaqueDeclContext(); + clang::FunctionDecl *src_function_decl = llvm::dyn_cast_or_null(src_decl_context); + + if (src_function_decl) + { + if (clang::FunctionDecl *copied_function_decl = llvm::dyn_cast_or_null(m_ast_importer_sp->CopyDecl(m_ast_context, src_ast->getASTContext(), src_function_decl))) + { + if (log) + { + ASTDumper ast_dumper((clang::Decl*)copied_function_decl); + + StreamString ss; + + function->DumpSymbolContext(&ss); + + log->Printf(" CEDM::FEVD[%u] Imported decl for function %s (description %s), returned %s", + current_id, + copied_function_decl->getName().str().c_str(), + ss.GetData(), + ast_dumper.GetCString()); + + } + + context.AddNamedDecl(copied_function_decl); + return; + } + else + { + if (log) + { + log->Printf (" Failed to import the function decl for '%s'", + src_function_decl->getName().str().c_str()); + } + } + } + } + } if (!function_type) { @@ -2230,7 +2126,7 @@ ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, CompilerType copied_function_type = GuardedCopyType(function_clang_type); if (copied_function_type) { - function_decl = context.AddFunDecl(copied_function_type); + function_decl = context.AddFunDecl(copied_function_type, extern_c); if (!function_decl) { @@ -2329,10 +2225,10 @@ ClangExpressionDeclMap::AddThisType(NameSearchContext &context, { CompilerType copied_clang_type = GuardedCopyType(ut); + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + if (!copied_clang_type) { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - if (log) log->Printf("ClangExpressionDeclMap::AddThisType - Couldn't import the type"); @@ -2349,7 +2245,7 @@ ClangExpressionDeclMap::AddThisType(NameSearchContext &context, &void_ptr_clang_type, 1, false, - copied_clang_type.GetTypeQualifiers()); + 0); const bool is_virtual = false; const bool is_static = false; @@ -2358,7 +2254,7 @@ ClangExpressionDeclMap::AddThisType(NameSearchContext &context, const bool is_attr_used = true; const bool is_artificial = false; - ClangASTContext::GetASTContext(m_ast_context)-> + CXXMethodDecl *method_decl = ClangASTContext::GetASTContext(m_ast_context)-> AddMethodToCXXRecordType (copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", method_type, @@ -2369,6 +2265,16 @@ ClangExpressionDeclMap::AddThisType(NameSearchContext &context, is_explicit, is_attr_used, is_artificial); + + if (log) + { + ASTDumper method_ast_dumper((clang::Decl*)method_decl); + ASTDumper type_ast_dumper(copied_clang_type); + + log->Printf(" CEDM::AddThisType Added function $__lldb_expr (description %s) for this type %s", + method_ast_dumper.GetCString(), + type_ast_dumper.GetCString()); + } } if (!copied_clang_type.IsValid()) diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h index b3f890c7acc7..537db71cfeb4 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -264,25 +264,6 @@ public: 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. @@ -707,6 +688,9 @@ private: AddThisType(NameSearchContext &context, TypeFromUser &type, unsigned int current_id); + + ClangASTContext * + GetClangASTContext(); }; } // namespace lldb_private diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h index bb620def691f..bcd30ec4af2e 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h @@ -67,11 +67,14 @@ public: /// the ASTs to after transformation. //------------------------------------------------------------------ virtual clang::ASTConsumer * - ASTTransformer (clang::ASTConsumer *passthrough) = 0; - + ASTTransformer(clang::ASTConsumer *passthrough) = 0; -protected: + virtual void + CommitPersistentDecls() + { + } +protected: }; } // namespace lldb_private diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp index 72c33fec8105..d1a3c0dea825 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -11,13 +11,18 @@ // C++ Includes // Other libraries and framework includes #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ExternalASTSource.h" +#include "clang/Basic/DiagnosticIDs.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetInfo.h" -#include "clang/Basic/Version.h" +#include "clang/Basic/Version.h" #include "clang/CodeGen/CodeGenAction.h" #include "clang/CodeGen/ModuleBuilder.h" +#include "clang/Edit/Commit.h" +#include "clang/Edit/EditsReceiver.h" +#include "clang/Edit/EditedSource.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendActions.h" @@ -28,6 +33,7 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Parse/ParseAST.h" #include "clang/Rewrite/Frontend/FrontendActions.h" +#include "clang/Rewrite/Core/Rewriter.h" #include "clang/Sema/SemaConsumer.h" #include "clang/StaticAnalyzer/Frontend/FrontendActions.h" @@ -37,7 +43,11 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/TargetSelect.h" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wglobal-constructors" #include "llvm/ExecutionEngine/MCJIT.h" +#pragma clang diagnostic pop + #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Support/ErrorHandling.h" @@ -48,6 +58,7 @@ // Project includes #include "ClangExpressionParser.h" +#include "ClangDiagnostic.h" #include "ClangASTSource.h" #include "ClangExpressionHelper.h" @@ -65,17 +76,21 @@ #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" -#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Core/StringList.h" #include "lldb/Expression/IRDynamicChecks.h" +#include "lldb/Expression/IRExecutionUnit.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/Language.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Target/ThreadPlanCallFunction.h" +#include "lldb/Utility/LLDBAssert.h" using namespace clang; using namespace llvm; @@ -85,21 +100,6 @@ 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//include - llvm::sys::path::append(P, "lib", "clang", CLANG_VERSION_STRING, - "include"); - } - - return P.str(); -} class ClangExpressionParser::LLDBPreprocessorCallbacks : public PPCallbacks { @@ -154,6 +154,100 @@ public: } }; +class ClangDiagnosticManagerAdapter : public clang::DiagnosticConsumer +{ +public: + ClangDiagnosticManagerAdapter() : m_passthrough(new clang::TextDiagnosticBuffer) {} + + ClangDiagnosticManagerAdapter(const std::shared_ptr &passthrough) + : m_passthrough(passthrough) + { + } + + void + ResetManager(DiagnosticManager *manager = nullptr) + { + m_manager = manager; + } + + void + HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) + { + if (m_manager) + { + llvm::SmallVector diag_str; + Info.FormatDiagnostic(diag_str); + diag_str.push_back('\0'); + const char *data = diag_str.data(); + + lldb_private::DiagnosticSeverity severity; + bool make_new_diagnostic = true; + + switch (DiagLevel) + { + case DiagnosticsEngine::Level::Fatal: + case DiagnosticsEngine::Level::Error: + severity = eDiagnosticSeverityError; + break; + case DiagnosticsEngine::Level::Warning: + severity = eDiagnosticSeverityWarning; + break; + case DiagnosticsEngine::Level::Remark: + case DiagnosticsEngine::Level::Ignored: + severity = eDiagnosticSeverityRemark; + break; + case DiagnosticsEngine::Level::Note: + m_manager->AppendMessageToDiagnostic(data); + make_new_diagnostic = false; + } + if (make_new_diagnostic) + { + ClangDiagnostic *new_diagnostic = new ClangDiagnostic(data, severity, Info.getID()); + m_manager->AddDiagnostic(new_diagnostic); + + // Don't store away warning fixits, since the compiler doesn't have enough + // context in an expression for the warning to be useful. + // FIXME: Should we try to filter out FixIts that apply to our generated + // code, and not the user's expression? + if (severity == eDiagnosticSeverityError) + { + size_t num_fixit_hints = Info.getNumFixItHints(); + for (size_t i = 0; i < num_fixit_hints; i++) + { + const clang::FixItHint &fixit = Info.getFixItHint(i); + if (!fixit.isNull()) + new_diagnostic->AddFixitHint(fixit); + } + } + } + } + + m_passthrough->HandleDiagnostic(DiagLevel, Info); + } + + void + FlushDiagnostics(DiagnosticsEngine &Diags) + { + m_passthrough->FlushDiagnostics(Diags); + } + + DiagnosticConsumer * + clone(DiagnosticsEngine &Diags) const + { + return new ClangDiagnosticManagerAdapter(m_passthrough); + } + + clang::TextDiagnosticBuffer * + GetPassthrough() + { + return m_passthrough.get(); + } + +private: + DiagnosticManager *m_manager = nullptr; + std::shared_ptr m_passthrough; +}; + //===----------------------------------------------------------------------===// // Implementation of ClangExpressionParser //===----------------------------------------------------------------------===// @@ -166,37 +260,78 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, m_code_generator (), m_pp_callbacks(nullptr) { + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + // We can't compile expressions without a target. So if the exe_scope is null or doesn't have a target, + // then we just need to get out of here. I'll lldb_assert and not make any of the compiler objects since + // I can't return errors directly from the constructor. Further calls will check if the compiler was made and + // bag out if it wasn't. + + if (!exe_scope) + { + lldb_assert(exe_scope, "Can't make an expression parser with a null scope.", __FUNCTION__, __FILE__, __LINE__); + return; + } + + lldb::TargetSP target_sp; + target_sp = exe_scope->CalculateTarget(); + if (!target_sp) + { + lldb_assert(exe_scope, "Can't make an expression parser with a null target.", __FUNCTION__, __FILE__, __LINE__); + return; + } + // 1. Create a new compiler instance. m_compiler.reset(new CompilerInstance()); + lldb::LanguageType frame_lang = expr.Language(); // defaults to lldb::eLanguageTypeUnknown + bool overridden_target_opts = false; + lldb_private::LanguageRuntime *lang_rt = nullptr; - // 2. Install the target. + std::string abi; + ArchSpec target_arch; + target_arch = target_sp->GetArchitecture(); - lldb::TargetSP target_sp; - if (exe_scope) - target_sp = exe_scope->CalculateTarget(); + const auto target_machine = target_arch.GetMachine(); + + // If the expression is being evaluated in the context of an existing + // stack frame, we introspect to see if the language runtime is available. + + lldb::StackFrameSP frame_sp = exe_scope->CalculateStackFrame(); + lldb::ProcessSP process_sp = exe_scope->CalculateProcess(); + + // Make sure the user hasn't provided a preferred execution language + // with `expression --language X -- ...` + if (frame_sp && frame_lang == lldb::eLanguageTypeUnknown) + frame_lang = frame_sp->GetLanguage(); + + if (process_sp && frame_lang != lldb::eLanguageTypeUnknown) + { + lang_rt = process_sp->GetLanguageRuntime(frame_lang); + if (log) + log->Printf("Frame has language of type %s", Language::GetNameForLanguageType(frame_lang)); + } - // 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()) + // 2. Configure the compiler with a set of default options that are appropriate + // for most situations. + if (target_arch.IsValid()) { - std::string triple = target_sp->GetArchitecture().GetTriple().str(); + std::string triple = target_arch.GetTriple().str(); m_compiler->getTargetOpts().Triple = triple; + if (log) + log->Printf("Using %s as the target triple", m_compiler->getTargetOpts().Triple.c_str()); } else { + // If we get here we don't have a valid target and just have to guess. + // 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. In such a case the language runtime should expose an overridden options set (3), + // below. m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple(); + if (log) + log->Printf("Using default target triple of %s", m_compiler->getTargetOpts().Triple.c_str()); } - - 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"); - } - + // Now add some special fixes for known architectures: // 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 && @@ -204,17 +339,60 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, { m_compiler->getTargetOpts().ABI = "apcs-gnu"; } + // Supported subsets of x86 + if (target_machine == llvm::Triple::x86 || + target_machine == llvm::Triple::x86_64) + { + m_compiler->getTargetOpts().Features.push_back("+sse"); + m_compiler->getTargetOpts().Features.push_back("+sse2"); + } - m_compiler->createDiagnostics(); + // Set the target CPU to generate code for. + // This will be empty for any CPU that doesn't really need to make a special CPU string. + m_compiler->getTargetOpts().CPU = target_arch.GetClangTargetCPU(); - // Create the target instance. - m_compiler->setTarget(TargetInfo::CreateTargetInfo( - m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts)); + // Set the target ABI + abi = GetClangTargetABI(target_arch); + if (!abi.empty()) + m_compiler->getTargetOpts().ABI = abi; - assert (m_compiler->hasTarget()); + // 3. Now allow the runtime to provide custom configuration options for the target. + // In this case, a specialized language runtime is available and we can query it for extra options. + // For 99% of use cases, this will not be needed and should be provided when basic platform detection is not enough. + if (lang_rt) + overridden_target_opts = lang_rt->GetOverrideExprOptions(m_compiler->getTargetOpts()); + + if (overridden_target_opts) + if (log) + { + log->Debug("Using overridden target options for the expression evaluation"); + + auto opts = m_compiler->getTargetOpts(); + log->Debug("Triple: '%s'", opts.Triple.c_str()); + log->Debug("CPU: '%s'", opts.CPU.c_str()); + log->Debug("FPMath: '%s'", opts.FPMath.c_str()); + log->Debug("ABI: '%s'", opts.ABI.c_str()); + log->Debug("LinkerVersion: '%s'", opts.LinkerVersion.c_str()); + StringList::LogDump(log, opts.FeaturesAsWritten, "FeaturesAsWritten"); + StringList::LogDump(log, opts.Features, "Features"); + StringList::LogDump(log, opts.Reciprocals, "Reciprocals"); + } + + // 4. Create and install the target on the compiler. + m_compiler->createDiagnostics(); + auto target_info = TargetInfo::CreateTargetInfo(m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts); + if (log) + { + log->Printf("Using SIMD alignment: %d", target_info->getSimdDefaultAlign()); + log->Printf("Target datalayout string: '%s'", target_info->getDataLayout().getStringRepresentation().c_str()); + log->Printf("Target ABI: '%s'", target_info->getABI().str().c_str()); + log->Printf("Target vector alignment: %d", target_info->getMaxVectorAlign()); + } + m_compiler->setTarget(target_info); - // 3. Set options. + assert (m_compiler->hasTarget()); + // 5. Set language options. lldb::LanguageType language = expr.Language(); switch (language) @@ -242,7 +420,7 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, case lldb::eLanguageTypeC_plus_plus_14: m_compiler->getLangOpts().CPlusPlus11 = true; m_compiler->getHeaderSearchOpts().UseLibcxx = true; - // fall thru ... + LLVM_FALLTHROUGH; case lldb::eLanguageTypeC_plus_plus_03: m_compiler->getLangOpts().CPlusPlus = true; // FIXME: the following language option is a temporary workaround, @@ -277,10 +455,6 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, // 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()) @@ -305,9 +479,9 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, m_compiler->getCodeGenOpts().DisableFPElim = true; m_compiler->getCodeGenOpts().OmitLeafFramePointer = false; if (generate_debug_info) - m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::FullDebugInfo); + m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::FullDebugInfo); else - m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::NoDebugInfo); + m_compiler->getCodeGenOpts().setDebugInfo(codegenoptions::NoDebugInfo); // Disable some warnings. m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError, @@ -321,11 +495,11 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, // created. This complexity should be lifted elsewhere. m_compiler->getTarget().adjust(m_compiler->getLangOpts()); - // 4. Set up the diagnostic buffer for reporting errors + // 6. Set up the diagnostic buffer for reporting errors - m_compiler->getDiagnostics().setClient(new clang::TextDiagnosticBuffer); + m_compiler->getDiagnostics().setClient(new ClangDiagnosticManagerAdapter); - // 5. Set up the source management objects inside the compiler + // 7. Set up the source management objects inside the compiler clang::FileSystemOptions file_system_options; m_file_manager.reset(new clang::FileManager(file_system_options)); @@ -344,7 +518,7 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks)); } - // 6. Most of this we get from the CompilerInstance, but we + // 8. 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()); @@ -387,37 +561,38 @@ ClangExpressionParser::~ClangExpressionParser() } unsigned -ClangExpressionParser::Parse (Stream &stream) +ClangExpressionParser::Parse(DiagnosticManager &diagnostic_manager) { - TextDiagnosticBuffer *diag_buf = static_cast(m_compiler->getDiagnostics().getClient()); + ClangDiagnosticManagerAdapter *adapter = + static_cast(m_compiler->getDiagnostics().getClient()); + clang::TextDiagnosticBuffer *diag_buf = adapter->GetPassthrough(); + diag_buf->FlushDiagnostics(m_compiler->getDiagnostics()); - diag_buf->FlushDiagnostics (m_compiler->getDiagnostics()); + adapter->ResetManager(&diagnostic_manager); const char *expr_text = m_expr.Text(); - clang::SourceManager &SourceMgr = m_compiler->getSourceManager(); + clang::SourceManager &source_mgr = m_compiler->getSourceManager(); bool created_main_file = false; - if (m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo) + if (m_compiler->getCodeGenOpts().getDebugInfo() == codegenoptions::FullDebugInfo) { - std::string temp_source_path; - int temp_fd = -1; llvm::SmallString 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(); + std::string 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); + 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()) @@ -425,9 +600,8 @@ ClangExpressionParser::Parse (Stream &stream) if (bytes_written == expr_text_len) { file.Close(); - SourceMgr.setMainFileID(SourceMgr.createFileID( - m_file_manager->getFile(result_path), - SourceLocation(), SrcMgr::C_User)); + source_mgr.setMainFileID(source_mgr.createFileID(m_file_manager->getFile(result_path), + SourceLocation(), SrcMgr::C_User)); created_main_file = true; } } @@ -437,7 +611,7 @@ ClangExpressionParser::Parse (Stream &stream) if (!created_main_file) { std::unique_ptr memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__); - SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(memory_buffer))); + source_mgr.setMainFileID(source_mgr.createFileID(std::move(memory_buffer))); } diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor()); @@ -462,58 +636,147 @@ ClangExpressionParser::Parse (Stream &stream) diag_buf->EndSourceFile(); - TextDiagnosticBuffer::const_iterator diag_iterator; + unsigned num_errors = diag_buf->getNumErrors(); - int num_errors = 0; - if (m_pp_callbacks && m_pp_callbacks->hasErrors()) { num_errors++; - - stream.PutCString(m_pp_callbacks->getErrorString().c_str()); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "while importing modules:"); + diagnostic_manager.AppendMessageToDiagnostic(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()); + if (!num_errors) + { + if (type_system_helper->DeclMap() && !type_system_helper->DeclMap()->ResolveUnknownTypes()) + { + diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't infer the type of a variable"); + num_errors++; + } + } - for (diag_iterator = diag_buf->err_begin(); - diag_iterator != diag_buf->err_end(); - ++diag_iterator) + if (!num_errors) { - num_errors++; - stream.Printf("error: %s\n", (*diag_iterator).second.c_str()); + type_system_helper->CommitPersistentDecls(); } - 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()); + adapter->ResetManager(); - if (!num_errors) + return num_errors; +} + +std::string +ClangExpressionParser::GetClangTargetABI (const ArchSpec &target_arch) +{ + std::string abi; + + if(target_arch.IsMIPS()) { - if (type_system_helper->DeclMap() && !type_system_helper->DeclMap()->ResolveUnknownTypes()) + switch (target_arch.GetFlags () & ArchSpec::eMIPSABI_mask) + { + case ArchSpec::eMIPSABI_N64: + abi = "n64"; break; + case ArchSpec::eMIPSABI_N32: + abi = "n32"; break; + case ArchSpec::eMIPSABI_O32: + abi = "o32"; break; + default: + break; + } + } + return abi; +} + +bool +ClangExpressionParser::RewriteExpression(DiagnosticManager &diagnostic_manager) +{ + clang::SourceManager &source_manager = m_compiler->getSourceManager(); + clang::edit::EditedSource editor(source_manager, m_compiler->getLangOpts(), nullptr); + clang::edit::Commit commit(editor); + clang::Rewriter rewriter(source_manager, m_compiler->getLangOpts()); + + class RewritesReceiver : public edit::EditsReceiver { + Rewriter &rewrite; + + public: + RewritesReceiver(Rewriter &in_rewrite) : rewrite(in_rewrite) { } + + void insert(SourceLocation loc, StringRef text) override { + rewrite.InsertText(loc, text); + } + void replace(CharSourceRange range, StringRef text) override { + rewrite.ReplaceText(range.getBegin(), rewrite.getRangeSize(range), text); + } + }; + + RewritesReceiver rewrites_receiver(rewriter); + + const DiagnosticList &diagnostics = diagnostic_manager.Diagnostics(); + size_t num_diags = diagnostics.size(); + if (num_diags == 0) + return false; + + for (const Diagnostic *diag : diagnostic_manager.Diagnostics()) + { + const ClangDiagnostic *diagnostic = llvm::dyn_cast(diag); + if (diagnostic && diagnostic->HasFixIts()) { - stream.Printf("error: Couldn't infer the type of a variable\n"); - num_errors++; + for (const FixItHint &fixit : diagnostic->FixIts()) + { + // This is cobbed from clang::Rewrite::FixItRewriter. + if (fixit.CodeToInsert.empty()) + { + if (fixit.InsertFromRange.isValid()) + { + commit.insertFromRange(fixit.RemoveRange.getBegin(), + fixit.InsertFromRange, /*afterToken=*/false, + fixit.BeforePreviousInsertions); + } + else + commit.remove(fixit.RemoveRange); + } + else + { + if (fixit.RemoveRange.isTokenRange() || + fixit.RemoveRange.getBegin() != fixit.RemoveRange.getEnd()) + commit.replace(fixit.RemoveRange, fixit.CodeToInsert); + else + commit.insert(fixit.RemoveRange.getBegin(), fixit.CodeToInsert, + /*afterToken=*/false, fixit.BeforePreviousInsertions); + } + } } } + + // FIXME - do we want to try to propagate specific errors here? + if (!commit.isCommitable()) + return false; + else if (!editor.commit(commit)) + return false; + + // Now play all the edits, and stash the result in the diagnostic manager. + editor.applyRewrites(rewrites_receiver); + RewriteBuffer &main_file_buffer = rewriter.getEditBuffer(source_manager.getMainFileID()); - return num_errors; + std::string fixed_expression; + llvm::raw_string_ostream out_stream(fixed_expression); + + main_file_buffer.write(out_stream); + out_stream.flush(); + diagnostic_manager.SetFixedExpression(fixed_expression); + + return true; } 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) + for (const auto &func : module->getFunctionList()) { - if (fi->getName().str().find(orig_name) != std::string::npos) + const StringRef &name = func.getName(); + if (name.find(orig_name) != StringRef::npos) { - mangled_name.SetCString(fi->getName().str().c_str()); + mangled_name.SetString(name); return true; } } @@ -521,7 +784,7 @@ static bool FindFunctionInModule (ConstString &mangled_name, return false; } -Error +lldb_private::Error ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, lldb::addr_t &func_end, lldb::IRExecutionUnitSP &execution_unit_sp, @@ -533,7 +796,7 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, func_end = LLDB_INVALID_ADDRESS; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - Error err; + lldb_private::Error err; std::unique_ptr llvm_module_ap (m_code_generator->ReleaseModule()); @@ -544,26 +807,65 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, 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())) + if (execution_policy != eExecutionPolicyTopLevel) { - err.SetErrorToGenericError(); - err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName()); - return err; + // Find the actual name of the function (it's often mangled somehow) + + 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()); + } } - else + + SymbolContext sc; + + if (lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP()) + { + sc = frame_sp->GetSymbolContext(lldb::eSymbolContextEverything); + } + else if (lldb::TargetSP target_sp = exe_ctx.GetTargetSP()) + { + sc.target_sp = target_sp; + } + + LLVMUserExpression::IRPasses custom_passes; { + auto lang = m_expr.Language(); if (log) - log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName()); + log->Printf("%s - Currrent expression language is %s\n", __FUNCTION__, + Language::GetNameForLanguageType(lang)); + + if (lang != lldb::eLanguageTypeUnknown) + { + auto runtime = exe_ctx.GetProcessSP()->GetLanguageRuntime(lang); + if (runtime) + runtime->GetIRPasses(custom_passes); + } + } + + if (custom_passes.EarlyPasses) + { + if (log) + log->Printf("%s - Running Early IR Passes from LanguageRuntime on expression module '%s'", __FUNCTION__, + m_expr.FunctionName()); + + custom_passes.EarlyPasses->run(*llvm_module_ap); } execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here llvm_module_ap, // handed off here function_name, exe_ctx.GetTargetSP(), + sc, m_compiler->getTargetOpts().Features)); ClangExpressionHelper *type_system_helper = dyn_cast(m_expr.GetTypeSystemHelper()); @@ -576,20 +878,28 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, if (target) error_stream = target->GetDebugger().GetErrorFile().get(); - IRForTarget ir_for_target(decl_map, - m_expr.NeedsVariableResolution(), - *execution_unit_sp, - error_stream, + 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 (execution_policy != eExecutionPolicyAlways && execution_policy != eExecutionPolicyTopLevel) + { + lldb_private::Error interpret_error; + + 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 (!can_interpret && execution_policy == eExecutionPolicyNever) + { + err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString()); + return err; + } + } if (!ir_can_run) { @@ -597,19 +907,21 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, return err; } - if (!can_interpret && execution_policy == eExecutionPolicyNever) + if (!process && execution_policy == eExecutionPolicyAlways) { - err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString()); + err.SetErrorString("Expression needed to run in the target, but the target can't be run"); return err; } - if (!process && execution_policy == eExecutionPolicyAlways) + if (!process && execution_policy == eExecutionPolicyTopLevel) { - err.SetErrorString("Expression needed to run in the target, but the target can't be run"); + err.SetErrorString( + "Top-level code needs to be inserted into a runnable target, but the target can't be run"); return err; } - if (execution_policy == eExecutionPolicyAlways || !can_interpret) + if (execution_policy == eExecutionPolicyAlways || + (execution_policy != eExecutionPolicyTopLevel && !can_interpret)) { if (m_expr.NeedsValidation() && process) { @@ -617,14 +929,14 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, { DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions(); - StreamString install_errors; + DiagnosticManager install_diagnostics; - if (!dynamic_checkers->Install(install_errors, exe_ctx)) + if (!dynamic_checkers->Install(install_diagnostics, exe_ctx)) { - if (install_errors.GetString().empty()) - err.SetErrorString ("couldn't install checkers, unknown error"); + if (install_diagnostics.Diagnostics().size()) + err.SetErrorString("couldn't install checkers, unknown error"); else - err.SetErrorString (install_errors.GetString().c_str()); + err.SetErrorString(install_diagnostics.GetString().c_str()); return err; } @@ -637,14 +949,28 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString()); - if (!ir_dynamic_checks.runOnModule(*execution_unit_sp->GetModule())) + llvm::Module *module = execution_unit_sp->GetModule(); + if (!module || !ir_dynamic_checks.runOnModule(*module)) { err.SetErrorToGenericError(); err.SetErrorString("Couldn't add dynamic checks to the expression"); return err; } + + if (custom_passes.LatePasses) + { + if (log) + log->Printf("%s - Running Late IR Passes from LanguageRuntime on expression module '%s'", + __FUNCTION__, m_expr.FunctionName()); + + custom_passes.LatePasses->run(*module); + } } + } + if (execution_policy == eExecutionPolicyAlways || execution_policy == eExecutionPolicyTopLevel || + !can_interpret) + { execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); } } @@ -655,3 +981,51 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, return err; } + +lldb_private::Error +ClangExpressionParser::RunStaticInitializers (lldb::IRExecutionUnitSP &execution_unit_sp, + ExecutionContext &exe_ctx) +{ + lldb_private::Error err; + + lldbassert(execution_unit_sp.get()); + lldbassert(exe_ctx.HasThreadScope()); + + if (!execution_unit_sp.get()) + { + err.SetErrorString ("can't run static initializers for a NULL execution unit"); + return err; + } + + if (!exe_ctx.HasThreadScope()) + { + err.SetErrorString ("can't run static initializers without a thread"); + return err; + } + + std::vector static_initializers; + + execution_unit_sp->GetStaticInitializers(static_initializers); + + for (lldb::addr_t static_initializer : static_initializers) + { + EvaluateExpressionOptions options; + + lldb::ThreadPlanSP call_static_initializer(new ThreadPlanCallFunction(exe_ctx.GetThreadRef(), + Address(static_initializer), + CompilerType(), + llvm::ArrayRef(), + options)); + + DiagnosticManager execution_errors; + lldb::ExpressionResults results = exe_ctx.GetThreadRef().GetProcess()->RunThreadPlan(exe_ctx, call_static_initializer, options, execution_errors); + + if (results != lldb::eExpressionCompleted) + { + err.SetErrorStringWithFormat ("couldn't run static initializer: %s", execution_errors.GetString().c_str()); + return err; + } + } + + return err; +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h index 3c055380b839..34c0212b73a4 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h @@ -10,11 +10,12 @@ #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/DiagnosticManager.h" #include "lldb/Expression/ExpressionParser.h" +#include "lldb/lldb-public.h" #include #include @@ -63,16 +64,19 @@ public: /// 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. + /// @param[in] diagnostic_manager + /// The diagnostic manager to report errors to. /// /// @return /// The number of errors encountered during parsing. 0 means /// success. //------------------------------------------------------------------ unsigned - Parse (Stream &stream) override; + Parse(DiagnosticManager &diagnostic_manager) override; + bool + RewriteExpression(DiagnosticManager &diagnostic_manager) override; + //------------------------------------------------------------------ /// Ready an already-parsed expression for execution, possibly /// evaluating it statically. @@ -98,7 +102,7 @@ public: /// /// @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 has no side effects, this is set to the result of the /// expression. /// /// @param[in] execution_policy @@ -117,7 +121,35 @@ public: ExecutionContext &exe_ctx, bool &can_interpret, lldb_private::ExecutionPolicy execution_policy) override; - + + //------------------------------------------------------------------ + /// Run all static initializers for an execution unit. + /// + /// @param[in] execution_unit_sp + /// The execution unit. + /// + /// @param[in] exe_ctx + /// The execution context to use when running them. Thread can't be null. + /// + /// @return + /// The error code indicating the + //------------------------------------------------------------------ + Error + RunStaticInitializers (lldb::IRExecutionUnitSP &execution_unit_sp, + ExecutionContext &exe_ctx); + + //------------------------------------------------------------------ + /// Returns a string representing current ABI. + /// + /// @param[in] target_arch + /// The target architecture. + /// + /// @return + /// A string representing target ABI for the current architecture. + //------------------------------------------------------------------- + std::string + GetClangTargetABI (const ArchSpec &target_arch); + private: std::unique_ptr m_llvm_context; ///< The LLVM context to generate IR into std::unique_ptr m_file_manager; ///< The Clang file manager object used by the compiler diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp index 0d0d7475a00e..02c0ad5013ec 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp @@ -74,10 +74,15 @@ ClangFunctionCaller::~ClangFunctionCaller() } unsigned -ClangFunctionCaller::CompileFunction (Stream &errors) + +ClangFunctionCaller::CompileFunction (lldb::ThreadSP thread_to_use_sp, + DiagnosticManager &diagnostic_manager) { if (m_compiled) return 0; + + // Compilation might call code, make sure to keep on the thread the caller indicated. + ThreadList::ExpressionExecutionThreadPusher execution_thread_pusher(thread_to_use_sp); // FIXME: How does clang tell us there's no return value? We need to handle that case. unsigned num_errors = 0; @@ -143,8 +148,9 @@ ClangFunctionCaller::CompileFunction (Stream &errors) type_name = clang_qual_type.GetTypeName().AsCString(""); } else - { - errors.Printf("Could not determine type of input value %" PRIu64 ".", (uint64_t)i); + { + diagnostic_manager.Printf(eDiagnosticSeverityError, + "Could not determine type of input value %" PRIu64 ".", (uint64_t)i); return 1; } } @@ -195,15 +201,15 @@ ClangFunctionCaller::CompileFunction (Stream &errors) { 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); + + num_errors = m_parser->Parse(diagnostic_manager); } else { - errors.Printf("no process - unable to inject function"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "no process - unable to inject function"); num_errors = 1; } - + m_compiled = (num_errors == 0); if (!m_compiled) diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h index 3e30f818a932..468b9c1c76dc 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h +++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h @@ -137,17 +137,23 @@ public: //------------------------------------------------------------------ /// Compile the wrapper function /// - /// @param[in] errors - /// The stream to print parser errors to. + /// @param[in] thread_to_use_sp + /// Compilation might end up calling functions. Pass in the thread you + /// want the compilation to use. If you pass in an empty ThreadSP it will + /// use the currently selected thread. + /// + /// @param[in] diagnostic_manager + /// The diagnostic manager to report parser errors to. /// /// @return /// The number of errors. //------------------------------------------------------------------ unsigned - CompileFunction (Stream &errors) override; - + CompileFunction (lldb::ThreadSP thread_to_use_sp, + DiagnosticManager &diagnostic_manager) override; + ExpressionTypeSystemHelper * - GetTypeSystemHelper () override + GetTypeSystemHelper() override { return &m_type_system_helper; } diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp index 05d8a320a5a4..63a3a85bacb4 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -585,6 +585,7 @@ ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVec break; case clang::tok::TokenKind::raw_identifier: macro_expansion.append(ti->getRawIdentifier().str()); + break; default: macro_expansion.append(ti->getName()); break; @@ -627,7 +628,9 @@ ClangModulesDeclVendor::Create(Target &target) std::vector compiler_invocation_arguments = { + "clang", "-fmodules", + "-fimplicit-module-maps", "-fcxx-modules", "-fsyntax-only", "-femit-all-decls", diff --git a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp index 9bf9d435d7ea..d1478e49bff5 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp @@ -14,6 +14,8 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/Value.h" +#include "clang/AST/Decl.h" + #include "llvm/ADT/StringMap.h" using namespace lldb; @@ -66,18 +68,26 @@ ClangPersistentVariables::GetNextPersistentVariableName () } void -ClangPersistentVariables::RegisterPersistentType (const ConstString &name, - clang::TypeDecl *type_decl) +ClangPersistentVariables::RegisterPersistentDecl (const ConstString &name, + clang::NamedDecl *decl) { - m_persistent_types.insert(std::pair(name.GetCString(), type_decl)); + m_persistent_decls.insert(std::pair(name.GetCString(), decl)); + + if (clang::EnumDecl *enum_decl = llvm::dyn_cast(decl)) + { + for (clang::EnumConstantDecl *enumerator_decl : enum_decl->enumerators()) + { + m_persistent_decls.insert(std::pair(ConstString(enumerator_decl->getNameAsString()).GetCString(), enumerator_decl)); + } + } } -clang::TypeDecl * -ClangPersistentVariables::GetPersistentType (const ConstString &name) +clang::NamedDecl * +ClangPersistentVariables::GetPersistentDecl (const ConstString &name) { - PersistentTypeMap::const_iterator i = m_persistent_types.find(name.GetCString()); + PersistentDeclMap::const_iterator i = m_persistent_decls.find(name.GetCString()); - if (i == m_persistent_types.end()) + if (i == m_persistent_decls.end()) return NULL; else return i->second; diff --git a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h index 0e03d013d049..2928976592d8 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h +++ b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h @@ -70,15 +70,12 @@ public: 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); + RegisterPersistentDecl (const ConstString &name, + clang::NamedDecl *decl); - clang::TypeDecl * - GetPersistentType (const ConstString &name); + clang::NamedDecl * + GetPersistentDecl (const ConstString &name); void AddHandLoadedClangModule(ClangModulesDeclVendor::ModuleID module) @@ -94,8 +91,8 @@ public: private: uint32_t m_next_persistent_variable_id; ///< The counter used by GetNextResultName(). - typedef llvm::DenseMap PersistentTypeMap; - PersistentTypeMap m_persistent_types; ///< The persistent types declared by the user. + typedef llvm::DenseMap PersistentDeclMap; + PersistentDeclMap m_persistent_decls; ///< Persistent entities 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. diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 11f7f84ff5f1..52d49aecec9a 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -23,8 +23,10 @@ #include "ClangExpressionParser.h" #include "ClangModulesDeclVendor.h" #include "ClangPersistentVariables.h" +#include "ClangDiagnostic.h" #include "lldb/Core/ConstString.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/StreamFile.h" @@ -55,28 +57,25 @@ 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()) +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(), options.GetExecutionPolicy() == eExecutionPolicyTopLevel) { 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; + 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; } } @@ -326,11 +325,9 @@ ApplyObjcCastHack(std::string &expr) } bool -ClangUserExpression::Parse (Stream &error_stream, - ExecutionContext &exe_ctx, - lldb_private::ExecutionPolicy execution_policy, - bool keep_result_in_memory, - bool generate_debug_info) +ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, 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)); @@ -346,13 +343,13 @@ ClangUserExpression::Parse (Stream &error_stream, } else { - error_stream.PutCString ("error: couldn't start parsing (no persistent data)"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "couldn't start parsing (no persistent data)"); return false; } } else { - error_stream.PutCString ("error: couldn't start parsing (no target)"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "error: couldn't start parsing (no target)"); return false; } @@ -360,11 +357,9 @@ ClangUserExpression::Parse (Stream &error_stream, if (!err.Success()) { - error_stream.Printf("warning: %s\n", err.AsCString()); + diagnostic_manager.PutCString(eDiagnosticSeverityWarning, err.AsCString()); } - StreamString m_transformed_stream; - //////////////////////////////////// // Generate the expression // @@ -404,22 +399,30 @@ ClangUserExpression::Parse (Stream &error_stream, } } } - - std::unique_ptr 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; + lldb::LanguageType lang_type = lldb::eLanguageTypeUnknown; - if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_in_static_method, exe_ctx)) + if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) { - error_stream.PutCString ("error: couldn't construct expression body"); - return false; + m_transformed_text = m_expr_text; + } + else + { + std::unique_ptr source_code( + ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str())); + + 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_in_static_method, exe_ctx)) + { + diagnostic_manager.PutCString(eDiagnosticSeverityError, "couldn't construct expression body"); + return false; + } } if (log) @@ -433,7 +436,7 @@ ClangUserExpression::Parse (Stream &error_stream, if (!target) { - error_stream.PutCString ("error: invalid target\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid target"); return false; } @@ -467,26 +470,47 @@ ClangUserExpression::Parse (Stream &error_stream, if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) { - error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "current process state is unsuitable for expression parsing"); ResetDeclMap(); // We are being careful here in the case of breakpoint conditions. return false; } + if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) + { + DeclMap()->SetLookupsEnabled(true); + } + Process *process = exe_ctx.GetProcessPtr(); ExecutionContextScope *exe_scope = process; if (!exe_scope) exe_scope = exe_ctx.GetTargetPtr(); + // We use a shared pointer here so we can use the original parser - if it succeeds + // or the rewrite parser we might make if it fails. But the parser_sp will never be empty. + ClangExpressionParser parser(exe_scope, *this, generate_debug_info); - unsigned num_errors = parser.Parse (error_stream); + unsigned num_errors = parser.Parse(diagnostic_manager); + // Check here for FixItHints. If there are any try to apply the fixits and set the fixed text in m_fixed_text + // before returning an error. if (num_errors) { - error_stream.Printf ("error: %d errors parsing expression\n", num_errors); + if (diagnostic_manager.HasFixIts()) + { + if (parser.RewriteExpression(diagnostic_manager)) + { + size_t fixed_start; + size_t fixed_end; + const std::string &fixed_expression = diagnostic_manager.GetFixedExpression(); + if (ExpressionSourceCode::GetOriginalBodyBounds(fixed_expression, lang_type, fixed_start, fixed_end)) + m_fixed_text = fixed_expression.substr(fixed_start, fixed_end - fixed_start); + } + } ResetDeclMap(); // We are being careful here in the case of breakpoint conditions. @@ -497,16 +521,70 @@ ClangUserExpression::Parse (Stream &error_stream, // 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); + { + 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 (!jit_error.Success()) + { + const char *error_cstr = jit_error.AsCString(); + if (error_cstr && error_cstr[0]) + diagnostic_manager.PutCString(eDiagnosticSeverityError, error_cstr); + else + diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression can't be interpreted or run"); + return false; + } + } + + if (exe_ctx.GetProcessPtr() && execution_policy == eExecutionPolicyTopLevel) + { + Error static_init_error = parser.RunStaticInitializers(m_execution_unit_sp, exe_ctx); + + if (!static_init_error.Success()) + { + const char *error_cstr = static_init_error.AsCString(); + if (error_cstr && error_cstr[0]) + diagnostic_manager.Printf(eDiagnosticSeverityError, "couldn't run static initializers: %s\n", + error_cstr); + else + diagnostic_manager.PutCString(eDiagnosticSeverityError, "couldn't run static initializers\n"); + return false; + } + } + + if (m_execution_unit_sp) + { + bool register_execution_unit = false; + + if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) + { + register_execution_unit = true; + } + + // If there is more than one external function in the execution + // unit, it needs to keep living even if it's not top level, because + // the result could refer to that function. + + if (m_execution_unit_sp->GetJittedFunctions().size() > 1) + { + register_execution_unit = true; + } + + if (register_execution_unit) + { + llvm::cast( + exe_ctx.GetTargetPtr()->GetPersistentExpressionStateForLanguage(m_language)) + ->RegisterExecutionUnit(m_execution_unit_sp); + } + } if (generate_debug_info) { - lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule()); + lldb::ModuleSP jit_module_sp(m_execution_unit_sp->GetJITModule()); if (jit_module_sp) { @@ -517,52 +595,23 @@ ClangUserExpression::Parse (Stream &error_stream, 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. + 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; - } + if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS) + m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); + return true; } bool -ClangUserExpression::AddArguments (ExecutionContext &exe_ctx, - std::vector &args, - lldb::addr_t struct_address, - Stream &error_stream) +ClangUserExpression::AddArguments(ExecutionContext &exe_ctx, std::vector &args, + lldb::addr_t struct_address, DiagnosticManager &diagnostic_manager) { lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS; - lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS; - + lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS; + if (m_needs_object_ptr) { lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP(); @@ -581,7 +630,7 @@ ClangUserExpression::AddArguments (ExecutionContext &exe_ctx, } else { - error_stream.Printf("Need object pointer but don't know the language\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "need object pointer but don't know the language"); return false; } @@ -591,7 +640,7 @@ ClangUserExpression::AddArguments (ExecutionContext &exe_ctx, if (!object_ptr_error.Success()) { - error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); + exe_ctx.GetTargetRef().GetDebugger().GetAsyncOutputStream()->Printf("warning: `%s' is not accessible (subsituting 0)\n", object_name.AsCString()); object_ptr = 0; } @@ -603,12 +652,14 @@ ClangUserExpression::AddArguments (ExecutionContext &exe_ctx, if (!object_ptr_error.Success()) { - error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); + diagnostic_manager.Printf(eDiagnosticSeverityWarning, + "couldn't get cmd pointer (substituting NULL): %s", + object_ptr_error.AsCString()); cmd_ptr = 0; } } - if (object_ptr) - args.push_back(object_ptr); + + args.push_back(object_ptr); if (m_in_objectivec_method) args.push_back(cmd_ptr); @@ -635,14 +686,22 @@ ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(ExecutionContext &e } clang::ASTConsumer * -ClangUserExpression::ClangUserExpressionHelper::ASTTransformer (clang::ASTConsumer *passthrough) +ClangUserExpression::ClangUserExpressionHelper::ASTTransformer(clang::ASTConsumer *passthrough) { - m_result_synthesizer_up.reset(new ASTResultSynthesizer(passthrough, - m_target)); + m_result_synthesizer_up.reset(new ASTResultSynthesizer(passthrough, m_top_level, m_target)); return m_result_synthesizer_up.get(); } +void +ClangUserExpression::ClangUserExpressionHelper::CommitPersistentDecls() +{ + if (m_result_synthesizer_up.get()) + { + m_result_synthesizer_up->CommitPersistentDecls(); + } +} + ClangUserExpression::ResultDelegate::ResultDelegate() { } diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h index f2bfe31dce09..6077588b0244 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -51,13 +51,10 @@ public: class ClangUserExpressionHelper : public ClangExpressionHelper { public: - ClangUserExpressionHelper (Target &target) : - m_target(target) - { - } - + ClangUserExpressionHelper(Target &target, bool top_level) : m_target(target), m_top_level(top_level) {} + ~ClangUserExpressionHelper() override = default; - + //------------------------------------------------------------------ /// Return the object that the parser should use when resolving external /// values. May be NULL if everything should be self-contained. @@ -88,11 +85,16 @@ public: clang::ASTConsumer * ASTTransformer(clang::ASTConsumer *passthrough) override; + void + CommitPersistentDecls() override; + private: - Target &m_target; + Target &m_target; std::unique_ptr m_expr_decl_map_up; - std::unique_ptr m_struct_extractor_up; ///< The class that generates the argument struct layout. + std::unique_ptr + m_struct_extractor_up; ///< The class that generates the argument struct layout. std::unique_ptr m_result_synthesizer_up; + bool m_top_level; }; //------------------------------------------------------------------ @@ -126,8 +128,8 @@ public: //------------------------------------------------------------------ /// Parse the expression /// - /// @param[in] error_stream - /// A stream to print parse errors and warnings to. + /// @param[in] diagnostic_manager + /// A diagnostic manager to report parse errors and warnings to. /// /// @param[in] exe_ctx /// The execution context to use when looking up entities that @@ -145,11 +147,9 @@ public: /// 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; + Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, + bool generate_debug_info) override; ExpressionTypeSystemHelper * GetTypeSystemHelper () override @@ -188,13 +188,11 @@ private: lldb_private::Error &err) override; bool - AddArguments (ExecutionContext &exe_ctx, - std::vector &args, - lldb::addr_t struct_address, - Stream &error_stream) override; - - ClangUserExpressionHelper m_type_system_helper; - + AddArguments(ExecutionContext &exe_ctx, std::vector &args, lldb::addr_t struct_address, + DiagnosticManager &diagnostic_manager) override; + + ClangUserExpressionHelper m_type_system_helper; + class ResultDelegate : public Materializer::PersistentVariableDelegate { public: diff --git a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp index fe044c17ac78..727e4b3329b3 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp +++ b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -55,8 +55,8 @@ ClangUtilityFunction::~ClangUtilityFunction () //------------------------------------------------------------------ /// Install the utility function into a process /// -/// @param[in] error_stream -/// A stream to print parse errors and warnings to. +/// @param[in] diagnostic_manager +/// A diagnostic manager to report errors and warnings to. /// /// @param[in] exe_ctx /// The execution context to install the utility function to. @@ -65,35 +65,34 @@ ClangUtilityFunction::~ClangUtilityFunction () /// True on success (no errors); false otherwise. //------------------------------------------------------------------ bool -ClangUtilityFunction::Install (Stream &error_stream, - ExecutionContext &exe_ctx) +ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) { if (m_jit_start_addr != LLDB_INVALID_ADDRESS) { - error_stream.PutCString("error: already installed\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityWarning, "already installed"); return false; } - + //////////////////////////////////// // Set up the target and compiler // Target *target = exe_ctx.GetTargetPtr(); - + if (!target) { - error_stream.PutCString ("error: invalid target\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid target"); return false; } - + Process *process = exe_ctx.GetProcessPtr(); - + if (!process) { - error_stream.PutCString ("error: invalid process\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid process"); return false; } - + ////////////////////////// // Parse the expression // @@ -101,24 +100,23 @@ ClangUtilityFunction::Install (Stream &error_stream, 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"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "current process state is unsuitable for expression parsing"); return false; } - + const bool generate_debug_info = true; ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info); - - unsigned num_errors = parser.Parse (error_stream); - + + unsigned num_errors = parser.Parse(diagnostic_manager); + if (num_errors) { - error_stream.Printf ("error: %d errors parsing expression\n", num_errors); - ResetDeclMap(); - + return false; } @@ -175,9 +173,13 @@ ClangUtilityFunction::Install (Stream &error_stream, { const char *error_cstr = jit_error.AsCString(); if (error_cstr && error_cstr[0]) - error_stream.Printf ("error: %s\n", error_cstr); + { + diagnostic_manager.Printf(eDiagnosticSeverityError, "%s", error_cstr); + } else - error_stream.Printf ("error: expression can't be interpreted or run\n"); + { + diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression can't be interpreted or run"); + } return false; } } diff --git a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h index 74839717946b..d4ed37eee049 100644 --- a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h +++ b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h @@ -124,12 +124,12 @@ public: { m_type_system_helper.ResetDeclMap(exe_ctx, keep_result_in_memory); } - + bool - Install (Stream &error_stream, ExecutionContext &exe_ctx) override; - + Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) override; + private: - ClangUtilityFunctionHelper m_type_system_helper; ///< The map to use when parsing and materializing the expression. + ClangUtilityFunctionHelper m_type_system_helper; ///< The map to use when parsing and materializing the expression. }; } // namespace lldb_private diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp index 509c594280a0..12ba7e3c2ac0 100644 --- a/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp +++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp @@ -25,16 +25,17 @@ #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/Core/dwarf.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRInterpreter.h" #include "lldb/Host/Endian.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ClangUtil.h" #include "lldb/Symbol/CompilerType.h" #include @@ -43,13 +44,6 @@ 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() @@ -72,28 +66,6 @@ IRForTarget::FunctionValueCache::GetValue(llvm::Function *function) 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) { @@ -113,11 +85,11 @@ IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map, 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_execution_unit(execution_unit), m_result_store(NULL), m_result_is_pointer(false), m_reloc_placeholder(NULL), @@ -163,213 +135,9 @@ 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 alternates; - bool found_it = m_decl_map->GetFunctionAddress (name, fun_addr); - - 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(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(u)) { - call->removeAttribute(AttributeSet::FunctionIndex, builtin); - } - } - } - - fun->replaceAllUsesWith(value); - } - break; - } - } - return true; } - clang::NamedDecl * IRForTarget::DeclForGlobal (const GlobalValue *global_val, Module *module) { @@ -572,7 +340,7 @@ IRForTarget::CreateResultVariable (llvm::Function &llvm_function) } - lldb::TargetSP target_sp (m_data_allocator.GetTarget()); + lldb::TargetSP target_sp (m_execution_unit.GetTarget()); lldb_private::ExecutionContext exe_ctx (target_sp, true); if (m_result_type.GetBitSize(exe_ctx.GetBestExecutionContextScope()) == 0) { @@ -704,7 +472,8 @@ IRForTarget::RewriteObjCConstString (llvm::GlobalVariable *ns_str, static lldb_private::ConstString g_CFStringCreateWithBytes_str ("CFStringCreateWithBytes"); - if (!m_decl_map->GetFunctionAddress (g_CFStringCreateWithBytes_str, CFStringCreateWithBytes_addr)) + CFStringCreateWithBytes_addr = m_execution_unit.FindSymbol (g_CFStringCreateWithBytes_str); + if (CFStringCreateWithBytes_addr == LLDB_INVALID_ADDRESS) { if (log) log->PutCString("Couldn't find CFStringCreateWithBytes in the target"); @@ -1093,7 +862,8 @@ IRForTarget::RewriteObjCSelector (Instruction* selector_load) 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)) + sel_registerName_addr = m_execution_unit.FindSymbol (g_sel_registerName_str); + if (sel_registerName_addr == LLDB_INVALID_ADDRESS) return false; if (log) @@ -1335,7 +1105,13 @@ IRForTarget::MaterializeInitializer (uint8_t *data, Constant *initializer) if (ConstantInt *int_initializer = dyn_cast(initializer)) { - memcpy (data, int_initializer->getValue().getRawData(), m_target_data->getTypeStoreSize(initializer_type)); + size_t constant_size = m_target_data->getTypeStoreSize(initializer_type); + lldb_private::Scalar scalar = int_initializer->getValue().zextOrTrunc(llvm::NextPowerOf2(constant_size) * 8); + + lldb_private::Error get_data_error; + if (!scalar.GetAsMemoryData(data, constant_size, lldb_private::endian::InlHostByteOrder(), get_data_error)) + return false; + return true; } else if (ConstantDataArray *array_initializer = dyn_cast(initializer)) @@ -1388,48 +1164,6 @@ IRForTarget::MaterializeInitializer (uint8_t *data, Constant *initializer) 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) @@ -1455,7 +1189,7 @@ IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr) else if (GlobalVariable *global_variable = dyn_cast(llvm_value_ptr)) { if (!GlobalValue::isExternalLinkage(global_variable->getLinkage())) - return MaterializeInternalVariable(global_variable); + return true; clang::NamedDecl *named_decl = DeclForGlobal(global_variable); @@ -1508,11 +1242,8 @@ IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr) 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); + name.c_str(), lldb_private::ClangUtil::GetQualType(compiler_type).getAsString().c_str(), + PrintType(value_type).c_str(), value_size, value_alignment); } @@ -1524,10 +1255,8 @@ IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr) { if (!global_variable->hasExternalLinkage()) return true; - else if (HandleSymbol (global_variable)) - return true; else - return false; + return true; } } else if (dyn_cast(llvm_value_ptr)) @@ -1783,231 +1512,6 @@ IRForTarget::ResolveExternals (Function &llvm_function) return true; } -bool -IRForTarget::ReplaceStrings () -{ - lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - typedef std::map 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(gc_type); - - if (!gc_array_type) - continue; - - Type *gc_element_type = gc_array_type->getElementType(); - - IntegerType *gc_integer_type = dyn_cast(gc_element_type); - - if (gc_integer_type->getBitWidth() != 8) - continue; - - str = ""; - } - else - { - ConstantDataArray *gc_array = dyn_cast(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(u); - StoreInst *store_inst = dyn_cast(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 ConstantList; - typedef SmallVector 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(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(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; @@ -2436,79 +1940,6 @@ IRForTarget::BuildRelocation(llvm::Type *type, uint64_t offset) 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 global_vars; - std::seterased_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) { @@ -2530,25 +1961,29 @@ IRForTarget::runOnModule (Module &llvm_module) 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())); + Function *const main_function = m_func_name.IsEmpty() ? nullptr : m_module->getFunction(m_func_name.GetStringRef()); - if (!main_function) + if (!m_func_name.IsEmpty() && !main_function) { if (log) - log->Printf("Couldn't find \"%s()\" in the module", m_func_name.c_str()); + log->Printf("Couldn't find \"%s()\" in the module", m_func_name.AsCString()); if (m_error_stream) - m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find wrapper '%s' in the module", m_func_name.c_str()); + m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find wrapper '%s' in the module", + m_func_name.AsCString()); return false; } - if (!FixFunctionLinkage (*main_function)) + if (main_function) { - if (log) - log->Printf("Couldn't fix the linkage for the function"); + if (!FixFunctionLinkage(*main_function)) + { + if (log) + log->Printf("Couldn't fix the linkage for the function"); - return false; + return false; + } } llvm::Type *int8_ty = Type::getInt8Ty(m_module->getContext()); @@ -2567,14 +2002,17 @@ IRForTarget::runOnModule (Module &llvm_module) // Replace $__lldb_expr_result with a persistent variable // - if (!CreateResultVariable(*main_function)) + if (main_function) { - if (log) - log->Printf("CreateResultVariable() failed"); + if (!CreateResultVariable(*main_function)) + { + if (log) + log->Printf("CreateResultVariable() failed"); - // CreateResultVariable() reports its own errors, so we don't do so here + // CreateResultVariable() reports its own errors, so we don't do so here - return false; + return false; + } } if (log && log->GetVerbose()) @@ -2650,20 +2088,6 @@ IRForTarget::runOnModule (Module &llvm_module) 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) @@ -2705,14 +2129,6 @@ IRForTarget::runOnModule (Module &llvm_module) return false; } - - if (!ReplaceStaticLiterals(*bbi)) - { - if (log) - log->Printf("ReplaceStaticLiterals() failed"); - - return false; - } } } @@ -2720,46 +2136,27 @@ IRForTarget::runOnModule (Module &llvm_module) // 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 (main_function) { - if (log) - log->Printf("ReplaceVariables() failed"); - - // ReplaceVariables() reports its own errors, so we don't do so here - - return false; - } + if (!ResolveExternals(*main_function)) + { + if (log) + log->Printf("ResolveExternals() failed"); - if (!ReplaceStrings()) - { - if (log) - log->Printf("ReplaceStrings() failed"); + // ResolveExternals() reports its own errors, so we don't do so here - return false; - } + return false; + } - if (!CompleteDataAllocation()) - { - if (log) - log->Printf("CompleteDataAllocation() failed"); + if (!ReplaceVariables(*main_function)) + { + if (log) + log->Printf("ReplaceVariables() failed"); - return false; - } + // ReplaceVariables() reports its own errors, so we don't do so here - if (!StripAllGVs(llvm_module)) - { - if (log) - log->Printf("StripAllGVs() failed"); + return false; + } } if (log && log->GetVerbose()) diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.h b/source/Plugins/ExpressionParser/Clang/IRForTarget.h index fb4abcc103de..0f95f67babfd 100644 --- a/source/Plugins/ExpressionParser/Clang/IRForTarget.h +++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.h @@ -213,40 +213,6 @@ private: 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. @@ -564,38 +530,6 @@ private: 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 @@ -612,73 +546,45 @@ private: /// @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(); + ReplaceVariables(llvm::Function &llvm_function); - 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 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 + bool m_resolve_vars; ///< True if external variable references and persistent variable references should be resolved + lldb_private::ConstString 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 + 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 + 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 + lldb_private::IRExecutionUnit &m_execution_unit; ///< The execution unit containing the IR being created. + + 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. /// @@ -688,7 +594,7 @@ private: /// @return /// True on success; false otherwise //------------------------------------------------------------------ - + class FunctionValueCache { public: typedef std::function Maker; diff --git a/source/Plugins/ExpressionParser/Clang/Makefile b/source/Plugins/ExpressionParser/Clang/Makefile deleted file mode 100644 index eb592daabb48..000000000000 --- a/source/Plugins/ExpressionParser/Clang/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ExpressionParser/Clang ---------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginExpressionParserClang -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ExpressionParser/Go/GoAST.h b/source/Plugins/ExpressionParser/Go/GoAST.h index 6d51240eab5c..89836a38acb0 100644 --- a/source/Plugins/ExpressionParser/Go/GoAST.h +++ b/source/Plugins/ExpressionParser/Go/GoAST.h @@ -2764,6 +2764,7 @@ R GoASTExpr::Visit(V* v) const return v->VisitUnaryExpr(llvm::cast(this)); default: assert(false && "Invalid kind"); + return R(); } } diff --git a/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp b/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp index 3f12a2b6255b..f69c3e23457d 100644 --- a/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp +++ b/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp @@ -26,7 +26,6 @@ // 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" @@ -37,9 +36,11 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectRegister.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionVariable.h" -#include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/GoASTContext.h" +#include "lldb/Symbol/SymbolFile.h" +#include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" @@ -48,6 +49,7 @@ #include "lldb/Target/Target.h" #include "lldb/Target/ThreadPlan.h" #include "lldb/Target/ThreadPlanCallUserExpression.h" +#include "lldb/lldb-private.h" #include "Plugins/ExpressionParser/Go/GoAST.h" #include "Plugins/ExpressionParser/Go/GoParser.h" @@ -229,7 +231,8 @@ LookupType(TargetSP target, ConstString name) return CompilerType(); SymbolContext sc; TypeList type_list; - uint32_t num_matches = target->GetImages().FindTypes(sc, name, false, 2, type_list); + llvm::DenseSet searched_symbol_files; + uint32_t num_matches = target->GetImages().FindTypes(sc, name, false, 2, searched_symbol_files, type_list); if (num_matches > 0) { return type_list.GetTypeAtIndex(0)->GetFullCompilerType(); @@ -245,8 +248,9 @@ GoUserExpression::GoUserExpression(ExecutionContextScope &exe_scope, const char } bool -GoUserExpression::Parse(Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, - bool keep_result_in_memory, bool generate_debug_info) +GoUserExpression::Parse(DiagnosticManager &diagnostic_manager, 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())); @@ -254,15 +258,16 @@ GoUserExpression::Parse(Stream &error_stream, ExecutionContext &exe_ctx, lldb_pr return true; const char *error_cstr = m_interpreter->error().AsCString(); if (error_cstr && error_cstr[0]) - error_stream.Printf("error: %s\n", error_cstr); + diagnostic_manager.PutCString(eDiagnosticSeverityError, error_cstr); else - error_stream.Printf("error: expression can't be interpreted or run\n"); + diagnostic_manager.Printf(eDiagnosticSeverityError, "expression can't be interpreted or run"); return false; } lldb::ExpressionResults -GoUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, - lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result) +GoUserExpression::DoExecute(DiagnosticManager &diagnostic_manager, 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)); @@ -279,7 +284,7 @@ GoUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, const if (log) log->Printf("== [GoUserExpression::Evaluate] Expression may not run, but is not constant =="); - error_stream.Printf("expression needed to run but couldn't"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression needed to run but couldn't"); return execution_results; } @@ -294,9 +299,9 @@ GoUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, const { const char *error_cstr = err.AsCString(); if (error_cstr && error_cstr[0]) - error_stream.Printf("error: %s\n", error_cstr); + diagnostic_manager.PutCString(eDiagnosticSeverityError, error_cstr); else - error_stream.Printf("error: expression can't be interpreted or run\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression can't be interpreted or run"); return lldb::eExpressionDiscarded; } result.reset(new ExpressionVariable(ExpressionVariable::eKindGo)); diff --git a/source/Plugins/ExpressionParser/Go/GoUserExpression.h b/source/Plugins/ExpressionParser/Go/GoUserExpression.h index b429c68f023d..711a4c46215d 100644 --- a/source/Plugins/ExpressionParser/Go/GoUserExpression.h +++ b/source/Plugins/ExpressionParser/Go/GoUserExpression.h @@ -62,32 +62,34 @@ class GoPersistentExpressionState : public PersistentExpressionState 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; + GoUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix, + lldb::LanguageType language, ResultType desired_type, const EvaluateExpressionOptions &options); + + bool + Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, + bool generate_debug_info) override; + + bool + CanInterpret() override + { + return true; + } + bool + FinalizeJITExecution(DiagnosticManager &diagnostic_manager, 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; } + protected: + lldb::ExpressionResults + DoExecute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, + const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, + lldb::ExpressionVariableSP &result) override; + private: class GoInterpreter; std::unique_ptr m_interpreter; diff --git a/source/Plugins/ExpressionParser/Go/Makefile b/source/Plugins/ExpressionParser/Go/Makefile deleted file mode 100644 index c5bd7fb2857e..000000000000 --- a/source/Plugins/ExpressionParser/Go/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ExpressionParser/Clang ---------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginExpressionParserGo -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp index d646d4d4754a..884078b27175 100644 --- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -13004,7 +13004,7 @@ EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address { if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target)) { - if (m_arch.GetTriple().getArch() == llvm::Triple::thumb) + if (m_arch.GetTriple().getArch() == llvm::Triple::thumb || m_arch.IsAlwaysThumbInstructions ()) m_opcode_mode = eModeThumb; else { @@ -13017,7 +13017,7 @@ EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address else return false; } - if (m_opcode_mode == eModeThumb) + if (m_opcode_mode == eModeThumb || m_arch.IsAlwaysThumbInstructions ()) m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T; else m_opcode_cpsr = CPSR_MODE_USR; @@ -13040,7 +13040,7 @@ EmulateInstructionARM::ReadInstruction () read_inst_context.type = eContextReadOpcode; read_inst_context.SetNoArgs (); - if (m_opcode_cpsr & MASK_CPSR_T) + if ((m_opcode_cpsr & MASK_CPSR_T) || m_arch.IsAlwaysThumbInstructions ()) { m_opcode_mode = eModeThumb; uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success); @@ -13062,6 +13062,15 @@ EmulateInstructionARM::ReadInstruction () m_opcode_mode = eModeARM; m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success), GetByteOrder()); } + + if (!m_ignore_conditions) + { + // If we are not ignoreing the conditions then init the it session from the current + // value of cpsr. + uint32_t it = (Bits32(m_opcode_cpsr, 15, 10) << 2) | Bits32(m_opcode_cpsr, 26, 25); + if (it != 0) + m_it_session.InitIT(it); + } } } if (!success) @@ -13572,20 +13581,13 @@ EmulateInstructionARM::WriteFlags (Context &context, bool EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options) { - // Advance the ITSTATE bits to their values for the next instruction. - if (m_opcode_mode == eModeThumb && m_it_session.InITBlock()) - m_it_session.ITAdvance(); - ARMOpcode *opcode_data = NULL; if (m_opcode_mode == eModeThumb) opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa); else if (m_opcode_mode == eModeARM) opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa); - - if (opcode_data == NULL) - return false; - + const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC; m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions; @@ -13609,41 +13611,48 @@ EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options) if (!success) return false; } - - // Call the Emulate... function. - success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding); - if (!success) - return false; - + + // Call the Emulate... function if we managed to decode the opcode. + if (opcode_data) + { + success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding); + if (!success) + return false; + } + + // Advance the ITSTATE bits to their values for the next instruction if we haven't just executed + // an IT instruction what initialized it. + if (m_opcode_mode == eModeThumb && m_it_session.InITBlock() && + (opcode_data == nullptr || opcode_data->callback != &EmulateInstructionARM::EmulateIT)) + m_it_session.ITAdvance(); + if (auto_advance_pc) { uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success); if (!success) return false; - + if (auto_advance_pc && (after_pc_value == orig_pc_value)) { - if (opcode_data->size == eSize32) - after_pc_value += 4; - else if (opcode_data->size == eSize16) - after_pc_value += 2; - + after_pc_value += m_opcode.GetByteSize(); + EmulateInstruction::Context context; context.type = eContextAdvancePC; context.SetNoArgs(); if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value)) return false; - } } return true; } -bool -EmulateInstructionARM::IsInstructionConditional() +EmulateInstruction::InstructionCondition +EmulateInstructionARM::GetInstructionCondition() { const uint32_t cond = CurrentCond (m_opcode.GetOpcode32()); - return cond != 0xe && cond != 0xf && cond != UINT32_MAX; + if (cond == 0xe || cond == 0xf || cond == UINT32_MAX) + return EmulateInstruction::UnconditionalCondition; + return cond; } bool @@ -13669,19 +13678,19 @@ EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, Option } test_opcode = value_sp->GetUInt64Value (); - if (arch.GetTriple().getArch() == llvm::Triple::arm) - { - m_opcode_mode = eModeARM; - m_opcode.SetOpcode32 (test_opcode, GetByteOrder()); - } - else if (arch.GetTriple().getArch() == llvm::Triple::thumb) + + if (arch.GetTriple().getArch() == llvm::Triple::thumb || arch.IsAlwaysThumbInstructions ()) { m_opcode_mode = eModeThumb; if (test_opcode < 0x10000) - m_opcode.SetOpcode16 (test_opcode, GetByteOrder()); + m_opcode.SetOpcode16 (test_opcode, endian::InlHostByteOrder()); else - m_opcode.SetOpcode32 (test_opcode, GetByteOrder()); - + m_opcode.SetOpcode32 (test_opcode, endian::InlHostByteOrder()); + } + else if (arch.GetTriple().getArch() == llvm::Triple::arm) + { + m_opcode_mode = eModeARM; + m_opcode.SetOpcode32 (test_opcode, endian::InlHostByteOrder()); } else { diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h index 893f43f19977..6e75a3db2eb5 100644 --- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h +++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h @@ -166,8 +166,8 @@ public: bool EvaluateInstruction (uint32_t evaluate_options) override; - bool - IsInstructionConditional() override; + InstructionCondition + GetInstructionCondition() override; bool TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) override; diff --git a/source/Plugins/Instruction/ARM/EmulationStateARM.cpp b/source/Plugins/Instruction/ARM/EmulationStateARM.cpp index 6072264f1efc..547db44ebfb2 100644 --- a/source/Plugins/Instruction/ARM/EmulationStateARM.cpp +++ b/source/Plugins/Instruction/ARM/EmulationStateARM.cpp @@ -61,11 +61,15 @@ EmulationStateARM::LoadPseudoRegistersFromFrame (StackFrame &frame) if (reg_ctx->ReadRegister (reg_info, reg_value)) { + uint64_t value = reg_value.GetAsUInt64(); uint32_t idx = i - dwarf_d0; if (i < 16) - m_vfp_regs.sd_regs[idx].d_reg = reg_value.GetAsUInt64(); + { + m_vfp_regs.s_regs[idx * 2] = (uint32_t)value; + m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32); + } else - m_vfp_regs.d_regs[idx - 16] = reg_value.GetAsUInt64(); + m_vfp_regs.d_regs[idx - 16] = value; } else success = false; @@ -82,16 +86,18 @@ EmulationStateARM::StorePseudoRegisterValue (uint32_t reg_num, uint64_t value) else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) { uint32_t idx = reg_num - dwarf_s0; - m_vfp_regs.sd_regs[idx / 2].s_reg[idx % 2] = (uint32_t) value; + m_vfp_regs.s_regs[idx] = (uint32_t)value; } else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) { - if ((reg_num - dwarf_d0) < 16) + uint32_t idx = reg_num - dwarf_d0; + if (idx < 16) { - m_vfp_regs.sd_regs[reg_num - dwarf_d0].d_reg = value; + m_vfp_regs.s_regs[idx * 2] = (uint32_t)value; + m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32); } else - m_vfp_regs.d_regs[reg_num - dwarf_d16] = value; + m_vfp_regs.d_regs[idx - 16] = value; } else return false; @@ -110,14 +116,15 @@ EmulationStateARM::ReadPseudoRegisterValue (uint32_t reg_num, bool &success) else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) { uint32_t idx = reg_num - dwarf_s0; - value = m_vfp_regs.sd_regs[idx / 2].s_reg[idx % 2]; + value = m_vfp_regs.d_regs[idx]; } else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) { - if ((reg_num - dwarf_d0) < 16) - value = m_vfp_regs.sd_regs[reg_num - dwarf_d0].d_reg; + uint32_t idx = reg_num - dwarf_d0; + if (idx < 16) + value = (uint64_t)m_vfp_regs.s_regs[idx * 2] | ((uint64_t)m_vfp_regs.s_regs[idx * 2 + 1] >> 32); else - value = m_vfp_regs.d_regs[reg_num - dwarf_d16]; + value = m_vfp_regs.d_regs[idx - 16]; } else success = false; @@ -131,8 +138,8 @@ EmulationStateARM::ClearPseudoRegisters () for (int i = 0; i < 17; ++i) m_gpr[i] = 0; - for (int i = 0; i < 16; ++i) - m_vfp_regs.sd_regs[i].d_reg = 0; + for (int i = 0; i < 32; ++i) + m_vfp_regs.s_regs[i] = 0; for (int i = 0; i < 16; ++i) m_vfp_regs.d_regs[i] = 0; @@ -145,23 +152,14 @@ EmulationStateARM::ClearPseudoMemory () } bool -EmulationStateARM::StoreToPseudoAddress (lldb::addr_t p_address, uint64_t value, uint32_t size) +EmulationStateARM::StoreToPseudoAddress (lldb::addr_t p_address, uint32_t value) { - if (size > 8) - return false; - - if (size <= 4) - m_memory[p_address] = value; - else if (size == 8) - { - m_memory[p_address] = (value << 32) >> 32; - m_memory[p_address + 4] = value << 32; - } + m_memory[p_address] = value; return true; } uint32_t -EmulationStateARM::ReadFromPseudoAddress (lldb::addr_t p_address, uint32_t size, bool &success) +EmulationStateARM::ReadFromPseudoAddress (lldb::addr_t p_address, bool &success) { std::map::iterator pos; uint32_t ret_val = 0; @@ -191,25 +189,31 @@ EmulationStateARM::ReadPseudoMemory (EmulateInstruction *instruction, EmulationStateARM *pseudo_state = (EmulationStateARM *) baton; if (length <= 4) { - uint32_t value = pseudo_state->ReadFromPseudoAddress (addr, length, success); + uint32_t value = pseudo_state->ReadFromPseudoAddress (addr, success); if (!success) return 0; + if (endian::InlHostByteOrder() == lldb::eByteOrderBig) + value = llvm::ByteSwap_32 (value); *((uint32_t *) dst) = value; } else if (length == 8) { - uint32_t value1 = pseudo_state->ReadFromPseudoAddress (addr, 4, success); + uint32_t value1 = pseudo_state->ReadFromPseudoAddress (addr, success); if (!success) return 0; - uint32_t value2 = pseudo_state->ReadFromPseudoAddress (addr + 4, 4, success); + uint32_t value2 = pseudo_state->ReadFromPseudoAddress (addr + 4, success); if (!success) return 0; - uint64_t value64 = value2; - value64 = (value64 << 32) | value1; - *((uint64_t *) dst) = value64; + if (endian::InlHostByteOrder() == lldb::eByteOrderBig) + { + value1 = llvm::ByteSwap_32 (value1); + value2 = llvm::ByteSwap_32 (value2); + } + ((uint32_t *) dst)[0] = value1; + ((uint32_t *) dst)[1] = value2; } else success = false; @@ -231,13 +235,32 @@ EmulationStateARM::WritePseudoMemory (EmulateInstruction *instruction, if (!baton) return 0; - bool success; EmulationStateARM *pseudo_state = (EmulationStateARM *) baton; - uint64_t value = *((const uint64_t *) dst); - success = pseudo_state->StoreToPseudoAddress (addr, value, length); - if (success) + + if (length <= 4) + { + uint32_t value = *((const uint32_t *) dst); + if (endian::InlHostByteOrder() == lldb::eByteOrderBig) + value = llvm::ByteSwap_32 (value); + + pseudo_state->StoreToPseudoAddress (addr, value); return length; - + } + else if (length == 8) + { + uint32_t value1 = ((const uint32_t *) dst)[0]; + uint32_t value2 = ((const uint32_t *) dst)[1]; + if (endian::InlHostByteOrder() == lldb::eByteOrderBig) + { + value1 = llvm::ByteSwap_32 (value1); + value2 = llvm::ByteSwap_32 (value2); + } + + pseudo_state->StoreToPseudoAddress (addr, value1); + pseudo_state->StoreToPseudoAddress (addr + 4, value2); + return length; + } + return 0; } @@ -289,27 +312,16 @@ EmulationStateARM::CompareState (EmulationStateARM &other_state) match = false; } - for (int i = 0; match && i < 16; ++i) + for (int i = 0; match && i < 32; ++i) { - if (m_vfp_regs.sd_regs[i].s_reg[0] != other_state.m_vfp_regs.sd_regs[i].s_reg[0]) - match = false; - - if (m_vfp_regs.sd_regs[i].s_reg[1] != other_state.m_vfp_regs.sd_regs[i].s_reg[1]) + if (m_vfp_regs.s_regs[i] != other_state.m_vfp_regs.s_regs[i]) match = false; } - for (int i = 0; match && i < 32; ++i) + for (int i = 0; match && i < 16; ++i) { - if (i < 16) - { - if (m_vfp_regs.sd_regs[i].d_reg != other_state.m_vfp_regs.sd_regs[i].d_reg) - match = false; - } - else - { - if (m_vfp_regs.d_regs[i - 16] != other_state.m_vfp_regs.d_regs[i - 16]) - match = false; - } + if (m_vfp_regs.d_regs[i] != other_state.m_vfp_regs.d_regs[i]) + match = false; } return match; @@ -355,7 +367,7 @@ EmulationStateARM::LoadStateFromDictionary (OptionValueDictionary *test_data) if (value_sp.get() == NULL) return false; uint64_t value = value_sp->GetUInt64Value(); - StoreToPseudoAddress (address, value, 4); + StoreToPseudoAddress (address, value); address = address + 4; } } diff --git a/source/Plugins/Instruction/ARM/EmulationStateARM.h b/source/Plugins/Instruction/ARM/EmulationStateARM.h index ad596a3c2779..e82ef94b5a01 100644 --- a/source/Plugins/Instruction/ARM/EmulationStateARM.h +++ b/source/Plugins/Instruction/ARM/EmulationStateARM.h @@ -30,10 +30,10 @@ public: ReadPseudoRegisterValue (uint32_t reg_num, bool &success); bool - StoreToPseudoAddress (lldb::addr_t p_address, uint64_t value, uint32_t size); + StoreToPseudoAddress (lldb::addr_t p_address, uint32_t value); uint32_t - ReadFromPseudoAddress (lldb::addr_t p_address, uint32_t size, bool &success); + ReadFromPseudoAddress (lldb::addr_t p_address, bool &success); void ClearPseudoRegisters (); @@ -82,11 +82,7 @@ private: uint32_t m_gpr[17]; struct _sd_regs { - union - { - uint32_t s_reg[2]; - uint64_t d_reg; - } sd_regs[16]; // sregs 0 - 31 & dregs 0 - 15 + uint32_t s_regs[32]; // sregs 0 - 31 & dregs 0 - 15 uint64_t d_regs[16]; // dregs 16-31 diff --git a/source/Plugins/Instruction/ARM/Makefile b/source/Plugins/Instruction/ARM/Makefile deleted file mode 100644 index 31a233b0b374..000000000000 --- a/source/Plugins/Instruction/ARM/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Instruction/ARM/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginInstructionARM -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp index 372ccf9b05f4..ea67928280d3 100644 --- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp +++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp @@ -980,7 +980,7 @@ EmulateInstructionARM64::EmulateLDRSTRImm (const uint32_t opcode) if (!WriteRegister (context, ®_info_Rt, data_Rt)) return false; - + break; default: return false; } diff --git a/source/Plugins/Instruction/ARM64/Makefile b/source/Plugins/Instruction/ARM64/Makefile deleted file mode 100644 index 8f60ce6dcd47..000000000000 --- a/source/Plugins/Instruction/ARM64/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Instruction/ARM/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginInstructionARM64 -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp index a71fca7c5c3a..99856a3684cb 100644 --- a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp +++ b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp @@ -17,7 +17,7 @@ #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCContext.h" @@ -1142,7 +1142,7 @@ EmulateInstructionMIPS::Emulate_SWSP (llvm::MCInst& insn) // We look for sp based non-volatile register stores. if (base == dwarf_sp_mips && nonvolatile_reg_p (src)) { - RegisterInfo reg_info_src; + RegisterInfo reg_info_src = {}; Context context; RegisterValue data_src; context.type = eContextPushRegisterOnStack; @@ -1482,56 +1482,56 @@ EmulateInstructionMIPS::Emulate_BXX_3ops_C (llvm::MCInst& insn) if (!strcasecmp (op_name, "BEQC")) { if (rs_val == rt_val) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BNEC")) { if (rs_val != rt_val) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BLTC")) { if (rs_val < rt_val) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BGEC")) { if (rs_val >= rt_val) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BLTUC")) { if (rs_val < rt_val) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BGEUC")) { if ((uint32_t)rs_val >= (uint32_t)rt_val) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BOVC")) { if (IsAdd64bitOverflow (rs_val, rt_val)) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BNVC")) { if (!IsAdd64bitOverflow (rs_val, rt_val)) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } @@ -1773,42 +1773,42 @@ EmulateInstructionMIPS::Emulate_BXX_2ops_C (llvm::MCInst& insn) if (!strcasecmp (op_name, "BLTZC")) { if (rs_val < 0) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BLEZC")) { if (rs_val <= 0) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BGEZC")) { if (rs_val >= 0) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BGTZC")) { if (rs_val > 0) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BEQZC")) { if (rs_val == 0) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BNEZC")) { if (rs_val != 0) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } @@ -2129,7 +2129,7 @@ EmulateInstructionMIPS::Emulate_BALC (llvm::MCInst& insn) if (!success) return false; - target = pc + 4 + offset; + target = pc + offset; Context context; @@ -2159,7 +2159,7 @@ EmulateInstructionMIPS::Emulate_BC (llvm::MCInst& insn) if (!success) return false; - target = pc + 4 + offset; + target = pc + offset; Context context; @@ -2603,7 +2603,7 @@ EmulateInstructionMIPS::Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_b bool success = false, branch_hit = true; int32_t target = 0; RegisterValue reg_value; - uint8_t * ptr = NULL; + const uint8_t *ptr = NULL; uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); int32_t offset = insn.getOperand(1).getImm(); @@ -2613,7 +2613,7 @@ EmulateInstructionMIPS::Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_b return false; if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value)) - ptr = (uint8_t *)reg_value.GetBytes(); + ptr = (const uint8_t *)reg_value.GetBytes(); else return false; @@ -2626,15 +2626,15 @@ EmulateInstructionMIPS::Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_b branch_hit = false; break; case 2: - if((*(uint16_t *)ptr == 0 && bnz) || (*(uint16_t *)ptr != 0 && !bnz)) + if ((*(const uint16_t *)ptr == 0 && bnz) || (*(const uint16_t *)ptr != 0 && !bnz)) branch_hit = false; break; case 4: - if((*(uint32_t *)ptr == 0 && bnz) || (*(uint32_t *)ptr != 0 && !bnz)) + if ((*(const uint32_t *)ptr == 0 && bnz) || (*(const uint32_t *)ptr != 0 && !bnz)) branch_hit = false; break; case 8: - if((*(uint64_t *)ptr == 0 && bnz) || (*(uint64_t *)ptr != 0 && !bnz)) + if ((*(const uint64_t *)ptr == 0 && bnz) || (*(const uint64_t *)ptr != 0 && !bnz)) branch_hit = false; break; } diff --git a/source/Plugins/Instruction/MIPS/Makefile b/source/Plugins/Instruction/MIPS/Makefile deleted file mode 100644 index e9cef4ba0cf7..000000000000 --- a/source/Plugins/Instruction/MIPS/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Instruction/MIPS/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginInstructionMIPS -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp index 9c09d383beae..dd071b00de31 100644 --- a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp +++ b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp @@ -17,7 +17,7 @@ #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCContext.h" @@ -483,6 +483,7 @@ EmulateInstructionMIPS64::GetOpcodeForInstruction (const char *op_name) // Prologue/Epilogue instructions //---------------------------------------------------------------------- { "DADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu, "DADDIU rt,rs,immediate" }, + { "ADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu, "ADDIU rt,rs,immediate" }, { "SD", &EmulateInstructionMIPS64::Emulate_SD, "SD rt,offset(rs)" }, { "LD", &EmulateInstructionMIPS64::Emulate_LD, "LD rt,offset(base)" }, @@ -1066,7 +1067,7 @@ EmulateInstructionMIPS64::Emulate_BALC (llvm::MCInst& insn) if (!success) return false; - target = pc + 4 + offset; + target = pc + offset; Context context; @@ -1240,7 +1241,7 @@ EmulateInstructionMIPS64::Emulate_BC (llvm::MCInst& insn) if (!success) return false; - target = pc + 4 + offset; + target = pc + offset; Context context; @@ -1289,56 +1290,56 @@ EmulateInstructionMIPS64::Emulate_BXX_3ops_C (llvm::MCInst& insn) if (!strcasecmp (op_name, "BEQC")) { if (rs_val == rt_val) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BNEC")) { if (rs_val != rt_val) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BLTC")) { if (rs_val < rt_val) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BGEC")) { if (rs_val >= rt_val) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BLTUC")) { if (rs_val < rt_val) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BGEUC")) { if ((uint32_t)rs_val >= (uint32_t)rt_val) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BOVC")) { if (IsAdd64bitOverflow (rs_val, rt_val)) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BNVC")) { if (!IsAdd64bitOverflow (rs_val, rt_val)) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } @@ -1381,42 +1382,42 @@ EmulateInstructionMIPS64::Emulate_BXX_2ops_C (llvm::MCInst& insn) if (!strcasecmp (op_name, "BLTZC")) { if (rs_val < 0) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BLEZC")) { if (rs_val <= 0) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BGEZC")) { if (rs_val >= 0) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BGTZC")) { if (rs_val > 0) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BEQZC")) { if (rs_val == 0) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } else if (!strcasecmp (op_name, "BNEZC")) { if (rs_val != 0) - target = pc + 4 + offset; + target = pc + offset; else target = pc + 4; } @@ -1874,7 +1875,7 @@ EmulateInstructionMIPS64::Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element bool success = false, branch_hit = true; int64_t target = 0; RegisterValue reg_value; - uint8_t * ptr = NULL; + const uint8_t *ptr = NULL; uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); int64_t offset = insn.getOperand(1).getImm(); @@ -1884,7 +1885,7 @@ EmulateInstructionMIPS64::Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element return false; if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value)) - ptr = (uint8_t *)reg_value.GetBytes(); + ptr = (const uint8_t *)reg_value.GetBytes(); else return false; @@ -1897,15 +1898,15 @@ EmulateInstructionMIPS64::Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element branch_hit = false; break; case 2: - if((*(uint16_t *)ptr == 0 && bnz) || (*(uint16_t *)ptr != 0 && !bnz)) + if ((*(const uint16_t *)ptr == 0 && bnz) || (*(const uint16_t *)ptr != 0 && !bnz)) branch_hit = false; break; case 4: - if((*(uint32_t *)ptr == 0 && bnz) || (*(uint32_t *)ptr != 0 && !bnz)) + if ((*(const uint32_t *)ptr == 0 && bnz) || (*(const uint32_t *)ptr != 0 && !bnz)) branch_hit = false; break; case 8: - if((*(uint64_t *)ptr == 0 && bnz) || (*(uint64_t *)ptr != 0 && !bnz)) + if ((*(const uint64_t *)ptr == 0 && bnz) || (*(const uint64_t *)ptr != 0 && !bnz)) branch_hit = false; break; } diff --git a/source/Plugins/Instruction/MIPS64/Makefile b/source/Plugins/Instruction/MIPS64/Makefile deleted file mode 100644 index 7e5b339a359d..000000000000 --- a/source/Plugins/Instruction/MIPS64/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Instruction/MIPS64/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginInstructionMIPS64 -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp index c2f1f2e95c83..99857cd3d1b0 100644 --- a/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp +++ b/source/Plugins/InstrumentationRuntime/AddressSanitizer/AddressSanitizerRuntime.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Expression/UserExpression.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" @@ -97,8 +98,8 @@ AddressSanitizerRuntime::ModulesDidLoad(lldb_private::ModuleList &module_list) Activate(); return; } - - Mutex::Locker modules_locker(module_list.GetMutex()); + + std::lock_guard guard(module_list.GetMutex()); const size_t num_modules = module_list.GetSize(); for (size_t i = 0; i < num_modules; ++i) { @@ -127,9 +128,10 @@ AddressSanitizerRuntime::IsActive() } #define RETRIEVE_REPORT_DATA_FUNCTION_TIMEOUT_USEC 2*1000*1000 - const char * -address_sanitizer_retrieve_report_data_command = R"( +address_sanitizer_retrieve_report_data_prefix = R"( +extern "C" +{ int __asan_report_present(); void *__asan_get_report_pc(); void *__asan_get_report_bp(); @@ -138,6 +140,11 @@ void *__asan_get_report_address(); const char *__asan_get_report_description(); int __asan_get_report_access_type(); size_t __asan_get_report_access_size(); +} +)"; + +const char * +address_sanitizer_retrieve_report_data_command = R"( struct { int present; int access_type; @@ -167,7 +174,7 @@ AddressSanitizerRuntime::RetrieveReportData() if (!process_sp) return StructuredData::ObjectSP(); - ThreadSP thread_sp = process_sp->GetThreadList().GetSelectedThread(); + ThreadSP thread_sp = process_sp->GetThreadList().GetExpressionExecutionThread(); StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); if (!frame_sp) @@ -179,10 +186,24 @@ AddressSanitizerRuntime::RetrieveReportData() options.SetStopOthers(true); options.SetIgnoreBreakpoints(true); options.SetTimeoutUsec(RETRIEVE_REPORT_DATA_FUNCTION_TIMEOUT_USEC); + options.SetPrefix(address_sanitizer_retrieve_report_data_prefix); + options.SetAutoApplyFixIts(false); + options.SetLanguage(eLanguageTypeObjC_plus_plus); ValueObjectSP return_value_sp; - if (process_sp->GetTarget().EvaluateExpression(address_sanitizer_retrieve_report_data_command, frame_sp.get(), return_value_sp, options) != eExpressionCompleted) + ExecutionContext exe_ctx; + Error eval_error; + frame_sp->CalculateExecutionContext(exe_ctx); + ExpressionResults result = UserExpression::Evaluate (exe_ctx, + options, + address_sanitizer_retrieve_report_data_command, + "", + return_value_sp, + eval_error); + if (result != eExpressionCompleted) { + process_sp->GetTarget().GetDebugger().GetAsyncOutputStream()->Printf("Warning: Cannot evaluate AddressSanitizer expression:\n%s\n", eval_error.AsCString()); return StructuredData::ObjectSP(); + } int present = return_value_sp->GetValueForExpressionPath(".present")->GetValueAsUnsigned(0); if (present != 1) diff --git a/source/Plugins/InstrumentationRuntime/AddressSanitizer/Makefile b/source/Plugins/InstrumentationRuntime/AddressSanitizer/Makefile deleted file mode 100644 index 030aec17b026..000000000000 --- a/source/Plugins/InstrumentationRuntime/AddressSanitizer/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/InstrumentationRuntime/AddressSanitizer Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginInstrumentationRuntimeAddressSanitizer -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/InstrumentationRuntime/CMakeLists.txt b/source/Plugins/InstrumentationRuntime/CMakeLists.txt index 8ee303b25359..ae7c6e5972d3 100644 --- a/source/Plugins/InstrumentationRuntime/CMakeLists.txt +++ b/source/Plugins/InstrumentationRuntime/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(AddressSanitizer) +add_subdirectory(ThreadSanitizer) diff --git a/source/Plugins/InstrumentationRuntime/ThreadSanitizer/CMakeLists.txt b/source/Plugins/InstrumentationRuntime/ThreadSanitizer/CMakeLists.txt new file mode 100644 index 000000000000..6ef79433d67a --- /dev/null +++ b/source/Plugins/InstrumentationRuntime/ThreadSanitizer/CMakeLists.txt @@ -0,0 +1,3 @@ +add_lldb_library(lldbPluginInstrumentationRuntimeThreadSanitizer + ThreadSanitizerRuntime.cpp + ) diff --git a/source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp b/source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp new file mode 100644 index 000000000000..62e5ce63a542 --- /dev/null +++ b/source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.cpp @@ -0,0 +1,887 @@ +//===-- ThreadSanitizerRuntime.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ThreadSanitizerRuntime.h" + +#include "lldb/Breakpoint/StoppointCallbackContext.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleList.h" +#include "lldb/Core/RegularExpression.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Expression/UserExpression.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Symbol/Symbol.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/Variable.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/InstrumentationRuntimeStopInfo.h" +#include "lldb/Target/SectionLoadList.h" +#include "lldb/Target/StopInfo.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "Plugins/Process/Utility/HistoryThread.h" + +using namespace lldb; +using namespace lldb_private; + +lldb::InstrumentationRuntimeSP +ThreadSanitizerRuntime::CreateInstance (const lldb::ProcessSP &process_sp) +{ + return InstrumentationRuntimeSP(new ThreadSanitizerRuntime(process_sp)); +} + +void +ThreadSanitizerRuntime::Initialize() +{ + PluginManager::RegisterPlugin (GetPluginNameStatic(), + "ThreadSanitizer instrumentation runtime plugin.", + CreateInstance, + GetTypeStatic); +} + +void +ThreadSanitizerRuntime::Terminate() +{ + PluginManager::UnregisterPlugin (CreateInstance); +} + +lldb_private::ConstString +ThreadSanitizerRuntime::GetPluginNameStatic() +{ + return ConstString("ThreadSanitizer"); +} + +lldb::InstrumentationRuntimeType +ThreadSanitizerRuntime::GetTypeStatic() +{ + return eInstrumentationRuntimeTypeThreadSanitizer; +} + +ThreadSanitizerRuntime::ThreadSanitizerRuntime(const ProcessSP &process_sp) : +m_is_active(false), +m_runtime_module_wp(), +m_process_wp(), +m_breakpoint_id(0) +{ + if (process_sp) + m_process_wp = process_sp; +} + +ThreadSanitizerRuntime::~ThreadSanitizerRuntime() +{ + Deactivate(); +} + +static bool +ModuleContainsTSanRuntime(ModuleSP module_sp) +{ + static ConstString g_tsan_get_current_report("__tsan_get_current_report"); + const Symbol* symbol = module_sp->FindFirstSymbolWithNameAndType(g_tsan_get_current_report, lldb::eSymbolTypeAny); + return symbol != nullptr; +} + +void +ThreadSanitizerRuntime::ModulesDidLoad(lldb_private::ModuleList &module_list) +{ + if (IsActive()) + return; + + if (GetRuntimeModuleSP()) { + Activate(); + return; + } + + module_list.ForEach ([this](const lldb::ModuleSP module_sp) -> bool + { + const FileSpec & file_spec = module_sp->GetFileSpec(); + if (! file_spec) + return true; // Keep iterating through modules + + llvm::StringRef module_basename(file_spec.GetFilename().GetStringRef()); + if (module_sp->IsExecutable() || module_basename.startswith("libclang_rt.tsan_")) + { + if (ModuleContainsTSanRuntime(module_sp)) + { + m_runtime_module_wp = module_sp; + Activate(); + return false; // Stop iterating + } + } + + return true; // Keep iterating through modules + }); +} + +bool +ThreadSanitizerRuntime::IsActive() +{ + return m_is_active; +} + +#define RETRIEVE_REPORT_DATA_FUNCTION_TIMEOUT_USEC 2*1000*1000 + +const char * +thread_sanitizer_retrieve_report_data_prefix = R"( +extern "C" +{ + void *__tsan_get_current_report(); + int __tsan_get_report_data(void *report, const char **description, int *count, + int *stack_count, int *mop_count, int *loc_count, + int *mutex_count, int *thread_count, + int *unique_tid_count, void **sleep_trace, + unsigned long trace_size); + int __tsan_get_report_stack(void *report, unsigned long idx, void **trace, + unsigned long trace_size); + int __tsan_get_report_mop(void *report, unsigned long idx, int *tid, void **addr, + int *size, int *write, int *atomic, void **trace, + unsigned long trace_size); + int __tsan_get_report_loc(void *report, unsigned long idx, const char **type, + void **addr, unsigned long *start, unsigned long *size, int *tid, + int *fd, int *suppressable, void **trace, + unsigned long trace_size); + int __tsan_get_report_mutex(void *report, unsigned long idx, unsigned long *mutex_id, void **addr, + int *destroyed, void **trace, unsigned long trace_size); + int __tsan_get_report_thread(void *report, unsigned long idx, int *tid, unsigned long *os_id, + int *running, const char **name, int *parent_tid, + void **trace, unsigned long trace_size); + int __tsan_get_report_unique_tid(void *report, unsigned long idx, int *tid); +} + +const int REPORT_TRACE_SIZE = 128; +const int REPORT_ARRAY_SIZE = 4; + +struct data { + void *report; + const char *description; + int report_count; + + void *sleep_trace[REPORT_TRACE_SIZE]; + + int stack_count; + struct { + int idx; + void *trace[REPORT_TRACE_SIZE]; + } stacks[REPORT_ARRAY_SIZE]; + + int mop_count; + struct { + int idx; + int tid; + int size; + int write; + int atomic; + void *addr; + void *trace[REPORT_TRACE_SIZE]; + } mops[REPORT_ARRAY_SIZE]; + + int loc_count; + struct { + int idx; + const char *type; + void *addr; + unsigned long start; + unsigned long size; + int tid; + int fd; + int suppressable; + void *trace[REPORT_TRACE_SIZE]; + } locs[REPORT_ARRAY_SIZE]; + + int mutex_count; + struct { + int idx; + unsigned long mutex_id; + void *addr; + int destroyed; + void *trace[REPORT_TRACE_SIZE]; + } mutexes[REPORT_ARRAY_SIZE]; + + int thread_count; + struct { + int idx; + int tid; + unsigned long os_id; + int running; + const char *name; + int parent_tid; + void *trace[REPORT_TRACE_SIZE]; + } threads[REPORT_ARRAY_SIZE]; + + int unique_tid_count; + struct { + int idx; + int tid; + } unique_tids[REPORT_ARRAY_SIZE]; +}; +)"; + +const char * +thread_sanitizer_retrieve_report_data_command = R"( +data t = {0}; + +t.report = __tsan_get_current_report(); +__tsan_get_report_data(t.report, &t.description, &t.report_count, &t.stack_count, &t.mop_count, &t.loc_count, &t.mutex_count, &t.thread_count, &t.unique_tid_count, t.sleep_trace, REPORT_TRACE_SIZE); + +if (t.stack_count > REPORT_ARRAY_SIZE) t.stack_count = REPORT_ARRAY_SIZE; +for (int i = 0; i < t.stack_count; i++) { + t.stacks[i].idx = i; + __tsan_get_report_stack(t.report, i, t.stacks[i].trace, REPORT_TRACE_SIZE); +} + +if (t.mop_count > REPORT_ARRAY_SIZE) t.mop_count = REPORT_ARRAY_SIZE; +for (int i = 0; i < t.mop_count; i++) { + t.mops[i].idx = i; + __tsan_get_report_mop(t.report, i, &t.mops[i].tid, &t.mops[i].addr, &t.mops[i].size, &t.mops[i].write, &t.mops[i].atomic, t.mops[i].trace, REPORT_TRACE_SIZE); +} + +if (t.loc_count > REPORT_ARRAY_SIZE) t.loc_count = REPORT_ARRAY_SIZE; +for (int i = 0; i < t.loc_count; i++) { + t.locs[i].idx = i; + __tsan_get_report_loc(t.report, i, &t.locs[i].type, &t.locs[i].addr, &t.locs[i].start, &t.locs[i].size, &t.locs[i].tid, &t.locs[i].fd, &t.locs[i].suppressable, t.locs[i].trace, REPORT_TRACE_SIZE); +} + +if (t.mutex_count > REPORT_ARRAY_SIZE) t.mutex_count = REPORT_ARRAY_SIZE; +for (int i = 0; i < t.mutex_count; i++) { + t.mutexes[i].idx = i; + __tsan_get_report_mutex(t.report, i, &t.mutexes[i].mutex_id, &t.mutexes[i].addr, &t.mutexes[i].destroyed, t.mutexes[i].trace, REPORT_TRACE_SIZE); +} + +if (t.thread_count > REPORT_ARRAY_SIZE) t.thread_count = REPORT_ARRAY_SIZE; +for (int i = 0; i < t.thread_count; i++) { + t.threads[i].idx = i; + __tsan_get_report_thread(t.report, i, &t.threads[i].tid, &t.threads[i].os_id, &t.threads[i].running, &t.threads[i].name, &t.threads[i].parent_tid, t.threads[i].trace, REPORT_TRACE_SIZE); +} + +if (t.unique_tid_count > REPORT_ARRAY_SIZE) t.unique_tid_count = REPORT_ARRAY_SIZE; +for (int i = 0; i < t.unique_tid_count; i++) { + t.unique_tids[i].idx = i; + __tsan_get_report_unique_tid(t.report, i, &t.unique_tids[i].tid); +} + +t; +)"; + +static StructuredData::Array * +CreateStackTrace(ValueObjectSP o, std::string trace_item_name = ".trace") { + StructuredData::Array *trace = new StructuredData::Array(); + ValueObjectSP trace_value_object = o->GetValueForExpressionPath(trace_item_name.c_str()); + for (int j = 0; j < 8; j++) { + addr_t trace_addr = trace_value_object->GetChildAtIndex(j, true)->GetValueAsUnsigned(0); + if (trace_addr == 0) + break; + trace->AddItem(StructuredData::ObjectSP(new StructuredData::Integer(trace_addr))); + } + return trace; +} + +static StructuredData::Array * +ConvertToStructuredArray(ValueObjectSP return_value_sp, std::string items_name, std::string count_name, std::function const &callback) +{ + StructuredData::Array *array = new StructuredData::Array(); + unsigned int count = return_value_sp->GetValueForExpressionPath(count_name.c_str())->GetValueAsUnsigned(0); + ValueObjectSP objects = return_value_sp->GetValueForExpressionPath(items_name.c_str()); + for (unsigned int i = 0; i < count; i++) { + ValueObjectSP o = objects->GetChildAtIndex(i, true); + StructuredData::Dictionary *dict = new StructuredData::Dictionary(); + + callback(o, dict); + + array->AddItem(StructuredData::ObjectSP(dict)); + } + return array; +} + +static std::string +RetrieveString(ValueObjectSP return_value_sp, ProcessSP process_sp, std::string expression_path) +{ + addr_t ptr = return_value_sp->GetValueForExpressionPath(expression_path.c_str())->GetValueAsUnsigned(0); + std::string str; + Error error; + process_sp->ReadCStringFromMemory(ptr, str, error); + return str; +} + +static void +GetRenumberedThreadIds(ProcessSP process_sp, ValueObjectSP data, std::map &thread_id_map) +{ + ConvertToStructuredArray(data, ".threads", ".thread_count", [process_sp, &thread_id_map] (ValueObjectSP o, StructuredData::Dictionary *dict) { + uint64_t thread_id = o->GetValueForExpressionPath(".tid")->GetValueAsUnsigned(0); + uint64_t thread_os_id = o->GetValueForExpressionPath(".os_id")->GetValueAsUnsigned(0); + user_id_t lldb_user_id = 0; + + bool can_update = true; + ThreadSP lldb_thread = process_sp->GetThreadList().FindThreadByID(thread_os_id, can_update); + if (lldb_thread) { + lldb_user_id = lldb_thread->GetIndexID(); + } else { + // This isn't a live thread anymore. Ask process to assign a new Index ID (or return an old one if we've already seen this thread_os_id). + // It will also make sure that no new threads are assigned this Index ID. + lldb_user_id = process_sp->AssignIndexIDToThread(thread_os_id); + } + + thread_id_map[thread_id] = lldb_user_id; + }); +} + +static user_id_t Renumber(uint64_t id, std::map &thread_id_map) { + if (! thread_id_map.count(id)) + return 0; + + return thread_id_map[id]; +} + +StructuredData::ObjectSP +ThreadSanitizerRuntime::RetrieveReportData(ExecutionContextRef exe_ctx_ref) +{ + ProcessSP process_sp = GetProcessSP(); + if (!process_sp) + return StructuredData::ObjectSP(); + + ThreadSP thread_sp = exe_ctx_ref.GetThreadSP(); + StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); + + if (!frame_sp) + return StructuredData::ObjectSP(); + + EvaluateExpressionOptions options; + options.SetUnwindOnError(true); + options.SetTryAllThreads(true); + options.SetStopOthers(true); + options.SetIgnoreBreakpoints(true); + options.SetTimeoutUsec(RETRIEVE_REPORT_DATA_FUNCTION_TIMEOUT_USEC); + options.SetPrefix(thread_sanitizer_retrieve_report_data_prefix); + options.SetAutoApplyFixIts(false); + options.SetLanguage(eLanguageTypeObjC_plus_plus); + + ValueObjectSP main_value; + ExecutionContext exe_ctx; + Error eval_error; + frame_sp->CalculateExecutionContext(exe_ctx); + ExpressionResults result = UserExpression::Evaluate (exe_ctx, + options, + thread_sanitizer_retrieve_report_data_command, + "", + main_value, + eval_error); + if (result != eExpressionCompleted) { + process_sp->GetTarget().GetDebugger().GetAsyncOutputStream()->Printf("Warning: Cannot evaluate ThreadSanitizer expression:\n%s\n", eval_error.AsCString()); + return StructuredData::ObjectSP(); + } + + std::map thread_id_map; + GetRenumberedThreadIds(process_sp, main_value, thread_id_map); + + StructuredData::Dictionary *dict = new StructuredData::Dictionary(); + dict->AddStringItem("instrumentation_class", "ThreadSanitizer"); + dict->AddStringItem("issue_type", RetrieveString(main_value, process_sp, ".description")); + dict->AddIntegerItem("report_count", main_value->GetValueForExpressionPath(".report_count")->GetValueAsUnsigned(0)); + dict->AddItem("sleep_trace", StructuredData::ObjectSP(CreateStackTrace(main_value, ".sleep_trace"))); + + StructuredData::Array *stacks = ConvertToStructuredArray(main_value, ".stacks", ".stack_count", [thread_sp] (ValueObjectSP o, StructuredData::Dictionary *dict) { + dict->AddIntegerItem("index", o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); + dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); + // "stacks" happen on the current thread + dict->AddIntegerItem("thread_id", thread_sp->GetIndexID()); + }); + dict->AddItem("stacks", StructuredData::ObjectSP(stacks)); + + StructuredData::Array *mops = ConvertToStructuredArray(main_value, ".mops", ".mop_count", [&thread_id_map] (ValueObjectSP o, StructuredData::Dictionary *dict) { + dict->AddIntegerItem("index", o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); + dict->AddIntegerItem("thread_id", Renumber(o->GetValueForExpressionPath(".tid")->GetValueAsUnsigned(0), thread_id_map)); + dict->AddIntegerItem("size", o->GetValueForExpressionPath(".size")->GetValueAsUnsigned(0)); + dict->AddBooleanItem("is_write", o->GetValueForExpressionPath(".write")->GetValueAsUnsigned(0)); + dict->AddBooleanItem("is_atomic", o->GetValueForExpressionPath(".atomic")->GetValueAsUnsigned(0)); + dict->AddIntegerItem("address", o->GetValueForExpressionPath(".addr")->GetValueAsUnsigned(0)); + dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); + }); + dict->AddItem("mops", StructuredData::ObjectSP(mops)); + + StructuredData::Array *locs = ConvertToStructuredArray(main_value, ".locs", ".loc_count", [process_sp, &thread_id_map] (ValueObjectSP o, StructuredData::Dictionary *dict) { + dict->AddIntegerItem("index", o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); + dict->AddStringItem("type", RetrieveString(o, process_sp, ".type")); + dict->AddIntegerItem("address", o->GetValueForExpressionPath(".addr")->GetValueAsUnsigned(0)); + dict->AddIntegerItem("start", o->GetValueForExpressionPath(".start")->GetValueAsUnsigned(0)); + dict->AddIntegerItem("size", o->GetValueForExpressionPath(".size")->GetValueAsUnsigned(0)); + dict->AddIntegerItem("thread_id", Renumber(o->GetValueForExpressionPath(".tid")->GetValueAsUnsigned(0), thread_id_map)); + dict->AddIntegerItem("file_descriptor", o->GetValueForExpressionPath(".fd")->GetValueAsUnsigned(0)); + dict->AddIntegerItem("suppressable", o->GetValueForExpressionPath(".suppressable")->GetValueAsUnsigned(0)); + dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); + }); + dict->AddItem("locs", StructuredData::ObjectSP(locs)); + + StructuredData::Array *mutexes = ConvertToStructuredArray(main_value, ".mutexes", ".mutex_count", [] (ValueObjectSP o, StructuredData::Dictionary *dict) { + dict->AddIntegerItem("index", o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); + dict->AddIntegerItem("mutex_id", o->GetValueForExpressionPath(".mutex_id")->GetValueAsUnsigned(0)); + dict->AddIntegerItem("address", o->GetValueForExpressionPath(".addr")->GetValueAsUnsigned(0)); + dict->AddIntegerItem("destroyed", o->GetValueForExpressionPath(".destroyed")->GetValueAsUnsigned(0)); + dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); + }); + dict->AddItem("mutexes", StructuredData::ObjectSP(mutexes)); + + StructuredData::Array *threads = ConvertToStructuredArray(main_value, ".threads", ".thread_count", [process_sp, &thread_id_map] (ValueObjectSP o, StructuredData::Dictionary *dict) { + dict->AddIntegerItem("index", o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); + dict->AddIntegerItem("thread_id", Renumber(o->GetValueForExpressionPath(".tid")->GetValueAsUnsigned(0), thread_id_map)); + dict->AddIntegerItem("thread_os_id", o->GetValueForExpressionPath(".os_id")->GetValueAsUnsigned(0)); + dict->AddIntegerItem("running", o->GetValueForExpressionPath(".running")->GetValueAsUnsigned(0)); + dict->AddStringItem("name", RetrieveString(o, process_sp, ".name")); + dict->AddIntegerItem("parent_thread_id", Renumber(o->GetValueForExpressionPath(".parent_tid")->GetValueAsUnsigned(0), thread_id_map)); + dict->AddItem("trace", StructuredData::ObjectSP(CreateStackTrace(o))); + }); + dict->AddItem("threads", StructuredData::ObjectSP(threads)); + + StructuredData::Array *unique_tids = ConvertToStructuredArray(main_value, ".unique_tids", ".unique_tid_count", [&thread_id_map] (ValueObjectSP o, StructuredData::Dictionary *dict) { + dict->AddIntegerItem("index", o->GetValueForExpressionPath(".idx")->GetValueAsUnsigned(0)); + dict->AddIntegerItem("tid", Renumber(o->GetValueForExpressionPath(".tid")->GetValueAsUnsigned(0), thread_id_map)); + }); + dict->AddItem("unique_tids", StructuredData::ObjectSP(unique_tids)); + + return StructuredData::ObjectSP(dict); +} + +std::string +ThreadSanitizerRuntime::FormatDescription(StructuredData::ObjectSP report) +{ + std::string description = report->GetAsDictionary()->GetValueForKey("issue_type")->GetAsString()->GetValue(); + + if (description == "data-race") { + return "Data race"; + } else if (description == "data-race-vptr") { + return "Data race on C++ virtual pointer"; + } else if (description == "heap-use-after-free") { + return "Use of deallocated memory"; + } else if (description == "heap-use-after-free-vptr") { + return "Use of deallocated C++ virtual pointer"; + } else if (description == "thread-leak") { + return "Thread leak"; + } else if (description == "locked-mutex-destroy") { + return "Destruction of a locked mutex"; + } else if (description == "mutex-double-lock") { + return "Double lock of a mutex"; + } else if (description == "mutex-invalid-access") { + return "Use of an uninitialized or destroyed mutex"; + } else if (description == "mutex-bad-unlock") { + return "Unlock of an unlocked mutex (or by a wrong thread)"; + } else if (description == "mutex-bad-read-lock") { + return "Read lock of a write locked mutex"; + } else if (description == "mutex-bad-read-unlock") { + return "Read unlock of a write locked mutex"; + } else if (description == "signal-unsafe-call") { + return "Signal-unsafe call inside a signal handler"; + } else if (description == "errno-in-signal-handler") { + return "Overwrite of errno in a signal handler"; + } else if (description == "lock-order-inversion") { + return "Lock order inversion (potential deadlock)"; + } + + // for unknown report codes just show the code + return description; +} + +static std::string +Sprintf(const char *format, ...) +{ + StreamString s; + va_list args; + va_start (args, format); + s.PrintfVarArg(format, args); + va_end (args); + return s.GetString(); +} + +static std::string +GetSymbolNameFromAddress(ProcessSP process_sp, addr_t addr) +{ + lldb_private::Address so_addr; + if (! process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) + return ""; + + lldb_private::Symbol *symbol = so_addr.CalculateSymbolContextSymbol(); + if (! symbol) + return ""; + + std::string sym_name = symbol->GetName().GetCString(); + return sym_name; +} + +static void +GetSymbolDeclarationFromAddress(ProcessSP process_sp, addr_t addr, Declaration &decl) +{ + lldb_private::Address so_addr; + if (! process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) + return; + + lldb_private::Symbol *symbol = so_addr.CalculateSymbolContextSymbol(); + if (! symbol) + return; + + ConstString sym_name = symbol->GetMangled().GetName(lldb::eLanguageTypeUnknown, Mangled::ePreferMangled); + + ModuleSP module = symbol->CalculateSymbolContextModule(); + if (! module) + return; + + VariableList var_list; + module->FindGlobalVariables(sym_name, nullptr, true, 1U, var_list); + if (var_list.GetSize() < 1) + return; + + VariableSP var = var_list.GetVariableAtIndex(0); + decl = var->GetDeclaration(); +} + +addr_t +ThreadSanitizerRuntime::GetFirstNonInternalFramePc(StructuredData::ObjectSP trace) +{ + ProcessSP process_sp = GetProcessSP(); + ModuleSP runtime_module_sp = GetRuntimeModuleSP(); + + addr_t result = 0; + trace->GetAsArray()->ForEach([process_sp, runtime_module_sp, &result] (StructuredData::Object *o) -> bool { + addr_t addr = o->GetIntegerValue(); + lldb_private::Address so_addr; + if (! process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) + return true; + + if (so_addr.GetModule() == runtime_module_sp) + return true; + + result = addr; + return false; + }); + + return result; +} + +std::string +ThreadSanitizerRuntime::GenerateSummary(StructuredData::ObjectSP report) +{ + ProcessSP process_sp = GetProcessSP(); + + std::string summary = report->GetAsDictionary()->GetValueForKey("description")->GetAsString()->GetValue(); + addr_t pc = 0; + if (report->GetAsDictionary()->GetValueForKey("mops")->GetAsArray()->GetSize() > 0) + pc = GetFirstNonInternalFramePc(report->GetAsDictionary()->GetValueForKey("mops")->GetAsArray()->GetItemAtIndex(0)->GetAsDictionary()->GetValueForKey("trace")); + + if (report->GetAsDictionary()->GetValueForKey("stacks")->GetAsArray()->GetSize() > 0) + pc = GetFirstNonInternalFramePc(report->GetAsDictionary()->GetValueForKey("stacks")->GetAsArray()->GetItemAtIndex(0)->GetAsDictionary()->GetValueForKey("trace")); + + if (pc != 0) { + summary = summary + " in " + GetSymbolNameFromAddress(process_sp, pc); + } + + if (report->GetAsDictionary()->GetValueForKey("locs")->GetAsArray()->GetSize() > 0) { + StructuredData::ObjectSP loc = report->GetAsDictionary()->GetValueForKey("locs")->GetAsArray()->GetItemAtIndex(0); + addr_t addr = loc->GetAsDictionary()->GetValueForKey("address")->GetAsInteger()->GetValue(); + if (addr == 0) + addr = loc->GetAsDictionary()->GetValueForKey("start")->GetAsInteger()->GetValue(); + + if (addr != 0) { + std::string global_name = GetSymbolNameFromAddress(process_sp, addr); + if (!global_name.empty()) { + summary = summary + " at " + global_name; + } else { + summary = summary + " at " + Sprintf("0x%llx", addr); + } + } else { + int fd = loc->GetAsDictionary()->GetValueForKey("file_descriptor")->GetAsInteger()->GetValue(); + if (fd != 0) { + summary = summary + " on file descriptor " + Sprintf("%d", fd); + } + } + } + + return summary; +} + +addr_t +ThreadSanitizerRuntime::GetMainRacyAddress(StructuredData::ObjectSP report) +{ + addr_t result = (addr_t)-1; + + report->GetObjectForDotSeparatedPath("mops")->GetAsArray()->ForEach([&result] (StructuredData::Object *o) -> bool { + addr_t addr = o->GetObjectForDotSeparatedPath("address")->GetIntegerValue(); + if (addr < result) result = addr; + return true; + }); + + return (result == (addr_t)-1) ? 0 : result; +} + +std::string +ThreadSanitizerRuntime::GetLocationDescription(StructuredData::ObjectSP report, addr_t &global_addr, std::string &global_name, std::string &filename, uint32_t &line) +{ + std::string result = ""; + + ProcessSP process_sp = GetProcessSP(); + + if (report->GetAsDictionary()->GetValueForKey("locs")->GetAsArray()->GetSize() > 0) { + StructuredData::ObjectSP loc = report->GetAsDictionary()->GetValueForKey("locs")->GetAsArray()->GetItemAtIndex(0); + std::string type = loc->GetAsDictionary()->GetValueForKey("type")->GetStringValue(); + if (type == "global") { + global_addr = loc->GetAsDictionary()->GetValueForKey("address")->GetAsInteger()->GetValue(); + global_name = GetSymbolNameFromAddress(process_sp, global_addr); + if (!global_name.empty()) { + result = Sprintf("'%s' is a global variable (0x%llx)", global_name.c_str(), global_addr); + } else { + result = Sprintf("0x%llx is a global variable", global_addr); + } + + Declaration decl; + GetSymbolDeclarationFromAddress(process_sp, global_addr, decl); + if (decl.GetFile()) { + filename = decl.GetFile().GetPath(); + line = decl.GetLine(); + } + } else if (type == "heap") { + addr_t addr = loc->GetAsDictionary()->GetValueForKey("start")->GetAsInteger()->GetValue(); + long size = loc->GetAsDictionary()->GetValueForKey("size")->GetAsInteger()->GetValue(); + result = Sprintf("Location is a %ld-byte heap object at 0x%llx", size, addr); + } else if (type == "stack") { + int tid = loc->GetAsDictionary()->GetValueForKey("thread_id")->GetAsInteger()->GetValue(); + result = Sprintf("Location is stack of thread %d", tid); + } else if (type == "tls") { + int tid = loc->GetAsDictionary()->GetValueForKey("thread_id")->GetAsInteger()->GetValue(); + result = Sprintf("Location is TLS of thread %d", tid); + } else if (type == "fd") { + int fd = loc->GetAsDictionary()->GetValueForKey("file_descriptor")->GetAsInteger()->GetValue(); + result = Sprintf("Location is file descriptor %d", fd); + } + } + + return result; +} + +bool +ThreadSanitizerRuntime::NotifyBreakpointHit(void *baton, StoppointCallbackContext *context, user_id_t break_id, user_id_t break_loc_id) +{ + assert (baton && "null baton"); + if (!baton) + return false; + + ThreadSanitizerRuntime *const instance = static_cast(baton); + + StructuredData::ObjectSP report = instance->RetrieveReportData(context->exe_ctx_ref); + std::string stop_reason_description; + if (report) { + std::string issue_description = instance->FormatDescription(report); + report->GetAsDictionary()->AddStringItem("description", issue_description); + stop_reason_description = issue_description + " detected"; + report->GetAsDictionary()->AddStringItem("stop_description", stop_reason_description); + std::string summary = instance->GenerateSummary(report); + report->GetAsDictionary()->AddStringItem("summary", summary); + addr_t main_address = instance->GetMainRacyAddress(report); + report->GetAsDictionary()->AddIntegerItem("memory_address", main_address); + + addr_t global_addr = 0; + std::string global_name = ""; + std::string location_filename = ""; + uint32_t location_line = 0; + std::string location_description = instance->GetLocationDescription(report, global_addr, global_name, location_filename, location_line); + report->GetAsDictionary()->AddStringItem("location_description", location_description); + if (global_addr != 0) { + report->GetAsDictionary()->AddIntegerItem("global_address", global_addr); + } + if (!global_name.empty()) { + report->GetAsDictionary()->AddStringItem("global_name", global_name); + } + if (location_filename != "") { + report->GetAsDictionary()->AddStringItem("location_filename", location_filename); + report->GetAsDictionary()->AddIntegerItem("location_line", location_line); + } + + bool all_addresses_are_same = true; + report->GetObjectForDotSeparatedPath("mops")->GetAsArray()->ForEach([&all_addresses_are_same, main_address] (StructuredData::Object *o) -> bool { + addr_t addr = o->GetObjectForDotSeparatedPath("address")->GetIntegerValue(); + if (main_address != addr) all_addresses_are_same = false; + return true; + }); + report->GetAsDictionary()->AddBooleanItem("all_addresses_are_same", all_addresses_are_same); + } + + ProcessSP process_sp = instance->GetProcessSP(); + // Make sure this is the right process + if (process_sp && process_sp == context->exe_ctx_ref.GetProcessSP()) + { + ThreadSP thread_sp = context->exe_ctx_ref.GetThreadSP(); + if (thread_sp) + thread_sp->SetStopInfo(InstrumentationRuntimeStopInfo::CreateStopReasonWithInstrumentationData(*thread_sp, stop_reason_description.c_str(), report)); + + StreamFileSP stream_sp (process_sp->GetTarget().GetDebugger().GetOutputFile()); + if (stream_sp) + { + stream_sp->Printf ("ThreadSanitizer report breakpoint hit. Use 'thread info -s' to get extended information about the report.\n"); + } + return true; // Return true to stop the target + } + else + return false; // Let target run +} + +void +ThreadSanitizerRuntime::Activate() +{ + if (m_is_active) + return; + + ProcessSP process_sp = GetProcessSP(); + if (!process_sp) + return; + + ConstString symbol_name ("__tsan_on_report"); + const Symbol *symbol = GetRuntimeModuleSP()->FindFirstSymbolWithNameAndType (symbol_name, eSymbolTypeCode); + + if (symbol == NULL) + return; + + if (!symbol->ValueIsAddress() || !symbol->GetAddressRef().IsValid()) + return; + + Target &target = process_sp->GetTarget(); + addr_t symbol_address = symbol->GetAddressRef().GetOpcodeLoadAddress(&target); + + if (symbol_address == LLDB_INVALID_ADDRESS) + return; + + bool internal = true; + bool hardware = false; + Breakpoint *breakpoint = process_sp->GetTarget().CreateBreakpoint(symbol_address, internal, hardware).get(); + breakpoint->SetCallback (ThreadSanitizerRuntime::NotifyBreakpointHit, this, true); + breakpoint->SetBreakpointKind ("thread-sanitizer-report"); + m_breakpoint_id = breakpoint->GetID(); + + StreamFileSP stream_sp (process_sp->GetTarget().GetDebugger().GetOutputFile()); + if (stream_sp) + { + stream_sp->Printf ("ThreadSanitizer debugger support is active.\n"); + } + + m_is_active = true; +} + +void +ThreadSanitizerRuntime::Deactivate() +{ + if (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; +} + +static std::string +GenerateThreadName(std::string path, StructuredData::Object *o, StructuredData::ObjectSP main_info) { + std::string result = "additional information"; + + if (path == "mops") { + int size = o->GetObjectForDotSeparatedPath("size")->GetIntegerValue(); + int thread_id = o->GetObjectForDotSeparatedPath("thread_id")->GetIntegerValue(); + bool is_write = o->GetObjectForDotSeparatedPath("is_write")->GetBooleanValue(); + bool is_atomic = o->GetObjectForDotSeparatedPath("is_atomic")->GetBooleanValue(); + addr_t addr = o->GetObjectForDotSeparatedPath("address")->GetIntegerValue(); + + std::string addr_string = Sprintf(" at 0x%llx", addr); + + if (main_info->GetObjectForDotSeparatedPath("all_addresses_are_same")->GetBooleanValue()){ + addr_string = ""; + } + + result = Sprintf("%s%s of size %d%s by thread %d", is_atomic ? "atomic " : "", is_write ? "write" : "read", size, addr_string.c_str(), thread_id); + } + + if (path == "threads") { + int thread_id = o->GetObjectForDotSeparatedPath("thread_id")->GetIntegerValue(); + result = Sprintf("Thread %d created", thread_id); + } + + if (path == "locs") { + std::string type = o->GetAsDictionary()->GetValueForKey("type")->GetStringValue(); + int thread_id = o->GetObjectForDotSeparatedPath("thread_id")->GetIntegerValue(); + int fd = o->GetObjectForDotSeparatedPath("file_descriptor")->GetIntegerValue(); + if (type == "heap") { + result = Sprintf("Heap block allocated by thread %d", thread_id); + } else if (type == "fd") { + result = Sprintf("File descriptor %d created by thread %t", fd, thread_id); + } + } + + if (path == "mutexes") { + int mutex_id = o->GetObjectForDotSeparatedPath("mutex_id")->GetIntegerValue(); + + result = Sprintf("Mutex M%d created", mutex_id); + } + + if (path == "stacks") { + int thread_id = o->GetObjectForDotSeparatedPath("thread_id")->GetIntegerValue(); + result = Sprintf("Thread %d", thread_id); + } + + result[0] = toupper(result[0]); + + return result; +} + +static void +AddThreadsForPath(std::string path, ThreadCollectionSP threads, ProcessSP process_sp, StructuredData::ObjectSP info) +{ + info->GetObjectForDotSeparatedPath(path)->GetAsArray()->ForEach([process_sp, threads, path, info] (StructuredData::Object *o) -> bool { + std::vector pcs; + o->GetObjectForDotSeparatedPath("trace")->GetAsArray()->ForEach([&pcs] (StructuredData::Object *pc) -> bool { + pcs.push_back(pc->GetAsInteger()->GetValue()); + return true; + }); + + if (pcs.size() == 0) + return true; + + StructuredData::ObjectSP thread_id_obj = o->GetObjectForDotSeparatedPath("thread_os_id"); + tid_t tid = thread_id_obj ? thread_id_obj->GetIntegerValue() : 0; + + uint32_t stop_id = 0; + bool stop_id_is_valid = false; + HistoryThread *history_thread = new HistoryThread(*process_sp, tid, pcs, stop_id, stop_id_is_valid); + ThreadSP new_thread_sp(history_thread); + new_thread_sp->SetName(GenerateThreadName(path, o, info).c_str()); + + // Save this in the Process' ExtendedThreadList so a strong pointer retains the object + process_sp->GetExtendedThreadList().AddThread(new_thread_sp); + threads->AddThread(new_thread_sp); + + return true; + }); +} + +lldb::ThreadCollectionSP +ThreadSanitizerRuntime::GetBacktracesFromExtendedStopInfo(StructuredData::ObjectSP info) +{ + ThreadCollectionSP threads; + threads.reset(new ThreadCollection()); + + if (info->GetObjectForDotSeparatedPath("instrumentation_class")->GetStringValue() != "ThreadSanitizer") + return threads; + + ProcessSP process_sp = GetProcessSP(); + + AddThreadsForPath("stacks", threads, process_sp, info); + AddThreadsForPath("mops", threads, process_sp, info); + AddThreadsForPath("locs", threads, process_sp, info); + AddThreadsForPath("mutexes", threads, process_sp, info); + AddThreadsForPath("threads", threads, process_sp, info); + + return threads; +} diff --git a/source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.h b/source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.h new file mode 100644 index 000000000000..ca7af23aa3bd --- /dev/null +++ b/source/Plugins/InstrumentationRuntime/ThreadSanitizer/ThreadSanitizerRuntime.h @@ -0,0 +1,119 @@ +//===-- ThreadSanitizerRuntime.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_ThreadSanitizerRuntime_h_ +#define liblldb_ThreadSanitizerRuntime_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" +#include "lldb/Target/Process.h" +#include "lldb/Core/StructuredData.h" + +namespace lldb_private { + +class ThreadSanitizerRuntime : public lldb_private::InstrumentationRuntime +{ +public: + ~ThreadSanitizerRuntime() override; + + static lldb::InstrumentationRuntimeSP + CreateInstance (const lldb::ProcessSP &process_sp); + + static void + Initialize(); + + static void + Terminate(); + + static lldb_private::ConstString + GetPluginNameStatic(); + + static lldb::InstrumentationRuntimeType + GetTypeStatic(); + + lldb_private::ConstString + GetPluginName() override + { + return GetPluginNameStatic(); + } + + virtual lldb::InstrumentationRuntimeType + GetType() { return GetTypeStatic(); } + + uint32_t + GetPluginVersion() override + { + return 1; + } + + void + ModulesDidLoad(lldb_private::ModuleList &module_list) override; + + bool + IsActive() override; + + lldb::ThreadCollectionSP + GetBacktracesFromExtendedStopInfo(StructuredData::ObjectSP info) override; + +private: + ThreadSanitizerRuntime(const lldb::ProcessSP &process_sp); + + lldb::ProcessSP + GetProcessSP () + { + return m_process_wp.lock(); + } + + lldb::ModuleSP + GetRuntimeModuleSP () + { + return m_runtime_module_wp.lock(); + } + + void + Activate(); + + void + Deactivate(); + + static bool + NotifyBreakpointHit(void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id); + + StructuredData::ObjectSP + RetrieveReportData(ExecutionContextRef exe_ctx_ref); + + std::string + FormatDescription(StructuredData::ObjectSP report); + + std::string + GenerateSummary(StructuredData::ObjectSP report); + + lldb::addr_t + GetMainRacyAddress(StructuredData::ObjectSP report); + + std::string + GetLocationDescription(StructuredData::ObjectSP report, lldb::addr_t &global_addr, std::string &global_name, std::string &filename, uint32_t &line); + + lldb::addr_t + GetFirstNonInternalFramePc(StructuredData::ObjectSP trace); + + bool m_is_active; + lldb::ModuleWP m_runtime_module_wp; + lldb::ProcessWP m_process_wp; + lldb::user_id_t m_breakpoint_id; +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadSanitizerRuntime_h_ diff --git a/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp index 143e44794057..a126ad026a55 100644 --- a/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp +++ b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp @@ -9,7 +9,10 @@ // C Includes +#include "llvm/Support/MathExtras.h" + #include "lldb/Breakpoint/Breakpoint.h" +#include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" @@ -22,12 +25,41 @@ #include "lldb/Target/Process.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/LLDBAssert.h" #include "JITLoaderGDB.h" using namespace lldb; using namespace lldb_private; +//------------------------------------------------------------------ +// Debug Interface Structures +//------------------------------------------------------------------ +typedef enum +{ + JIT_NOACTION = 0, + JIT_REGISTER_FN, + JIT_UNREGISTER_FN +} jit_actions_t; + +template +struct jit_code_entry +{ + ptr_t next_entry; // pointer + ptr_t prev_entry; // pointer + ptr_t symfile_addr; // pointer + uint64_t symfile_size; +}; + +template +struct jit_descriptor +{ + uint32_t version; + uint32_t action_flag; // Values are jit_action_t + ptr_t relevant_entry; // pointer + ptr_t first_entry; // pointer +}; + namespace { PropertyDefinition @@ -78,34 +110,34 @@ namespace { return g_settings_sp; } -} // anonymous namespace end + template + bool ReadJITEntry(const addr_t from_addr, Process *process, jit_code_entry *entry) + { + lldbassert(from_addr % sizeof(ptr_t) == 0); -//------------------------------------------------------------------ -// Debug Interface Structures -//------------------------------------------------------------------ -typedef enum -{ - JIT_NOACTION = 0, - JIT_REGISTER_FN, - JIT_UNREGISTER_FN -} jit_actions_t; + ArchSpec::Core core = process->GetTarget().GetArchitecture().GetCore(); + bool i386_target = ArchSpec::kCore_x86_32_first <= core && core <= ArchSpec::kCore_x86_32_last; + uint8_t uint64_align_bytes = i386_target ? 4 : 8; + const size_t data_byte_size = llvm::alignTo(sizeof(ptr_t) * 3, uint64_align_bytes) + sizeof(uint64_t); -template -struct jit_code_entry -{ - ptr_t next_entry; // pointer - ptr_t prev_entry; // pointer - ptr_t symfile_addr; // pointer - uint64_t symfile_size; -}; -template -struct jit_descriptor -{ - uint32_t version; - uint32_t action_flag; // Values are jit_action_t - ptr_t relevant_entry; // pointer - ptr_t first_entry; // pointer -}; + Error error; + DataBufferHeap data(data_byte_size, 0); + size_t bytes_read = process->ReadMemory(from_addr, data.GetBytes(), data.GetByteSize(), error); + if (bytes_read != data_byte_size || !error.Success()) + return false; + + DataExtractor extractor (data.GetBytes(), data.GetByteSize(), process->GetByteOrder(), sizeof(ptr_t)); + lldb::offset_t offset = 0; + entry->next_entry = extractor.GetPointer(&offset); + entry->prev_entry = extractor.GetPointer(&offset); + entry->symfile_addr = extractor.GetPointer(&offset); + offset = llvm::alignTo(offset, uint64_align_bytes); + entry->symfile_size = extractor.GetU64(&offset); + + return true; + } + +} // anonymous namespace end JITLoaderGDB::JITLoaderGDB (lldb_private::Process *process) : JITLoader(process), @@ -268,8 +300,7 @@ static void updateSectionLoadAddress(const SectionList §ion_list, bool JITLoaderGDB::ReadJITDescriptor(bool all_entries) { - Target &target = m_process->GetTarget(); - if (target.GetArchitecture().GetAddressByteSize() == 8) + if (m_process->GetTarget().GetArchitecture().GetAddressByteSize() == 8) return ReadJITDescriptorImpl(all_entries); else return ReadJITDescriptorImpl(all_entries); @@ -310,9 +341,7 @@ JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) while (jit_relevant_entry != 0) { jit_code_entry jit_entry; - const size_t jit_entry_size = sizeof(jit_entry); - bytes_read = m_process->DoReadMemory(jit_relevant_entry, &jit_entry, jit_entry_size, error); - if (bytes_read != jit_entry_size || !error.Success()) + if (!ReadJITEntry(jit_relevant_entry, m_process, &jit_entry)) { if (log) log->Printf( @@ -340,7 +369,9 @@ JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) if (module_sp && module_sp->GetObjectFile()) { - bool changed; + // load the symbol table right away + module_sp->GetObjectFile()->GetSymtab(); + m_jit_objects.insert(std::make_pair(symbolfile_addr, module_sp)); if (module_sp->GetObjectFile()->GetPluginName() == ConstString("mach-o")) { @@ -360,12 +391,10 @@ JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) } else { + bool changed = false; module_sp->SetLoadAddress(target, 0, true, changed); } - // load the symbol table right away - module_sp->GetObjectFile()->GetSymtab(); - module_list.AppendIfNeeded(module_sp); ModuleList module_list; diff --git a/source/Plugins/JITLoader/GDB/Makefile b/source/Plugins/JITLoader/GDB/Makefile deleted file mode 100644 index cd5404ffca18..000000000000 --- a/source/Plugins/JITLoader/GDB/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/JITLoader/GDB/Makefile ---------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginJITLoaderGDB -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Language/CMakeLists.txt b/source/Plugins/Language/CMakeLists.txt index 60b3da2406b6..725138a56c8e 100644 --- a/source/Plugins/Language/CMakeLists.txt +++ b/source/Plugins/Language/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(CPlusPlus) add_subdirectory(Go) +add_subdirectory(Java) add_subdirectory(ObjC) add_subdirectory(ObjCPlusPlus) diff --git a/source/Plugins/Language/CPlusPlus/BlockPointer.cpp b/source/Plugins/Language/CPlusPlus/BlockPointer.cpp new file mode 100644 index 000000000000..92e30d54f6e1 --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/BlockPointer.cpp @@ -0,0 +1,225 @@ +//===-- BlockPointer.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 "BlockPointer.h" + +#include "lldb/Core/ValueObject.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ClangASTImporter.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Symbol/TypeSystem.h" +#include "lldb/Target/Target.h" + +#include "lldb/Utility/LLDBAssert.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +namespace lldb_private +{ +namespace formatters +{ + +class BlockPointerSyntheticFrontEnd : public SyntheticChildrenFrontEnd +{ +public: + BlockPointerSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) + : SyntheticChildrenFrontEnd(*valobj_sp), + m_block_struct_type() + { + CompilerType block_pointer_type(m_backend.GetCompilerType()); + CompilerType function_pointer_type; + block_pointer_type.IsBlockPointerType(&function_pointer_type); + + TargetSP target_sp(m_backend.GetTargetSP()); + + if (!target_sp) + { + return; + } + + Error err; + TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage(&err, lldb::eLanguageTypeC_plus_plus); + + if (!err.Success() || !type_system) + { + return; + } + + ClangASTContext *clang_ast_context = llvm::dyn_cast(type_system); + + if (!clang_ast_context) + { + return; + } + + ClangASTImporterSP clang_ast_importer = target_sp->GetClangASTImporter(); + + if (!clang_ast_importer) + { + return; + } + + const char *const isa_name("__isa"); + const CompilerType isa_type = clang_ast_context->GetBasicType(lldb::eBasicTypeObjCClass); + const char *const flags_name("__flags"); + const CompilerType flags_type = clang_ast_context->GetBasicType(lldb::eBasicTypeInt); + const char *const reserved_name("__reserved"); + const CompilerType reserved_type = clang_ast_context->GetBasicType(lldb::eBasicTypeInt); + const char *const FuncPtr_name("__FuncPtr"); + const CompilerType FuncPtr_type = clang_ast_importer->CopyType(*clang_ast_context, function_pointer_type); + + m_block_struct_type = clang_ast_context->CreateStructForIdentifier(ConstString(), + { + {isa_name, isa_type}, + {flags_name, flags_type}, + {reserved_name, reserved_type}, + {FuncPtr_name, FuncPtr_type} + }); + + } + + ~BlockPointerSyntheticFrontEnd() override = default; + + size_t + CalculateNumChildren() override + { + const bool omit_empty_base_classes = false; + return m_block_struct_type.GetNumChildren(omit_empty_base_classes); + } + + lldb::ValueObjectSP + GetChildAtIndex(size_t idx) override + { + if (!m_block_struct_type.IsValid()) + { + return lldb::ValueObjectSP(); + } + + if (idx >= CalculateNumChildren()) + { + return lldb::ValueObjectSP(); + } + + const bool thread_and_frame_only_if_stopped = true; + ExecutionContext exe_ctx = m_backend.GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped); + const bool transparent_pointers = false; + const bool omit_empty_base_classes = false; + const bool ignore_array_bounds = false; + ValueObject *value_object = nullptr; + + std::string child_name; + uint32_t child_byte_size = 0; + int32_t child_byte_offset = 0; + uint32_t child_bitfield_bit_size = 0; + uint32_t child_bitfield_bit_offset = 0; + bool child_is_base_class = false; + bool child_is_deref_of_parent = false; + uint64_t language_flags = 0; + + const CompilerType child_type = m_block_struct_type.GetChildCompilerTypeAtIndex(&exe_ctx, idx, transparent_pointers, omit_empty_base_classes, ignore_array_bounds, child_name, child_byte_size, child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent, value_object, language_flags); + + ValueObjectSP struct_pointer_sp = m_backend.Cast(m_block_struct_type.GetPointerType()); + + if (!struct_pointer_sp) + { + return lldb::ValueObjectSP(); + } + + Error err; + ValueObjectSP struct_sp = struct_pointer_sp->Dereference(err); + + if (!struct_sp || !err.Success()) + { + return lldb::ValueObjectSP(); + } + + ValueObjectSP child_sp(struct_sp->GetSyntheticChildAtOffset(child_byte_offset, + child_type, + true, + ConstString(child_name.c_str(), child_name.size()))); + + return child_sp; + } + + // return true if this object is now safe to use forever without + // ever updating again; the typical (and tested) answer here is + // 'false' + bool + Update() override + { + return false; + } + + // maybe return false if the block pointer is, say, null + bool + MightHaveChildren() override + { + return true; + } + + size_t + GetIndexOfChildWithName(const ConstString &name) override + { + if (!m_block_struct_type.IsValid()) + return UINT32_MAX; + + const bool omit_empty_base_classes = false; + return m_block_struct_type.GetIndexOfChildWithName(name.AsCString(), omit_empty_base_classes); + } + +private: + CompilerType m_block_struct_type; +}; + +} // namespace formatters +} // namespace lldb_private + +bool +lldb_private::formatters::BlockPointerSummaryProvider(ValueObject &valobj, Stream &s, const TypeSummaryOptions &) +{ + lldb_private::SyntheticChildrenFrontEnd *synthetic_children = BlockPointerSyntheticFrontEndCreator(nullptr, valobj.GetSP()); + if (!synthetic_children) + { + return false; + } + + synthetic_children->Update(); + + static const ConstString s_FuncPtr_name("__FuncPtr"); + + lldb::ValueObjectSP child_sp = synthetic_children->GetChildAtIndex(synthetic_children->GetIndexOfChildWithName(s_FuncPtr_name)); + + if (!child_sp) + { + return false; + } + + lldb::ValueObjectSP qualified_child_representation_sp = child_sp->GetQualifiedRepresentationIfAvailable(lldb::eDynamicDontRunTarget, true); + + const char *child_value = qualified_child_representation_sp->GetValueAsCString(); + + s.Printf("%s", child_value); + + return true; +} + +lldb_private::SyntheticChildrenFrontEnd * +lldb_private::formatters::BlockPointerSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) +{ + if (!valobj_sp) + return nullptr; + return new BlockPointerSyntheticFrontEnd(valobj_sp); +} diff --git a/source/Plugins/Language/CPlusPlus/BlockPointer.h b/source/Plugins/Language/CPlusPlus/BlockPointer.h new file mode 100644 index 000000000000..5e6c748b5dbb --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/BlockPointer.h @@ -0,0 +1,27 @@ +//===-- BlockPointer.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_BlockPointer_h_ +#define liblldb_BlockPointer_h_ + +#include "lldb/lldb-forward.h" + +namespace lldb_private +{ +namespace formatters +{ +bool +BlockPointerSummaryProvider(ValueObject &, Stream &, const TypeSummaryOptions &); + +SyntheticChildrenFrontEnd * +BlockPointerSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP); +} // namespace formatters +} // namespace lldb_private + +#endif // liblldb_BlockPointer_h_ diff --git a/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/source/Plugins/Language/CPlusPlus/CMakeLists.txt index 0b0f0f451a8d..de0dc99d85dd 100644 --- a/source/Plugins/Language/CPlusPlus/CMakeLists.txt +++ b/source/Plugins/Language/CPlusPlus/CMakeLists.txt @@ -1,7 +1,9 @@ add_lldb_library(lldbPluginCPlusPlusLanguage + BlockPointer.cpp CPlusPlusLanguage.cpp CxxStringTypes.cpp LibCxx.cpp + LibCxxAtomic.cpp LibCxxInitializerList.cpp LibCxxList.cpp LibCxxMap.cpp diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 09031e2f8064..33d22bf2e583 100644 --- a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -1,4 +1,4 @@ -//===-- CPlusPlusLanguage.cpp --------------------------------------*- C++ -*-===// +//===-- CPlusPlusLanguage.cpp -----------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -9,9 +9,17 @@ #include "CPlusPlusLanguage.h" +// C Includes +// C++ Includes +#include +#include +#include +#include +// Other libraries and framework includes #include "llvm/ADT/StringRef.h" +// Project includes #include "lldb/Core/ConstString.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/RegularExpression.h" @@ -21,15 +29,12 @@ #include "lldb/DataFormatters/FormattersHelpers.h" #include "lldb/DataFormatters/VectorType.h" +#include "BlockPointer.h" #include "CxxStringTypes.h" #include "LibCxx.h" +#include "LibCxxAtomic.h" #include "LibStdcpp.h" -#include -#include -#include -#include - using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; @@ -55,10 +60,10 @@ CPlusPlusLanguage::GetPluginNameStatic() return g_name; } - //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + lldb_private::ConstString CPlusPlusLanguage::GetPluginName() { @@ -74,6 +79,7 @@ CPlusPlusLanguage::GetPluginVersion() //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + Language * CPlusPlusLanguage::CreateInstance (lldb::LanguageType language) { @@ -319,16 +325,13 @@ CPlusPlusLanguage::IsCPPMangledName (const char *name) // 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; + return (name != nullptr && name[0] == '_' && name[1] == 'Z'); } 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]*)$"); + 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)) { @@ -344,7 +347,6 @@ class CPPRuntimeEquivalents public: CPPRuntimeEquivalents () { - m_impl.Append(ConstString("std::basic_string, std::allocator >").AsCString(), ConstString("basic_string")); // these two (with a prefixed std::) occur when c++stdlib string class occurs as a template argument in some STL container @@ -364,11 +366,10 @@ public: FindExactMatches (ConstString& type_name, std::vector& equivalents) { - uint32_t count = 0; for (ImplData match = m_impl.FindFirstValueForName(type_name.AsCString()); - match != NULL; + match != nullptr; match = m_impl.FindNextValueForName(match)) { equivalents.push_back(match->value); @@ -387,7 +388,6 @@ public: FindPartialMatches (ConstString& type_name, std::vector& equivalents) { - uint32_t count = 0; const char* type_name_cstr = type_name.AsCString(); @@ -406,11 +406,9 @@ public: } return count; - } private: - std::string& replace (std::string& target, std::string& pattern, std::string& with) @@ -429,14 +427,13 @@ private: const char *matching_key, std::vector& 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 != nullptr; match = m_impl.FindNextValueForName(match)) { std::string target(original); @@ -470,7 +467,6 @@ GetEquivalentsMap () return g_equivalents_map; } - uint32_t CPlusPlusLanguage::FindEquivalentNames(ConstString type_name, std::vector& equivalents) { @@ -478,8 +474,8 @@ CPlusPlusLanguage::FindEquivalentNames(ConstString type_name, std::vector') != NULL); // angle brackets in the type_name before trying to scan for partial matches + && (strchr(type_name.AsCString(), '<') != nullptr // we should only have partial matches when templates are involved, check that we have + && strchr(type_name.AsCString(), '>') != nullptr); // angle brackets in the type_name before trying to scan for partial matches if ( might_have_partials ) count = GetEquivalentsMap().FindPartialMatches(type_name, equivalents); @@ -508,60 +504,66 @@ LoadLibCxxFormatters (lldb::TypeCategoryImplSP cpp_category_sp) cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::string"), std_string_summary_sp); + cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__ndk1::string"), + std_string_summary_sp); cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::basic_string, std::__1::allocator >"), std_string_summary_sp); + cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__ndk1::basic_string, std::__ndk1::allocator >"), + std_string_summary_sp); cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::wstring"), std_wstring_summary_sp); + cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__ndk1::wstring"), + std_wstring_summary_sp); cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::basic_string, std::__1::allocator >"), std_wstring_summary_sp); + cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__ndk1::basic_string, std::__ndk1::allocator >"), + 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 synthetic children", ConstString("std::__1::vector >"), stl_synth_flags); - AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector synthetic children", ConstString("std::__1::vector >"), 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::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector synthetic children", ConstString("^std::__(ndk)?1::vector >$"), stl_synth_flags, true); + AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator, "libc++ std::vector synthetic children", ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"), stl_synth_flags, true); + AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator, "libc++ std::list synthetic children", ConstString("^std::__(ndk)?1::list<.+>(( )?&)?$"), stl_synth_flags, true); + AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::map synthetic children", ConstString("^std::__(ndk)?1::map<.+> >(( )?&)?$"), stl_synth_flags, true); + AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector synthetic children", ConstString("std::__(ndk)?1::vector >"), stl_synth_flags); + AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector synthetic children", ConstString("std::__(ndk)?1::vector >"), stl_synth_flags); + AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::set synthetic children", ConstString("^std::__(ndk)?1::set<.+> >(( )?&)?$"), stl_synth_flags, true); + AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multiset synthetic children", ConstString("^std::__(ndk)?1::multiset<.+> >(( )?&)?$"), stl_synth_flags, true); + AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multimap synthetic children", ConstString("^std::__(ndk)?1::multimap<.+> >(( )?&)?$"), stl_synth_flags, true); + AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator, "libc++ std::unordered containers synthetic children", ConstString("^(std::__(ndk)?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<.+>(( )?&)?$")), + AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator, "libc++ std::atomic synthetic children", ConstString("^std::__(ndk)?1::atomic<.+>$"), stl_synth_flags, true); + + cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^(std::__(ndk)?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); + AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator, "shared_ptr synthetic children", ConstString("^(std::__(ndk)?1::)shared_ptr<.+>(( )?&)?$"), stl_synth_flags, true); + AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator, "weak_ptr synthetic children", ConstString("^(std::__(ndk)?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 synthetic children", ConstString("std::__1::vector >"), 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 summary provider", ConstString("std::__1::vector >"), stl_summary_flags); - AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector summary provider", ConstString("std::__1::vector >"), 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); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector summary provider", ConstString("std::__(ndk)?1::vector >"), stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector summary provider", ConstString("^std::__(ndk)?1::vector<.+>(( )?&)?$"), stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::list summary provider", ConstString("^std::__(ndk)?1::list<.+>(( )?&)?$"), stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::map summary provider", ConstString("^std::__(ndk)?1::map<.+>(( )?&)?$"), stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::deque summary provider", ConstString("^std::__(ndk)?1::deque<.+>(( )?&)?$"), stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::set summary provider", ConstString("^std::__(ndk)?1::set<.+>(( )?&)?$"), stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multiset summary provider", ConstString("^std::__(ndk)?1::multiset<.+>(( )?&)?$"), stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multimap summary provider", ConstString("^std::__(ndk)?1::multimap<.+>(( )?&)?$"), stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::unordered containers summary provider", ConstString("^(std::__(ndk)?1::)unordered_(multi)?(map|set)<.+> >$"), stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibCxxAtomicSummaryProvider, "libc++ std::atomic summary provider", ConstString("^std::__(ndk)?1::atomic<.+>$"), 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::LibcxxSmartPointerSummaryProvider, "libc++ std::shared_ptr summary provider", ConstString("^std::__(ndk)?1::shared_ptr<.+>(( )?&)?$"), stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxSmartPointerSummaryProvider, "libc++ std::weak_ptr summary provider", ConstString("^std::__(ndk)?1::weak_ptr<.+>(( )?&)?$"), stl_summary_flags, true); - AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector summary provider", ConstString("std::__1::vector >"), 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); + AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^std::__(ndk)?1::__wrap_iter<.+>$"), stl_synth_flags, true); - AddFilter(cpp_category_sp, {"__a_"}, "libc++ std::atomic filter", ConstString("^std::__1::atomic<.*>$"), stl_synth_flags, true); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector summary provider", ConstString("std::__(ndk)?1::vector >"), stl_summary_flags); + AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::__(ndk)?1::__map_iterator<.+>$"), stl_synth_flags, true); #endif } @@ -648,8 +650,22 @@ LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) "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); + + AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator, + "std::shared_ptr synthetic children", ConstString("^std::shared_ptr<.+>(( )?&)?$"), stl_synth_flags, + true); + AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator, + "std::weak_ptr synthetic children", ConstString("^std::weak_ptr<.+>(( )?&)?$"), stl_synth_flags, + true); + + AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibStdcppSmartPointerSummaryProvider, + "libstdc++ std::shared_ptr summary provider", ConstString("^std::shared_ptr<.+>(( )?&)?$"), + stl_summary_flags, true); + AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibStdcppSmartPointerSummaryProvider, + "libstdc++ std::weak_ptr summary provider", ConstString("^std::weak_ptr<.+>(( )?&)?$"), + stl_summary_flags, true); #endif } @@ -774,6 +790,25 @@ CPlusPlusLanguage::GetHardcodedSummaries () } 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::BlockPointerSummaryProvider, + "block pointer summary provider")); + if (valobj.GetCompilerType().IsBlockPointerType(nullptr)) + { + return formatter_sp; + } + return nullptr; + }); }); return g_formatters; @@ -801,8 +836,21 @@ CPlusPlusLanguage::GetHardcodedSynthetics () } return nullptr; }); + 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), + "block pointer synthetic children", + lldb_private::formatters::BlockPointerSyntheticFrontEndCreator)); + if (valobj.GetCompilerType().IsBlockPointerType(nullptr)) + { + return formatter_sp; + } + return nullptr; + }); + }); return g_formatters; } - diff --git a/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp b/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp index 7e8d9582a2b5..a2c45fb99893 100644 --- a/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp +++ b/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp @@ -192,6 +192,14 @@ lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& str if (error.Fail()) 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::ReadBufferAndDumpToStreamOptions options(valobj); options.SetData(data); options.SetStream(&stream); @@ -200,5 +208,17 @@ lldb_private::formatters::WCharSummaryProvider (ValueObject& valobj, Stream& str options.SetSourceSize(1); options.SetBinaryZeroIsTerminator(false); - return StringPrinter::ReadBufferAndDumpToStream(options); + switch (wchar_size) + { + case 8: + return StringPrinter::ReadBufferAndDumpToStream(options); + case 16: + return StringPrinter::ReadBufferAndDumpToStream(options); + case 32: + return StringPrinter::ReadBufferAndDumpToStream(options); + default: + stream.Printf("size for wchar_t is not valid"); + return true; + } + return true; } diff --git a/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/source/Plugins/Language/CPlusPlus/LibCxx.cpp index 950bd62c5c9f..beb89b89c635 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxx.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxx.cpp @@ -9,6 +9,10 @@ #include "LibCxx.h" +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Error.h" @@ -74,12 +78,12 @@ lldb_private::formatters::LibcxxSmartPointerSummaryProvider (ValueObject& valobj } 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() + SyntheticChildrenFrontEnd(*valobj_sp), + m_bool_type(), + m_exe_ctx_ref(), + m_count(0), + m_base_data_address(0), + m_children() { if (valobj_sp) { @@ -141,7 +145,7 @@ lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex (si return ValueObjectSP(); } bool bit_set = ((byte & mask) != 0); - DataBufferSP buffer_sp(new DataBufferHeap(m_bool_type.GetByteSize(nullptr),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); @@ -208,15 +212,12 @@ lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetIndexOfChildWith return idx; } -lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd () -{} +lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::~LibcxxVectorBoolSyntheticFrontEnd() = default; SyntheticChildrenFrontEnd* lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) { - if (!valobj_sp) - return NULL; - return (new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp)); + return (valobj_sp ? new LibcxxVectorBoolSyntheticFrontEnd(valobj_sp) : nullptr); } /* @@ -238,8 +239,8 @@ lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator (CXXSynthetic */ lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::LibCxxMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd(*valobj_sp.get()), -m_pair_ptr() + SyntheticChildrenFrontEnd(*valobj_sp), + m_pair_ptr() { if (valobj_sp) Update(); @@ -264,11 +265,11 @@ lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() // 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(); + nullptr, + nullptr, + nullptr, + ValueObject::GetValueForExpressionPathOptions().DontCheckDotVsArrowSyntax().SetSyntheticChildrenTraversal(ValueObject::GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None), + nullptr).get(); return false; } @@ -312,9 +313,7 @@ lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::~LibCxxMapIterator SyntheticChildrenFrontEnd* lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) { - if (!valobj_sp) - return NULL; - return (new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp)); + return (valobj_sp ? new LibCxxMapIteratorSyntheticFrontEnd(valobj_sp) : nullptr); } /* @@ -332,18 +331,16 @@ lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator (CXXSynth 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)); + return (valobj_sp ? new VectorIteratorSyntheticFrontEnd(valobj_sp, g_item_name) : nullptr); } 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) + SyntheticChildrenFrontEnd(*valobj_sp), + m_cntrl(nullptr), + m_count_sp(), + m_weak_count_sp(), + m_ptr_size(0), + m_byte_order(lldb::eByteOrderInvalid) { if (valobj_sp) Update(); @@ -404,7 +401,7 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::Update() { m_count_sp.reset(); m_weak_count_sp.reset(); - m_cntrl = NULL; + m_cntrl = nullptr; ValueObjectSP valobj_sp = m_backend.GetSP(); if (!valobj_sp) @@ -441,15 +438,12 @@ lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::GetIndexOfChildWithN return UINT32_MAX; } -lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::~LibcxxSharedPtrSyntheticFrontEnd () -{} +lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEnd::~LibcxxSharedPtrSyntheticFrontEnd() = default; SyntheticChildrenFrontEnd* lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) { - if (!valobj_sp) - return NULL; - return (new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp)); + return (valobj_sp ? new LibcxxSharedPtrSyntheticFrontEnd(valobj_sp) : nullptr); } bool @@ -462,7 +456,7 @@ lldb_private::formatters::LibcxxContainerSummaryProvider (ValueObject& valobj, S return false; stream.Printf("0x%016" PRIx64 " ", value); } - return FormatEntity::FormatStringRef("size=${svar%#}", stream, NULL, NULL, NULL, &valobj, false, false); + return FormatEntity::FormatStringRef("size=${svar%#}", stream, nullptr, nullptr, nullptr, &valobj, false, false); } // the field layout in a libc++ string (cap, side, data or data, size, cap) @@ -551,7 +545,7 @@ bool lldb_private::formatters::LibcxxWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options) { uint64_t size = 0; - ValueObjectSP location_sp((ValueObject*)nullptr); + ValueObjectSP location_sp; if (!ExtractLibcxxStringInfo(valobj, location_sp, size)) return false; if (size == 0) @@ -613,7 +607,7 @@ bool lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& summary_options) { uint64_t size = 0; - ValueObjectSP location_sp((ValueObject*)nullptr); + ValueObjectSP location_sp; if (!ExtractLibcxxStringInfo(valobj, location_sp, size)) return false; @@ -643,7 +637,7 @@ lldb_private::formatters::LibcxxStringSummaryProvider (ValueObject& valobj, Stre options.SetData(extractor); options.SetStream(&stream); - options.SetPrefixToken(0); + options.SetPrefixToken(nullptr); options.SetQuote('"'); options.SetSourceSize(size); options.SetBinaryZeroIsTerminator(false); diff --git a/source/Plugins/Language/CPlusPlus/LibCxxAtomic.cpp b/source/Plugins/Language/CPlusPlus/LibCxxAtomic.cpp new file mode 100644 index 000000000000..a20d7f7d9871 --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibCxxAtomic.cpp @@ -0,0 +1,121 @@ +//===-- LibCxxAtomic.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "LibCxxAtomic.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +bool +lldb_private::formatters::LibCxxAtomicSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options) +{ + static ConstString g___a_("__a_"); + + if (ValueObjectSP child = valobj.GetChildMemberWithName(g___a_, true)) + { + std::string summary; + if (child->GetSummaryAsCString(summary, options) && summary.size() > 0) + { + stream.Printf("%s", summary.c_str()); + return true; + } + } + + return false; +} + +namespace lldb_private { + namespace formatters { + class LibcxxStdAtomicSyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + LibcxxStdAtomicSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + ~LibcxxStdAtomicSyntheticFrontEnd() 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; + + lldb::ValueObjectSP + GetSyntheticValue () override; + private: + ValueObject *m_real_child; + }; + } // namespace formatters +} // namespace lldb_private + +lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::LibcxxStdAtomicSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : + SyntheticChildrenFrontEnd(*valobj_sp), + m_real_child(nullptr) +{ +} + +bool +lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::Update() +{ + static ConstString g___a_("__a_"); + + m_real_child = m_backend.GetChildMemberWithName(g___a_, true).get(); + + return false; +} + +bool +lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::MightHaveChildren() +{ + return true; +} + +size_t +lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::CalculateNumChildren() +{ + return m_real_child ? m_real_child->GetNumChildren() : 0; +} + +lldb::ValueObjectSP +lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::GetChildAtIndex(size_t idx) +{ + return m_real_child ? m_real_child->GetChildAtIndex(idx, true) : nullptr; +} + +size_t +lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::GetIndexOfChildWithName(const ConstString &name) +{ + return m_real_child ? m_real_child->GetIndexOfChildWithName(name) : UINT32_MAX; +} + +lldb::ValueObjectSP +lldb_private::formatters::LibcxxStdAtomicSyntheticFrontEnd::GetSyntheticValue () +{ + if (m_real_child && m_real_child->CanProvideValue()) + return m_real_child->GetSP(); + return nullptr; +} + +SyntheticChildrenFrontEnd* +lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ + if (valobj_sp) + return new LibcxxStdAtomicSyntheticFrontEnd(valobj_sp); + return nullptr; +} + diff --git a/source/Plugins/Language/CPlusPlus/LibCxxAtomic.h b/source/Plugins/Language/CPlusPlus/LibCxxAtomic.h new file mode 100644 index 000000000000..5cf729bfa45f --- /dev/null +++ b/source/Plugins/Language/CPlusPlus/LibCxxAtomic.h @@ -0,0 +1,29 @@ +//===-- LibCxxAtomic.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_LibCxxAtomic_h_ +#define liblldb_LibCxxAtomic_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 + LibCxxAtomicSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); + + SyntheticChildrenFrontEnd* LibcxxAtomicSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + } // namespace formatters +} // namespace lldb_private + +#endif // liblldb_LibCxxAtomic_h_ diff --git a/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp b/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp index 9970d49dac62..54fddd15dd0b 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp @@ -50,18 +50,16 @@ namespace lldb_private { CompilerType m_element_type; uint32_t m_element_size; size_t m_num_elements; - std::map 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() + SyntheticChildrenFrontEnd(*valobj_sp), + m_start(nullptr), + m_element_type(), + m_element_size(0), + m_num_elements(0) { if (valobj_sp) Update(); @@ -90,17 +88,11 @@ lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetChildAtInde 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; + return CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type); } bool @@ -110,10 +102,9 @@ lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::Update() 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()) + if (kind != lldb::eTemplateArgumentKindType || !m_element_type.IsValid()) return false; m_element_size = m_element_type.GetByteSize(nullptr); @@ -141,7 +132,5 @@ lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::GetIndexOfChil lldb_private::SyntheticChildrenFrontEnd* lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) { - if (!valobj_sp) - return NULL; - return (new LibcxxInitializerListSyntheticFrontEnd(valobj_sp)); + return (valobj_sp ? new LibcxxInitializerListSyntheticFrontEnd(valobj_sp) : nullptr); } diff --git a/source/Plugins/Language/CPlusPlus/LibCxxList.cpp b/source/Plugins/Language/CPlusPlus/LibCxxList.cpp index f86f968ea857..35cee566a773 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxList.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxList.cpp @@ -34,7 +34,7 @@ namespace { public: ListEntry() = default; ListEntry (ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {} - ListEntry (const ListEntry& rhs) : m_entry_sp(rhs.m_entry_sp) {} + ListEntry(const ListEntry& rhs) = default; ListEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {} ListEntry @@ -69,7 +69,7 @@ namespace { explicit operator bool () { - return GetEntry().get() != nullptr && null() == false; + return GetEntry() && !null(); } ValueObjectSP @@ -106,7 +106,7 @@ namespace { ListIterator() = default; ListIterator (ListEntry entry) : m_entry(entry) {} ListIterator (ValueObjectSP entry) : m_entry(entry) {} - ListIterator (const ListIterator& rhs) : m_entry(rhs.m_entry) {} + ListIterator(const ListIterator& rhs) = default; ListIterator (ValueObject* entry) : m_entry(entry) {} ValueObjectSP @@ -200,23 +200,21 @@ namespace lldb_private { ValueObject* m_tail; CompilerType m_element_type; size_t m_count; - std::map m_children; std::map 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() + SyntheticChildrenFrontEnd(*valobj_sp), + m_list_capping_size(0), + m_loop_detected(0), + m_node_address(), + m_head(nullptr), + m_tail(nullptr), + m_element_type(), + m_count(UINT32_MAX), + m_iterators() { if (valobj_sp) Update(); @@ -225,7 +223,7 @@ m_iterators() bool lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop(size_t count) { - if (g_use_loop_detect == false) + if (!g_use_loop_detect) return false; // don't bother checking for a loop if we won't actually need to jump nodes if (m_count < 2) @@ -312,10 +310,6 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex (size_ 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(); @@ -350,15 +344,17 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex (size_ StreamString name; name.Printf("[%" PRIu64 "]", (uint64_t)idx); - return (m_children[idx] = CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type)); + return 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_head = m_tail = nullptr; m_node_address = 0; m_count = UINT32_MAX; m_loop_detected = 0; @@ -372,7 +368,7 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::Update() 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) + if (err.Fail() || !backend_addr) return false; m_node_address = backend_addr->GetValueAsUnsigned(0); if (!m_node_address || m_node_address == LLDB_INVALID_ADDRESS) @@ -408,7 +404,5 @@ lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetIndexOfChildWithNam SyntheticChildrenFrontEnd* lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) { - if (!valobj_sp) - return NULL; - return (new LibcxxStdListSyntheticFrontEnd(valobj_sp)); + return (valobj_sp ? new LibcxxStdListSyntheticFrontEnd(valobj_sp) : nullptr); } diff --git a/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp index aa82557edb02..d89869283cd3 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp @@ -32,7 +32,7 @@ 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) {} + MapEntry(const MapEntry& rhs) = default; explicit MapEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {} ValueObjectSP @@ -124,7 +124,7 @@ public: ValueObjectSP advance (size_t count) { - ValueObjectSP fail(nullptr); + ValueObjectSP fail; if (m_error) return fail; size_t steps = 0; @@ -147,7 +147,7 @@ protected: if (m_entry.null()) return; MapEntry right(m_entry.right()); - if (right.null() == false) + if (!right.null()) { m_entry = tree_min(std::move(right)); return; @@ -179,7 +179,7 @@ private: return MapEntry(); MapEntry left(x.left()); size_t steps = 0; - while (left.null() == false) + while (!left.null()) { if (left.error()) { @@ -246,21 +246,19 @@ namespace lldb_private { CompilerType m_element_type; uint32_t m_skip_size; size_t m_count; - std::map m_children; std::map 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() + SyntheticChildrenFrontEnd(*valobj_sp), + m_tree(nullptr), + m_root_node(nullptr), + m_element_type(), + m_skip_size(UINT32_MAX), + m_count(UINT32_MAX), + m_iterators() { if (valobj_sp) Update(); @@ -274,7 +272,7 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::CalculateNumChildren () if (m_count != UINT32_MAX) return m_count; - if (m_tree == NULL) + if (m_tree == nullptr) return 0; ValueObjectSP m_item(m_tree->GetChildMemberWithName(g___pair3_, true)); if (!m_item) @@ -315,7 +313,7 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetValueOffset (const l return; CompilerType node_type(node->GetCompilerType()); uint64_t bit_offset; - if (node_type.GetIndexOfFieldWithName("__value_", NULL, &bit_offset) == UINT32_MAX) + if (node_type.GetIndexOfFieldWithName("__value_", nullptr, &bit_offset) == UINT32_MAX) return; m_skip_size = bit_offset / 8u; } @@ -327,16 +325,11 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t static ConstString g___nc("__nc"); static ConstString g___value_("__value_"); - if (idx >= CalculateNumChildren()) return lldb::ValueObjectSP(); - if (m_tree == NULL || m_root_node == NULL) + if (m_tree == nullptr || m_root_node == nullptr) 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); @@ -352,10 +345,10 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t } ValueObjectSP iterated_sp(iterator.advance(actual_advancde)); - if (iterated_sp.get() == NULL) + if (!iterated_sp) { // this tree is garbage - stop - m_tree = NULL; // this will stop all future searches until an Update() happens + m_tree = nullptr; // this will stop all future searches until an Update() happens return iterated_sp; } if (GetDataType()) @@ -366,14 +359,14 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t iterated_sp = iterated_sp->Dereference(error); if (!iterated_sp || error.Fail()) { - m_tree = NULL; + m_tree = nullptr; return lldb::ValueObjectSP(); } GetValueOffset(iterated_sp); iterated_sp = iterated_sp->GetChildMemberWithName(g___value_, true); if (!iterated_sp) { - m_tree = NULL; + m_tree = nullptr; return lldb::ValueObjectSP(); } } @@ -385,20 +378,20 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t GetChildAtIndex(0); if (m_skip_size == UINT32_MAX) { - m_tree = NULL; + m_tree = nullptr; return lldb::ValueObjectSP(); } iterated_sp = iterated_sp->GetSyntheticChildAtOffset(m_skip_size, m_element_type, true); if (!iterated_sp) { - m_tree = NULL; + m_tree = nullptr; return lldb::ValueObjectSP(); } } } else { - m_tree = NULL; + m_tree = nullptr; return lldb::ValueObjectSP(); } // at this point we have a valid @@ -408,7 +401,7 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t iterated_sp->GetData(data, error); if (error.Fail()) { - m_tree = NULL; + m_tree = nullptr; return lldb::ValueObjectSP(); } StreamString name; @@ -438,7 +431,7 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t potential_child_sp->SetName(ConstString(name.GetData())); } m_iterators[idx] = iterator; - return (m_children[idx] = potential_child_sp); + return potential_child_sp; } bool @@ -447,8 +440,7 @@ 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_tree = m_root_node = nullptr; m_iterators.clear(); m_tree = m_backend.GetChildMemberWithName(g___tree_, true).get(); if (!m_tree) @@ -472,7 +464,5 @@ lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetIndexOfChildWithName SyntheticChildrenFrontEnd* lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) { - if (!valobj_sp) - return NULL; - return (new LibcxxStdMapSyntheticFrontEnd(valobj_sp)); + return (valobj_sp ? new LibcxxStdMapSyntheticFrontEnd(valobj_sp) : nullptr); } diff --git a/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp index 8ad806d52bce..a547695448ce 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp @@ -55,19 +55,17 @@ namespace lldb_private { ValueObject* m_tree; size_t m_num_elements; ValueObject* m_next_element; - std::map m_children; std::vector > 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() + SyntheticChildrenFrontEnd(*valobj_sp), + m_tree(nullptr), + m_num_elements(0), + m_next_element(nullptr), + m_elements_cache() { if (valobj_sp) Update(); @@ -86,13 +84,9 @@ lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetChildAtInde { if (idx >= CalculateNumChildren()) return lldb::ValueObjectSP(); - if (m_tree == NULL) + if (m_tree == nullptr) 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) @@ -125,10 +119,10 @@ lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetChildAtInde 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()); + return CreateValueObjectFromData(stream.GetData(), + data, + exe_ctx, + val_hash.first->GetCompilerType()); } bool @@ -137,7 +131,6 @@ 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; @@ -166,7 +159,5 @@ lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetIndexOfChil SyntheticChildrenFrontEnd* lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) { - if (!valobj_sp) - return NULL; - return (new LibcxxStdUnorderedMapSyntheticFrontEnd(valobj_sp)); + return (valobj_sp ? new LibcxxStdUnorderedMapSyntheticFrontEnd(valobj_sp) : nullptr); } diff --git a/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp b/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp index 9fb4f48e9090..ed26eaea121c 100644 --- a/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp +++ b/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp @@ -50,18 +50,16 @@ namespace lldb_private { ValueObject* m_finish; CompilerType m_element_type; uint32_t m_element_size; - std::map 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() + SyntheticChildrenFrontEnd(*valobj_sp), + m_start(nullptr), + m_finish(nullptr), + m_element_type(), + m_element_size(0) { if (valobj_sp) Update(); @@ -100,24 +98,20 @@ lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex (siz 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; + return CreateValueObjectFromAddress(name.GetData(), + offset, + m_backend.GetExecutionContextRef(), + m_element_type); } bool lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update() { - m_start = m_finish = NULL; - m_children.clear(); + m_start = m_finish = nullptr; ValueObjectSP data_type_finder_sp(m_backend.GetChildMemberWithName(ConstString("__end_cap_"),true)); if (!data_type_finder_sp) return false; @@ -153,7 +147,5 @@ lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetIndexOfChildWithN lldb_private::SyntheticChildrenFrontEnd* lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) { - if (!valobj_sp) - return NULL; - return (new LibcxxStdVectorSyntheticFrontEnd(valobj_sp)); + return (valobj_sp ? new LibcxxStdVectorSyntheticFrontEnd(valobj_sp) : nullptr); } diff --git a/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp index ed89c5c84ea3..6d6f915f68e2 100644 --- a/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp +++ b/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp @@ -1,4 +1,4 @@ -//===-- LibStdcpp.cpp ---------------------------------------------*- C++ -*-===// +//===-- LibStdcpp.cpp -------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -9,6 +9,10 @@ #include "LibStdcpp.h" +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Error.h" #include "lldb/Core/Stream.h" @@ -24,11 +28,25 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; +namespace +{ + class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd { + /* + (std::_Rb_tree_iterator, std::allocator > > >) 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 + } + } + */ + public: - LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - + explicit LibstdcppMapIteratorSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp); + size_t CalculateNumChildren() override; @@ -44,41 +62,45 @@ public: 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::allocator > > >) 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 - } - } - */ +class LibStdcppSharedPtrSyntheticFrontEnd : public SyntheticChildrenFrontEnd +{ +public: + explicit LibStdcppSharedPtrSyntheticFrontEnd(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; +}; + +} // end of anonymous namespace LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIteratorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : - SyntheticChildrenFrontEnd(*valobj_sp.get()), + SyntheticChildrenFrontEnd(*valobj_sp), 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 @@ -159,15 +181,10 @@ LibstdcppMapIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstStrin 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)); + return (valobj_sp ? new LibstdcppMapIteratorSyntheticFrontEnd(valobj_sp) : nullptr); } /* @@ -185,24 +202,22 @@ lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSy 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)); + return (valobj_sp ? new VectorIteratorSyntheticFrontEnd(valobj_sp, g_item_name) : nullptr); } 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() + SyntheticChildrenFrontEnd(*valobj_sp), + m_exe_ctx_ref(), + m_item_name(item_name), + m_item_sp() { if (valobj_sp) Update(); } bool -lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update() +VectorIteratorSyntheticFrontEnd::Update() { m_item_sp.reset(); @@ -227,13 +242,13 @@ lldb_private::formatters::VectorIteratorSyntheticFrontEnd::Update() } size_t -lldb_private::formatters::VectorIteratorSyntheticFrontEnd::CalculateNumChildren () +VectorIteratorSyntheticFrontEnd::CalculateNumChildren() { return 1; } lldb::ValueObjectSP -lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size_t idx) +VectorIteratorSyntheticFrontEnd::GetChildAtIndex(size_t idx) { if (idx == 0) return m_item_sp; @@ -241,23 +256,19 @@ lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetChildAtIndex (size } bool -lldb_private::formatters::VectorIteratorSyntheticFrontEnd::MightHaveChildren () +VectorIteratorSyntheticFrontEnd::MightHaveChildren() { return true; } size_t -lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +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) { @@ -371,3 +382,95 @@ lldb_private::formatters::LibStdcppWStringSummaryProvider (ValueObject& valobj, } return false; } + +LibStdcppSharedPtrSyntheticFrontEnd::LibStdcppSharedPtrSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) + : SyntheticChildrenFrontEnd(*valobj_sp) +{ + if (valobj_sp) + Update(); +} + +size_t +LibStdcppSharedPtrSyntheticFrontEnd::CalculateNumChildren() +{ + return 1; +} + +lldb::ValueObjectSP +LibStdcppSharedPtrSyntheticFrontEnd::GetChildAtIndex(size_t idx) +{ + ValueObjectSP valobj_sp = m_backend.GetSP(); + if (!valobj_sp) + return lldb::ValueObjectSP(); + + if (idx == 0) + return valobj_sp->GetChildMemberWithName(ConstString("_M_ptr"), true); + else + return lldb::ValueObjectSP(); +} + +bool +LibStdcppSharedPtrSyntheticFrontEnd::Update() +{ + return false; +} + +bool +LibStdcppSharedPtrSyntheticFrontEnd::MightHaveChildren() +{ + return true; +} + +size_t +LibStdcppSharedPtrSyntheticFrontEnd::GetIndexOfChildWithName(const ConstString &name) +{ + if (name == ConstString("_M_ptr")) + return 0; + return UINT32_MAX; +} + +SyntheticChildrenFrontEnd * +lldb_private::formatters::LibStdcppSharedPtrSyntheticFrontEndCreator(CXXSyntheticChildren *, + lldb::ValueObjectSP valobj_sp) +{ + return (valobj_sp ? new LibStdcppSharedPtrSyntheticFrontEnd(valobj_sp) : nullptr); +} + +bool +lldb_private::formatters::LibStdcppSmartPointerSummaryProvider(ValueObject &valobj, Stream &stream, + const TypeSummaryOptions &options) +{ + ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue()); + if (!valobj_sp) + return false; + + ValueObjectSP ptr_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_ptr"), true)); + if (!ptr_sp) + return false; + + ValueObjectSP usecount_sp( + valobj_sp->GetChildAtNamePath({ConstString("_M_refcount"), ConstString("_M_pi"), ConstString("_M_use_count")})); + if (!usecount_sp) + return false; + + if (ptr_sp->GetValueAsUnsigned(0) == 0 || usecount_sp->GetValueAsUnsigned(0) == 0) + { + stream.Printf("nullptr"); + return true; + } + + 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)) + { + return true; + } + } + + stream.Printf("ptr = 0x%" PRIx64, ptr_sp->GetValueAsUnsigned(0)); + return true; +} diff --git a/source/Plugins/Language/CPlusPlus/LibStdcpp.h b/source/Plugins/Language/CPlusPlus/LibStdcpp.h index 347856a1695c..b84c0ff831eb 100644 --- a/source/Plugins/Language/CPlusPlus/LibStdcpp.h +++ b/source/Plugins/Language/CPlusPlus/LibStdcpp.h @@ -24,9 +24,14 @@ namespace lldb_private { bool LibStdcppWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libcstdc++ c++11 std::wstring + bool + LibStdcppSmartPointerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libstdc++ std::shared_ptr<> and std::weak_ptr<> + SyntheticChildrenFrontEnd* LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); - + SyntheticChildrenFrontEnd* LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); + + SyntheticChildrenFrontEnd* LibStdcppSharedPtrSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP); } // namespace formatters } // namespace lldb_private diff --git a/source/Plugins/Language/CPlusPlus/Makefile b/source/Plugins/Language/CPlusPlus/Makefile deleted file mode 100644 index 2cb0dcf638b3..000000000000 --- a/source/Plugins/Language/CPlusPlus/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Language/CPlusPlus -------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginCPlusPlusLanguage -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Language/Go/Makefile b/source/Plugins/Language/Go/Makefile deleted file mode 100644 index 3ea09f6c538f..000000000000 --- a/source/Plugins/Language/Go/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Language/Go -------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginGoLanguage -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Language/Java/CMakeLists.txt b/source/Plugins/Language/Java/CMakeLists.txt new file mode 100644 index 000000000000..80f7b08e7b65 --- /dev/null +++ b/source/Plugins/Language/Java/CMakeLists.txt @@ -0,0 +1,4 @@ +add_lldb_library(lldbPluginJavaLanguage + JavaFormatterFunctions.cpp + JavaLanguage.cpp +) diff --git a/source/Plugins/Language/Java/JavaFormatterFunctions.cpp b/source/Plugins/Language/Java/JavaFormatterFunctions.cpp new file mode 100644 index 000000000000..29e6ad0ee89f --- /dev/null +++ b/source/Plugins/Language/Java/JavaFormatterFunctions.cpp @@ -0,0 +1,186 @@ +//===-- JavaFormatterFunctions.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 "JavaFormatterFunctions.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/DataFormatters/StringPrinter.h" +#include "lldb/Symbol/JavaASTContext.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +namespace +{ + +class JavaArraySyntheticFrontEnd : public SyntheticChildrenFrontEnd +{ +public: + JavaArraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) : + SyntheticChildrenFrontEnd(*valobj_sp) + { + if (valobj_sp) + Update(); + } + + size_t + CalculateNumChildren() override + { + ValueObjectSP valobj = GetDereferencedValueObject(); + if (!valobj) + return 0; + + CompilerType type = valobj->GetCompilerType(); + uint32_t size = JavaASTContext::CalculateArraySize(type, *valobj); + if (size == UINT32_MAX) + return 0; + return size; + } + + lldb::ValueObjectSP + GetChildAtIndex(size_t idx) override + { + ValueObjectSP valobj = GetDereferencedValueObject(); + if (!valobj) + return nullptr; + + ProcessSP process_sp = valobj->GetProcessSP(); + if (!process_sp) + return nullptr; + + CompilerType type = valobj->GetCompilerType(); + CompilerType element_type = type.GetArrayElementType(); + lldb::addr_t address = valobj->GetAddressOf() + JavaASTContext::CalculateArrayElementOffset(type, idx); + + Error error; + size_t byte_size = element_type.GetByteSize(nullptr); + DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0)); + size_t bytes_read = process_sp->ReadMemory(address, buffer_sp->GetBytes(), byte_size, error); + if (error.Fail() || byte_size != bytes_read) + return nullptr; + + StreamString name; + name.Printf("[%" PRIu64 "]", (uint64_t)idx); + DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); + return CreateValueObjectFromData(name.GetData(), data, valobj->GetExecutionContextRef(), + element_type); + } + + bool + Update() override + { + return false; + } + + bool + MightHaveChildren() override + { + return true; + } + + size_t + GetIndexOfChildWithName(const ConstString &name) override + { + return ExtractIndexFromString(name.GetCString()); + } + +private: + ValueObjectSP + GetDereferencedValueObject() + { + if (!m_backend.IsPointerOrReferenceType()) + return m_backend.GetSP(); + + Error error; + return m_backend.Dereference(error); + } +}; + +} // end of anonymous namespace + +bool +lldb_private::formatters::JavaStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &opts) +{ + if (valobj.IsPointerOrReferenceType()) + { + Error error; + ValueObjectSP deref = valobj.Dereference(error); + if (error.Fail()) + return false; + return JavaStringSummaryProvider(*deref, stream, opts); + } + + ProcessSP process_sp = valobj.GetProcessSP(); + if (!process_sp) + return false; + + ConstString data_name("value"); + ConstString length_name("count"); + + ValueObjectSP length_sp = valobj.GetChildMemberWithName(length_name, true); + ValueObjectSP data_sp = valobj.GetChildMemberWithName(data_name, true); + if (!data_sp || !length_sp) + return false; + + bool success = false; + uint64_t length = length_sp->GetValueAsUnsigned(0, &success); + if (!success) + return false; + + if (length == 0) + { + stream.Printf("\"\""); + return true; + } + lldb::addr_t valobj_addr = data_sp->GetAddressOf(); + + StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); + options.SetLocation(valobj_addr); + options.SetProcessSP(process_sp); + options.SetStream(&stream); + options.SetSourceSize(length); + options.SetNeedsZeroTermination(false); + options.SetLanguage(eLanguageTypeJava); + + if (StringPrinter::ReadStringAndDumpToStream(options)) + return true; + + stream.Printf("Summary Unavailable"); + return true; +} + +bool +lldb_private::formatters::JavaArraySummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) +{ + if (valobj.IsPointerOrReferenceType()) + { + Error error; + ValueObjectSP deref = valobj.Dereference(error); + if (error.Fail()) + return false; + return JavaArraySummaryProvider(*deref, stream, options); + } + + CompilerType type = valobj.GetCompilerType(); + uint32_t size = JavaASTContext::CalculateArraySize(type, valobj); + if (size == UINT32_MAX) + return false; + stream.Printf("[%u]{...}", size); + return true; +} + +SyntheticChildrenFrontEnd* +lldb_private::formatters::JavaArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ + return valobj_sp ? new JavaArraySyntheticFrontEnd(valobj_sp) : nullptr; +} diff --git a/source/Plugins/Language/Java/JavaFormatterFunctions.h b/source/Plugins/Language/Java/JavaFormatterFunctions.h new file mode 100644 index 000000000000..f9588c5590ae --- /dev/null +++ b/source/Plugins/Language/Java/JavaFormatterFunctions.h @@ -0,0 +1,36 @@ +//===-- JavaFormatterFunctions.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_JavaFormatterFunctions_h_ +#define liblldb_JavaFormatterFunctions_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-forward.h" + +namespace lldb_private +{ +namespace formatters +{ + +bool +JavaStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); + +bool +JavaArraySummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); + +SyntheticChildrenFrontEnd* +JavaArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp); + +} // namespace formatters +} // namespace lldb_private + +#endif // liblldb_JavaFormatterFunctions_h_ diff --git a/source/Plugins/Language/Java/JavaLanguage.cpp b/source/Plugins/Language/Java/JavaLanguage.cpp new file mode 100644 index 000000000000..a4f883f68827 --- /dev/null +++ b/source/Plugins/Language/Java/JavaLanguage.cpp @@ -0,0 +1,112 @@ +//===-- JavaLanguage.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 +// C++ Includes +#include +#include + +// Other libraries and framework includes +#include "llvm/ADT/StringRef.h" + +// Project includes +#include "JavaFormatterFunctions.h" +#include "JavaLanguage.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/DataFormatters/DataVisualization.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Symbol/JavaASTContext.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +void +JavaLanguage::Initialize() +{ + PluginManager::RegisterPlugin(GetPluginNameStatic(), "Java Language", CreateInstance); +} + +void +JavaLanguage::Terminate() +{ + PluginManager::UnregisterPlugin(CreateInstance); +} + +lldb_private::ConstString +JavaLanguage::GetPluginNameStatic() +{ + static ConstString g_name("Java"); + return g_name; +} + +lldb_private::ConstString +JavaLanguage::GetPluginName() +{ + return GetPluginNameStatic(); +} + +uint32_t +JavaLanguage::GetPluginVersion() +{ + return 1; +} + +Language * +JavaLanguage::CreateInstance(lldb::LanguageType language) +{ + if (language == eLanguageTypeJava) + return new JavaLanguage(); + return nullptr; +} + +bool +JavaLanguage::IsNilReference(ValueObject &valobj) +{ + if (!valobj.GetCompilerType().IsReferenceType()) + return false; + + // If we failed to read the value then it is not a nil reference. + return valobj.GetValueAsUnsigned(UINT64_MAX) == 0; +} + +lldb::TypeCategoryImplSP +JavaLanguage::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) + { + const char* array_regexp = "^.*\\[\\]&?$"; + + lldb::TypeSummaryImplSP string_summary_sp(new CXXFunctionSummaryFormat( + TypeSummaryImpl::Flags().SetDontShowChildren(true), lldb_private::formatters::JavaStringSummaryProvider, + "java.lang.String summary provider")); + g_category->GetTypeSummariesContainer()->Add(ConstString("java::lang::String"), string_summary_sp); + + lldb::TypeSummaryImplSP array_summary_sp(new CXXFunctionSummaryFormat( + TypeSummaryImpl::Flags().SetDontShowChildren(true), lldb_private::formatters::JavaArraySummaryProvider, + "Java array summary provider")); + g_category->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(array_regexp)), + array_summary_sp); + +#ifndef LLDB_DISABLE_PYTHON + AddCXXSynthetic(g_category, lldb_private::formatters::JavaArraySyntheticFrontEndCreator, + "Java array synthetic children", ConstString(array_regexp), + SyntheticChildren::Flags().SetCascades(true), true); +#endif + } + }); + return g_category; +} diff --git a/source/Plugins/Language/Java/JavaLanguage.h b/source/Plugins/Language/Java/JavaLanguage.h new file mode 100644 index 000000000000..164facd27ab5 --- /dev/null +++ b/source/Plugins/Language/Java/JavaLanguage.h @@ -0,0 +1,64 @@ +//===-- JavaLanguage.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_JavaLanguage_h_ +#define liblldb_JavaLanguage_h_ + +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +#include "llvm/ADT/StringRef.h" + +// Project includes +#include "lldb/Core/ConstString.h" +#include "lldb/Target/Language.h" +#include "lldb/lldb-private.h" + +namespace lldb_private +{ + +class JavaLanguage : public Language +{ +public: + lldb::LanguageType + GetLanguageType() const override + { + return lldb::eLanguageTypeJava; + } + + static void + Initialize(); + + static void + Terminate(); + + static lldb_private::Language * + CreateInstance(lldb::LanguageType language); + + static lldb_private::ConstString + GetPluginNameStatic(); + + ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; + + bool + IsNilReference(ValueObject &valobj) override; + + lldb::TypeCategoryImplSP + GetFormatters() override; +}; + +} // namespace lldb_private + +#endif // liblldb_JavaLanguage_h_ diff --git a/source/Plugins/Language/ObjC/CF.cpp b/source/Plugins/Language/ObjC/CF.cpp index 614eb29a0f7a..617bb613aa0b 100644 --- a/source/Plugins/Language/ObjC/CF.cpp +++ b/source/Plugins/Language/ObjC/CF.cpp @@ -73,37 +73,28 @@ lldb_private::formatters::CFBagSummaryProvider (ValueObject& valobj, Stream& str if (descriptor->IsCFType()) { ConstString type_name(valobj.GetTypeName()); - if (type_name == ConstString("__CFBag") || type_name == ConstString("const struct __CFBag")) + + static ConstString g___CFBag("__CFBag"); + static ConstString g_conststruct__CFBag("const struct __CFBag"); + + if (type_name == g___CFBag || + type_name == g_conststruct__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 + if (is_type_ok) { - uint32_t offset = 2*ptr_size+4 + valobj_addr; + lldb::addr_t offset = 2*ptr_size+4 + valobj_addr; Error error; count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error); if (error.Fail()) return false; } + else + return false; std::string prefix,suffix; if (Language* language = Language::FindPlugin(options.GetLanguage())) @@ -284,37 +275,30 @@ lldb_private::formatters::CFBinaryHeapSummaryProvider (ValueObject& valobj, Stre if (descriptor->IsCFType()) { ConstString type_name(valobj.GetTypeName()); - if (type_name == ConstString("__CFBinaryHeap") || type_name == ConstString("const struct __CFBinaryHeap")) + + static ConstString g___CFBinaryHeap("__CFBinaryHeap"); + static ConstString g_conststruct__CFBinaryHeap("const struct __CFBinaryHeap"); + static ConstString g_CFBinaryHeapRef("CFBinaryHeapRef"); + + if (type_name == g___CFBinaryHeap || + type_name == g_conststruct__CFBinaryHeap || + type_name == g_CFBinaryHeapRef) { if (valobj.IsPointerType()) is_type_ok = true; } } - if (is_type_ok == false) + if (is_type_ok) { - 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; + lldb::addr_t offset = 2*ptr_size + valobj_addr; Error error; count = process_sp->ReadUnsignedIntegerFromMemory(offset, 4, 0, error); if (error.Fail()) return false; } + else + return false; std::string prefix,suffix; if (Language* language = Language::FindPlugin(options.GetLanguage())) diff --git a/source/Plugins/Language/ObjC/Cocoa.cpp b/source/Plugins/Language/ObjC/Cocoa.cpp index aa6e476b6131..017c46ee3bb3 100644 --- a/source/Plugins/Language/ObjC/Cocoa.cpp +++ b/source/Plugins/Language/ObjC/Cocoa.cpp @@ -50,7 +50,7 @@ lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream& ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - if (!descriptor.get() || !descriptor->IsValid()) + if (!descriptor || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); @@ -71,16 +71,15 @@ lldb_private::formatters::NSBundleSummaryProvider (ValueObject& valobj, Stream& ValueObjectSP text(valobj.GetSyntheticChildAtOffset(offset, valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID), true)); StreamString summary_stream; - bool was_nsstring_ok = NSStringSummaryProvider(*text.get(), summary_stream, options); + bool was_nsstring_ok = NSStringSummaryProvider(*text, 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()); + + return false; } bool @@ -97,7 +96,7 @@ lldb_private::formatters::NSTimeZoneSummaryProvider (ValueObject& valobj, Stream ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - if (!descriptor.get() || !descriptor->IsValid()) + if (!descriptor || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); @@ -117,14 +116,15 @@ lldb_private::formatters::NSTimeZoneSummaryProvider (ValueObject& valobj, Stream 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); + bool was_nsstring_ok = NSStringSummaryProvider(*text, 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()); + + return false; } bool @@ -141,7 +141,7 @@ lldb_private::formatters::NSNotificationSummaryProvider (ValueObject& valobj, St ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - if (!descriptor.get() || !descriptor->IsValid()) + if (!descriptor || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); @@ -161,16 +161,15 @@ lldb_private::formatters::NSNotificationSummaryProvider (ValueObject& valobj, St 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); + bool was_nsstring_ok = NSStringSummaryProvider(*text, 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()); + + return false; } bool @@ -187,7 +186,7 @@ lldb_private::formatters::NSMachPortSummaryProvider (ValueObject& valobj, Stream ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - if (!descriptor.get() || !descriptor->IsValid()) + if (!descriptor || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); @@ -204,22 +203,19 @@ lldb_private::formatters::NSMachPortSummaryProvider (ValueObject& valobj, Stream uint64_t port_number = 0; - do + if (!strcmp(class_name,"NSMachPort")) { - 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()) { - 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; + stream.Printf("mach port: %u",(uint32_t)(port_number & 0x00000000FFFFFFFF)); + return true; } - if (!ExtractValueFromObjCExpression(valobj, "int", "machPort", port_number)) - return false; - } while (false); + } - stream.Printf("mach port: %u",(uint32_t)(port_number & 0x00000000FFFFFFFF)); - return true; + return false; } bool @@ -236,7 +232,7 @@ lldb_private::formatters::NSIndexSetSummaryProvider (ValueObject& valobj, Stream ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - if (!descriptor.get() || !descriptor->IsValid()) + if (!descriptor || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); @@ -289,10 +285,7 @@ lldb_private::formatters::NSIndexSetSummaryProvider (ValueObject& valobj, Stream } } else - { - if (!ExtractValueFromObjCExpression(valobj, "unsigned long long int", "count", count)) - return false; - } + return false; } while (false); stream.Printf("%" PRIu64 " index%s", count, @@ -458,7 +451,7 @@ lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream& ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - if (!descriptor.get() || !descriptor->IsValid()) + if (!descriptor || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); @@ -531,6 +524,7 @@ lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream& break; case 17: // 0B10001 data_location += 8; + LLVM_FALLTHROUGH; case 4: // 0B0100 value = process_sp->ReadUnsignedIntegerFromMemory(data_location, 8, 0, error); if (error.Fail()) @@ -542,7 +536,8 @@ lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream& 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); + float flt_value = 0.0f; + memcpy(&flt_value, &flt_as_int, sizeof(flt_as_int)); NSNumber_FormatFloat(valobj, stream, flt_value, options.GetLanguage()); break; } @@ -551,7 +546,8 @@ lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream& 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); + double dbl_value = 0.0; + memcpy(&dbl_value, &dbl_as_lng, sizeof(dbl_as_lng)); NSNumber_FormatDouble(valobj, stream, dbl_value, options.GetLanguage()); break; } @@ -561,10 +557,8 @@ lldb_private::formatters::NSNumberSummaryProvider (ValueObject& valobj, Stream& return true; } } - else - { - return ExtractSummaryFromObjCExpression(valobj, "NSString*", "stringValue", stream, options.GetLanguage()); - } + + return false; } bool @@ -581,7 +575,7 @@ lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& str ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - if (!descriptor.get() || !descriptor->IsValid()) + if (!descriptor || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); @@ -625,10 +619,7 @@ lldb_private::formatters::NSURLSummaryProvider (ValueObject& valobj, Stream& str return true; } } - else - { - return ExtractSummaryFromObjCExpression(valobj, "NSString*", "description", stream, options.GetLanguage()); - } + return false; } @@ -646,7 +637,7 @@ lldb_private::formatters::NSDateSummaryProvider (ValueObject& valobj, Stream& st ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - if (!descriptor.get() || !descriptor->IsValid()) + if (!descriptor || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); @@ -659,44 +650,48 @@ lldb_private::formatters::NSDateSummaryProvider (ValueObject& valobj, Stream& st uint64_t date_value_bits = 0; double date_value = 0.0; - const char* class_name = descriptor->GetClassName().GetCString(); + ConstString class_name = descriptor->GetClassName(); - if (!class_name || !*class_name) + static const ConstString g_NSDate("NSDate"); + static const ConstString g___NSDate("__NSDate"); + static const ConstString g___NSTaggedDate("__NSTaggedDate"); + static const ConstString g_NSCalendarDate("NSCalendarDate"); + + if (class_name.IsEmpty()) return false; - if (strcmp(class_name,"NSDate") == 0 || - strcmp(class_name,"__NSDate") == 0 || - strcmp(class_name,"__NSTaggedDate") == 0) + if ((class_name == g_NSDate) || + (class_name == g___NSDate) || + (class_name == g___NSTaggedDate)) { 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); + memcpy(&date_value, &date_value_bits, sizeof(date_value_bits)); } else { + llvm::Triple triple(process_sp->GetTarget().GetArchitecture().GetTriple()); + uint32_t delta = (triple.isWatchOS() && triple.isWatchABI()) ? 8 : ptr_size; Error error; - date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+ptr_size, 8, 0, error); - date_value = *((double*)&date_value_bits); + date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+delta, 8, 0, error); + memcpy(&date_value, &date_value_bits, sizeof(date_value_bits)); if (error.Fail()) return false; } } - else if (!strcmp(class_name,"NSCalendarDate")) + else if (class_name == g_NSCalendarDate) { Error error; date_value_bits = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr+2*ptr_size, 8, 0, error); - date_value = *((double*)&date_value_bits); + memcpy(&date_value, &date_value_bits, sizeof(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); - } + return false; + if (date_value == -63114076800) { stream.Printf("0001-12-30 00:00:00 +0000"); @@ -731,7 +726,7 @@ lldb_private::formatters::ObjCClassSummaryProvider (ValueObject& valobj, Stream& ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptorFromISA(valobj.GetValueAsUnsigned(0))); - if (!descriptor.get() || !descriptor->IsValid()) + if (!descriptor || !descriptor->IsValid()) return false; ConstString class_name = descriptor->GetClassName(); @@ -750,7 +745,7 @@ class ObjCClassSyntheticChildrenFrontEnd : public SyntheticChildrenFrontEnd { public: ObjCClassSyntheticChildrenFrontEnd (lldb::ValueObjectSP valobj_sp) : - SyntheticChildrenFrontEnd(*valobj_sp.get()) + SyntheticChildrenFrontEnd(*valobj_sp) { } @@ -808,7 +803,7 @@ lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& st ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - if (!descriptor.get() || !descriptor->IsValid()) + if (!descriptor || !descriptor->IsValid()) return false; bool is_64bit = (process_sp->GetAddressByteSize() == 8); @@ -834,11 +829,20 @@ lldb_private::formatters::NSDataSummaryProvider (ValueObject& valobj, Stream& st if (error.Fail()) return false; } - else + else if (!strcmp(class_name, "_NSInlineData")) { - if (!ExtractValueFromObjCExpression(valobj, "int", "length", value)) + uint32_t offset = (is_64bit ? 8 : 4); + Error error; + value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + offset, 2, 0, error); + if (error.Fail()) return false; } + else if (!strcmp(class_name, "_NSZeroData")) + { + value = 0; + } + else + return false; stream.Printf("%s%" PRIu64 " byte%s%s", (needs_at ? "@\"" : ""), @@ -869,13 +873,19 @@ lldb_private::formatters::ObjCBOOLSummaryProvider (ValueObject& valobj, Stream& if (!real_guy_sp) return false; } - uint64_t value = real_guy_sp->GetValueAsUnsigned(0); - if (value == 0) + uint8_t value = (real_guy_sp->GetValueAsUnsigned(0) & 0xFF); + switch (value) { - stream.Printf("NO"); - return true; + case 0: + stream.Printf("NO"); + break; + case 1: + stream.Printf("YES"); + break; + default: + stream.Printf("%u",value); + break; } - stream.Printf("YES"); return true; } @@ -932,28 +942,16 @@ lldb_private::formatters::GetOSXEpoch () 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_year = 2001-1900; tm_epoch.tm_isdst = -1; tm_epoch.tm_gmtoff = 0; - tm_epoch.tm_zone = NULL; + tm_epoch.tm_zone = nullptr; 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 (ValueObject&, Stream&, const TypeSummaryOptions&); diff --git a/source/Plugins/Language/ObjC/Cocoa.h b/source/Plugins/Language/ObjC/Cocoa.h index 0caacf3453d4..f43b1639cb38 100644 --- a/source/Plugins/Language/ObjC/Cocoa.h +++ b/source/Plugins/Language/ObjC/Cocoa.h @@ -13,6 +13,7 @@ #include "lldb/Core/Stream.h" #include "lldb/Core/ValueObject.h" #include "lldb/DataFormatters/TypeSummary.h" +#include "lldb/DataFormatters/TypeSynthetic.h" #include "lldb/Target/ObjCLanguageRuntime.h" namespace lldb_private { @@ -77,9 +78,6 @@ namespace lldb_private { extern template bool ObjCSELSummaryProvider (ValueObject&, Stream&, const TypeSummaryOptions&); - bool - RuntimeSpecificDescriptionSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); - bool NSError_SummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); @@ -91,6 +89,16 @@ namespace lldb_private { SyntheticChildrenFrontEnd* NSExceptionSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp); + + class NSArray_Additionals + { + public: + static std::map& + GetAdditionalSummaries (); + + static std::map& + GetAdditionalSynthetics (); + }; } // namespace formatters } // namespace lldb_private diff --git a/source/Plugins/Language/ObjC/Makefile b/source/Plugins/Language/ObjC/Makefile deleted file mode 100644 index 58c9e58f2bc6..000000000000 --- a/source/Plugins/Language/ObjC/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Language/ObjC ------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginObjCLanguage -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Language/ObjC/NSArray.cpp b/source/Plugins/Language/ObjC/NSArray.cpp index ccc82ab95ecc..5de97b6f0257 100644 --- a/source/Plugins/Language/ObjC/NSArray.cpp +++ b/source/Plugins/Language/ObjC/NSArray.cpp @@ -35,6 +35,20 @@ using namespace lldb_private::formatters; namespace lldb_private { namespace formatters { + std::map& + NSArray_Additionals::GetAdditionalSummaries () + { + static std::map g_map; + return g_map; + } + + std::map& + NSArray_Additionals::GetAdditionalSynthetics () + { + static std::map g_map; + return g_map; + } + class NSArrayMSyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: @@ -73,7 +87,6 @@ namespace lldb_private { ExecutionContextRef m_exe_ctx_ref; uint8_t m_ptr_size; CompilerType m_id_type; - std::vector m_children; }; class NSArrayMSyntheticFrontEnd_109 : public NSArrayMSyntheticFrontEnd @@ -103,7 +116,7 @@ namespace lldb_private { struct DataDescriptor_32 { uint32_t _used; - uint32_t _priv1 : 2 ; + uint32_t _priv1 : 2; uint32_t _size : 30; uint32_t _priv2 : 2; uint32_t _offset : 30; @@ -114,7 +127,7 @@ namespace lldb_private { struct DataDescriptor_64 { uint64_t _used; - uint64_t _priv1 : 2 ; + uint64_t _priv1 : 2; uint64_t _size : 62; uint64_t _priv2 : 2; uint64_t _offset : 62; @@ -202,7 +215,6 @@ namespace lldb_private { uint64_t m_items; lldb::addr_t m_data_ptr; CompilerType m_id_type; - std::vector m_children; }; class NSArray0SyntheticFrontEnd : public SyntheticChildrenFrontEnd @@ -227,14 +239,14 @@ namespace lldb_private { size_t GetIndexOfChildWithName(const ConstString &name) override; }; - - class NSArrayCodeRunningSyntheticFrontEnd : public SyntheticChildrenFrontEnd + + class NSArray1SyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: - NSArrayCodeRunningSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); - - ~NSArrayCodeRunningSyntheticFrontEnd() override = default; - + NSArray1SyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + ~NSArray1SyntheticFrontEnd() override = default; + size_t CalculateNumChildren() override; @@ -269,7 +281,7 @@ lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& s ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - if (!descriptor.get() || !descriptor->IsValid()) + if (!descriptor || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); @@ -281,30 +293,40 @@ lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& s uint64_t value = 0; - const char* class_name = descriptor->GetClassName().GetCString(); + ConstString class_name(descriptor->GetClassName()); - if (!class_name || !*class_name) + static const ConstString g_NSArrayI("__NSArrayI"); + static const ConstString g_NSArrayM("__NSArrayM"); + static const ConstString g_NSArray0("__NSArray0"); + static const ConstString g_NSArray1("__NSSingleObjectArrayI"); + static const ConstString g_NSArrayCF("__NSCFArray"); + + if (class_name.IsEmpty()) return false; - if (!strcmp(class_name,"__NSArrayI")) + if (class_name == g_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")) + else if (class_name == g_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")) + else if (class_name == g_NSArray0) { value = 0; } - else if (!strcmp(class_name,"__NSCFArray")) + else if (class_name == g_NSArray1) + { + value = 1; + } + else if (class_name == g_NSArrayCF) { Error error; value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + 2 * ptr_size, ptr_size, 0, error); @@ -313,7 +335,11 @@ lldb_private::formatters::NSArraySummaryProvider (ValueObject& valobj, Stream& s } else { - if (!ExtractValueFromObjCExpression(valobj, "int", "count", value)) + auto& map(NSArray_Additionals::GetAdditionalSummaries()); + auto iter = map.find(class_name), end = map.end(); + if (iter != end) + return iter->second(valobj, stream, options); + else return false; } @@ -340,8 +366,7 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::NSArrayMSyntheticFrontEnd ( SyntheticChildrenFrontEnd(*valobj_sp), m_exe_ctx_ref(), m_ptr_size(8), -m_id_type(), -m_children() +m_id_type() { if (valobj_sp) { @@ -354,16 +379,16 @@ m_children() } lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::NSArrayMSyntheticFrontEnd_109 (lldb::ValueObjectSP valobj_sp) : -NSArrayMSyntheticFrontEnd(valobj_sp), -m_data_32(NULL), -m_data_64(NULL) + NSArrayMSyntheticFrontEnd(valobj_sp), + m_data_32(nullptr), + m_data_64(nullptr) { } lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::NSArrayMSyntheticFrontEnd_1010 (lldb::ValueObjectSP valobj_sp) : -NSArrayMSyntheticFrontEnd(valobj_sp), -m_data_32(NULL), -m_data_64(NULL) + NSArrayMSyntheticFrontEnd(valobj_sp), + m_data_32(nullptr), + m_data_64(nullptr) { } @@ -386,24 +411,21 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetChildAtIndex (size_t idx 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; + return CreateValueObjectFromAddress(idx_name.GetData(), + object_at_idx, + m_exe_ctx_ref, + m_id_type); } 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; + m_data_32 = nullptr; delete m_data_64; - m_data_64 = NULL; + m_data_64 = nullptr; if (!valobj_sp) return false; m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); @@ -432,13 +454,12 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::Update() 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; + m_data_32 = nullptr; delete m_data_64; - m_data_64 = NULL; + m_data_64 = nullptr; if (!valobj_sp) return false; m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); @@ -483,9 +504,9 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd::GetIndexOfChildWithName (co lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::~NSArrayMSyntheticFrontEnd_109() { delete m_data_32; - m_data_32 = NULL; + m_data_32 = nullptr; delete m_data_64; - m_data_64 = NULL; + m_data_64 = nullptr; } lldb::addr_t @@ -527,9 +548,9 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd_109::GetSize () lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::~NSArrayMSyntheticFrontEnd_1010() { delete m_data_32; - m_data_32 = NULL; + m_data_32 = nullptr; delete m_data_64; - m_data_64 = NULL; + m_data_64 = nullptr; } lldb::addr_t @@ -569,11 +590,11 @@ lldb_private::formatters::NSArrayMSyntheticFrontEnd_1010::GetSize () } 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) + SyntheticChildrenFrontEnd(*valobj_sp), + m_exe_ctx_ref(), + m_ptr_size(8), + m_items(0), + m_data_ptr(0) { if (valobj_sp) { @@ -609,7 +630,6 @@ 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; @@ -649,16 +669,14 @@ lldb_private::formatters::NSArrayISyntheticFrontEnd::GetChildAtIndex (size_t idx 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; + return CreateValueObjectFromAddress(idx_name.GetData(), + object_at_idx, + m_exe_ctx_ref, + m_id_type); } lldb_private::formatters::NSArray0SyntheticFrontEnd::NSArray0SyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : -SyntheticChildrenFrontEnd (*valobj_sp.get()) + SyntheticChildrenFrontEnd(*valobj_sp) { } @@ -692,17 +710,64 @@ lldb_private::formatters::NSArray0SyntheticFrontEnd::GetChildAtIndex (size_t idx return lldb::ValueObjectSP(); } -SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +lldb_private::formatters::NSArray1SyntheticFrontEnd::NSArray1SyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +SyntheticChildrenFrontEnd (*valobj_sp.get()) +{ +} + +size_t +lldb_private::formatters::NSArray1SyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ + static const ConstString g_zero("[0]"); + + if (name == g_zero) + return 0; + + return UINT32_MAX; +} + +size_t +lldb_private::formatters::NSArray1SyntheticFrontEnd::CalculateNumChildren () +{ + return 1; +} + +bool +lldb_private::formatters::NSArray1SyntheticFrontEnd::Update() +{ + return false; +} + +bool +lldb_private::formatters::NSArray1SyntheticFrontEnd::MightHaveChildren () +{ + return true; +} + +lldb::ValueObjectSP +lldb_private::formatters::NSArray1SyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ + static const ConstString g_zero("[0]"); + + if (idx == 0) + { + CompilerType id_type(m_backend.GetTargetSP()->GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeObjCID)); + return m_backend.GetSyntheticChildAtOffset(m_backend.GetProcessSP()->GetAddressByteSize(), id_type, true, g_zero); + } + return lldb::ValueObjectSP(); +} + +SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCreator (CXXSyntheticChildren* synth, lldb::ValueObjectSP valobj_sp) { if (!valobj_sp) return nullptr; lldb::ProcessSP process_sp (valobj_sp->GetProcessSP()); if (!process_sp) - return NULL; + return nullptr; AppleObjCRuntime *runtime = llvm::dyn_cast_or_null(process_sp->GetObjCLanguageRuntime()); if (!runtime) - return NULL; + return nullptr; CompilerType valobj_type(valobj_sp->GetCompilerType()); Flags flags(valobj_type.GetTypeInfo()); @@ -712,28 +777,37 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCre Error error; valobj_sp = valobj_sp->AddressOf(error); if (error.Fail() || !valobj_sp) - return NULL; + return nullptr; } - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get())); + ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp)); - if (!descriptor.get() || !descriptor->IsValid()) - return NULL; + if (!descriptor || !descriptor->IsValid()) + return nullptr; - const char* class_name = descriptor->GetClassName().GetCString(); + ConstString class_name(descriptor->GetClassName()); - if (!class_name || !*class_name) - return NULL; + static const ConstString g_NSArrayI("__NSArrayI"); + static const ConstString g_NSArrayM("__NSArrayM"); + static const ConstString g_NSArray0("__NSArray0"); + static const ConstString g_NSArray1("__NSSingleObjectArrayI"); + + if (class_name.IsEmpty()) + return nullptr; - if (!strcmp(class_name,"__NSArrayI")) + if (class_name == g_NSArrayI) { return (new NSArrayISyntheticFrontEnd(valobj_sp)); } - else if (!strcmp(class_name,"__NSArray0")) + else if (class_name == g_NSArray0) { return (new NSArray0SyntheticFrontEnd(valobj_sp)); } - else if (!strcmp(class_name,"__NSArrayM")) + else if (class_name == g_NSArray1) + { + return (new NSArray1SyntheticFrontEnd(valobj_sp)); + } + else if (class_name == g_NSArrayM) { if (runtime->GetFoundationVersion() >= 1100) return (new NSArrayMSyntheticFrontEnd_1010(valobj_sp)); @@ -742,51 +816,11 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSArraySyntheticFrontEndCre } 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())); + auto& map(NSArray_Additionals::GetAdditionalSynthetics()); + auto iter = map.find(class_name), end = map.end(); + if (iter != end) + return iter->second(synth, valobj_sp); } - 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; + + return nullptr; } diff --git a/source/Plugins/Language/ObjC/NSDictionary.cpp b/source/Plugins/Language/ObjC/NSDictionary.cpp index e4a7425329f5..cdebd6b3c23c 100644 --- a/source/Plugins/Language/ObjC/NSDictionary.cpp +++ b/source/Plugins/Language/ObjC/NSDictionary.cpp @@ -63,7 +63,7 @@ GetLLDBNSPairType (TargetSP target_sp) if (!compiler_type) { - compiler_type = target_ast_context->CreateRecordType(NULL, lldb::eAccessPublic, g___lldb_autogen_nspair.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC); + compiler_type = target_ast_context->CreateRecordType(nullptr, lldb::eAccessPublic, g___lldb_autogen_nspair.GetCString(), clang::TTK_Struct, lldb::eLanguageTypeC); if (compiler_type) { @@ -131,6 +131,32 @@ namespace lldb_private { CompilerType m_pair_type; std::vector m_children; }; + + class NSDictionary1SyntheticFrontEnd : public SyntheticChildrenFrontEnd + { + public: + NSDictionary1SyntheticFrontEnd (lldb::ValueObjectSP valobj_sp); + + ~NSDictionary1SyntheticFrontEnd() 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: + ValueObjectSP m_pair; + }; class NSDictionaryMSyntheticFrontEnd : public SyntheticChildrenFrontEnd { @@ -190,29 +216,6 @@ namespace lldb_private { CompilerType m_pair_type; std::vector 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 @@ -232,7 +235,7 @@ lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stre ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - if (!descriptor.get() || !descriptor->IsValid()) + if (!descriptor || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); @@ -245,13 +248,16 @@ lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stre uint64_t value = 0; - ConstString class_name_cs = descriptor->GetClassName(); - const char* class_name = class_name_cs.GetCString(); + ConstString class_name(descriptor->GetClassName()); + + static const ConstString g_DictionaryI("__NSDictionaryI"); + static const ConstString g_DictionaryM("__NSDictionaryM"); + static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI"); - if (!class_name || !*class_name) + if (class_name.IsEmpty()) return false; - - if (!strcmp(class_name,"__NSDictionaryI")) + + if (class_name == g_DictionaryI) { Error error; value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); @@ -259,7 +265,7 @@ lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stre return false; value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); } - else if (!strcmp(class_name,"__NSDictionaryM")) + else if (class_name == g_DictionaryM) { Error error; value = process_sp->ReadUnsignedIntegerFromMemory(valobj_addr + ptr_size, ptr_size, 0, error); @@ -267,6 +273,10 @@ lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stre return false; value &= (is_64bit ? ~0xFC00000000000000UL : ~0xFC000000U); } + else if (class_name == g_Dictionary1) + { + value = 1; + } /*else if (!strcmp(class_name,"__NSCFDictionary")) { Error error; @@ -279,10 +289,10 @@ lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stre else { auto& map(NSDictionary_Additionals::GetAdditionalSummaries()); - auto iter = map.find(class_name_cs), end = map.end(); + auto iter = map.find(class_name), end = map.end(); if (iter != end) return iter->second(valobj, stream, options); - if (!ExtractValueFromObjCExpression(valobj, "int", "count", value)) + else return false; } @@ -309,10 +319,10 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontE { lldb::ProcessSP process_sp (valobj_sp->GetProcessSP()); if (!process_sp) - return NULL; + return nullptr; ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); if (!runtime) - return NULL; + return nullptr; CompilerType valobj_type(valobj_sp->GetCompilerType()); Flags flags(valobj_type.GetTypeInfo()); @@ -322,111 +332,63 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSDictionarySyntheticFrontE Error error; valobj_sp = valobj_sp->AddressOf(error); if (error.Fail() || !valobj_sp) - return NULL; + return nullptr; } - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get())); + ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp)); - if (!descriptor.get() || !descriptor->IsValid()) - return NULL; + if (!descriptor || !descriptor->IsValid()) + return nullptr; - ConstString class_name_cs = descriptor->GetClassName(); - const char* class_name = class_name_cs.GetCString(); + ConstString class_name(descriptor->GetClassName()); - if (!class_name || !*class_name) - return NULL; + static const ConstString g_DictionaryI("__NSDictionaryI"); + static const ConstString g_DictionaryM("__NSDictionaryM"); + static const ConstString g_Dictionary1("__NSSingleEntryDictionaryI"); - if (!strcmp(class_name,"__NSDictionaryI")) + if (class_name.IsEmpty()) + return nullptr; + + if (class_name == g_DictionaryI) { return (new NSDictionaryISyntheticFrontEnd(valobj_sp)); } - else if (!strcmp(class_name,"__NSDictionaryM")) + else if (class_name == g_DictionaryM) { return (new NSDictionaryMSyntheticFrontEnd(valobj_sp)); } + else if (class_name == g_Dictionary1) + { + return (new NSDictionary1SyntheticFrontEnd(valobj_sp)); + } else { auto& map(NSDictionary_Additionals::GetAdditionalSynthetics()); - auto iter = map.find(class_name_cs), end = map.end(); + auto iter = map.find(class_name), 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; + + return nullptr; } 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() + SyntheticChildrenFrontEnd(*valobj_sp), + m_exe_ctx_ref(), + m_ptr_size(8), + m_order(lldb::eByteOrderInvalid), + m_data_32(nullptr), + m_data_64(nullptr), + m_pair_type() { } lldb_private::formatters::NSDictionaryISyntheticFrontEnd::~NSDictionaryISyntheticFrontEnd () { delete m_data_32; - m_data_32 = NULL; + m_data_32 = nullptr; delete m_data_64; - m_data_64 = NULL; + m_data_64 = nullptr; } size_t @@ -452,9 +414,9 @@ lldb_private::formatters::NSDictionaryISyntheticFrontEnd::Update() { m_children.clear(); delete m_data_32; - m_data_32 = NULL; + m_data_32 = nullptr; delete m_data_64; - m_data_64 = NULL; + m_data_64 = nullptr; m_ptr_size = 0; ValueObjectSP valobj_sp = m_backend.GetSP(); if (!valobj_sp) @@ -575,23 +537,113 @@ lldb_private::formatters::NSDictionaryISyntheticFrontEnd::GetChildAtIndex (size_ return dict_item.valobj_sp; } -lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : +lldb_private::formatters::NSDictionary1SyntheticFrontEnd::NSDictionary1SyntheticFrontEnd (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() +m_pair(nullptr) +{ +} + +size_t +lldb_private::formatters::NSDictionary1SyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name) +{ + static const ConstString g_zero("[0]"); + + if (name == g_zero) + return 0; + + return UINT32_MAX; +} + +size_t +lldb_private::formatters::NSDictionary1SyntheticFrontEnd::CalculateNumChildren () +{ + return 1; +} + +bool +lldb_private::formatters::NSDictionary1SyntheticFrontEnd::Update() +{ + m_pair.reset(); + return false; +} + +bool +lldb_private::formatters::NSDictionary1SyntheticFrontEnd::MightHaveChildren () +{ + return true; +} + +lldb::ValueObjectSP +lldb_private::formatters::NSDictionary1SyntheticFrontEnd::GetChildAtIndex (size_t idx) +{ + if (idx != 0) + return lldb::ValueObjectSP(); + + if (m_pair.get()) + return m_pair; + + auto process_sp(m_backend.GetProcessSP()); + if (!process_sp) + return nullptr; + + auto ptr_size = process_sp->GetAddressByteSize(); + + lldb::addr_t key_ptr = m_backend.GetValueAsUnsigned(LLDB_INVALID_ADDRESS) + ptr_size; + lldb::addr_t value_ptr = key_ptr + ptr_size; + + Error error; + + lldb::addr_t value_at_idx = process_sp->ReadPointerFromMemory(key_ptr, error); + if (error.Fail()) + return nullptr; + lldb::addr_t key_at_idx = process_sp->ReadPointerFromMemory(value_ptr, error); + if (error.Fail()) + return nullptr; + + auto pair_type = GetLLDBNSPairType(process_sp->GetTarget().shared_from_this()); + + DataBufferSP buffer_sp(new DataBufferHeap(2*ptr_size,0)); + + if (ptr_size == 8) + { + uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes(); + *data_ptr = key_at_idx; + *(data_ptr+1) = value_at_idx; + } + else + { + uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes(); + *data_ptr = key_ptr; + *(data_ptr+1) = value_ptr; + } + + DataExtractor data(buffer_sp, process_sp->GetByteOrder(), ptr_size); + m_pair = CreateValueObjectFromData("[0]", + data, + m_backend.GetExecutionContextRef(), + pair_type); + + + return m_pair; +} + +lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::NSDictionaryMSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : + SyntheticChildrenFrontEnd(*valobj_sp), + m_exe_ctx_ref(), + m_ptr_size(8), + m_order(lldb::eByteOrderInvalid), + m_data_32(nullptr), + m_data_64(nullptr), + m_pair_type() { } lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::~NSDictionaryMSyntheticFrontEnd () { delete m_data_32; - m_data_32 = NULL; + m_data_32 = nullptr; delete m_data_64; - m_data_64 = NULL; + m_data_64 = nullptr; } size_t @@ -619,9 +671,9 @@ lldb_private::formatters::NSDictionaryMSyntheticFrontEnd::Update() ValueObjectSP valobj_sp = m_backend.GetSP(); m_ptr_size = 0; delete m_data_32; - m_data_32 = NULL; + m_data_32 = nullptr; delete m_data_64; - m_data_64 = NULL; + m_data_64 = nullptr; if (!valobj_sp) return false; m_exe_ctx_ref = valobj_sp->GetExecutionContextRef(); diff --git a/source/Plugins/Language/ObjC/NSError.cpp b/source/Plugins/Language/ObjC/NSError.cpp index c627cd031926..4bfb024206d3 100644 --- a/source/Plugins/Language/ObjC/NSError.cpp +++ b/source/Plugins/Language/ObjC/NSError.cpp @@ -34,27 +34,49 @@ 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) +static lldb::addr_t +DerefToNSErrorPointer (ValueObject& valobj) { - 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); + return valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); } else - ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); + { + lldb::addr_t ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS); + if (type_flags.AllSet(eTypeIsPointer)) + { + CompilerType pointee_type(valobj_type.GetPointeeType()); + Flags pointee_flags(pointee_type.GetTypeInfo()); + if (pointee_flags.AllSet(eTypeIsPointer)) + { + if (ProcessSP process_sp = valobj.GetProcessSP()) + { + Error error; + ptr_value = process_sp->ReadPointerFromMemory(ptr_value, error); + } + } + } + return ptr_value; + } + + return LLDB_INVALID_ADDRESS; +} +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 = DerefToNSErrorPointer(valobj); 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; @@ -135,18 +157,7 @@ public: 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); - + lldb::addr_t userinfo_location = DerefToNSErrorPointer(m_backend); if (userinfo_location == LLDB_INVALID_ADDRESS) return false; @@ -158,10 +169,10 @@ public: 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)); + m_child_sp = CreateValueObjectFromData("_userInfo", + isw.GetAsData(process_sp->GetByteOrder()), + m_backend.GetExecutionContextRef(), + process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeObjCID)); return false; } diff --git a/source/Plugins/Language/ObjC/NSException.cpp b/source/Plugins/Language/ObjC/NSException.cpp index e58223a4d461..f70e7c7356e1 100644 --- a/source/Plugins/Language/ObjC/NSException.cpp +++ b/source/Plugins/Language/ObjC/NSException.cpp @@ -157,10 +157,10 @@ public: 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)); + m_child_sp = CreateValueObjectFromData("userInfo", + isw.GetAsData(process_sp->GetByteOrder()), + m_backend.GetExecutionContextRef(), + process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(lldb::eBasicTypeObjCID)); return false; } diff --git a/source/Plugins/Language/ObjC/NSIndexPath.cpp b/source/Plugins/Language/ObjC/NSIndexPath.cpp index 245f6da80c7f..0c8a54d76df1 100644 --- a/source/Plugins/Language/ObjC/NSIndexPath.cpp +++ b/source/Plugins/Language/ObjC/NSIndexPath.cpp @@ -31,6 +31,8 @@ class NSIndexPathSyntheticFrontEnd : public SyntheticChildrenFrontEnd public: NSIndexPathSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) : SyntheticChildrenFrontEnd (*valobj_sp.get()), + m_descriptor_sp(nullptr), + m_impl(), m_ptr_size(0), m_uint_star_type() { @@ -169,9 +171,8 @@ protected: Invalid }; - struct Impl { - Mode m_mode; - + struct Impl + { size_t GetNumIndexes () { @@ -200,48 +201,52 @@ protected: return m_outsourced.GetIndexAtIndex (idx); } } - - struct InlinedIndexes { + + 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 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); + 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) + { + if (!m_process) + return nullptr; - return ValueObjectConstResult::Create(m_process, v, ConstString(idx_name.GetData())); - } + std::pair 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 () @@ -251,53 +256,60 @@ protected: m_ptr_size = 0; m_process = nullptr; } - + + InlinedIndexes () : + 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 - _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}; + 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 + _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}; - } - + 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; - + + struct OutsourcedIndexes + { lldb::ValueObjectSP GetIndexAtIndex (size_t idx) { @@ -315,9 +327,19 @@ protected: m_indexes = nullptr; m_count = 0; } + + OutsourcedIndexes () : + m_indexes(nullptr), + m_count(0) + { + } + + ValueObject *m_indexes; + size_t m_count; }; - - union { + + union + { struct InlinedIndexes m_inlined; struct OutsourcedIndexes m_outsourced; }; @@ -329,6 +351,13 @@ protected: m_inlined.Clear(); m_outsourced.Clear(); } + + Impl() : + m_mode(Mode::Invalid) + { + } + + Mode m_mode; } m_impl; uint32_t m_ptr_size; diff --git a/source/Plugins/Language/ObjC/NSSet.cpp b/source/Plugins/Language/ObjC/NSSet.cpp index 93115957e329..315771045ba6 100644 --- a/source/Plugins/Language/ObjC/NSSet.cpp +++ b/source/Plugins/Language/ObjC/NSSet.cpp @@ -94,33 +94,6 @@ namespace lldb_private { std::vector 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 m_children; - }; - class NSSetMSyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: @@ -215,7 +188,7 @@ lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& str ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(valobj)); - if (!descriptor.get() || !descriptor->IsValid()) + if (!descriptor || !descriptor->IsValid()) return false; uint32_t ptr_size = process_sp->GetAddressByteSize(); @@ -277,7 +250,7 @@ lldb_private::formatters::NSSetSummaryProvider (ValueObject& valobj, Stream& str 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)) + else return false; } @@ -304,10 +277,10 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreat { lldb::ProcessSP process_sp (valobj_sp->GetProcessSP()); if (!process_sp) - return NULL; + return nullptr; ObjCLanguageRuntime *runtime = (ObjCLanguageRuntime*)process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC); if (!runtime) - return NULL; + return nullptr; CompilerType valobj_type(valobj_sp->GetCompilerType()); Flags flags(valobj_type.GetTypeInfo()); @@ -317,19 +290,19 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreat Error error; valobj_sp = valobj_sp->AddressOf(error); if (error.Fail() || !valobj_sp) - return NULL; + return nullptr; } - ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp.get())); + ObjCLanguageRuntime::ClassDescriptorSP descriptor(runtime->GetClassDescriptor(*valobj_sp)); - if (!descriptor.get() || !descriptor->IsValid()) - return NULL; + if (!descriptor || !descriptor->IsValid()) + return nullptr; ConstString class_name_cs = descriptor->GetClassName(); const char* class_name = class_name_cs.GetCString(); if (!class_name || !*class_name) - return NULL; + return nullptr; if (!strcmp(class_name,"__NSSetI")) { @@ -339,26 +312,22 @@ SyntheticChildrenFrontEnd* lldb_private::formatters::NSSetSyntheticFrontEndCreat { 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; + return nullptr; } } 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) + SyntheticChildrenFrontEnd(*valobj_sp), + m_exe_ctx_ref(), + m_ptr_size(8), + m_data_32(nullptr), + m_data_64(nullptr) { if (valobj_sp) Update(); @@ -367,9 +336,9 @@ m_data_64(NULL) lldb_private::formatters::NSSetISyntheticFrontEnd::~NSSetISyntheticFrontEnd () { delete m_data_32; - m_data_32 = NULL; + m_data_32 = nullptr; delete m_data_64; - m_data_64 = NULL; + m_data_64 = nullptr; } size_t @@ -395,9 +364,9 @@ lldb_private::formatters::NSSetISyntheticFrontEnd::Update() { m_children.clear(); delete m_data_32; - m_data_32 = NULL; + m_data_32 = nullptr; delete m_data_64; - m_data_64 = NULL; + m_data_64 = nullptr; m_ptr_size = 0; ValueObjectSP valobj_sp = m_backend.GetSP(); if (!valobj_sp) @@ -521,11 +490,11 @@ lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex (size_t idx) } 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) + SyntheticChildrenFrontEnd(*valobj_sp), + m_exe_ctx_ref(), + m_ptr_size(8), + m_data_32(nullptr), + m_data_64(nullptr) { if (valobj_sp) Update (); @@ -534,9 +503,9 @@ m_data_64(NULL) lldb_private::formatters::NSSetMSyntheticFrontEnd::~NSSetMSyntheticFrontEnd () { delete m_data_32; - m_data_32 = NULL; + m_data_32 = nullptr; delete m_data_64; - m_data_64 = NULL; + m_data_64 = nullptr; } size_t @@ -564,9 +533,9 @@ lldb_private::formatters::NSSetMSyntheticFrontEnd::Update() ValueObjectSP valobj_sp = m_backend.GetSP(); m_ptr_size = 0; delete m_data_32; - m_data_32 = NULL; + m_data_32 = nullptr; delete m_data_64; - m_data_64 = NULL; + m_data_64 = nullptr; if (!valobj_sp) return false; if (!valobj_sp) @@ -688,69 +657,6 @@ lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx) 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 (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); diff --git a/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/source/Plugins/Language/ObjC/ObjCLanguage.cpp index 91a3a0fb4299..0ecbfd35b1a2 100644 --- a/source/Plugins/Language/ObjC/ObjCLanguage.cpp +++ b/source/Plugins/Language/ObjC/ObjCLanguage.cpp @@ -61,6 +61,7 @@ ObjCLanguage::GetPluginNameStatic() //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + lldb_private::ConstString ObjCLanguage::GetPluginName() { @@ -76,6 +77,7 @@ ObjCLanguage::GetPluginVersion() //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + Language * ObjCLanguage::CreateInstance (lldb::LanguageType language) { @@ -192,7 +194,7 @@ ObjCLanguage::MethodName::GetClassNameWithCategory () 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) + if (!m_class && strchr(m_class_category.GetCString(), '(') == nullptr) { m_class = m_class_category; // No '(' was found in the full name, we can definitively say @@ -451,6 +453,7 @@ LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) 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("__NSSingleObjectArrayI"), 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); @@ -460,6 +463,7 @@ LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("NSMutableDictionary"), appkit_flags); AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("__NSCFDictionary"), appkit_flags); AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("__NSDictionaryI"), appkit_flags); + AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("__NSSingleEntryDictionaryI"), appkit_flags); AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("__NSDictionaryM"), appkit_flags); AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("CFDictionaryRef"), appkit_flags); AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDictionarySummaryProvider, "NSDictionary summary provider", ConstString("CFMutableDictionaryRef"), appkit_flags); @@ -487,6 +491,7 @@ LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) 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("__NSSingleObjectArrayI"), 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()); @@ -495,6 +500,7 @@ LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) 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("__NSSingleEntryDictionaryI"), 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()); @@ -532,6 +538,7 @@ LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) 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::NSStringSummaryProvider, "NSString summary provider", ConstString("NSTaggedPointerString"), 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); @@ -540,6 +547,7 @@ LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) AddCXXSummary(objc_category_sp, lldb_private::formatters::NSBundleSummaryProvider, "NSBundle summary provider", ConstString("NSBundle"), appkit_flags); AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider, "NSData summary provider", ConstString("NSData"), appkit_flags); + AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider, "NSData summary provider", ConstString("_NSInlineData"), appkit_flags); AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider, "NSData summary provider", ConstString("NSConcreteData"), appkit_flags); AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider, "NSData summary provider", ConstString("NSConcreteMutableData"), appkit_flags); AddCXXSummary(objc_category_sp, lldb_private::formatters::NSDataSummaryProvider, "NSData summary provider", ConstString("NSMutableData"), appkit_flags); @@ -551,10 +559,7 @@ LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) 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); @@ -562,11 +567,6 @@ LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) 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); @@ -732,7 +732,7 @@ ObjCLanguage::GetTypeScavenger () ConstString key_cs(key); if (clang_modules_decl_vendor->FindDecls(key_cs, false, UINT32_MAX, decls) > 0 && - decls.size() > 0) + !decls.empty()) { CompilerType module_type = ClangASTContext::GetTypeForDecl(decls.front()); result = true; diff --git a/source/Plugins/Language/ObjC/ObjCLanguage.h b/source/Plugins/Language/ObjC/ObjCLanguage.h index e30aa18c0443..b1435d26429a 100644 --- a/source/Plugins/Language/ObjC/ObjCLanguage.h +++ b/source/Plugins/Language/ObjC/ObjCLanguage.h @@ -12,6 +12,7 @@ // C Includes // C++ Includes +#include #include // Other libraries and framework includes @@ -187,7 +188,7 @@ public: if (!name) return false; - if (strchr(name, ':') == NULL) + if (strchr(name, ':') == nullptr) return true; else if (name[strlen(name) - 1] == ':') return true; diff --git a/source/Plugins/Language/ObjCPlusPlus/Makefile b/source/Plugins/Language/ObjCPlusPlus/Makefile deleted file mode 100644 index 74e1a14bcf4d..000000000000 --- a/source/Plugins/Language/ObjCPlusPlus/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Language/ObjCPlusPlus ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginObjCPlusPlusLanguage -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/LanguageRuntime/CMakeLists.txt b/source/Plugins/LanguageRuntime/CMakeLists.txt index 66b17a4af229..2cf579212ec1 100644 --- a/source/Plugins/LanguageRuntime/CMakeLists.txt +++ b/source/Plugins/LanguageRuntime/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(CPlusPlus) add_subdirectory(ObjC) add_subdirectory(Go) +add_subdirectory(Java) add_subdirectory(RenderScript) diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index 8e2cfb5570d9..c49feb07200e 100644 --- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -13,13 +13,18 @@ #include "lldb/Core/ConstString.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" +#include "lldb/Core/Mangled.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/Interpreter/CommandObject.h" +#include "lldb/Interpreter/CommandObjectMultiword.h" +#include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -43,68 +48,26 @@ ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value) 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, - Value::ValueType &value_type) +TypeAndOrName +ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress(ValueObject &in_value, lldb::addr_t original_ptr, + lldb::addr_t vtable_load_addr) { - // 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 - // vtable.) We can then look up the symbol containing this "address point" and that symbol's name - // demangled will contain the full class name. - // The second pointer above the "address point" is the "offset_to_top". We'll use that to get the - // start of the value object which holds the dynamic type. - // - - 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)) + if (m_process && vtable_load_addr != LLDB_INVALID_ADDRESS) { - // First job, pull out the address at 0 offset from the object. - AddressType address_type; - lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type); - if (original_ptr == LLDB_INVALID_ADDRESS) - return false; - - ExecutionContext exe_ctx (in_value.GetExecutionContextRef()); - - Target *target = exe_ctx.GetTargetPtr(); - Process *process = exe_ctx.GetProcessPtr(); - - char memory_buffer[16]; - DataExtractor data(memory_buffer, sizeof(memory_buffer), - process->GetByteOrder(), - process->GetAddressByteSize()); - size_t address_byte_size = process->GetAddressByteSize(); - Error error; - size_t bytes_read = process->ReadMemory (original_ptr, - memory_buffer, - address_byte_size, - error); - if (!error.Success() || (bytes_read != address_byte_size)) - { - return false; - } - - lldb::offset_t offset = 0; - lldb::addr_t vtable_address_point = data.GetAddress (&offset); - - if (offset == 0) - return false; - - // Now find the symbol that contains this address: - - SymbolContext sc; - Address address_point_address; - if (target && !target->GetSectionLoadList().IsEmpty()) + // Find the symbol that contains the "vtable_load_addr" address + Address vtable_addr; + Target &target = m_process->GetTarget(); + if (!target.GetSectionLoadList().IsEmpty()) { - if (target->GetSectionLoadList().ResolveLoadAddress (vtable_address_point, address_point_address)) + if (target.GetSectionLoadList().ResolveLoadAddress(vtable_load_addr, vtable_addr)) { - target->GetImages().ResolveSymbolContextForAddress (address_point_address, eSymbolContextSymbol, sc); + // See if we have cached info for this type already + TypeAndOrName type_info = GetDynamicTypeInfo(vtable_addr); + if (type_info) + return type_info; + + SymbolContext sc; + target.GetImages().ResolveSymbolContextForAddress(vtable_addr, eSymbolContextSymbol, sc); Symbol *symbol = sc.symbol; if (symbol != NULL) { @@ -119,52 +82,56 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, name); // We are a C++ class, that's good. Get the class name and look it up: const char *class_name = name + strlen(vtable_demangled_prefix); - class_type_or_name.SetName (class_name); + type_info.SetName(class_name); const bool exact_match = true; TypeList class_types; - + uint32_t num_matches = 0; // First look in the module that the vtable symbol came from // and look for a single exact match. + llvm::DenseSet searched_symbol_files; if (sc.module_sp) { num_matches = sc.module_sp->FindTypes (sc, ConstString(class_name), exact_match, 1, + searched_symbol_files, class_types); } - + // If we didn't find a symbol, then move on to the entire // module list in the target and get as many unique matches // as possible if (num_matches == 0) { - num_matches = target->GetImages().FindTypes (sc, - ConstString(class_name), - exact_match, - UINT32_MAX, - class_types); + num_matches = target.GetImages().FindTypes(sc, ConstString(class_name), exact_match, + UINT32_MAX, searched_symbol_files, class_types); } - + lldb::TypeSP type_sp; if (num_matches == 0) { if (log) log->Printf("0x%16.16" PRIx64 ": is not dynamic\n", original_ptr); - return false; + return TypeAndOrName(); } if (num_matches == 1) { type_sp = class_types.GetTypeAtIndex(0); - if (log) - log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has dynamic type: uid={0x%" PRIx64 "}, type-name='%s'\n", - original_ptr, - in_value.GetTypeName().AsCString(), - type_sp->GetID(), - type_sp->GetName().GetCString()); - - class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0)); + if (type_sp) + { + if (ClangASTContext::IsCXXClassType(type_sp->GetForwardCompilerType())) + { + if (log) + log->Printf("0x%16.16" PRIx64 + ": static-type = '%s' has dynamic type: uid={0x%" PRIx64 + "}, type-name='%s'\n", + original_ptr, in_value.GetTypeName().AsCString(), type_sp->GetID(), + type_sp->GetName().GetCString()); + type_info.SetTypeSP(type_sp); + } + } } else if (num_matches > 1) { @@ -191,7 +158,7 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, type_sp = class_types.GetTypeAtIndex(i); if (type_sp) { - if (ClangASTContext::IsCXXClassType(type_sp->GetFullCompilerType ())) + if (ClangASTContext::IsCXXClassType(type_sp->GetForwardCompilerType())) { 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", @@ -199,74 +166,112 @@ ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, in_value.GetTypeName().AsCString(), type_sp->GetID(), type_sp->GetName().GetCString()); - class_type_or_name.SetTypeSP(type_sp); - break; + type_info.SetTypeSP(type_sp); } } } - - if (i == num_matches) - { - if (log) - log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, didn't find a C++ match\n", - original_ptr, - in_value.GetTypeName().AsCString()); - return false; - } - } - - // There can only be one type with a given name, - // so we've just found duplicate definitions, and this - // one will do as well as any other. - // We don't consider something to have a dynamic type if - // it is the same as the static type. So compare against - // the value we were handed. - if (type_sp) - { - 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... - return false; - } - // The offset_to_top is two pointers above the address. - Address offset_to_top_address = address_point_address; - int64_t slide = -2 * ((int64_t) target->GetArchitecture().GetAddressByteSize()); - offset_to_top_address.Slide (slide); - - Error error; - lldb::addr_t offset_to_top_location = offset_to_top_address.GetLoadAddress(target); - - size_t bytes_read = process->ReadMemory (offset_to_top_location, - memory_buffer, - address_byte_size, - error); - - if (!error.Success() || (bytes_read != address_byte_size)) - { - return false; - } - - offset = 0; - int64_t offset_to_top = data.GetMaxS64(&offset, process->GetAddressByteSize()); - - // So the dynamic type is a value that starts at offset_to_top - // above the original address. - lldb::addr_t dynamic_addr = original_ptr + offset_to_top; - if (!target->GetSectionLoadList().ResolveLoadAddress (dynamic_addr, dynamic_address)) + if (log && i == num_matches) { - dynamic_address.SetRawAddress(dynamic_addr); + log->Printf("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic " + "types, didn't find a C++ match\n", + original_ptr, in_value.GetTypeName().AsCString()); } - return true; } + if (type_info) + SetDynamicTypeInfo(vtable_addr, type_info); + return type_info; } } } } } - + return TypeAndOrName(); +} + +bool +ItaniumABILanguageRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, + TypeAndOrName &class_type_or_name, 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 + // vtable.) We can then look up the symbol containing this "address point" and that symbol's name + // demangled will contain the full class name. + // The second pointer above the "address point" is the "offset_to_top". We'll use that to get the + // start of the value object which holds the dynamic type. + // + + 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)) + { + // First job, pull out the address at 0 offset from the object. + AddressType address_type; + lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type); + if (original_ptr == LLDB_INVALID_ADDRESS) + return false; + + ExecutionContext exe_ctx(in_value.GetExecutionContextRef()); + + Process *process = exe_ctx.GetProcessPtr(); + + if (process == nullptr) + return false; + + Error error; + const lldb::addr_t vtable_address_point = process->ReadPointerFromMemory(original_ptr, error); + + if (!error.Success() || vtable_address_point == LLDB_INVALID_ADDRESS) + { + return false; + } + + class_type_or_name = GetTypeInfoFromVTableAddress(in_value, original_ptr, vtable_address_point); + + if (class_type_or_name) + { + TypeSP type_sp = class_type_or_name.GetTypeSP(); + // There can only be one type with a given name, + // so we've just found duplicate definitions, and this + // one will do as well as any other. + // We don't consider something to have a dynamic type if + // it is the same as the static type. So compare against + // the value we were handed. + if (type_sp) + { + if (ClangASTContext::AreTypesSame(in_value.GetCompilerType(), type_sp->GetForwardCompilerType())) + { + // The dynamic type we found was the same type, + // so we don't have a dynamic type here... + return false; + } + + // The offset_to_top is two pointers above the vtable pointer. + const uint32_t addr_byte_size = process->GetAddressByteSize(); + const lldb::addr_t offset_to_top_location = vtable_address_point - 2 * addr_byte_size; + // Watch for underflow, offset_to_top_location should be less than vtable_address_point + if (offset_to_top_location >= vtable_address_point) + return false; + const int64_t offset_to_top = + process->ReadSignedIntegerFromMemory(offset_to_top_location, addr_byte_size, INT64_MIN, error); + + if (offset_to_top == INT64_MIN) + return false; + // So the dynamic type is a value that starts at offset_to_top + // above the original address. + lldb::addr_t dynamic_addr = original_ptr + offset_to_top; + if (!process->GetTarget().GetSectionLoadList().ResolveLoadAddress(dynamic_addr, dynamic_address)) + { + dynamic_address.SetRawAddress(dynamic_addr); + } + return true; + } + } + } + return class_type_or_name.IsEmpty() == false; } @@ -336,12 +341,94 @@ ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType return NULL; } +class CommandObjectMultiwordItaniumABI_Demangle : public CommandObjectParsed +{ +public: + CommandObjectMultiwordItaniumABI_Demangle (CommandInterpreter &interpreter) : + CommandObjectParsed (interpreter, + "demangle", + "Demangle a C++ mangled name.", + "language cplusplus demangle") + { + CommandArgumentEntry arg; + CommandArgumentData index_arg; + + // Define the first (and only) variant of this arg. + index_arg.arg_type = eArgTypeSymbol; + index_arg.arg_repetition = eArgRepeatPlus; + + // There is only one variant this argument could be; put it into the argument entry. + arg.push_back (index_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back (arg); + } + + ~CommandObjectMultiwordItaniumABI_Demangle() override = default; + +protected: + bool + DoExecute(Args& command, CommandReturnObject &result) override + { + bool demangled_any = false; + bool error_any = false; + for (size_t i = 0; i < command.GetArgumentCount(); i++) + { + auto arg = command.GetArgumentAtIndex(i); + if (arg && *arg) + { + ConstString mangled_cs(arg); + + // the actual Mangled class should be strict about this, but on the command line + // if you're copying mangled names out of 'nm' on Darwin, they will come out with + // an extra underscore - be willing to strip this on behalf of the user + // This is the moral equivalent of the -_/-n options to c++filt + if (mangled_cs.GetStringRef().startswith("__Z")) + mangled_cs.SetCString(arg+1); + + Mangled mangled(mangled_cs, true); + if (mangled.GuessLanguage() == lldb::eLanguageTypeC_plus_plus) + { + ConstString demangled(mangled.GetDisplayDemangledName(lldb::eLanguageTypeC_plus_plus)); + demangled_any = true; + result.AppendMessageWithFormat("%s ---> %s\n", arg, demangled.GetCString()); + } + else + { + error_any = true; + result.AppendErrorWithFormat("%s is not a valid C++ mangled name\n", arg); + } + } + } + + result.SetStatus(error_any ? lldb::eReturnStatusFailed : + (demangled_any ? lldb::eReturnStatusSuccessFinishResult : lldb::eReturnStatusSuccessFinishNoResult)); + return result.Succeeded(); + } +}; + +class CommandObjectMultiwordItaniumABI : public CommandObjectMultiword +{ +public: + CommandObjectMultiwordItaniumABI(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "cplusplus", "Commands for operating on the C++ language runtime.", + "cplusplus []") + { + LoadSubCommand ("demangle", CommandObjectSP (new CommandObjectMultiwordItaniumABI_Demangle (interpreter))); + } + + ~CommandObjectMultiwordItaniumABI() override = default; +}; + void ItaniumABILanguageRuntime::Initialize() { PluginManager::RegisterPlugin (GetPluginNameStatic(), "Itanium ABI for the C++ language", - CreateInstance); + CreateInstance, + [] (CommandInterpreter& interpreter) -> lldb::CommandObjectSP { + return CommandObjectSP(new CommandObjectMultiwordItaniumABI(interpreter)); + }); } void @@ -408,6 +495,7 @@ ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch exception_names.size(), eFunctionNameTypeBase, eLanguageTypeUnknown, + 0, eLazyBoolNo)); return resolver_sp; @@ -510,3 +598,21 @@ ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP sto m_cxx_exception_bp_sp->GetID()); } + +TypeAndOrName +ItaniumABILanguageRuntime::GetDynamicTypeInfo(const lldb_private::Address &vtable_addr) +{ + std::lock_guard locker(m_dynamic_type_map_mutex); + DynamicTypeCache::const_iterator pos = m_dynamic_type_map.find(vtable_addr); + if (pos == m_dynamic_type_map.end()) + return TypeAndOrName(); + else + return pos->second; +} + +void +ItaniumABILanguageRuntime::SetDynamicTypeInfo(const lldb_private::Address &vtable_addr, const TypeAndOrName &type_info) +{ + std::lock_guard locker(m_dynamic_type_map_mutex); + m_dynamic_type_map[vtable_addr] = type_info; +} diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h index c06b9863a9bf..86bd728d6c6f 100644 --- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h +++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h @@ -12,12 +12,15 @@ // C Includes // C++ Includes +#include +#include #include // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" #include "lldb/Breakpoint/BreakpointResolver.h" +#include "lldb/Symbol/Type.h" #include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/CPPLanguageRuntime.h" #include "lldb/Core/Value.h" @@ -100,9 +103,29 @@ namespace lldb_private { bool is_internal); private: - ItaniumABILanguageRuntime(Process *process) : lldb_private::CPPLanguageRuntime(process) { } // Call CreateInstance instead. - - lldb::BreakpointSP m_cxx_exception_bp_sp; + typedef std::map DynamicTypeCache; + + ItaniumABILanguageRuntime(Process *process) + : // Call CreateInstance instead. + lldb_private::CPPLanguageRuntime(process), + m_cxx_exception_bp_sp(), + m_dynamic_type_map(), + m_dynamic_type_map_mutex() + { + } + + lldb::BreakpointSP m_cxx_exception_bp_sp; + DynamicTypeCache m_dynamic_type_map; + std::mutex m_dynamic_type_map_mutex; + + TypeAndOrName + GetTypeInfoFromVTableAddress(ValueObject &in_value, lldb::addr_t original_ptr, lldb::addr_t vtable_addr); + + TypeAndOrName + GetDynamicTypeInfo(const lldb_private::Address &vtable_addr); + + void + SetDynamicTypeInfo(const lldb_private::Address &vtable_addr, const TypeAndOrName &type_info); }; } // namespace lldb_private diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/Makefile b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/Makefile deleted file mode 100644 index ac87437f9d2a..000000000000 --- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/LangRuntime/C++/ItaniumABI/Makefile --*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../../.. -LIBRARYNAME := lldbPluginCXXItaniumABI -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp b/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp index d59f292e7a08..c752971e7a09 100644 --- a/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp +++ b/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp @@ -20,6 +20,7 @@ #include "lldb/Core/ValueObjectMemory.h" #include "lldb/Symbol/GoASTContext.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -117,10 +118,12 @@ LookupRuntimeType(ValueObjectSP type, ExecutionContext* exe_ctx, bool* is_direct SymbolContext sc; TypeList type_list; + llvm::DenseSet searched_symbol_files; uint32_t num_matches = target->GetImages().FindTypes (sc, const_typename, false, 2, + searched_symbol_files, type_list); if (num_matches > 0) { return type_list.GetTypeAtIndex(0)->GetFullCompilerType(); diff --git a/source/Plugins/LanguageRuntime/Go/Makefile b/source/Plugins/LanguageRuntime/Go/Makefile deleted file mode 100644 index 1c8114e421c1..000000000000 --- a/source/Plugins/LanguageRuntime/Go/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- Source/Plugins/LangRuntime/Go/Makefile ----*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginLanguageRuntimeGo -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/LanguageRuntime/Java/CMakeLists.txt b/source/Plugins/LanguageRuntime/Java/CMakeLists.txt new file mode 100644 index 000000000000..4cfd71c2e242 --- /dev/null +++ b/source/Plugins/LanguageRuntime/Java/CMakeLists.txt @@ -0,0 +1,3 @@ +add_lldb_library(lldbPluginLanguageRuntimeJava + JavaLanguageRuntime.cpp + ) diff --git a/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.cpp b/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.cpp new file mode 100644 index 000000000000..07312a8af0d6 --- /dev/null +++ b/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.cpp @@ -0,0 +1,176 @@ +//===-- JavaLanguageRuntime.cpp ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "JavaLanguageRuntime.h" + +#include "lldb/Core/PluginManager.h" +#include "lldb/Symbol/JavaASTContext.h" +#include "lldb/Symbol/Symbol.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/SymbolFile.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/TypeList.h" +#include "lldb/Target/SectionLoadList.h" +#include "lldb/Target/Target.h" +#include "llvm/ADT/StringRef.h" + +using namespace lldb; +using namespace lldb_private; + +JavaLanguageRuntime::JavaLanguageRuntime(Process *process) : LanguageRuntime(process) +{ +} + +LanguageRuntime * +JavaLanguageRuntime::CreateInstance(Process *process, lldb::LanguageType language) +{ + if (language == eLanguageTypeJava) + return new JavaLanguageRuntime(process); + return nullptr; +} + +void +JavaLanguageRuntime::Initialize() +{ + PluginManager::RegisterPlugin(GetPluginNameStatic(), "Java language runtime", CreateInstance); +} + +void +JavaLanguageRuntime::Terminate() +{ + PluginManager::UnregisterPlugin(CreateInstance); +} + +lldb_private::ConstString +JavaLanguageRuntime::GetPluginNameStatic() +{ + static ConstString g_name("java"); + return g_name; +} + +lldb_private::ConstString +JavaLanguageRuntime::GetPluginName() +{ + return GetPluginNameStatic(); +} + +uint32_t +JavaLanguageRuntime::GetPluginVersion() +{ + return 1; +} + +bool +JavaLanguageRuntime::CouldHaveDynamicValue(ValueObject &in_value) +{ + return true; +} + +static ConstString +GetDynamicTypeId(ExecutionContext *exe_ctx, Target *target, ValueObject &in_value) +{ + SymbolContext sc; + TypeList class_types; + llvm::DenseSet searched_symbol_files; + size_t num_matches = target->GetImages().FindTypes(sc, ConstString("Object"), + true, // name_is_fully_qualified + UINT32_MAX, searched_symbol_files, class_types); + for (size_t i = 0; i < num_matches; ++i) + { + TypeSP type_sp = class_types.GetTypeAtIndex(i); + CompilerType compiler_type = type_sp->GetFullCompilerType(); + + if (compiler_type.GetMinimumLanguage() != eLanguageTypeJava || + compiler_type.GetTypeName() != ConstString("java::lang::Object")) + continue; + + if (compiler_type.GetCompleteType() && compiler_type.IsCompleteType()) + { + uint64_t type_id = JavaASTContext::CalculateDynamicTypeId(exe_ctx, compiler_type, in_value); + if (type_id != UINT64_MAX) + { + char id[32]; + snprintf(id, sizeof(id), "0x%" PRIX64, type_id); + return ConstString(id); + } + } + } + return ConstString(); +} + +bool +JavaLanguageRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, + TypeAndOrName &class_type_or_name, Address &dynamic_address, + Value::ValueType &value_type) +{ + class_type_or_name.Clear(); + + // null references don't have a dynamic type + if (in_value.IsNilReference()) + return false; + + ExecutionContext exe_ctx(in_value.GetExecutionContextRef()); + Target *target = exe_ctx.GetTargetPtr(); + if (!target) + return false; + + ConstString linkage_name; + CompilerType in_type = in_value.GetCompilerType(); + if (in_type.IsPossibleDynamicType(nullptr, false, false)) + linkage_name = GetDynamicTypeId(&exe_ctx, target, in_value); + else + linkage_name = JavaASTContext::GetLinkageName(in_type); + + if (!linkage_name) + return false; + + class_type_or_name.SetName(in_type.GetNonReferenceType().GetTypeName()); + + SymbolContext sc; + TypeList class_types; + llvm::DenseSet searched_symbol_files; + size_t num_matches = target->GetImages().FindTypes(sc, linkage_name, + true, // name_is_fully_qualified + UINT32_MAX, searched_symbol_files, class_types); + + for (size_t i = 0; i < num_matches; ++i) + { + TypeSP type_sp = class_types.GetTypeAtIndex(i); + CompilerType compiler_type = type_sp->GetFullCompilerType(); + + if (compiler_type.GetMinimumLanguage() != eLanguageTypeJava) + continue; + + if (compiler_type.GetCompleteType() && compiler_type.IsCompleteType()) + { + class_type_or_name.SetTypeSP(type_sp); + + Value &value = in_value.GetValue(); + value_type = value.GetValueType(); + dynamic_address.SetRawAddress(value.GetScalar().ULongLong(0)); + return true; + } + } + return false; +} + +TypeAndOrName +JavaLanguageRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value) +{ + CompilerType static_type(static_value.GetCompilerType()); + + TypeAndOrName ret(type_and_or_name); + if (type_and_or_name.HasType()) + { + CompilerType orig_type = type_and_or_name.GetCompilerType(); + if (static_type.IsReferenceType()) + ret.SetCompilerType(orig_type.GetLValueReferenceType()); + } + return ret; +} diff --git a/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.h b/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.h new file mode 100644 index 000000000000..83ed35dbb59d --- /dev/null +++ b/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.h @@ -0,0 +1,90 @@ +//===-- JavaLanguageRuntime.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_JavaLanguageRuntime_h_ +#define liblldb_JavaLanguageRuntime_h_ + +// C Includes +// C++ Includes +#include +// Other libraries and framework includes +// Project includes +#include "lldb/Core/PluginInterface.h" +#include "lldb/Target/LanguageRuntime.h" +#include "lldb/lldb-private.h" + +namespace lldb_private +{ + +class JavaLanguageRuntime : public LanguageRuntime +{ +public: + static void + Initialize(); + + static void + Terminate(); + + static lldb_private::LanguageRuntime * + CreateInstance(Process *process, lldb::LanguageType language); + + static lldb_private::ConstString + GetPluginNameStatic(); + + lldb_private::ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; + + lldb::LanguageType + GetLanguageType() const override + { + return lldb::eLanguageTypeJava; + } + + bool + GetObjectDescription(Stream &str, ValueObject &object) override + { + return false; + } + + bool + GetObjectDescription(Stream &str, Value &value, ExecutionContextScope *exe_scope) override + { + return false; + } + + lldb::BreakpointResolverSP + CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override + { + return nullptr; + } + + TypeAndOrName + FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value) override; + + bool + CouldHaveDynamicValue(ValueObject &in_value) override; + + bool + GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, + TypeAndOrName &class_type_or_name, Address &address, + Value::ValueType &value_type) override; + +protected: + JavaLanguageRuntime(Process *process); + +private: + DISALLOW_COPY_AND_ASSIGN(JavaLanguageRuntime); +}; + +} // namespace lldb_private + +#endif // liblldb_JavaLanguageRuntime_h_ diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp index 711d324d8aa7..5cf99a573d86 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp @@ -499,11 +499,9 @@ ClassDescriptorV2::GetInstanceSize () return 0; } -ClassDescriptorV2::iVarsStorage::iVarsStorage (): -m_filled(false), -m_ivars(), -m_mutex(Mutex::eMutexTypeRecursive) -{} +ClassDescriptorV2::iVarsStorage::iVarsStorage() : m_filled(false), m_ivars(), m_mutex() +{ +} size_t ClassDescriptorV2::iVarsStorage::size () @@ -522,7 +520,7 @@ ClassDescriptorV2::iVarsStorage::fill (AppleObjCRuntimeV2& runtime, ClassDescrip { if (m_filled) return; - Mutex::Locker lock(m_mutex); + std::lock_guard guard(m_mutex); Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES | LIBLLDB_LOG_VERBOSE)); if (log) log->Printf("[ClassDescriptorV2::iVarsStorage::fill] class_name = %s", descriptor.GetClassName().AsCString(" + // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" -#include "lldb/Host/Mutex.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "AppleObjCRuntimeV2.h" @@ -247,7 +248,7 @@ private: private: bool m_filled; std::vector m_ivars; - Mutex m_mutex; + std::recursive_mutex m_mutex; }; // The constructor should only be invoked by the runtime as it builds its caches diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp index cd6ece297ed1..0c0e4f1ce8cc 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp @@ -9,10 +9,11 @@ #include "AppleObjCDeclVendor.h" +#include "Plugins/ExpressionParser/Clang/ASTDumper.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" -#include "Plugins/ExpressionParser/Clang/ASTDumper.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" +#include "lldb/Symbol/ClangUtil.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -356,9 +357,10 @@ public: } clang::Selector sel = ast_ctx.Selectors.getSelector(is_zero_argument ? 0 : selector_components.size(), selector_components.data()); - - clang::QualType ret_type = ClangASTContext::GetQualType(type_realizer_sp->RealizeType(interface_decl->getASTContext(), m_type_vector[0].c_str(), for_expression)); - + + clang::QualType ret_type = ClangUtil::GetQualType( + type_realizer_sp->RealizeType(interface_decl->getASTContext(), m_type_vector[0].c_str(), for_expression)); + if (ret_type.isNull()) return NULL; @@ -384,8 +386,9 @@ public: ++ai) { const bool for_expression = true; - clang::QualType arg_type = ClangASTContext::GetQualType(type_realizer_sp->RealizeType(ast_ctx, m_type_vector[ai].c_str(), for_expression)); - + clang::QualType arg_type = ClangUtil::GetQualType( + type_realizer_sp->RealizeType(ast_ctx, m_type_vector[ai].c_str(), for_expression)); + if (arg_type.isNull()) return NULL; // well, we just wasted a bunch of time. Wish we could delete the stuff we'd just made! @@ -404,6 +407,24 @@ public: return ret; } + + explicit operator bool () + { + return m_is_valid; + } + + size_t + GetNumTypes () + { + return m_type_vector.size(); + } + + const char* + GetTypeAtIndex (size_t idx) + { + return m_type_vector[idx].c_str(); + } + private: typedef std::vector TypeVector; @@ -502,17 +523,12 @@ AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { clang::TypeSourceInfo * const type_source_info = nullptr; const bool is_synthesized = false; - clang::ObjCIvarDecl *ivar_decl = clang::ObjCIvarDecl::Create (*m_ast_ctx.getASTContext(), - interface_decl, - clang::SourceLocation(), - clang::SourceLocation(), - &m_ast_ctx.getASTContext()->Idents.get(name), - ClangASTContext::GetQualType(ivar_type), - type_source_info, // TypeSourceInfo * - clang::ObjCIvarDecl::Public, - 0, - is_synthesized); - + clang::ObjCIvarDecl *ivar_decl = clang::ObjCIvarDecl::Create( + *m_ast_ctx.getASTContext(), interface_decl, clang::SourceLocation(), clang::SourceLocation(), + &m_ast_ctx.getASTContext()->Idents.get(name), ClangUtil::GetQualType(ivar_type), + type_source_info, // TypeSourceInfo * + clang::ObjCIvarDecl::Public, 0, is_synthesized); + if (ivar_decl) { interface_decl->addDecl(ivar_decl); diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp index 2810b24cb7a4..6d83f7a7c5e1 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -23,6 +23,7 @@ #include "lldb/Core/Section.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ObjectFile.h" @@ -151,10 +152,10 @@ AppleObjCRuntime::GetObjectDescription (Stream &strm, Value &value, ExecutionCon exe_ctx.SetFrameSP(thread->GetSelectedFrame()); } } - + // Now we're ready to call the function: - - StreamString error_stream; + + DiagnosticManager diagnostics; lldb::addr_t wrapper_struct_addr = LLDB_INVALID_ADDRESS; if (!m_print_object_caller_up) @@ -172,30 +173,22 @@ AppleObjCRuntime::GetObjectDescription (Stream &strm, Value &value, ExecutionCon strm.Printf("Could not get function runner to call print for debugger function: %s.", error.AsCString()); return false; } - m_print_object_caller_up->InsertFunction(exe_ctx, wrapper_struct_addr, error_stream); + m_print_object_caller_up->InsertFunction(exe_ctx, wrapper_struct_addr, diagnostics); } else { - m_print_object_caller_up->WriteFunctionArguments(exe_ctx, - wrapper_struct_addr, - arg_value_list, - error_stream); + m_print_object_caller_up->WriteFunctionArguments(exe_ctx, wrapper_struct_addr, arg_value_list, diagnostics); } - - EvaluateExpressionOptions options; options.SetUnwindOnError(true); options.SetTryAllThreads(true); options.SetStopOthers(true); options.SetIgnoreBreakpoints(true); options.SetTimeoutUsec(PO_FUNCTION_TIMEOUT_USEC); - - ExpressionResults results = m_print_object_caller_up->ExecuteFunction (exe_ctx, - &wrapper_struct_addr, - options, - error_stream, - ret); + + ExpressionResults results = + m_print_object_caller_up->ExecuteFunction(exe_ctx, &wrapper_struct_addr, options, diagnostics, ret); if (results != eExpressionCompleted) { strm.Printf("Error evaluating Print Object function: %d.\n", results); @@ -401,8 +394,8 @@ AppleObjCRuntime::GetObjCVersion (Process *process, ModuleSP &objc_module_sp) return ObjCRuntimeVersions::eObjC_VersionUnknown; const ModuleList &target_modules = target.GetImages(); - Mutex::Locker modules_locker(target_modules.GetMutex()); - + std::lock_guard gaurd(target_modules.GetMutex()); + size_t num_images = target_modules.GetSize(); for (size_t i = 0; i < num_images; i++) { @@ -531,7 +524,7 @@ AppleObjCRuntime::ReadObjCLibraryIfNeeded (const ModuleList &module_list) { if (!HasReadObjCLibrary ()) { - Mutex::Locker locker (module_list.GetMutex ()); + std::lock_guard guard(module_list.GetMutex()); size_t num_modules = module_list.GetSize(); for (size_t i = 0; i < num_modules; i++) diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp index 59b28b63f6b3..805fca7a31b9 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp @@ -136,6 +136,7 @@ AppleObjCRuntimeV1::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bo eFunctionNameTypeBase, eLanguageTypeUnknown, Breakpoint::Exact, + 0, eLazyBoolNo)); // FIXME: don't do catch yet. return resolver_sp; diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 584449430829..e9a799bb3651 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -36,12 +36,14 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/Timer.h" #include "lldb/Core/ValueObjectVariable.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/CommandObjectMultiword.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/OptionValueBoolean.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Symbol.h" @@ -60,9 +62,6 @@ #include "AppleObjCDeclVendor.h" #include "AppleObjCTrampolineHandler.h" -#if defined(__APPLE__) -#include "Plugins/Platform/MacOSX/PlatformiOSSimulator.h" -#endif using namespace lldb; using namespace lldb_private; @@ -81,12 +80,7 @@ extern "C" char *strncpy (char * s1, const char * s2, size_t n); int printf(const char * format, ...); } -//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN -#ifdef ENABLE_DEBUG_PRINTF -#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else -#define DEBUG_PRINTF(fmt, ...) -#endif +#define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__) typedef struct _NXMapTable { void *prototype; @@ -112,7 +106,8 @@ struct ClassInfo uint32_t __lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr, void *class_infos_ptr, - uint32_t class_infos_byte_size) + uint32_t class_infos_byte_size, + uint32_t should_log) { DEBUG_PRINTF ("gdb_objc_realized_classes_ptr = %p\n", gdb_objc_realized_classes_ptr); DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr); @@ -170,12 +165,7 @@ extern "C" int printf(const char * format, ...); } -// #define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN -#ifdef ENABLE_DEBUG_PRINTF -#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__) -#else -#define DEBUG_PRINTF(fmt, ...) -#endif +#define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__) struct objc_classheader_t { @@ -224,12 +214,13 @@ struct ClassInfo uint32_t __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr, void *class_infos_ptr, - uint32_t class_infos_byte_size) + uint32_t class_infos_byte_size, + uint32_t should_log) { uint32_t idx = 0; DEBUG_PRINTF ("objc_opt_ro_ptr = %p\n", objc_opt_ro_ptr); DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr); - DEBUG_PRINTF ("class_infos_byte_size = %u (%" PRIu64 " class infos)\n", class_infos_byte_size, (size_t)(class_infos_byte_size/sizeof(ClassInfo))); + DEBUG_PRINTF ("class_infos_byte_size = %u (%llu class infos)\n", class_infos_byte_size, (uint64_t)(class_infos_byte_size/sizeof(ClassInfo))); if (objc_opt_ro_ptr) { const objc_opt_t *objc_opt = (objc_opt_t *)objc_opt_ro_ptr; @@ -250,7 +241,7 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr, DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt->headeropt_offset); DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt->clsopt_offset); } - if (objc_opt->version == 12 || objc_opt->version == 13 || objc_opt->version == 14) + if (objc_opt->version == 12 || objc_opt->version == 13 || objc_opt->version == 14 || objc_opt->version == 15) { const objc_clsopt_t* clsopt = NULL; if (is_v14_format) @@ -258,6 +249,7 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr, else clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt + objc_opt->clsopt_offset); const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo); + DEBUG_PRINTF("max_class_infos = %llu\n", (uint64_t)max_class_infos); ClassInfo *class_infos = (ClassInfo *)class_infos_ptr; int32_t invalidEntryOffset = 0; // this is safe to do because the version field order is invariant @@ -269,13 +261,21 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr, DEBUG_PRINTF ("clsopt->capacity = %u\n", clsopt->capacity); DEBUG_PRINTF ("clsopt->mask = 0x%8.8x\n", clsopt->mask); DEBUG_PRINTF ("classOffsets = %p\n", classOffsets); + DEBUG_PRINTF("invalidEntryOffset = %d\n", invalidEntryOffset); for (uint32_t i=0; icapacity; ++i) { const int32_t clsOffset = classOffsets[i].clsOffset; + DEBUG_PRINTF("clsOffset[%u] = %u\n", i, clsOffset); if (clsOffset & 1) + { + DEBUG_PRINTF("clsOffset & 1\n"); continue; // duplicate + } else if (clsOffset == invalidEntryOffset) + { + DEBUG_PRINTF("clsOffset == invalidEntryOffset\n"); continue; // invalid offset + } if (class_infos && idx < max_class_infos) { @@ -289,6 +289,10 @@ __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr, h = ((h << 5) + h) + c; class_infos[idx].hash = h; } + else + { + DEBUG_PRINTF("not(class_infos && idx < max_class_infos)\n"); + } ++idx; } @@ -375,27 +379,27 @@ ExtractRuntimeGlobalSymbol (Process* process, } } -AppleObjCRuntimeV2::AppleObjCRuntimeV2 (Process *process, - const ModuleSP &objc_module_sp) : - AppleObjCRuntime (process), - m_get_class_info_code(), - m_get_class_info_args (LLDB_INVALID_ADDRESS), - m_get_class_info_args_mutex (Mutex::eMutexTypeNormal), - m_get_shared_cache_class_info_code(), - m_get_shared_cache_class_info_args (LLDB_INVALID_ADDRESS), - m_get_shared_cache_class_info_args_mutex (Mutex::eMutexTypeNormal), - m_decl_vendor_ap (), - m_isa_hash_table_ptr (LLDB_INVALID_ADDRESS), - m_hash_signature (), - m_has_object_getClass (false), - m_loaded_objc_opt (false), - m_non_pointer_isa_cache_ap(NonPointerISACache::CreateInstance(*this,objc_module_sp)), - m_tagged_pointer_vendor_ap(TaggedPointerVendorV2::CreateInstance(*this,objc_module_sp)), - m_encoding_to_type_sp(), - m_noclasses_warning_emitted(false) +AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process, const ModuleSP &objc_module_sp) + : AppleObjCRuntime(process), + m_get_class_info_code(), + m_get_class_info_args(LLDB_INVALID_ADDRESS), + m_get_class_info_args_mutex(), + m_get_shared_cache_class_info_code(), + m_get_shared_cache_class_info_args(LLDB_INVALID_ADDRESS), + m_get_shared_cache_class_info_args_mutex(), + m_decl_vendor_ap(), + m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS), + m_hash_signature(), + m_has_object_getClass(false), + m_loaded_objc_opt(false), + m_non_pointer_isa_cache_ap(NonPointerISACache::CreateInstance(*this, objc_module_sp)), + m_tagged_pointer_vendor_ap(TaggedPointerVendorV2::CreateInstance(*this, objc_module_sp)), + m_encoding_to_type_sp(), + m_noclasses_warning_emitted(false) { static const ConstString g_gdb_object_getClass("gdb_object_getClass"); - m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_object_getClass, eSymbolTypeCode) != NULL); + m_has_object_getClass = + (objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_object_getClass, eSymbolTypeCode) != NULL); } bool @@ -485,6 +489,52 @@ AppleObjCRuntimeV2::CreateInstance (Process *process, LanguageType language) class CommandObjectObjC_ClassTable_Dump : public CommandObjectParsed { public: + class CommandOptions : public Options + { + public: + CommandOptions (CommandInterpreter &interpreter) : + Options(interpreter), + m_verbose(false,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 'v': + m_verbose.SetCurrentValue(true); + m_verbose.SetOptionWasSet(); + break; + + default: + error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); + break; + } + + return error; + } + + void + OptionParsingStarting() override + { + m_verbose.Clear(); + } + + const OptionDefinition* + GetDefinitions() override + { + return g_option_table; + } + + OptionValueBoolean m_verbose; + static OptionDefinition g_option_table[]; + }; + CommandObjectObjC_ClassTable_Dump (CommandInterpreter &interpreter) : CommandObjectParsed (interpreter, "dump", @@ -492,39 +542,116 @@ public: "language objc class-table dump", eCommandRequiresProcess | eCommandProcessMustBeLaunched | - eCommandProcessMustBePaused ) + eCommandProcessMustBePaused ), + m_options(interpreter) { + CommandArgumentEntry arg; + CommandArgumentData index_arg; + + // Define the first (and only) variant of this arg. + index_arg.arg_type = eArgTypeRegularExpression; + index_arg.arg_repetition = eArgRepeatOptional; + + // There is only one variant this argument could be; put it into the argument entry. + arg.push_back (index_arg); + + // Push the data for the first argument into the m_arguments vector. + m_arguments.push_back (arg); } ~CommandObjectObjC_ClassTable_Dump() override = default; + Options * + GetOptions() override + { + return &m_options; + } + protected: bool DoExecute(Args& command, CommandReturnObject &result) override { + std::unique_ptr regex_up; + switch(command.GetArgumentCount()) + { + case 0: + break; + case 1: + { + regex_up.reset(new RegularExpression()); + if (!regex_up->Compile(command.GetArgumentAtIndex(0))) + { + result.AppendError("invalid argument - please provide a valid regular expression"); + result.SetStatus(lldb::eReturnStatusFailed); + return false; + } + break; + } + default: + { + result.AppendError("please provide 0 or 1 arguments"); + result.SetStatus(lldb::eReturnStatusFailed); + return false; + } + } + Process *process = m_exe_ctx.GetProcessPtr(); ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime(); if (objc_runtime) { auto iterators_pair = objc_runtime->GetDescriptorIteratorPair(); auto iterator = iterators_pair.first; + auto &std_out = result.GetOutputStream(); for(; iterator != iterators_pair.second; iterator++) { - result.GetOutputStream().Printf("isa = 0x%" PRIx64, iterator->first); if (iterator->second) { - result.GetOutputStream().Printf(" name = %s", iterator->second->GetClassName().AsCString("")); - result.GetOutputStream().Printf(" instance size = %" PRIu64, iterator->second->GetInstanceSize()); - result.GetOutputStream().Printf(" num ivars = %" PRIuPTR, (uintptr_t)iterator->second->GetNumIVars()); + const char* class_name = iterator->second->GetClassName().AsCString(""); + if (regex_up && class_name && !regex_up->Execute(class_name)) + continue; + std_out.Printf("isa = 0x%" PRIx64, iterator->first); + std_out.Printf(" name = %s", class_name); + std_out.Printf(" instance size = %" PRIu64, iterator->second->GetInstanceSize()); + std_out.Printf(" num ivars = %" PRIuPTR, (uintptr_t)iterator->second->GetNumIVars()); if (auto superclass = iterator->second->GetSuperclass()) { - result.GetOutputStream().Printf(" superclass = %s", superclass->GetClassName().AsCString("")); + std_out.Printf(" superclass = %s", superclass->GetClassName().AsCString("")); + } + std_out.Printf("\n"); + if (m_options.m_verbose) + { + for(size_t i = 0; + i < iterator->second->GetNumIVars(); + i++) + { + auto ivar = iterator->second->GetIVarAtIndex(i); + std_out.Printf(" ivar name = %s type = %s size = %" PRIu64 " offset = %" PRId32 "\n", + ivar.m_name.AsCString(""), + ivar.m_type.GetDisplayTypeName().AsCString(""), + ivar.m_size, + ivar.m_offset); + } + iterator->second->Describe(nullptr, + [objc_runtime, &std_out] (const char* name, const char* type) -> bool { + std_out.Printf(" instance method name = %s type = %s\n", + name, + type); + return false; + }, + [objc_runtime, &std_out] (const char* name, const char* type) -> bool { + std_out.Printf(" class method name = %s type = %s\n", + name, + type); + return false; + }, + nullptr); } - result.GetOutputStream().Printf("\n"); } else { - result.GetOutputStream().Printf(" has no associated class.\n"); + if (regex_up && !regex_up->Execute("")) + continue; + std_out.Printf("isa = 0x%" PRIx64 " has no associated class.\n", iterator->first); } } result.SetStatus(lldb::eReturnStatusSuccessFinishResult); @@ -537,6 +664,15 @@ protected: return false; } } + + CommandOptions m_options; +}; + +OptionDefinition +CommandObjectObjC_ClassTable_Dump::CommandOptions::g_option_table[] = +{ + { LLDB_OPT_SET_ALL, false, "verbose" , 'v', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Print ivar and method information in detail"}, + { 0 , false, nullptr , 0, 0 , nullptr, nullptr, 0, eArgTypeNone, nullptr } }; class CommandObjectMultiwordObjC_TaggedPointer_Info : public CommandObjectParsed @@ -639,11 +775,9 @@ protected: class CommandObjectMultiwordObjC_ClassTable : public CommandObjectMultiword { public: - CommandObjectMultiwordObjC_ClassTable (CommandInterpreter &interpreter) : - CommandObjectMultiword (interpreter, - "class-table", - "A set of commands for operating on the Objective-C class table.", - "class-table []") + CommandObjectMultiwordObjC_ClassTable(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "class-table", "Commands for operating on the Objective-C class table.", + "class-table []") { LoadSubCommand ("dump", CommandObjectSP (new CommandObjectObjC_ClassTable_Dump (interpreter))); } @@ -654,12 +788,10 @@ public: class CommandObjectMultiwordObjC_TaggedPointer : public CommandObjectMultiword { public: - - CommandObjectMultiwordObjC_TaggedPointer (CommandInterpreter &interpreter) : - CommandObjectMultiword (interpreter, - "tagged-pointer", - "A set of commands for operating on Objective-C tagged pointers.", - "class-table []") + CommandObjectMultiwordObjC_TaggedPointer(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "tagged-pointer", + "Commands for operating on Objective-C tagged pointers.", + "class-table []") { LoadSubCommand ("info", CommandObjectSP (new CommandObjectMultiwordObjC_TaggedPointer_Info (interpreter))); } @@ -670,11 +802,9 @@ public: class CommandObjectMultiwordObjC : public CommandObjectMultiword { public: - CommandObjectMultiwordObjC (CommandInterpreter &interpreter) : - CommandObjectMultiword (interpreter, - "objc", - "A set of commands for operating on the Objective-C Language Runtime.", - "objc []") + CommandObjectMultiwordObjC(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "objc", "Commands for operating on the Objective-C language runtime.", + "objc []") { LoadSubCommand ("class-table", CommandObjectSP (new CommandObjectMultiwordObjC_ClassTable (interpreter))); LoadSubCommand ("tagged-pointer", CommandObjectSP (new CommandObjectMultiwordObjC_TaggedPointer (interpreter))); @@ -733,6 +863,7 @@ AppleObjCRuntimeV2::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bo eFunctionNameTypeBase, eLanguageTypeUnknown, Breakpoint::Exact, + 0, eLazyBoolNo)); // FIXME: We don't do catch breakpoints for ObjC yet. // Should there be some way for the runtime to specify what it can do in this regard? @@ -1231,7 +1362,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table ExecutionContext exe_ctx; - ThreadSP thread_sp = process->GetThreadList().GetSelectedThread(); + ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread(); if (!thread_sp) return false; @@ -1241,13 +1372,13 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table if (!ast) return false; - + Address function_address; - - StreamString errors; - + + DiagnosticManager diagnostics; + const uint32_t addr_size = process->GetAddressByteSize(); - + Error err; // Read the total number of classes from the hash table @@ -1281,12 +1412,15 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table } else { - errors.Clear(); - - if (!m_get_class_info_code->Install(errors, exe_ctx)) + diagnostics.Clear(); + + if (!m_get_class_info_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install implementation lookup: %s.", errors.GetData()); + { + log->Printf("Failed to install implementation lookup"); + diagnostics.Dump(log); + } m_get_class_info_code.reset(); } } @@ -1303,9 +1437,11 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table value.SetValueType (Value::eValueTypeScalar); value.SetCompilerType (clang_uint32_t_type); arguments.PushValue (value); + arguments.PushValue (value); get_class_info_function = m_get_class_info_code->MakeFunctionCaller(clang_uint32_t_type, arguments, + thread_sp, error); if (error.Fail()) @@ -1321,14 +1457,18 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table if (!get_class_info_function) { if (log) - log->Printf ("Failed to get implementation lookup function caller: %s.", errors.GetData()); + { + log->Printf("Failed to get implementation lookup function caller."); + diagnostics.Dump(log); + } + return false; } arguments = get_class_info_function->GetArgumentValues(); } - errors.Clear(); - + diagnostics.Clear(); + const uint32_t class_info_byte_size = addr_size + 4; const uint32_t class_infos_byte_size = num_classes * class_info_byte_size; lldb::addr_t class_infos_addr = process->AllocateMemory(class_infos_byte_size, @@ -1337,23 +1477,22 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table if (class_infos_addr == LLDB_INVALID_ADDRESS) return false; - - Mutex::Locker locker(m_get_class_info_args_mutex); - + + std::lock_guard guard(m_get_class_info_args_mutex); + // Fill in our function argument values arguments.GetValueAtIndex(0)->GetScalar() = hash_table.GetTableLoadAddress(); arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr; arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size; + arguments.GetValueAtIndex(3)->GetScalar() = (GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES) == nullptr ? 0 : 1); + bool success = false; - - errors.Clear(); - + + diagnostics.Clear(); + // Write our function arguments into the process so we can run our function - if (get_class_info_function->WriteFunctionArguments (exe_ctx, - m_get_class_info_args, - arguments, - errors)) + if (get_class_info_function->WriteFunctionArguments(exe_ctx, m_get_class_info_args, arguments, diagnostics)) { EvaluateExpressionOptions options; options.SetUnwindOnError(true); @@ -1365,18 +1504,15 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table Value return_value; return_value.SetValueType (Value::eValueTypeScalar); //return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type); - return_value.SetCompilerType (clang_uint32_t_type); + return_value.SetCompilerType(clang_uint32_t_type); return_value.GetScalar() = 0; - - errors.Clear(); - + + diagnostics.Clear(); + // Run the function - ExpressionResults results = get_class_info_function->ExecuteFunction (exe_ctx, - &m_get_class_info_args, - options, - errors, - return_value); - + ExpressionResults results = get_class_info_function->ExecuteFunction(exe_ctx, &m_get_class_info_args, options, + diagnostics, return_value); + if (results == eExpressionCompleted) { // The result is the number of ClassInfo structures that were filled in @@ -1401,15 +1537,21 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table else { if (log) - log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData()); + { + log->Printf("Error evaluating our find class name function."); + diagnostics.Dump(log); + } } } else { if (log) - log->Printf ("Error writing function arguments: \"%s\".", errors.GetData()); + { + log->Printf("Error writing function arguments."); + diagnostics.Dump(log); + } } - + // Deallocate the memory we allocated for the ClassInfo array process->DeallocateMemory(class_infos_addr); @@ -1475,7 +1617,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() ExecutionContext exe_ctx; - ThreadSP thread_sp = process->GetThreadList().GetSelectedThread(); + ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread(); if (!thread_sp) return DescriptorMapUpdateResult::Fail(); @@ -1485,13 +1627,13 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() if (!ast) return DescriptorMapUpdateResult::Fail(); - + Address function_address; - - StreamString errors; - + + DiagnosticManager diagnostics; + const uint32_t addr_size = process->GetAddressByteSize(); - + Error err; const lldb::addr_t objc_opt_ptr = GetSharedCacheReadOnlyAddress(); @@ -1530,16 +1672,19 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() } else { - errors.Clear(); - - if (!m_get_shared_cache_class_info_code->Install(errors, exe_ctx)) + diagnostics.Clear(); + + if (!m_get_shared_cache_class_info_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install implementation lookup: %s.", errors.GetData()); + { + log->Printf("Failed to install implementation lookup."); + diagnostics.Dump(log); + } m_get_shared_cache_class_info_code.reset(); } } - + if (!m_get_shared_cache_class_info_code.get()) return DescriptorMapUpdateResult::Fail(); @@ -1555,9 +1700,11 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() //value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type); value.SetCompilerType (clang_uint32_t_type); arguments.PushValue (value); + arguments.PushValue (value); get_shared_cache_class_info_function = m_get_shared_cache_class_info_code->MakeFunctionCaller(clang_uint32_t_type, arguments, + thread_sp, error); if (get_shared_cache_class_info_function == nullptr) @@ -1571,9 +1718,9 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() return DescriptorMapUpdateResult::Fail(); arguments = get_shared_cache_class_info_function->GetArgumentValues(); } - - errors.Clear(); - + + diagnostics.Clear(); + const uint32_t class_info_byte_size = addr_size + 4; const uint32_t class_infos_byte_size = num_classes * class_info_byte_size; lldb::addr_t class_infos_addr = process->AllocateMemory (class_infos_byte_size, @@ -1582,24 +1729,24 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() if (class_infos_addr == LLDB_INVALID_ADDRESS) return DescriptorMapUpdateResult::Fail(); - - Mutex::Locker locker(m_get_shared_cache_class_info_args_mutex); - + + std::lock_guard guard(m_get_shared_cache_class_info_args_mutex); + // Fill in our function argument values arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr; arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr; arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size; + arguments.GetValueAtIndex(3)->GetScalar() = (GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES) == nullptr ? 0 : 1); + bool success = false; bool any_found = false; - - errors.Clear(); - + + diagnostics.Clear(); + // Write our function arguments into the process so we can run our function - if (get_shared_cache_class_info_function->WriteFunctionArguments (exe_ctx, - m_get_shared_cache_class_info_args, - arguments, - errors)) + if (get_shared_cache_class_info_function->WriteFunctionArguments(exe_ctx, m_get_shared_cache_class_info_args, + arguments, diagnostics)) { EvaluateExpressionOptions options; options.SetUnwindOnError(true); @@ -1611,18 +1758,15 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() Value return_value; return_value.SetValueType (Value::eValueTypeScalar); //return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type); - return_value.SetCompilerType (clang_uint32_t_type); + return_value.SetCompilerType(clang_uint32_t_type); return_value.GetScalar() = 0; - - errors.Clear(); - + + diagnostics.Clear(); + // Run the function - ExpressionResults results = get_shared_cache_class_info_function->ExecuteFunction (exe_ctx, - &m_get_shared_cache_class_info_args, - options, - errors, - return_value); - + ExpressionResults results = get_shared_cache_class_info_function->ExecuteFunction( + exe_ctx, &m_get_shared_cache_class_info_args, options, diagnostics, return_value); + if (results == eExpressionCompleted) { // The result is the number of ClassInfo structures that were filled in @@ -1668,15 +1812,21 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() else { if (log) - log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData()); + { + log->Printf("Error evaluating our find class name function."); + diagnostics.Dump(log); + } } } else { if (log) - log->Printf ("Error writing function arguments: \"%s\".", errors.GetData()); + { + log->Printf("Error writing function arguments."); + diagnostics.Dump(log); + } } - + // Deallocate the memory we allocated for the ClassInfo array process->DeallocateMemory(class_infos_addr); @@ -1803,17 +1953,14 @@ AppleObjCRuntimeV2::WarnIfNoClassesCached () if (m_noclasses_warning_emitted) return; -#if defined(__APPLE__) if (m_process && m_process->GetTarget().GetPlatform() && - m_process->GetTarget().GetPlatform()->GetPluginName() == PlatformiOSSimulator::GetPluginNameStatic()) + m_process->GetTarget().GetPlatform()->GetPluginName().GetStringRef().endswith("-simulator")) { - // the iOS simulator does not have the objc_opt_ro class table - // so don't actually complain to the user + // Simulators do not have the objc_opt_ro class table so don't actually complain to the user m_noclasses_warning_emitted = true; return; } -#endif Debugger &debugger(GetProcess()->GetTarget().GetDebugger()); @@ -2025,6 +2172,74 @@ AppleObjCRuntimeV2::TaggedPointerVendorV2::CreateInstance (AppleObjCRuntimeV2& r if (error.Fail()) return new TaggedPointerVendorLegacy(runtime); + // try to detect the "extended tagged pointer" variables - if any are missing, use the non-extended vendor + do + { + auto objc_debug_taggedpointer_ext_mask = ExtractRuntimeGlobalSymbol(process, + ConstString("objc_debug_taggedpointer_ext_mask"), + objc_module_sp, + error); + if (error.Fail()) + break; + + auto objc_debug_taggedpointer_ext_slot_shift = ExtractRuntimeGlobalSymbol(process, + ConstString("objc_debug_taggedpointer_ext_slot_shift"), + objc_module_sp, + error, + true, + 4); + if (error.Fail()) + break; + + auto objc_debug_taggedpointer_ext_slot_mask = ExtractRuntimeGlobalSymbol(process, + ConstString("objc_debug_taggedpointer_ext_slot_mask"), + objc_module_sp, + error, + true, + 4); + if (error.Fail()) + break; + + auto objc_debug_taggedpointer_ext_classes = ExtractRuntimeGlobalSymbol(process, + ConstString("objc_debug_taggedpointer_ext_classes"), + objc_module_sp, + error, + false); + if (error.Fail()) + break; + + auto objc_debug_taggedpointer_ext_payload_lshift = ExtractRuntimeGlobalSymbol(process, + ConstString("objc_debug_taggedpointer_ext_payload_lshift"), + objc_module_sp, + error, + true, + 4); + if (error.Fail()) + break; + + auto objc_debug_taggedpointer_ext_payload_rshift = ExtractRuntimeGlobalSymbol(process, + ConstString("objc_debug_taggedpointer_ext_payload_rshift"), + objc_module_sp, + error, + true, + 4); + if (error.Fail()) + break; + + return new TaggedPointerVendorExtended(runtime, + objc_debug_taggedpointer_mask, + objc_debug_taggedpointer_ext_mask, + objc_debug_taggedpointer_slot_shift, + objc_debug_taggedpointer_ext_slot_shift, + objc_debug_taggedpointer_slot_mask, + objc_debug_taggedpointer_ext_slot_mask, + objc_debug_taggedpointer_payload_lshift, + objc_debug_taggedpointer_payload_rshift, + objc_debug_taggedpointer_ext_payload_lshift, + objc_debug_taggedpointer_ext_payload_rshift, + objc_debug_taggedpointer_classes, + objc_debug_taggedpointer_ext_classes); + } while(false); // we might want to have some rules to outlaw these values (e.g if the table's address is zero) @@ -2164,6 +2379,87 @@ AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor (lldb return ClassDescriptorSP(new ClassDescriptorV2Tagged(actual_class_descriptor_sp,data_payload)); } +AppleObjCRuntimeV2::TaggedPointerVendorExtended::TaggedPointerVendorExtended (AppleObjCRuntimeV2& runtime, + uint64_t objc_debug_taggedpointer_mask, + uint64_t objc_debug_taggedpointer_ext_mask, + uint32_t objc_debug_taggedpointer_slot_shift, + uint32_t objc_debug_taggedpointer_ext_slot_shift, + uint32_t objc_debug_taggedpointer_slot_mask, + uint32_t objc_debug_taggedpointer_ext_slot_mask, + uint32_t objc_debug_taggedpointer_payload_lshift, + uint32_t objc_debug_taggedpointer_payload_rshift, + uint32_t objc_debug_taggedpointer_ext_payload_lshift, + uint32_t objc_debug_taggedpointer_ext_payload_rshift, + lldb::addr_t objc_debug_taggedpointer_classes, + lldb::addr_t objc_debug_taggedpointer_ext_classes) : +TaggedPointerVendorRuntimeAssisted(runtime, + objc_debug_taggedpointer_mask, + objc_debug_taggedpointer_slot_shift, + objc_debug_taggedpointer_slot_mask, + objc_debug_taggedpointer_payload_lshift, + objc_debug_taggedpointer_payload_rshift, + objc_debug_taggedpointer_classes), +m_ext_cache(), +m_objc_debug_taggedpointer_ext_mask(objc_debug_taggedpointer_ext_mask), +m_objc_debug_taggedpointer_ext_slot_shift(objc_debug_taggedpointer_ext_slot_shift), +m_objc_debug_taggedpointer_ext_slot_mask(objc_debug_taggedpointer_ext_slot_mask), +m_objc_debug_taggedpointer_ext_payload_lshift(objc_debug_taggedpointer_ext_payload_lshift), +m_objc_debug_taggedpointer_ext_payload_rshift(objc_debug_taggedpointer_ext_payload_rshift), +m_objc_debug_taggedpointer_ext_classes(objc_debug_taggedpointer_ext_classes) +{ +} + +bool +AppleObjCRuntimeV2::TaggedPointerVendorExtended::IsPossibleExtendedTaggedPointer (lldb::addr_t ptr) +{ + if (!IsPossibleTaggedPointer(ptr)) + return false; + + if (m_objc_debug_taggedpointer_ext_mask == 0) + return false; + + return ((ptr & m_objc_debug_taggedpointer_ext_mask) == m_objc_debug_taggedpointer_ext_mask); +} + +ObjCLanguageRuntime::ClassDescriptorSP +AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor (lldb::addr_t ptr) +{ + ClassDescriptorSP actual_class_descriptor_sp; + uint64_t data_payload; + + if (!IsPossibleTaggedPointer(ptr)) + return ObjCLanguageRuntime::ClassDescriptorSP(); + + if (!IsPossibleExtendedTaggedPointer(ptr)) + return this->TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(ptr); + + uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_ext_slot_shift) & m_objc_debug_taggedpointer_ext_slot_mask; + + CacheIterator iterator = m_ext_cache.find(slot), + end = m_ext_cache.end(); + if (iterator != end) + { + actual_class_descriptor_sp = iterator->second; + } + else + { + Process* process(m_runtime.GetProcess()); + uintptr_t slot_ptr = slot*process->GetAddressByteSize()+m_objc_debug_taggedpointer_ext_classes; + Error error; + uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error); + if (error.Fail() || slot_data == 0 || slot_data == uintptr_t(LLDB_INVALID_ADDRESS)) + return nullptr; + actual_class_descriptor_sp = m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data); + if (!actual_class_descriptor_sp) + return ObjCLanguageRuntime::ClassDescriptorSP(); + m_ext_cache[slot] = actual_class_descriptor_sp; + } + + data_payload = (((uint64_t)ptr << m_objc_debug_taggedpointer_ext_payload_lshift) >> m_objc_debug_taggedpointer_ext_payload_rshift); + + return ClassDescriptorSP(new ClassDescriptorV2Tagged(actual_class_descriptor_sp,data_payload)); +} + AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache (AppleObjCRuntimeV2& runtime, uint64_t objc_debug_isa_class_mask, uint64_t objc_debug_isa_magic_mask, diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h index 96b47e8770f9..4b27c7400481 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h @@ -14,6 +14,7 @@ // C++ Includes #include #include +#include // Other libraries and framework includes // Project includes @@ -234,6 +235,45 @@ private: DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorRuntimeAssisted); }; + class TaggedPointerVendorExtended : public TaggedPointerVendorRuntimeAssisted + { + public: + ObjCLanguageRuntime::ClassDescriptorSP + GetClassDescriptor(lldb::addr_t ptr) override; + + protected: + TaggedPointerVendorExtended (AppleObjCRuntimeV2& runtime, + uint64_t objc_debug_taggedpointer_mask, + uint64_t objc_debug_taggedpointer_ext_mask, + uint32_t objc_debug_taggedpointer_slot_shift, + uint32_t objc_debug_taggedpointer_ext_slot_shift, + uint32_t objc_debug_taggedpointer_slot_mask, + uint32_t objc_debug_taggedpointer_ext_slot_mask, + uint32_t objc_debug_taggedpointer_payload_lshift, + uint32_t objc_debug_taggedpointer_payload_rshift, + uint32_t objc_debug_taggedpointer_ext_payload_lshift, + uint32_t objc_debug_taggedpointer_ext_payload_rshift, + lldb::addr_t objc_debug_taggedpointer_classes, + lldb::addr_t objc_debug_taggedpointer_ext_classes); + + bool + IsPossibleExtendedTaggedPointer (lldb::addr_t ptr); + + typedef std::map Cache; + typedef Cache::iterator CacheIterator; + Cache m_ext_cache; + uint64_t m_objc_debug_taggedpointer_ext_mask; + uint32_t m_objc_debug_taggedpointer_ext_slot_shift; + uint32_t m_objc_debug_taggedpointer_ext_slot_mask; + uint32_t m_objc_debug_taggedpointer_ext_payload_lshift; + uint32_t m_objc_debug_taggedpointer_ext_payload_rshift; + lldb::addr_t m_objc_debug_taggedpointer_ext_classes; + + friend class AppleObjCRuntimeV2::TaggedPointerVendorV2; + + DISALLOW_COPY_AND_ASSIGN(TaggedPointerVendorExtended); + }; + class TaggedPointerVendorLegacy : public TaggedPointerVendorV2 { public: @@ -314,11 +354,11 @@ private: std::unique_ptr m_get_class_info_code; lldb::addr_t m_get_class_info_args; - Mutex m_get_class_info_args_mutex; + std::mutex m_get_class_info_args_mutex; std::unique_ptr m_get_shared_cache_class_info_code; lldb::addr_t m_get_shared_cache_class_info_args; - Mutex m_get_shared_cache_class_info_args_mutex; + std::mutex m_get_shared_cache_class_info_args_mutex; std::unique_ptr m_decl_vendor_ap; lldb::addr_t m_isa_hash_table_ptr; diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp index d38a076ad5d7..5fedb80e29a6 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp @@ -22,19 +22,20 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/Value.h" -#include "lldb/Expression/UserExpression.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" +#include "lldb/Expression/UserExpression.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Host/FileSpec.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/ABI.h" +#include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ThreadPlanRunToAddress.h" #include "llvm/ADT/STLExtras.h" @@ -43,7 +44,6 @@ using namespace lldb; using namespace lldb_private; const char *AppleObjCTrampolineHandler::g_lookup_implementation_function_name = "__lldb_objc_find_implementation_for_selector"; -const char *AppleObjCTrampolineHandler::g_lookup_implementation_function_code = NULL; const char *AppleObjCTrampolineHandler::g_lookup_implementation_with_stret_function_code = " \n\ extern \"C\" \n\ { \n\ @@ -461,7 +461,7 @@ AppleObjCTrampolineHandler::AppleObjCVTables::InitializeVTableSymbols () Target &target = process_sp->GetTarget(); const ModuleList &target_modules = target.GetImages(); - Mutex::Locker modules_locker(target_modules.GetMutex()); + std::lock_guard guard(target_modules.GetMutex()); size_t num_modules = target_modules.GetSize(); if (!m_objc_module_sp) { @@ -657,6 +657,7 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler (const ProcessSP &process const ModuleSP &objc_module_sp) : m_process_wp (), m_objc_module_sp (objc_module_sp), + m_lookup_implementation_function_code(nullptr), m_impl_fn_addr (LLDB_INVALID_ADDRESS), m_impl_stret_fn_addr (LLDB_INVALID_ADDRESS), m_msg_forward_addr (LLDB_INVALID_ADDRESS) @@ -703,11 +704,11 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler (const ProcessSP &process // It there is no stret return lookup function, assume that it is the same as the straight lookup: m_impl_stret_fn_addr = m_impl_fn_addr; // Also we will use the version of the lookup code that doesn't rely on the stret version of the function. - g_lookup_implementation_function_code = g_lookup_implementation_no_stret_function_code; + m_lookup_implementation_function_code = g_lookup_implementation_no_stret_function_code; } else { - g_lookup_implementation_function_code = g_lookup_implementation_with_stret_function_code; + m_lookup_implementation_function_code = g_lookup_implementation_with_stret_function_code; } // Look up the addresses for the objc dispatch functions and cache them. For now I'm inspecting the symbol @@ -738,26 +739,28 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler (const ProcessSP &process } lldb::addr_t -AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &dispatch_values) +AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread, ValueList &dispatch_values) { - ExecutionContext exe_ctx (thread.shared_from_this()); - StreamString errors; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); + ThreadSP thread_sp(thread.shared_from_this()); + ExecutionContext exe_ctx (thread_sp); + DiagnosticManager diagnostics; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; FunctionCaller *impl_function_caller = nullptr; // Scope for mutex locker: { - Mutex::Locker locker(m_impl_function_mutex); - + std::lock_guard guard(m_impl_function_mutex); + // First stage is to make the ClangUtility to hold our injected function: if (!m_impl_code.get()) { - if (g_lookup_implementation_function_code != NULL) + if (m_lookup_implementation_function_code != NULL) { Error error; - m_impl_code.reset (exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage (g_lookup_implementation_function_code, + m_impl_code.reset (exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage (m_lookup_implementation_function_code, eLanguageTypeObjC, g_lookup_implementation_function_name, error)); @@ -768,11 +771,14 @@ AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &di m_impl_code.reset(); return args_addr; } - - if (!m_impl_code->Install(errors, exe_ctx)) + + if (!m_impl_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install implementation lookup: %s.", errors.GetData()); + { + log->Printf("Failed to install implementation lookup."); + diagnostics.Dump(log); + } m_impl_code.reset(); return args_addr; } @@ -781,10 +787,8 @@ AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &di { if (log) log->Printf("No method lookup implementation code."); - errors.Printf ("No method lookup implementation code found."); return LLDB_INVALID_ADDRESS; } - // Next make the runner function for our implementation utility function. ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext(); @@ -793,6 +797,7 @@ AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &di impl_function_caller = m_impl_code->MakeFunctionCaller(clang_void_ptr_type, dispatch_values, + thread_sp, error); if (error.Fail()) { @@ -806,20 +811,23 @@ AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &di impl_function_caller = m_impl_code->GetFunctionCaller(); } } - - errors.Clear(); - + + diagnostics.Clear(); + // Now write down the argument values for this particular call. This looks like it might be a race condition // if other threads were calling into here, but actually it isn't because we allocate a new args structure for // this call by passing args_addr = LLDB_INVALID_ADDRESS... - if (impl_function_caller->WriteFunctionArguments (exe_ctx, args_addr, dispatch_values, errors)) + if (!impl_function_caller->WriteFunctionArguments(exe_ctx, args_addr, dispatch_values, diagnostics)) { if (log) - log->Printf ("Error writing function arguments: \"%s\".", errors.GetData()); + { + log->Printf("Error writing function arguments."); + diagnostics.Dump(log); + } return args_addr; } - + return args_addr; } diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h index 42d3461ddfa5..c0d1944a7f2f 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h @@ -13,12 +13,12 @@ // C Includes // C++ Includes #include +#include #include // Other libraries and framework includes // Project includes #include "lldb/lldb-public.h" -#include "lldb/Host/Mutex.h" #include "lldb/Expression/UtilityFunction.h" namespace lldb_private @@ -65,7 +65,6 @@ public: private: static const char *g_lookup_implementation_function_name; - static const char *g_lookup_implementation_function_code; static const char *g_lookup_implementation_with_stret_function_code; static const char *g_lookup_implementation_no_stret_function_code; @@ -195,8 +194,9 @@ private: MsgsendMap m_msgSend_map; lldb::ProcessWP m_process_wp; lldb::ModuleSP m_objc_module_sp; + const char *m_lookup_implementation_function_code; std::unique_ptr m_impl_code; - Mutex m_impl_function_mutex; + std::mutex m_impl_function_mutex; lldb::addr_t m_impl_fn_addr; lldb::addr_t m_impl_stret_fn_addr; lldb::addr_t m_msg_forward_addr; diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp index 9308c7a668d2..d4adc094bc1b 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.cpp @@ -10,6 +10,7 @@ #include "AppleObjCTypeEncodingParser.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ClangUtil.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -155,7 +156,7 @@ AppleObjCTypeEncodingParser::BuildAggregate (clang::ASTContext &ast_ctx, lldb_ut } ClangASTContext::CompleteTagDeclarationDefinition(union_type); } - return ClangASTContext::GetQualType(union_type); + return ClangUtil::GetQualType(union_type); } clang::QualType @@ -171,7 +172,7 @@ AppleObjCTypeEncodingParser::BuildArray (clang::ASTContext &ast_ctx, lldb_utilit if (!lldb_ctx) return clang::QualType(); CompilerType array_type(lldb_ctx->CreateArrayType(CompilerType(&ast_ctx, element_type), size, false)); - return ClangASTContext::GetQualType(array_type); + return ClangUtil::GetQualType(array_type); } // the runtime can emit these in the form of @"SomeType", giving more specifics @@ -261,8 +262,8 @@ AppleObjCTypeEncodingParser::BuildObjCObjectPointerType (clang::ASTContext &ast_ if (!num_types) return ast_ctx.getObjCIdType(); #endif - - return ClangASTContext::GetQualType(ClangASTContext::GetTypeForDecl(decls[0]).GetPointerType()); + + return ClangUtil::GetQualType(ClangASTContext::GetTypeForDecl(decls[0]).GetPointerType()); } else { diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp index 285786a09dbb..a2101c927b4d 100644 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp +++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp @@ -13,16 +13,16 @@ // Project includes #include "AppleThreadPlanStepThroughObjCTrampoline.h" #include "AppleObjCTrampolineHandler.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Thread.h" +#include "lldb/Core/Log.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlanRunToAddress.h" #include "lldb/Target/ThreadPlanStepOut.h" -#include "lldb/Core/Log.h" - using namespace lldb; using namespace lldb_private; @@ -75,9 +75,9 @@ AppleThreadPlanStepThroughObjCTrampoline::InitializeFunctionCaller () { if (!m_func_sp) { - StreamString errors; + DiagnosticManager diagnostics; m_args_addr = m_trampoline_handler->SetupDispatchFunction(m_thread, m_input_values); - + if (m_args_addr == LLDB_INVALID_ADDRESS) { return false; @@ -89,12 +89,9 @@ AppleThreadPlanStepThroughObjCTrampoline::InitializeFunctionCaller () options.SetIgnoreBreakpoints(true); options.SetStopOthers(m_stop_others); m_thread.CalculateExecutionContext(exc_ctx); - m_func_sp = m_impl_function->GetThreadPlanToCallFunction (exc_ctx, - m_args_addr, - options, - errors); + m_func_sp = m_impl_function->GetThreadPlanToCallFunction(exc_ctx, m_args_addr, options, diagnostics); m_func_sp->SetOkayToDiscard(true); - m_thread.QueueThreadPlan (m_func_sp, false); + m_thread.QueueThreadPlan(m_func_sp, false); } return true; } diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/Makefile b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/Makefile deleted file mode 100644 index 485fe75b3f88..000000000000 --- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/LangRuntime/ObjC/AppleRT/Makefile ----*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../../.. -LIBRARYNAME := lldbPluginAppleObjCRuntime -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/Makefile b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/Makefile deleted file mode 100644 index eeb50ae3fcae..000000000000 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- Source/Plugins/LangRuntime/RenderScript/RenderScriptRuntime/Makefile ----*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../../.. -LIBRARYNAME := lldbPluginRenderScriptRuntime -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp index 8e5d31b66350..7441fd991511 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp @@ -13,50 +13,49 @@ // Project includes #include "RenderScriptRuntime.h" +#include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/Debugger.h" #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/Core/ValueObjectVariable.h" #include "lldb/DataFormatters/DumpValueObjectOptions.h" +#include "lldb/Expression/UserExpression.h" #include "lldb/Host/StringConvert.h" +#include "lldb/Interpreter/Args.h" +#include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandObjectMultiword.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/Options.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/Type.h" +#include "lldb/Symbol/VariableList.h" #include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.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" -#include "lldb/Interpreter/CommandReturnObject.h" -#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 { +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 -class empirical_type +template class empirical_type { public: // Ctor. Contents is invalid when constructed. - empirical_type() - : valid(false) - {} + empirical_type() : valid(false) {} // Return true and copy contents to out if valid, else return false. - bool get(type_t& out) const + bool + get(type_t &out) const { if (valid) out = data; @@ -64,32 +63,37 @@ public: } // Return a pointer to the contents or nullptr if it was not valid. - const type_t* get() const + const type_t * + get() const { return valid ? &data : nullptr; } // Assign data explicitly. - void set(const type_t in) + void + set(const type_t in) { data = in; valid = true; } // Mark contents as invalid. - void invalidate() + void + invalidate() { valid = false; } // Returns true if this type contains valid data. - bool isValid() const + bool + isValid() const { return valid; } // Assignment operator. - empirical_type& operator = (const type_t in) + empirical_type & + operator=(const type_t in) { set(in); return *this; @@ -97,7 +101,7 @@ public: // Dereference operator returns contents. // Warning: Will assert if not valid so use only when you know data is valid. - const type_t& operator * () const + const type_t &operator*() const { assert(valid); return data; @@ -108,6 +112,378 @@ protected: type_t data; }; +// ArgItem is used by the GetArgs() function when reading function arguments from the target. +struct ArgItem +{ + enum + { + ePointer, + eInt32, + eInt64, + eLong, + eBool + } type; + + uint64_t value; + + explicit operator uint64_t() const { return value; } +}; + +// Context structure to be passed into GetArgsXXX(), argument reading functions below. +struct GetArgsCtx +{ + RegisterContext *reg_ctx; + Process *process; +}; + +bool +GetArgsX86(const GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) +{ + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE); + + Error error; + + // get the current stack pointer + uint64_t sp = ctx.reg_ctx->GetSP(); + + for (size_t i = 0; i < num_args; ++i) + { + ArgItem &arg = arg_list[i]; + // advance up the stack by one argument + sp += sizeof(uint32_t); + // get the argument type size + size_t arg_size = sizeof(uint32_t); + // read the argument from memory + arg.value = 0; + Error error; + size_t read = ctx.process->ReadMemory(sp, &arg.value, sizeof(uint32_t), error); + if (read != arg_size || !error.Success()) + { + if (log) + log->Printf("%s - error reading argument: %" PRIu64 " '%s'", __FUNCTION__, uint64_t(i), + error.AsCString()); + return false; + } + } + return true; +} + +bool +GetArgsX86_64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) +{ + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE); + + // number of arguments passed in registers + static const uint32_t c_args_in_reg = 6; + // register passing order + static const std::array c_reg_names{{"rdi", "rsi", "rdx", "rcx", "r8", "r9"}}; + // argument type to size mapping + static const std::array arg_size{{ + 8, // ePointer, + 4, // eInt32, + 8, // eInt64, + 8, // eLong, + 4, // eBool, + }}; + + Error error; + + // get the current stack pointer + uint64_t sp = ctx.reg_ctx->GetSP(); + // step over the return address + sp += sizeof(uint64_t); + + // check the stack alignment was correct (16 byte aligned) + if ((sp & 0xf) != 0x0) + { + if (log) + log->Printf("%s - stack misaligned", __FUNCTION__); + return false; + } + + // find the start of arguments on the stack + uint64_t sp_offset = 0; + for (uint32_t i = c_args_in_reg; i < num_args; ++i) + { + sp_offset += arg_size[arg_list[i].type]; + } + // round up to multiple of 16 + sp_offset = (sp_offset + 0xf) & 0xf; + sp += sp_offset; + + for (size_t i = 0; i < num_args; ++i) + { + bool success = false; + ArgItem &arg = arg_list[i]; + // arguments passed in registers + if (i < c_args_in_reg) + { + const RegisterInfo *rArg = ctx.reg_ctx->GetRegisterInfoByName(c_reg_names[i]); + RegisterValue rVal; + if (ctx.reg_ctx->ReadRegister(rArg, rVal)) + arg.value = rVal.GetAsUInt64(0, &success); + } + // arguments passed on the stack + else + { + // get the argument type size + const size_t size = arg_size[arg_list[i].type]; + // read the argument from memory + arg.value = 0; + // note: due to little endian layout reading 4 or 8 bytes will give the correct value. + size_t read = ctx.process->ReadMemory(sp, &arg.value, size, error); + success = (error.Success() && read==size); + // advance past this argument + sp -= size; + } + // fail if we couldn't read this argument + if (!success) + { + if (log) + log->Printf("%s - error reading argument: %" PRIu64", reason: %s", + __FUNCTION__, uint64_t(i), error.AsCString("n/a")); + return false; + } + } + return true; +} + +bool +GetArgsArm(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) +{ + // number of arguments passed in registers + static const uint32_t c_args_in_reg = 4; + + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE); + + Error error; + + // get the current stack pointer + uint64_t sp = ctx.reg_ctx->GetSP(); + + for (size_t i = 0; i < num_args; ++i) + { + bool success = false; + ArgItem &arg = arg_list[i]; + // arguments passed in registers + if (i < c_args_in_reg) + { + const RegisterInfo *rArg = ctx.reg_ctx->GetRegisterInfoAtIndex(i); + RegisterValue rVal; + if (ctx.reg_ctx->ReadRegister(rArg, rVal)) + arg.value = rVal.GetAsUInt32(0, &success); + } + // arguments passed on the stack + else + { + // get the argument type size + const size_t arg_size = sizeof(uint32_t); + // clear all 64bits + arg.value = 0; + // read this argument from memory + size_t bytes_read = ctx.process->ReadMemory(sp, &arg.value, arg_size, error); + success = (error.Success() && bytes_read == arg_size); + // advance the stack pointer + sp += sizeof(uint32_t); + } + // fail if we couldn't read this argument + if (!success) + { + if (log) + log->Printf("%s - error reading argument: %" PRIu64", reason: %s", + __FUNCTION__, uint64_t(i), error.AsCString("n/a")); + return false; + } + } + return true; +} + +bool +GetArgsAarch64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) +{ + // number of arguments passed in registers + static const uint32_t c_args_in_reg = 8; + + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE); + + for (size_t i = 0; i < num_args; ++i) + { + bool success = false; + ArgItem &arg = arg_list[i]; + // arguments passed in registers + if (i < c_args_in_reg) + { + const RegisterInfo *rArg = ctx.reg_ctx->GetRegisterInfoAtIndex(i); + RegisterValue rVal; + if (ctx.reg_ctx->ReadRegister(rArg, rVal)) + arg.value = rVal.GetAsUInt64(0, &success); + } + // arguments passed on the stack + else + { + if (log) + log->Printf("%s - reading arguments spilled to stack not implemented", __FUNCTION__); + } + // fail if we couldn't read this argument + if (!success) + { + if (log) + log->Printf("%s - error reading argument: %" PRIu64, __FUNCTION__, + uint64_t(i)); + return false; + } + } + return true; +} + +bool +GetArgsMipsel(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) +{ + // number of arguments passed in registers + static const uint32_t c_args_in_reg = 4; + // register file offset to first argument + static const uint32_t c_reg_offset = 4; + + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE); + + Error error; + + // find offset to arguments on the stack (+16 to skip over a0-a3 shadow space) + uint64_t sp = ctx.reg_ctx->GetSP() + 16; + + for (size_t i = 0; i < num_args; ++i) + { + bool success = false; + ArgItem &arg = arg_list[i]; + // arguments passed in registers + if (i < c_args_in_reg) + { + const RegisterInfo *rArg = ctx.reg_ctx->GetRegisterInfoAtIndex(i + c_reg_offset); + RegisterValue rVal; + if (ctx.reg_ctx->ReadRegister(rArg, rVal)) + arg.value = rVal.GetAsUInt64(0, &success); + } + // arguments passed on the stack + else + { + const size_t arg_size = sizeof(uint32_t); + arg.value = 0; + size_t bytes_read = ctx.process->ReadMemory(sp, &arg.value, arg_size, error); + success = (error.Success() && bytes_read == arg_size); + // advance the stack pointer + sp += arg_size; + } + // fail if we couldn't read this argument + if (!success) + { + if (log) + log->Printf("%s - error reading argument: %" PRIu64", reason: %s", + __FUNCTION__, uint64_t(i), error.AsCString("n/a")); + return false; + } + } + return true; +} + +bool +GetArgsMips64el(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) +{ + // number of arguments passed in registers + static const uint32_t c_args_in_reg = 8; + // register file offset to first argument + static const uint32_t c_reg_offset = 4; + + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE); + + Error error; + + // get the current stack pointer + uint64_t sp = ctx.reg_ctx->GetSP(); + + for (size_t i = 0; i < num_args; ++i) + { + bool success = false; + ArgItem &arg = arg_list[i]; + // arguments passed in registers + if (i < c_args_in_reg) + { + const RegisterInfo *rArg = ctx.reg_ctx->GetRegisterInfoAtIndex(i + c_reg_offset); + RegisterValue rVal; + if (ctx.reg_ctx->ReadRegister(rArg, rVal)) + arg.value = rVal.GetAsUInt64(0, &success); + } + // arguments passed on the stack + else + { + // get the argument type size + const size_t arg_size = sizeof(uint64_t); + // clear all 64bits + arg.value = 0; + // read this argument from memory + size_t bytes_read = ctx.process->ReadMemory(sp, &arg.value, arg_size, error); + success = (error.Success() && bytes_read == arg_size); + // advance the stack pointer + sp += arg_size; + } + // fail if we couldn't read this argument + if (!success) + { + if (log) + log->Printf("%s - error reading argument: %" PRIu64", reason: %s", + __FUNCTION__, uint64_t(i), error.AsCString("n/a")); + return false; + } + } + return true; +} + +bool +GetArgs(ExecutionContext &context, ArgItem *arg_list, size_t num_args) +{ + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE); + + // verify that we have a target + if (!context.GetTargetPtr()) + { + if (log) + log->Printf("%s - invalid target", __FUNCTION__); + return false; + } + + GetArgsCtx ctx = {context.GetRegisterContext(), context.GetProcessPtr()}; + assert(ctx.reg_ctx && ctx.process); + + // dispatch based on architecture + switch (context.GetTargetPtr()->GetArchitecture().GetMachine()) + { + case llvm::Triple::ArchType::x86: + return GetArgsX86(ctx, arg_list, num_args); + + case llvm::Triple::ArchType::x86_64: + return GetArgsX86_64(ctx, arg_list, num_args); + + case llvm::Triple::ArchType::arm: + return GetArgsArm(ctx, arg_list, num_args); + + case llvm::Triple::ArchType::aarch64: + return GetArgsAarch64(ctx, arg_list, num_args); + + case llvm::Triple::ArchType::mipsel: + return GetArgsMipsel(ctx, arg_list, num_args); + + case llvm::Triple::ArchType::mips64el: + return GetArgsMips64el(ctx, arg_list, num_args); + + default: + // unsupported architecture + if (log) + { + log->Printf("%s - architecture not supported: '%s'", __FUNCTION__, + context.GetTargetRef().GetArchitecture().GetArchitectureName()); + } + return false; + } +} } // anonymous namespace // The ScriptDetails class collects data associated with a single script instance. @@ -193,21 +569,23 @@ struct RenderScriptRuntime::Element RS_TYPE_INVALID = 10000 }; - std::vector children; // Child Element fields for structs - empirical_type element_ptr; // Pointer to the RS Element of the Type - empirical_type type; // Type of each data pointer stored by the allocation - empirical_type type_kind; // Defines pixel type if Allocation is created from an image - empirical_type type_vec_size; // Vector size of each data point, e.g '4' for uchar4 - empirical_type field_count; // Number of Subelements - empirical_type datum_size; // Size of a single Element with padding - empirical_type padding; // Number of padding bytes - empirical_type 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 + std::vector children; // Child Element fields for structs + empirical_type element_ptr; // Pointer to the RS Element of the Type + empirical_type type; // Type of each data pointer stored by the allocation + empirical_type type_kind; // Defines pixel type if Allocation is created from an image + empirical_type type_vec_size; // Vector size of each data point, e.g '4' for uchar4 + empirical_type field_count; // Number of Subelements + empirical_type datum_size; // Size of a single Element with padding + empirical_type padding; // Number of padding bytes + empirical_type 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 + 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(); @@ -228,10 +606,10 @@ struct RenderScriptRuntime::AllocationDetails Dimension() { - dim_1 = 0; - dim_2 = 0; - dim_3 = 0; - cubeMap = 0; + dim_1 = 0; + dim_2 = 0; + dim_3 = 0; + cubeMap = 0; } }; @@ -245,52 +623,51 @@ struct RenderScriptRuntime::AllocationDetails // These offsets are 4 bytes in size, and the 0 offset signifies no more children. struct FileHeader { - uint8_t ident[4]; // ASCII 'RSAD' identifying the file - uint32_t dims[3]; // Dimensions - uint16_t hdr_size; // Header size in bytes, including all element headers + uint8_t ident[4]; // ASCII 'RSAD' identifying the file + uint32_t dims[3]; // Dimensions + uint16_t hdr_size; // Header size in bytes, including all element headers }; struct ElementHeader { - uint16_t type; // DataType enum - uint32_t kind; // DataKind enum - uint32_t element_size; // Size of a single element, including padding - uint16_t vector_size; // Vector width - uint32_t array_size; // Number of elements in array + uint16_t type; // DataType enum + uint32_t kind; // DataKind enum + uint32_t element_size; // Size of a single element, including padding + uint16_t vector_size; // Vector width + uint32_t array_size; // Number of elements in array }; // Monotonically increasing from 1 - static unsigned int ID; + static uint32_t ID; // Maps Allocation DataType enum and vector size to printable strings // using mapping from RenderScript numerical types summary documentation - static const char* RsDataTypeToString[][4]; + static const char *RsDataTypeToString[][4]; // Maps Allocation DataKind enum to printable strings - static const char* RsDataKindToString[]; + static const char *RsDataKindToString[]; // Maps allocation types to format sizes for printing. - static const unsigned int RSTypeToFormat[][3]; + static const uint32_t RSTypeToFormat[][3]; // Give each allocation an ID as a way // for commands to reference it. - const unsigned int id; + const uint32_t id; - RenderScriptRuntime::Element element; // Allocation Element type - empirical_type dimension; // Dimensions of the Allocation - empirical_type address; // Pointer to address of the RS Allocation - empirical_type data_ptr; // Pointer to the data held by the Allocation - empirical_type type_ptr; // Pointer to the RS Type of the Allocation - empirical_type context; // Pointer to the RS Context of the Allocation - empirical_type size; // Size of the allocation - empirical_type stride; // Stride between rows of the allocation + RenderScriptRuntime::Element element; // Allocation Element type + empirical_type dimension; // Dimensions of the Allocation + empirical_type address; // Pointer to address of the RS Allocation + empirical_type data_ptr; // Pointer to the data held by the Allocation + empirical_type type_ptr; // Pointer to the RS Type of the Allocation + empirical_type context; // Pointer to the RS Context of the Allocation + empirical_type size; // Size of the allocation + empirical_type stride; // Stride between rows of the allocation // Give each allocation an id, so we can reference it in user commands. - AllocationDetails(): id(ID++) - { - } + AllocationDetails() : id(ID++) {} - bool shouldRefresh() const + bool + shouldRefresh() const { bool valid_ptrs = data_ptr.isValid() && *data_ptr.get() != 0x0; valid_ptrs = valid_ptrs && type_ptr.isValid() && *type_ptr.get() != 0x0; @@ -305,24 +682,15 @@ RenderScriptRuntime::Element::GetFallbackStructName() return FallbackStructName; } -unsigned int RenderScriptRuntime::AllocationDetails::ID = 1; +uint32_t 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::RsDataKindToString[] = { + "User", + "Undefined", "Undefined", "Undefined", "Undefined", "Undefined", "Undefined", // Enum jumps from 0 to 7 + "L Pixel", "A Pixel", "LA Pixel", "RGB Pixel", + "RGBA Pixel", "Pixel Depth", "YUV Pixel"}; -const char* RenderScriptRuntime::AllocationDetails::RsDataTypeToString[][4] = -{ +const char *RenderScriptRuntime::AllocationDetails::RsDataTypeToString[][4] = { {"None", "None", "None", "None"}, {"half", "half2", "half3", "half4"}, {"float", "float2", "float3", "float4"}, @@ -356,38 +724,37 @@ const char* RenderScriptRuntime::AllocationDetails::RsDataTypeToString[][4] = {"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"} -}; + {"RS Font", "RS Font", "RS Font", "RS Font"}}; // Used as an index into the RSTypeToFormat array elements -enum TypeToFormatIndex { - eFormatSingle = 0, - eFormatVector, - eElementSize +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 +const uint32_t 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 + {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 9}, // RS_TYPE_MATRIX_3X3 + {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 4} // RS_TYPE_MATRIX_2X2 }; //------------------------------------------------------------------ @@ -400,7 +767,7 @@ RenderScriptRuntime::CreateInstance(Process *process, lldb::LanguageType languag if (language == eLanguageTypeExtRenderScript) return new RenderScriptRuntime(process); else - return NULL; + return nullptr; } // Callback with a module to search for matching symbols. @@ -408,10 +775,7 @@ RenderScriptRuntime::CreateInstance(Process *process, lldb::LanguageType languag // 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) +RSBreakpointResolver::SearchCallback(SearchFilter &filter, SymbolContext &context, Address *, bool) { ModuleSP module = context.module_sp; @@ -426,7 +790,7 @@ RSBreakpointResolver::SearchCallback(SearchFilter &filter, // If it's not found, it's likely debug info is unavailable - try to set a // breakpoint on .expand. - const Symbol* kernel_sym = module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode); + const Symbol *kernel_sym = module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode); if (!kernel_sym) { std::string kernel_name_expanded(m_kernel_name.AsCString()); @@ -447,7 +811,8 @@ RSBreakpointResolver::SearchCallback(SearchFilter &filter, void RenderScriptRuntime::Initialize() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), "RenderScript language support", CreateInstance, GetCommandObject); + PluginManager::RegisterPlugin(GetPluginNameStatic(), "RenderScript language support", CreateInstance, + GetCommandObject); } void @@ -493,7 +858,6 @@ RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp) { return eModuleKindImpl; } - } return eModuleKindIgnored; } @@ -505,15 +869,15 @@ RenderScriptRuntime::IsRenderScriptModule(const lldb::ModuleSP &module_sp) } void -RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list ) +RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list) { - Mutex::Locker locker (module_list.GetMutex ()); + std::lock_guard guard(module_list.GetMutex()); size_t num_modules = module_list.GetSize(); for (size_t i = 0; i < num_modules; i++) { - auto mod = module_list.GetModuleAtIndex (i); - if (IsRenderScriptModule (mod)) + auto mod = module_list.GetModuleAtIndex(i); + if (IsRenderScriptModule(mod)) { LoadModule(mod); } @@ -550,8 +914,7 @@ RenderScriptRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::Dynam } TypeAndOrName -RenderScriptRuntime::FixUpDynamicType (const TypeAndOrName& type_and_or_name, - ValueObject& static_value) +RenderScriptRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value) { return type_and_or_name; } @@ -569,86 +932,71 @@ RenderScriptRuntime::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bo return resolver_sp; } -const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] = -{ - //rsdScript +const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] = { + // rsdScript { - "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 + "rsdScriptInit", + "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhjj", + "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhmj", + 0, + RenderScriptRuntime::eModuleKindDriver, + &lldb_private::RenderScriptRuntime::CaptureScriptInit }, { - "rsdScriptInvokeForEach", // name - "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvjPK12RsScriptCall", // symbol name 32bit - "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvmPK12RsScriptCall", // symbol name 64bit - 0, // version - RenderScriptRuntime::eModuleKindDriver, // type - nullptr // handler + "rsdScriptInvokeForEachMulti", + "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall", + "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEmPS6_PKvmPK12RsScriptCall", + 0, + RenderScriptRuntime::eModuleKindDriver, + &lldb_private::RenderScriptRuntime::CaptureScriptInvokeForEachMulti }, { - "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 + "rsdScriptSetGlobalVar", + "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvj", + "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvm", + 0, + RenderScriptRuntime::eModuleKindDriver, + &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar }, - //rsdAllocation + // rsdAllocation { - "rsdAllocationInit", // name - "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 32bit - "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 64bit - 0, // version - RenderScriptRuntime::eModuleKindDriver, // type - &lldb_private::RenderScriptRuntime::CaptureAllocationInit1 // handler + "rsdAllocationInit", + "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", + "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", + 0, + RenderScriptRuntime::eModuleKindDriver, + &lldb_private::RenderScriptRuntime::CaptureAllocationInit }, { - "rsdAllocationRead2D", //name - "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvjj", // symbol name 32bit - "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvmm", // symbol name 64bit - 0, // version - RenderScriptRuntime::eModuleKindDriver, // type - nullptr // handler + "rsdAllocationRead2D", + "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvjj", + "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvmm", + 0, + RenderScriptRuntime::eModuleKindDriver, + nullptr }, { - "rsdAllocationDestroy", // name - "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_10AllocationE", // symbol name 32bit - "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_10AllocationE", // symbol name 64bit - 0, // version - RenderScriptRuntime::eModuleKindDriver, // type - &lldb_private::RenderScriptRuntime::CaptureAllocationDestroy // handler + "rsdAllocationDestroy", + "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_10AllocationE", + "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_10AllocationE", + 0, + RenderScriptRuntime::eModuleKindDriver, + &lldb_private::RenderScriptRuntime::CaptureAllocationDestroy }, }; -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) +RenderScriptRuntime::HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id, + lldb::user_id_t break_loc_id) { - RuntimeHook* hook_info = (RuntimeHook*)baton; + RuntimeHook *hook_info = (RuntimeHook *)baton; ExecutionContext context(ctx->exe_ctx_ref); - RenderScriptRuntime *lang_rt = (RenderScriptRuntime *)context.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); + RenderScriptRuntime *lang_rt = + (RenderScriptRuntime *)context.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); lang_rt->HookCallback(hook_info, context); @@ -656,12 +1004,12 @@ RenderScriptRuntime::HookCallback(void *baton, StoppointCallbackContext *ctx, ll } void -RenderScriptRuntime::HookCallback(RuntimeHook* hook_info, ExecutionContext& context) +RenderScriptRuntime::HookCallback(RuntimeHook *hook_info, ExecutionContext &context) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (log) - log->Printf ("RenderScriptRuntime::HookCallback - '%s' .", hook_info->defn->name); + log->Printf("%s - '%s'", __FUNCTION__, hook_info->defn->name); if (hook_info->defn->grabber) { @@ -669,435 +1017,320 @@ RenderScriptRuntime::HookCallback(RuntimeHook* hook_info, ExecutionContext& cont } } -bool -RenderScriptRuntime::GetArgSimple(ExecutionContext &context, uint32_t arg, uint64_t *data) -{ - // 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; - +void +RenderScriptRuntime::CaptureScriptInvokeForEachMulti(RuntimeHook* hook_info, + ExecutionContext& context) +{ 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()) + enum + { + eRsContext = 0, + eRsScript, + eRsSlot, + eRsAIns, + eRsInLen, + eRsAOut, + eRsUsr, + eRsUsrLen, + eRsSc, + }; + + std::array args{{ + ArgItem{ArgItem::ePointer, 0}, // const Context *rsc + ArgItem{ArgItem::ePointer, 0}, // Script *s + ArgItem{ArgItem::eInt32, 0}, // uint32_t slot + ArgItem{ArgItem::ePointer, 0}, // const Allocation **aIns + ArgItem{ArgItem::eInt32, 0}, // size_t inLen + ArgItem{ArgItem::ePointer, 0}, // Allocation *aout + ArgItem{ArgItem::ePointer, 0}, // const void *usr + ArgItem{ArgItem::eInt32, 0}, // size_t usrLen + ArgItem{ArgItem::ePointer, 0}, // const RsScriptCall *sc + }}; + + bool success = GetArgs(context, &args[0], args.size()); + if (!success) { if (log) - log->Printf("RenderScriptRuntime::GetArgSimple - Invalid target"); - - return false; + log->Printf("%s - Error while reading the function parameters", __FUNCTION__); + return; } - switch (context.GetTargetPtr()->GetArchitecture().GetMachine()) + const uint32_t target_ptr_size = m_process->GetAddressByteSize(); + Error error; + std::vector allocs; + + // traverse allocation list + for (uint64_t i = 0; i < uint64_t(args[eRsInLen]); ++i) { - case llvm::Triple::ArchType::x86: - { - uint64_t sp = reg_ctx->GetSP(); - uint32_t offset = (1 + arg) * sizeof(uint32_t); - uint32_t result = 0; - process->ReadMemory(sp + offset, &result, sizeof(uint32_t), error); - if (error.Fail()) - { - if (log) - log->Printf("RenderScriptRuntime::GetArgSimple - error reading X86 stack: %s.", error.AsCString()); - } - else - { - *data = result; - success = true; - } - break; - } - case llvm::Triple::ArchType::x86_64: + // calculate offest to allocation pointer + const addr_t addr = addr_t(args[eRsAIns]) + i * target_ptr_size; + + // Note: due to little endian layout, reading 32bits or 64bits into res64 will + // give the correct results. + + uint64_t res64 = 0; + size_t read = m_process->ReadMemory(addr, &res64, target_ptr_size, error); + if (read != target_ptr_size || !error.Success()) { - // 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; - 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; + if (log) + log->Printf("%s - Error while reading allocation list argument %" PRIu64, __FUNCTION__, i); } - case llvm::Triple::ArchType::arm: + else { - // arm 32 bit - // first 4 arguments are passed via registers - 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); - uint32_t value = 0; - size_t bytes_read = process->ReadMemory(sp + offset, &value, sizeof(value), error); - if (error.Fail() || bytes_read != sizeof(value)) - { - if (log) - log->Printf("RenderScriptRuntime::GetArgSimple - error reading ARM stack: %s.", error.AsCString()); - } - else - { - *data = value; - success = true; - } - } - break; + allocs.push_back(res64); } - case llvm::Triple::ArchType::aarch64: + } + + // if there is an output allocation track it + if (uint64_t aOut = uint64_t(args[eRsAOut])) + { + allocs.push_back(aOut); + } + + // for all allocations we have found + for (const uint64_t alloc_addr : allocs) + { + AllocationDetails* alloc = LookUpAllocation(alloc_addr, true); + if (alloc) { - // arm 64 bit - // first 8 arguments are in the registers - if (arg < 8) + // save the allocation address + if (alloc->address.isValid()) { - 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); - } + // check the allocation address we already have matches + assert(*alloc->address.get() == alloc_addr); } 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 - // first 4 arguments are passed in 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); - } - } - // arguments > 4 are read from the stack - else - { - uint64_t sp = reg_ctx->GetSP(); - uint32_t offset = arg * sizeof(uint32_t); - uint32_t value = 0; - size_t bytes_read = process->ReadMemory(sp + offset, &value, sizeof(value), error); - if (error.Fail() || bytes_read != sizeof(value)) - { - if (log) - log->Printf("RenderScriptRuntime::GetArgSimple - error reading Mips stack: %s.", error.AsCString()); - } - else - { - *data = value; - 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); - } + alloc->address = alloc_addr; } - // arguments > 8 are read from the stack - else + + // save the context + if (log) { - uint64_t sp = reg_ctx->GetSP(); - uint32_t offset = (arg - 8) * sizeof(uint64_t); - uint64_t value = 0; - size_t bytes_read = process->ReadMemory(sp + offset, &value, sizeof(value), error); - if (error.Fail() || bytes_read != sizeof(value)) - { - if (log) - log->Printf("RenderScriptRuntime::GetArgSimple - Mips64 - Error reading Mips64 stack: %s.", error.AsCString()); - } - else - { - *data = value; - success = true; - } + if (alloc->context.isValid() && *alloc->context.get() != addr_t(args[eRsContext])) + log->Printf("%s - Allocation used by multiple contexts", __FUNCTION__); } - break; - } - default: - { - // invalid architecture - if (log) - log->Printf("RenderScriptRuntime::GetArgSimple - Architecture not supported"); + alloc->context = addr_t(args[eRsContext]); } } - if (!success) + // make sure we track this script object + if (lldb_private::RenderScriptRuntime::ScriptDetails *script = LookUpScript(addr_t(args[eRsScript]), true)) { if (log) - log->Printf("RenderScriptRuntime::GetArgSimple - failed to get argument at index %" PRIu32, arg); + { + if (script->context.isValid() && *script->context.get() != addr_t(args[eRsContext])) + log->Printf("%s - Script used by multiple contexts", __FUNCTION__); + } + script->context = addr_t(args[eRsContext]); } - return success; } void -RenderScriptRuntime::CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context) +RenderScriptRuntime::CaptureSetGlobalVar(RuntimeHook *hook_info, ExecutionContext &context) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); - - //Context, Script, int, data, length + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); - 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; + enum + { + eRsContext, + eRsScript, + eRsId, + eRsData, + eRsLength, + }; - 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); + std::array args{{ + ArgItem{ArgItem::ePointer, 0}, // eRsContext + ArgItem{ArgItem::ePointer, 0}, // eRsScript + ArgItem{ArgItem::eInt32, 0}, // eRsId + ArgItem{ArgItem::ePointer, 0}, // eRsData + ArgItem{ArgItem::eInt32, 0}, // eRsLength + }}; + bool success = GetArgs(context, &args[0], args.size()); if (!success) { if (log) - log->Printf("RenderScriptRuntime::CaptureSetGlobalVar1 - Error while reading the function parameters"); + log->Printf("%s - error reading the function parameters.", __FUNCTION__); return; } if (log) { - log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 ":%" PRIu64 "bytes.", - rs_context_u64, rs_script_u64, rs_id_u64, rs_data_u64, rs_length_u64); + log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 ":%" PRIu64 "bytes.", __FUNCTION__, + uint64_t(args[eRsContext]), uint64_t(args[eRsScript]), uint64_t(args[eRsId]), + uint64_t(args[eRsData]), uint64_t(args[eRsLength])); - addr_t script_addr = (addr_t)rs_script_u64; - if (m_scriptMappings.find( script_addr ) != m_scriptMappings.end()) + addr_t script_addr = addr_t(args[eRsScript]); + if (m_scriptMappings.find(script_addr) != m_scriptMappings.end()) { auto rsm = m_scriptMappings[script_addr]; - if (rs_id_u64 < rsm->m_globals.size()) + if (uint64_t(args[eRsId]) < rsm->m_globals.size()) { - 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()); + auto rsg = rsm->m_globals[uint64_t(args[eRsId])]; + log->Printf("%s - Setting of '%s' within '%s' inferred", __FUNCTION__, rsg.m_name.AsCString(), + rsm->m_module->GetFileSpec().GetFilename().AsCString()); } } } } void -RenderScriptRuntime::CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context) +RenderScriptRuntime::CaptureAllocationInit(RuntimeHook *hook_info, ExecutionContext &context) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); - //Context, Alloc, bool + enum + { + eRsContext, + eRsAlloc, + eRsForceZero + }; - uint64_t rs_context_u64 = 0U; - uint64_t rs_alloc_u64 = 0U; - uint64_t rs_forceZero_u64 = 0U; + std::array args{{ + ArgItem{ArgItem::ePointer, 0}, // eRsContext + ArgItem{ArgItem::ePointer, 0}, // eRsAlloc + ArgItem{ArgItem::eBool, 0}, // eRsForceZero + }}; - bool success = - GetArgSimple(context, 0, &rs_context_u64) && - GetArgSimple(context, 1, &rs_alloc_u64) && - GetArgSimple(context, 2, &rs_forceZero_u64); + bool success = GetArgs(context, &args[0], args.size()); if (!success) // error case { if (log) - log->Printf("RenderScriptRuntime::CaptureAllocationInit1 - Error while reading the function parameters"); + log->Printf("%s - error while reading the function parameters", __FUNCTION__); return; // abort } if (log) - log->Printf ("RenderScriptRuntime::CaptureAllocationInit1 - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .", - rs_context_u64, rs_alloc_u64, rs_forceZero_u64); + log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .", __FUNCTION__, uint64_t(args[eRsContext]), + uint64_t(args[eRsAlloc]), uint64_t(args[eRsForceZero])); - AllocationDetails* alloc = LookUpAllocation(rs_alloc_u64, true); + AllocationDetails *alloc = LookUpAllocation(uint64_t(args[eRsAlloc]), true); if (alloc) - alloc->context = rs_context_u64; + alloc->context = uint64_t(args[eRsContext]); } void -RenderScriptRuntime::CaptureAllocationDestroy(RuntimeHook* hook_info, ExecutionContext& context) +RenderScriptRuntime::CaptureAllocationDestroy(RuntimeHook *hook_info, ExecutionContext &context) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); - // Context, Alloc - uint64_t rs_context_u64 = 0U; - uint64_t rs_alloc_u64 = 0U; + enum + { + eRsContext, + eRsAlloc, + }; - bool success = GetArgSimple(context, 0, &rs_context_u64) && GetArgSimple(context, 1, &rs_alloc_u64); - if (!success) // error case + std::array args{{ + ArgItem{ArgItem::ePointer, 0}, // eRsContext + ArgItem{ArgItem::ePointer, 0}, // eRsAlloc + }}; + + bool success = GetArgs(context, &args[0], args.size()); + if (!success) { if (log) - log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - Error while reading the function parameters"); - return; // abort + log->Printf("%s - error while reading the function parameters.", __FUNCTION__); + return; } if (log) - log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - 0x%" PRIx64 ", 0x%" PRIx64 ".", - rs_context_u64, rs_alloc_u64); + log->Printf("%s - 0x%" PRIx64 ", 0x%" PRIx64 ".", __FUNCTION__, uint64_t(args[eRsContext]), + uint64_t(args[eRsAlloc])); 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) + auto &allocation_ap = *iter; // get the unique pointer + if (allocation_ap->address.isValid() && *allocation_ap->address.get() == addr_t(args[eRsAlloc])) { m_allocations.erase(iter); if (log) - log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - Deleted allocation entry"); + log->Printf("%s - deleted allocation entry.", __FUNCTION__); return; } } if (log) - log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - Couldn't find destroyed allocation"); + log->Printf("%s - couldn't find destroyed allocation.", __FUNCTION__); } void -RenderScriptRuntime::CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext& context) +RenderScriptRuntime::CaptureScriptInit(RuntimeHook *hook_info, ExecutionContext &context) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); - //Context, Script, resname Str, cachedir Str Error error; - Process* process = context.GetProcessPtr(); - - 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; + Process *process = context.GetProcessPtr(); - // 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); + enum + { + eRsContext, + eRsScript, + eRsResNamePtr, + eRsCachedDirPtr + }; + std::array args{{ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0}, + ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0}}}; + bool success = GetArgs(context, &args[0], args.size()); if (!success) { if (log) - log->Printf("RenderScriptRuntime::CaptureScriptInit1 - Error while reading the function parameters"); + log->Printf("%s - error while reading the function parameters.", __FUNCTION__); return; } - process->ReadCStringFromMemory((lldb::addr_t)rs_resnameptr_u64, resname, error); + std::string resname; + process->ReadCStringFromMemory(addr_t(args[eRsResNamePtr]), resname, error); if (error.Fail()) { if (log) - log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading resname: %s.", error.AsCString()); - + log->Printf("%s - error reading resname: %s.", __FUNCTION__, error.AsCString()); } - process->ReadCStringFromMemory((lldb::addr_t)rs_cachedirptr_u64, cachedir, error); + std::string cachedir; + process->ReadCStringFromMemory(addr_t(args[eRsCachedDirPtr]), cachedir, error); if (error.Fail()) { if (log) - log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading cachedir: %s.", error.AsCString()); + log->Printf("%s - error reading cachedir: %s.", __FUNCTION__, error.AsCString()); } if (log) - log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .", - rs_context_u64, rs_script_u64, resname.c_str(), cachedir.c_str()); + log->Printf("%s - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .", __FUNCTION__, uint64_t(args[eRsContext]), + uint64_t(args[eRsScript]), resname.c_str(), cachedir.c_str()); if (resname.size() > 0) { StreamString strm; strm.Printf("librs.%s.so", resname.c_str()); - ScriptDetails* script = LookUpScript(rs_script_u64, true); + ScriptDetails *script = LookUpScript(addr_t(args[eRsScript]), true); if (script) { script->type = ScriptDetails::eScriptC; script->cacheDir = cachedir; script->resName = resname; script->scriptDyLib = strm.GetData(); - script->context = addr_t(rs_context_u64); + script->context = addr_t(args[eRsContext]); } if (log) - log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - '%s' tagged with context 0x%" PRIx64 " and script 0x%" PRIx64 ".", - strm.GetData(), rs_context_u64, rs_script_u64); + log->Printf("%s - '%s' tagged with context 0x%" PRIx64 " and script 0x%" PRIx64 ".", __FUNCTION__, + strm.GetData(), uint64_t(args[eRsContext]), uint64_t(args[eRsScript])); } else if (log) { - log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - resource name invalid, Script not tagged"); + log->Printf("%s - resource name invalid, Script not tagged.", __FUNCTION__); } } void RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!module) { @@ -1107,17 +1340,15 @@ RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind) 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 (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, Mips supported currently."); - + log->Printf("%s - unable to hook runtime functions.", __FUNCTION__); return; } @@ -1125,17 +1356,21 @@ RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind) for (size_t idx = 0; idx < s_runtimeHookCount; idx++) { - const HookDefn* hook_defn = &s_runtimeHookDefns[idx]; - if (hook_defn->kind != kind) { + const HookDefn *hook_defn = &s_runtimeHookDefns[idx]; + if (hook_defn->kind != kind) + { continue; } - const char* symbol_name = (archByteSize == 4) ? hook_defn->symbol_name_m32 : hook_defn->symbol_name_m64; + 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); + if (!sym) + { + if (log) + { + log->Printf("%s - symbol '%s' related to the function %s not found", + __FUNCTION__, symbol_name, hook_defn->name); } continue; } @@ -1144,14 +1379,15 @@ RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind) if (addr == LLDB_INVALID_ADDRESS) { if (log) - log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to resolve the address of hook function '%s' with symbol '%s'.", - hook_defn->name, symbol_name); + log->Printf("%s - unable to resolve the address of hook function '%s' with symbol '%s'.", + __FUNCTION__, hook_defn->name, symbol_name); continue; } else { if (log) - log->Printf("RenderScriptRuntime::LoadRuntimeHooks - Function %s, address resolved at 0x%" PRIx64, hook_defn->name, addr); + log->Printf("%s - function %s, address resolved at 0x%" PRIx64, + __FUNCTION__, hook_defn->name, addr); } RuntimeHookSP hook(new RuntimeHook()); @@ -1162,8 +1398,9 @@ RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind) m_runtimeHooks[addr] = hook; if (log) { - log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Successfully hooked '%s' in '%s' version %" PRIu64 " at 0x%" PRIx64 ".", - hook_defn->name, module->GetFileSpec().GetFilename().AsCString(), (uint64_t)hook_defn->version, (uint64_t)addr); + log->Printf("%s - successfully hooked '%s' in '%s' version %" PRIu64 " at 0x%" PRIx64 ".", + __FUNCTION__, hook_defn->name, module->GetFileSpec().GetFilename().AsCString(), + (uint64_t)hook_defn->version, (uint64_t)addr); } } } @@ -1174,14 +1411,14 @@ RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp) if (!rsmodule_sp) return; - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); const ModuleSP module = rsmodule_sp->m_module; - const FileSpec& file = module->GetPlatformFileSpec(); + const FileSpec &file = module->GetPlatformFileSpec(); // 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) + for (const auto &rs_script : m_scripts) { // Extract the expected .so file path for this script. std::string dylib; @@ -1204,8 +1441,8 @@ RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp) 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()); + log->Printf("%s - script %" PRIx64 " wants reassigned to new rsmodule '%s'.", __FUNCTION__, + (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); } } // We don't have a script mapping for the current script. @@ -1219,8 +1456,8 @@ RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp) // 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()); + log->Printf("%s - script %" PRIx64 " associated with rsmodule '%s'.", __FUNCTION__, + (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); } } } @@ -1229,21 +1466,23 @@ RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp) // 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) +RenderScriptRuntime::EvalRSExpression(const char *expression, StackFrame *frame_ptr, uint64_t *result) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (log) - log->Printf("RenderScriptRuntime::EvalRSExpression(%s)", expression); + log->Printf("%s(%s)", __FUNCTION__, expression); ValueObjectSP expr_result; + EvaluateExpressionOptions options; + options.SetLanguage(lldb::eLanguageTypeC_plus_plus); // Perform the actual expression evaluation - GetProcess()->GetTarget().EvaluateExpression(expression, frame_ptr, expr_result); + GetProcess()->GetTarget().EvaluateExpression(expression, frame_ptr, expr_result, options); if (!expr_result) { - if (log) - log->Printf("RenderScriptRuntime::EvalRSExpression - Error: Couldn't evaluate expression"); - return false; + if (log) + log->Printf("%s: couldn't evaluate expression.", __FUNCTION__); + return false; } // The result of the expression is invalid @@ -1253,159 +1492,104 @@ RenderScriptRuntime::EvalRSExpression(const char* expression, StackFrame* frame_ if (err.GetError() == UserExpression::kNoResult) // Expression returned void, so this is actually a success { if (log) - log->Printf("RenderScriptRuntime::EvalRSExpression - Expression returned void"); + log->Printf("%s - expression returned void.", __FUNCTION__); result = nullptr; return true; } if (log) - log->Printf("RenderScriptRuntime::EvalRSExpression - Error evaluating expression result: %s", err.AsCString()); + log->Printf("%s - error evaluating expression result: %s", __FUNCTION__, + err.AsCString()); return false; } bool success = false; - *result = expr_result->GetValueAsUnsigned(0, &success); // We only read the result as an unsigned int. + *result = expr_result->GetValueAsUnsigned(0, &success); // We only read the result as an uint32_t. if (!success) { - if (log) - log->Printf("RenderScriptRuntime::EvalRSExpression - Error: Couldn't convert expression result to unsigned int"); - return false; + if (log) + log->Printf("%s - couldn't convert expression result to uint32_t", __FUNCTION__); + return false; } return true; } -namespace // anonymous +namespace { - // max length of an expanded expression - const int jit_max_expr_size = 768; +// Used to index expression format strings +enum ExpressionStrings +{ + eExprGetOffsetPtr = 0, + eExprAllocGetType, + eExprTypeDimX, + eExprTypeDimY, + eExprTypeDimZ, + eExprTypeElemPtr, + eExprElementType, + eExprElementKind, + eExprElementVec, + eExprElementFieldCount, + eExprSubelementsId, + eExprSubelementsName, + eExprSubelementsArrSize, + + _eExprLast // keep at the end, implicit size of the array runtimeExpressions +}; +// max length of an expanded expression +const int jit_max_expr_size = 512; + +// Retrieve the string to JIT for the given expression +const char* +JITTemplate(ExpressionStrings e) +{ // Format strings containing the expressions we may need to evaluate. - const char runtimeExpressions[][256] = - { + static std::array runtimeExpressions = {{ // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap) - "(int*)_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace(0x%lx, %u, %u, %u, 0, 0)", + "(int*)_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace" + "(0x%" PRIx64 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", 0, 0)", // Type* rsaAllocationGetType(Context*, Allocation*) - "(void*)rsaAllocationGetType(0x%lx, 0x%lx)", + "(void*)rsaAllocationGetType(0x%" PRIx64 ", 0x%" PRIx64 ")", // 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 + "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 6); data[0]", // X dim + "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 6); data[1]", // Y dim + "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 6); data[2]", // Z dim + "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", 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]; + "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 5); data[0]", // Type + "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 5); data[1]", // Kind + "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", data, 5); data[3]", // Vector Size + "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%" PRIx64 ", 0x%" PRIx64 ", 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 + // Element* of field + "void* ids[%" PRIu32 "]; const char* names[%" PRIu32 "]; size_t arr_size[%" PRIu32 "];" + "(void*)rsaElementGetSubElements(0x%" PRIx64 ", 0x%" PRIx64 ", ids, names, arr_size, %" PRIu32 "); ids[%" PRIu32 "]", + + // Name of field + "void* ids[%" PRIu32 "]; const char* names[%" PRIu32 "]; size_t arr_size[%" PRIu32 "];" + "(void*)rsaElementGetSubElements(0x%" PRIx64 ", 0x%" PRIx64 ", ids, names, arr_size, %" PRIu32 "); names[%" PRIu32 "]", + + // Array size of field + "void* ids[%" PRIu32 "]; const char* names[%" PRIu32 "]; size_t arr_size[%" PRIu32 "];" + "(void*)rsaElementGetSubElements(0x%" PRIx64 ", 0x%" PRIx64 ", ids, names, arr_size, %" PRIu32 "); arr_size[%" PRIu32 "]" + }}; + + return runtimeExpressions[e]; } +} // end of the anonymous namespace // JITs the RS runtime for the internal data pointer of an allocation. @@ -1413,32 +1597,32 @@ RenderScriptRuntime::JITTemplate(ExpressionStrings e) // 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) +RenderScriptRuntime::JITDataPointer(AllocationDetails *allocation, StackFrame *frame_ptr, uint32_t x, + uint32_t y, uint32_t z) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!allocation->address.isValid()) { if (log) - log->Printf("RenderScriptRuntime::JITDataPointer - Failed to find allocation details"); + log->Printf("%s - failed to find allocation details.", __FUNCTION__); return false; } - const char* expr_cstr = JITTemplate(eExprGetOffsetPtr); + 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()"); + log->Printf("%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (chars_written >= jit_max_expr_size) { if (log) - log->Printf("RenderScriptRuntime::JITDataPointer - Expression too long"); + log->Printf("%s - expression too long.", __FUNCTION__); return false; } @@ -1456,31 +1640,32 @@ RenderScriptRuntime::JITDataPointer(AllocationDetails* allocation, StackFrame* f // 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) +RenderScriptRuntime::JITTypePointer(AllocationDetails *allocation, StackFrame *frame_ptr) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!allocation->address.isValid() || !allocation->context.isValid()) { if (log) - log->Printf("RenderScriptRuntime::JITTypePointer - Failed to find allocation details"); + log->Printf("%s - failed to find allocation details.", __FUNCTION__); return false; } - const char* expr_cstr = JITTemplate(eExprAllocGetType); + 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()); + 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()"); + log->Printf("%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (chars_written >= jit_max_expr_size) { if (log) - log->Printf("RenderScriptRuntime::JITTypePointer - Expression too long"); + log->Printf("%s - expression too long.", __FUNCTION__); return false; } @@ -1498,43 +1683,43 @@ RenderScriptRuntime::JITTypePointer(AllocationDetails* allocation, StackFrame* f // 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) +RenderScriptRuntime::JITTypePacked(AllocationDetails *allocation, StackFrame *frame_ptr) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!allocation->type_ptr.isValid() || !allocation->context.isValid()) { if (log) - log->Printf("RenderScriptRuntime::JITTypePacked - Failed to find allocation details"); + log->Printf("%s - Failed to find allocation details.", __FUNCTION__); 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; + const uint32_t bits = archByteSize == 4 ? 32 : 64; // We want 4 elements from packed data - const unsigned int num_exprs = 4; + const uint32_t 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) + for (uint32_t 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()); + 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()"); + log->Printf("%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (chars_written >= jit_max_expr_size) { if (log) - log->Printf("RenderScriptRuntime::JITTypePacked - Expression too long"); + log->Printf("%s - expression too long.", __FUNCTION__); return false; } @@ -1554,7 +1739,7 @@ RenderScriptRuntime::JITTypePacked(AllocationDetails* allocation, StackFrame* fr allocation->element.element_ptr = elem_ptr; if (log) - log->Printf("RenderScriptRuntime::JITTypePacked - dims (%u, %u, %u) Element*: 0x%" PRIx64, + log->Printf("%s - dims (%" PRIu32 ", %" PRIu32 ", %" PRIu32 ") Element*: 0x%" PRIx64 ".", __FUNCTION__, dims.dim_1, dims.dim_2, dims.dim_3, elem_ptr); return true; @@ -1564,38 +1749,38 @@ RenderScriptRuntime::JITTypePacked(AllocationDetails* allocation, StackFrame* fr // 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) +RenderScriptRuntime::JITElementPacked(Element &elem, const lldb::addr_t context, StackFrame *frame_ptr) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!elem.element_ptr.isValid()) { if (log) - log->Printf("RenderScriptRuntime::JITElementPacked - Failed to find allocation details"); + log->Printf("%s - failed to find allocation details.", __FUNCTION__); return false; } // We want 4 elements from packed data - const unsigned int num_exprs = 4; + const uint32_t 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++) + for (uint32_t i = 0; i < num_exprs; i++) { - const char* expr_cstr = JITTemplate((ExpressionStrings) (eExprElementType + 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 (log) - log->Printf("RenderScriptRuntime::JITElementPacked - Encoding error in snprintf()"); + log->Printf("%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (chars_written >= jit_max_expr_size) { if (log) - log->Printf("RenderScriptRuntime::JITElementPacked - Expression too long"); + log->Printf("%s - expression too long.", __FUNCTION__); return false; } @@ -1611,8 +1796,8 @@ RenderScriptRuntime::JITElementPacked(Element& elem, const lldb::addr_t context, elem.field_count = static_cast(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()); + log->Printf("%s - data type %" PRIu32 ", pixel type %" PRIu32 ", vector size %" PRIu32 ", field count %" PRIu32, + __FUNCTION__, *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)) @@ -1625,14 +1810,14 @@ RenderScriptRuntime::JITElementPacked(Element& elem, const lldb::addr_t context, // 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) +RenderScriptRuntime::JITSubelements(Element &elem, const lldb::addr_t context, StackFrame *frame_ptr) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + 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"); + log->Printf("%s - failed to find allocation details.", __FUNCTION__); return false; } @@ -1644,25 +1829,25 @@ RenderScriptRuntime::JITSubelements(Element& elem, const lldb::addr_t context, S // 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) + for (uint32_t field_index = 0; field_index < field_count; ++field_index) { Element child; - for (unsigned int expr_index = 0; expr_index < num_exprs; ++expr_index) + for (uint32_t expr_index = 0; expr_index < num_exprs; ++expr_index) { - const char* expr_cstr = JITTemplate((ExpressionStrings) (eExprSubelementsId + 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()"); + log->Printf("%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (chars_written >= jit_max_expr_size) { if (log) - log->Printf("RenderScriptRuntime::JITSubelements - Expression too long"); + log->Printf("%s - expression too long.", __FUNCTION__); return false; } @@ -1671,9 +1856,9 @@ RenderScriptRuntime::JITSubelements(Element& elem, const lldb::addr_t context, S return false; if (log) - log->Printf("RenderScriptRuntime::JITSubelements - Expr result 0x%" PRIx64, results); + log->Printf("%s - expr result 0x%" PRIx64 ".", __FUNCTION__, results); - switch(expr_index) + switch (expr_index) { case 0: // Element* of child child.element_ptr = static_cast(results); @@ -1689,7 +1874,7 @@ RenderScriptRuntime::JITSubelements(Element& elem, const lldb::addr_t context, S else { if (log) - log->Printf("RenderScriptRuntime::JITSubelements - Warning: Couldn't read field name"); + log->Printf("%s - warning: Couldn't read field name.", __FUNCTION__); } break; } @@ -1718,22 +1903,22 @@ RenderScriptRuntime::JITSubelements(Element& elem, const lldb::addr_t context, S // 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) +RenderScriptRuntime::JITAllocationSize(AllocationDetails *allocation, StackFrame *frame_ptr) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); - if (!allocation->address.isValid() || !allocation->dimension.isValid() - || !allocation->data_ptr.isValid() || !allocation->element.datum_size.isValid()) + 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"); + log->Printf("%s - failed to find allocation details.", __FUNCTION__); 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; + uint32_t dim_x = allocation->dimension.get()->dim_1; + uint32_t dim_y = allocation->dimension.get()->dim_2; + uint32_t 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. @@ -1746,12 +1931,12 @@ RenderScriptRuntime::JITAllocationSize(AllocationDetails* allocation, StackFrame 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()); - + log->Printf("%s - infered size of struct allocation %" PRIu32 ".", __FUNCTION__, + *allocation->size.get()); return true; } - const char* expr_cstr = JITTemplate(eExprGetOffsetPtr); + const char *expr_cstr = JITTemplate(eExprGetOffsetPtr); char buffer[jit_max_expr_size]; // Calculate last element @@ -1759,18 +1944,17 @@ RenderScriptRuntime::JITAllocationSize(AllocationDetails* allocation, StackFrame 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); + 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()"); + log->Printf("%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (chars_written >= jit_max_expr_size) { if (log) - log->Printf("RenderScriptRuntime::JITAllocationSize - Expression too long"); + log->Printf("%s - expression too long.", __FUNCTION__); return false; } @@ -1780,7 +1964,8 @@ RenderScriptRuntime::JITAllocationSize(AllocationDetails* allocation, StackFrame addr_t mem_ptr = static_cast(result); // Find pointer to last element and add on size of an element - allocation->size = static_cast(mem_ptr - *allocation->data_ptr.get()) + *allocation->element.datum_size.get(); + allocation->size = + static_cast(mem_ptr - *allocation->data_ptr.get()) + *allocation->element.datum_size.get(); return true; } @@ -1789,32 +1974,31 @@ RenderScriptRuntime::JITAllocationSize(AllocationDetails* allocation, StackFrame // 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) +RenderScriptRuntime::JITAllocationStride(AllocationDetails *allocation, StackFrame *frame_ptr) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + 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"); + log->Printf("%s - failed to find allocation details.", __FUNCTION__); return false; } - const char* expr_cstr = JITTemplate(eExprGetOffsetPtr); + 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); + 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()"); + log->Printf("%s - encoding error in snprintf().", __FUNCTION__); return false; } else if (chars_written >= jit_max_expr_size) { if (log) - log->Printf("RenderScriptRuntime::JITAllocationStride - Expression too long"); + log->Printf("%s - expression too long.", __FUNCTION__); return false; } @@ -1830,7 +2014,7 @@ RenderScriptRuntime::JITAllocationStride(AllocationDetails* allocation, StackFra // JIT all the current runtime info regarding an allocation bool -RenderScriptRuntime::RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr) +RenderScriptRuntime::RefreshAllocation(AllocationDetails *allocation, StackFrame *frame_ptr) { // GetOffsetPointer() if (!JITDataPointer(allocation, frame_ptr)) @@ -1862,9 +2046,9 @@ RenderScriptRuntime::RefreshAllocation(AllocationDetails* allocation, StackFrame // 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) +RenderScriptRuntime::FindStructTypeName(Element &elem, StackFrame *frame_ptr) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (!elem.type_name.IsEmpty()) // Name already set return; @@ -1883,7 +2067,7 @@ RenderScriptRuntime::FindStructTypeName(Element& elem, StackFrame* frame_ptr) { const VariableSP var_sp(variable_list.GetVariableAtIndex(var_index)); if (!var_sp) - continue; + continue; ValueObjectSP valobj_sp = ValueObjectVariable::Create(frame_ptr, var_sp); if (!valobj_sp) @@ -1914,13 +2098,13 @@ RenderScriptRuntime::FindStructTypeName(Element& elem, StackFrame* frame_ptr) // 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; + const uint32_t size_diff = elem.children.size() - num_children; if (log) - log->Printf("RenderScriptRuntime::FindStructTypeName - %u padding struct entries", size_diff); + log->Printf("%s - %" PRIu32 " padding struct entries", __FUNCTION__, size_diff); - for (unsigned int padding_index = 0; padding_index < size_diff; ++padding_index) + for (uint32_t padding_index = 0; padding_index < size_diff; ++padding_index) { - const ConstString& name = elem.children[num_children + padding_index].type_name; + const ConstString &name = elem.children[num_children + padding_index].type_name; if (strcmp(name.AsCString(), "#rs_padding") < 0) found = false; } @@ -1941,7 +2125,7 @@ RenderScriptRuntime::FindStructTypeName(Element& elem, StackFrame* frame_ptr) // 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()); + log->Printf("%s - element name set to %s", __FUNCTION__, elem.type_name.AsCString()); return; } @@ -1951,29 +2135,30 @@ RenderScriptRuntime::FindStructTypeName(Element& elem, StackFrame* frame_ptr) // 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) +RenderScriptRuntime::SetElementSize(Element &elem) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + 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"); + 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; + const uint32_t vec_size = *elem.type_vec_size.get(); + uint32_t data_size = 0; + uint32_t 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) + for (Element &child : elem.children) { SetElementSize(child); - const unsigned int array_size = child.array_size.isValid() ? *child.array_size.get() : 1; + const uint32_t 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 + // These have been packed already + 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) { data_size = AllocationDetails::RSTypeToFormat[type][eElementSize]; } @@ -1989,40 +2174,41 @@ RenderScriptRuntime::SetElementSize(Element& elem) elem.padding = padding; elem.datum_size = data_size + padding; if (log) - log->Printf("RenderScriptRuntime::SetElementSize - element size set to %u", data_size + padding); + log->Printf("%s - element size set to %" PRIu32, __FUNCTION__, 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 -RenderScriptRuntime::GetAllocationData(AllocationDetails* allocation, StackFrame* frame_ptr) +RenderScriptRuntime::GetAllocationData(AllocationDetails *allocation, StackFrame *frame_ptr) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + 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"); + log->Printf("%s - allocation details not calculated yet, jitting info", __FUNCTION__); if (!RefreshAllocation(allocation, frame_ptr)) { if (log) - log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't JIT allocation details"); + log->Printf("%s - couldn't JIT allocation details", __FUNCTION__); return nullptr; } } - assert(allocation->data_ptr.isValid() && allocation->element.type.isValid() && allocation->element.type_vec_size.isValid() - && allocation->size.isValid() && "Allocation information not available"); + 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(); + const uint32_t size = *allocation->size.get(); std::shared_ptr buffer(new uint8_t[size]); if (!buffer) { if (log) - log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't allocate a %u byte buffer", size); + log->Printf("%s - couldn't allocate a %" PRIu32 " byte buffer", __FUNCTION__, size); return nullptr; } @@ -2033,8 +2219,8 @@ RenderScriptRuntime::GetAllocationData(AllocationDetails* allocation, StackFrame 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); + log->Printf("%s - '%s' Couldn't read %" PRIu32 " bytes of allocation data from 0x%" PRIx64, + __FUNCTION__, error.AsCString(), size, data_ptr); return nullptr; } @@ -2045,34 +2231,34 @@ RenderScriptRuntime::GetAllocationData(AllocationDetails* allocation, StackFrame // 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) +RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const char *filename, StackFrame *frame_ptr) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); // Find allocation with the given id - AllocationDetails* alloc = FindAllocByID(strm, alloc_id); + AllocationDetails *alloc = FindAllocByID(strm, alloc_id); if (!alloc) return false; if (log) - log->Printf("RenderScriptRuntime::LoadAllocation - Found allocation 0x%" PRIx64, *alloc->address.get()); + log->Printf("%s - found allocation 0x%" PRIx64, __FUNCTION__, *alloc->address.get()); // JIT all the allocation details if (alloc->shouldRefresh()) { if (log) - log->Printf("RenderScriptRuntime::LoadAllocation - Allocation details not calculated yet, jitting info"); + log->Printf("%s - allocation details not calculated yet, jitting info.", __FUNCTION__); if (!RefreshAllocation(alloc, frame_ptr)) { if (log) - log->Printf("RenderScriptRuntime::LoadAllocation - Couldn't JIT allocation details"); + log->Printf("%s - couldn't JIT allocation details", __FUNCTION__); 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"); + 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); @@ -2094,19 +2280,18 @@ RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const DataBufferSP data_sp(file.ReadFileContents()); // Cast start of buffer to FileHeader and use pointer to read metadata - void* file_buffer = data_sp->GetBytes(); - if (file_buffer == NULL || data_sp->GetByteSize() < - (sizeof(AllocationDetails::FileHeader) + sizeof(AllocationDetails::ElementHeader))) + void *file_buffer = data_sp->GetBytes(); + if (file_buffer == nullptr || + data_sp->GetByteSize() < (sizeof(AllocationDetails::FileHeader) + sizeof(AllocationDetails::ElementHeader))) { strm.Printf("Error: File %s does not contain enough data for header", filename); strm.EOL(); return false; } - const AllocationDetails::FileHeader* file_header = static_cast(file_buffer); + const AllocationDetails::FileHeader *file_header = static_cast(file_buffer); // Check file starts with ascii characters "RSAD" - if (file_header->ident[0] != 'R' || file_header->ident[1] != 'S' || file_header->ident[2] != 'A' - || file_header->ident[3] != 'D') + if (memcmp(file_header->ident, "RSAD", 4)) { strm.Printf("Error: File doesn't contain identifier for an RS allocation dump. Are you sure this is the correct file?"); strm.EOL(); @@ -2115,24 +2300,24 @@ RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const // Look at the type of the root element in the header AllocationDetails::ElementHeader root_element_header; - memcpy(&root_element_header, static_cast(file_buffer) + sizeof(AllocationDetails::FileHeader), + memcpy(&root_element_header, static_cast(file_buffer) + sizeof(AllocationDetails::FileHeader), sizeof(AllocationDetails::ElementHeader)); if (log) - log->Printf("RenderScriptRuntime::LoadAllocation - header type %u, element size %u", + log->Printf("%s - header type %" PRIu32 ", element size %" PRIu32, __FUNCTION__, root_element_header.type, root_element_header.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() != root_element_header.element_size) { - strm.Printf("Warning: Mismatched Element sizes - file %u bytes, allocation %u bytes", + strm.Printf("Warning: Mismatched Element sizes - file %" PRIu32 " bytes, allocation %" PRIu32 " bytes", root_element_header.element_size, *alloc->element.datum_size.get()); strm.EOL(); } // Check if the target allocation and file both have the same type - const unsigned int alloc_type = static_cast(*alloc->element.type.get()); - const unsigned int file_type = root_element_header.type; + const uint32_t alloc_type = static_cast(*alloc->element.type.get()); + const uint32_t file_type = root_element_header.type; if (file_type > Element::RS_TYPE_FONT) { @@ -2142,36 +2327,36 @@ RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const else if (alloc_type != file_type) { // Enum value isn't monotonous, so doesn't always index RsDataTypeToString array - unsigned int printable_target_type_index = alloc_type; - unsigned int printable_head_type_index = file_type; + uint32_t printable_target_type_index = alloc_type; + uint32_t printable_head_type_index = file_type; if (alloc_type >= Element::RS_TYPE_ELEMENT && alloc_type <= Element::RS_TYPE_FONT) - printable_target_type_index = static_cast( - (alloc_type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1); + printable_target_type_index = static_cast((alloc_type - Element::RS_TYPE_ELEMENT) + + Element::RS_TYPE_MATRIX_2X2 + 1); if (file_type >= Element::RS_TYPE_ELEMENT && file_type <= Element::RS_TYPE_FONT) - printable_head_type_index = static_cast( - (file_type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1); + printable_head_type_index = static_cast((file_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]; + 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.Printf("Warning: Mismatched Types - file '%s' type, allocation '%s' type", file_type_cstr, + target_type_cstr); strm.EOL(); } // Advance buffer past header - file_buffer = static_cast(file_buffer) + file_header->hdr_size; + file_buffer = static_cast(file_buffer) + file_header->hdr_size; // Calculate size of allocation data in file size_t length = data_sp->GetByteSize() - file_header->hdr_size; // Check if the target allocation and file both have the same total data size. - const unsigned int alloc_size = *alloc->size.get(); + const uint32_t 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.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64 " bytes, allocation 0x%" PRIx32 " bytes", + (uint64_t)length, alloc_size); strm.EOL(); length = alloc_size < length ? alloc_size : length; // Set length to copy to minimum } @@ -2187,7 +2372,7 @@ RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const return false; } - strm.Printf("Contents of file '%s' read into allocation %u", filename, alloc->id); + strm.Printf("Contents of file '%s' read into allocation %" PRIu32, filename, alloc->id); strm.EOL(); return true; @@ -2196,9 +2381,11 @@ RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const // Function takes as parameters a byte buffer, which will eventually be written to file as the element header, // an offset into that buffer, and an Element that will be saved into the buffer at the parametrised offset. // Return value is the new offset after writing the element into the buffer. -// Elements are saved to the file as the ElementHeader struct followed by offsets to the structs of all the element's children. +// Elements are saved to the file as the ElementHeader struct followed by offsets to the structs of all the element's +// children. size_t -RenderScriptRuntime::PopulateElementHeaders(const std::shared_ptr header_buffer, size_t offset, const Element& elem) +RenderScriptRuntime::PopulateElementHeaders(const std::shared_ptr header_buffer, size_t offset, + const Element &elem) { // File struct for an element header with all the relevant details copied from elem. // We assume members are valid already. @@ -2211,13 +2398,13 @@ RenderScriptRuntime::PopulateElementHeaders(const std::shared_ptr heade const size_t elem_header_size = sizeof(AllocationDetails::ElementHeader); // Copy struct into buffer and advance offset - // We assume that header_buffer has been checked for NULL before this method is called + // We assume that header_buffer has been checked for nullptr before this method is called memcpy(header_buffer.get() + offset, &elem_header, elem_header_size); offset += elem_header_size; // Starting offset of child ElementHeader struct size_t child_offset = offset + ((elem.children.size() + 1) * sizeof(uint32_t)); - for (const RenderScriptRuntime::Element& child : elem.children) + for (const RenderScriptRuntime::Element &child : elem.children) { // Recursively populate the buffer with the element header structs of children. // Then save the offsets where they were set after the parent element header. @@ -2233,17 +2420,18 @@ RenderScriptRuntime::PopulateElementHeaders(const std::shared_ptr heade return child_offset; } -// Given an Element object this function returns the total size needed in the file header to store the element's details. +// Given an Element object this function returns the total size needed in the file header to store the element's +// details. // Taking into account the size of the element header struct, plus the offsets to all the element's children. // Function is recursive so that the size of all ancestors is taken into account. size_t -RenderScriptRuntime::CalculateElementHeaderSize(const Element& elem) +RenderScriptRuntime::CalculateElementHeaderSize(const Element &elem) { size_t size = (elem.children.size() + 1) * sizeof(uint32_t); // Offsets to children plus zero terminator - size += sizeof(AllocationDetails::ElementHeader); // Size of header struct with type details + size += sizeof(AllocationDetails::ElementHeader); // Size of header struct with type details // Calculate recursively for all descendants - for (const Element& child : elem.children) + for (const Element &child : elem.children) size += CalculateElementHeaderSize(child); return size; @@ -2253,34 +2441,35 @@ RenderScriptRuntime::CalculateElementHeaderSize(const Element& elem) // 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) +RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const char *filename, StackFrame *frame_ptr) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); // Find allocation with the given id - AllocationDetails* alloc = FindAllocByID(strm, alloc_id); + AllocationDetails *alloc = FindAllocByID(strm, alloc_id); if (!alloc) return false; if (log) - log->Printf("RenderScriptRuntime::SaveAllocation - Found allocation 0x%" PRIx64, *alloc->address.get()); + log->Printf("%s - found allocation 0x%" PRIx64 ".", __FUNCTION__, *alloc->address.get()); - // JIT all the allocation details + // JIT all the allocation details if (alloc->shouldRefresh()) { if (log) - log->Printf("RenderScriptRuntime::SaveAllocation - Allocation details not calculated yet, jitting info"); + log->Printf("%s - allocation details not calculated yet, jitting info.", __FUNCTION__); if (!RefreshAllocation(alloc, frame_ptr)) { if (log) - log->Printf("RenderScriptRuntime::SaveAllocation - Couldn't JIT allocation details"); + log->Printf("%s - couldn't JIT allocation details.", __FUNCTION__); 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"); + 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); @@ -2303,7 +2492,7 @@ RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const // Create the file header AllocationDetails::FileHeader head; - head.ident[0] = 'R'; head.ident[1] = 'S'; head.ident[2] = 'A'; head.ident[3] = 'D'; + memcpy(head.ident, "RSAD", 4); head.dims[0] = static_cast(alloc->dimension.get()->dim_1); head.dims[1] = static_cast(alloc->dimension.get()->dim_2); head.dims[2] = static_cast(alloc->dimension.get()->dim_3); @@ -2315,7 +2504,7 @@ RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const // Write the file header size_t num_bytes = sizeof(AllocationDetails::FileHeader); if (log) - log->Printf("RenderScriptRuntime::SaveAllocation - Writing File Header, 0x%zX bytes", num_bytes); + log->Printf("%s - writing File Header, 0x%" PRIx64 " bytes", __FUNCTION__, (uint64_t)num_bytes); Error err = file.Write(&head, num_bytes); if (!err.Success()) @@ -2329,7 +2518,7 @@ RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const std::shared_ptr element_header_buffer(new uint8_t[element_header_size]); if (element_header_buffer == nullptr) { - strm.Printf("Internal Error: Couldn't allocate %zu bytes on the heap", element_header_size); + strm.Printf("Internal Error: Couldn't allocate %" PRIu64 " bytes on the heap", (uint64_t)element_header_size); strm.EOL(); return false; } @@ -2339,7 +2528,7 @@ RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const // Write headers for allocation element type to file num_bytes = element_header_size; if (log) - log->Printf("RenderScriptRuntime::SaveAllocation - Writing Element Headers, 0x%zX bytes", num_bytes); + log->Printf("%s - writing element headers, 0x%" PRIx64 " bytes.", __FUNCTION__, (uint64_t)num_bytes); err = file.Write(element_header_buffer.get(), num_bytes); if (!err.Success()) @@ -2352,7 +2541,7 @@ RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const // Write allocation data to file num_bytes = static_cast(*alloc->size.get()); if (log) - log->Printf("RenderScriptRuntime::SaveAllocation - Writing 0x%zX bytes", num_bytes); + log->Printf("%s - writing 0x%" PRIx64 " bytes", __FUNCTION__, (uint64_t)num_bytes); err = file.Write(buffer.get(), num_bytes); if (!err.Success()) @@ -2370,7 +2559,7 @@ RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const bool RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); if (module_sp) { @@ -2424,7 +2613,8 @@ RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) { m_libRS = module_sp; static ConstString gDbgPresentStr("gDebuggerPresent"); - const Symbol* debug_present = m_libRS->FindFirstSymbolWithNameAndType(gDbgPresentStr, eSymbolTypeData); + const Symbol *debug_present = + m_libRS->FindFirstSymbolWithNameAndType(gDbgPresentStr, eSymbolTypeData); if (debug_present) { Error error; @@ -2432,21 +2622,22 @@ RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) Target &target = GetProcess()->GetTarget(); addr_t addr = debug_present->GetLoadAddress(&target); GetProcess()->WriteMemory(addr, &flag, sizeof(flag), error); - if(error.Success()) + if (error.Success()) { if (log) - log->Printf ("RenderScriptRuntime::LoadModule - Debugger present flag set on debugee"); + log->Printf("%s - debugger present flag set on debugee.", __FUNCTION__); m_debuggerPresentFlagged = true; } else if (log) { - log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags '%s' ", error.AsCString()); + log->Printf("%s - error writing debugger present flags '%s' ", __FUNCTION__, + error.AsCString()); } } else if (log) { - log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags - symbol not found"); + log->Printf("%s - error writing debugger present flags - symbol not found", __FUNCTION__); } } break; @@ -2475,98 +2666,98 @@ RenderScriptRuntime::Update() // The maximum line length of an .rs.info packet #define MAXLINE 500 +#define STRINGIFY(x) #x +#define MAXLINESTR_(x) "%" STRINGIFY(x) "s" +#define MAXLINESTR MAXLINESTR_(MAXLINE) // The .rs.info symbol in renderscript modules contains a string which needs to be parsed. // The string is basic and is parsed on a line by line basis. bool RSModuleDescriptor::ParseRSInfo() { + assert(m_module); const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData); - if (info_sym) - { - const addr_t addr = info_sym->GetAddressRef().GetFileAddress(); - const addr_t size = info_sym->GetByteSize(); - const FileSpec fs = m_module->GetFileSpec(); + if (!info_sym) + return false; + + const addr_t addr = info_sym->GetAddressRef().GetFileAddress(); + if (addr == LLDB_INVALID_ADDRESS) + return false; - DataBufferSP buffer = fs.ReadFileContents(addr, size); + const addr_t size = info_sym->GetByteSize(); + const FileSpec fs = m_module->GetFileSpec(); - if (!buffer) - return false; + const DataBufferSP buffer = fs.ReadFileContents(addr, size); + if (!buffer) + return false; - std::string info((const char *)buffer->GetBytes()); + // split rs.info. contents into lines + std::vector info_lines; + { + const std::string info((const char *)buffer->GetBytes()); + for (size_t tail = 0; tail < info.size();) + { + // find next new line or end of string + size_t head = info.find('\n', tail); + head = (head == std::string::npos) ? info.size() : head; + std::string line = info.substr(tail, head - tail); + // add to line list + info_lines.push_back(line); + tail = head + 1; + } + } - std::vector info_lines; - size_t lpos = info.find('\n'); - while (lpos != std::string::npos) + std::array name{{'\0'}}; + std::array value{{'\0'}}; + + // parse all text lines of .rs.info + for (auto line = info_lines.begin(); line != info_lines.end(); ++line) + { + uint32_t numDefns = 0; + if (sscanf(line->c_str(), "exportVarCount: %" PRIu32 "", &numDefns) == 1) { - info_lines.push_back(info.substr(0, lpos)); - info = info.substr(lpos + 1); - lpos = info.find('\n'); + while (numDefns--) + m_globals.push_back(RSGlobalDescriptor(this, (++line)->c_str())); } - size_t offset = 0; - while (offset < info_lines.size()) + else if (sscanf(line->c_str(), "exportForEachCount: %" PRIu32 "", &numDefns) == 1) { - std::string line = info_lines[offset]; - // Parse directives - uint32_t numDefns = 0; - if (sscanf(line.c_str(), "exportVarCount: %u", &numDefns) == 1) - { - while (numDefns--) - m_globals.push_back(RSGlobalDescriptor(this, info_lines[++offset].c_str())); - } - else if (sscanf(line.c_str(), "exportFuncCount: %u", &numDefns) == 1) + while (numDefns--) { - } - else if (sscanf(line.c_str(), "exportForEachCount: %u", &numDefns) == 1) - { - char name[MAXLINE]; - while (numDefns--) + uint32_t slot = 0; + name[0] = '\0'; + static const char *fmt_s = "%" PRIu32 " - " MAXLINESTR; + if (sscanf((++line)->c_str(), fmt_s, &slot, name.data()) == 2) { - uint32_t slot = 0; - name[0] = '\0'; - if (sscanf(info_lines[++offset].c_str(), "%u - %s", &slot, &name[0]) == 2) - { - m_kernels.push_back(RSKernelDescriptor(this, name, slot)); - } + if (name[0] != '\0') + m_kernels.push_back(RSKernelDescriptor(this, name.data(), slot)); } } - else if (sscanf(line.c_str(), "pragmaCount: %u", &numDefns) == 1) + } + else if (sscanf(line->c_str(), "pragmaCount: %" PRIu32 "", &numDefns) == 1) + { + while (numDefns--) { - char name[MAXLINE]; - char value[MAXLINE]; - while (numDefns--) + name[0] = value[0] = '\0'; + static const char *fmt_s = MAXLINESTR " - " MAXLINESTR; + if (sscanf((++line)->c_str(), fmt_s, name.data(), value.data()) != 0) { - name[0] = '\0'; - value[0] = '\0'; - if (sscanf(info_lines[++offset].c_str(), "%s - %s", &name[0], &value[0]) != 0 - && (name[0] != '\0')) - { - m_pragmas[std::string(name)] = value; - } + if (name[0] != '\0') + m_pragmas[std::string(name.data())] = value.data(); } } - else if (sscanf(line.c_str(), "objectSlotCount: %u", &numDefns) == 1) + } + else + { + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + if (log) { + log->Printf("%s - skipping .rs.info field '%s'", __FUNCTION__, line->c_str()); } - - offset++; } - return m_kernels.size() > 0; } - return false; -} -bool -RenderScriptRuntime::ProbeModules(const ModuleList module_list) -{ - bool rs_found = false; - size_t num_modules = module_list.GetSize(); - for (size_t i = 0; i < num_modules; i++) - { - auto module = module_list.GetModuleAtIndex(i); - rs_found |= LoadModule(module); - } - return rs_found; + // 'root' kernel should always be present + return m_kernels.size() > 0; } void @@ -2616,7 +2807,7 @@ RenderScriptRuntime::DumpContexts(Stream &strm) const // 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) + for (const auto &script : m_scripts) { if (!script->context.isValid()) continue; @@ -2632,7 +2823,7 @@ RenderScriptRuntime::DumpContexts(Stream &strm) const } } - for (const auto& cRef : contextReferences) + for (const auto &cRef : contextReferences) { strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances", cRef.first, cRef.second); strm.EOL(); @@ -2648,7 +2839,7 @@ RenderScriptRuntime::DumpKernels(Stream &strm) const strm.IndentMore(); for (const auto &module : m_rsmodules) { - strm.Printf("Resource '%s':",module->m_resname.c_str()); + strm.Printf("Resource '%s':", module->m_resname.c_str()); strm.EOL(); for (const auto &kernel : module->m_kernels) { @@ -2659,32 +2850,31 @@ RenderScriptRuntime::DumpKernels(Stream &strm) const strm.IndentLess(); } -RenderScriptRuntime::AllocationDetails* +RenderScriptRuntime::AllocationDetails * RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id) { - AllocationDetails* alloc = nullptr; + 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) + if (alloc_id <= m_allocations.size() && alloc_id != 0 && m_allocations[alloc_id - 1]->id == alloc_id) { - alloc = m_allocations[alloc_id-1].get(); + alloc = m_allocations[alloc_id - 1].get(); return alloc; } // Fallback to searching - for (const auto & a : m_allocations) + for (const auto &a : m_allocations) { - if (a->id == alloc_id) - { - alloc = a.get(); - break; - } + 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.Printf("Error: Couldn't find allocation with id matching %" PRIu32, alloc_id); strm.EOL(); } @@ -2693,23 +2883,23 @@ RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id) // 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) +RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr, const uint32_t id) { - Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); // Check we can find the desired allocation - AllocationDetails* alloc = FindAllocByID(strm, id); + 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()); + log->Printf("%s - found allocation 0x%" PRIx64, __FUNCTION__, *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"); + log->Printf("%s - allocation details not calculated yet, jitting info.", __FUNCTION__); // JIT all the allocation information if (!RefreshAllocation(alloc, frame_ptr)) @@ -2721,11 +2911,10 @@ RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame* frame_ptr, const u } // Establish format and size of each data element - const unsigned int vec_size = *alloc->element.type_vec_size.get(); + const uint32_t 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"); + assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT && "Invalid allocation type"); lldb::Format format; if (type >= Element::RS_TYPE_ELEMENT) @@ -2734,10 +2923,10 @@ RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame* frame_ptr, const u format = vec_size == 1 ? static_cast(AllocationDetails::RSTypeToFormat[type][eFormatSingle]) : static_cast(AllocationDetails::RSTypeToFormat[type][eFormatVector]); - const unsigned int data_size = *alloc->element.datum_size.get(); + const uint32_t data_size = *alloc->element.datum_size.get(); if (log) - log->Printf("RenderScriptRuntime::DumpAllocation - Element size %u bytes, including padding", data_size); + log->Printf("%s - element size %" PRIu32 " bytes, including padding", __FUNCTION__, data_size); // Allocate a buffer to copy data into std::shared_ptr buffer = GetAllocationData(alloc, frame_ptr); @@ -2761,44 +2950,45 @@ RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame* frame_ptr, const u 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; + const uint32_t stride = *alloc->stride.get(); + const uint32_t size = *alloc->size.get(); // Size of whole allocation + const uint32_t 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); + log->Printf("%s - stride %" PRIu32 " bytes, size %" PRIu32 " bytes, padding %" PRIu32, + __FUNCTION__, stride, size, padding); // Find dimensions used to index loops, so need to be non-zero - unsigned int dim_x = alloc->dimension.get()->dim_1; + uint32_t dim_x = alloc->dimension.get()->dim_1; dim_x = dim_x == 0 ? 1 : dim_x; - unsigned int dim_y = alloc->dimension.get()->dim_2; + uint32_t dim_y = alloc->dimension.get()->dim_2; dim_y = dim_y == 0 ? 1 : dim_y; - unsigned int dim_z = alloc->dimension.get()->dim_3; + uint32_t 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 + uint32_t offset = 0; // Offset in buffer to next element to be printed + uint32_t 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 (uint32_t z = 0; z < dim_z; ++z) { - for (unsigned int y = 0; y < dim_y; ++y) + for (uint32_t y = 0; y < dim_y; ++y) { // Use stride to index start of next row. - if (!(y==0 && z==0)) + 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) + for (uint32_t x = 0; x < dim_x; ++x) { - strm.Printf("\n(%u, %u, %u) = ", x, y, z); + strm.Printf("\n(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ") = ", x, y, z); if ((type == Element::RS_TYPE_NONE) && (alloc->element.children.size() > 0) && (alloc->element.type_name != Element::GetFallbackStructName())) { @@ -2812,12 +3002,12 @@ RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame* frame_ptr, const u // 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); + alloc->element.type_name.AsCString(), *alloc->data_ptr.get() + offset); if (chars_written < 0 || chars_written >= jit_max_expr_size) { if (log) - log->Printf("RenderScriptRuntime::DumpAllocation- Error in snprintf()"); + log->Printf("%s - error in snprintf().", __FUNCTION__); continue; } @@ -2841,10 +3031,35 @@ RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame* frame_ptr, const u return true; } -// Prints infomation regarding all the currently loaded allocations. +// Function recalculates all our cached information about allocations by jitting the +// RS runtime regarding each allocation we know about. +// Returns true if all allocations could be recomputed, false otherwise. +bool +RenderScriptRuntime::RecomputeAllAllocations(Stream &strm, StackFrame *frame_ptr) +{ + bool success = true; + for (auto &alloc : m_allocations) + { + // JIT current allocation information + if (!RefreshAllocation(alloc.get(), frame_ptr)) + { + strm.Printf("Error: Couldn't evaluate details for allocation %" PRIu32 "\n", alloc->id); + success = false; + } + } + + if (success) + strm.Printf("All allocations successfully recomputed"); + strm.EOL(); + + return success; +} + +// Prints information regarding currently loaded allocations. // These details are gathered by jitting the runtime, which has as latency. +// Index parameter specifies a single allocation ID to print, or a zero value to print them all void -RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute) +RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame *frame_ptr, const uint32_t index) { strm.Printf("RenderScript Allocations:"); strm.EOL(); @@ -2852,17 +3067,20 @@ RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool r 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; + // index will only be zero if we want to print all allocations + if (index != 0 && index != alloc->id) + continue; // JIT current allocation information - if (do_refresh && !RefreshAllocation(alloc.get(), frame_ptr)) + if (alloc->shouldRefresh() && !RefreshAllocation(alloc.get(), frame_ptr)) { - strm.Printf("Error: Couldn't evaluate details for allocation %u\n", alloc->id); + strm.Printf("Error: Couldn't evaluate details for allocation %" PRIu32, alloc->id); + strm.EOL(); continue; } - strm.Printf("%u:\n",alloc->id); + strm.Printf("%" PRIu32 ":", alloc->id); + strm.EOL(); strm.IndentMore(); strm.Indent("Context: "); @@ -2887,9 +3105,8 @@ RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool r 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.Printf("(%" PRId32 ", %" PRId32 ", %" PRId32 ")\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()) @@ -2905,13 +3122,16 @@ RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool r { // 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((type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1); + type = static_cast((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) + 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(type)][vector_size-1]); + strm.Printf("%s\n", AllocationDetails::RsDataTypeToString[static_cast(type)] + [vector_size - 1]); } } @@ -2924,7 +3144,7 @@ RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool r 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(kind)]); + strm.Printf("%s\n", AllocationDetails::RsDataKindToString[static_cast(kind)]); } strm.EOL(); @@ -2955,7 +3175,7 @@ RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp void RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target) { - Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); InitSearchFilter(target); @@ -2968,29 +3188,28 @@ RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target) BreakOnModuleKernels(module); if (log) - log->Printf("RenderScriptRuntime::SetBreakAllKernels(True)" - "- breakpoints set on all currently loaded kernels"); + log->Printf("%s(True) - breakpoints set on all currently loaded kernels.", __FUNCTION__); } 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"); + log->Printf("%s(False) - breakpoints no longer automatically set.", __FUNCTION__); } } // 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) +RenderScriptRuntime::CreateKernelBreakpoint(const ConstString &name) { - Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); if (!m_filtersp) { if (log) - log->Printf("RenderScriptRuntime::CreateKernelBreakpoint - Error: No breakpoint search filter set"); + log->Printf("%s - error, no breakpoint search filter set.", __FUNCTION__); return nullptr; } @@ -3000,7 +3219,7 @@ RenderScriptRuntime::CreateKernelBreakpoint(const ConstString& name) // 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()); + log->Printf("%s - error setting break name, '%s'.", __FUNCTION__, err.AsCString()); return bp; } @@ -3009,41 +3228,113 @@ RenderScriptRuntime::CreateKernelBreakpoint(const ConstString& name) // 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) +RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp, const char *var_name, uint64_t &val) { - Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + 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)); + 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); - + log->Printf("%s - error, couldn't find '%s' in frame", __FUNCTION__, var_name); return false; } - // Find the unsigned int value for the variable + // Find the uint32_t 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); - + log->Printf("%s - error, couldn't parse '%s' as an uint32_t.", __FUNCTION__, var_name); return false; } return true; } +// Function attempts to find the current coordinate of a kernel invocation by investigating the +// values of frame variables in the .expand function. These coordinates are returned via the coord +// array reference parameter. Returns true if the coordinates could be found, and false otherwise. +bool +RenderScriptRuntime::GetKernelCoordinate(RSCoordinate &coord, Thread *thread_ptr) +{ + static const std::string s_runtimeExpandSuffix(".expand"); + static const std::array s_runtimeCoordVars{{"rsIndex", "p->current.y", "p->current.z"}}; + + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + + if (!thread_ptr) + { + if (log) + log->Printf("%s - Error, No thread pointer", __FUNCTION__); + + return false; + } + + // Walk the call stack looking for a function whose name has the suffix '.expand' + // and contains the variables we're looking for. + for (uint32_t i = 0; i < thread_ptr->GetStackFrameCount(); ++i) + { + if (!thread_ptr->SetSelectedFrameByIndex(i)) + continue; + + StackFrameSP frame_sp = thread_ptr->GetSelectedFrame(); + if (!frame_sp) + continue; + + // Find the function name + const SymbolContext sym_ctx = frame_sp->GetSymbolContext(false); + const char *func_name_cstr = sym_ctx.GetFunctionName().AsCString(); + if (!func_name_cstr) + continue; + + if (log) + log->Printf("%s - Inspecting function '%s'", __FUNCTION__, func_name_cstr); + + // Check if function name has .expand suffix + std::string func_name(func_name_cstr); + const int length_difference = func_name.length() - s_runtimeExpandSuffix.length(); + if (length_difference <= 0) + continue; + + const int32_t has_expand_suffix = func_name.compare(length_difference, + s_runtimeExpandSuffix.length(), + s_runtimeExpandSuffix); + + if (has_expand_suffix != 0) + continue; + + if (log) + log->Printf("%s - Found .expand function '%s'", __FUNCTION__, func_name_cstr); + + // Get values for variables in .expand frame that tell us the current kernel invocation + bool found_coord_variables = true; + assert(s_runtimeCoordVars.size() == coord.size()); + + for (uint32_t i = 0; i < coord.size(); ++i) + { + uint64_t value = 0; + if (!GetFrameVarAsUnsigned(frame_sp, s_runtimeCoordVars[i], value)) + { + found_coord_variables = false; + break; + } + coord[i] = value; + } + + if (found_coord_variables) + return true; + } + return false; +} + // 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. @@ -3051,61 +3342,46 @@ RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp, const ch // 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) +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)); + 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(baton); + const uint32_t *target_coord = static_cast(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]); + log->Printf("%s - Break ID %" PRIu64 ", (%" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", __FUNCTION__, break_id, + target_coord[0], target_coord[1], target_coord[2]); - // Go up one stack frame to .expand kernel + // Select current thread 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"); + Thread *thread_ptr = context.GetThreadPtr(); + assert(thread_ptr && "Null thread pointer"); - return false; - } - - StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); - if (!frame_sp) + // Find current kernel invocation from .expand frame variables + RSCoordinate current_coord{}; // Zero initialise array + if (!GetKernelCoordinate(current_coord, thread_ptr)) { if (log) - log->Printf("RenderScriptRuntime::KernelBreakpointHit - Error, couldn't select .expand stack frame"); - + log->Printf("%s - Error, couldn't select .expand stack frame", __FUNCTION__); 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]); - } + if (log) + log->Printf("%s - (%" PRIu32 ",%" PRIu32 ",%" PRIu32 ")", __FUNCTION__, current_coord[0], current_coord[1], + current_coord[2]); // Check if the current kernel invocation coordinate matches our target coordinate - if (current_coord[0] == static_cast(target_coord[0]) && - current_coord[1] == static_cast(target_coord[1]) && - current_coord[2] == static_cast(target_coord[2])) + if (current_coord[0] == target_coord[0] && + current_coord[1] == target_coord[1] && + current_coord[2] == target_coord[2]) { if (log) - log->Printf("RenderScriptRuntime::KernelBreakpointHit, BREAKING %" PRIu64 ", %" PRIu64 ", %" PRIu64, - current_coord[0], current_coord[1], current_coord[2]); + log->Printf("%s, BREAKING (%" PRIu32 ",%" PRIu32 ",%" PRIu32 ")", __FUNCTION__, 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"); @@ -3121,8 +3397,8 @@ RenderScriptRuntime::KernelBreakpointHit(void *baton, StoppointCallbackContext * // 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 coords, - Error& error, TargetSP target) +RenderScriptRuntime::PlaceBreakpointOnKernel(Stream &strm, const char *name, const std::array coords, + Error &error, TargetSP target) { if (!name) { @@ -3138,11 +3414,12 @@ RenderScriptRuntime::PlaceBreakpointOnKernel(Stream &strm, const char* name, con // 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.Printf("Conditional kernel breakpoint on coordinate %" PRId32 ", %" PRId32 ", %" PRId32, + coords[0], coords[1], coords[2]); strm.EOL(); // Allocate memory for the baton, and copy over coordinate - int* baton = new int[3]; + uint32_t *baton = new uint32_t[coords.size()]; baton[0] = coords[0]; baton[1] = coords[1]; baton[2] = coords[2]; // Create a callback that will be invoked everytime the breakpoint is hit. @@ -3150,7 +3427,7 @@ RenderScriptRuntime::PlaceBreakpointOnKernel(Stream &strm, const char* name, con 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(baton); + m_conditional_breaks[bp->GetID()] = std::shared_ptr(baton); } if (bp) @@ -3170,10 +3447,10 @@ RenderScriptRuntime::DumpModules(Stream &strm) const strm.IndentLess(); } -RenderScriptRuntime::ScriptDetails* +RenderScriptRuntime::ScriptDetails * RenderScriptRuntime::LookUpScript(addr_t address, bool create) { - for (const auto & s : m_scripts) + for (const auto &s : m_scripts) { if (s->script.isValid()) if (*s->script == address) @@ -3189,10 +3466,10 @@ RenderScriptRuntime::LookUpScript(addr_t address, bool create) return nullptr; } -RenderScriptRuntime::AllocationDetails* +RenderScriptRuntime::AllocationDetails * RenderScriptRuntime::LookUpAllocation(addr_t address, bool create) { - for (const auto & a : m_allocations) + for (const auto &a : m_allocations) { if (a->address.isValid()) if (*a->address == address) @@ -3213,7 +3490,7 @@ RSModuleDescriptor::Dump(Stream &strm) const { strm.Indent(); m_module->GetFileSpec().Dump(&strm); - if(m_module->GetNumCompileUnits()) + if (m_module->GetNumCompileUnits()) { strm.Indent("Debug info loaded."); } @@ -3240,7 +3517,7 @@ RSModuleDescriptor::Dump(Stream &strm) const { kernel.Dump(strm); } - strm.Printf("Pragmas: %" PRIu64 , static_cast(m_pragmas.size())); + strm.Printf("Pragmas: %" PRIu64, static_cast(m_pragmas.size())); strm.EOL(); strm.IndentMore(); for (const auto &key_val : m_pragmas) @@ -3261,7 +3538,7 @@ RSGlobalDescriptor::Dump(Stream &strm) const { auto var = var_list.GetVariableAtIndex(0); auto type = var->GetType(); - if(type) + if (type) { strm.Printf(" - "); type->DumpTypeName(&strm); @@ -3274,7 +3551,7 @@ RSGlobalDescriptor::Dump(Stream &strm) const else { strm.Printf(" - variable identified, but not found in binary"); - const Symbol* s = m_module->m_module->FindFirstSymbolWithNameAndType(m_name, eSymbolTypeData); + const Symbol *s = m_module->m_module->FindFirstSymbolWithNameAndType(m_name, eSymbolTypeData); if (s) { strm.Printf(" (symbol exists) "); @@ -3291,44 +3568,6 @@ RSKernelDescriptor::Dump(Stream &strm) const strm.EOL(); } -class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed -{ -public: - CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "renderscript module probe", - "Initiates a Probe of all loaded modules for kernels and other renderscript objects.", - "renderscript module probe", - eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBeLaunched) - { - } - - ~CommandObjectRenderScriptRuntimeModuleProbe() override = default; - - bool - DoExecute(Args &command, CommandReturnObject &result) override - { - const size_t argc = command.GetArgumentCount(); - if (argc == 0) - { - Target *target = m_exe_ctx.GetTargetPtr(); - RenderScriptRuntime *runtime = - (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); - auto module_list = target->GetImages(); - bool new_rs_details = runtime->ProbeModules(module_list); - if (new_rs_details) - { - result.AppendMessage("New renderscript modules added to runtime model."); - } - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } - - result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } -}; - class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed { public: @@ -3356,10 +3595,9 @@ class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword { public: CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.", - NULL) + : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with RenderScript modules.", + nullptr) { - LoadSubCommand("probe", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleProbe(interpreter))); LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter))); } @@ -3371,8 +3609,8 @@ class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed public: CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "renderscript kernel list", - "Lists renderscript kernel names and associated script resources.", "renderscript kernel list", - eCommandRequiresProcess | eCommandProcessMustBeLaunched) + "Lists renderscript kernel names and associated script resources.", + "renderscript kernel list", eCommandRequiresProcess | eCommandProcessMustBeLaunched) { } @@ -3394,14 +3632,16 @@ class CommandObjectRenderScriptRuntimeKernelBreakpointSet : public CommandObject public: CommandObjectRenderScriptRuntimeKernelBreakpointSet(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "renderscript kernel breakpoint set", - "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint set [-c x,y,z]", - eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), m_options(interpreter) + "Sets a breakpoint on a renderscript kernel.", + "renderscript kernel breakpoint set [-c x,y,z]", + eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), + m_options(interpreter) { } ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() override = default; - Options* + Options * GetOptions() override { return &m_options; @@ -3410,9 +3650,7 @@ public: class CommandOptions : public Options { public: - CommandOptions(CommandInterpreter &interpreter) : Options(interpreter) - { - } + CommandOptions(CommandInterpreter &interpreter) : Options(interpreter) {} ~CommandOptions() override = default; @@ -3426,7 +3664,8 @@ public: { case 'c': if (!ParseCoordinate(option_arg)) - error.SetErrorStringWithFormat("Couldn't parse coordinate '%s', should be in format 'x,y,z'.", 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); @@ -3439,23 +3678,23 @@ public: // Where 'id_cstr' is this argument with the whitespace trimmed. // Missing coordinates are defaulted to zero. bool - ParseCoordinate(const char* id_cstr) + 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, ®ex_match)) + if (regex.Compile("^([0-9]+),([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, ®ex_match)) matched = true; - else if(regex.Compile("^([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, ®ex_match)) + else if (regex.Compile("^([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, ®ex_match)) matched = true; - else if(regex.Compile("^([0-9]+)$") && regex.Execute(id_cstr, ®ex_match)) + else if (regex.Compile("^([0-9]+)$") && regex.Execute(id_cstr, ®ex_match)) matched = true; - for(uint32_t i = 0; i < 3; i++) + 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); + if (regex_match.GetMatchAtIndex(id_cstr, i + 1, group)) + m_coord[i] = (uint32_t)strtoul(group.c_str(), nullptr, 0); else m_coord[i] = 0; } @@ -3471,14 +3710,14 @@ public: m_coord[2] = -1; } - const OptionDefinition* + const OptionDefinition * GetDefinitions() override { return g_option_table; } static OptionDefinition g_option_table[]; - std::array m_coord; + std::array m_coord; }; bool @@ -3487,13 +3726,14 @@ public: 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.AppendErrorWithFormat("'%s' takes 1 argument of kernel name, and an optional coordinate.", + m_cmd_name.c_str()); result.SetStatus(eReturnStatusFailed); return false; } RenderScriptRuntime *runtime = - (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); + (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); Error error; runtime->PlaceBreakpointOnKernel(result.GetOutputStream(), command.GetArgumentAtIndex(0), m_options.m_coord, @@ -3514,26 +3754,24 @@ 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 } -}; +OptionDefinition CommandObjectRenderScriptRuntimeKernelBreakpointSet::CommandOptions::g_option_table[] = { + {LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 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, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}}; 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 ", - eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) + : 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 ", + eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) { } @@ -3550,11 +3788,11 @@ public: return false; } - RenderScriptRuntime *runtime = - static_cast(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); + RenderScriptRuntime *runtime = static_cast( + m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); bool do_break = false; - const char* argument = command.GetArgumentAtIndex(0); + const char *argument = command.GetArgumentAtIndex(0); if (strcmp(argument, "enable") == 0) { do_break = true; @@ -3579,12 +3817,48 @@ public: } }; +class CommandObjectRenderScriptRuntimeKernelCoordinate : public CommandObjectParsed +{ +public: + CommandObjectRenderScriptRuntimeKernelCoordinate(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "renderscript kernel coordinate", + "Shows the (x,y,z) coordinate of the current kernel invocation.", + "renderscript kernel coordinate", + eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) + { + } + + ~CommandObjectRenderScriptRuntimeKernelCoordinate() override = default; + + bool + DoExecute(Args &command, CommandReturnObject &result) override + { + RSCoordinate coord{}; // Zero initialize array + bool success = RenderScriptRuntime::GetKernelCoordinate(coord, m_exe_ctx.GetThreadPtr()); + Stream &stream = result.GetOutputStream(); + + if (success) + { + stream.Printf("Coordinate: (%" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", coord[0], coord[1], coord[2]); + stream.EOL(); + result.SetStatus(eReturnStatusSuccessFinishResult); + } + else + { + stream.Printf("Error: Coordinate could not be found."); + stream.EOL(); + result.SetStatus(eReturnStatusFailed); + } + return true; + } +}; + class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectMultiword { public: CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that generate breakpoints on renderscript kernels.", - nullptr) + : CommandObjectMultiword(interpreter, "renderscript kernel", + "Commands that generate breakpoints on renderscript kernels.", nullptr) { LoadSubCommand("set", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(interpreter))); LoadSubCommand("all", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(interpreter))); @@ -3597,11 +3871,14 @@ class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword { public: CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with renderscript kernels.", - NULL) + : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with RenderScript kernels.", + nullptr) { LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(interpreter))); - LoadSubCommand("breakpoint", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter))); + LoadSubCommand("coordinate", + CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelCoordinate(interpreter))); + LoadSubCommand("breakpoint", + CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter))); } ~CommandObjectRenderScriptRuntimeKernel() override = default; @@ -3611,9 +3888,8 @@ class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed { public: CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "renderscript context dump", - "Dumps renderscript context information.", "renderscript context dump", - eCommandRequiresProcess | eCommandProcessMustBeLaunched) + : CommandObjectParsed(interpreter, "renderscript context dump", "Dumps renderscript context information.", + "renderscript context dump", eCommandRequiresProcess | eCommandProcessMustBeLaunched) { } @@ -3634,8 +3910,8 @@ class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword { public: CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with renderscript contexts.", - NULL) + : CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with RenderScript contexts.", + nullptr) { LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(interpreter))); } @@ -3649,13 +3925,14 @@ public: CommandObjectRenderScriptRuntimeAllocationDump(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "renderscript allocation dump", "Displays the contents of a particular allocation", "renderscript allocation dump ", - eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter) + eCommandRequiresProcess | eCommandProcessMustBeLaunched), + m_options(interpreter) { } ~CommandObjectRenderScriptRuntimeAllocationDump() override = default; - Options* + Options * GetOptions() override { return &m_options; @@ -3664,9 +3941,7 @@ public: class CommandOptions : public Options { public: - CommandOptions(CommandInterpreter &interpreter) : Options(interpreter) - { - } + CommandOptions(CommandInterpreter &interpreter) : Options(interpreter) {} ~CommandOptions() override = default; @@ -3699,7 +3974,7 @@ public: m_outfile.Clear(); } - const OptionDefinition* + const OptionDefinition * GetDefinitions() override { return g_option_table; @@ -3721,10 +3996,10 @@ public: return false; } - RenderScriptRuntime *runtime = - static_cast(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); + RenderScriptRuntime *runtime = static_cast( + m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); - const char* id_cstr = command.GetArgumentAtIndex(0); + 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) @@ -3734,7 +4009,7 @@ public: return false; } - Stream* output_strm = nullptr; + Stream *output_strm = nullptr; StreamFile outfile_stream; const FileSpec &outfile_spec = m_options.m_outfile; // Dump allocation to file instead if (outfile_spec) @@ -3773,13 +4048,10 @@ 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 } -}; +OptionDefinition CommandObjectRenderScriptRuntimeAllocationDump::CommandOptions::g_option_table[] = { + {LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, + "Print results to specified file instead of command line."}, + {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}}; class CommandObjectRenderScriptRuntimeAllocationList : public CommandObjectParsed { @@ -3787,13 +4059,14 @@ public: CommandObjectRenderScriptRuntimeAllocationList(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "renderscript allocation list", "List renderscript allocations and their information.", "renderscript allocation list", - eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter) + eCommandRequiresProcess | eCommandProcessMustBeLaunched), + m_options(interpreter) { } ~CommandObjectRenderScriptRuntimeAllocationList() override = default; - Options* + Options * GetOptions() override { return &m_options; @@ -3802,9 +4075,7 @@ public: class CommandOptions : public Options { public: - CommandOptions(CommandInterpreter &interpreter) : Options(interpreter), m_refresh(false) - { - } + CommandOptions(CommandInterpreter &interpreter) : Options(interpreter), m_id(0) {} ~CommandOptions() override = default; @@ -3816,8 +4087,11 @@ public: switch (short_option) { - case 'r': - m_refresh = true; + case 'i': + bool success; + m_id = StringConvert::ToUInt32(option_arg, 0, 0, &success); + if (!success) + error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option); break; default: error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); @@ -3829,25 +4103,25 @@ public: void OptionParsingStarting() override { - m_refresh = false; + m_id = 0; } - const OptionDefinition* + const OptionDefinition * GetDefinitions() override { return g_option_table; } static OptionDefinition g_option_table[]; - bool m_refresh; + uint32_t m_id; }; bool DoExecute(Args &command, CommandReturnObject &result) override { - RenderScriptRuntime *runtime = - static_cast(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); - runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), m_options.m_refresh); + RenderScriptRuntime *runtime = static_cast( + m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); + runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), m_options.m_id); result.SetStatus(eReturnStatusSuccessFinishResult); return true; } @@ -3856,21 +4130,18 @@ 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 } -}; +OptionDefinition CommandObjectRenderScriptRuntimeAllocationList::CommandOptions::g_option_table[] = { + {LLDB_OPT_SET_1, false, "id", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeIndex, + "Only show details of a single allocation with specified id."}, + {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}}; class CommandObjectRenderScriptRuntimeAllocationLoad : public CommandObjectParsed { public: CommandObjectRenderScriptRuntimeAllocationLoad(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "renderscript allocation load", - "Loads renderscript allocation contents from a file.", "renderscript allocation load ", - eCommandRequiresProcess | eCommandProcessMustBeLaunched) + : CommandObjectParsed( + interpreter, "renderscript allocation load", "Loads renderscript allocation contents from a file.", + "renderscript allocation load ", eCommandRequiresProcess | eCommandProcessMustBeLaunched) { } @@ -3882,25 +4153,26 @@ public: 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.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(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); + RenderScriptRuntime *runtime = static_cast( + m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); - const char* id_cstr = command.GetArgumentAtIndex(0); + 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); + result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr); + result.SetStatus(eReturnStatusFailed); return false; } - const char* filename = command.GetArgumentAtIndex(1); + const char *filename = command.GetArgumentAtIndex(1); bool success = runtime->LoadAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr()); if (success) @@ -3916,9 +4188,9 @@ class CommandObjectRenderScriptRuntimeAllocationSave : public CommandObjectParse { public: CommandObjectRenderScriptRuntimeAllocationSave(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "renderscript allocation save", - "Write renderscript allocation contents to a file.", "renderscript allocation save ", - eCommandRequiresProcess | eCommandProcessMustBeLaunched) + : CommandObjectParsed( + interpreter, "renderscript allocation save", "Write renderscript allocation contents to a file.", + "renderscript allocation save ", eCommandRequiresProcess | eCommandProcessMustBeLaunched) { } @@ -3930,25 +4202,26 @@ public: 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.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(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); + RenderScriptRuntime *runtime = static_cast( + m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); - const char* id_cstr = command.GetArgumentAtIndex(0); + 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); + result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr); + result.SetStatus(eReturnStatusFailed); return false; } - const char* filename = command.GetArgumentAtIndex(1); + const char *filename = command.GetArgumentAtIndex(1); bool success = runtime->SaveAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr()); if (success) @@ -3960,17 +4233,51 @@ public: } }; +class CommandObjectRenderScriptRuntimeAllocationRefresh : public CommandObjectParsed +{ +public: + CommandObjectRenderScriptRuntimeAllocationRefresh(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "renderscript allocation refresh", + "Recomputes the details of all allocations.", "renderscript allocation refresh", + eCommandRequiresProcess | eCommandProcessMustBeLaunched) + { + } + + ~CommandObjectRenderScriptRuntimeAllocationRefresh() override = default; + + bool + DoExecute(Args &command, CommandReturnObject &result) override + { + RenderScriptRuntime *runtime = static_cast( + m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); + + bool success = runtime->RecomputeAllAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr()); + + if (success) + { + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + else + { + result.SetStatus(eReturnStatusFailed); + return false; + } + } +}; + class CommandObjectRenderScriptRuntimeAllocation : public CommandObjectMultiword { public: CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "renderscript allocation", "Commands that deal with renderscript allocations.", - NULL) + : CommandObjectMultiword(interpreter, "renderscript allocation", + "Commands that deal with RenderScript allocations.", nullptr) { LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationList(interpreter))); LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationDump(interpreter))); LoadSubCommand("save", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationSave(interpreter))); LoadSubCommand("load", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationLoad(interpreter))); + LoadSubCommand("refresh", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationRefresh(interpreter))); } ~CommandObjectRenderScriptRuntimeAllocation() override = default; @@ -3980,9 +4287,8 @@ class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed { public: CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "renderscript status", - "Displays current renderscript runtime status.", "renderscript status", - eCommandRequiresProcess | eCommandProcessMustBeLaunched) + : CommandObjectParsed(interpreter, "renderscript status", "Displays current RenderScript runtime status.", + "renderscript status", eCommandRequiresProcess | eCommandProcessMustBeLaunched) { } @@ -4003,7 +4309,7 @@ class CommandObjectRenderScriptRuntime : public CommandObjectMultiword { public: CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter) - : CommandObjectMultiword(interpreter, "renderscript", "A set of commands for operating on renderscript.", + : CommandObjectMultiword(interpreter, "renderscript", "Commands for operating on the RenderScript runtime.", "renderscript []") { LoadSubCommand("module", CommandObjectSP(new CommandObjectRenderScriptRuntimeModule(interpreter))); @@ -4023,21 +4329,18 @@ 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()); } lldb::CommandObjectSP -RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter& interpreter) +RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter &interpreter) { - static CommandObjectSP command_object; - if(!command_object) - { - command_object.reset(new CommandObjectRenderScriptRuntime(interpreter)); - } - return command_object; + return CommandObjectSP(new CommandObjectRenderScriptRuntime(interpreter)); } RenderScriptRuntime::~RenderScriptRuntime() = default; diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h index 2fe439017bbc..2a0839a1a78b 100644 --- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h +++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h @@ -20,13 +20,15 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" -#include "lldb/Target/LanguageRuntime.h" -#include "lldb/Target/CPPLanguageRuntime.h" #include "lldb/Core/Module.h" +#include "lldb/Target/CPPLanguageRuntime.h" +#include "lldb/Target/LanguageRuntime.h" +#include "lldb/lldb-private.h" -namespace lldb_private { -namespace lldb_renderscript { +namespace lldb_private +{ +namespace lldb_renderscript +{ typedef uint32_t RSSlot; class RSModuleDescriptor; @@ -36,6 +38,7 @@ struct RSKernelDescriptor; typedef std::shared_ptr RSModuleDescriptorSP; typedef std::shared_ptr RSGlobalDescriptorSP; typedef std::shared_ptr RSKernelDescriptorSP; +typedef std::array RSCoordinate; // Breakpoint Resolvers decide where a breakpoint is placed, // so having our own allows us to limit the search scope to RS kernel modules. @@ -43,9 +46,8 @@ typedef std::shared_ptr RSKernelDescriptorSP; class RSBreakpointResolver : public BreakpointResolver { public: - RSBreakpointResolver(Breakpoint *bkpt, ConstString name): - BreakpointResolver (bkpt, BreakpointResolver::NameResolver), - m_kernel_name(name) + RSBreakpointResolver(Breakpoint *bkpt, ConstString name) + : BreakpointResolver(bkpt, BreakpointResolver::NameResolver), m_kernel_name(name) { } @@ -62,10 +64,7 @@ public: } Searcher::CallbackReturn - SearchCallback(SearchFilter &filter, - SymbolContext &context, - Address *addr, - bool containing) override; + SearchCallback(SearchFilter &filter, SymbolContext &context, Address *addr, bool containing) override; Searcher::Depth GetDepth() override @@ -88,13 +87,12 @@ struct RSKernelDescriptor { public: RSKernelDescriptor(const RSModuleDescriptor *module, const char *name, uint32_t slot) - : m_module(module) - , m_name(name) - , m_slot(slot) + : m_module(module), m_name(name), m_slot(slot) { } - void Dump(Stream &strm) const; + void + Dump(Stream &strm) const; const RSModuleDescriptor *m_module; ConstString m_name; @@ -104,13 +102,10 @@ public: struct RSGlobalDescriptor { public: - RSGlobalDescriptor(const RSModuleDescriptor *module, const char *name ) - : m_module(module) - , m_name(name) - { - } + RSGlobalDescriptor(const RSModuleDescriptor *module, const char *name) : m_module(module), m_name(name) {} - void Dump(Stream &strm) const; + void + Dump(Stream &strm) const; const RSModuleDescriptor *m_module; ConstString m_name; @@ -119,16 +114,15 @@ public: class RSModuleDescriptor { public: - RSModuleDescriptor(const lldb::ModuleSP &module) - : m_module(module) - { - } + RSModuleDescriptor(const lldb::ModuleSP &module) : m_module(module) {} ~RSModuleDescriptor() = default; - bool ParseRSInfo(); + bool + ParseRSInfo(); - void Dump(Stream &strm) const; + void + Dump(Stream &strm) const; const lldb::ModuleSP m_module; std::vector m_kernels; @@ -156,105 +150,144 @@ public: //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ - static void Initialize(); + static void + Initialize(); - static void Terminate(); + static void + Terminate(); - static lldb_private::LanguageRuntime *CreateInstance(Process *process, lldb::LanguageType language); + static lldb_private::LanguageRuntime * + CreateInstance(Process *process, lldb::LanguageType language); - static lldb::CommandObjectSP GetCommandObject(CommandInterpreter& interpreter); + static lldb::CommandObjectSP + GetCommandObject(CommandInterpreter &interpreter); - static lldb_private::ConstString GetPluginNameStatic(); + static lldb_private::ConstString + GetPluginNameStatic(); - static bool IsRenderScriptModule(const lldb::ModuleSP &module_sp); + static bool + IsRenderScriptModule(const lldb::ModuleSP &module_sp); - static ModuleKind GetModuleKind(const lldb::ModuleSP &module_sp); + static ModuleKind + GetModuleKind(const lldb::ModuleSP &module_sp); - static void ModulesDidLoad(const lldb::ProcessSP& process_sp, const ModuleList &module_list ); + static void + ModulesDidLoad(const lldb::ProcessSP &process_sp, const ModuleList &module_list); - bool IsVTableName(const char *name) override; + bool + IsVTableName(const char *name) override; + + bool + GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, + TypeAndOrName &class_type_or_name, Address &address, + Value::ValueType &value_type) override; - 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; + FixUpDynamicType(const TypeAndOrName &type_and_or_name, ValueObject &static_value) override; - bool CouldHaveDynamicValue(ValueObject &in_value) override; + bool + CouldHaveDynamicValue(ValueObject &in_value) override; - lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override; + lldb::BreakpointResolverSP + CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) override; - bool LoadModule(const lldb::ModuleSP &module_sp); + bool + LoadModule(const lldb::ModuleSP &module_sp); - bool ProbeModules(const ModuleList module_list); + void + DumpModules(Stream &strm) const; - void DumpModules(Stream &strm) const; + void + DumpContexts(Stream &strm) const; - void DumpContexts(Stream &strm) const; + void + DumpKernels(Stream &strm) const; - void DumpKernels(Stream &strm) const; + bool + DumpAllocation(Stream &strm, StackFrame *frame_ptr, const uint32_t id); - bool DumpAllocation(Stream &strm, StackFrame* frame_ptr, const uint32_t id); + void + ListAllocations(Stream &strm, StackFrame *frame_ptr, const uint32_t index); - void ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute); + bool + RecomputeAllAllocations(Stream &strm, StackFrame *frame_ptr); - void PlaceBreakpointOnKernel(Stream &strm, const char *name, const std::array coords, - Error &error, lldb::TargetSP target); + void + PlaceBreakpointOnKernel(Stream &strm, const char *name, const std::array coords, Error &error, + lldb::TargetSP target); - void SetBreakAllKernels(bool do_break, lldb::TargetSP target); + void + SetBreakAllKernels(bool do_break, lldb::TargetSP target); - void Status(Stream &strm) const; + void + Status(Stream &strm) const; - void ModulesDidLoad(const ModuleList &module_list) override; + void + ModulesDidLoad(const ModuleList &module_list) override; - bool LoadAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr); + 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); + bool + SaveAllocation(Stream &strm, const uint32_t alloc_id, const char *filename, StackFrame *frame_ptr); - void Update(); + void + Update(); - void Initiate(); + void + Initiate(); //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - lldb_private::ConstString GetPluginName() override; + lldb_private::ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; - uint32_t GetPluginVersion() override; + static bool + GetKernelCoordinate(lldb_renderscript::RSCoordinate &coord, Thread *thread_ptr); protected: struct ScriptDetails; struct AllocationDetails; struct Element; - void InitSearchFilter(lldb::TargetSP target) + void + InitSearchFilter(lldb::TargetSP target) { if (!m_filtersp) m_filtersp.reset(new SearchFilterForUnconstrainedSearches(target)); } - void FixupScriptDetails(lldb_renderscript::RSModuleDescriptorSP rsmodule_sp); + void + FixupScriptDetails(lldb_renderscript::RSModuleDescriptorSP rsmodule_sp); - void LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind); + void + LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind); - bool RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr); + bool + RefreshAllocation(AllocationDetails *allocation, StackFrame *frame_ptr); - bool EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result); + bool + EvalRSExpression(const char *expression, StackFrame *frame_ptr, uint64_t *result); - lldb::BreakpointSP CreateKernelBreakpoint(const ConstString& name); + lldb::BreakpointSP + CreateKernelBreakpoint(const ConstString &name); + + void + BreakOnModuleKernels(const lldb_renderscript::RSModuleDescriptorSP rsmodule_sp); - void BreakOnModuleKernels(const lldb_renderscript::RSModuleDescriptorSP rsmodule_sp); - struct RuntimeHook; - typedef void (RenderScriptRuntime::*CaptureStateFn)(RuntimeHook* hook_info, ExecutionContext &context); // Please do this! + typedef void (RenderScriptRuntime::*CaptureStateFn)(RuntimeHook *hook_info, + ExecutionContext &context); // Please do this! struct HookDefn { - const char * 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 + const char *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; @@ -263,7 +296,7 @@ protected: struct RuntimeHook { lldb::addr_t address; - const HookDefn *defn; + const HookDefn *defn; lldb::BreakpointSP bp_sp; }; @@ -279,7 +312,7 @@ protected: std::map m_scriptMappings; std::map m_runtimeHooks; - std::map> m_conditional_breaks; + std::map> m_conditional_breaks; lldb::SearchFilterSP m_filtersp; // Needed to create breakpoints through Target API @@ -290,81 +323,93 @@ protected: static const size_t s_runtimeHookCount; 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 + 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); + 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); + void + HookCallback(RuntimeHook *hook_info, ExecutionContext &context); - bool GetArgSimple(ExecutionContext& context, uint32_t arg, uint64_t* data); + void + CaptureScriptInit(RuntimeHook *hook_info, ExecutionContext &context); - 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); + void + CaptureAllocationInit(RuntimeHook *hook_info, ExecutionContext &context); + + void + CaptureAllocationDestroy(RuntimeHook *hook_info, ExecutionContext &context); + + void + CaptureSetGlobalVar(RuntimeHook *hook_info, ExecutionContext &context); + + void + CaptureScriptInvokeForEachMulti(RuntimeHook *hook_info, ExecutionContext &context); + + AllocationDetails * + FindAllocByID(Stream &strm, const uint32_t alloc_id); + + std::shared_ptr + 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); - AllocationDetails* FindAllocByID(Stream &strm, const uint32_t alloc_id); - std::shared_ptr 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); + size_t + PopulateElementHeaders(const std::shared_ptr header_buffer, size_t offset, const Element &elem); - size_t PopulateElementHeaders(const std::shared_ptr header_buffer, size_t offset, const Element& elem); - size_t CalculateElementHeaderSize(const Element& elem); + size_t + CalculateElementHeaderSize(const Element &elem); // // 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 + JITDataPointer(AllocationDetails *allocation, StackFrame *frame_ptr, + uint32_t x = 0, uint32_t y = 0, uint32_t z = 0); - bool JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr); + bool + JITTypePointer(AllocationDetails *allocation, StackFrame *frame_ptr); - bool JITTypePacked(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 + JITElementPacked(Element &elem, const lldb::addr_t context, StackFrame *frame_ptr); - bool JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr); + bool + JITAllocationSize(AllocationDetails *allocation, StackFrame *frame_ptr); - bool JITSubelements(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr); + bool + JITSubelements(Element &elem, const lldb::addr_t context, StackFrame *frame_ptr); - bool JITAllocationStride(AllocationDetails* allocation, 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); + 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); + AllocationDetails * + LookUpAllocation(lldb::addr_t address, bool create); }; } // namespace lldb_private diff --git a/source/Plugins/Makefile b/source/Plugins/Makefile deleted file mode 100644 index 931f459a26b7..000000000000 --- a/source/Plugins/Makefile +++ /dev/null @@ -1,67 +0,0 @@ -##===- source/Plugins/Makefile -----------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../.. - -include $(LLDB_LEVEL)/../../Makefile.config - - -PARALLEL_DIRS := ABI/MacOSX-arm ABI/MacOSX-arm64 ABI/MacOSX-i386 ABI/SysV-i386 ABI/SysV-x86_64 \ - ABI/SysV-arm ABI/SysV-arm64 ABI/SysV-hexagon ABI/SysV-ppc ABI/SysV-ppc64 \ - ABI/SysV-mips ABI/SysV-mips64 Disassembler/llvm \ - ObjectContainer/BSD-Archive ObjectFile/ELF ObjectFile/PECOFF \ - ObjectContainer/Universal-Mach-O ObjectFile/Mach-O \ - ObjectFile/JIT SymbolFile/DWARF SymbolFile/Symtab Process/Utility \ - DynamicLoader/Static Platform Process/elf-core Process/gdb-remote \ - Instruction/ARM Instruction/ARM64 Instruction/MIPS Instruction/MIPS64 \ - UnwindAssembly/InstEmulation UnwindAssembly/x86 \ - LanguageRuntime/CPlusPlus/ItaniumABI \ - LanguageRuntime/ObjC/AppleObjCRuntime \ - LanguageRuntime/Go/ \ - LanguageRuntime/RenderScript/RenderScriptRuntime \ - Language/CPlusPlus \ - Language/Go \ - Language/ObjC \ - Language/ObjCPlusPlus \ - DynamicLoader/POSIX-DYLD \ - DynamicLoader/Hexagon-DYLD \ - DynamicLoader/MacOSX-DYLD \ - DynamicLoader/Windows-DYLD \ - JITLoader/GDB \ - ExpressionParser/Clang \ - ExpressionParser/Go \ - OperatingSystem/Go \ - OperatingSystem/Python \ - SystemRuntime/MacOSX \ - SymbolVendor/ELF \ - MemoryHistory/asan \ - InstrumentationRuntime/AddressSanitizer \ - ScriptInterpreter/Python ScriptInterpreter/None - -ifeq ($(HOST_OS),Darwin) -PARALLEL_DIRS += Process/MacOSX-Kernel -PARALLEL_DIRS += DynamicLoader/Darwin-Kernel -PARALLEL_DIRS += SymbolVendor/MacOSX -#PARALLEL_DIRS += Process/MacOSX-User -PARALLEL_DIRS += Process/mach-core -endif - -ifeq ($(HOST_OS),Linux) -PARALLEL_DIRS += Process/Linux Process/POSIX -endif - -ifneq (,$(filter $(HOST_OS), FreeBSD GNU/kFreeBSD)) -PARALLEL_DIRS += Process/FreeBSD Process/POSIX -endif - -ifeq ($(HOST_OS),NetBSD) -PARALLEL_DIRS += Process/POSIX -endif - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/MemoryHistory/asan/Makefile b/source/Plugins/MemoryHistory/asan/Makefile deleted file mode 100644 index 86de6aba3638..000000000000 --- a/source/Plugins/MemoryHistory/asan/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/MemoryHistory/asan/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginMemoryHistoryASan -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp index c57519871624..a9d13ac79c37 100644 --- a/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp +++ b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp @@ -12,8 +12,10 @@ #include "lldb/Target/MemoryHistory.h" #include "lldb/lldb-private.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Expression/UserExpression.h" #include "lldb/Target/ThreadList.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Target.h" @@ -22,6 +24,8 @@ #include "Plugins/Process/Utility/HistoryThread.h" #include "lldb/Core/ValueObject.h" +#include + using namespace lldb; using namespace lldb_private; @@ -34,7 +38,7 @@ MemoryHistoryASan::CreateInstance (const ProcessSP &process_sp) Target & target = process_sp->GetTarget(); const ModuleList &target_modules = target.GetImages(); - Mutex::Locker modules_locker(target_modules.GetMutex()); + std::lock_guard guard(target_modules.GetMutex()); const size_t num_modules = target_modules.GetSize(); for (size_t i = 0; i < num_modules; ++i) { @@ -80,8 +84,14 @@ MemoryHistoryASan::MemoryHistoryASan(const ProcessSP &process_sp) } const char * -memory_history_asan_command_format = R"( - struct t { +memory_history_asan_command_prefix = R"( + extern "C" + { + size_t __asan_get_alloc_stack(void *addr, void **trace, size_t size, int *thread_id); + size_t __asan_get_free_stack(void *addr, void **trace, size_t size, int *thread_id); + } + + struct data { void *alloc_trace[256]; size_t alloc_count; int alloc_tid; @@ -89,10 +99,15 @@ memory_history_asan_command_format = R"( void *free_trace[256]; size_t free_count; int free_tid; - } t; + }; +)"; + +const char * +memory_history_asan_command_format = R"( + data t; - t.alloc_count = ((size_t (*) (void *, void **, size_t, int *))__asan_get_alloc_stack)((void *)0x%)" PRIx64 R"(, t.alloc_trace, 256, &t.alloc_tid); - t.free_count = ((size_t (*) (void *, void **, size_t, int *))__asan_get_free_stack)((void *)0x%)" PRIx64 R"(, t.free_trace, 256, &t.free_tid); + t.alloc_count = __asan_get_alloc_stack((void *)0x%)" PRIx64 R"(, t.alloc_trace, 256, &t.alloc_tid); + t.free_count = __asan_get_free_stack((void *)0x%)" PRIx64 R"(, t.free_trace, 256, &t.free_tid); t; )"; @@ -110,7 +125,7 @@ static void CreateHistoryThreadFromValueObject(ProcessSP process_sp, ValueObject return; int count = count_sp->GetValueAsUnsigned(0); - tid_t tid = tid_sp->GetValueAsUnsigned(0); + tid_t tid = tid_sp->GetValueAsUnsigned(0) + 1; if (count <= 0) return; @@ -131,8 +146,9 @@ static void CreateHistoryThreadFromValueObject(ProcessSP process_sp, ValueObject HistoryThread *history_thread = new HistoryThread(*process_sp, tid, pcs, 0, false); ThreadSP new_thread_sp(history_thread); - // let's use thread name for the type of history thread, since history threads don't have names anyway - history_thread->SetThreadName(thread_name); + std::ostringstream thread_name_with_number; + thread_name_with_number << thread_name << " Thread " << tid; + history_thread->SetThreadName(thread_name_with_number.str().c_str()); // Save this in the Process' ExtendedThreadList so a strong pointer retains the object process_sp->GetExtendedThreadList().AddThread (new_thread_sp); result.push_back(new_thread_sp); @@ -146,38 +162,49 @@ MemoryHistoryASan::GetHistoryThreads(lldb::addr_t address) HistoryThreads result; ProcessSP process_sp = m_process_wp.lock(); - if (process_sp) - { - ThreadSP thread_sp = process_sp->GetThreadList().GetSelectedThread(); - - 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); - } - } - } - } + if (! process_sp) + return result; + + ThreadSP thread_sp = process_sp->GetThreadList().GetExpressionExecutionThread(); + if (!thread_sp) + return result; + + StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); + if (!frame_sp) + return result; + + ExecutionContext exe_ctx (frame_sp); + ValueObjectSP return_value_sp; + StreamString expr; + Error eval_error; + 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); + options.SetPrefix(memory_history_asan_command_prefix); + options.SetAutoApplyFixIts(false); + options.SetLanguage(eLanguageTypeObjC_plus_plus); + + ExpressionResults expr_result = UserExpression::Evaluate (exe_ctx, + options, + expr.GetData(), + "", + return_value_sp, + eval_error); + if (expr_result != eExpressionCompleted) { + process_sp->GetTarget().GetDebugger().GetAsyncOutputStream()->Printf("Warning: Cannot evaluate AddressSanitizer expression:\n%s\n", eval_error.AsCString()); + return result; } + + if (!return_value_sp) + return result; + + CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "free", "Memory deallocated by", result); + CreateHistoryThreadFromValueObject(process_sp, return_value_sp, "alloc", "Memory allocated by", result); + return result; } diff --git a/source/Plugins/ObjectContainer/BSD-Archive/Makefile b/source/Plugins/ObjectContainer/BSD-Archive/Makefile deleted file mode 100644 index 00c5911ea95f..000000000000 --- a/source/Plugins/ObjectContainer/BSD-Archive/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ObjectContainer/BSD-Archive/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginObjectContainerBSDArchive -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp index f2a74b05fe26..984a9ece12ef 100644 --- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp +++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp @@ -35,7 +35,6 @@ typedef struct ar_hdr #include "lldb/Core/PluginManager.h" #include "lldb/Core/Stream.h" #include "lldb/Core/Timer.h" -#include "lldb/Host/Mutex.h" #include "lldb/Symbol/ObjectFile.h" using namespace lldb; @@ -226,7 +225,7 @@ ObjectContainerBSDArchive::Archive::FindObject (const ConstString &object_name, ObjectContainerBSDArchive::Archive::shared_ptr ObjectContainerBSDArchive::Archive::FindCachedArchive (const FileSpec &file, const ArchSpec &arch, const TimeValue &time, lldb::offset_t file_offset) { - Mutex::Locker locker(Archive::GetArchiveCacheMutex ()); + std::lock_guard guard(Archive::GetArchiveCacheMutex()); shared_ptr archive_sp; Archive::Map &archive_map = Archive::GetArchiveCache (); Archive::Map::iterator pos = archive_map.find (file); @@ -281,7 +280,7 @@ ObjectContainerBSDArchive::Archive::ParseAndCacheArchiveForFile const size_t num_objects = archive_sp->ParseObjects (); if (num_objects > 0) { - Mutex::Locker locker(Archive::GetArchiveCacheMutex ()); + std::lock_guard guard(Archive::GetArchiveCacheMutex()); Archive::GetArchiveCache().insert(std::make_pair(file, archive_sp)); } else @@ -299,14 +298,13 @@ ObjectContainerBSDArchive::Archive::GetArchiveCache () return g_archive_map; } -Mutex & -ObjectContainerBSDArchive::Archive::GetArchiveCacheMutex () +std::recursive_mutex & +ObjectContainerBSDArchive::Archive::GetArchiveCacheMutex() { - static Mutex g_archive_map_mutex (Mutex::eMutexTypeRecursive); + static std::recursive_mutex g_archive_map_mutex; return g_archive_map_mutex; } - void ObjectContainerBSDArchive::Initialize() { diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h index cbb3848dc7cd..03b0bf3e2f09 100644 --- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h +++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h @@ -12,6 +12,8 @@ // C Includes // C++ Includes +#include + // Other libraries and framework includes // Project includes #include "lldb/Symbol/ObjectContainer.h" @@ -138,8 +140,8 @@ protected: static Map & GetArchiveCache (); - static lldb_private::Mutex & - GetArchiveCacheMutex (); + static std::recursive_mutex & + GetArchiveCacheMutex(); static Archive::shared_ptr FindCachedArchive (const lldb_private::FileSpec &file, diff --git a/source/Plugins/ObjectContainer/Universal-Mach-O/Makefile b/source/Plugins/ObjectContainer/Universal-Mach-O/Makefile deleted file mode 100644 index 957753527d24..000000000000 --- a/source/Plugins/ObjectContainer/Universal-Mach-O/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ObjectContainer/Universal-Mach-O/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginObjectContainerMachOArchive -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ObjectFile/ELF/ELFHeader.cpp b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp index 641a7cc3e0e2..625cce3c1062 100644 --- a/source/Plugins/ObjectFile/ELF/ELFHeader.cpp +++ b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp @@ -198,6 +198,9 @@ ELFHeader::GetRelocationJumpSlotType() const case EM_MIPS: slot = R_MIPS_JUMP_SLOT; break; + case EM_S390: + slot = R_390_JMP_SLOT; + break; } return slot; diff --git a/source/Plugins/ObjectFile/ELF/Makefile b/source/Plugins/ObjectFile/ELF/Makefile deleted file mode 100644 index 470660bb7861..000000000000 --- a/source/Plugins/ObjectFile/ELF/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ObjectFile/ELF/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginObjectFileELF -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index b16a2cda10f7..68e4e50a96e5 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -31,7 +31,9 @@ #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/ARMBuildAttributes.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/MipsABIFlags.h" #define CASE_AND_STREAM(s, def, width) \ case def: s->Printf("%-*s", width, #def); break; @@ -283,7 +285,7 @@ ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) } } - const char *cstr = data.GetCStr(offset, llvm::RoundUpToAlignment (n_namesz, 4)); + const char *cstr = data.GetCStr(offset, llvm::alignTo (n_namesz, 4)); if (cstr == NULL) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS)); @@ -729,7 +731,10 @@ ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file, SectionHeaderColl section_headers; lldb_private::UUID &uuid = spec.GetUUID(); - GetSectionHeaderInfo(section_headers, data, header, uuid, gnu_debuglink_file, gnu_debuglink_crc, spec.GetArchitecture ()); + using namespace std::placeholders; + const SetDataFunction set_data = std::bind(&ObjectFileELF::SetData, std::cref(data), _1, _2, _3); + GetSectionHeaderInfo(section_headers, set_data, header, uuid, gnu_debuglink_file, gnu_debuglink_crc, spec.GetArchitecture ()); + llvm::Triple &spec_triple = spec.GetArchitecture ().GetTriple (); @@ -759,7 +764,7 @@ ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file, data.SetData(data_sp); } ProgramHeaderColl program_headers; - GetProgramHeaderInfo(program_headers, data, header); + GetProgramHeaderInfo(program_headers, set_data, header); size_t segment_data_end = 0; for (ProgramHeaderCollConstIter I = program_headers.begin(); @@ -918,10 +923,14 @@ ObjectFileELF::SetLoadAddress (Target &target, // 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; + lldb::addr_t load_addr = section_sp->GetFileAddress(); + // We don't want to update the load address of a section with type + // eSectionTypeAbsoluteAddress as they already have the absolute load address + // already specified + if (section_sp->GetType() != eSectionTypeAbsoluteAddress) + load_addr += 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. @@ -1256,7 +1265,7 @@ ObjectFileELF::ParseDependentModules() //---------------------------------------------------------------------- size_t ObjectFileELF::GetProgramHeaderInfo(ProgramHeaderColl &program_headers, - DataExtractor &object_data, + const SetDataFunction &set_data, const ELFHeader &header) { // We have already parsed the program headers @@ -1274,7 +1283,7 @@ ObjectFileELF::GetProgramHeaderInfo(ProgramHeaderColl &program_headers, const size_t ph_size = header.e_phnum * header.e_phentsize; const elf_off ph_offset = header.e_phoff; DataExtractor data; - if (data.SetData(object_data, ph_offset, ph_size) != ph_size) + if (set_data(data, ph_offset, ph_size) != ph_size) return 0; uint32_t idx; @@ -1298,7 +1307,10 @@ ObjectFileELF::GetProgramHeaderInfo(ProgramHeaderColl &program_headers, size_t ObjectFileELF::ParseProgramHeaders() { - return GetProgramHeaderInfo(m_program_headers, m_data, m_header); + using namespace std::placeholders; + return GetProgramHeaderInfo(m_program_headers, + std::bind(&ObjectFileELF::SetDataWithReadMemoryFallback, this, _1, _2, _3), + m_header); } lldb_private::Error @@ -1400,8 +1412,9 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l // Only bother processing this if we don't already have the uuid set. if (!uuid.IsValid()) { - // 16 bytes is UUID|MD5, 20 bytes is SHA1 - if ((note.n_descsz == 16 || note.n_descsz == 20)) + // 16 bytes is UUID|MD5, 20 bytes is SHA1. Other linkers may produce a build-id of a different + // length. Accept it as long as it's at least 4 bytes as it will be better than our own crc32. + if (note.n_descsz >= 4 && note.n_descsz <= 20) { uint8_t uuidbuf[20]; if (data.GetU8 (&offset, &uuidbuf, note.n_descsz) == nullptr) @@ -1449,7 +1462,7 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l // this ELF targets. if(note.n_descsz) { - const char *cstr = data.GetCStr(&offset, llvm::RoundUpToAlignment (note.n_descsz, 4)); + const char *cstr = data.GetCStr(&offset, llvm::alignTo (note.n_descsz, 4)); (void)cstr; } } @@ -1505,13 +1518,87 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l return error; } +void +ObjectFileELF::ParseARMAttributes(DataExtractor &data, uint64_t length, ArchSpec &arch_spec) +{ + lldb::offset_t Offset = 0; + + uint8_t FormatVersion = data.GetU8(&Offset); + if (FormatVersion != llvm::ARMBuildAttrs::Format_Version) + return; + + Offset = Offset + sizeof(uint32_t); // Section Length + llvm::StringRef VendorName = data.GetCStr(&Offset); + + if (VendorName != "aeabi") + return; + + if (arch_spec.GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment) + arch_spec.GetTriple().setEnvironment(llvm::Triple::EABI); + + while (Offset < length) + { + uint8_t Tag = data.GetU8(&Offset); + uint32_t Size = data.GetU32(&Offset); + + if (Tag != llvm::ARMBuildAttrs::File || Size == 0) + continue; + + while (Offset < length) + { + uint64_t Tag = data.GetULEB128(&Offset); + switch (Tag) + { + default: + if (Tag < 32) + data.GetULEB128(&Offset); + else if (Tag % 2 == 0) + data.GetULEB128(&Offset); + else + data.GetCStr(&Offset); + + break; + + case llvm::ARMBuildAttrs::CPU_raw_name: + case llvm::ARMBuildAttrs::CPU_name: + data.GetCStr(&Offset); + + break; + + case llvm::ARMBuildAttrs::ABI_VFP_args: + { + uint64_t VFPArgs = data.GetULEB128(&Offset); + + if (VFPArgs == llvm::ARMBuildAttrs::BaseAAPCS) + { + if (arch_spec.GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment || + arch_spec.GetTriple().getEnvironment() == llvm::Triple::EABIHF) + arch_spec.GetTriple().setEnvironment(llvm::Triple::EABI); + + arch_spec.SetFlags(ArchSpec::eARM_abi_soft_float); + } + else if (VFPArgs == llvm::ARMBuildAttrs::HardFPAAPCS) + { + if (arch_spec.GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment || + arch_spec.GetTriple().getEnvironment() == llvm::Triple::EABI) + arch_spec.GetTriple().setEnvironment(llvm::Triple::EABIHF); + + arch_spec.SetFlags(ArchSpec::eARM_abi_hard_float); + } + + break; + } + } + } + } +} //---------------------------------------------------------------------- // GetSectionHeaderInfo //---------------------------------------------------------------------- size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers, - lldb_private::DataExtractor &object_data, + const SetDataFunction &set_data, const elf::ELFHeader &header, lldb_private::UUID &uuid, std::string &gnu_debuglink_file, @@ -1556,6 +1643,15 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers, } } + if (arch_spec.GetMachine() == llvm::Triple::arm || + arch_spec.GetMachine() == llvm::Triple::thumb) + { + if (header.e_flags & llvm::ELF::EF_ARM_SOFT_FLOAT) + arch_spec.SetFlags (ArchSpec::eARM_abi_soft_float); + else if (header.e_flags & llvm::ELF::EF_ARM_VFP_FLOAT) + arch_spec.SetFlags (ArchSpec::eARM_abi_hard_float); + } + // If there are no section headers we are done. if (header.e_shnum == 0) return 0; @@ -1569,7 +1665,7 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers, const size_t sh_size = header.e_shnum * header.e_shentsize; const elf_off sh_offset = header.e_shoff; DataExtractor sh_data; - if (sh_data.SetData (object_data, sh_offset, sh_size) != sh_size) + if (set_data (sh_data, sh_offset, sh_size) != sh_size) return 0; uint32_t idx; @@ -1590,7 +1686,7 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers, const Elf64_Off offset = sheader.sh_offset; lldb_private::DataExtractor shstr_data; - if (shstr_data.SetData (object_data, offset, byte_size) == byte_size) + if (set_data (shstr_data, offset, byte_size) == byte_size) { for (SectionHeaderCollIter I = section_headers.begin(); I != section_headers.end(); ++I) @@ -1602,40 +1698,93 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers, I->section_name = name; - 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 (arch_spec.IsMIPS()) { uint32_t arch_flags = arch_spec.GetFlags (); DataExtractor data; if (sheader.sh_type == SHT_MIPS_ABIFLAGS) { - if (section_size && (data.SetData (object_data, sheader.sh_offset, section_size) == section_size)) + if (section_size && (set_data (data, sheader.sh_offset, section_size) == section_size)) { - lldb::offset_t ase_offset = 12; // MIPS ABI Flags Version: 0 - arch_flags |= data.GetU32 (&ase_offset); + // MIPS ASE Mask is at offset 12 in MIPS.abiflags section + lldb::offset_t offset = 12; // MIPS ABI Flags Version: 0 + arch_flags |= data.GetU32 (&offset); + + // The floating point ABI is at offset 7 + offset = 7; + switch (data.GetU8 (&offset)) + { + case llvm::Mips::Val_GNU_MIPS_ABI_FP_ANY : + arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_ANY; + break; + case llvm::Mips::Val_GNU_MIPS_ABI_FP_DOUBLE : + arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_DOUBLE; + break; + case llvm::Mips::Val_GNU_MIPS_ABI_FP_SINGLE : + arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_SINGLE; + break; + case llvm::Mips::Val_GNU_MIPS_ABI_FP_SOFT : + arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT; + break; + case llvm::Mips::Val_GNU_MIPS_ABI_FP_OLD_64 : + arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_OLD_64; + break; + case llvm::Mips::Val_GNU_MIPS_ABI_FP_XX : + arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_XX; + break; + case llvm::Mips::Val_GNU_MIPS_ABI_FP_64 : + arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_64; + break; + case llvm::Mips::Val_GNU_MIPS_ABI_FP_64A : + arch_flags |= lldb_private::ArchSpec::eMIPS_ABI_FP_64A; + break; + } } } // Settings appropriate ArchSpec ABI Flags - if (header.e_flags & llvm::ELF::EF_MIPS_ABI2) + switch(header.e_flags & llvm::ELF::EF_MIPS_ABI) { - 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; + case llvm::ELF::EF_MIPS_ABI_O32: + arch_flags |= lldb_private::ArchSpec::eMIPSABI_O32; + break; + case EF_MIPS_ABI_O64: + arch_flags |= lldb_private::ArchSpec::eMIPSABI_O64; + break; + case EF_MIPS_ABI_EABI32: + arch_flags |= lldb_private::ArchSpec::eMIPSABI_EABI32; + break; + case EF_MIPS_ABI_EABI64: + arch_flags |= lldb_private::ArchSpec::eMIPSABI_EABI64; + break; + default: + // ABI Mask doesn't cover N32 and N64 ABI. + if (header.e_ident[EI_CLASS] == llvm::ELF::ELFCLASS64) + arch_flags |= lldb_private::ArchSpec::eMIPSABI_N64; + else if (header.e_flags && llvm::ELF::EF_MIPS_ABI2) + arch_flags |= lldb_private::ArchSpec::eMIPSABI_N32; + break; } arch_spec.SetFlags (arch_flags); } + if (arch_spec.GetMachine() == llvm::Triple::arm || arch_spec.GetMachine() == llvm::Triple::thumb) + { + DataExtractor data; + + if (sheader.sh_type == SHT_ARM_ATTRIBUTES && section_size != 0 && + set_data(data, sheader.sh_offset, section_size) == section_size) + ParseARMAttributes(data, section_size, arch_spec); + } + if (name == g_sect_name_gnu_debuglink) { DataExtractor data; - if (section_size && (data.SetData (object_data, sheader.sh_offset, section_size) == section_size)) + if (section_size && (set_data (data, sheader.sh_offset, section_size) == section_size)) { lldb::offset_t gnu_debuglink_offset = 0; gnu_debuglink_file = data.GetCStr (&gnu_debuglink_offset); - gnu_debuglink_offset = llvm::RoundUpToAlignment (gnu_debuglink_offset, 4); + gnu_debuglink_offset = llvm::alignTo (gnu_debuglink_offset, 4); data.GetU32 (&gnu_debuglink_offset, &gnu_debuglink_crc, 1); } } @@ -1653,7 +1802,7 @@ ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl §ion_headers, { // Allow notes to refine module info. DataExtractor data; - if (section_size && (data.SetData (object_data, sheader.sh_offset, section_size) == section_size)) + if (section_size && (set_data (data, sheader.sh_offset, section_size) == section_size)) { Error error = RefineModuleDetailsFromNote (data, arch_spec, uuid); if (error.Fail ()) @@ -1719,7 +1868,41 @@ ObjectFileELF::StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const size_t ObjectFileELF::ParseSectionHeaders() { - return GetSectionHeaderInfo(m_section_headers, m_data, m_header, m_uuid, m_gnu_debuglink_file, m_gnu_debuglink_crc, m_arch_spec); + using namespace std::placeholders; + + return GetSectionHeaderInfo(m_section_headers, + std::bind(&ObjectFileELF::SetDataWithReadMemoryFallback, this, _1, _2, _3), + m_header, + m_uuid, + m_gnu_debuglink_file, + m_gnu_debuglink_crc, + m_arch_spec); +} + +lldb::offset_t +ObjectFileELF::SetData(const lldb_private::DataExtractor &src, lldb_private::DataExtractor &dst, lldb::offset_t offset, lldb::offset_t length) +{ + return dst.SetData(src, offset, length); +} + +lldb::offset_t +ObjectFileELF::SetDataWithReadMemoryFallback(lldb_private::DataExtractor &dst, lldb::offset_t offset, lldb::offset_t length) +{ + if (offset + length <= m_data.GetByteSize()) + return dst.SetData(m_data, offset, length); + + const auto process_sp = m_process_wp.lock(); + if (process_sp != nullptr) + { + addr_t file_size = offset + length; + + DataBufferSP data_sp = ReadMemory(process_sp, m_memory_addr, file_size); + if (!data_sp) + return false; + m_data.SetData(data_sp, 0, file_size); + } + + return dst.SetData(m_data, offset, length); } const ObjectFileELF::ELFSectionHeaderInfo * @@ -1849,6 +2032,9 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list) else if (name == g_sect_name_arm_extab) sect_type = eSectionTypeARMextab; else if (name == g_sect_name_go_symtab) sect_type = eSectionTypeGoSymtab; + const uint32_t permissions = ((header.sh_flags & SHF_ALLOC) ? ePermissionsReadable : 0) | + ((header.sh_flags & SHF_WRITE) ? ePermissionsWritable : 0) | + ((header.sh_flags & SHF_EXECINSTR) ? ePermissionsExecutable : 0); switch (header.sh_type) { case SHT_SYMTAB: @@ -1900,6 +2086,7 @@ ObjectFileELF::CreateSections(SectionList &unified_section_list) header.sh_flags, // Flags for this section. target_bytes_size));// Number of host bytes per target byte + section_sp->SetPermissions(permissions); if (is_thread_specific) section_sp->SetIsThreadSpecific (is_thread_specific); m_sections_ap->AddSection(section_sp); @@ -1997,7 +2184,7 @@ ObjectFileELF::ParseSymbols (Symtab *symtab, static ConstString bss_section_name(".bss"); static ConstString opd_section_name(".opd"); // For ppc64 - // On Android the oatdata and the oatexec symbols in system@framework@boot.oat covers the full + // On Android the oatdata and the oatexec symbols in the oat and odex files covers the full // .text section what causes issues with displaying unusable symbol name to the user and very // slow unwinding speed because the instruction emulation based unwind plans try to emulate all // instructions in these symbols. Don't add these symbols to the symbol list as they have no @@ -2005,10 +2192,13 @@ ObjectFileELF::ParseSymbols (Symtab *symtab, // Filtering can't be restricted to Android because this special object file don't contain the // note section specifying the environment to Android but the custom extension and file name // makes it highly unlikely that this will collide with anything else. - bool skip_oatdata_oatexec = m_file.GetFilename() == ConstString("system@framework@boot.oat"); + ConstString file_extension = m_file.GetFileNameExtension(); + bool skip_oatdata_oatexec = file_extension == ConstString("oat") || file_extension == ConstString("odex"); ArchSpec arch; GetArchitecture(arch); + ModuleSP module_sp(GetModule()); + SectionList* module_section_list = module_sp ? module_sp->GetSectionList() : nullptr; // 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 @@ -2034,9 +2224,9 @@ ObjectFileELF::ParseSymbols (Symtab *symtab, SectionSP symbol_section_sp; SymbolType symbol_type = eSymbolTypeInvalid; - Elf64_Half symbol_idx = symbol.st_shndx; + Elf64_Half section_idx = symbol.st_shndx; - switch (symbol_idx) + switch (section_idx) { case SHN_ABS: symbol_type = eSymbolTypeAbsolute; @@ -2045,7 +2235,7 @@ ObjectFileELF::ParseSymbols (Symtab *symtab, symbol_type = eSymbolTypeUndefined; break; default: - symbol_section_sp = section_list->GetSectionAtIndex(symbol_idx); + symbol_section_sp = section_list->GetSectionAtIndex(section_idx); break; } @@ -2092,7 +2282,7 @@ ObjectFileELF::ParseSymbols (Symtab *symtab, } } - if (symbol_type == eSymbolTypeInvalid) + if (symbol_type == eSymbolTypeInvalid && symbol.getType() != STT_SECTION) { if (symbol_section_sp) { @@ -2229,30 +2419,44 @@ ObjectFileELF::ParseSymbols (Symtab *symtab, } } - // symbol_value_offset may contain 0 for ARM symbols or -1 for - // THUMB symbols. See above for more details. + // 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 == nullptr && section_idx == SHN_ABS && symbol.st_size != 0) + { + // We don't have a section for a symbol with non-zero size. Create a new section for it + // so the address range covered by the symbol is also covered by the module (represented + // through the section list). It is needed so module lookup for the addresses covered + // by this symbol will be successfull. This case happens for absolute symbols. + ConstString fake_section_name(std::string(".absolute.") + symbol_name); + symbol_section_sp = std::make_shared
(module_sp, + this, + SHN_ABS, + fake_section_name, + eSectionTypeAbsoluteAddress, + symbol_value, + symbol.st_size, + 0, 0, 0, + SHF_ALLOC); + + module_section_list->AddSection(symbol_section_sp); + section_list->AddSection(symbol_section_sp); + } + if (symbol_section_sp && CalculateType() != ObjectFile::Type::eTypeObjectFile) symbol_value -= symbol_section_sp->GetFileAddress(); - if (symbol_section_sp) + if (symbol_section_sp && module_section_list && module_section_list != section_list) { - ModuleSP module_sp(GetModule()); - if (module_sp) - { - SectionList *module_section_list = module_sp->GetSectionList(); - if (module_section_list && module_section_list != section_list) - { - const ConstString §_name = symbol_section_sp->GetName(); - 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; - } - } + const ConstString §_name = symbol_section_sp->GetName(); + 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; } bool is_global = symbol.getBinding() == STB_GLOBAL; @@ -2283,6 +2487,12 @@ ObjectFileELF::ParseSymbols (Symtab *symtab, mangled.SetDemangledName( ConstString((demangled_name + suffix).str()) ); } + // In ELF all symbol should have a valid size but it is not true for some function symbols + // coming from hand written assembly. As none of the function symbol should have 0 size we + // try to calculate the size for these symbols in the symtab with saying that their original + // size is not valid. + bool symbol_size_valid = symbol.st_size != 0 || symbol.getType() != STT_FUNC; + Symbol dc_symbol( i + start_id, // ID is the original symbol table index. mangled, @@ -2295,7 +2505,7 @@ ObjectFileELF::ParseSymbols (Symtab *symtab, symbol_section_sp, // Section in which this symbol is defined or null. symbol_value, // Offset in section or symbol value. symbol.st_size), // Size in bytes of this symbol. - symbol.st_size != 0, // Size is valid if it is not 0 + symbol_size_valid, // Symbol size is valid has_suffix, // Contains linker annotations? flags); // Symbol flags. symtab->AddSymbol(dc_symbol); @@ -2304,7 +2514,9 @@ ObjectFileELF::ParseSymbols (Symtab *symtab, } unsigned -ObjectFileELF::ParseSymbolTable(Symtab *symbol_table, user_id_t start_id, lldb_private::Section *symtab) +ObjectFileELF::ParseSymbolTable(Symtab *symbol_table, + user_id_t start_id, + lldb_private::Section *symtab) { if (symtab->GetObjectFile() != this) { @@ -2430,9 +2642,12 @@ GetPltEntrySizeAndOffset(const ELFSectionHeader* rel_hdr, const ELFSectionHeader // Clang 3.3 sets entsize to 4 for 32-bit binaries, but the plt entries are 16 bytes. // So round the entsize up by the alignment if addralign is set. elf_xword plt_entsize = plt_hdr->sh_addralign ? - llvm::RoundUpToAlignment (plt_hdr->sh_entsize, plt_hdr->sh_addralign) : plt_hdr->sh_entsize; + llvm::alignTo (plt_hdr->sh_entsize, plt_hdr->sh_addralign) : plt_hdr->sh_entsize; - if (plt_entsize == 0) + // Some linkers e.g ld for arm, fill plt_hdr->sh_entsize field incorrectly. + // PLT entries relocation code in general requires multiple instruction and + // should be greater than 4 bytes in most cases. Try to guess correct size just in case. + if (plt_entsize <= 4) { // 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 @@ -2533,17 +2748,17 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table, { assert(rel_hdr->sh_type == SHT_RELA || rel_hdr->sh_type == SHT_REL); - // The link field points to the associated symbol table. The info field - // points to the section holding the plt. + // The link field points to the associated symbol table. user_id_t symtab_id = rel_hdr->sh_link; - user_id_t plt_id = rel_hdr->sh_info; // If the link field doesn't point to the appropriate symbol name table then // try to find it by name as some compiler don't fill in the link fields. if (!symtab_id) symtab_id = GetSectionIndexByName(".dynsym"); - if (!plt_id) - plt_id = GetSectionIndexByName(".plt"); + + // Get PLT section. We cannot use rel_hdr->sh_info, since current linkers + // point that to the .got.plt or .got section instead of .plt. + user_id_t plt_id = GetSectionIndexByName(".plt"); if (!symtab_id || !plt_id) return 0; @@ -2760,7 +2975,7 @@ ObjectFileELF::GetSymtab() return NULL; uint64_t symbol_id = 0; - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard guard(module_sp->GetMutex()); // Sharable objects and dynamic executables usually have 2 distinct symbol // tables, one named ".symtab", and the other ".dynsym". The dynsym is a smaller @@ -2806,6 +3021,14 @@ ObjectFileELF::GetSymtab() } } + DWARFCallFrameInfo* eh_frame = GetUnwindTable().GetEHFrameInfo(); + if (eh_frame) + { + if (m_symtab_ap == nullptr) + m_symtab_ap.reset(new Symtab(this)); + ParseUnwindSymbols (m_symtab_ap.get(), eh_frame); + } + // 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) @@ -2835,57 +3058,64 @@ ObjectFileELF::GetSymtab() return m_symtab_ap.get(); } -Symbol * -ObjectFileELF::ResolveSymbolForAddress(const Address& so_addr, bool verify_unique) +void +ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table, DWARFCallFrameInfo* eh_frame) { - if (!m_symtab_ap.get()) - return nullptr; // GetSymtab() should be called first. - - const SectionList *section_list = GetSectionList(); + SectionList* section_list = GetSectionList(); if (!section_list) - return nullptr; + return; - if (DWARFCallFrameInfo *eh_frame = GetUnwindTable().GetEHFrameInfo()) - { - AddressRange range; - if (eh_frame->GetAddressRange (so_addr, range)) + // First we save the new symbols into a separate list and add them to the symbol table after + // we colleced all symbols we want to add. This is neccessary because adding a new symbol + // invalidates the internal index of the symtab what causing the next lookup to be slow because + // it have to recalculate the index first. + std::vector new_symbols; + + eh_frame->ForEachFDEEntries( + [this, symbol_table, section_list, &new_symbols](lldb::addr_t file_addr, + uint32_t size, + dw_offset_t) { + Symbol* symbol = symbol_table->FindSymbolAtFileAddress(file_addr); + if (symbol) { - const addr_t file_addr = range.GetBaseAddress().GetFileAddress(); - Symbol * symbol = verify_unique ? m_symtab_ap->FindSymbolContainingFileAddress(file_addr) : nullptr; - if (symbol) - return symbol; - - // Note that a (stripped) symbol won't be found by GetSymtab()... - lldb::SectionSP eh_sym_section_sp = section_list->FindSectionContainingFileAddress(file_addr); - if (eh_sym_section_sp.get()) + if (!symbol->GetByteSizeIsValid()) { - addr_t section_base = eh_sym_section_sp->GetFileAddress(); - addr_t offset = file_addr - section_base; - uint64_t symbol_id = m_symtab_ap->GetNumSymbols(); - + symbol->SetByteSize(size); + symbol->SetSizeIsSynthesized(true); + } + } + else + { + SectionSP section_sp = section_list->FindSectionContainingFileAddress(file_addr); + if (section_sp) + { + addr_t offset = file_addr - section_sp->GetFileAddress(); + const char* symbol_name = GetNextSyntheticSymbolName().GetCString(); + uint64_t symbol_id = symbol_table->GetNumSymbols(); Symbol eh_symbol( - symbol_id, // Symbol table index. - "???", // Symbol name. - false, // Is the symbol name mangled? - eSymbolTypeCode, // Type of this symbol. - true, // Is this globally visible? - false, // Is this symbol debug info? - false, // Is this symbol a trampoline? - true, // Is this symbol artificial? - eh_sym_section_sp, // Section in which this symbol is defined or null. - offset, // Offset in section or symbol value. - range.GetByteSize(), // Size in bytes of this symbol. - true, // Size is valid. - false, // Contains linker annotations? - 0); // Symbol flags. - if (symbol_id == m_symtab_ap->AddSymbol(eh_symbol)) - return m_symtab_ap->SymbolAtIndex(symbol_id); + symbol_id, // Symbol table index. + symbol_name, // Symbol name. + false, // Is the symbol name mangled? + eSymbolTypeCode, // Type of this symbol. + true, // Is this globally visible? + false, // Is this symbol debug info? + false, // Is this symbol a trampoline? + true, // Is this symbol artificial? + section_sp, // Section in which this symbol is defined or null. + offset, // Offset in section or symbol value. + 0, // Size: Don't specify the size as an FDE can + false, // Size is valid: cover multiple symbols. + false, // Contains linker annotations? + 0); // Symbol flags. + new_symbols.push_back(eh_symbol); } } - } - return nullptr; -} + return true; + }); + for (const Symbol& s : new_symbols) + symbol_table->AddSymbol(s); +} bool ObjectFileELF::IsStripped () @@ -2903,6 +3133,22 @@ ObjectFileELF::IsStripped () void ObjectFileELF::Dump(Stream *s) { + ModuleSP module_sp(GetModule()); + if (!module_sp) + { + return; + } + + std::lock_guard guard(module_sp->GetMutex()); + s->Printf("%p: ", static_cast(this)); + s->Indent(); + s->PutCString("ObjectFileELF"); + + ArchSpec header_arch; + GetArchitecture(header_arch); + + *s << ", file = '" << m_file << "', arch = " << header_arch.GetArchitectureName() << "\n"; + DumpELFHeader(s, m_header); s->EOL(); DumpELFProgramHeaders(s); diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index 4b97f92c6c5c..e2f73f53ec63 100644 --- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -14,6 +14,7 @@ #include // C++ Includes +#include #include // Other libraries and framework includes @@ -56,7 +57,7 @@ struct ELFNote size_t GetByteSize() const { - return 12 + llvm::RoundUpToAlignment (n_namesz, 4) + llvm::RoundUpToAlignment (n_descsz, 4); + return 12 + llvm::alignTo (n_namesz, 4) + llvm::alignTo (n_descsz, 4); } }; @@ -149,9 +150,6 @@ public: lldb_private::Symtab * GetSymtab() override; - lldb_private::Symbol * - ResolveSymbolForAddress(const lldb_private::Address& so_addr, bool verify_unique) override; - bool IsStripped () override; @@ -231,6 +229,7 @@ private: typedef DynamicSymbolColl::const_iterator DynamicSymbolCollConstIter; typedef std::map FileAddressToAddressClassMap; + typedef std::function SetDataFunction; /// Version of this reader common to all plugins based on this class. static const uint32_t m_plugin_version = 1; @@ -279,7 +278,7 @@ private: // Parses the ELF program headers. static size_t GetProgramHeaderInfo(ProgramHeaderColl &program_headers, - lldb_private::DataExtractor &data, + const SetDataFunction &set_data, const elf::ELFHeader &header); // Finds PT_NOTE segments and calculates their crc sum. @@ -299,10 +298,14 @@ private: size_t ParseSectionHeaders(); + static void + ParseARMAttributes(lldb_private::DataExtractor &data, uint64_t length, + lldb_private::ArchSpec &arch_spec); + /// Parses the elf section headers and returns the uuid, debug link name, crc, archspec. static size_t GetSectionHeaderInfo(SectionHeaderColl §ion_headers, - lldb_private::DataExtractor &data, + const SetDataFunction &set_data, const elf::ELFHeader &header, lldb_private::UUID &uuid, std::string &gnu_debuglink_file, @@ -347,6 +350,10 @@ private: const ELFSectionHeaderInfo *rela_hdr, lldb::user_id_t section_id); + void + ParseUnwindSymbols(lldb_private::Symtab *symbol_table, + lldb_private::DWARFCallFrameInfo* eh_frame); + /// Relocates debug sections unsigned RelocateDebugSections(const elf::ELFSectionHeader *rel_hdr, lldb::user_id_t rel_id); @@ -437,6 +444,13 @@ private: static lldb_private::Error RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, lldb_private::ArchSpec &arch_spec, lldb_private::UUID &uuid); + + + static lldb::offset_t + SetData(const lldb_private::DataExtractor &src, lldb_private::DataExtractor &dst, lldb::offset_t offset, lldb::offset_t length); + + lldb::offset_t + SetDataWithReadMemoryFallback(lldb_private::DataExtractor &dst, lldb::offset_t offset, lldb::offset_t length); }; #endif // liblldb_ObjectFileELF_h_ diff --git a/source/Plugins/ObjectFile/JIT/Makefile b/source/Plugins/ObjectFile/JIT/Makefile deleted file mode 100644 index 2af3521777a1..000000000000 --- a/source/Plugins/ObjectFile/JIT/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ObjectFile/JIT/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginObjectFileJIT -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp index 3103ed8fb8fe..e3d838333711 100644 --- a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp +++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp @@ -158,11 +158,11 @@ ObjectFileJIT::GetSymtab() ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard guard(module_sp->GetMutex()); if (m_symtab_ap.get() == NULL) { m_symtab_ap.reset(new Symtab(this)); - Mutex::Locker symtab_locker (m_symtab_ap->GetMutex()); + std::lock_guard symtab_guard(m_symtab_ap->GetMutex()); ObjectFileJITDelegateSP delegate_sp (m_delegate_wp.lock()); if (delegate_sp) delegate_sp->PopulateSymtab(this, *m_symtab_ap); @@ -200,7 +200,7 @@ ObjectFileJIT::Dump (Stream *s) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard guard(module_sp->GetMutex()); s->Printf("%p: ", static_cast(this)); s->Indent(); s->PutCString("ObjectFileJIT"); diff --git a/source/Plugins/ObjectFile/Mach-O/Makefile b/source/Plugins/ObjectFile/Mach-O/Makefile deleted file mode 100644 index 2fab0238e411..000000000000 --- a/source/Plugins/ObjectFile/Mach-O/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ObjectFile/Mach-O/Makefile -----------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginObjectFileMachO -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index 9c1e17782508..5f8242211b7f 100644 --- a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -541,6 +541,7 @@ public: lldb::offset_t next_thread_state = offset + (count * 4); switch (flavor) { + case GPRAltRegSet: case GPRRegSet: for (uint32_t i=0; iGetMutex()); + std::lock_guard guard(module_sp->GetMutex()); bool can_parse = false; lldb::offset_t offset = 0; m_data.SetByteOrder (endian::InlHostByteOrder()); @@ -1387,6 +1392,7 @@ ObjectFileMachO::GetAddressClass (lldb::addr_t file_addr) case eSectionTypeCompactUnwind: return eAddressClassRuntime; + case eSectionTypeAbsoluteAddress: case eSectionTypeELFSymbolTable: case eSectionTypeELFDynamicSymbols: case eSectionTypeELFRelocationEntries: @@ -1451,11 +1457,11 @@ ObjectFileMachO::GetSymtab() ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard guard(module_sp->GetMutex()); if (m_symtab_ap.get() == NULL) { m_symtab_ap.reset(new Symtab(this)); - Mutex::Locker symtab_locker (m_symtab_ap->GetMutex()); + std::lock_guard symtab_guard(m_symtab_ap->GetMutex()); ParseSymtab (); m_symtab_ap->Finalize (); } @@ -1619,6 +1625,10 @@ ObjectFileMachO::CreateSections (SectionList &unified_section_list) } if (m_data.GetU32(&offset, &load_cmd.maxprot, 4)) { + const uint32_t segment_permissions = + ((load_cmd.initprot & VM_PROT_READ) ? ePermissionsReadable : 0) | + ((load_cmd.initprot & VM_PROT_WRITE) ? ePermissionsWritable : 0) | + ((load_cmd.initprot & VM_PROT_EXECUTE) ? ePermissionsExecutable : 0); const bool segment_is_encrypted = (load_cmd.flags & SG_PROTECTED_VERSION_1) != 0; @@ -1645,6 +1655,7 @@ ObjectFileMachO::CreateSections (SectionList &unified_section_list) segment_sp->SetIsEncrypted (segment_is_encrypted); m_sections_ap->AddSection(segment_sp); + segment_sp->SetPermissions(segment_permissions); if (add_to_unified) unified_section_list.AddSection(segment_sp); } @@ -1776,7 +1787,7 @@ ObjectFileMachO::CreateSections (SectionList &unified_section_list) sect64.align, load_cmd.flags)); // Flags for this section segment_sp->SetIsFake(true); - + segment_sp->SetPermissions(segment_permissions); m_sections_ap->AddSection(segment_sp); if (add_to_unified) unified_section_list.AddSection(segment_sp); @@ -1926,6 +1937,7 @@ ObjectFileMachO::CreateSections (SectionList &unified_section_list) section_is_encrypted = encrypted_file_ranges.FindEntryThatContains(sect64.offset) != NULL; section_sp->SetIsEncrypted (segment_is_encrypted || section_is_encrypted); + section_sp->SetPermissions(segment_permissions); segment_sp->GetChildren().AddSection(section_sp); if (segment_sp->IsFake()) @@ -2601,6 +2613,23 @@ ObjectFileMachO::ParseSymtab () const size_t function_starts_count = function_starts.GetSize(); + // For user process binaries (executables, dylibs, frameworks, bundles), if we don't have + // LC_FUNCTION_STARTS/eh_frame section in this binary, we're going to assume the binary + // has been stripped. Don't allow assembly language instruction emulation because we don't + // know proper function start boundaries. + // + // For all other types of binaries (kernels, stand-alone bare board binaries, kexts), they + // may not have LC_FUNCTION_STARTS / eh_frame sections - we should not make any assumptions + // about them based on that. + if (function_starts_count == 0 && CalculateStrata() == eStrataUser) + { + m_allow_assembly_emulation_unwind_plans = false; + Log *unwind_or_symbol_log (lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_SYMBOLS | LIBLLDB_LOG_UNWIND)); + + if (unwind_or_symbol_log) + module_sp->LogMessage(unwind_or_symbol_log, "no LC_FUNCTION_STARTS, will not allow assembly profiled unwinds"); + } + const user_id_t TEXT_eh_frame_sectID = eh_frame_section_sp.get() ? eh_frame_section_sp->GetID() : static_cast(NO_SECT); @@ -3078,7 +3107,7 @@ ObjectFileMachO::ParseSymtab () { // This is usually the second N_SO entry that contains just the filename, // so here we combine it with the first one if we are minimizing the symbol table - const char *so_path = sym[sym_idx - 1].GetMangled().GetDemangledName().AsCString(); + const char *so_path = sym[sym_idx - 1].GetMangled().GetDemangledName(lldb::eLanguageTypeUnknown).AsCString(); if (so_path && so_path[0]) { std::string full_so_path (so_path); @@ -3465,7 +3494,7 @@ ObjectFileMachO::ParseSymtab () sym[sym_idx].GetMangled().SetValue(const_symbol_name, symbol_name_is_mangled); if (is_gsym && is_debug) { - const char *gsym_name = sym[sym_idx].GetMangled().GetName(Mangled::ePreferMangled).GetCString(); + const char *gsym_name = sym[sym_idx].GetMangled().GetName(lldb::eLanguageTypeUnknown, Mangled::ePreferMangled).GetCString(); if (gsym_name) N_GSYM_name_to_sym_idx[gsym_name] = sym_idx; } @@ -3539,7 +3568,7 @@ ObjectFileMachO::ParseSymtab () bool found_it = false; for (ValueToSymbolIndexMap::const_iterator pos = range.first; pos != range.second; ++pos) { - if (sym[sym_idx].GetMangled().GetName(Mangled::ePreferMangled) == sym[pos->second].GetMangled().GetName(Mangled::ePreferMangled)) + if (sym[sym_idx].GetMangled().GetName(lldb::eLanguageTypeUnknown, Mangled::ePreferMangled) == sym[pos->second].GetMangled().GetName(lldb::eLanguageTypeUnknown, Mangled::ePreferMangled)) { m_nlist_idx_to_sym_idx[nlist_idx] = pos->second; // We just need the flags from the linker symbol, so put these flags @@ -3578,7 +3607,7 @@ ObjectFileMachO::ParseSymtab () bool found_it = false; for (ValueToSymbolIndexMap::const_iterator pos = range.first; pos != range.second; ++pos) { - if (sym[sym_idx].GetMangled().GetName(Mangled::ePreferMangled) == sym[pos->second].GetMangled().GetName(Mangled::ePreferMangled)) + if (sym[sym_idx].GetMangled().GetName(lldb::eLanguageTypeUnknown, Mangled::ePreferMangled) == sym[pos->second].GetMangled().GetName(lldb::eLanguageTypeUnknown, Mangled::ePreferMangled)) { m_nlist_idx_to_sym_idx[nlist_idx] = pos->second; // We just need the flags from the linker symbol, so put these flags @@ -3595,7 +3624,7 @@ ObjectFileMachO::ParseSymtab () } else { - const char *gsym_name = sym[sym_idx].GetMangled().GetName(Mangled::ePreferMangled).GetCString(); + const char *gsym_name = sym[sym_idx].GetMangled().GetName(lldb::eLanguageTypeUnknown, Mangled::ePreferMangled).GetCString(); if (gsym_name) { // Combine N_GSYM stab entries with the non stab symbol @@ -4089,7 +4118,7 @@ ObjectFileMachO::ParseSymtab () case N_ECOML: // end common (local name): 0,,n_sect,0,address symbol_section = section_info.GetSection (nlist.n_sect, nlist.n_value); - // Fall through + LLVM_FALLTHROUGH; case N_ECOMM: // end common: name,,n_sect,0,0 @@ -4145,7 +4174,8 @@ ObjectFileMachO::ParseSymtab () ConstString undefined_name(symbol_name + ((symbol_name[0] == '_') ? 1 : 0)); undefined_name_to_desc[undefined_name] = nlist.n_desc; } - // Fall through + LLVM_FALLTHROUGH; + case N_PBUD: type = eSymbolTypeUndefined; break; @@ -4516,7 +4546,6 @@ ObjectFileMachO::ParseSymtab () if (function_starts_count > 0) { - char synthetic_function_symbol[PATH_MAX]; uint32_t num_synthetic_function_symbols = 0; for (i=0; iResize (num_syms); } - uint32_t synthetic_function_symbol_idx = 0; for (i=0; iGetFileSpec().GetFilename().GetCString()); sym[sym_idx].SetID (synthetic_sym_id++); - sym[sym_idx].GetMangled().SetDemangledName(ConstString(synthetic_function_symbol)); + sym[sym_idx].GetMangled().SetDemangledName(GetNextSyntheticSymbolName()); sym[sym_idx].SetType (eSymbolTypeCode); sym[sym_idx].SetIsSynthetic (true); sym[sym_idx].GetAddressRef() = symbol_addr; @@ -4743,7 +4766,7 @@ ObjectFileMachO::Dump (Stream *s) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard guard(module_sp->GetMutex()); s->Printf("%p: ", static_cast(this)); s->Indent(); if (m_header.magic == MH_MAGIC_64 || m_header.magic == MH_CIGAM_64) @@ -4827,9 +4850,22 @@ ObjectFileMachO::GetArchitecture (const llvm::MachO::mach_header &header, if (header.filetype == MH_PRELOAD) { - // Set vendor to an unspecified unknown or a "*" so it can match any vendor - triple.setVendor(llvm::Triple::UnknownVendor); - triple.setVendorName(llvm::StringRef()); + if (header.cputype == CPU_TYPE_ARM) + { + // If this is a 32-bit arm binary, and it's a standalone binary, + // force the Vendor to Apple so we don't accidentally pick up + // the generic armv7 ABI at runtime. Apple's armv7 ABI always uses + // r7 for the frame pointer register; most other armv7 ABIs use a + // combination of r7 and r11. + triple.setVendor(llvm::Triple::Apple); + } + else + { + // Set vendor to an unspecified unknown or a "*" so it can match any vendor + // This is required for correct behavior of EFI debugging on x86_64 + triple.setVendor(llvm::Triple::UnknownVendor); + triple.setVendorName(llvm::StringRef()); + } return true; } else @@ -4886,7 +4922,7 @@ ObjectFileMachO::GetUUID (lldb_private::UUID* uuid) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard guard(module_sp->GetMutex()); lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); return GetUUID (m_header, m_data, offset, *uuid); } @@ -4900,7 +4936,7 @@ ObjectFileMachO::GetDependentModules (FileSpecList& files) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard guard(module_sp->GetMutex()); struct load_command load_cmd; lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); std::vector rpath_paths; @@ -5028,7 +5064,7 @@ ObjectFileMachO::GetEntryPointAddress () ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard guard(module_sp->GetMutex()); struct load_command load_cmd; lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); uint32_t i; @@ -5059,7 +5095,7 @@ ObjectFileMachO::GetEntryPointAddress () switch (m_header.cputype) { case llvm::MachO::CPU_TYPE_ARM: - if (flavor == 1) // ARM_THREAD_STATE from mach/arm/thread_status.h + if (flavor == 1 || flavor == 9) // ARM_THREAD_STATE/ARM_THREAD_STATE32 from mach/arm/thread_status.h { offset += 60; // This is the offset of pc in the GPR thread state data structure. start_address = m_data.GetU32(&offset); @@ -5111,6 +5147,7 @@ ObjectFileMachO::GetEntryPointAddress () start_address = text_segment_sp->GetFileAddress() + entryoffset; } } + break; default: break; @@ -5177,7 +5214,7 @@ ObjectFileMachO::GetNumThreadContexts () ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard guard(module_sp->GetMutex()); if (!m_thread_context_offsets_valid) { m_thread_context_offsets_valid = true; @@ -5211,7 +5248,7 @@ ObjectFileMachO::GetThreadContextAtIndex (uint32_t idx, lldb_private::Thread &th ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard guard(module_sp->GetMutex()); if (!m_thread_context_offsets_valid) GetNumThreadContexts (); @@ -5347,7 +5384,7 @@ ObjectFileMachO::GetVersion (uint32_t *versions, uint32_t num_versions) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard guard(module_sp->GetMutex()); struct dylib_command load_cmd; lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); uint32_t version_cmd = 0; @@ -5402,7 +5439,7 @@ ObjectFileMachO::GetArchitecture (ArchSpec &arch) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard guard(module_sp->GetMutex()); return GetArchitecture (m_header, m_data, MachHeaderSizeFromMagic(m_header.magic), arch); } return false; @@ -5614,6 +5651,12 @@ ObjectFileMachO::GetIsDynamicLinkEditor() return m_header.filetype == llvm::MachO::MH_DYLINKER; } +bool +ObjectFileMachO::AllowAssemblyEmulationUnwindPlans () +{ + return m_allow_assembly_emulation_unwind_plans; +} + //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h index 6b7ad531b83b..251a0865e782 100644 --- a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h +++ b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h @@ -19,7 +19,6 @@ #include "lldb/Core/FileSpecList.h" #include "lldb/Core/RangeMap.h" #include "lldb/Host/FileSpec.h" -#include "lldb/Host/Mutex.h" #include "lldb/Symbol/ObjectFile.h" //---------------------------------------------------------------------- @@ -176,6 +175,9 @@ public: lldb::offset_t *data_offset_ptr, llvm::MachO::mach_header &header); + bool + AllowAssemblyEmulationUnwindPlans () override; + //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ @@ -247,6 +249,7 @@ protected: FileRangeArray m_thread_context_offsets; bool m_thread_context_offsets_valid; lldb_private::FileSpecList m_reexported_dylibs; + bool m_allow_assembly_emulation_unwind_plans; }; #endif // liblldb_ObjectFileMachO_h_ diff --git a/source/Plugins/ObjectFile/PECOFF/Makefile b/source/Plugins/ObjectFile/PECOFF/Makefile deleted file mode 100644 index 1b5abc461e82..000000000000 --- a/source/Plugins/ObjectFile/PECOFF/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ObjectFile/PECOFF/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginObjectFilePECOFF -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp index ccd4400995c7..5f5a0ab07ad6 100644 --- a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -192,7 +192,8 @@ ObjectFilePECOFF::ObjectFilePECOFF (const lldb::ModuleSP &module_sp, m_dos_header (), m_coff_header (), m_coff_header_opt (), - m_sect_headers () + m_sect_headers (), + m_entry_point_address () { ::memset (&m_dos_header, 0, sizeof(m_dos_header)); ::memset (&m_coff_header, 0, sizeof(m_coff_header)); @@ -211,7 +212,7 @@ ObjectFilePECOFF::ParseHeader () ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard guard(module_sp->GetMutex()); m_sect_headers.clear(); m_data.SetByteOrder (eByteOrderLittle); lldb::offset_t offset = 0; @@ -533,13 +534,13 @@ ObjectFilePECOFF::GetSymtab() ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard guard(module_sp->GetMutex()); if (m_symtab_ap.get() == NULL) { SectionList *sect_list = GetSectionList(); m_symtab_ap.reset(new Symtab(this)); - Mutex::Locker symtab_locker (m_symtab_ap->GetMutex()); - + std::lock_guard guard(m_symtab_ap->GetMutex()); + const uint32_t num_syms = m_coff_header.nsyms; if (num_syms > 0 && m_coff_header.symoff > 0) @@ -662,6 +663,7 @@ ObjectFilePECOFF::GetSymtab() symbols[i].SetDebug(true); } } + m_symtab_ap->CalculateSymbolSizes(); } } return m_symtab_ap.get(); @@ -687,7 +689,7 @@ ObjectFilePECOFF::CreateSections (SectionList &unified_section_list) ModuleSP module_sp(GetModule()); if (module_sp) { - lldb_private::Mutex::Locker locker(module_sp->GetMutex()); + std::lock_guard guard(module_sp->GetMutex()); const uint32_t nsects = m_sect_headers.size(); ModuleSP module_sp (GetModule()); for (uint32_t idx = 0; idxGetMutex()); + std::lock_guard guard(module_sp->GetMutex()); s->Printf("%p: ", static_cast(this)); s->Indent(); s->PutCString("ObjectFilePECOFF"); diff --git a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h index 44e5ee1b044b..6c1cdbf56c6b 100644 --- a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h +++ b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h @@ -144,8 +144,8 @@ public: uint32_t GetDependentModules(lldb_private::FileSpecList& files) override; -// virtual lldb_private::Address -// GetEntryPointAddress (); + virtual lldb_private::Address + GetEntryPointAddress () override; ObjectFile::Type CalculateType() override; @@ -301,6 +301,7 @@ private: coff_opt_header_t m_coff_header_opt; SectionHeaderColl m_sect_headers; lldb::addr_t m_image_base; + lldb_private::Address m_entry_point_address; }; #endif // liblldb_ObjectFilePECOFF_h_ diff --git a/source/Plugins/OperatingSystem/Go/Makefile b/source/Plugins/OperatingSystem/Go/Makefile deleted file mode 100644 index 7d06d483d3ae..000000000000 --- a/source/Plugins/OperatingSystem/Go/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##==- source/Plugins/OperatingSystem/Go/Makefile --------*- Makefile -*-==## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginOSGo -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp b/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp index 86c574f2776c..ec0b7014d4d4 100644 --- a/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp +++ b/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp @@ -197,7 +197,7 @@ OperatingSystemGo::CreateInstance(Process *process, bool force) if (!target_sp) return nullptr; ModuleList &module_list = target_sp->GetImages(); - Mutex::Locker modules_locker(module_list.GetMutex()); + std::lock_guard guard(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) @@ -249,8 +249,19 @@ OperatingSystemGo::Init(ThreadList &threads) 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"); + // Go 1.6 stores goroutines in a slice called runtime.allgs + ValueObjectSP allgs_sp = FindGlobal(target_sp, "runtime.allgs"); + if (allgs_sp) + { + m_allg_sp = allgs_sp->GetChildMemberWithName(ConstString("array"), true); + m_allglen_sp = allgs_sp->GetChildMemberWithName(ConstString("len"), true); + } + else + { + // Go 1.4 stores goroutines in the variable runtime.allg. + m_allg_sp = FindGlobal(target_sp, "runtime.allg"); + m_allglen_sp = FindGlobal(target_sp, "runtime.allglen"); + } if (m_allg_sp && !m_allglen_sp) { @@ -506,7 +517,7 @@ OperatingSystemGo::Goroutine OperatingSystemGo::CreateGoroutineAtIndex(uint64_t idx, Error &err) { err.Clear(); - Goroutine result; + Goroutine result = {}; ValueObjectSP g = m_allg_sp->GetSyntheticArrayMember(idx, true)->Dereference(err); if (err.Fail()) { diff --git a/source/Plugins/OperatingSystem/Python/Makefile b/source/Plugins/OperatingSystem/Python/Makefile deleted file mode 100644 index 67cd0acd7038..000000000000 --- a/source/Plugins/OperatingSystem/Python/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##==- source/Plugins/OperatingSystem/Python/Makefile --------*- Makefile -*-==## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginOSPython -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp index a556b0e84e83..dfb631e399f1 100644 --- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp +++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp @@ -183,16 +183,16 @@ OperatingSystemPython::UpdateThreadList (ThreadList &old_thread_list, // This is a recursive lock so we can grant it to any Python code called on // the stack below us. Target &target = m_process->GetTarget(); - Mutex::Locker api_locker; - api_locker.TryLock(target.GetAPIMutex()); - + std::unique_lock lock(target.GetAPIMutex(), std::defer_lock); + lock.try_lock(); + if (log) log->Printf ("OperatingSystemPython::UpdateThreadList() fetching thread data from python for pid %" PRIu64, m_process->GetID()); // 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. - - auto lock = m_interpreter->AcquireInterpreterLock(); // to make sure threads_list stays alive + + auto interpreter_lock = m_interpreter->AcquireInterpreterLock(); // to make sure threads_list stays alive StructuredData::ArraySP threads_list = m_interpreter->OSPlugin_ThreadsInfo(m_python_object_sp); const uint32_t num_cores = core_thread_list.GetSize(false); @@ -324,7 +324,7 @@ OperatingSystemPython::CreateRegisterContextForThread (Thread *thread, addr_t re // content of the process, and we're going to use python, which requires the API lock to do it. // So get & hold that. This is a recursive lock so we can grant it to any Python code called on the stack below us. Target &target = m_process->GetTarget(); - Mutex::Locker api_locker (target.GetAPIMutex()); + std::lock_guard guard(target.GetAPIMutex()); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); @@ -399,8 +399,8 @@ OperatingSystemPython::CreateThread (lldb::tid_t tid, addr_t context) // content of the process, and we're going to use python, which requires the API lock to do it. // So get & hold that. This is a recursive lock so we can grant it to any Python code called on the stack below us. Target &target = m_process->GetTarget(); - Mutex::Locker api_locker (target.GetAPIMutex()); - + std::lock_guard guard(target.GetAPIMutex()); + auto lock = m_interpreter->AcquireInterpreterLock(); // to make sure thread_info_dict stays alive StructuredData::DictionarySP thread_info_dict = m_interpreter->OSPlugin_CreateThread(m_python_object_sp, tid, context); std::vector core_used_map; diff --git a/source/Plugins/Platform/Android/AdbClient.cpp b/source/Plugins/Platform/Android/AdbClient.cpp index 736447fd22d2..1b07ddba59fc 100644 --- a/source/Plugins/Platform/Android/AdbClient.cpp +++ b/source/Plugins/Platform/Android/AdbClient.cpp @@ -8,33 +8,41 @@ //===----------------------------------------------------------------------===// // Other libraries and framework includes +#include "AdbClient.h" + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/FileUtilities.h" + #include "lldb/Core/DataBuffer.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataEncoder.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/StreamString.h" +#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/FileSpec.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/Support/FileUtilities.h" - -// Project includes -#include "AdbClient.h" #include #include +#include #include #include +// On Windows, transitive dependencies pull in , which defines a +// macro that clashes with a method name. +#ifdef SendMessage +#undef SendMessage +#endif + using namespace lldb; using namespace lldb_private; using namespace lldb_private::platform_android; namespace { -const uint32_t kReadTimeout = 1000000; // 1 second +const std::chrono::seconds kReadTimeout(8); const char * kOKAY = "OKAY"; const char * kFAIL = "FAIL"; const char * kDATA = "DATA"; @@ -53,6 +61,35 @@ const uint32_t kDefaultMode = 0100770; // S_IFREG | S_IRWXU | S_IRWXG const char * kSocketNamespaceAbstract = "localabstract"; const char * kSocketNamespaceFileSystem = "localfilesystem"; +Error +ReadAllBytes (Connection &conn, void *buffer, size_t size) +{ + using namespace std::chrono; + + Error error; + ConnectionStatus status; + char *read_buffer = static_cast(buffer); + + auto now = steady_clock::now(); + const auto deadline = now + kReadTimeout; + size_t total_read_bytes = 0; + while (total_read_bytes < size && now < deadline) + { + uint32_t timeout_usec = duration_cast(deadline - now).count(); + auto read_bytes = + conn.Read(read_buffer + total_read_bytes, size - total_read_bytes, timeout_usec, status, &error); + if (error.Fail ()) + return error; + total_read_bytes += read_bytes; + if (status != eConnectionStatusSuccess) + break; + now = steady_clock::now(); + } + if (total_read_bytes < size) + error = Error("Unable to read requested number of bytes. Connection status: %d.", status); + return error; +} + } // namespace Error @@ -63,30 +100,39 @@ AdbClient::CreateByDeviceID(const std::string &device_id, AdbClient &adb) if (error.Fail()) return error; - if (device_id.empty()) + std::string android_serial; + if (!device_id.empty()) + android_serial = device_id; + else if (const char *env_serial = std::getenv("ANDROID_SERIAL")) + android_serial = env_serial; + + if (android_serial.empty()) { if (connect_devices.size() != 1) - return Error("Expected a single connected device, got instead %" PRIu64, - static_cast(connect_devices.size())); - + return Error("Expected a single connected device, got instead %zu - try setting 'ANDROID_SERIAL'", + connect_devices.size()); adb.SetDeviceID(connect_devices.front()); } else { - auto find_it = std::find(connect_devices.begin(), connect_devices.end(), device_id); + auto find_it = std::find(connect_devices.begin(), connect_devices.end(), android_serial); if (find_it == connect_devices.end()) - return Error("Device \"%s\" not found", device_id.c_str()); + return Error("Device \"%s\" not found", android_serial.c_str()); adb.SetDeviceID(*find_it); } return error; } +AdbClient::AdbClient () {} + AdbClient::AdbClient (const std::string &device_id) : m_device_id (device_id) { } +AdbClient::~AdbClient() {} + void AdbClient::SetDeviceID (const std::string &device_id) { @@ -103,7 +149,8 @@ Error AdbClient::Connect () { Error error; - m_conn.Connect ("connect://localhost:5037", &error); + m_conn.reset (new ConnectionFileDescriptor); + m_conn->Connect ("connect://localhost:5037", &error); return error; } @@ -131,6 +178,9 @@ AdbClient::GetDevices (DeviceIDList &device_list) for (const auto device: devices) device_list.push_back (device.split ('\t').first); + // Force disconnect since ADB closes connection after host:devices + // response is sent. + m_conn.reset (); return error; } @@ -184,7 +234,7 @@ Error AdbClient::SendMessage (const std::string &packet, const bool reconnect) { Error error; - if (reconnect) + if (!m_conn || reconnect) { error = Connect (); if (error.Fail ()) @@ -196,11 +246,11 @@ AdbClient::SendMessage (const std::string &packet, const bool reconnect) ConnectionStatus status; - m_conn.Write (length_buffer, 4, status, &error); + m_conn->Write (length_buffer, 4, status, &error); if (error.Fail ()) return error; - m_conn.Write (packet.c_str (), packet.size (), status, &error); + m_conn->Write (packet.c_str (), packet.size (), status, &error); return error; } @@ -251,7 +301,7 @@ AdbClient::ReadMessageStream (std::vector& message, uint32_t timeout_ms) if (elapsed_time >= timeout_ms) return Error("Timed out"); - size_t n = m_conn.Read(buffer, sizeof(buffer), 1000 * (timeout_ms - elapsed_time), status, &error); + size_t n = m_conn->Read(buffer, sizeof(buffer), 1000 * (timeout_ms - elapsed_time), status, &error); if (n > 0) message.insert(message.end(), &buffer[0], &buffer[n]); } @@ -304,12 +354,118 @@ AdbClient::SwitchDeviceTransport () } Error -AdbClient::PullFile (const FileSpec &remote_file, const FileSpec &local_file) +AdbClient::StartSync () +{ + auto error = SwitchDeviceTransport (); + if (error.Fail ()) + return Error ("Failed to switch to device transport: %s", error.AsCString ()); + + error = Sync (); + if (error.Fail ()) + return Error ("Sync failed: %s", error.AsCString ()); + + return error; +} + +Error +AdbClient::Sync () { - auto error = StartSync (); + auto error = SendMessage ("sync:", false); if (error.Fail ()) return error; + return ReadResponseStatus (); +} + +Error +AdbClient::ReadAllBytes (void *buffer, size_t size) +{ + return ::ReadAllBytes (*m_conn, buffer, size); +} + +Error +AdbClient::internalShell(const char *command, uint32_t timeout_ms, std::vector &output_buf) +{ + output_buf.clear(); + + auto error = SwitchDeviceTransport(); + if (error.Fail()) + return Error("Failed to switch to device transport: %s", error.AsCString()); + + StreamString adb_command; + adb_command.Printf("shell:%s", command); + error = SendMessage(adb_command.GetData(), false); + if (error.Fail()) + return error; + + error = ReadResponseStatus(); + if (error.Fail()) + return error; + + error = ReadMessageStream(output_buf, timeout_ms); + if (error.Fail()) + return error; + + // ADB doesn't propagate return code of shell execution - if + // output starts with /system/bin/sh: most likely command failed. + static const char *kShellPrefix = "/system/bin/sh:"; + if (output_buf.size() > strlen(kShellPrefix)) + { + if (!memcmp(&output_buf[0], kShellPrefix, strlen(kShellPrefix))) + return Error("Shell command %s failed: %s", command, + std::string(output_buf.begin(), output_buf.end()).c_str()); + } + + return Error(); +} + +Error +AdbClient::Shell(const char *command, uint32_t timeout_ms, std::string *output) +{ + std::vector output_buffer; + auto error = internalShell(command, timeout_ms, output_buffer); + if (error.Fail()) + return error; + + if (output) + output->assign(output_buffer.begin(), output_buffer.end()); + return error; +} + +Error +AdbClient::ShellToFile(const char *command, uint32_t timeout_ms, const FileSpec &output_file_spec) +{ + std::vector output_buffer; + auto error = internalShell(command, timeout_ms, output_buffer); + if (error.Fail()) + return error; + + const auto output_filename = output_file_spec.GetPath(); + std::ofstream dst(output_filename, std::ios::out | std::ios::binary); + if (!dst.is_open()) + return Error("Unable to open local file %s", output_filename.c_str()); + + dst.write(&output_buffer[0], output_buffer.size()); + dst.close(); + if (!dst) + return Error("Failed to write file %s", output_filename.c_str()); + return Error(); +} + +std::unique_ptr +AdbClient::GetSyncService (Error &error) +{ + std::unique_ptr sync_service; + error = StartSync (); + if (error.Success ()) + sync_service.reset (new SyncService(std::move(m_conn))); + + return sync_service; +} + +Error +AdbClient::SyncService::internalPullFile (const FileSpec &remote_file, const FileSpec &local_file) +{ const auto local_file_path = local_file.GetPath (); llvm::FileRemover local_file_remover (local_file_path.c_str ()); @@ -318,7 +474,7 @@ AdbClient::PullFile (const FileSpec &remote_file, const FileSpec &local_file) return Error ("Unable to open local file %s", local_file_path.c_str()); const auto remote_file_path = remote_file.GetPath (false); - error = SendSyncRequest (kRECV, remote_file_path.length (), remote_file_path.c_str ()); + auto error = SendSyncRequest (kRECV, remote_file_path.length (), remote_file_path.c_str ()); if (error.Fail ()) return error; @@ -338,12 +494,8 @@ AdbClient::PullFile (const FileSpec &remote_file, const FileSpec &local_file) } Error -AdbClient::PushFile (const FileSpec &local_file, const FileSpec &remote_file) +AdbClient::SyncService::internalPushFile (const FileSpec &local_file, const FileSpec &remote_file) { - auto error = StartSync (); - if (error.Fail ()) - return error; - const auto local_file_path (local_file.GetPath ()); std::ifstream src (local_file_path.c_str(), std::ios::in | std::ios::binary); if (!src.is_open ()) @@ -352,7 +504,7 @@ AdbClient::PushFile (const FileSpec &local_file, const FileSpec &remote_file) std::stringstream file_description; file_description << remote_file.GetPath(false).c_str() << "," << kDefaultMode; std::string file_description_str = file_description.str(); - error = SendSyncRequest (kSEND, file_description_str.length(), file_description_str.c_str()); + auto error = SendSyncRequest (kSEND, file_description_str.length(), file_description_str.c_str()); if (error.Fail ()) return error; @@ -392,67 +544,89 @@ AdbClient::PushFile (const FileSpec &local_file, const FileSpec &remote_file) } Error -AdbClient::StartSync () +AdbClient::SyncService::internalStat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime) { - auto error = SwitchDeviceTransport (); + const std::string remote_file_path (remote_file.GetPath (false)); + auto error = SendSyncRequest (kSTAT, remote_file_path.length (), remote_file_path.c_str ()); if (error.Fail ()) - return Error ("Failed to switch to device transport: %s", error.AsCString ()); + return Error ("Failed to send request: %s", error.AsCString ()); - error = Sync (); + static const size_t stat_len = strlen (kSTAT); + static const size_t response_len = stat_len + (sizeof (uint32_t) * 3); + + std::vector buffer (response_len); + error = ReadAllBytes (&buffer[0], buffer.size ()); if (error.Fail ()) - return Error ("Sync failed: %s", error.AsCString ()); + return Error ("Failed to read response: %s", error.AsCString ()); - return error; + DataExtractor extractor (&buffer[0], buffer.size (), eByteOrderLittle, sizeof (void*)); + offset_t offset = 0; + + const void* command = extractor.GetData (&offset, stat_len); + if (!command) + return Error ("Failed to get response command"); + const char* command_str = static_cast (command); + if (strncmp (command_str, kSTAT, stat_len)) + return Error ("Got invalid stat command: %s", command_str); + + mode = extractor.GetU32 (&offset); + size = extractor.GetU32 (&offset); + mtime = extractor.GetU32 (&offset); + return Error (); } Error -AdbClient::Sync () +AdbClient::SyncService::PullFile (const FileSpec &remote_file, const FileSpec &local_file) { - auto error = SendMessage ("sync:", false); - if (error.Fail ()) - return error; + return executeCommand ([this, &remote_file, &local_file]() { + return internalPullFile (remote_file, local_file); + }); +} - return ReadResponseStatus (); +Error +AdbClient::SyncService::PushFile (const FileSpec &local_file, const FileSpec &remote_file) +{ + return executeCommand ([this, &local_file, &remote_file]() { + return internalPushFile (local_file, remote_file); + }); } Error -AdbClient::PullFileChunk (std::vector &buffer, bool &eof) +AdbClient::SyncService::Stat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime) { - buffer.clear (); + return executeCommand ([this, &remote_file, &mode, &size, &mtime]() { + return internalStat (remote_file, mode, size, mtime); + }); +} - std::string response_id; - uint32_t data_len; - auto error = ReadSyncHeader (response_id, data_len); - if (error.Fail ()) - return error; +bool +AdbClient::SyncService::IsConnected () const +{ + return m_conn && m_conn->IsConnected (); +} - if (response_id == kDATA) - { - buffer.resize (data_len, 0); - error = ReadAllBytes (&buffer[0], data_len); - if (error.Fail ()) - buffer.clear (); - } - else if (response_id == kDONE) - { - eof = true; - } - else if (response_id == kFAIL) - { - std::string error_message (data_len, 0); - error = ReadAllBytes (&error_message[0], data_len); - if (error.Fail ()) - return Error ("Failed to read pull error message: %s", error.AsCString ()); - return Error ("Failed to pull file: %s", error_message.c_str ()); - } - else - return Error ("Pull failed with unknown response: %s", response_id.c_str ()); +AdbClient::SyncService::SyncService(std::unique_ptr &&conn): +m_conn(std::move(conn)) +{ +} - return Error (); +Error +AdbClient::SyncService::executeCommand (const std::function &cmd) +{ + if (!m_conn) + return Error ("SyncService is disconnected"); + + const auto error = cmd (); + if (error.Fail ()) + m_conn.reset (); + + return error; } +AdbClient::SyncService::~SyncService () {} + Error -AdbClient::SendSyncRequest (const char *request_id, const uint32_t data_len, const void *data) +AdbClient::SyncService::SendSyncRequest (const char *request_id, const uint32_t data_len, const void *data) { const DataBufferSP data_sp (new DataBufferHeap (kSyncPacketLen, 0)); DataEncoder encoder (data_sp, eByteOrderLittle, sizeof (void*)); @@ -461,17 +635,17 @@ AdbClient::SendSyncRequest (const char *request_id, const uint32_t data_len, con Error error; ConnectionStatus status; - m_conn.Write (data_sp->GetBytes (), kSyncPacketLen, status, &error); + m_conn->Write (data_sp->GetBytes (), kSyncPacketLen, status, &error); if (error.Fail ()) return error; if (data) - m_conn.Write (data, data_len, status, &error); + m_conn->Write (data, data_len, status, &error); return error; } Error -AdbClient::ReadSyncHeader (std::string &response_id, uint32_t &data_len) +AdbClient::SyncService::ReadSyncHeader (std::string &response_id, uint32_t &data_len) { char buffer[kSyncPacketLen]; @@ -488,82 +662,44 @@ AdbClient::ReadSyncHeader (std::string &response_id, uint32_t &data_len) } Error -AdbClient::ReadAllBytes (void *buffer, size_t size) +AdbClient::SyncService::PullFileChunk (std::vector &buffer, bool &eof) { - Error error; - ConnectionStatus status; - char *read_buffer = static_cast(buffer); - - size_t tota_read_bytes = 0; - while (tota_read_bytes < size) - { - auto read_bytes = m_conn.Read (read_buffer + tota_read_bytes, size - tota_read_bytes, kReadTimeout, status, &error); - if (error.Fail ()) - return error; - tota_read_bytes += read_bytes; - } - return error; -} + buffer.clear (); -Error -AdbClient::Stat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime) -{ - auto error = StartSync (); + std::string response_id; + uint32_t data_len; + auto error = ReadSyncHeader (response_id, data_len); if (error.Fail ()) return error; - const std::string remote_file_path (remote_file.GetPath (false)); - error = SendSyncRequest (kSTAT, remote_file_path.length (), remote_file_path.c_str ()); - if (error.Fail ()) - return Error ("Failed to send request: %s", error.AsCString ()); - - static const size_t stat_len = strlen (kSTAT); - static const size_t response_len = stat_len + (sizeof (uint32_t) * 3); - - std::vector buffer (response_len); - error = ReadAllBytes (&buffer[0], buffer.size ()); - if (error.Fail ()) - return Error ("Failed to read response: %s", error.AsCString ()); - - DataExtractor extractor (&buffer[0], buffer.size (), eByteOrderLittle, sizeof (void*)); - offset_t offset = 0; - - const void* command = extractor.GetData (&offset, stat_len); - if (!command) - return Error ("Failed to get response command"); - const char* command_str = static_cast (command); - if (strncmp (command_str, kSTAT, stat_len)) - return Error ("Got invalid stat command: %s", command_str); + if (response_id == kDATA) + { + buffer.resize (data_len, 0); + error = ReadAllBytes (&buffer[0], data_len); + if (error.Fail ()) + buffer.clear (); + } + else if (response_id == kDONE) + { + eof = true; + } + else if (response_id == kFAIL) + { + std::string error_message (data_len, 0); + error = ReadAllBytes (&error_message[0], data_len); + if (error.Fail ()) + return Error ("Failed to read pull error message: %s", error.AsCString ()); + return Error ("Failed to pull file: %s", error_message.c_str ()); + } + else + return Error ("Pull failed with unknown response: %s", response_id.c_str ()); - mode = extractor.GetU32 (&offset); - size = extractor.GetU32 (&offset); - mtime = extractor.GetU32 (&offset); return Error (); } Error -AdbClient::Shell (const char* command, uint32_t timeout_ms, std::string* output) +AdbClient::SyncService::ReadAllBytes (void *buffer, size_t size) { - auto error = SwitchDeviceTransport (); - if (error.Fail ()) - return Error ("Failed to switch to device transport: %s", error.AsCString ()); - - StreamString adb_command; - adb_command.Printf("shell:%s", command); - error = SendMessage (adb_command.GetData(), false); - if (error.Fail ()) - return error; - - error = ReadResponseStatus (); - if (error.Fail ()) - return error; - - std::vector in_buffer; - error = ReadMessageStream (in_buffer, timeout_ms); - if (error.Fail()) - return error; - - if (output) - output->assign(in_buffer.begin(), in_buffer.end()); - return error; + return ::ReadAllBytes (*m_conn, buffer, size); } + diff --git a/source/Plugins/Platform/Android/AdbClient.h b/source/Plugins/Platform/Android/AdbClient.h index 4ec411d1411d..37973bbdccf8 100644 --- a/source/Plugins/Platform/Android/AdbClient.h +++ b/source/Plugins/Platform/Android/AdbClient.h @@ -14,7 +14,9 @@ // C++ Includes +#include #include +#include #include #include @@ -22,7 +24,6 @@ // Project includes #include "lldb/Core/Error.h" -#include "lldb/Host/ConnectionFileDescriptor.h" namespace lldb_private { @@ -41,12 +42,63 @@ public: using DeviceIDList = std::list; + class SyncService + { + friend class AdbClient; + + public: + ~SyncService (); + + Error + PullFile (const FileSpec &remote_file, const FileSpec &local_file); + + Error + PushFile (const FileSpec &local_file, const FileSpec &remote_file); + + Error + Stat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime); + + bool + IsConnected () const; + + private: + explicit SyncService (std::unique_ptr &&conn); + + Error + SendSyncRequest (const char *request_id, const uint32_t data_len, const void *data); + + Error + ReadSyncHeader (std::string &response_id, uint32_t &data_len); + + Error + PullFileChunk (std::vector &buffer, bool &eof); + + Error + ReadAllBytes (void *buffer, size_t size); + + Error + internalPullFile (const FileSpec &remote_file, const FileSpec &local_file); + + Error + internalPushFile (const FileSpec &local_file, const FileSpec &remote_file); + + Error + internalStat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime); + + Error + executeCommand (const std::function &cmd); + + std::unique_ptr m_conn; + }; + static Error CreateByDeviceID(const std::string &device_id, AdbClient &adb); - AdbClient () = default; + AdbClient (); explicit AdbClient (const std::string &device_id); + ~AdbClient(); + const std::string& GetDeviceID() const; @@ -65,16 +117,16 @@ public: DeletePortForwarding (const uint16_t local_port); Error - PullFile (const FileSpec &remote_file, const FileSpec &local_file); + Shell (const char* command, uint32_t timeout_ms, std::string* output); Error - PushFile (const FileSpec &local_file, const FileSpec &remote_file); + ShellToFile(const char *command, uint32_t timeout_ms, const FileSpec &output_file_spec); - Error - Stat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime); + std::unique_ptr + GetSyncService (Error &error); Error - Shell (const char* command, uint32_t timeout_ms, std::string* output); + SwitchDeviceTransport (); private: Error @@ -89,12 +141,6 @@ private: Error SendDeviceMessage (const std::string &packet); - Error - SendSyncRequest (const char *request_id, const uint32_t data_len, const void *data); - - Error - ReadSyncHeader (std::string &response_id, uint32_t &data_len); - Error ReadMessage (std::vector &message); @@ -107,9 +153,6 @@ private: Error ReadResponseStatus (); - Error - SwitchDeviceTransport (); - Error Sync (); @@ -117,16 +160,17 @@ private: StartSync (); Error - PullFileChunk (std::vector &buffer, bool &eof); + internalShell(const char *command, uint32_t timeout_ms, std::vector &output_buf); Error - ReadAllBytes (void *buffer, size_t size); + ReadAllBytes(void *buffer, size_t size); std::string m_device_id; - ConnectionFileDescriptor m_conn; + std::unique_ptr m_conn; }; } // namespace platform_android } // namespace lldb_private #endif // liblldb_AdbClient_h_ + diff --git a/source/Plugins/Platform/Android/Makefile b/source/Plugins/Platform/Android/Makefile deleted file mode 100644 index aa186f924e66..000000000000 --- a/source/Plugins/Platform/Android/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Platform/Android/Makefile ------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginPlatformAndroid -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Platform/Android/PlatformAndroid.cpp b/source/Plugins/Platform/Android/PlatformAndroid.cpp index e842884c046a..381795171d36 100644 --- a/source/Plugins/Platform/Android/PlatformAndroid.cpp +++ b/source/Plugins/Platform/Android/PlatformAndroid.cpp @@ -225,8 +225,36 @@ PlatformAndroid::GetFile (const FileSpec& source, if (source_spec.IsRelative()) source_spec = GetRemoteWorkingDirectory ().CopyByAppendingPathComponent (source_spec.GetCString (false)); - AdbClient adb (m_device_id); - return adb.PullFile (source_spec, destination); + Error error; + auto sync_service = GetSyncService (error); + if (error.Fail ()) + return error; + + uint32_t mode = 0, size = 0, mtime = 0; + error = sync_service->Stat(source_spec, mode, size, mtime); + if (error.Fail()) + return error; + + if (mode != 0) + return sync_service->PullFile(source_spec, destination); + + auto source_file = source_spec.GetCString(false); + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) + log->Printf("Got mode == 0 on '%s': try to get file via 'shell cat'", source_file); + + if (strchr(source_file, '\'') != nullptr) + return Error("Doesn't support single-quotes in filenames"); + + // mode == 0 can signify that adbd cannot access the file + // due security constraints - try "cat ..." as a fallback. + AdbClient adb(m_device_id); + + char cmd[PATH_MAX]; + snprintf(cmd, sizeof(cmd), "cat '%s'", source_file); + + return adb.ShellToFile(cmd, 60000 /* ms */, destination); } Error @@ -242,9 +270,12 @@ PlatformAndroid::PutFile (const FileSpec& source, if (destination_spec.IsRelative()) destination_spec = GetRemoteWorkingDirectory ().CopyByAppendingPathComponent (destination_spec.GetCString (false)); - AdbClient adb (m_device_id); // TODO: Set correct uid and gid on remote file. - return adb.PushFile(source, destination_spec); + Error error; + auto sync_service = GetSyncService (error); + if (error.Fail ()) + return error; + return sync_service->PushFile(source, destination_spec); } const char * @@ -315,8 +346,9 @@ PlatformAndroid::DownloadSymbolFile (const lldb::ModuleSP& module_sp, const FileSpec& dst_file_spec) { // For oat file we can try to fetch additional debug info from the device - if (module_sp->GetFileSpec().GetFileNameExtension() != ConstString("oat")) - return Error("Symbol file downloading only supported for oat files"); + ConstString extension = module_sp->GetFileSpec().GetFileNameExtension(); + if (extension != ConstString("oat") && extension != ConstString("odex")) + return Error("Symbol file downloading only supported for oat and odex files"); // If we have no information about the platform file we can't execute oatdump if (!module_sp->GetPlatformFileSpec()) @@ -331,7 +363,6 @@ PlatformAndroid::DownloadSymbolFile (const lldb::ModuleSP& module_sp, return Error("Symtab already available in the module"); AdbClient adb(m_device_id); - std::string tmpdir; Error error = adb.Shell("mktemp --directory --tmpdir /data/local/tmp", 5000 /* ms */, &tmpdir); if (error.Fail() || tmpdir.empty()) @@ -387,3 +418,15 @@ PlatformAndroid::GetLibdlFunctionDeclarations() const extern "C" char* dlerror(void) asm("__dl_dlerror"); )"; } + +AdbClient::SyncService* +PlatformAndroid::GetSyncService (Error &error) +{ + if (m_adb_sync_svc && m_adb_sync_svc->IsConnected ()) + return m_adb_sync_svc.get (); + + AdbClient adb (m_device_id); + m_adb_sync_svc = adb.GetSyncService (error); + return (error.Success ()) ? m_adb_sync_svc.get () : nullptr; +} + diff --git a/source/Plugins/Platform/Android/PlatformAndroid.h b/source/Plugins/Platform/Android/PlatformAndroid.h index 119d0a0bdf04..6f7a87ca9fef 100644 --- a/source/Plugins/Platform/Android/PlatformAndroid.h +++ b/source/Plugins/Platform/Android/PlatformAndroid.h @@ -12,12 +12,15 @@ // C Includes // C++ Includes +#include #include // Other libraries and framework includes // Project includes #include "Plugins/Platform/Linux/PlatformLinux.h" +#include "AdbClient.h" + namespace lldb_private { namespace platform_android { @@ -102,6 +105,9 @@ namespace platform_android { GetLibdlFunctionDeclarations() const override; private: + AdbClient::SyncService* GetSyncService (Error &error); + + std::unique_ptr m_adb_sync_svc; std::string m_device_id; uint32_t m_sdk_version; diff --git a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp index 3d91dd6b7a32..f11f2874e356 100644 --- a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp +++ b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp @@ -11,6 +11,8 @@ #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" #include "lldb/Host/common/TCPSocket.h" +#include "lldb/Host/ConnectionFileDescriptor.h" + #include "PlatformAndroidRemoteGDBServer.h" #include "Utility/UriParser.h" @@ -258,18 +260,3 @@ PlatformAndroidRemoteGDBServer::ConnectProcess(const char* connect_url, target, error); } - -size_t -PlatformAndroidRemoteGDBServer::ConnectToWaitingProcesses(Debugger& debugger, Error& error) -{ - std::vector connection_urls; - GetPendingGdbServerList(connection_urls); - - for (size_t i = 0; i < connection_urls.size(); ++i) - { - ConnectProcess(connection_urls[i].c_str(), nullptr, debugger, nullptr, error); - if (error.Fail()) - return i; // We already connected to i process succsessfully - } - return connection_urls.size(); -} diff --git a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h index 3d2653812ded..79e273c665eb 100644 --- a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h +++ b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h @@ -46,9 +46,6 @@ public: lldb_private::Target *target, lldb_private::Error &error) override; - size_t - ConnectToWaitingProcesses(lldb_private::Debugger& debugger, lldb_private::Error& error) override; - protected: std::string m_device_id; std::map m_port_forwards; diff --git a/source/Plugins/Platform/FreeBSD/Makefile b/source/Plugins/Platform/FreeBSD/Makefile deleted file mode 100644 index e5c25d8504df..000000000000 --- a/source/Plugins/Platform/FreeBSD/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Platform/FreeBSD/Makefile ------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginPlatformFreeBSD -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp index 9b3c57501117..83c9247f4682 100644 --- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp +++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp @@ -614,84 +614,31 @@ PlatformFreeBSD::GetStatus (Stream &strm) size_t PlatformFreeBSD::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()) + switch (target.GetArchitecture().GetMachine()) { - default: - assert(false && "Unhandled architecture in PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode()"); - break; - case llvm::Triple::aarch64: - { - static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xd4 }; - trap_opcode = g_aarch64_opcode; - trap_opcode_size = sizeof(g_aarch64_opcode); - } - break; - // TODO: support big-endian arm and thumb trap codes. case llvm::Triple::arm: { - static const uint8_t g_arm_breakpoint_opcode[] = { 0xfe, 0xde, 0xff, 0xe7 }; - static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde }; - - lldb::BreakpointLocationSP bp_loc_sp (bp_site->GetOwnerAtIndex (0)); + lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0)); AddressClass addr_class = eAddressClassUnknown; if (bp_loc_sp) - addr_class = bp_loc_sp->GetAddress ().GetAddressClass (); + { + addr_class = bp_loc_sp->GetAddress().GetAddressClass(); + if (addr_class == eAddressClassUnknown && (bp_loc_sp->GetAddress().GetFileAddress() & 1)) + addr_class = eAddressClassCodeAlternateISA; + } - if (addr_class == eAddressClassCodeAlternateISA - || (addr_class == eAddressClassUnknown && (bp_site->GetLoadAddress() & 1))) + if (addr_class == eAddressClassCodeAlternateISA) { // TODO: Enable when FreeBSD supports thumb breakpoints. // FreeBSD kernel as of 10.x, does not support thumb breakpoints - trap_opcode = g_thumb_breakpoint_opcode; - trap_opcode_size = 0; - } - else - { - trap_opcode = g_arm_breakpoint_opcode; - trap_opcode_size = sizeof(g_arm_breakpoint_opcode); + return 0; } } - break; - case llvm::Triple::mips64: - { - static const uint8_t g_hex_opcode[] = { 0x00, 0x00, 0x00, 0x0d }; - trap_opcode = g_hex_opcode; - trap_opcode_size = sizeof(g_hex_opcode); - } - break; - case llvm::Triple::mips64el: - { - static const uint8_t g_hex_opcode[] = { 0x0d, 0x00, 0x00, 0x00 }; - trap_opcode = g_hex_opcode; - trap_opcode_size = sizeof(g_hex_opcode); - } - break; - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - { - static const uint8_t g_ppc_opcode[] = { 0x7f, 0xe0, 0x00, 0x08 }; - trap_opcode = g_ppc_opcode; - trap_opcode_size = sizeof(g_ppc_opcode); - } - 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; + LLVM_FALLTHROUGH; + default: + return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site); } - - if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) - return trap_opcode_size; - return 0; } diff --git a/source/Plugins/Platform/Kalimba/Makefile b/source/Plugins/Platform/Kalimba/Makefile deleted file mode 100644 index c22b7d21c13d..000000000000 --- a/source/Plugins/Platform/Kalimba/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Platform/Kalimba/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginPlatformKalimba -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Platform/Linux/Makefile b/source/Plugins/Platform/Linux/Makefile deleted file mode 100644 index 2877fddf0bcd..000000000000 --- a/source/Plugins/Platform/Linux/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Platform/Linux/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginPlatformLinux -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Platform/Linux/PlatformLinux.cpp b/source/Plugins/Platform/Linux/PlatformLinux.cpp index 8dc9769844c7..846e350eec56 100644 --- a/source/Plugins/Platform/Linux/PlatformLinux.cpp +++ b/source/Plugins/Platform/Linux/PlatformLinux.cpp @@ -485,6 +485,7 @@ PlatformLinux::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) case 6: triple.setArchName("mips"); break; case 7: triple.setArchName("mips64el"); break; case 8: triple.setArchName("mipsel"); break; + case 9: triple.setArchName("s390x"); break; default: return false; } // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the vendor by @@ -522,98 +523,6 @@ PlatformLinux::GetStatus (Stream &strm) #endif } -size_t -PlatformLinux::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 && "CPU type not supported!"); - break; - - case llvm::Triple::aarch64: - { - static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xd4 }; - trap_opcode = g_aarch64_opcode; - trap_opcode_size = sizeof(g_aarch64_opcode); - } - break; - case llvm::Triple::x86: - case llvm::Triple::x86_64: - { - static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC }; - trap_opcode = g_i386_breakpoint_opcode; - trap_opcode_size = sizeof(g_i386_breakpoint_opcode); - } - break; - case llvm::Triple::hexagon: - { - static const uint8_t g_hex_opcode[] = { 0x0c, 0xdb, 0x00, 0x54 }; - trap_opcode = g_hex_opcode; - trap_opcode_size = sizeof(g_hex_opcode); - } - 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 == eAddressClassUnknown && - (bp_loc_sp->GetAddress ().GetFileAddress () & 1)) - { - addr_class = eAddressClassCodeAlternateISA; - } - } - - if (addr_class == eAddressClassCodeAlternateISA) - { - trap_opcode = g_thumb_breakpoint_opcode; - trap_opcode_size = sizeof(g_thumb_breakpoint_opcode); - } - else - { - trap_opcode = g_arm_breakpoint_opcode; - trap_opcode_size = sizeof(g_arm_breakpoint_opcode); - } - } - break; - case llvm::Triple::mips: - case llvm::Triple::mips64: - { - static const uint8_t g_hex_opcode[] = { 0x00, 0x00, 0x00, 0x0d }; - trap_opcode = g_hex_opcode; - trap_opcode_size = sizeof(g_hex_opcode); - } - break; - case llvm::Triple::mipsel: - case llvm::Triple::mips64el: - { - static const uint8_t g_hex_opcode[] = { 0x0d, 0x00, 0x00, 0x00 }; - trap_opcode = g_hex_opcode; - trap_opcode_size = sizeof(g_hex_opcode); - } - break; - } - - if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) - return trap_opcode_size; - return 0; -} - int32_t PlatformLinux::GetResumeCountForLaunchInfo (ProcessLaunchInfo &launch_info) { @@ -762,9 +671,9 @@ PlatformLinux::DebugProcess (ProcessLaunchInfo &launch_info, if (log) log->Printf ("PlatformLinux::%s setting up hijacker", __FUNCTION__); - listener_sp.reset (new Listener("lldb.PlatformLinux.DebugProcess.hijack")); + listener_sp = Listener::MakeListener("lldb.PlatformLinux.DebugProcess.hijack"); launch_info.SetHijackListener (listener_sp); - process_sp->HijackProcessEvents (listener_sp.get ()); + process_sp->HijackProcessEvents (listener_sp); } // Log file actions. @@ -790,7 +699,7 @@ PlatformLinux::DebugProcess (ProcessLaunchInfo &launch_info, // Handle the hijacking of process events. if (listener_sp) { - const StateType state = process_sp->WaitForProcessToStop (NULL, NULL, false, listener_sp.get()); + const StateType state = process_sp->WaitForProcessToStop (NULL, NULL, false, listener_sp); if (state == eStateStopped) { diff --git a/source/Plugins/Platform/Linux/PlatformLinux.h b/source/Plugins/Platform/Linux/PlatformLinux.h index 770a20c90cce..d99256cff0ea 100644 --- a/source/Plugins/Platform/Linux/PlatformLinux.h +++ b/source/Plugins/Platform/Linux/PlatformLinux.h @@ -87,10 +87,6 @@ namespace platform_linux { bool GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) override; - size_t - GetSoftwareBreakpointTrapOpcode (Target &target, - BreakpointSite *bp_site) override; - int32_t GetResumeCountForLaunchInfo (ProcessLaunchInfo &launch_info) override; diff --git a/source/Plugins/Platform/MacOSX/Makefile b/source/Plugins/Platform/MacOSX/Makefile deleted file mode 100644 index 4377d369bc19..000000000000 --- a/source/Plugins/Platform/MacOSX/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -##===- source/Plugins/Platform/MacOSX/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LEVEL := $(LLDB_LEVEL)/../.. - -include $(LEVEL)/Makefile.config - -SOURCES += PlatformDarwin.cpp \ - PlatformDarwinKernel.cpp \ - PlatformMacOSX.cpp \ - PlatformRemoteiOS.cpp \ - PlatformRemoteAppleTV.cpp \ - PlatformRemoteAppleWatch.cpp - -ifeq ($(HOST_OS),Darwin) -SOURCES += PlatformAppleSimulator.cpp \ - PlatformiOSSimulator.cpp \ - PlatformiOSSimulatorCoreSimulatorSupport.mm \ - PlatformAppleTVSimulator.cpp \ - PlatformAppleWatchSimulator.cpp -endif - -LIBRARYNAME := lldbPluginPlatformMacOSX -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile - diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp index eea2844d5649..a5f165e1f925 100644 --- a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp @@ -252,7 +252,7 @@ FileSpec PlatformAppleSimulator::GetCoreSimulatorPath() { #if defined(__APPLE__) - Mutex::Locker locker (m_mutex); + std::lock_guard guard(m_mutex); if (!m_core_simulator_framework_path.hasValue()) { const char *developer_dir = GetDeveloperDirectory(); diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp index f537934a9172..097d58dcfbc1 100644 --- a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp @@ -304,7 +304,7 @@ EnumerateDirectoryCallback (void *baton, FileSpec::FileType file_type, const Fil const char * PlatformAppleTVSimulator::GetSDKDirectoryAsCString() { - Mutex::Locker locker (m_mutex); + std::lock_guard guard(m_mutex); if (m_sdk_directory.empty()) { const char *developer_dir = GetDeveloperDirectory(); diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp index ea8e789b2920..46e5970bc089 100644 --- a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp @@ -304,7 +304,7 @@ EnumerateDirectoryCallback (void *baton, FileSpec::FileType file_type, const Fil const char * PlatformAppleWatchSimulator::GetSDKDirectoryAsCString() { - Mutex::Locker locker (m_mutex); + std::lock_guard guard(m_mutex); if (m_sdk_directory.empty()) { const char *developer_dir = GetDeveloperDirectory(); diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp index fb38630710a1..f9eada986529 100644 --- a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -583,22 +583,13 @@ PlatformDarwin::GetSharedModule (const ModuleSpec &module_spec, size_t PlatformDarwin::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site) { - const uint8_t *trap_opcode = NULL; + const uint8_t *trap_opcode = nullptr; uint32_t trap_opcode_size = 0; bool bp_is_thumb = false; - + llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine(); switch (machine) { - case llvm::Triple::x86: - case llvm::Triple::x86_64: - { - static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC }; - trap_opcode = g_i386_breakpoint_opcode; - trap_opcode_size = sizeof(g_i386_breakpoint_opcode); - } - break; - case llvm::Triple::aarch64: { // TODO: fix this with actual darwin breakpoint opcode for arm64. @@ -611,7 +602,8 @@ PlatformDarwin::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite break; case llvm::Triple::thumb: - bp_is_thumb = true; // Fall through... + bp_is_thumb = true; + LLVM_FALLTHROUGH; case llvm::Triple::arm: { static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 }; @@ -634,7 +626,7 @@ PlatformDarwin::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite trap_opcode_size = sizeof(g_arm_breakpoint_opcode); } break; - + case llvm::Triple::ppc: case llvm::Triple::ppc64: { @@ -643,12 +635,11 @@ PlatformDarwin::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite trap_opcode_size = sizeof(g_ppc_breakpoint_opcode); } break; - + default: - assert(!"Unhandled architecture in PlatformDarwin::GetSoftwareBreakpointTrapOpcode()"); - break; + return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site); } - + if (trap_opcode && trap_opcode_size) { if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) @@ -1024,7 +1015,7 @@ PlatformDarwin::ARMGetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch const char * PlatformDarwin::GetDeveloperDirectory() { - Mutex::Locker locker (m_mutex); + std::lock_guard guard(m_mutex); if (m_developer_directory.empty()) { bool developer_dir_path_valid = false; @@ -1166,6 +1157,7 @@ PlatformDarwin::SetThreadCreationBreakpoint (Target &target) llvm::array_lengthof(g_bp_names), eFunctionNameTypeFull, eLanguageTypeUnknown, + 0, skip_prologue, internal, hardware); @@ -1580,10 +1572,10 @@ PlatformDarwin::AddClangModuleCompilationOptionsForSDKType (Target *target, std: FileSpec sysroot_spec; // Scope for mutex locker below { - Mutex::Locker locker (m_mutex); + std::lock_guard guard(m_mutex); sysroot_spec = GetSDKDirectoryForModules(sdk_type); } - + if (sysroot_spec.IsDirectory()) { options.push_back("-isysroot"); @@ -1703,3 +1695,28 @@ PlatformDarwin::LocateExecutable (const char *basename) return FileSpec(); } + +lldb_private::Error +PlatformDarwin::LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) +{ + // Starting in Fall 2016 OSes, NSLog messages only get mirrored to stderr + // if the OS_ACTIVITY_DT_MODE environment variable is set. (It doesn't + // require any specific value; rather, it just needs to exist). + // We will set it here as long as the IDE_DISABLED_OS_ACTIVITY_DT_MODE flag + // is not set. Xcode makes use of IDE_DISABLED_OS_ACTIVITY_DT_MODE to tell + // LLDB *not* to muck with the OS_ACTIVITY_DT_MODE flag when they + // specifically want it unset. + const char *disable_env_var = "IDE_DISABLED_OS_ACTIVITY_DT_MODE"; + auto &env_vars = launch_info.GetEnvironmentEntries(); + if (!env_vars.ContainsEnvironmentVariable(disable_env_var)) + { + // We want to make sure that OS_ACTIVITY_DT_MODE is set so that + // we get os_log and NSLog messages mirrored to the target process + // stderr. + if (!env_vars.ContainsEnvironmentVariable("OS_ACTIVITY_DT_MODE")) + env_vars.AppendArgument("OS_ACTIVITY_DT_MODE=enable"); + } + + // Let our parent class do the real launching. + return PlatformPOSIX::LaunchProcess(launch_info); +} diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/source/Plugins/Platform/MacOSX/PlatformDarwin.h index b280b35da655..faecf4cc5a24 100644 --- a/source/Plugins/Platform/MacOSX/PlatformDarwin.h +++ b/source/Plugins/Platform/MacOSX/PlatformDarwin.h @@ -98,6 +98,9 @@ public: lldb_private::FileSpec LocateExecutable (const char *basename) override; + lldb_private::Error + LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) override; + protected: void ReadLibdispatchOffsetsAddress (lldb_private::Process *process); diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp index a502aa03eb26..d3c1c805a83b 100644 --- a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp @@ -30,6 +30,7 @@ #include "lldb/Interpreter/OptionValueFileSpecList.h" #include "lldb/Interpreter/OptionValueProperties.h" #include "lldb/Interpreter/Property.h" +#include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -881,12 +882,24 @@ PlatformDarwinKernel::GetSharedModule (const ModuleSpec &module_spec, ModuleSP module_sp (new Module (kern_spec)); if (module_sp && module_sp->GetObjectFile() && module_sp->MatchesModuleSpec (kern_spec)) { - Error error; - error = ModuleList::GetSharedModule (kern_spec, module_sp, NULL, NULL, NULL); - if (module_sp && module_sp->GetObjectFile()) + // module_sp is an actual kernel binary we want to add. + if (process) { + process->GetTarget().GetImages().AppendIfNeeded (module_sp); + error.Clear(); return error; } + else + { + error = ModuleList::GetSharedModule (kern_spec, module_sp, NULL, NULL, NULL); + if (module_sp + && module_sp->GetObjectFile() + && module_sp->GetObjectFile()->GetType() != ObjectFile::Type::eTypeCoreFile) + { + return error; + } + module_sp.reset(); + } } } } diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp index 04231f27ff9b..30af2bb2250b 100644 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp @@ -158,14 +158,6 @@ PlatformRemoteAppleTV::CreateInstance (bool force, const ArchSpec *arch) case llvm::Triple::TvOS: // This is the right triple value for Apple TV debugging break; -#if defined(__APPLE__) - // Only accept "unknown" for the OS if the host is Apple and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) - case llvm::Triple::UnknownOS: - create = !arch->TripleOSWasSpecified(); - break; -#endif default: create = false; break; @@ -314,9 +306,14 @@ PlatformRemoteAppleTV::GetContainedFilesIntoVectorOfStringsCallback (void *baton bool PlatformRemoteAppleTV::UpdateSDKDirectoryInfosIfNeeded() { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (m_sdk_directory_infos.empty()) { const char *device_support_dir = GetDeviceSupportDirectory(); + if (log) + { + log->Printf ("PlatformRemoteAppleTV::UpdateSDKDirectoryInfosIfNeeded Got DeviceSupport directory %s", device_support_dir); + } if (device_support_dir) { const bool find_directories = true; @@ -341,12 +338,20 @@ PlatformRemoteAppleTV::UpdateSDKDirectoryInfosIfNeeded() if (sdk_symbols_symlink_fspec.Exists()) { m_sdk_directory_infos.push_back(sdk_directory_info); + if (log) + { + log->Printf ("PlatformRemoteAppleTV::UpdateSDKDirectoryInfosIfNeeded added builtin SDK directory %s", sdk_symbols_symlink_fspec.GetPath().c_str()); + } } else { sdk_symbols_symlink_fspec.GetFilename().SetCString("Symbols"); if (sdk_symbols_symlink_fspec.Exists()) m_sdk_directory_infos.push_back(sdk_directory_info); + if (log) + { + log->Printf ("PlatformRemoteAppleTV::UpdateSDKDirectoryInfosIfNeeded added builtin SDK directory %s", sdk_symbols_symlink_fspec.GetPath().c_str()); + } } } @@ -374,6 +379,10 @@ PlatformRemoteAppleTV::UpdateSDKDirectoryInfosIfNeeded() } if (local_sdk_cache.Exists()) { + if (log) + { + log->Printf ("PlatformRemoteAppleTV::UpdateSDKDirectoryInfosIfNeeded searching %s for additional SDKs", local_sdk_cache.GetPath().c_str()); + } char path[PATH_MAX]; if (local_sdk_cache.GetPath(path, sizeof(path))) { @@ -388,6 +397,10 @@ PlatformRemoteAppleTV::UpdateSDKDirectoryInfosIfNeeded() for (uint32_t i=num_installed; iPrintf ("PlatformRemoteAppleTV::UpdateSDKDirectoryInfosIfNeeded user SDK directory %s", m_sdk_directory_infos[i].directory.GetPath().c_str()); + } } } } @@ -572,6 +585,7 @@ uint32_t PlatformRemoteAppleTV::FindFileInAllSDKs (const char *platform_file_path, FileSpecList &file_list) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | LIBLLDB_LOG_VERBOSE); if (platform_file_path && platform_file_path[0] && UpdateSDKDirectoryInfosIfNeeded()) { const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); @@ -579,6 +593,10 @@ PlatformRemoteAppleTV::FindFileInAllSDKs (const char *platform_file_path, // First try for an exact match of major, minor and update for (uint32_t sdk_idx=0; sdk_idxPrintf ("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[sdk_idx].directory.GetPath().c_str()); + } if (GetFileInSDK (platform_file_path, sdk_idx, local_file)) @@ -618,6 +636,7 @@ PlatformRemoteAppleTV::GetFileInSDKRoot (const char *platform_file_path, bool symbols_dirs_only, lldb_private::FileSpec &local_file) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (sdkroot_path && sdkroot_path[0] && platform_file_path && platform_file_path[0]) { char resolved_path[PATH_MAX]; @@ -632,7 +651,13 @@ PlatformRemoteAppleTV::GetFileInSDKRoot (const char *platform_file_path, local_file.SetFile(resolved_path, true); if (local_file.Exists()) + { + if (log) + { + log->Printf ("Found a copy of %s in the SDK dir %s", platform_file_path, sdkroot_path); + } return true; + } } ::snprintf (resolved_path, @@ -643,7 +668,13 @@ PlatformRemoteAppleTV::GetFileInSDKRoot (const char *platform_file_path, local_file.SetFile(resolved_path, true); if (local_file.Exists()) + { + if (log) + { + log->Printf ("Found a copy of %s in the SDK dir %s/Symbols.Internal", platform_file_path, sdkroot_path); + } return true; + } ::snprintf (resolved_path, sizeof(resolved_path), "%s/Symbols%s", @@ -652,7 +683,13 @@ PlatformRemoteAppleTV::GetFileInSDKRoot (const char *platform_file_path, local_file.SetFile(resolved_path, true); if (local_file.Exists()) + { + if (log) + { + log->Printf ("Found a copy of %s in the SDK dir %s/Symbols", platform_file_path, sdkroot_path); + } return true; + } } return false; } @@ -662,6 +699,7 @@ PlatformRemoteAppleTV::GetSymbolFile (const FileSpec &platform_file, const UUID *uuid_ptr, FileSpec &local_file) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); Error error; char platform_file_path[PATH_MAX]; if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) @@ -679,7 +717,13 @@ PlatformRemoteAppleTV::GetSymbolFile (const FileSpec &platform_file, local_file.SetFile(resolved_path, true); if (local_file.Exists()) + { + if (log) + { + log->Printf ("Found a copy of %s in the DeviceSupport dir %s", platform_file_path, os_version_dir); + } return error; + } ::snprintf (resolved_path, sizeof(resolved_path), @@ -689,7 +733,13 @@ PlatformRemoteAppleTV::GetSymbolFile (const FileSpec &platform_file, local_file.SetFile(resolved_path, true); if (local_file.Exists()) + { + if (log) + { + log->Printf ("Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal", platform_file_path, os_version_dir); + } return error; + } ::snprintf (resolved_path, sizeof(resolved_path), "%s/Symbols/%s", @@ -698,8 +748,13 @@ PlatformRemoteAppleTV::GetSymbolFile (const FileSpec &platform_file, local_file.SetFile(resolved_path, true); if (local_file.Exists()) + { + if (log) + { + log->Printf ("Found a copy of %s in the DeviceSupport dir %s/Symbols", platform_file_path, os_version_dir); + } return error; - + } } local_file = platform_file; if (local_file.Exists()) @@ -729,6 +784,7 @@ PlatformRemoteAppleTV::GetSharedModule (const ModuleSpec &module_spec, // then we attempt to get a shared module for the right architecture // with the right UUID. const FileSpec &platform_file = module_spec.GetFileSpec(); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | LIBLLDB_LOG_VERBOSE); Error error; char platform_file_path[PATH_MAX]; @@ -746,6 +802,10 @@ PlatformRemoteAppleTV::GetSharedModule (const ModuleSpec &module_spec, const uint32_t connected_sdk_idx = GetConnectedSDKIndex (); if (connected_sdk_idx < num_sdk_infos) { + if (log) + { + log->Printf ("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[connected_sdk_idx].directory.GetPath().c_str()); + } if (GetFileInSDK (platform_file_path, connected_sdk_idx, platform_module_spec.GetFileSpec())) { module_sp.reset(); @@ -765,6 +825,10 @@ PlatformRemoteAppleTV::GetSharedModule (const ModuleSpec &module_spec, // will tend to be valid in that same SDK. if (m_last_module_sdk_idx < num_sdk_infos) { + if (log) + { + log->Printf ("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[m_last_module_sdk_idx].directory.GetPath().c_str()); + } if (GetFileInSDK (platform_file_path, m_last_module_sdk_idx, platform_module_spec.GetFileSpec())) { module_sp.reset(); @@ -788,6 +852,10 @@ PlatformRemoteAppleTV::GetSharedModule (const ModuleSpec &module_spec, // it above continue; } + if (log) + { + log->Printf ("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[sdk_idx].directory.GetPath().c_str()); + } if (GetFileInSDK (platform_file_path, sdk_idx, platform_module_spec.GetFileSpec())) { //printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str()); @@ -812,6 +880,76 @@ PlatformRemoteAppleTV::GetSharedModule (const ModuleSpec &module_spec, if (error.Success()) return error; + // See if the file is present in any of the module_search_paths_ptr directories. + if (!module_sp && module_search_paths_ptr && platform_file) + { + // create a vector of all the file / directory names in platform_file + // e.g. this might be /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation + // + // We'll need to look in the module_search_paths_ptr directories for + // both "UIFoundation" and "UIFoundation.framework" -- most likely the + // latter will be the one we find there. + + FileSpec platform_pull_apart (platform_file); + std::vector path_parts; + ConstString unix_root_dir("/"); + while (true) + { + ConstString part = platform_pull_apart.GetLastPathComponent(); + platform_pull_apart.RemoveLastPathComponent(); + if (part.IsEmpty() || part == unix_root_dir) + break; + path_parts.push_back (part.AsCString()); + } + const size_t path_parts_size = path_parts.size(); + + size_t num_module_search_paths = module_search_paths_ptr->GetSize(); + for (size_t i = 0; i < num_module_search_paths; ++i) + { + // Create a new FileSpec with this module_search_paths_ptr + // plus just the filename ("UIFoundation"), then the parent + // dir plus filename ("UIFoundation.framework/UIFoundation") + // etc - up to four names (to handle "Foo.framework/Contents/MacOS/Foo") + + for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) + { + FileSpec path_to_try (module_search_paths_ptr->GetFileSpecAtIndex (i)); + + // Add the components backwards. For .../PrivateFrameworks/UIFoundation.framework/UIFoundation + // path_parts is + // [0] UIFoundation + // [1] UIFoundation.framework + // [2] PrivateFrameworks + // + // and if 'j' is 2, we want to append path_parts[1] and then path_parts[0], aka + // 'UIFoundation.framework/UIFoundation', to the module_search_paths_ptr path. + + for (int k = j; k >= 0; --k) + { + path_to_try.AppendPathComponent (path_parts[k]); + } + + if (path_to_try.Exists()) + { + ModuleSpec new_module_spec (module_spec); + new_module_spec.GetFileSpec() = path_to_try; + Error new_error (Platform::GetSharedModule (new_module_spec, + process, + module_sp, + NULL, + old_module_sp_ptr, + did_create_ptr)); + + if (module_sp) + { + module_sp->SetPlatformFileSpec (path_to_try); + return new_error; + } + } + } + } + } + const bool always_create = false; error = ModuleList::GetSharedModule (module_spec, module_sp, diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp index 808fd96a5284..ba59887ccf27 100644 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp @@ -158,14 +158,6 @@ PlatformRemoteAppleWatch::CreateInstance (bool force, const ArchSpec *arch) case llvm::Triple::WatchOS: // This is the right triple value for Apple Watch debugging break; -#if defined(__APPLE__) - // Only accept "unknown" for the OS if the host is Apple and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) - case llvm::Triple::UnknownOS: - create = !arch->TripleOSWasSpecified(); - break; -#endif default: create = false; break; @@ -322,9 +314,14 @@ PlatformRemoteAppleWatch::GetContainedFilesIntoVectorOfStringsCallback (void *ba bool PlatformRemoteAppleWatch::UpdateSDKDirectoryInfosIfNeeded() { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (m_sdk_directory_infos.empty()) { const char *device_support_dir = GetDeviceSupportDirectory(); + if (log) + { + log->Printf ("PlatformRemoteAppleWatch::UpdateSDKDirectoryInfosIfNeeded Got DeviceSupport directory %s", device_support_dir); + } if (device_support_dir) { const bool find_directories = true; @@ -349,12 +346,20 @@ PlatformRemoteAppleWatch::UpdateSDKDirectoryInfosIfNeeded() if (sdk_symbols_symlink_fspec.Exists()) { m_sdk_directory_infos.push_back(sdk_directory_info); + if (log) + { + log->Printf ("PlatformRemoteAppleWatch::UpdateSDKDirectoryInfosIfNeeded added builtin SDK directory %s", sdk_symbols_symlink_fspec.GetPath().c_str()); + } } else { sdk_symbols_symlink_fspec.GetFilename().SetCString("Symbols"); if (sdk_symbols_symlink_fspec.Exists()) m_sdk_directory_infos.push_back(sdk_directory_info); + if (log) + { + log->Printf ("PlatformRemoteAppleWatch::UpdateSDKDirectoryInfosIfNeeded added builtin SDK directory %s", sdk_symbols_symlink_fspec.GetPath().c_str()); + } } } @@ -374,6 +379,10 @@ PlatformRemoteAppleWatch::UpdateSDKDirectoryInfosIfNeeded() } if (local_sdk_cache.Exists()) { + if (log) + { + log->Printf ("PlatformRemoteAppleWatch::UpdateSDKDirectoryInfosIfNeeded searching %s for additional SDKs", local_sdk_cache.GetPath().c_str()); + } char path[PATH_MAX]; if (local_sdk_cache.GetPath(path, sizeof(path))) { @@ -388,6 +397,10 @@ PlatformRemoteAppleWatch::UpdateSDKDirectoryInfosIfNeeded() for (uint32_t i=num_installed; iPrintf ("PlatformRemoteAppleWatch::UpdateSDKDirectoryInfosIfNeeded user SDK directory %s", m_sdk_directory_infos[i].directory.GetPath().c_str()); + } } } } @@ -583,6 +596,7 @@ uint32_t PlatformRemoteAppleWatch::FindFileInAllSDKs (const char *platform_file_path, FileSpecList &file_list) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | LIBLLDB_LOG_VERBOSE); if (platform_file_path && platform_file_path[0] && UpdateSDKDirectoryInfosIfNeeded()) { const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); @@ -590,6 +604,10 @@ PlatformRemoteAppleWatch::FindFileInAllSDKs (const char *platform_file_path, // First try for an exact match of major, minor and update for (uint32_t sdk_idx=0; sdk_idxPrintf ("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[sdk_idx].directory.GetPath().c_str()); + } if (GetFileInSDK (platform_file_path, sdk_idx, local_file)) @@ -629,6 +647,7 @@ PlatformRemoteAppleWatch::GetFileInSDKRoot (const char *platform_file_path, bool symbols_dirs_only, lldb_private::FileSpec &local_file) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); if (sdkroot_path && sdkroot_path[0] && platform_file_path && platform_file_path[0]) { char resolved_path[PATH_MAX]; @@ -643,7 +662,13 @@ PlatformRemoteAppleWatch::GetFileInSDKRoot (const char *platform_file_path, local_file.SetFile(resolved_path, true); if (local_file.Exists()) + { + if (log) + { + log->Printf ("Found a copy of %s in the SDK dir %s", platform_file_path, sdkroot_path); + } return true; + } } ::snprintf (resolved_path, @@ -654,7 +679,13 @@ PlatformRemoteAppleWatch::GetFileInSDKRoot (const char *platform_file_path, local_file.SetFile(resolved_path, true); if (local_file.Exists()) + { + if (log) + { + log->Printf ("Found a copy of %s in the SDK dir %s/Symbols.Internal", platform_file_path, sdkroot_path); + } return true; + } ::snprintf (resolved_path, sizeof(resolved_path), "%s/Symbols%s", @@ -663,7 +694,13 @@ PlatformRemoteAppleWatch::GetFileInSDKRoot (const char *platform_file_path, local_file.SetFile(resolved_path, true); if (local_file.Exists()) + { + if (log) + { + log->Printf ("Found a copy of %s in the SDK dir %s/Symbols", platform_file_path, sdkroot_path); + } return true; + } } return false; } @@ -673,6 +710,7 @@ PlatformRemoteAppleWatch::GetSymbolFile (const FileSpec &platform_file, const UUID *uuid_ptr, FileSpec &local_file) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); Error error; char platform_file_path[PATH_MAX]; if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) @@ -690,7 +728,13 @@ PlatformRemoteAppleWatch::GetSymbolFile (const FileSpec &platform_file, local_file.SetFile(resolved_path, true); if (local_file.Exists()) + { + if (log) + { + log->Printf ("Found a copy of %s in the DeviceSupport dir %s", platform_file_path, os_version_dir); + } return error; + } ::snprintf (resolved_path, sizeof(resolved_path), @@ -700,7 +744,13 @@ PlatformRemoteAppleWatch::GetSymbolFile (const FileSpec &platform_file, local_file.SetFile(resolved_path, true); if (local_file.Exists()) + { + if (log) + { + log->Printf ("Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal", platform_file_path, os_version_dir); + } return error; + } ::snprintf (resolved_path, sizeof(resolved_path), "%s/Symbols/%s", @@ -709,7 +759,13 @@ PlatformRemoteAppleWatch::GetSymbolFile (const FileSpec &platform_file, local_file.SetFile(resolved_path, true); if (local_file.Exists()) + { + if (log) + { + log->Printf ("Found a copy of %s in the DeviceSupport dir %s/Symbols", platform_file_path, os_version_dir); + } return error; + } } local_file = platform_file; @@ -740,6 +796,7 @@ PlatformRemoteAppleWatch::GetSharedModule (const ModuleSpec &module_spec, // then we attempt to get a shared module for the right architecture // with the right UUID. const FileSpec &platform_file = module_spec.GetFileSpec(); + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST | LIBLLDB_LOG_VERBOSE); Error error; char platform_file_path[PATH_MAX]; @@ -757,6 +814,10 @@ PlatformRemoteAppleWatch::GetSharedModule (const ModuleSpec &module_spec, const uint32_t connected_sdk_idx = GetConnectedSDKIndex (); if (connected_sdk_idx < num_sdk_infos) { + if (log) + { + log->Printf ("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[connected_sdk_idx].directory.GetPath().c_str()); + } if (GetFileInSDK (platform_file_path, connected_sdk_idx, platform_module_spec.GetFileSpec())) { module_sp.reset(); @@ -776,6 +837,10 @@ PlatformRemoteAppleWatch::GetSharedModule (const ModuleSpec &module_spec, // will tend to be valid in that same SDK. if (m_last_module_sdk_idx < num_sdk_infos) { + if (log) + { + log->Printf ("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[m_last_module_sdk_idx].directory.GetPath().c_str()); + } if (GetFileInSDK (platform_file_path, m_last_module_sdk_idx, platform_module_spec.GetFileSpec())) { module_sp.reset(); @@ -799,6 +864,10 @@ PlatformRemoteAppleWatch::GetSharedModule (const ModuleSpec &module_spec, // it above continue; } + if (log) + { + log->Printf ("Searching for %s in sdk path %s", platform_file_path, m_sdk_directory_infos[sdk_idx].directory.GetPath().c_str()); + } if (GetFileInSDK (platform_file_path, sdk_idx, platform_module_spec.GetFileSpec())) { //printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str()); @@ -823,6 +892,76 @@ PlatformRemoteAppleWatch::GetSharedModule (const ModuleSpec &module_spec, if (error.Success()) return error; + // See if the file is present in any of the module_search_paths_ptr directories. + if (!module_sp && module_search_paths_ptr && platform_file) + { + // create a vector of all the file / directory names in platform_file + // e.g. this might be /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation + // + // We'll need to look in the module_search_paths_ptr directories for + // both "UIFoundation" and "UIFoundation.framework" -- most likely the + // latter will be the one we find there. + + FileSpec platform_pull_apart (platform_file); + std::vector path_parts; + ConstString unix_root_dir("/"); + while (true) + { + ConstString part = platform_pull_apart.GetLastPathComponent(); + platform_pull_apart.RemoveLastPathComponent(); + if (part.IsEmpty() || part == unix_root_dir) + break; + path_parts.push_back (part.AsCString()); + } + const size_t path_parts_size = path_parts.size(); + + size_t num_module_search_paths = module_search_paths_ptr->GetSize(); + for (size_t i = 0; i < num_module_search_paths; ++i) + { + // Create a new FileSpec with this module_search_paths_ptr + // plus just the filename ("UIFoundation"), then the parent + // dir plus filename ("UIFoundation.framework/UIFoundation") + // etc - up to four names (to handle "Foo.framework/Contents/MacOS/Foo") + + for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) + { + FileSpec path_to_try (module_search_paths_ptr->GetFileSpecAtIndex (i)); + + // Add the components backwards. For .../PrivateFrameworks/UIFoundation.framework/UIFoundation + // path_parts is + // [0] UIFoundation + // [1] UIFoundation.framework + // [2] PrivateFrameworks + // + // and if 'j' is 2, we want to append path_parts[1] and then path_parts[0], aka + // 'UIFoundation.framework/UIFoundation', to the module_search_paths_ptr path. + + for (int k = j; k >= 0; --k) + { + path_to_try.AppendPathComponent (path_parts[k]); + } + + if (path_to_try.Exists()) + { + ModuleSpec new_module_spec (module_spec); + new_module_spec.GetFileSpec() = path_to_try; + Error new_error (Platform::GetSharedModule (new_module_spec, + process, + module_sp, + NULL, + old_module_sp_ptr, + did_create_ptr)); + + if (module_sp) + { + module_sp->SetPlatformFileSpec (path_to_try); + return new_error; + } + } + } + } + } + const bool always_create = false; error = ModuleList::GetSharedModule (module_spec, module_sp, diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp index 75afa9019dcd..abc429a72345 100644 --- a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp @@ -142,14 +142,6 @@ PlatformRemoteiOS::CreateInstance (bool force, const ArchSpec *arch) case llvm::Triple::IOS: // This is the right triple value for iOS debugging break; -#if defined(__APPLE__) - // Only accept "unknown" for the OS if the host is Apple and - // it "unknown" wasn't specified (it was just returned because it - // was NOT specified) - case llvm::Triple::UnknownOS: - create = !arch->TripleOSWasSpecified(); - break; -#endif default: create = false; break; @@ -913,6 +905,76 @@ PlatformRemoteiOS::GetSharedModule (const ModuleSpec &module_spec, if (error.Success()) return error; + // See if the file is present in any of the module_search_paths_ptr directories. + if (!module_sp && module_search_paths_ptr && platform_file) + { + // create a vector of all the file / directory names in platform_file + // e.g. this might be /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation + // + // We'll need to look in the module_search_paths_ptr directories for + // both "UIFoundation" and "UIFoundation.framework" -- most likely the + // latter will be the one we find there. + + FileSpec platform_pull_apart (platform_file); + std::vector path_parts; + ConstString unix_root_dir("/"); + while (true) + { + ConstString part = platform_pull_apart.GetLastPathComponent(); + platform_pull_apart.RemoveLastPathComponent(); + if (part.IsEmpty() || part == unix_root_dir) + break; + path_parts.push_back (part.AsCString()); + } + const size_t path_parts_size = path_parts.size(); + + size_t num_module_search_paths = module_search_paths_ptr->GetSize(); + for (size_t i = 0; i < num_module_search_paths; ++i) + { + // Create a new FileSpec with this module_search_paths_ptr + // plus just the filename ("UIFoundation"), then the parent + // dir plus filename ("UIFoundation.framework/UIFoundation") + // etc - up to four names (to handle "Foo.framework/Contents/MacOS/Foo") + + for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) + { + FileSpec path_to_try (module_search_paths_ptr->GetFileSpecAtIndex (i)); + + // Add the components backwards. For .../PrivateFrameworks/UIFoundation.framework/UIFoundation + // path_parts is + // [0] UIFoundation + // [1] UIFoundation.framework + // [2] PrivateFrameworks + // + // and if 'j' is 2, we want to append path_parts[1] and then path_parts[0], aka + // 'UIFoundation.framework/UIFoundation', to the module_search_paths_ptr path. + + for (int k = j; k >= 0; --k) + { + path_to_try.AppendPathComponent (path_parts[k]); + } + + if (path_to_try.Exists()) + { + ModuleSpec new_module_spec (module_spec); + new_module_spec.GetFileSpec() = path_to_try; + Error new_error (Platform::GetSharedModule (new_module_spec, + process, + module_sp, + NULL, + old_module_sp_ptr, + did_create_ptr)); + + if (module_sp) + { + module_sp->SetPlatformFileSpec (path_to_try); + return new_error; + } + } + } + } + } + const bool always_create = false; error = ModuleList::GetSharedModule (module_spec, module_sp, diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp index cbe9c7949a4a..99b9324417b5 100644 --- a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp +++ b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp @@ -308,7 +308,7 @@ EnumerateDirectoryCallback (void *baton, FileSpec::FileType file_type, const Fil const char * PlatformiOSSimulator::GetSDKDirectoryAsCString() { - Mutex::Locker locker (m_mutex); + std::lock_guard guard(m_mutex); if (m_sdk_directory.empty()) { const char *developer_dir = GetDeveloperDirectory(); diff --git a/source/Plugins/Platform/Makefile b/source/Plugins/Platform/Makefile deleted file mode 100644 index 572b08644074..000000000000 --- a/source/Plugins/Platform/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -##===- source/Plugins/Platform/Makefile --------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../.. - -include $(LLDB_LEVEL)/../../Makefile.config - -PARALLEL_DIRS := gdb-server MacOSX Linux FreeBSD NetBSD POSIX Windows Kalimba Android - -# ifeq ($(HOST_OS),Darwin) -# DIRS += MacOSX -# endif -# -# ifeq ($(HOST_OS),Linux) -# DIRS += Linux -# endif -# -# ifeq ($(HOST_OS),FreeBSD) -# DIRS += FreeBSD -# endif -# -# ifeq ($(HOST_OS),GNU/kFreeBSD) -# DIRS += FreeBSD -# endif -# -# ifeq ($(HOST_OS),NetBSD) -# DIRS += NetBSD -# endif - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Platform/NetBSD/Makefile b/source/Plugins/Platform/NetBSD/Makefile deleted file mode 100644 index 2c480bdbe8da..000000000000 --- a/source/Plugins/Platform/NetBSD/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Platform/NetBSD/Makefile ------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginPlatformNetBSD -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp b/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp index 2979d1e438b7..3482d2ae5e20 100644 --- a/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp +++ b/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp @@ -585,34 +585,6 @@ PlatformNetBSD::GetStatus (Stream &strm) 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 () { diff --git a/source/Plugins/Platform/NetBSD/PlatformNetBSD.h b/source/Plugins/Platform/NetBSD/PlatformNetBSD.h index b0187be99b05..46d1d1843c63 100644 --- a/source/Plugins/Platform/NetBSD/PlatformNetBSD.h +++ b/source/Plugins/Platform/NetBSD/PlatformNetBSD.h @@ -86,10 +86,6 @@ namespace platform_netbsd { lldb::ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr) override; - size_t - GetSoftwareBreakpointTrapOpcode(Target &target, - BreakpointSite *bp_site) override; - bool GetRemoteOSVersion () override; diff --git a/source/Plugins/Platform/POSIX/Makefile b/source/Plugins/Platform/POSIX/Makefile deleted file mode 100644 index eca927720ba8..000000000000 --- a/source/Plugins/Platform/POSIX/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Platform/POSIX/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginPlatformPOSIX -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp index c7564655a11b..bc890695f0ce 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp @@ -41,6 +41,9 @@ using namespace lldb_private; //------------------------------------------------------------------ PlatformPOSIX::PlatformPOSIX (bool is_host) : Platform(is_host), // This is the local host platform +m_option_group_platform_rsync(new OptionGroupPlatformRSync()), +m_option_group_platform_ssh(new OptionGroupPlatformSSH()), +m_option_group_platform_caching(new OptionGroupPlatformCaching()), m_remote_platform_sp () { } @@ -69,14 +72,17 @@ PlatformPOSIX::GetModuleSpec (const FileSpec& module_file_spec, lldb_private::OptionGroupOptions* PlatformPOSIX::GetConnectionOptions (lldb_private::CommandInterpreter& interpreter) { - if (m_options.get() == NULL) + auto iter = m_options.find(&interpreter), end = m_options.end(); + if (iter == end) { - m_options.reset(new OptionGroupOptions(interpreter)); - m_options->Append(new OptionGroupPlatformRSync()); - m_options->Append(new OptionGroupPlatformSSH()); - m_options->Append(new OptionGroupPlatformCaching()); + std::unique_ptr options(new OptionGroupOptions(interpreter)); + options->Append(m_option_group_platform_rsync.get()); + options->Append(m_option_group_platform_ssh.get()); + options->Append(m_option_group_platform_caching.get()); + m_options[&interpreter] = std::move(options); } - return m_options.get(); + + return m_options.at(&interpreter).get(); } bool @@ -675,29 +681,21 @@ PlatformPOSIX::ConnectRemote (Args& args) if (error.Success() && m_remote_platform_sp) { - if (m_options.get()) + if (m_option_group_platform_rsync.get() && m_option_group_platform_ssh.get() && m_option_group_platform_caching.get()) { - OptionGroupOptions* options = m_options.get(); - const OptionGroupPlatformRSync *m_rsync_options = - static_cast(options->GetGroupWithOption('r')); - const OptionGroupPlatformSSH *m_ssh_options = - static_cast(options->GetGroupWithOption('s')); - const OptionGroupPlatformCaching *m_cache_options = - static_cast(options->GetGroupWithOption('c')); - - if (m_rsync_options->m_rsync) + if (m_option_group_platform_rsync->m_rsync) { SetSupportsRSync(true); - SetRSyncOpts(m_rsync_options->m_rsync_opts.c_str()); - SetRSyncPrefix(m_rsync_options->m_rsync_prefix.c_str()); - SetIgnoresRemoteHostname(m_rsync_options->m_ignores_remote_hostname); + SetRSyncOpts(m_option_group_platform_rsync->m_rsync_opts.c_str()); + SetRSyncPrefix(m_option_group_platform_rsync->m_rsync_prefix.c_str()); + SetIgnoresRemoteHostname(m_option_group_platform_rsync->m_ignores_remote_hostname); } - if (m_ssh_options->m_ssh) + if (m_option_group_platform_ssh->m_ssh) { SetSupportsSSH(true); - SetSSHOpts(m_ssh_options->m_ssh_opts.c_str()); + SetSSHOpts(m_option_group_platform_ssh->m_ssh_opts.c_str()); } - SetLocalCacheDirectory(m_cache_options->m_cache_dir.c_str()); + SetLocalCacheDirectory(m_option_group_platform_caching->m_cache_dir.c_str()); } } @@ -801,13 +799,13 @@ PlatformPOSIX::Attach (ProcessAttachInfo &attach_info, if (process_sp) { - auto listener_sp = attach_info.GetHijackListener(); + ListenerSP listener_sp = attach_info.GetHijackListener(); if (listener_sp == nullptr) { - listener_sp.reset(new Listener("lldb.PlatformPOSIX.attach.hijack")); + listener_sp = Listener::MakeListener("lldb.PlatformPOSIX.attach.hijack"); attach_info.SetHijackListener(listener_sp); } - process_sp->HijackProcessEvents(listener_sp.get()); + process_sp->HijackProcessEvents(listener_sp); error = process_sp->Attach (attach_info); } } @@ -869,7 +867,7 @@ PlatformPOSIX::EvaluateLibdlExpression(lldb_private::Process* process, return error; } - ThreadSP thread_sp(process->GetThreadList().GetSelectedThread()); + ThreadSP thread_sp(process->GetThreadList().GetExpressionExecutionThread()); if (!thread_sp) return Error("Selected thread isn't valid"); @@ -884,6 +882,7 @@ PlatformPOSIX::EvaluateLibdlExpression(lldb_private::Process* process, expr_options.SetIgnoreBreakpoints(true); expr_options.SetExecutionPolicy(eExecutionPolicyAlways); expr_options.SetLanguage(eLanguageTypeC_plus_plus); + expr_options.SetTimeoutUsec(2000000); // 2 seconds Error expr_error; UserExpression::Evaluate(exe_ctx, @@ -945,7 +944,7 @@ PlatformPOSIX::DoLoadImage(lldb_private::Process* process, if (image_ptr == 0) { ValueObjectSP error_str_sp = result_valobj_sp->GetChildAtIndex(1, true); - if (error_str_sp && error_str_sp->IsCStringContainer(true)) + if (error_str_sp) { DataBufferSP buffer_sp(new DataBufferHeap(10240,0)); size_t num_chars = error_str_sp->ReadPointedString (buffer_sp, error, 10240).first; diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h index 60f6207d140b..4f1f22002816 100644 --- a/source/Plugins/Platform/POSIX/PlatformPOSIX.h +++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h @@ -12,6 +12,7 @@ // C Includes // C++ Includes +#include #include // Other libraries and framework includes @@ -192,7 +193,11 @@ public: ConnectToWaitingProcesses(lldb_private::Debugger& debugger, lldb_private::Error& error) override; protected: - std::unique_ptr m_options; + std::unique_ptr m_option_group_platform_rsync; + std::unique_ptr m_option_group_platform_ssh; + std::unique_ptr m_option_group_platform_caching; + + std::map> m_options; lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote POSIX-compliant OS lldb_private::Error diff --git a/source/Plugins/Platform/Windows/Makefile b/source/Plugins/Platform/Windows/Makefile deleted file mode 100644 index b78cd7bfd080..000000000000 --- a/source/Plugins/Platform/Windows/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Platform/Windows/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginPlatformWindows -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Platform/Windows/PlatformWindows.cpp b/source/Plugins/Platform/Windows/PlatformWindows.cpp index 4172f80176d3..cef5684d9bac 100644 --- a/source/Plugins/Platform/Windows/PlatformWindows.cpp +++ b/source/Plugins/Platform/Windows/PlatformWindows.cpp @@ -321,42 +321,6 @@ PlatformWindows::ResolveExecutable (const ModuleSpec &ms, return error; } -size_t -PlatformWindows::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site) -{ - ArchSpec arch = target.GetArchitecture(); - const uint8_t *trap_opcode = nullptr; - size_t trap_opcode_size = 0; - - switch (arch.GetMachine()) - { - 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; - - case llvm::Triple::hexagon: - { - static const uint8_t g_hex_opcode[] = { 0x0c, 0xdb, 0x00, 0x54 }; - trap_opcode = g_hex_opcode; - trap_opcode_size = sizeof(g_hex_opcode); - } - break; - default: - llvm_unreachable("Unhandled architecture in PlatformWindows::GetSoftwareBreakpointTrapOpcode()"); - break; - } - - if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) - return trap_opcode_size; - - return 0; -} - bool PlatformWindows::GetRemoteOSVersion () { @@ -601,7 +565,7 @@ PlatformWindows::Attach(ProcessAttachInfo &attach_info, const char *plugin_name = attach_info.GetProcessPluginName(); process_sp = target->CreateProcess(attach_info.GetListenerForProcess(debugger), plugin_name, nullptr); - process_sp->HijackProcessEvents(attach_info.GetHijackListener().get()); + process_sp->HijackProcessEvents(attach_info.GetHijackListener()); if (process_sp) error = process_sp->Attach (attach_info); diff --git a/source/Plugins/Platform/Windows/PlatformWindows.h b/source/Plugins/Platform/Windows/PlatformWindows.h index e9a04b4cc33d..6af178bb8c26 100644 --- a/source/Plugins/Platform/Windows/PlatformWindows.h +++ b/source/Plugins/Platform/Windows/PlatformWindows.h @@ -72,10 +72,6 @@ public: return GetPluginDescriptionStatic(IsHost()); } - size_t - GetSoftwareBreakpointTrapOpcode(lldb_private::Target &target, - lldb_private::BreakpointSite *bp_site) override; - bool GetRemoteOSVersion() override; diff --git a/source/Plugins/Platform/gdb-server/Makefile b/source/Plugins/Platform/gdb-server/Makefile deleted file mode 100644 index c56613b2a653..000000000000 --- a/source/Plugins/Platform/gdb-server/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Platform/gdb-server/Makefile ---------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginPlatformGDB -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index f16ea017676f..e64ed66be3ca 100644 --- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -714,9 +714,9 @@ PlatformRemoteGDBServer::Attach (ProcessAttachInfo &attach_info, error = process_sp->ConnectRemote(nullptr, connect_url.c_str()); if (error.Success()) { - auto listener = attach_info.GetHijackListener(); - if (listener != nullptr) - process_sp->HijackProcessEvents(listener.get()); + ListenerSP listener_sp = attach_info.GetHijackListener(); + if (listener_sp) + process_sp->HijackProcessEvents(listener_sp); error = process_sp->Attach(attach_info); } @@ -1001,6 +1001,22 @@ PlatformRemoteGDBServer::ConnectProcess(const char* connect_url, return Platform::ConnectProcess(connect_url, plugin_name, debugger, target, error); } +size_t +PlatformRemoteGDBServer::ConnectToWaitingProcesses(Debugger& debugger, Error& error) +{ + std::vector connection_urls; + GetPendingGdbServerList(connection_urls); + + for (size_t i = 0; i < connection_urls.size(); ++i) + { + ConnectProcess(connection_urls[i].c_str(), nullptr, debugger, nullptr, error); + if (error.Fail()) + return i; // We already connected to i process succsessfully + } + return connection_urls.size(); + +} + size_t PlatformRemoteGDBServer::GetPendingGdbServerList(std::vector& connection_urls) { diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h index 61136f1185e6..9d640f3c174b 100644 --- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -224,6 +224,9 @@ public: lldb_private::Target *target, lldb_private::Error &error) override; + size_t + ConnectToWaitingProcesses(lldb_private::Debugger& debugger, lldb_private::Error& error) override; + virtual size_t GetPendingGdbServerList(std::vector& connection_urls); diff --git a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp index 2b292442399f..3cb1cec6983f 100644 --- a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp +++ b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp @@ -558,22 +558,40 @@ FreeBSDThread::WatchNotify(const ProcessMessage &message) void FreeBSDThread::TraceNotify(const ProcessMessage &message) { - POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); - if (reg_ctx) + Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); + + // Try to resolve the breakpoint object corresponding to the 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 current pc is a breakpoint site then set the StopInfo to Breakpoint. + // Otherwise, set the StopInfo to Watchpoint or Trace. + // 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 && (bp_site->ValidForThisThread(this) || GetProcess()->GetOperatingSystem () != NULL)) + SetStopInfo(StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_site->GetID())); + else { - uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints(); - uint32_t wp_idx; - for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) + POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol(); + if (reg_ctx) { - if (reg_ctx->IsWatchpointHit(wp_idx)) + uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints(); + uint32_t wp_idx; + for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++) { - WatchNotify(message); - return; + if (reg_ctx->IsWatchpointHit(wp_idx)) + { + WatchNotify(message); + return; + } } } + SetStopInfo (StopInfo::CreateStopReasonToTrace(*this)); } - - SetStopInfo (StopInfo::CreateStopReasonToTrace(*this)); } void diff --git a/source/Plugins/Process/FreeBSD/Makefile b/source/Plugins/Process/FreeBSD/Makefile deleted file mode 100644 index 7f546540e556..000000000000 --- a/source/Plugins/Process/FreeBSD/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -##===- source/Plugins/Process/FreeBSD/Makefile ---------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginProcessFreeBSD -BUILD_ARCHIVE = 1 - -# Extend the include path so we may locate UnwindLLDB.h -CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp index 769ccd7248ac..3a72a65da696 100644 --- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp @@ -63,12 +63,12 @@ namespace lldb::ProcessSP ProcessFreeBSD::CreateInstance(lldb::TargetSP target_sp, - Listener &listener, + lldb::ListenerSP listener_sp, const FileSpec *crash_file_path) { lldb::ProcessSP process_sp; if (crash_file_path == NULL) - process_sp.reset(new ProcessFreeBSD (target_sp, listener, GetFreeBSDSignals())); + process_sp.reset(new ProcessFreeBSD (target_sp, listener_sp, GetFreeBSDSignals())); return process_sp; } @@ -143,7 +143,7 @@ ProcessFreeBSD::DoResume() SetPrivateState(eStateRunning); - Mutex::Locker lock(m_thread_list.GetMutex()); + std::lock_guard guard(m_thread_list.GetMutex()); bool do_step = false; for (tid_collection::const_iterator t_pos = m_run_tids.begin(), t_end = m_run_tids.end(); t_pos != t_end; ++t_pos) @@ -229,7 +229,7 @@ ProcessFreeBSD::WillResume() void ProcessFreeBSD::SendMessage(const ProcessMessage &message) { - Mutex::Locker lock(m_message_mutex); + std::lock_guard guard(m_message_mutex); switch (message.GetKind()) { @@ -269,12 +269,12 @@ ProcessFreeBSD::SendMessage(const ProcessMessage &message) //------------------------------------------------------------------------------ // Constructors and destructors. -ProcessFreeBSD::ProcessFreeBSD(lldb::TargetSP target_sp, Listener &listener, UnixSignalsSP &unix_signals_sp) - : Process(target_sp, listener, unix_signals_sp), +ProcessFreeBSD::ProcessFreeBSD(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, UnixSignalsSP &unix_signals_sp) + : Process(target_sp, listener_sp, unix_signals_sp), m_byte_order(endian::InlHostByteOrder()), m_monitor(NULL), m_module(NULL), - m_message_mutex (Mutex::eMutexTypeRecursive), + m_message_mutex(), m_exit_now(false), m_seen_initial_stop(), m_resume_signo(0) @@ -603,7 +603,7 @@ ProcessFreeBSD::RefreshStateAfterStop() 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); + std::lock_guard guard(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 @@ -630,7 +630,7 @@ ProcessFreeBSD::RefreshStateAfterStop() if (log) log->Printf ("ProcessFreeBSD::%s() removing thread, tid = %" PRIi64, __FUNCTION__, tid); - Mutex::Locker lock(m_thread_list.GetMutex()); + std::lock_guard guard(m_thread_list.GetMutex()); ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false); thread_sp.reset(); @@ -801,7 +801,7 @@ ProcessFreeBSD::EnableWatchpoint(Watchpoint *wp, bool notify) // 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()); + std::lock_guard guard(m_thread_list.GetMutex()); FreeBSDThread *thread = static_cast( m_thread_list.GetThreadAtIndex(0, false).get()); @@ -871,7 +871,7 @@ ProcessFreeBSD::DisableWatchpoint(Watchpoint *wp, bool notify) if (wp->IsHardware()) { bool wp_disabled = true; - Mutex::Locker lock(m_thread_list.GetMutex()); + std::lock_guard guard(m_thread_list.GetMutex()); uint32_t thread_count = m_thread_list.GetSize(false); for (uint32_t i = 0; i < thread_count; ++i) { @@ -901,7 +901,7 @@ Error ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num) { Error error; - Mutex::Locker lock(m_thread_list.GetMutex()); + std::lock_guard guard(m_thread_list.GetMutex()); FreeBSDThread *thread = static_cast( m_thread_list.GetThreadAtIndex(0, false).get()); if (thread) @@ -924,7 +924,7 @@ ProcessFreeBSD::GetWatchpointSupportInfo(uint32_t &num, bool &after) uint32_t ProcessFreeBSD::UpdateThreadListIfNeeded() { - Mutex::Locker lock(m_thread_list.GetMutex()); + std::lock_guard guard(m_thread_list.GetMutex()); // Do not allow recursive updates. return m_thread_list.GetSize(false); } @@ -1015,7 +1015,7 @@ bool ProcessFreeBSD::IsAThreadRunning() { bool is_running = false; - Mutex::Locker lock(m_thread_list.GetMutex()); + std::lock_guard guard(m_thread_list.GetMutex()); uint32_t thread_count = m_thread_list.GetSize(false); for (uint32_t i = 0; i < thread_count; ++i) { diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h index 5f9365418d7a..888e2a90ad76 100644 --- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h +++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h @@ -13,8 +13,9 @@ // C Includes // C++ Includes -#include +#include #include +#include // Other libraries and framework includes #include "lldb/Target/Process.h" @@ -35,7 +36,7 @@ public: //------------------------------------------------------------------ static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp, - lldb_private::Listener &listener, + lldb::ListenerSP listener_sp, const lldb_private::FileSpec *crash_file_path); static void @@ -54,7 +55,7 @@ public: // Constructors and destructors //------------------------------------------------------------------ ProcessFreeBSD(lldb::TargetSP target_sp, - lldb_private::Listener &listener, + lldb::ListenerSP listener_sp, lldb::UnixSignalsSP &unix_signals_sp); ~ProcessFreeBSD(); @@ -212,7 +213,7 @@ protected: lldb_private::Module *m_module; /// Message queue notifying this instance of inferior process state changes. - lldb_private::Mutex m_message_mutex; + std::recursive_mutex m_message_mutex; std::queue m_message_queue; /// Drive any exit events to completion. diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp index cd016fbd4b8c..16707a5c8b97 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp @@ -819,6 +819,8 @@ ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process, m_terminal_fd(-1), m_operation(0) { + using namespace std::placeholders; + std::unique_ptr args(new LaunchArgs(this, module, argv, envp, stdin_file_spec, stdout_file_spec, @@ -856,7 +858,7 @@ WAIT_AGAIN: // Finally, start monitoring the child process for change in state. m_monitor_thread = Host::StartMonitoringChildProcess( - ProcessMonitor::MonitorCallback, this, GetPID(), true); + std::bind(&ProcessMonitor::MonitorCallback, this, _1, _2, _3, _4), GetPID(), true); if (!m_monitor_thread.IsJoinable()) { error.SetErrorToGenericError(); @@ -873,6 +875,8 @@ ProcessMonitor::ProcessMonitor(ProcessFreeBSD *process, m_terminal_fd(-1), m_operation(0) { + using namespace std::placeholders; + sem_init(&m_operation_pending, 0, 0); sem_init(&m_operation_done, 0, 0); @@ -906,7 +910,7 @@ WAIT_AGAIN: // Finally, start monitoring the child process for change in state. m_monitor_thread = Host::StartMonitoringChildProcess( - ProcessMonitor::MonitorCallback, this, GetPID(), true); + std::bind(&ProcessMonitor::MonitorCallback, this, _1, _2, _3, _4), GetPID(), true); if (!m_monitor_thread.IsJoinable()) { error.SetErrorToGenericError(); @@ -1180,14 +1184,9 @@ ProcessMonitor::GetCurrentThreadIDs(std::vector&thread_ids) } bool -ProcessMonitor::MonitorCallback(void *callback_baton, - lldb::pid_t pid, - bool exited, - int signal, - int status) +ProcessMonitor::MonitorCallback(ProcessMonitor *monitor, lldb::pid_t pid, bool exited, int signal, int status) { ProcessMessage message; - ProcessMonitor *monitor = static_cast(callback_baton); ProcessFreeBSD *process = monitor->m_process; assert(process); bool stop_monitoring; @@ -1349,7 +1348,7 @@ ProcessMonitor::ServeOperation(OperationArgs *args) void ProcessMonitor::DoOperation(Operation *op) { - Mutex::Locker lock(m_operation_mutex); + std::lock_guard guard(m_operation_mutex); m_operation = op; diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h index 07fa6b7869ad..93f6be111361 100644 --- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h +++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h @@ -15,11 +15,12 @@ #include // C++ Includes +#include + // Other libraries and framework includes #include "lldb/lldb-types.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/HostThread.h" -#include "lldb/Host/Mutex.h" namespace lldb_private { @@ -223,7 +224,7 @@ private: // current operation which must be executed on the privileged thread Operation *m_operation; - lldb_private::Mutex m_operation_mutex; + std::mutex m_operation_mutex; // semaphores notified when Operation is ready to be processed and when // the operation is complete. @@ -302,8 +303,7 @@ private: DupDescriptor(const lldb_private::FileSpec &file_spec, int fd, int flags); static bool - MonitorCallback(void *callback_baton, - lldb::pid_t pid, bool exited, int signal, int status); + MonitorCallback(ProcessMonitor *monitor, lldb::pid_t pid, bool exited, int signal, int status); static ProcessMessage MonitorSIGTRAP(ProcessMonitor *monitor, diff --git a/source/Plugins/Process/Linux/CMakeLists.txt b/source/Plugins/Process/Linux/CMakeLists.txt index 80de8413d209..8291fef467e3 100644 --- a/source/Plugins/Process/Linux/CMakeLists.txt +++ b/source/Plugins/Process/Linux/CMakeLists.txt @@ -9,6 +9,8 @@ add_lldb_library(lldbPluginProcessLinux NativeRegisterContextLinux_arm64.cpp NativeRegisterContextLinux_x86_64.cpp NativeRegisterContextLinux_mips64.cpp + NativeRegisterContextLinux_s390x.cpp NativeThreadLinux.cpp ProcFileReader.cpp + SingleStepCheck.cpp ) diff --git a/source/Plugins/Process/Linux/Makefile b/source/Plugins/Process/Linux/Makefile deleted file mode 100644 index 239e94d608e9..000000000000 --- a/source/Plugins/Process/Linux/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -##===- source/Plugins/Process/Linux/Makefile ---------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginProcessLinux -BUILD_ARCHIVE = 1 - -# Extend the include path so we may locate UnwindLLDB.h -CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/source/Plugins/Process/Linux/NativeProcessLinux.cpp index 87c76f57830c..b3842302c6db 100644 --- a/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -25,15 +25,14 @@ // Other libraries and framework includes #include "lldb/Core/EmulateInstruction.h" #include "lldb/Core/Error.h" -#include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/State.h" -#include "lldb/Host/common/NativeBreakpoint.h" -#include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Host/Host.h" #include "lldb/Host/ThreadLauncher.h" -#include "lldb/Target/Platform.h" +#include "lldb/Host/common/NativeBreakpoint.h" +#include "lldb/Host/common/NativeRegisterContext.h" +#include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Process.h" #include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Target/Target.h" @@ -58,7 +57,6 @@ #include "lldb/Host/linux/Personality.h" #include "lldb/Host/linux/Ptrace.h" -#include "lldb/Host/linux/Signalfd.h" #include "lldb/Host/linux/Uio.h" #include "lldb/Host/android/Android.h" @@ -111,45 +109,96 @@ static bool ProcessVmReadvSupported() namespace { - Error - ResolveProcessArchitecture (lldb::pid_t pid, Platform &platform, ArchSpec &arch) - { - // Grab process info for the running process. - ProcessInstanceInfo process_info; - if (!platform.GetProcessInfo (pid, process_info)) - return Error("failed to get process info"); +Error +ResolveProcessArchitecture(lldb::pid_t pid, ArchSpec &arch) +{ + // Grab process info for the running process. + ProcessInstanceInfo process_info; + if (!Host::GetProcessInfo(pid, process_info)) + return Error("failed to get process info"); - // Resolve the executable module. - ModuleSP exe_module_sp; - ModuleSpec exe_module_spec(process_info.GetExecutableFile(), process_info.GetArchitecture()); - FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths ()); - Error error = platform.ResolveExecutable( - exe_module_spec, - exe_module_sp, - executable_search_paths.GetSize () ? &executable_search_paths : NULL); + // Resolve the executable module. + ModuleSpecList module_specs; + if (!ObjectFile::GetModuleSpecifications(process_info.GetExecutableFile(), 0, 0, module_specs)) + return Error("failed to get module specifications"); + assert(module_specs.GetSize() == 1); - if (!error.Success ()) - return error; + arch = module_specs.GetModuleSpecRefAtIndex(0).GetArchitecture(); + if (arch.IsValid()) + return Error(); + else + return Error("failed to retrieve a valid architecture from the exe module"); +} - // Check if we've got our architecture from the exe_module. - arch = exe_module_sp->GetArchitecture (); - if (arch.IsValid ()) - return Error(); - else - return Error("failed to retrieve a valid architecture from the exe module"); - } +// Used to notify the parent about which part of the launch sequence failed. +enum LaunchCallSpecifier +{ + ePtraceFailed, + eDupStdinFailed, + eDupStdoutFailed, + eDupStderrFailed, + eChdirFailed, + eExecFailed, + eSetGidFailed, + eSetSigMaskFailed, + eLaunchCallMax = eSetSigMaskFailed +}; - void - DisplayBytes (StreamString &s, void *bytes, uint32_t count) +static uint8_t LLVM_ATTRIBUTE_NORETURN +ExitChildAbnormally(LaunchCallSpecifier spec) +{ + static_assert(eLaunchCallMax < 0x8, "Have more launch calls than we are able to represent"); + // This may truncate the topmost bits of the errno because the exit code is only 8 bits wide. + // However, it should still give us a pretty good indication of what went wrong. (And the + // most common errors have small numbers anyway). + _exit(unsigned(spec) | (errno << 3)); +} + +// The second member is the errno (or its 5 lowermost bits anyway). +inline std::pair +DecodeChildExitCode(int exit_code) +{ + return std::make_pair(LaunchCallSpecifier(exit_code & 0x7), exit_code >> 3); +} + +void +MaybeLogLaunchInfo(const ProcessLaunchInfo &info) +{ + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + if (!log) + return; + + if (const FileAction *action = info.GetFileActionForFD(STDIN_FILENO)) + log->Printf("%s: setting STDIN to '%s'", __FUNCTION__, action->GetFileSpec().GetCString()); + else + log->Printf("%s leaving STDIN as is", __FUNCTION__); + + if (const FileAction *action = info.GetFileActionForFD(STDOUT_FILENO)) + log->Printf("%s setting STDOUT to '%s'", __FUNCTION__, action->GetFileSpec().GetCString()); + else + log->Printf("%s leaving STDOUT as is", __FUNCTION__); + + if (const FileAction *action = info.GetFileActionForFD(STDERR_FILENO)) + log->Printf("%s setting STDERR to '%s'", __FUNCTION__, action->GetFileSpec().GetCString()); + else + log->Printf("%s leaving STDERR as is", __FUNCTION__); + + int i = 0; + for (const char **args = info.GetArguments().GetConstArgumentVector(); *args; ++args, ++i) + log->Printf("%s arg %d: \"%s\"", __FUNCTION__, i, *args ? *args : "nullptr"); +} + +void +DisplayBytes(StreamString &s, void *bytes, uint32_t count) +{ + uint8_t *ptr = (uint8_t *)bytes; + const uint32_t loop_count = std::min(DEBUG_PTRACE_MAXBYTES, count); + for (uint32_t i = 0; i < loop_count; i++) { - uint8_t *ptr = (uint8_t *)bytes; - const uint32_t loop_count = std::min(DEBUG_PTRACE_MAXBYTES, count); - for(uint32_t i=0; iResolveExecutable( - ModuleSpec(launch_info.GetExecutableFile(), launch_info.GetArchitecture()), - exe_module_sp, - nullptr); - - if (! error.Success()) - return error; + Error error; // Verify the working directory is valid if one was specified. FileSpec working_dir{launch_info.GetWorkingDirectory()}; @@ -295,59 +314,9 @@ NativeProcessProtocol::Launch ( return error; } - const 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{}; - - file_action = launch_info.GetFileActionForFD (STDIN_FILENO); - if (file_action) - stdin_file_spec = file_action->GetFileSpec(); - - file_action = launch_info.GetFileActionForFD (STDOUT_FILENO); - if (file_action) - stdout_file_spec = file_action->GetFileSpec(); - - file_action = launch_info.GetFileActionForFD (STDERR_FILENO); - if (file_action) - stderr_file_spec = file_action->GetFileSpec(); - - if (log) - { - if (stdin_file_spec) - log->Printf ("NativeProcessLinux::%s setting STDIN to '%s'", - __FUNCTION__, stdin_file_spec.GetCString()); - else - log->Printf ("NativeProcessLinux::%s leaving STDIN as is", __FUNCTION__); - - if (stdout_file_spec) - log->Printf ("NativeProcessLinux::%s setting STDOUT to '%s'", - __FUNCTION__, stdout_file_spec.GetCString()); - else - log->Printf ("NativeProcessLinux::%s leaving STDOUT as is", __FUNCTION__); - - if (stderr_file_spec) - log->Printf ("NativeProcessLinux::%s setting STDERR to '%s'", - __FUNCTION__, stderr_file_spec.GetCString()); - else - log->Printf ("NativeProcessLinux::%s leaving STDERR as is", __FUNCTION__); - } - // Create the NativeProcessLinux in launch mode. native_process_sp.reset (new NativeProcessLinux ()); - if (log) - { - int i = 0; - for (const char **args = launch_info.GetArguments ().GetConstArgumentVector (); *args; ++args, ++i) - { - log->Printf ("NativeProcessLinux::%s arg %d: \"%s\"", __FUNCTION__, i, *args ? *args : "nullptr"); - ++i; - } - } - if (!native_process_sp->RegisterNativeDelegate (native_delegate)) { native_process_sp.reset (); @@ -355,17 +324,7 @@ NativeProcessProtocol::Launch ( return error; } - std::static_pointer_cast (native_process_sp)->LaunchInferior ( - mainloop, - exe_module_sp.get(), - launch_info.GetArguments ().GetConstArgumentVector (), - launch_info.GetEnvironmentEntries ().GetConstArgumentVector (), - stdin_file_spec, - stdout_file_spec, - stderr_file_spec, - working_dir, - launch_info, - error); + error = std::static_pointer_cast(native_process_sp)->LaunchInferior(mainloop, launch_info); if (error.Fail ()) { @@ -391,15 +350,9 @@ NativeProcessProtocol::Attach ( if (log && log->GetMask ().Test (POSIX_LOG_VERBOSE)) log->Printf ("NativeProcessLinux::%s(pid = %" PRIi64 ")", __FUNCTION__, pid); - // Grab the current platform architecture. This should be Linux, - // since this code is only intended to run on a Linux host. - PlatformSP platform_sp (Platform::GetHostPlatform ()); - if (!platform_sp) - return Error("failed to get a valid default platform"); - // Retrieve the architecture for the running process. ArchSpec process_arch; - Error error = ResolveProcessArchitecture (pid, *platform_sp.get (), process_arch); + Error error = ResolveProcessArchitecture(pid, process_arch); if (!error.Success ()) return error; @@ -428,227 +381,170 @@ NativeProcessLinux::NativeProcessLinux () : m_arch (), m_supports_mem_region (eLazyBoolCalculate), m_mem_region_cache (), - m_mem_region_cache_mutex(), m_pending_notification_tid(LLDB_INVALID_THREAD_ID) { } void -NativeProcessLinux::LaunchInferior ( - MainLoop &mainloop, - Module *module, - const char *argv[], - const char *envp[], - const FileSpec &stdin_file_spec, - const FileSpec &stdout_file_spec, - const FileSpec &stderr_file_spec, - const FileSpec &working_dir, - const ProcessLaunchInfo &launch_info, - Error &error) +NativeProcessLinux::AttachToInferior (MainLoop &mainloop, lldb::pid_t pid, Error &error) { + Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 ")", __FUNCTION__, pid); + m_sigchld_handle = mainloop.RegisterSignal(SIGCHLD, [this] (MainLoopBase &) { SigchldHandler(); }, error); if (! m_sigchld_handle) return; - if (module) - m_arch = module->GetArchitecture (); + error = ResolveProcessArchitecture(pid, m_arch); + if (!error.Success()) + return; - SetState (eStateLaunching); + // Set the architecture to the exe architecture. + if (log) + log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 ") detected architecture %s", __FUNCTION__, pid, m_arch.GetArchitectureName ()); - std::unique_ptr args( - new LaunchArgs(module, argv, envp, - stdin_file_spec, - stdout_file_spec, - stderr_file_spec, - working_dir, - launch_info)); + m_pid = pid; + SetState(eStateAttaching); - Launch(args.get(), error); + Attach(pid, error); } void -NativeProcessLinux::AttachToInferior (MainLoop &mainloop, lldb::pid_t pid, Error &error) +NativeProcessLinux::ChildFunc(const ProcessLaunchInfo &info) { - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 ")", __FUNCTION__, pid); + // Start tracing this child that is about to exec. + if (ptrace(PTRACE_TRACEME, 0, nullptr, nullptr) == -1) + ExitChildAbnormally(ePtraceFailed); - m_sigchld_handle = mainloop.RegisterSignal(SIGCHLD, - [this] (MainLoopBase &) { SigchldHandler(); }, error); - if (! m_sigchld_handle) - return; + // Do not inherit setgid powers. + if (setgid(getgid()) != 0) + ExitChildAbnormally(eSetGidFailed); - // We can use the Host for everything except the ResolveExecutable portion. - PlatformSP platform_sp = Platform::GetHostPlatform (); - if (!platform_sp) + // Attempt to have our own process group. + if (setpgid(0, 0) != 0) { - if (log) - log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 "): no default platform set", __FUNCTION__, pid); - error.SetErrorString ("no default platform available"); - return; + // FIXME log that this failed. This is common. + // Don't allow this to prevent an inferior exec. } - // Gather info about the process. - ProcessInstanceInfo process_info; - if (!platform_sp->GetProcessInfo (pid, process_info)) + // Dup file descriptors if needed. + if (const FileAction *action = info.GetFileActionForFD(STDIN_FILENO)) + if (!DupDescriptor(action->GetFileSpec(), STDIN_FILENO, O_RDONLY)) + ExitChildAbnormally(eDupStdinFailed); + + if (const FileAction *action = info.GetFileActionForFD(STDOUT_FILENO)) + if (!DupDescriptor(action->GetFileSpec(), STDOUT_FILENO, O_WRONLY | O_CREAT | O_TRUNC)) + ExitChildAbnormally(eDupStdoutFailed); + + if (const FileAction *action = info.GetFileActionForFD(STDERR_FILENO)) + if (!DupDescriptor(action->GetFileSpec(), STDERR_FILENO, O_WRONLY | O_CREAT | O_TRUNC)) + ExitChildAbnormally(eDupStderrFailed); + + // Close everything besides stdin, stdout, and stderr that has no file + // action to avoid leaking + for (int fd = 3; fd < sysconf(_SC_OPEN_MAX); ++fd) + if (!info.GetFileActionForFD(fd)) + close(fd); + + // Change working directory + if (info.GetWorkingDirectory() && 0 != ::chdir(info.GetWorkingDirectory().GetCString())) + ExitChildAbnormally(eChdirFailed); + + // Disable ASLR if requested. + if (info.GetFlags().Test(lldb::eLaunchFlagDisableASLR)) { - if (log) - log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 "): failed to get process info", __FUNCTION__, pid); - error.SetErrorString ("failed to get process info"); - return; + const int old_personality = personality(LLDB_PERSONALITY_GET_CURRENT_SETTINGS); + if (old_personality == -1) + { + // Can't retrieve Linux personality. Cannot disable ASLR. + } + else + { + const int new_personality = personality(ADDR_NO_RANDOMIZE | old_personality); + if (new_personality == -1) + { + // Disabling ASLR failed. + } + else + { + // Disabling ASLR succeeded. + } + } } - // Resolve the executable module - ModuleSP exe_module_sp; - FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths()); - ModuleSpec exe_module_spec(process_info.GetExecutableFile(), process_info.GetArchitecture()); - error = platform_sp->ResolveExecutable(exe_module_spec, exe_module_sp, - executable_search_paths.GetSize() ? &executable_search_paths : NULL); - if (!error.Success()) - return; + // Clear the signal mask to prevent the child from being affected by + // any masking done by the parent. + sigset_t set; + if (sigemptyset(&set) != 0 || pthread_sigmask(SIG_SETMASK, &set, nullptr) != 0) + ExitChildAbnormally(eSetSigMaskFailed); - // Set the architecture to the exe architecture. - m_arch = exe_module_sp->GetArchitecture(); - if (log) - log->Printf ("NativeProcessLinux::%s (pid = %" PRIi64 ") detected architecture %s", __FUNCTION__, pid, m_arch.GetArchitectureName ()); + const char **argv = info.GetArguments().GetConstArgumentVector(); - m_pid = pid; - SetState(eStateAttaching); + // Propagate the environment if one is not supplied. + const char **envp = info.GetEnvironmentEntries().GetConstArgumentVector(); + if (envp == NULL || envp[0] == NULL) + envp = const_cast(environ); - Attach(pid, error); + // Execute. We should never return... + execve(argv[0], const_cast(argv), const_cast(envp)); + + if (errno == ETXTBSY) + { + // On android M and earlier we can get this error because the adb deamon can hold a write + // handle on the executable even after it has finished uploading it. This state lasts + // only a short time and happens only when there are many concurrent adb commands being + // issued, such as when running the test suite. (The file remains open when someone does + // an "adb shell" command in the fork() child before it has had a chance to exec.) Since + // this state should clear up quickly, wait a while and then give it one more go. + usleep(50000); + execve(argv[0], const_cast(argv), const_cast(envp)); + } + + // ...unless exec fails. In which case we definitely need to end the child here. + ExitChildAbnormally(eExecFailed); } -::pid_t -NativeProcessLinux::Launch(LaunchArgs *args, Error &error) +Error +NativeProcessLinux::LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info) { - assert (args && "null args"); + Error error; + m_sigchld_handle = mainloop.RegisterSignal(SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, error); + if (!m_sigchld_handle) + return error; - const char **argv = args->m_argv; - const char **envp = args->m_envp; - const FileSpec working_dir = args->m_working_dir; + SetState(eStateLaunching); lldb_utility::PseudoTerminal terminal; const size_t err_len = 1024; char err_str[err_len]; lldb::pid_t pid; - // Propagate the environment if one is not supplied. - if (envp == NULL || envp[0] == NULL) - envp = const_cast(environ); + MaybeLogLaunchInfo(launch_info); if ((pid = terminal.Fork(err_str, err_len)) == static_cast (-1)) { error.SetErrorToGenericError(); error.SetErrorStringWithFormat("Process fork failed: %s", err_str); - return -1; + return error; } - // Recognized child exit status codes. - enum { - ePtraceFailed = 1, - eDupStdinFailed, - eDupStdoutFailed, - eDupStderrFailed, - eChdirFailed, - eExecFailed, - eSetGidFailed, - eSetSigMaskFailed - }; - // Child process. if (pid == 0) { // First, make sure we disable all logging. If we are logging to stdout, our logs can be // mistaken for inferior output. Log::DisableAllLogChannels(nullptr); - // FIXME consider opening a pipe between parent/child and have this forked child - // send log info to parent re: launch status. - - // Start tracing this child that is about to exec. - error = PtraceWrapper(PTRACE_TRACEME, 0); - if (error.Fail()) - exit(ePtraceFailed); // terminal has already dupped the tty descriptors to stdin/out/err. // This closes original fd from which they were copied (and avoids // leaking descriptors to the debugged process. terminal.CloseSlaveFileDescriptor(); - // Do not inherit setgid powers. - if (setgid(getgid()) != 0) - exit(eSetGidFailed); - - // Attempt to have our own process group. - if (setpgid(0, 0) != 0) - { - // FIXME log that this failed. This is common. - // Don't allow this to prevent an inferior exec. - } - - // Dup file descriptors if needed. - if (args->m_stdin_file_spec) - if (!DupDescriptor(args->m_stdin_file_spec, STDIN_FILENO, O_RDONLY)) - exit(eDupStdinFailed); - - if (args->m_stdout_file_spec) - if (!DupDescriptor(args->m_stdout_file_spec, STDOUT_FILENO, O_WRONLY | O_CREAT | O_TRUNC)) - exit(eDupStdoutFailed); - - if (args->m_stderr_file_spec) - if (!DupDescriptor(args->m_stderr_file_spec, STDERR_FILENO, O_WRONLY | O_CREAT | O_TRUNC)) - exit(eDupStderrFailed); - - // Close everything besides stdin, stdout, and stderr that has no file - // action to avoid leaking - for (int fd = 3; fd < sysconf(_SC_OPEN_MAX); ++fd) - if (!args->m_launch_info.GetFileActionForFD(fd)) - close(fd); - - // Change working directory - if (working_dir && 0 != ::chdir(working_dir.GetCString())) - exit(eChdirFailed); - - // Disable ASLR if requested. - if (args->m_launch_info.GetFlags ().Test (lldb::eLaunchFlagDisableASLR)) - { - const int old_personality = personality (LLDB_PERSONALITY_GET_CURRENT_SETTINGS); - if (old_personality == -1) - { - // Can't retrieve Linux personality. Cannot disable ASLR. - } - else - { - const int new_personality = personality (ADDR_NO_RANDOMIZE | old_personality); - if (new_personality == -1) - { - // Disabling ASLR failed. - } - else - { - // Disabling ASLR succeeded. - } - } - } - - // Clear the signal mask to prevent the child from being affected by - // any masking done by the parent. - sigset_t set; - if (sigemptyset(&set) != 0 || pthread_sigmask(SIG_SETMASK, &set, nullptr) != 0) - exit(eSetSigMaskFailed); - - // Execute. We should never return... - execve(argv[0], - const_cast(argv), - const_cast(envp)); - - // ...unless exec fails. In which case we definitely need to end the child here. - exit(eExecFailed); + ChildFunc(launch_info); } - // - // This is the parent code here. - // Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); // Wait for the child process to trap on its call to execve. @@ -665,42 +561,41 @@ NativeProcessLinux::Launch(LaunchArgs *args, Error &error) // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid. SetState (StateType::eStateInvalid); - return -1; + return error; } else if (WIFEXITED(status)) { - // open, dup or execve likely failed for some reason. - error.SetErrorToGenericError(); - switch (WEXITSTATUS(status)) + auto p = DecodeChildExitCode(WEXITSTATUS(status)); + Error child_error(p.second, eErrorTypePOSIX); + const char *failure_reason; + switch (p.first) { case ePtraceFailed: - error.SetErrorString("Child ptrace failed."); + failure_reason = "Child ptrace failed"; break; case eDupStdinFailed: - error.SetErrorString("Child open stdin failed."); + failure_reason = "Child open stdin failed"; break; case eDupStdoutFailed: - error.SetErrorString("Child open stdout failed."); + failure_reason = "Child open stdout failed"; break; case eDupStderrFailed: - error.SetErrorString("Child open stderr failed."); + failure_reason = "Child open stderr failed"; break; case eChdirFailed: - error.SetErrorString("Child failed to set working directory."); + failure_reason = "Child failed to set working directory"; break; case eExecFailed: - error.SetErrorString("Child exec failed."); + failure_reason = "Child exec failed"; break; case eSetGidFailed: - error.SetErrorString("Child setgid failed."); + failure_reason = "Child setgid failed"; break; case eSetSigMaskFailed: - error.SetErrorString("Child failed to set signal mask."); - break; - default: - error.SetErrorString("Child returned unknown exit status."); + failure_reason = "Child failed to set signal mask"; break; } + error.SetErrorStringWithFormat("%s: %d - %s (error code truncated)", failure_reason, child_error.GetError(), child_error.AsCString()); if (log) { @@ -713,7 +608,7 @@ NativeProcessLinux::Launch(LaunchArgs *args, Error &error) // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid. SetState (StateType::eStateInvalid); - return -1; + return error; } assert(WIFSTOPPED(status) && (wpid == static_cast< ::pid_t> (pid)) && "Could not sync with inferior process."); @@ -732,13 +627,14 @@ NativeProcessLinux::Launch(LaunchArgs *args, Error &error) // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid. SetState (StateType::eStateInvalid); - return -1; + return error; } // Release the master terminal descriptor and pass it off to the // NativeProcessLinux instance. Similarly stash the inferior pid. m_terminal_fd = terminal.ReleaseMasterFileDescriptor(); m_pid = pid; + launch_info.SetProcessID(pid); // Set the terminal fd to be in non blocking mode (it simplifies the // implementation of ProcessLinux::GetSTDOUT to have a non-blocking @@ -754,12 +650,13 @@ NativeProcessLinux::Launch(LaunchArgs *args, Error &error) // FIXME this could really use a new state - eStateLaunchFailure. For now, using eStateInvalid. SetState (StateType::eStateInvalid); - return -1; + return error; } if (log) log->Printf ("NativeProcessLinux::%s() adding pid = %" PRIu64, __FUNCTION__, pid); + ResolveProcessArchitecture(m_pid, m_arch); NativeThreadLinuxSP thread_sp = AddThread(pid); assert (thread_sp && "AddThread() returned a nullptr thread"); thread_sp->SetStoppedBySignal(SIGSTOP); @@ -772,17 +669,11 @@ NativeProcessLinux::Launch(LaunchArgs *args, Error &error) if (log) { if (error.Success ()) - { - log->Printf ("NativeProcessLinux::%s inferior launching succeeded", __FUNCTION__); - } + log->Printf("NativeProcessLinux::%s inferior launching succeeded", __FUNCTION__); else - { - log->Printf ("NativeProcessLinux::%s inferior launching failed: %s", - __FUNCTION__, error.AsCString ()); - return -1; - } + log->Printf("NativeProcessLinux::%s inferior launching failed: %s", __FUNCTION__, error.AsCString()); } - return pid; + return error; } ::pid_t @@ -1150,8 +1041,6 @@ NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, NativeThreadLinux &thr assert(info.si_signo == SIGTRAP && "Unexpected child signal!"); - Mutex::Locker locker (m_threads_mutex); - switch (info.si_code) { // TODO: these two cases are required if we want to support tracing of the inferiors' children. We'd need this to debug a monitor. @@ -1187,7 +1076,7 @@ NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, NativeThreadLinux &thr // Exec clears any pending notifications. m_pending_notification_tid = LLDB_INVALID_THREAD_ID; - // Remove all but the main thread here. Linux fork creates a new process which only copies the main thread. Mutexes are in undefined state. + // Remove all but the main thread here. Linux fork creates a new process which only copies the main thread. if (log) log->Printf ("NativeProcessLinux::%s exec received, stop tracking all but main thread", __FUNCTION__); @@ -1413,8 +1302,6 @@ NativeProcessLinux::MonitorSignal(const siginfo_t &info, NativeThreadLinux &thre // // Similarly, ACK signals generated by this monitor. - Mutex::Locker locker (m_threads_mutex); - // Handle the signal. if (info.si_code == SI_TKILL || info.si_code == SI_USER) { @@ -1713,8 +1600,6 @@ NativeProcessLinux::Resume (const ResumeActionList &resume_actions) bool software_single_step = !SupportHardwareSingleStepping(); - Mutex::Locker locker (m_threads_mutex); - if (software_single_step) { for (auto thread_sp : m_threads) @@ -1840,8 +1725,6 @@ NativeProcessLinux::Interrupt () if (log) log->Printf ("NativeProcessLinux::%s selecting running thread for interrupt target", __FUNCTION__); - Mutex::Locker locker (m_threads_mutex); - for (auto thread_sp : m_threads) { // The thread shouldn't be null but lets just cover that here. @@ -1956,6 +1839,9 @@ ParseMemoryRegionInfoFromProcMapsLine (const std::string &maps_line, MemoryRegio memory_region_info.GetRange ().SetRangeBase (start_address); memory_region_info.GetRange ().SetRangeEnd (end_address); + // Any memory region in /proc/{pid}/maps is by definition mapped into the process. + memory_region_info.SetMapped(MemoryRegionInfo::OptionalBool::eYes); + // Parse out each permission entry. if (line_extractor.GetBytesLeft () < 4) return Error ("malformed /proc/{pid}/maps entry, missing some portion of permissions"); @@ -1964,31 +1850,28 @@ ParseMemoryRegionInfoFromProcMapsLine (const std::string &maps_line, MemoryRegio const char read_perm_char = line_extractor.GetChar (); if (read_perm_char == 'r') memory_region_info.SetReadable (MemoryRegionInfo::OptionalBool::eYes); - else - { - assert ( (read_perm_char == '-') && "unexpected /proc/{pid}/maps read permission char" ); + else if (read_perm_char == '-') memory_region_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo); - } + else + return Error ("unexpected /proc/{pid}/maps read permission char"); // Handle write permission. const char write_perm_char = line_extractor.GetChar (); if (write_perm_char == 'w') memory_region_info.SetWritable (MemoryRegionInfo::OptionalBool::eYes); - else - { - assert ( (write_perm_char == '-') && "unexpected /proc/{pid}/maps write permission char" ); + else if (write_perm_char == '-') memory_region_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo); - } + else + return Error ("unexpected /proc/{pid}/maps write permission char"); // Handle execute permission. const char exec_perm_char = line_extractor.GetChar (); if (exec_perm_char == 'x') memory_region_info.SetExecutable (MemoryRegionInfo::OptionalBool::eYes); - else - { - assert ( (exec_perm_char == '-') && "unexpected /proc/{pid}/maps exec permission char" ); + else if (exec_perm_char == '-') memory_region_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo); - } + else + return Error ("unexpected /proc/{pid}/maps exec permission char"); return Error (); } @@ -2002,7 +1885,6 @@ NativeProcessLinux::GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInf // Use an approach that reads memory regions from /proc/{pid}/maps. // Assume proc maps entries are in ascending order. // FIXME assert if we find differently. - Mutex::Locker locker (m_mem_region_cache_mutex); Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); Error error; @@ -2085,6 +1967,7 @@ NativeProcessLinux::GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInf range_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo); range_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo); range_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo); + range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo); return error; } @@ -2102,21 +1985,11 @@ NativeProcessLinux::GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInf // load_addr as start and the amount of bytes betwwen load address and the end of the memory as // size. range_info.GetRange ().SetRangeBase (load_addr); - switch (m_arch.GetAddressByteSize()) - { - case 4: - range_info.GetRange ().SetByteSize (0x100000000ull - load_addr); - break; - case 8: - range_info.GetRange ().SetByteSize (0ull - load_addr); - break; - default: - assert(false && "Unrecognized data byte size"); - break; - } + range_info.GetRange ().SetRangeEnd(LLDB_INVALID_ADDRESS); range_info.SetReadable (MemoryRegionInfo::OptionalBool::eNo); range_info.SetWritable (MemoryRegionInfo::OptionalBool::eNo); range_info.SetExecutable (MemoryRegionInfo::OptionalBool::eNo); + range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo); return error; } @@ -2127,12 +2000,9 @@ NativeProcessLinux::DoStopIDBumped (uint32_t newBumpId) if (log) log->Printf ("NativeProcessLinux::%s(newBumpId=%" PRIu32 ") called", __FUNCTION__, newBumpId); - { - Mutex::Locker locker (m_mem_region_cache_mutex); if (log) log->Printf ("NativeProcessLinux::%s clearing %" PRIu64 " entries from the cache", __FUNCTION__, static_cast (m_mem_region_cache.size ())); m_mem_region_cache.clear (); - } } Error @@ -2179,49 +2049,8 @@ NativeProcessLinux::DeallocateMemory (lldb::addr_t addr) lldb::addr_t NativeProcessLinux::GetSharedLibraryInfoAddress () { -#if 1 // punt on this for now return LLDB_INVALID_ADDRESS; -#else - // Return the image info address for the exe module -#if 1 - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - - ModuleSP module_sp; - Error error = GetExeModuleSP (module_sp); - if (error.Fail ()) - { - if (log) - log->Warning ("NativeProcessLinux::%s failed to retrieve exe module: %s", __FUNCTION__, error.AsCString ()); - return LLDB_INVALID_ADDRESS; - } - - if (module_sp == nullptr) - { - if (log) - log->Warning ("NativeProcessLinux::%s exe module returned was NULL", __FUNCTION__); - return LLDB_INVALID_ADDRESS; - } - - ObjectFileSP object_file_sp = module_sp->GetObjectFile (); - if (object_file_sp == nullptr) - { - if (log) - log->Warning ("NativeProcessLinux::%s exe module returned a NULL object file", __FUNCTION__); - return LLDB_INVALID_ADDRESS; - } - - return obj_file_sp->GetImageInfoAddress(); -#else - 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; -#endif -#endif // punt on this for now } size_t @@ -2231,7 +2060,6 @@ NativeProcessLinux::UpdateThreads () // with respect to thread state and they keep the thread list // populated properly. All this method needs to do is return the // thread count. - Mutex::Locker locker (m_threads_mutex); return m_threads.size (); } @@ -2248,6 +2076,7 @@ NativeProcessLinux::GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size) // FIXME put this behind a breakpoint protocol class that can be // set per architecture. Need ARM, MIPS support here. static const uint8_t g_i386_opcode [] = { 0xCC }; + static const uint8_t g_s390x_opcode[] = { 0x00, 0x01 }; switch (m_arch.GetMachine ()) { @@ -2256,6 +2085,10 @@ NativeProcessLinux::GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size) actual_opcode_size = static_cast (sizeof(g_i386_opcode)); return Error (); + case llvm::Triple::systemz: + actual_opcode_size = static_cast (sizeof(g_s390x_opcode)); + return Error (); + case llvm::Triple::arm: case llvm::Triple::aarch64: case llvm::Triple::mips64: @@ -2295,6 +2128,7 @@ NativeProcessLinux::GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hin static const uint8_t g_i386_opcode [] = { 0xCC }; static const uint8_t g_mips64_opcode[] = { 0x00, 0x00, 0x00, 0x0d }; static const uint8_t g_mips64el_opcode[] = { 0x0d, 0x00, 0x00, 0x00 }; + static const uint8_t g_s390x_opcode[] = { 0x00, 0x01 }; static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde }; switch (m_arch.GetMachine ()) @@ -2338,6 +2172,11 @@ NativeProcessLinux::GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hin actual_opcode_size = sizeof(g_mips64el_opcode); return Error (); + case llvm::Triple::systemz: + trap_opcode_bytes = g_s390x_opcode; + actual_opcode_size = sizeof(g_s390x_opcode); + return Error (); + default: assert(false && "CPU type not supported!"); return Error ("CPU type not supported"); @@ -2655,43 +2494,6 @@ NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf, size_t size, return error; } -Error -NativeProcessLinux::Resume (lldb::tid_t tid, uint32_t signo) -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - - if (log) - log->Printf ("NativeProcessLinux::%s() resuming thread = %" PRIu64 " with signal %s", __FUNCTION__, tid, - Host::GetSignalAsCString(signo)); - - - - intptr_t data = 0; - - if (signo != LLDB_INVALID_SIGNAL_NUMBER) - data = signo; - - Error error = PtraceWrapper(PTRACE_CONT, tid, nullptr, (void*)data); - - if (log) - log->Printf ("NativeProcessLinux::%s() resuming thread = %" PRIu64 " result = %s", __FUNCTION__, tid, error.Success() ? "true" : "false"); - return error; -} - -Error -NativeProcessLinux::SingleStep(lldb::tid_t tid, uint32_t signo) -{ - intptr_t data = 0; - - if (signo != LLDB_INVALID_SIGNAL_NUMBER) - data = signo; - - // If hardware single-stepping is not supported, we just do a continue. The breakpoint on the - // next instruction has been setup in NativeProcessLinux::Resume. - return PtraceWrapper(SupportHardwareSingleStepping() ? PTRACE_SINGLESTEP : PTRACE_CONT, - tid, nullptr, (void*)data); -} - Error NativeProcessLinux::GetSignalInfo(lldb::tid_t tid, void *siginfo) { @@ -2754,7 +2556,6 @@ NativeProcessLinux::StopTrackingThread (lldb::tid_t thread_id) bool found = false; - Mutex::Locker locker (m_threads_mutex); for (auto it = m_threads.begin (); it != m_threads.end (); ++it) { if (*it && ((*it)->GetID () == thread_id)) @@ -2775,8 +2576,6 @@ NativeProcessLinux::AddThread (lldb::tid_t thread_id) { Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); - Mutex::Locker locker (m_threads_mutex); - if (log) { log->Printf ("NativeProcessLinux::%s pid %" PRIu64 " adding thread with tid %" PRIu64, @@ -2980,16 +2779,14 @@ NativeProcessLinux::ResumeThread(NativeThreadLinux &thread, lldb::StateType stat { case eStateRunning: { - thread.SetRunning(); - const auto resume_result = Resume(thread.GetID(), signo); + const auto resume_result = thread.Resume(signo); if (resume_result.Success()) SetState(eStateRunning, true); return resume_result; } case eStateStepping: { - thread.SetStepping(); - const auto step_result = SingleStep(thread.GetID(), signo); + const auto step_result = thread.SingleStep(signo); if (step_result.Success()) SetState(eStateRunning, true); return step_result; diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.h b/source/Plugins/Process/Linux/NativeProcessLinux.h index 7bac1dc8dbb7..d5be06f0cb58 100644 --- a/source/Plugins/Process/Linux/NativeProcessLinux.h +++ b/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -19,7 +19,6 @@ #include "lldb/Host/Debug.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/HostThread.h" -#include "lldb/Host/Mutex.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Host/common/NativeProcessProtocol.h" @@ -27,7 +26,6 @@ namespace lldb_private { class Error; - class Module; class Scalar; namespace process_linux { @@ -127,6 +125,9 @@ namespace process_linux { size_t data_size = 0, long *result = nullptr); + bool + SupportHardwareSingleStepping() const; + protected: // --------------------------------------------------------------------- // NativeProcessProtocol protected interface @@ -141,7 +142,6 @@ namespace process_linux { LazyBool m_supports_mem_region; std::vector m_mem_region_cache; - Mutex m_mem_region_cache_mutex; lldb::tid_t m_pending_notification_tid; @@ -149,66 +149,26 @@ namespace process_linux { // the relevan breakpoint std::map m_threads_stepping_with_breakpoint; - /// @class LauchArgs - /// - /// @brief Simple structure to pass data to the thread responsible for - /// launching a child process. - struct LaunchArgs - { - LaunchArgs(Module *module, - char const **argv, - char const **envp, - const FileSpec &stdin_file_spec, - const FileSpec &stdout_file_spec, - const FileSpec &stderr_file_spec, - const FileSpec &working_dir, - const ProcessLaunchInfo &launch_info); - - ~LaunchArgs(); - - Module *m_module; // The executable image to launch. - char const **m_argv; // Process arguments. - char const **m_envp; // Process environment. - const FileSpec m_stdin_file_spec; // Redirect stdin if not empty. - const FileSpec m_stdout_file_spec; // Redirect stdout if not empty. - const FileSpec m_stderr_file_spec; // Redirect stderr if not empty. - const FileSpec m_working_dir; // Working directory or empty. - const ProcessLaunchInfo &m_launch_info; - }; - - typedef std::function< ::pid_t(Error &)> InitialOperation; // --------------------------------------------------------------------- // Private Instance Methods // --------------------------------------------------------------------- NativeProcessLinux (); - /// Launches an inferior process ready for debugging. Forms the - /// implementation of Process::DoLaunch. - void - LaunchInferior ( - MainLoop &mainloop, - Module *module, - char const *argv[], - char const *envp[], - const FileSpec &stdin_file_spec, - const FileSpec &stdout_file_spec, - const FileSpec &stderr_file_spec, - const FileSpec &working_dir, - const ProcessLaunchInfo &launch_info, - Error &error); + Error + LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info); /// Attaches to an existing process. Forms the /// implementation of Process::DoAttach void AttachToInferior (MainLoop &mainloop, lldb::pid_t pid, Error &error); - ::pid_t - Launch(LaunchArgs *args, Error &error); - ::pid_t Attach(lldb::pid_t pid, Error &error); + static void + ChildFunc(const ProcessLaunchInfo &launch_info) LLVM_ATTRIBUTE_NORETURN; + static Error SetDefaultPtraceOpts(const lldb::pid_t); @@ -239,9 +199,6 @@ namespace process_linux { void MonitorSignal(const siginfo_t &info, NativeThreadLinux &thread, bool exited); - bool - SupportHardwareSingleStepping() const; - Error SetupSoftwareSingleStepping(NativeThreadLinux &thread); @@ -285,16 +242,6 @@ namespace process_linux { Error GetEventMessage(lldb::tid_t tid, unsigned long *message); - /// Resumes the given thread. If @p signo is anything but - /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. - Error - Resume(lldb::tid_t tid, uint32_t signo); - - /// Single steps the given thread. If @p signo is anything but - /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. - Error - SingleStep(lldb::tid_t tid, uint32_t signo); - void NotifyThreadDeath (lldb::tid_t tid); diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp index 79653fc62686..5dfbaff90891 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp @@ -592,7 +592,7 @@ NativeRegisterContextLinux_arm::NumSupportedHardwareWatchpoints () error = ReadHardwareDebugInfo (); if (error.Fail()) - return LLDB_INVALID_INDEX32; + return 0; return m_max_hwp_supported; } @@ -614,6 +614,7 @@ NativeRegisterContextLinux_arm::SetHardwareWatchpoint (lldb::addr_t addr, size_t return LLDB_INVALID_INDEX32; uint32_t control_value = 0, wp_index = 0, addr_word_offset = 0, byte_mask = 0; + lldb::addr_t real_addr = addr; // Check if we are setting watchpoint other than read/write/access // Also update watchpoint flag to match Arm write-read bit configuration. @@ -637,7 +638,24 @@ NativeRegisterContextLinux_arm::SetHardwareWatchpoint (lldb::addr_t addr, size_t if (size == 0 || size > 4) return LLDB_INVALID_INDEX32; - // We can only watch up to four bytes that follow a 4 byte aligned address + // Check 4-byte alignment for hardware watchpoint target address. + // Below is a hack to recalculate address and size in order to + // make sure we can watch non 4-byte alligned addresses as well. + if (addr & 0x03) + { + uint8_t watch_mask = (addr & 0x03) + size; + + if (watch_mask > 0x04) + return LLDB_INVALID_INDEX32; + else if (watch_mask <= 0x02) + size = 2; + else if (watch_mask <= 0x04) + size = 4; + + addr = addr & (~0x03); + } + + // We can only watch up to four bytes that follow a 4 byte aligned address // per watchpoint register pair, so make sure we can properly encode this. addr_word_offset = addr % 4; byte_mask = ((1u << size) - 1u) << addr_word_offset; @@ -682,6 +700,7 @@ NativeRegisterContextLinux_arm::SetHardwareWatchpoint (lldb::addr_t addr, size_t if ((m_hwp_regs[wp_index].control & 1) == 0) { // Update watchpoint in local cache + m_hwp_regs[wp_index].real_addr = real_addr; m_hwp_regs[wp_index].address = addr; m_hwp_regs[wp_index].control = control_value; m_hwp_regs[wp_index].refcount = 1; @@ -864,6 +883,7 @@ NativeRegisterContextLinux_arm::GetWatchpointHitIndex(uint32_t &wp_index, lldb:: if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr && trap_addr < watch_addr + watch_size) { + m_hwp_regs[wp_index].hit_addr = trap_addr; return Error(); } } @@ -884,7 +904,24 @@ NativeRegisterContextLinux_arm::GetWatchpointAddress (uint32_t wp_index) return LLDB_INVALID_ADDRESS; if (WatchpointIsEnabled(wp_index)) - return m_hwp_regs[wp_index].address; + return m_hwp_regs[wp_index].real_addr; + else + return LLDB_INVALID_ADDRESS; +} + +lldb::addr_t +NativeRegisterContextLinux_arm::GetWatchpointHitAddress (uint32_t wp_index) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); + + if (log) + log->Printf ("NativeRegisterContextLinux_arm::%s()", __FUNCTION__); + + if (wp_index >= m_max_hwp_supported) + return LLDB_INVALID_ADDRESS; + + if (WatchpointIsEnabled(wp_index)) + return m_hwp_regs[wp_index].hit_addr; else return LLDB_INVALID_ADDRESS; } diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h index 349564970428..452f13258c2b 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h @@ -73,6 +73,9 @@ namespace process_linux { Error GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override; + lldb::addr_t + GetWatchpointHitAddress (uint32_t wp_index) override; + lldb::addr_t GetWatchpointAddress (uint32_t wp_index) override; @@ -162,6 +165,8 @@ namespace process_linux { struct DREG { lldb::addr_t address; // Breakpoint/watchpoint address value. + lldb::addr_t hit_addr; // Address at which last watchpoint trigger exception occurred. + lldb::addr_t real_addr; // Address value that should cause target to stop. uint32_t control; // Breakpoint/watchpoint control value. uint32_t refcount; // Serves as enable/disable and refernce counter. }; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp index 22cdbb40d15c..9489f00c1afe 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -32,6 +32,8 @@ #include // NT_PRSTATUS and NT_FPREGSET definition #include +// user_hwdebug_state definition +#include #define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize()) @@ -542,7 +544,7 @@ NativeRegisterContextLinux_arm64::NumSupportedHardwareWatchpoints () error = ReadHardwareDebugInfo (); if (error.Fail()) - return LLDB_INVALID_INDEX32; + return 0; return m_max_hwp_supported; } @@ -564,6 +566,7 @@ NativeRegisterContextLinux_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size return LLDB_INVALID_INDEX32; uint32_t control_value = 0, wp_index = 0; + lldb::addr_t real_addr = addr; // Check if we are setting watchpoint other than read/write/access // Also update watchpoint flag to match AArch64 write-read bit configuration. @@ -586,9 +589,23 @@ NativeRegisterContextLinux_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size return LLDB_INVALID_INDEX32; // Check 8-byte alignment for hardware watchpoint target address. - // TODO: Add support for watching un-aligned addresses + // Below is a hack to recalculate address and size in order to + // make sure we can watch non 8-byte alligned addresses as well. if (addr & 0x07) - return LLDB_INVALID_INDEX32; + { + uint8_t watch_mask = (addr & 0x07) + size; + + if (watch_mask > 0x08) + return LLDB_INVALID_INDEX32; + else if (watch_mask <= 0x02) + size = 2; + else if (watch_mask <= 0x04) + size = 4; + else + size = 8; + + addr = addr & (~0x07); + } // Setup control value control_value = watch_flags << 3; @@ -618,6 +635,7 @@ NativeRegisterContextLinux_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size if ((m_hwp_regs[wp_index].control & 1) == 0) { // Update watchpoint in local cache + m_hwp_regs[wp_index].real_addr = real_addr; m_hwp_regs[wp_index].address = addr; m_hwp_regs[wp_index].control = control_value; m_hwp_regs[wp_index].refcount = 1; @@ -799,6 +817,7 @@ NativeRegisterContextLinux_arm64::GetWatchpointHitIndex(uint32_t &wp_index, lldb if (m_hwp_regs[wp_index].refcount >= 1 && WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr && trap_addr < watch_addr + watch_size) { + m_hwp_regs[wp_index].hit_addr = trap_addr; return Error(); } } @@ -819,7 +838,24 @@ NativeRegisterContextLinux_arm64::GetWatchpointAddress (uint32_t wp_index) return LLDB_INVALID_ADDRESS; if (WatchpointIsEnabled(wp_index)) - return m_hwp_regs[wp_index].address; + return m_hwp_regs[wp_index].real_addr; + else + return LLDB_INVALID_ADDRESS; +} + +lldb::addr_t +NativeRegisterContextLinux_arm64::GetWatchpointHitAddress (uint32_t wp_index) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS)); + + if (log) + log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__); + + if (wp_index >= m_max_hwp_supported) + return LLDB_INVALID_ADDRESS; + + if (WatchpointIsEnabled(wp_index)) + return m_hwp_regs[wp_index].hit_addr; else return LLDB_INVALID_ADDRESS; } diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h index c60baa637b8a..4d9a9902ac3c 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h @@ -73,6 +73,9 @@ namespace process_linux { Error GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override; + lldb::addr_t + GetWatchpointHitAddress (uint32_t wp_index) override; + lldb::addr_t GetWatchpointAddress (uint32_t wp_index) override; @@ -161,6 +164,8 @@ namespace process_linux { struct DREG { lldb::addr_t address; // Breakpoint/watchpoint address value. + lldb::addr_t hit_addr; // Address at which last watchpoint trigger exception occurred. + lldb::addr_t real_addr; // Address value that should cause target to stop. uint32_t control; // Breakpoint/watchpoint control value. uint32_t refcount; // Serves as enable/disable and refernce counter. }; diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp index 54d6f721c9d8..d5a61722da87 100644 --- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp @@ -824,7 +824,8 @@ NativeRegisterContextLinux_mips64::ReadCP1() error = NativeRegisterContextLinux::ReadFPR(); } - if (IsFR0() || IsFRE()) + // TODO: Add support for FRE + if (IsFR0()) { src = (uint8_t *)&m_fpr + 4 + (IsBigEndian * 4); dst = (uint8_t *)&m_fpr + 8 + (IsBigEndian * 4); @@ -851,7 +852,8 @@ NativeRegisterContextLinux_mips64::WriteCP1() uint32_t IsBigEndian = (byte_order == lldb::eByteOrderBig); - if (IsFR0() || IsFRE()) + // TODO: Add support for FRE + if (IsFR0()) { src = (uint8_t *)&m_fpr + 8 + (IsBigEndian * 4); dst = (uint8_t *)&m_fpr + 4 + (IsBigEndian * 4); diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp new file mode 100644 index 000000000000..b09ad400d909 --- /dev/null +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp @@ -0,0 +1,716 @@ +//===-- NativeRegisterContextLinux_s390x.cpp --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#if defined(__s390x__) && defined(__linux__) + +#include "NativeRegisterContextLinux_s390x.h" + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Host/HostInfo.h" + +#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h" + +#include +#include +#include + +using namespace lldb_private; +using namespace lldb_private::process_linux; + +// ---------------------------------------------------------------------------- +// Private namespace. +// ---------------------------------------------------------------------------- + +namespace +{ + // s390x 64-bit general purpose registers. + static const uint32_t g_gpr_regnums_s390x[] = + { + lldb_r0_s390x, + lldb_r1_s390x, + lldb_r2_s390x, + lldb_r3_s390x, + lldb_r4_s390x, + lldb_r5_s390x, + lldb_r6_s390x, + lldb_r7_s390x, + lldb_r8_s390x, + lldb_r9_s390x, + lldb_r10_s390x, + lldb_r11_s390x, + lldb_r12_s390x, + lldb_r13_s390x, + lldb_r14_s390x, + lldb_r15_s390x, + lldb_acr0_s390x, + lldb_acr1_s390x, + lldb_acr2_s390x, + lldb_acr3_s390x, + lldb_acr4_s390x, + lldb_acr5_s390x, + lldb_acr6_s390x, + lldb_acr7_s390x, + lldb_acr8_s390x, + lldb_acr9_s390x, + lldb_acr10_s390x, + lldb_acr11_s390x, + lldb_acr12_s390x, + lldb_acr13_s390x, + lldb_acr14_s390x, + lldb_acr15_s390x, + lldb_pswm_s390x, + lldb_pswa_s390x, + LLDB_INVALID_REGNUM // register sets need to end with this flag + }; + static_assert((sizeof(g_gpr_regnums_s390x) / sizeof(g_gpr_regnums_s390x[0])) - 1 == k_num_gpr_registers_s390x, + "g_gpr_regnums_s390x has wrong number of register infos"); + + // s390x 64-bit floating point registers. + static const uint32_t g_fpu_regnums_s390x[] = + { + lldb_f0_s390x, + lldb_f1_s390x, + lldb_f2_s390x, + lldb_f3_s390x, + lldb_f4_s390x, + lldb_f5_s390x, + lldb_f6_s390x, + lldb_f7_s390x, + lldb_f8_s390x, + lldb_f9_s390x, + lldb_f10_s390x, + lldb_f11_s390x, + lldb_f12_s390x, + lldb_f13_s390x, + lldb_f14_s390x, + lldb_f15_s390x, + lldb_fpc_s390x, + LLDB_INVALID_REGNUM // register sets need to end with this flag + }; + static_assert((sizeof(g_fpu_regnums_s390x) / sizeof(g_fpu_regnums_s390x[0])) - 1 == k_num_fpr_registers_s390x, + "g_fpu_regnums_s390x has wrong number of register infos"); + + // s390x Linux operating-system information. + static const uint32_t g_linux_regnums_s390x[] = + { + lldb_orig_r2_s390x, + lldb_last_break_s390x, + lldb_system_call_s390x, + LLDB_INVALID_REGNUM // register sets need to end with this flag + }; + static_assert((sizeof(g_linux_regnums_s390x) / sizeof(g_linux_regnums_s390x[0])) - 1 == k_num_linux_registers_s390x, + "g_linux_regnums_s390x has wrong number of register infos"); + + // Number of register sets provided by this context. + enum + { + k_num_register_sets = 3 + }; + + // Register sets for s390x 64-bit. + static const RegisterSet g_reg_sets_s390x[k_num_register_sets] = + { + { "General Purpose Registers", "gpr", k_num_gpr_registers_s390x, g_gpr_regnums_s390x }, + { "Floating Point Registers", "fpr", k_num_fpr_registers_s390x, g_fpu_regnums_s390x }, + { "Linux Operating System Data", "linux", k_num_linux_registers_s390x, g_linux_regnums_s390x }, + }; +} + +#define REG_CONTEXT_SIZE (sizeof(s390_regs) + sizeof(s390_fp_regs) + 4) + +// ---------------------------------------------------------------------------- +// Required ptrace defines. +// ---------------------------------------------------------------------------- + +#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */ +#define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */ + +NativeRegisterContextLinux * +NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec &target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) +{ + return new NativeRegisterContextLinux_s390x(target_arch, native_thread, concrete_frame_idx); +} + +// ---------------------------------------------------------------------------- +// NativeRegisterContextLinux_s390x members. +// ---------------------------------------------------------------------------- + +static RegisterInfoInterface * +CreateRegisterInfoInterface(const ArchSpec &target_arch) +{ + assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && + "Register setting path assumes this is a 64-bit host"); + return new RegisterContextLinux_s390x(target_arch); +} + +NativeRegisterContextLinux_s390x::NativeRegisterContextLinux_s390x(const ArchSpec &target_arch, + NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) + : NativeRegisterContextLinux(native_thread, concrete_frame_idx, CreateRegisterInfoInterface(target_arch)) +{ + // Set up data about ranges of valid registers. + switch (target_arch.GetMachine()) + { + case llvm::Triple::systemz: + m_reg_info.num_registers = k_num_registers_s390x; + m_reg_info.num_gpr_registers = k_num_gpr_registers_s390x; + m_reg_info.num_fpr_registers = k_num_fpr_registers_s390x; + m_reg_info.last_gpr = k_last_gpr_s390x; + m_reg_info.first_fpr = k_first_fpr_s390x; + m_reg_info.last_fpr = k_last_fpr_s390x; + break; + default: + assert(false && "Unhandled target architecture."); + break; + } + + // Clear out the watchpoint state. + m_watchpoint_addr = LLDB_INVALID_ADDRESS; +} + +uint32_t +NativeRegisterContextLinux_s390x::GetRegisterSetCount() const +{ + uint32_t sets = 0; + for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) + { + if (IsRegisterSetAvailable(set_index)) + ++sets; + } + + return sets; +} + +uint32_t +NativeRegisterContextLinux_s390x::GetUserRegisterCount() const +{ + uint32_t count = 0; + for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) + { + const RegisterSet *set = GetRegisterSet(set_index); + if (set) + count += set->num_registers; + } + return count; +} + +const RegisterSet * +NativeRegisterContextLinux_s390x::GetRegisterSet(uint32_t set_index) const +{ + if (!IsRegisterSetAvailable(set_index)) + return nullptr; + + switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) + { + case llvm::Triple::systemz: + return &g_reg_sets_s390x[set_index]; + default: + assert(false && "Unhandled target architecture."); + return nullptr; + } + + return nullptr; +} + +bool +NativeRegisterContextLinux_s390x::IsRegisterSetAvailable(uint32_t set_index) const +{ + return set_index < k_num_register_sets; +} + +bool +NativeRegisterContextLinux_s390x::IsGPR(uint32_t reg_index) const +{ + // GPRs come first. "orig_r2" counts as GPR since it is part of the GPR register area. + return reg_index <= m_reg_info.last_gpr || reg_index == lldb_orig_r2_s390x; +} + +bool +NativeRegisterContextLinux_s390x::IsFPR(uint32_t reg_index) const +{ + return (m_reg_info.first_fpr <= reg_index && reg_index <= m_reg_info.last_fpr); +} + +Error +NativeRegisterContextLinux_s390x::ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) +{ + if (!reg_info) + return Error("reg_info NULL"); + + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg == LLDB_INVALID_REGNUM) + return Error("register \"%s\" is an internal-only lldb register, cannot read directly", reg_info->name); + + if (IsGPR(reg)) + { + s390_regs regs; + Error error = DoReadGPR(®s, sizeof(regs)); + if (error.Fail()) + return error; + + uint8_t *src = (uint8_t *)®s + reg_info->byte_offset; + assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs)); + switch (reg_info->byte_size) + { + case 4: + reg_value.SetUInt32(*(uint32_t *)src); + break; + case 8: + reg_value.SetUInt64(*(uint64_t *)src); + break; + default: + assert(false && "Unhandled data size."); + return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); + } + return Error(); + } + + if (IsFPR(reg)) + { + s390_fp_regs fp_regs; + Error error = DoReadFPR(&fp_regs, sizeof(fp_regs)); + if (error.Fail()) + return error; + + // byte_offset is just the offset within FPR, not the whole user area. + uint8_t *src = (uint8_t *)&fp_regs + reg_info->byte_offset; + assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs)); + switch (reg_info->byte_size) + { + case 4: + reg_value.SetUInt32(*(uint32_t *)src); + break; + case 8: + reg_value.SetUInt64(*(uint64_t *)src); + break; + default: + assert(false && "Unhandled data size."); + return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); + } + return Error(); + } + + if (reg == lldb_last_break_s390x) + { + uint64_t last_break; + Error error = DoReadRegisterSet(NT_S390_LAST_BREAK, &last_break, 8); + if (error.Fail()) + return error; + + reg_value.SetUInt64(last_break); + return Error(); + } + + if (reg == lldb_system_call_s390x) + { + uint32_t system_call; + Error error = DoReadRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); + if (error.Fail()) + return error; + + reg_value.SetUInt32(system_call); + return Error(); + } + + return Error("failed - register wasn't recognized"); +} + +Error +NativeRegisterContextLinux_s390x::WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) +{ + if (!reg_info) + return Error("reg_info NULL"); + + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg == LLDB_INVALID_REGNUM) + return Error("register \"%s\" is an internal-only lldb register, cannot write directly", reg_info->name); + + if (IsGPR(reg)) + { + s390_regs regs; + Error error = DoReadGPR(®s, sizeof(regs)); + if (error.Fail()) + return error; + + uint8_t *dst = (uint8_t *)®s + reg_info->byte_offset; + assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs)); + switch (reg_info->byte_size) + { + case 4: + *(uint32_t *)dst = reg_value.GetAsUInt32(); + break; + case 8: + *(uint64_t *)dst = reg_value.GetAsUInt64(); + break; + default: + assert(false && "Unhandled data size."); + return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); + } + return DoWriteGPR(®s, sizeof(regs)); + } + + if (IsFPR(reg)) + { + s390_fp_regs fp_regs; + Error error = DoReadFPR(&fp_regs, sizeof(fp_regs)); + if (error.Fail()) + return error; + + // byte_offset is just the offset within fp_regs, not the whole user area. + uint8_t *dst = (uint8_t *)&fp_regs + reg_info->byte_offset; + assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs)); + switch (reg_info->byte_size) + { + case 4: + *(uint32_t *)dst = reg_value.GetAsUInt32(); + break; + case 8: + *(uint64_t *)dst = reg_value.GetAsUInt64(); + break; + default: + assert(false && "Unhandled data size."); + return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); + } + return DoWriteFPR(&fp_regs, sizeof(fp_regs)); + } + + if (reg == lldb_last_break_s390x) + { + return Error("The last break address is read-only"); + } + + if (reg == lldb_system_call_s390x) + { + uint32_t system_call = reg_value.GetAsUInt32(); + return DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); + } + + return Error("failed - register wasn't recognized"); +} + +Error +NativeRegisterContextLinux_s390x::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) +{ + Error error; + + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + if (!data_sp) + { + error.SetErrorStringWithFormat("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE); + return error; + } + + uint8_t *dst = data_sp->GetBytes(); + if (dst == nullptr) + { + error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", + REG_CONTEXT_SIZE); + return error; + } + + error = DoReadGPR(dst, sizeof(s390_regs)); + dst += sizeof(s390_regs); + if (error.Fail()) + return error; + + error = DoReadFPR(dst, sizeof(s390_fp_regs)); + dst += sizeof(s390_fp_regs); + if (error.Fail()) + return error; + + // Ignore errors if the regset is unsupported (happens on older kernels). + DoReadRegisterSet(NT_S390_SYSTEM_CALL, dst, 4); + dst += 4; + + // To enable inferior function calls while the process is stopped in + // an interrupted system call, we need to clear the system call flag. + // It will be restored to its original value by WriteAllRegisterValues. + // Again we ignore error if the regset is unsupported. + uint32_t system_call = 0; + DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); + + return error; +} + +Error +NativeRegisterContextLinux_s390x::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) +{ + Error error; + + if (!data_sp) + { + error.SetErrorStringWithFormat("NativeRegisterContextLinux_s390x::%s invalid data_sp provided", __FUNCTION__); + return error; + } + + if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) + { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_s390x::%s data_sp contained mismatched data size, expected %" PRIu64 + ", actual %" PRIu64, + __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); + return error; + } + + uint8_t *src = data_sp->GetBytes(); + if (src == nullptr) + { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_s390x::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__); + return error; + } + + error = DoWriteGPR(src, sizeof(s390_regs)); + src += sizeof(s390_regs); + if (error.Fail()) + return error; + + error = DoWriteFPR(src, sizeof(s390_fp_regs)); + src += sizeof(s390_fp_regs); + if (error.Fail()) + return error; + + // Ignore errors if the regset is unsupported (happens on older kernels). + DoWriteRegisterSet(NT_S390_SYSTEM_CALL, src, 4); + src += 4; + + return error; +} + +Error +NativeRegisterContextLinux_s390x::DoReadRegisterValue(uint32_t offset, const char *reg_name, uint32_t size, + RegisterValue &value) +{ + return Error("DoReadRegisterValue unsupported"); +} + +Error +NativeRegisterContextLinux_s390x::DoWriteRegisterValue(uint32_t offset, const char *reg_name, + const RegisterValue &value) +{ + return Error("DoWriteRegisterValue unsupported"); +} + +Error +NativeRegisterContextLinux_s390x::PeekUserArea(uint32_t offset, void *buf, size_t buf_size) +{ + ptrace_area parea; + parea.len = buf_size; + parea.process_addr = (addr_t)buf; + parea.kernel_addr = offset; + + return NativeProcessLinux::PtraceWrapper(PTRACE_PEEKUSR_AREA, m_thread.GetID(), &parea); +} + +Error +NativeRegisterContextLinux_s390x::PokeUserArea(uint32_t offset, const void *buf, size_t buf_size) +{ + ptrace_area parea; + parea.len = buf_size; + parea.process_addr = (addr_t)buf; + parea.kernel_addr = offset; + + return NativeProcessLinux::PtraceWrapper(PTRACE_POKEUSR_AREA, m_thread.GetID(), &parea); +} + +Error +NativeRegisterContextLinux_s390x::DoReadGPR(void *buf, size_t buf_size) +{ + assert(buf_size == sizeof(s390_regs)); + return PeekUserArea(offsetof(user_regs_struct, psw), buf, buf_size); +} + +Error +NativeRegisterContextLinux_s390x::DoWriteGPR(void *buf, size_t buf_size) +{ + assert(buf_size == sizeof(s390_regs)); + return PokeUserArea(offsetof(user_regs_struct, psw), buf, buf_size); +} + +Error +NativeRegisterContextLinux_s390x::DoReadFPR(void *buf, size_t buf_size) +{ + assert(buf_size == sizeof(s390_fp_regs)); + return PeekUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size); +} + +Error +NativeRegisterContextLinux_s390x::DoWriteFPR(void *buf, size_t buf_size) +{ + assert(buf_size == sizeof(s390_fp_regs)); + return PokeUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size); +} + +Error +NativeRegisterContextLinux_s390x::DoReadRegisterSet(uint32_t regset, void *buf, size_t buf_size) +{ + struct iovec iov; + iov.iov_base = buf; + iov.iov_len = buf_size; + + return ReadRegisterSet(&iov, buf_size, regset); +} + +Error +NativeRegisterContextLinux_s390x::DoWriteRegisterSet(uint32_t regset, const void *buf, size_t buf_size) +{ + struct iovec iov; + iov.iov_base = const_cast(buf); + iov.iov_len = buf_size; + + return WriteRegisterSet(&iov, buf_size, regset); +} + +Error +NativeRegisterContextLinux_s390x::IsWatchpointHit(uint32_t wp_index, bool &is_hit) +{ + per_lowcore_bits per_lowcore; + + if (wp_index >= NumSupportedHardwareWatchpoints()) + return Error("Watchpoint index out of range"); + + if (m_watchpoint_addr == LLDB_INVALID_ADDRESS) + { + is_hit = false; + return Error(); + } + + Error error = PeekUserArea(offsetof(user_regs_struct, per_info.lowcore), &per_lowcore, sizeof(per_lowcore)); + if (error.Fail()) + { + is_hit = false; + return error; + } + + is_hit = (per_lowcore.perc_storage_alteration == 1 && per_lowcore.perc_store_real_address == 0); + + if (is_hit) + { + // Do not report this watchpoint again. + memset(&per_lowcore, 0, sizeof(per_lowcore)); + PokeUserArea(offsetof(user_regs_struct, per_info.lowcore), &per_lowcore, sizeof(per_lowcore)); + } + + return Error(); +} + +Error +NativeRegisterContextLinux_s390x::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) +{ + uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); + for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) + { + bool is_hit; + Error error = IsWatchpointHit(wp_index, is_hit); + if (error.Fail()) + { + wp_index = LLDB_INVALID_INDEX32; + return error; + } + else if (is_hit) + { + return error; + } + } + wp_index = LLDB_INVALID_INDEX32; + return Error(); +} + +Error +NativeRegisterContextLinux_s390x::IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) +{ + if (wp_index >= NumSupportedHardwareWatchpoints()) + return Error("Watchpoint index out of range"); + + is_vacant = m_watchpoint_addr == LLDB_INVALID_ADDRESS; + + return Error(); +} + +bool +NativeRegisterContextLinux_s390x::ClearHardwareWatchpoint(uint32_t wp_index) +{ + per_struct per_info; + + if (wp_index >= NumSupportedHardwareWatchpoints()) + return false; + + Error error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info)); + if (error.Fail()) + return false; + + per_info.control_regs.bits.em_storage_alteration = 0; + per_info.control_regs.bits.storage_alt_space_ctl = 0; + per_info.starting_addr = 0; + per_info.ending_addr = 0; + + error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info)); + if (error.Fail()) + return false; + + m_watchpoint_addr = LLDB_INVALID_ADDRESS; + return true; +} + +Error +NativeRegisterContextLinux_s390x::ClearAllHardwareWatchpoints() +{ + if (ClearHardwareWatchpoint(0)) + return Error(); + return Error("Clearing all hardware watchpoints failed."); +} + +uint32_t +NativeRegisterContextLinux_s390x::SetHardwareWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags) +{ + per_struct per_info; + + if (watch_flags != 0x1) + return LLDB_INVALID_INDEX32; + + if (m_watchpoint_addr != LLDB_INVALID_ADDRESS) + return LLDB_INVALID_INDEX32; + + Error error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info)); + if (error.Fail()) + return LLDB_INVALID_INDEX32; + + per_info.control_regs.bits.em_storage_alteration = 1; + per_info.control_regs.bits.storage_alt_space_ctl = 1; + per_info.starting_addr = addr; + per_info.ending_addr = addr + size - 1; + + error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info)); + if (error.Fail()) + return LLDB_INVALID_INDEX32; + + m_watchpoint_addr = addr; + return 0; +} + +lldb::addr_t +NativeRegisterContextLinux_s390x::GetWatchpointAddress(uint32_t wp_index) +{ + if (wp_index >= NumSupportedHardwareWatchpoints()) + return LLDB_INVALID_ADDRESS; + return m_watchpoint_addr; +} + +uint32_t +NativeRegisterContextLinux_s390x::NumSupportedHardwareWatchpoints() +{ + return 1; +} + +#endif // defined(__s390x__) && defined(__linux__) diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h new file mode 100644 index 000000000000..8cd4ab7f1242 --- /dev/null +++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h @@ -0,0 +1,141 @@ +//===-- NativeRegisterContextLinux_s390x.h ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#if defined(__s390x__) && defined(__linux__) + +#ifndef lldb_NativeRegisterContextLinux_s390x_h +#define lldb_NativeRegisterContextLinux_s390x_h + +#include "Plugins/Process/Linux/NativeRegisterContextLinux.h" +#include "Plugins/Process/Utility/RegisterContext_s390x.h" +#include "Plugins/Process/Utility/lldb-s390x-register-enums.h" + +namespace lldb_private +{ +namespace process_linux +{ + +class NativeProcessLinux; + +class NativeRegisterContextLinux_s390x : public NativeRegisterContextLinux +{ +public: + NativeRegisterContextLinux_s390x(const ArchSpec &target_arch, NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx); + + uint32_t + GetRegisterSetCount() const override; + + const RegisterSet * + GetRegisterSet(uint32_t set_index) const override; + + uint32_t + GetUserRegisterCount() const override; + + Error + ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) override; + + Error + WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) override; + + Error + ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + + Error + WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + + Error + IsWatchpointHit(uint32_t wp_index, bool &is_hit) override; + + Error + GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override; + + Error + IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override; + + bool + ClearHardwareWatchpoint(uint32_t wp_index) override; + + Error + ClearAllHardwareWatchpoints() override; + + uint32_t + SetHardwareWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags) override; + + lldb::addr_t + GetWatchpointAddress(uint32_t wp_index) override; + + uint32_t + NumSupportedHardwareWatchpoints() override; + +protected: + Error + DoReadRegisterValue(uint32_t offset, const char *reg_name, uint32_t size, RegisterValue &value) override; + + Error + DoWriteRegisterValue(uint32_t offset, const char *reg_name, const RegisterValue &value) override; + + Error + DoReadGPR(void *buf, size_t buf_size) override; + + Error + DoWriteGPR(void *buf, size_t buf_size) override; + + Error + DoReadFPR(void *buf, size_t buf_size) override; + + Error + DoWriteFPR(void *buf, size_t buf_size) override; + +private: + // Info about register ranges. + struct RegInfo + { + uint32_t num_registers; + uint32_t num_gpr_registers; + uint32_t num_fpr_registers; + + uint32_t last_gpr; + uint32_t first_fpr; + uint32_t last_fpr; + }; + + // Private member variables. + RegInfo m_reg_info; + lldb::addr_t m_watchpoint_addr; + + // Private member methods. + bool + IsRegisterSetAvailable(uint32_t set_index) const; + + bool + IsGPR(uint32_t reg_index) const; + + bool + IsFPR(uint32_t reg_index) const; + + Error + PeekUserArea(uint32_t offset, void *buf, size_t buf_size); + + Error + PokeUserArea(uint32_t offset, const void *buf, size_t buf_size); + + Error + DoReadRegisterSet(uint32_t regset, void *buf, size_t buf_size); + + Error + DoWriteRegisterSet(uint32_t regset, const void *buf, size_t buf_size); +}; + +} // namespace process_linux +} // namespace lldb_private + +#endif // #ifndef lldb_NativeRegisterContextLinux_s390x_h + +#endif // defined(__s390x__) && defined(__linux__) diff --git a/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/source/Plugins/Process/Linux/NativeThreadLinux.cpp index cbf82885e23a..070b1bcda3b8 100644 --- a/source/Plugins/Process/Linux/NativeThreadLinux.cpp +++ b/source/Plugins/Process/Linux/NativeThreadLinux.cpp @@ -14,10 +14,12 @@ #include "NativeProcessLinux.h" #include "NativeRegisterContextLinux.h" +#include "SingleStepCheck.h" #include "lldb/Core/Log.h" #include "lldb/Core/State.h" #include "lldb/Host/HostNativeThread.h" +#include "lldb/Host/linux/Ptrace.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/lldb-enumerations.h" @@ -199,8 +201,8 @@ NativeThreadLinux::RemoveWatchpoint (lldb::addr_t addr) return Error ("Clearing hardware watchpoint failed."); } -void -NativeThreadLinux::SetRunning () +Error +NativeThreadLinux::Resume(uint32_t signo) { const StateType new_state = StateType::eStateRunning; MaybeLogStateChange (new_state); @@ -213,29 +215,92 @@ NativeThreadLinux::SetRunning () // then this is a new thread. So set all existing watchpoints. if (m_watchpoint_index_map.empty()) { - const auto process_sp = GetProcess(); - if (process_sp) + NativeProcessLinux &process = GetProcess(); + + const auto &watchpoint_map = process.GetWatchpointMap(); + GetRegisterContext()->ClearAllHardwareWatchpoints(); + for (const auto &pair : watchpoint_map) { - const auto &watchpoint_map = process_sp->GetWatchpointMap(); - if (watchpoint_map.empty()) return; - GetRegisterContext()->ClearAllHardwareWatchpoints(); - for (const auto &pair : watchpoint_map) - { - const auto& wp = pair.second; - SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware); - } + const auto &wp = pair.second; + SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags, wp.m_hardware); } } + + intptr_t data = 0; + + if (signo != LLDB_INVALID_SIGNAL_NUMBER) + data = signo; + + return NativeProcessLinux::PtraceWrapper(PTRACE_CONT, GetID(), nullptr, reinterpret_cast(data)); } void -NativeThreadLinux::SetStepping () +NativeThreadLinux::MaybePrepareSingleStepWorkaround() +{ + if (!SingleStepWorkaroundNeeded()) + return; + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); + + if (sched_getaffinity(static_cast<::pid_t>(m_tid), sizeof m_original_cpu_set, &m_original_cpu_set) != 0) + { + // This should really not fail. But, just in case... + if (log) + { + Error error(errno, eErrorTypePOSIX); + log->Printf("NativeThreadLinux::%s Unable to get cpu affinity for thread %" PRIx64 ": %s", __FUNCTION__, + m_tid, error.AsCString()); + } + return; + } + + cpu_set_t set; + CPU_ZERO(&set); + CPU_SET(0, &set); + if (sched_setaffinity(static_cast<::pid_t>(m_tid), sizeof set, &set) != 0 && log) + { + // This may fail in very locked down systems, if the thread is not allowed to run on + // cpu 0. If that happens, only thing we can do is it log it and continue... + Error error(errno, eErrorTypePOSIX); + log->Printf("NativeThreadLinux::%s Unable to set cpu affinity for thread %" PRIx64 ": %s", __FUNCTION__, m_tid, + error.AsCString()); + } +} + +void +NativeThreadLinux::MaybeCleanupSingleStepWorkaround() +{ + if (!SingleStepWorkaroundNeeded()) + return; + + if (sched_setaffinity(static_cast<::pid_t>(m_tid), sizeof m_original_cpu_set, &m_original_cpu_set) != 0) + { + Error error(errno, eErrorTypePOSIX); + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); + log->Printf("NativeThreadLinux::%s Unable to reset cpu affinity for thread %" PRIx64 ": %s", __FUNCTION__, + m_tid, error.AsCString()); + } +} + +Error +NativeThreadLinux::SingleStep(uint32_t signo) { const StateType new_state = StateType::eStateStepping; MaybeLogStateChange (new_state); m_state = new_state; - m_stop_info.reason = StopReason::eStopReasonNone; + + MaybePrepareSingleStepWorkaround(); + + intptr_t data = 0; + if (signo != LLDB_INVALID_SIGNAL_NUMBER) + data = signo; + + // If hardware single-stepping is not supported, we just do a continue. The breakpoint on the + // next instruction has been setup in NativeProcessLinux::Resume. + return NativeProcessLinux::PtraceWrapper(GetProcess().SupportHardwareSingleStepping() ? PTRACE_SINGLESTEP + : PTRACE_CONT, + m_tid, nullptr, reinterpret_cast(data)); } void @@ -245,9 +310,7 @@ NativeThreadLinux::SetStoppedBySignal(uint32_t signo, const siginfo_t *info) if (log) log->Printf ("NativeThreadLinux::%s called with signal 0x%02" PRIx32, __FUNCTION__, signo); - const StateType new_state = StateType::eStateStopped; - MaybeLogStateChange (new_state); - m_state = new_state; + SetStopped(); m_stop_info.reason = StopReason::eStopReasonSignal; m_stop_info.details.signal.signo = signo; @@ -288,6 +351,17 @@ NativeThreadLinux::IsStopped (int *signo) return true; } +void +NativeThreadLinux::SetStopped() +{ + if (m_state == StateType::eStateStepping) + MaybeCleanupSingleStepWorkaround(); + + const StateType new_state = StateType::eStateStopped; + MaybeLogStateChange(new_state); + m_state = new_state; + m_stop_description.clear(); +} void NativeThreadLinux::SetStoppedByExec () @@ -296,9 +370,7 @@ NativeThreadLinux::SetStoppedByExec () if (log) log->Printf ("NativeThreadLinux::%s()", __FUNCTION__); - const StateType new_state = StateType::eStateStopped; - MaybeLogStateChange (new_state); - m_state = new_state; + SetStopped(); m_stop_info.reason = StopReason::eStopReasonExec; m_stop_info.details.signal.signo = SIGSTOP; @@ -307,9 +379,7 @@ NativeThreadLinux::SetStoppedByExec () void NativeThreadLinux::SetStoppedByBreakpoint () { - const StateType new_state = StateType::eStateStopped; - MaybeLogStateChange (new_state); - m_state = new_state; + SetStopped(); m_stop_info.reason = StopReason::eStopReasonBreakpoint; m_stop_info.details.signal.signo = SIGTRAP; @@ -319,10 +389,7 @@ NativeThreadLinux::SetStoppedByBreakpoint () void NativeThreadLinux::SetStoppedByWatchpoint (uint32_t wp_index) { - const StateType new_state = StateType::eStateStopped; - MaybeLogStateChange (new_state); - m_state = new_state; - m_stop_description.clear (); + SetStopped(); lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid"); @@ -363,9 +430,7 @@ NativeThreadLinux::IsStoppedAtWatchpoint () void NativeThreadLinux::SetStoppedByTrace () { - const StateType new_state = StateType::eStateStopped; - MaybeLogStateChange (new_state); - m_state = new_state; + SetStopped(); m_stop_info.reason = StopReason::eStopReasonTrace; m_stop_info.details.signal.signo = SIGTRAP; @@ -374,9 +439,7 @@ NativeThreadLinux::SetStoppedByTrace () void NativeThreadLinux::SetStoppedWithNoReason () { - const StateType new_state = StateType::eStateStopped; - MaybeLogStateChange (new_state); - m_state = new_state; + SetStopped(); m_stop_info.reason = StopReason::eStopReasonNone; m_stop_info.details.signal.signo = 0; @@ -397,11 +460,9 @@ NativeThreadLinux::RequestStop () { Log* log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); - const auto process_sp = GetProcess(); - if (! process_sp) - return Error("Process is null."); + NativeProcessLinux &process = GetProcess(); - lldb::pid_t pid = process_sp->GetID(); + lldb::pid_t pid = process.GetID(); lldb::tid_t tid = GetID(); if (log) @@ -438,3 +499,11 @@ NativeThreadLinux::MaybeLogStateChange (lldb::StateType new_state) // Log it. log->Printf ("NativeThreadLinux: thread (pid=%" PRIu64 ", tid=%" PRIu64 ") changing from state %s to %s", pid, GetID (), StateAsCString (old_state), StateAsCString (new_state)); } + +NativeProcessLinux & +NativeThreadLinux::GetProcess() +{ + auto process_sp = std::static_pointer_cast(NativeThreadProtocol::GetProcess()); + assert(process_sp); + return *process_sp; +} diff --git a/source/Plugins/Process/Linux/NativeThreadLinux.h b/source/Plugins/Process/Linux/NativeThreadLinux.h index bf6b00a78cfd..f1b6a6e44782 100644 --- a/source/Plugins/Process/Linux/NativeThreadLinux.h +++ b/source/Plugins/Process/Linux/NativeThreadLinux.h @@ -13,6 +13,8 @@ #include "lldb/lldb-private-forward.h" #include "lldb/Host/common/NativeThreadProtocol.h" +#include + #include #include #include @@ -54,11 +56,16 @@ namespace process_linux { // --------------------------------------------------------------------- // Interface for friend classes // --------------------------------------------------------------------- - void - SetRunning (); - void - SetStepping (); + /// Resumes the thread. If @p signo is anything but + /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. + Error + Resume(uint32_t signo); + + /// Single steps the thread. If @p signo is anything but + /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread. + Error + SingleStep(uint32_t signo); void SetStoppedBySignal(uint32_t signo, const siginfo_t *info = nullptr); @@ -102,6 +109,18 @@ namespace process_linux { void MaybeLogStateChange (lldb::StateType new_state); + NativeProcessLinux & + GetProcess(); + + void + SetStopped(); + + inline void + MaybePrepareSingleStepWorkaround(); + + inline void + MaybeCleanupSingleStepWorkaround(); + // --------------------------------------------------------------------- // Member Variables // --------------------------------------------------------------------- @@ -111,6 +130,7 @@ namespace process_linux { std::string m_stop_description; using WatchpointIndexMap = std::map; WatchpointIndexMap m_watchpoint_index_map; + cpu_set_t m_original_cpu_set; // For single-step workaround. }; typedef std::shared_ptr NativeThreadLinuxSP; diff --git a/source/Plugins/Process/Linux/SingleStepCheck.cpp b/source/Plugins/Process/Linux/SingleStepCheck.cpp new file mode 100644 index 000000000000..8c557d4b6ff8 --- /dev/null +++ b/source/Plugins/Process/Linux/SingleStepCheck.cpp @@ -0,0 +1,177 @@ +//===-- SingleStepCheck.cpp ----------------------------------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "SingleStepCheck.h" + +#include +#include +#include +#include + +#include "NativeProcessLinux.h" + +#include "llvm/Support/Compiler.h" + +#include "lldb/Core/Error.h" +#include "lldb/Core/Log.h" +#include "lldb/Host/linux/Ptrace.h" + +using namespace lldb_private::process_linux; + +#if defined(__arm64__) || defined(__aarch64__) +namespace +{ + +void LLVM_ATTRIBUTE_NORETURN +Child() +{ + if (ptrace(PTRACE_TRACEME, 0, nullptr, nullptr) == -1) + _exit(1); + + // We just do an endless loop SIGSTOPPING ourselves until killed. The tracer will fiddle with our cpu + // affinities and monitor the behaviour. + for (;;) + { + raise(SIGSTOP); + + // Generate a bunch of instructions here, so that a single-step does not land in the + // raise() accidentally. If single-stepping works, we will be spinning in this loop. If + // it doesn't, we'll land in the raise() call above. + for (volatile unsigned i = 0; i < CPU_SETSIZE; ++i) + ; + } +} + +struct ChildDeleter +{ + ::pid_t pid; + + ~ChildDeleter() + { + int status; + kill(pid, SIGKILL); // Kill the child. + waitpid(pid, &status, __WALL); // Pick up the remains. + } +}; + +} // end anonymous namespace + +bool +impl::SingleStepWorkaroundNeeded() +{ + // We shall spawn a child, and use it to verify the debug capabilities of the cpu. We shall + // iterate through the cpus, bind the child to each one in turn, and verify that + // single-stepping works on that cpu. A workaround is needed if we find at least one broken + // cpu. + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); + Error error; + ::pid_t child_pid = fork(); + if (child_pid == -1) + { + if (log) + { + error.SetErrorToErrno(); + log->Printf("%s failed to fork(): %s", __FUNCTION__, error.AsCString()); + } + return false; + } + if (child_pid == 0) + Child(); + + ChildDeleter child_deleter{child_pid}; + cpu_set_t available_cpus; + if (sched_getaffinity(child_pid, sizeof available_cpus, &available_cpus) == -1) + { + if (log) + { + error.SetErrorToErrno(); + log->Printf("%s failed to get available cpus: %s", __FUNCTION__, error.AsCString()); + } + return false; + } + + int status; + ::pid_t wpid = waitpid(child_pid, &status, __WALL); + if (wpid != child_pid || !WIFSTOPPED(status)) + { + if (log) + { + error.SetErrorToErrno(); + log->Printf("%s waitpid() failed (status = %x): %s", __FUNCTION__, status, error.AsCString()); + } + return false; + } + + unsigned cpu; + for (cpu = 0; cpu < CPU_SETSIZE; ++cpu) + { + if (!CPU_ISSET(cpu, &available_cpus)) + continue; + + cpu_set_t cpus; + CPU_ZERO(&cpus); + CPU_SET(cpu, &cpus); + if (sched_setaffinity(child_pid, sizeof cpus, &cpus) == -1) + { + if (log) + { + error.SetErrorToErrno(); + log->Printf("%s failed to switch to cpu %u: %s", __FUNCTION__, cpu, error.AsCString()); + } + continue; + } + + int status; + error = NativeProcessLinux::PtraceWrapper(PTRACE_SINGLESTEP, child_pid); + if (error.Fail()) + { + if (log) + log->Printf("%s single step failed: %s", __FUNCTION__, error.AsCString()); + break; + } + + wpid = waitpid(child_pid, &status, __WALL); + if (wpid != child_pid || !WIFSTOPPED(status)) + { + if (log) + { + error.SetErrorToErrno(); + log->Printf("%s waitpid() failed (status = %x): %s", __FUNCTION__, status, error.AsCString()); + } + break; + } + if (WSTOPSIG(status) != SIGTRAP) + { + if (log) + log->Printf("%s single stepping on cpu %d failed with status %x", __FUNCTION__, cpu, status); + break; + } + } + + // cpu is either the index of the first broken cpu, or CPU_SETSIZE. + if (cpu == 0) + { + if (log) + log->Printf("%s SINGLE STEPPING ON FIRST CPU IS NOT WORKING. DEBUGGING LIKELY TO BE UNRELIABLE.", + __FUNCTION__); + // No point in trying to fiddle with the affinities, just give it our best shot and see how it goes. + return false; + } + + return cpu != CPU_SETSIZE; +} + +#else // !arm64 +bool +impl::SingleStepWorkaroundNeeded() +{ + return false; +} +#endif diff --git a/source/Plugins/Process/Linux/SingleStepCheck.h b/source/Plugins/Process/Linux/SingleStepCheck.h new file mode 100644 index 000000000000..f83f7c973f8d --- /dev/null +++ b/source/Plugins/Process/Linux/SingleStepCheck.h @@ -0,0 +1,41 @@ +//===-- SingleStepCheck.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_SingleStepCheck_H_ +#define liblldb_SingleStepCheck_H_ + +namespace lldb_private +{ +namespace process_linux +{ + +namespace impl +{ +extern bool +SingleStepWorkaroundNeeded(); +} + +// arm64 linux had a bug which prevented single-stepping and watchpoints from working on non-boot +// cpus, due to them being incorrectly initialized after coming out of suspend. This issue is +// particularly affecting android M, which uses suspend ("doze mode") quite aggressively. This +// code detects that situation and makes single-stepping work by doing all the step operations on +// the boot cpu. +// +// The underlying issue has been fixed in android N and linux 4.4. This code can be removed once +// these systems become obsolete. +inline bool +SingleStepWorkaroundNeeded() +{ + static bool value = impl::SingleStepWorkaroundNeeded(); + return value; +} +} // end namespace process_linux +} // end namespace lldb_private + +#endif // #ifndef liblldb_SingleStepCheck_H_ diff --git a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp index 5c1c3284a35c..29a0d58f7080 100644 --- a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp +++ b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp @@ -37,21 +37,21 @@ using namespace lldb_private; //---------------------------------------------------------------------- // CommunicationKDP constructor //---------------------------------------------------------------------- -CommunicationKDP::CommunicationKDP (const char *comm_name) : - Communication(comm_name), - m_addr_byte_size (4), - m_byte_order (eByteOrderLittle), - m_packet_timeout (5), - m_sequence_mutex (Mutex::eMutexTypeRecursive), - m_is_running (false), - m_session_key (0u), - m_request_sequence_id (0u), - m_exception_sequence_id (0u), - m_kdp_version_version (0u), - m_kdp_version_feature (0u), - m_kdp_hostinfo_cpu_mask (0u), - m_kdp_hostinfo_cpu_type (0u), - m_kdp_hostinfo_cpu_subtype (0u) +CommunicationKDP::CommunicationKDP(const char *comm_name) + : Communication(comm_name), + m_addr_byte_size(4), + m_byte_order(eByteOrderLittle), + m_packet_timeout(5), + m_sequence_mutex(), + m_is_running(false), + m_session_key(0u), + m_request_sequence_id(0u), + m_exception_sequence_id(0u), + m_kdp_version_version(0u), + m_kdp_version_feature(0u), + m_kdp_hostinfo_cpu_mask(0u), + m_kdp_hostinfo_cpu_type(0u), + m_kdp_hostinfo_cpu_subtype(0u) { } @@ -69,7 +69,7 @@ CommunicationKDP::~CommunicationKDP() bool CommunicationKDP::SendRequestPacket (const PacketStreamType &request_packet) { - Mutex::Locker locker(m_sequence_mutex); + std::lock_guard guard(m_sequence_mutex); return SendRequestPacketNoLock (request_packet); } @@ -111,7 +111,7 @@ CommunicationKDP::SendRequestAndGetReply (const CommandType command, return false; } - Mutex::Locker locker(m_sequence_mutex); + std::lock_guard guard(m_sequence_mutex); #ifdef LLDB_CONFIGURATION_DEBUG // NOTE: this only works for packets that are in native endian byte order assert (request_packet.GetSize() == *((uint16_t *)(request_packet.GetData() + 2))); @@ -205,9 +205,9 @@ CommunicationKDP::SendRequestPacketNoLock (const PacketStreamType &request_packe } bool -CommunicationKDP::GetSequenceMutex (Mutex::Locker& locker) +CommunicationKDP::GetSequenceMutex(std::unique_lock &lock) { - return locker.TryLock (m_sequence_mutex); + return (lock = std::unique_lock(m_sequence_mutex, std::try_to_lock)).owns_lock(); } @@ -220,7 +220,7 @@ CommunicationKDP::WaitForNotRunningPrivate (const TimeValue *timeout_ptr) size_t CommunicationKDP::WaitForPacketWithTimeoutMicroSeconds (DataExtractor &packet, uint32_t timeout_usec) { - Mutex::Locker locker(m_sequence_mutex); + std::lock_guard guard(m_sequence_mutex); return WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec); } @@ -284,8 +284,8 @@ bool CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, DataExtractor &packet) { // Put the packet data into the buffer in a thread safe fashion - Mutex::Locker locker(m_bytes_mutex); - + std::lock_guard guard(m_bytes_mutex); + Log *log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); if (src && src_len > 0) @@ -326,6 +326,7 @@ CommunicationKDP::CheckForPacket (const uint8_t *src, size_t src_len, DataExtrac SendRequestPacketNoLock (request_ack_packet); } // Fall through to case below to get packet contents + LLVM_FALLTHROUGH; case ePacketTypeReply | KDP_CONNECT: case ePacketTypeReply | KDP_DISCONNECT: case ePacketTypeReply | KDP_HOSTINFO: diff --git a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h index 98a146d5a06d..89e55a561e74 100644 --- a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h +++ b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h @@ -13,6 +13,7 @@ // C Includes // C++ Includes #include +#include #include // Other libraries and framework includes @@ -21,7 +22,6 @@ #include "lldb/Core/Communication.h" #include "lldb/Core/Listener.h" #include "lldb/Core/StreamBuffer.h" -#include "lldb/Host/Mutex.h" #include "lldb/Host/Predicate.h" #include "lldb/Host/TimeValue.h" @@ -109,7 +109,7 @@ public: uint32_t usec); bool - GetSequenceMutex(lldb_private::Mutex::Locker& locker); + GetSequenceMutex(std::unique_lock &lock); bool CheckForPacket (const uint8_t *src, @@ -324,7 +324,7 @@ protected: uint32_t m_addr_byte_size; lldb::ByteOrder m_byte_order; uint32_t m_packet_timeout; - lldb_private::Mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time + std::recursive_mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time lldb_private::Predicate m_is_running; uint32_t m_session_key; uint8_t m_request_sequence_id; diff --git a/source/Plugins/Process/MacOSX-Kernel/Makefile b/source/Plugins/Process/MacOSX-Kernel/Makefile deleted file mode 100644 index e42f390ffe0d..000000000000 --- a/source/Plugins/Process/MacOSX-Kernel/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Process/MacOSX-Darwin/Makefile -------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginProcessDarwin -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp index 628f76d104fe..898677df616b 100644 --- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp +++ b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp @@ -132,12 +132,12 @@ ProcessKDP::Terminate() lldb::ProcessSP ProcessKDP::CreateInstance (TargetSP target_sp, - Listener &listener, + ListenerSP listener_sp, const FileSpec *crash_file_path) { lldb::ProcessSP process_sp; if (crash_file_path == NULL) - process_sp.reset(new ProcessKDP (target_sp, listener)); + process_sp.reset(new ProcessKDP (target_sp, listener_sp)); return process_sp; } @@ -178,8 +178,8 @@ ProcessKDP::CanDebug(TargetSP target_sp, bool plugin_specified_by_name) //---------------------------------------------------------------------- // ProcessKDP constructor //---------------------------------------------------------------------- -ProcessKDP::ProcessKDP(TargetSP target_sp, Listener &listener) : - Process (target_sp, listener), +ProcessKDP::ProcessKDP(TargetSP target_sp, ListenerSP listener_sp) : + Process (target_sp, listener_sp), m_comm("lldb.process.kdp-remote.communication"), m_async_broadcaster (NULL, "lldb.process.kdp-remote.async-broadcaster"), m_dyld_plugin_name (), @@ -927,13 +927,13 @@ ProcessKDP::AsyncThread (void *arg) if (log) log->Printf ("ProcessKDP::AsyncThread (arg = %p, pid = %" PRIu64 ") thread starting...", arg, pid); - Listener listener ("ProcessKDP::AsyncThread"); + ListenerSP listener_sp (Listener::MakeListener("ProcessKDP::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) + if (listener_sp->StartListeningForEvents (&process->m_async_broadcaster, desired_event_mask) == desired_event_mask) { bool done = false; while (!done) @@ -941,7 +941,7 @@ ProcessKDP::AsyncThread (void *arg) if (log) log->Printf ("ProcessKDP::AsyncThread (pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...", pid); - if (listener.WaitForEvent (NULL, event_sp)) + if (listener_sp->WaitForEvent (NULL, event_sp)) { uint32_t event_type = event_sp->GetType(); if (log) @@ -981,7 +981,7 @@ ProcessKDP::AsyncThread (void *arg) // Check to see if we are supposed to exit. There is no way to // interrupt a running kernel, so all we can do is wait for an // exception or detach... - if (listener.GetNextEvent(event_sp)) + if (listener_sp->GetNextEvent(event_sp)) { // We got an event, go through the loop again event_type = event_sp->GetType(); @@ -1187,11 +1187,9 @@ public: class CommandObjectMultiwordProcessKDP : public CommandObjectMultiword { public: - CommandObjectMultiwordProcessKDP (CommandInterpreter &interpreter) : - CommandObjectMultiword (interpreter, - "process plugin", - "A set of commands for operating on a ProcessKDP process.", - "process plugin []") + CommandObjectMultiwordProcessKDP(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "process plugin", "Commands for operating on a ProcessKDP process.", + "process plugin []") { LoadSubCommand ("packet", CommandObjectSP (new CommandObjectProcessKDPPacket (interpreter))); } diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h index fe9a4e2844bf..49f636242510 100644 --- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h +++ b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h @@ -40,7 +40,7 @@ public: //------------------------------------------------------------------ static lldb::ProcessSP CreateInstance (lldb::TargetSP target_sp, - lldb_private::Listener &listener, + lldb::ListenerSP listener_sp, const lldb_private::FileSpec *crash_file_path); static void @@ -61,7 +61,7 @@ public: //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ - ProcessKDP(lldb::TargetSP target_sp, lldb_private::Listener &listener); + ProcessKDP(lldb::TargetSP target_sp, lldb::ListenerSP listener); virtual ~ProcessKDP(); diff --git a/source/Plugins/Process/POSIX/Makefile b/source/Plugins/Process/POSIX/Makefile deleted file mode 100644 index e8ac3a8ae0ed..000000000000 --- a/source/Plugins/Process/POSIX/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -##===- source/Plugins/Process/POSIX/Makefile ---------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginProcessPOSIX -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/../../Makefile.config - -# Extend the include path so we may locate UnwindLLDB.h -CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Utility - -ifeq ($(HOST_OS),Linux) -CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/Linux - -# Disable warning for now as offsetof is used with an index into a structure member array -# in defining register info tables. -CPP.Flags += -Wno-extended-offsetof -endif - -ifneq (,$(filter $(HOST_OS), FreeBSD GNU/kFreeBSD)) -# Extend the include path so we may locate ProcessMonitor -CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLDB_LEVEL)/source/Plugins/Process/FreeBSD -endif - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Process/Utility/CMakeLists.txt b/source/Plugins/Process/Utility/CMakeLists.txt index 4a847b4f966a..eb0c81fd7979 100644 --- a/source/Plugins/Process/Utility/CMakeLists.txt +++ b/source/Plugins/Process/Utility/CMakeLists.txt @@ -28,16 +28,19 @@ add_lldb_library(lldbPluginProcessUtility RegisterContextLinux_x86_64.cpp RegisterContextLinux_mips64.cpp RegisterContextLinux_mips.cpp + RegisterContextLinux_s390x.cpp RegisterContextLLDB.cpp RegisterContextMacOSXFrameBackchain.cpp RegisterContextMach_arm.cpp RegisterContextMach_i386.cpp RegisterContextMach_x86_64.cpp RegisterContextMemory.cpp + RegisterContextNetBSD_x86_64.cpp RegisterContextPOSIX_arm.cpp RegisterContextPOSIX_arm64.cpp RegisterContextPOSIX_mips64.cpp RegisterContextPOSIX_powerpc.cpp + RegisterContextPOSIX_s390x.cpp RegisterContextPOSIX_x86.cpp RegisterContextThreadMemory.cpp StopInfoMachException.cpp diff --git a/source/Plugins/Process/Utility/HistoryThread.cpp b/source/Plugins/Process/Utility/HistoryThread.cpp index 206b8290c5fd..956539da219c 100644 --- a/source/Plugins/Process/Utility/HistoryThread.cpp +++ b/source/Plugins/Process/Utility/HistoryThread.cpp @@ -22,28 +22,24 @@ using namespace lldb_private; // Constructor -HistoryThread::HistoryThread (lldb_private::Process &process, - lldb::tid_t tid, - std::vector pcs, - uint32_t stop_id, - bool stop_id_is_valid) : - Thread (process, tid, true), - m_framelist_mutex(), - m_framelist(), - m_pcs (pcs), - m_stop_id (stop_id), - m_stop_id_is_valid (stop_id_is_valid), - m_extended_unwind_token (LLDB_INVALID_ADDRESS), - m_queue_name (), - m_thread_name (), - m_originating_unique_thread_id (tid), - m_queue_id (LLDB_INVALID_QUEUE_ID) +HistoryThread::HistoryThread(lldb_private::Process &process, lldb::tid_t tid, std::vector pcs, + uint32_t stop_id, bool stop_id_is_valid) + : Thread(process, tid, true), + m_framelist_mutex(), + m_framelist(), + m_pcs(pcs), + m_stop_id(stop_id), + m_stop_id_is_valid(stop_id_is_valid), + m_extended_unwind_token(LLDB_INVALID_ADDRESS), + m_queue_name(), + m_thread_name(), + m_originating_unique_thread_id(tid), + m_queue_id(LLDB_INVALID_QUEUE_ID) { - m_unwinder_ap.reset (new HistoryUnwind (*this, pcs, stop_id_is_valid)); - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); + m_unwinder_ap.reset(new HistoryUnwind(*this, pcs, stop_id_is_valid)); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); if (log) - log->Printf ("%p HistoryThread::HistoryThread", - static_cast(this)); + log->Printf("%p HistoryThread::HistoryThread", static_cast(this)); } // Destructor @@ -78,7 +74,9 @@ HistoryThread::CreateRegisterContextForFrame (StackFrame *frame) lldb::StackFrameListSP HistoryThread::GetStackFrameList () { - Mutex::Locker (m_framelist_mutex); // FIXME do not throw away the lock after we acquire it.. + // FIXME do not throw away the lock after we acquire it.. + std::unique_lock lock(m_framelist_mutex); + lock.unlock(); if (m_framelist.get() == NULL) { m_framelist.reset (new StackFrameList (*this, StackFrameListSP(), true)); diff --git a/source/Plugins/Process/Utility/HistoryThread.h b/source/Plugins/Process/Utility/HistoryThread.h index e87f6496134b..43ac13c2d8bc 100644 --- a/source/Plugins/Process/Utility/HistoryThread.h +++ b/source/Plugins/Process/Utility/HistoryThread.h @@ -12,10 +12,11 @@ // C Includes // C++ Includes +#include + // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" -#include "lldb/Host/Mutex.h" #include "lldb/Core/Broadcaster.h" #include "lldb/Core/Event.h" #include "lldb/Core/UserID.h" @@ -125,7 +126,7 @@ protected: virtual lldb::StackFrameListSP GetStackFrameList (); - mutable Mutex m_framelist_mutex; + mutable std::mutex m_framelist_mutex; lldb::StackFrameListSP m_framelist; std::vector m_pcs; uint32_t m_stop_id; diff --git a/source/Plugins/Process/Utility/HistoryUnwind.cpp b/source/Plugins/Process/Utility/HistoryUnwind.cpp index 14afcbee0b49..01d8c3ebdcd3 100644 --- a/source/Plugins/Process/Utility/HistoryUnwind.cpp +++ b/source/Plugins/Process/Utility/HistoryUnwind.cpp @@ -40,7 +40,7 @@ HistoryUnwind::~HistoryUnwind () void HistoryUnwind::DoClear () { - Mutex::Locker locker(m_unwind_mutex); + std::lock_guard guard(m_unwind_mutex); m_pcs.clear(); m_stop_id_is_valid = false; } @@ -64,7 +64,9 @@ HistoryUnwind::DoCreateRegisterContextForFrame (StackFrame *frame) bool HistoryUnwind::DoGetFrameInfoAtIndex (uint32_t frame_idx, lldb::addr_t& cfa, lldb::addr_t& pc) { - Mutex::Locker (m_unwind_mutex); // FIXME do not throw away the lock after we acquire it.. + // FIXME do not throw away the lock after we acquire it.. + std::unique_lock guard(m_unwind_mutex); + guard.unlock(); if (frame_idx < m_pcs.size()) { cfa = frame_idx; diff --git a/source/Plugins/Process/Utility/HistoryUnwind.h b/source/Plugins/Process/Utility/HistoryUnwind.h index 2cb78bc1dc63..890604fcb680 100644 --- a/source/Plugins/Process/Utility/HistoryUnwind.h +++ b/source/Plugins/Process/Utility/HistoryUnwind.h @@ -17,7 +17,6 @@ // Other libraries and framework includes // Project includes #include "lldb/lldb-private.h" -#include "lldb/Host/Mutex.h" #include "lldb/Target/Unwind.h" namespace lldb_private { diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp index ebeba8c46a74..b694b833cb48 100644 --- a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp +++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp @@ -11,6 +11,8 @@ #include "lldb/Core/Address.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Expression/DiagnosticManager.h" +#include "lldb/Host/Config.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/ExecutionContext.h" @@ -18,7 +20,6 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadPlanCallFunction.h" -#include "lldb/Host/Config.h" #ifndef LLDB_DISABLE_POSIX #include @@ -43,7 +44,7 @@ lldb_private::InferiorCallMmap (Process *process, addr_t fd, addr_t offset) { - Thread *thread = process->GetThreadList().GetSelectedThread().get(); + Thread *thread = process->GetThreadList().GetExpressionExecutionThread().get(); if (thread == NULL) return false; @@ -96,27 +97,21 @@ lldb_private::InferiorCallMmap (Process *process, ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); 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(), - clang_void_ptr_type, - args, - options)); + lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(), + clang_void_ptr_type, args, options)); if (call_plan_sp) { - StreamFile error_strm; - - StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); + DiagnosticManager diagnostics; + + StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); if (frame) { ExecutionContext exe_ctx; frame->CalculateExecutionContext (exe_ctx); - ExpressionResults result = process->RunThreadPlan (exe_ctx, - call_plan_sp, - options, - error_strm); + ExpressionResults result = process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); if (result == eExpressionCompleted) { - + allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); if (process->GetAddressByteSize() == 4) { @@ -144,7 +139,7 @@ lldb_private::InferiorCallMunmap (Process *process, addr_t addr, addr_t length) { - Thread *thread = process->GetThreadList().GetSelectedThread().get(); + Thread *thread = process->GetThreadList().GetExpressionExecutionThread().get(); if (thread == NULL) return false; @@ -179,24 +174,18 @@ lldb_private::InferiorCallMunmap (Process *process, if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range)) { lldb::addr_t args[] = { addr, length }; - lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, - munmap_range.GetBaseAddress(), - CompilerType(), - args, - options)); + lldb::ThreadPlanSP call_plan_sp( + new ThreadPlanCallFunction(*thread, munmap_range.GetBaseAddress(), CompilerType(), args, options)); if (call_plan_sp) { - StreamFile error_strm; - - StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); + DiagnosticManager diagnostics; + + StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); if (frame) { ExecutionContext exe_ctx; frame->CalculateExecutionContext (exe_ctx); - ExpressionResults result = process->RunThreadPlan (exe_ctx, - call_plan_sp, - options, - error_strm); + ExpressionResults result = process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); if (result == eExpressionCompleted) { return true; @@ -219,7 +208,7 @@ lldb_private::InferiorCall (Process *process, addr_t &returned_func, bool trap_exceptions) { - Thread *thread = process->GetThreadList().GetSelectedThread().get(); + Thread *thread = process->GetThreadList().GetExpressionExecutionThread().get(); if (thread == NULL || address == NULL) return false; @@ -234,24 +223,18 @@ lldb_private::InferiorCall (Process *process, ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, - *address, - clang_void_ptr_type, - llvm::ArrayRef(), - options)); + lldb::ThreadPlanSP call_plan_sp( + new ThreadPlanCallFunction(*thread, *address, clang_void_ptr_type, llvm::ArrayRef(), options)); if (call_plan_sp) { - StreamString error_strm; + DiagnosticManager diagnostics; - StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); + StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); if (frame) { ExecutionContext exe_ctx; frame->CalculateExecutionContext (exe_ctx); - ExpressionResults result = process->RunThreadPlan (exe_ctx, - call_plan_sp, - options, - error_strm); + ExpressionResults result = process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); if (result == eExpressionCompleted) { returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); diff --git a/source/Plugins/Process/Utility/Makefile b/source/Plugins/Process/Utility/Makefile deleted file mode 100644 index eb0caf3f92fe..000000000000 --- a/source/Plugins/Process/Utility/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Utility/Makefile ---------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginProcessUtility -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp index 452fb47ebc8a..aa1bace77203 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp @@ -596,6 +596,7 @@ RegisterContextDarwin_arm::ReadRegisterSet (uint32_t set, bool force) switch (set) { case GPRRegSet: return ReadGPR(force); + case GPRAltRegSet: return ReadGPR(force); case FPURegSet: return ReadFPU(force); case EXCRegSet: return ReadEXC(force); case DBGRegSet: return ReadDBG(force); @@ -613,6 +614,7 @@ RegisterContextDarwin_arm::WriteRegisterSet (uint32_t set) switch (set) { case GPRRegSet: return WriteGPR(); + case GPRAltRegSet: return WriteGPR(); case FPURegSet: return WriteFPU(); case EXCRegSet: return WriteEXC(); case DBGRegSet: return WriteDBG(); diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h index f4d82259f9df..4e831b5a8da7 100644 --- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h +++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h @@ -162,10 +162,11 @@ public: protected: enum { - GPRRegSet = 1, // ARM_THREAD_STATE - FPURegSet = 2, // ARM_VFP_STATE - EXCRegSet = 3, // ARM_EXCEPTION_STATE - DBGRegSet = 4 // ARM_DEBUG_STATE + GPRRegSet = 1, // ARM_THREAD_STATE + GPRAltRegSet = 9, // ARM_THREAD_STATE32 + FPURegSet = 2, // ARM_VFP_STATE + EXCRegSet = 3, // ARM_EXCEPTION_STATE + DBGRegSet = 4 // ARM_DEBUG_STATE }; enum diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp index efda0edb70c9..8bbaeb8e9a59 100644 --- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -470,11 +470,13 @@ RegisterContextLLDB::InitializeNonZerothFrame() return; } - bool resolve_tail_call_address = true; // m_current_pc can be one past the address range of the function... - // This will handle the case where the saved pc does not point to - // a function/symbol because it is beyond the bounds of the correct - // function and there's no symbol there. ResolveSymbolContextForAddress - // will fail to find a symbol, back up the pc by 1 and re-search. + bool resolve_tail_call_address = false; // m_current_pc can be one past the address range of the function... + // If the saved pc does not point to a function/symbol because it is + // beyond the bounds of the correct function and there's no symbol there, + // we do *not* want ResolveSymbolContextForAddress to back up the pc by 1, + // because then we might not find the correct unwind information later. + // Instead, let ResolveSymbolContextForAddress fail, and handle the case + // via decr_pc_and_recompute_addr_range below. const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol; uint32_t resolved_scope = pc_module_sp->ResolveSymbolContextForAddress (m_current_pc, resolve_scope, @@ -1390,45 +1392,28 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat } } - if (have_unwindplan_regloc == false) - { - // Did the UnwindPlan fail to give us the caller's stack pointer? - // The stack pointer is defined to be the same as THIS frame's CFA, so return the CFA value as - // the caller's stack pointer. This is true on x86-32/x86-64 at least. - - RegisterNumber sp_regnum (m_thread, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); - if (sp_regnum.GetAsKind (eRegisterKindLLDB) != LLDB_INVALID_REGNUM - && sp_regnum.GetAsKind (eRegisterKindLLDB) == regnum.GetAsKind (eRegisterKindLLDB)) - { - // make sure we won't lose precision copying an addr_t (m_cfa) into a uint64_t (.inferred_value) - assert (sizeof (addr_t) <= sizeof (uint64_t)); - regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred; - regloc.location.inferred_value = m_cfa; - m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc; - UnwindLogMsg ("supplying caller's stack pointer %s (%d) value, computed from CFA", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); - return UnwindLLDB::RegisterSearchResult::eRegisterFound; - } - } - ExecutionContext exe_ctx(m_thread.shared_from_this()); Process *process = exe_ctx.GetProcessPtr(); if (have_unwindplan_regloc == false) { - // If a volatile register is being requested, we don't want to forward the next frame's register contents - // up the stack -- the register is not retrievable at this frame. + // If the UnwindPlan failed to give us an unwind location for this register, we may be able to fall back + // to some ABI-defined default. For example, some ABIs allow to determine the caller's SP via the CFA. + // Also, the ABI may set volatile registers to the undefined state. ABI *abi = process ? process->GetABI().get() : NULL; if (abi) { const RegisterInfo *reg_info = GetRegisterInfoAtIndex(regnum.GetAsKind (eRegisterKindLLDB)); - if (reg_info && abi->RegisterIsVolatile (reg_info)) + if (reg_info && abi->GetFallbackRegisterLocation (reg_info, unwindplan_regloc)) { - UnwindLogMsg ("did not supply reg location for %s (%d) because it is volatile", + UnwindLogMsg ("supplying caller's saved %s (%d)'s location using ABI default", regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); - return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile; + have_unwindplan_regloc = true; } } + } + if (have_unwindplan_regloc == false) + { if (IsFrameZero ()) { // This is frame 0 - we should return the actual live register context value @@ -1468,15 +1453,33 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; } + if (unwindplan_regloc.IsUndefined()) + { + UnwindLogMsg ("did not supply reg location for %s (%d) because it is volatile", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); + return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile; + } + if (unwindplan_regloc.IsSame()) { - regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister; - regloc.location.register_number = regnum.GetAsKind (eRegisterKindLLDB); - m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc; - UnwindLogMsg ("supplying caller's register %s (%d), saved in register %s (%d)", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); - return UnwindLLDB::RegisterSearchResult::eRegisterFound; + if (IsFrameZero() == false + && (regnum.GetAsKind (eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_PC + || regnum.GetAsKind (eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_RA)) + { + UnwindLogMsg ("register %s (%d) is marked as 'IsSame' - it is a pc or return address reg on a non-zero frame -- treat as if we have no information", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); + return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; + } + else + { + regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister; + regloc.location.register_number = regnum.GetAsKind (eRegisterKindLLDB); + m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc; + UnwindLogMsg ("supplying caller's register %s (%d), saved in register %s (%d)", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); + return UnwindLLDB::RegisterSearchResult::eRegisterFound; + } } if (unwindplan_regloc.IsCFAPlusOffset()) @@ -1536,7 +1539,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat dwarfexpr.SetRegisterKind (unwindplan_registerkind); Value result; Error error; - if (dwarfexpr.Evaluate (&exe_ctx, NULL, NULL, this, 0, NULL, result, &error)) + if (dwarfexpr.Evaluate (&exe_ctx, nullptr, nullptr, this, 0, nullptr, nullptr, result, &error)) { addr_t val; val = result.GetScalar().ULongLong(); @@ -1836,7 +1839,7 @@ RegisterContextLLDB::ReadCFAValueForRow (lldb::RegisterKind row_register_kind, dwarfexpr.SetRegisterKind (row_register_kind); Value result; Error error; - if (dwarfexpr.Evaluate (&exe_ctx, NULL, NULL, this, 0, NULL, result, &error)) + if (dwarfexpr.Evaluate (&exe_ctx, nullptr, nullptr, this, 0, nullptr, nullptr, result, &error)) { cfa_value = result.GetScalar().ULongLong(); @@ -1897,12 +1900,13 @@ RegisterContextLLDB::ReadGPRValue (lldb::RegisterKind register_kind, uint32_t re bool pc_register = false; uint32_t generic_regnum; - if (register_kind == eRegisterKindGeneric && regnum == LLDB_REGNUM_GENERIC_PC) + if (register_kind == eRegisterKindGeneric + && (regnum == LLDB_REGNUM_GENERIC_PC || regnum == LLDB_REGNUM_GENERIC_RA)) { pc_register = true; } else if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (register_kind, regnum, eRegisterKindGeneric, generic_regnum) - && generic_regnum == LLDB_REGNUM_GENERIC_PC) + && (generic_regnum == LLDB_REGNUM_GENERIC_PC || generic_regnum == LLDB_REGNUM_GENERIC_RA)) { pc_register = true; } @@ -1944,9 +1948,16 @@ RegisterContextLLDB::ReadRegister (const RegisterInfo *reg_info, RegisterValue & return m_thread.GetRegisterContext()->ReadRegister (reg_info, value); } + bool is_pc_regnum = false; + if (reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_PC + || reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_RA) + { + is_pc_regnum = true; + } + lldb_private::UnwindLLDB::RegisterLocation regloc; // Find out where the NEXT frame saved THIS frame's register contents - if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, false)) + if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, is_pc_regnum)) return false; return ReadRegisterValueFromRegisterLocation (regloc, reg_info, value); diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_s390x.cpp b/source/Plugins/Process/Utility/RegisterContextLinux_s390x.cpp new file mode 100644 index 000000000000..9aef1e9830e2 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextLinux_s390x.cpp @@ -0,0 +1,98 @@ +//===-- RegisterContextLinux_s390x.cpp --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "RegisterContextPOSIX_s390x.h" +#include "RegisterContextLinux_s390x.h" + +using namespace lldb_private; +using namespace lldb; + +//--------------------------------------------------------------------------- +// Include RegisterInfos_s390x to declare our g_register_infos_s390x structure. +//--------------------------------------------------------------------------- +#define DECLARE_REGISTER_INFOS_S390X_STRUCT +#include "RegisterInfos_s390x.h" +#undef DECLARE_REGISTER_INFOS_S390X_STRUCT + +static const RegisterInfo * +GetRegisterInfoPtr(const ArchSpec &target_arch) +{ + switch (target_arch.GetMachine()) + { + case llvm::Triple::systemz: + return g_register_infos_s390x; + default: + assert(false && "Unhandled target architecture."); + return nullptr; + } +} + +static uint32_t +GetRegisterInfoCount(const ArchSpec &target_arch) +{ + switch (target_arch.GetMachine()) + { + case llvm::Triple::systemz: + return k_num_registers_s390x; + default: + assert(false && "Unhandled target architecture."); + return 0; + } +} + +static uint32_t +GetUserRegisterInfoCount(const ArchSpec &target_arch) +{ + switch (target_arch.GetMachine()) + { + case llvm::Triple::systemz: + return k_num_user_registers_s390x + k_num_linux_registers_s390x; + default: + assert(false && "Unhandled target architecture."); + return 0; + } +} + +RegisterContextLinux_s390x::RegisterContextLinux_s390x(const ArchSpec &target_arch) + : 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)) +{ +} + +const std::vector * +RegisterContextLinux_s390x::GetDynamicRegisterInfoP() const +{ + return &d_register_infos; +} + +const RegisterInfo * +RegisterContextLinux_s390x::GetRegisterInfo() const +{ + return m_register_info_p; +} + +uint32_t +RegisterContextLinux_s390x::GetRegisterCount() const +{ + return m_register_info_count; +} + +uint32_t +RegisterContextLinux_s390x::GetUserRegisterCount() const +{ + return m_user_register_count; +} + +size_t +RegisterContextLinux_s390x::GetGPRSize() const +{ + return 0; +} diff --git a/source/Plugins/Process/Utility/RegisterContextLinux_s390x.h b/source/Plugins/Process/Utility/RegisterContextLinux_s390x.h new file mode 100644 index 000000000000..bdc7f34f62e7 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextLinux_s390x.h @@ -0,0 +1,42 @@ +//===-- RegisterContextLinux_s390x.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_RegisterContextLinux_s390x_h_ +#define liblldb_RegisterContextLinux_s390x_h_ + +#include "RegisterInfoInterface.h" + +class RegisterContextLinux_s390x : public lldb_private::RegisterInfoInterface +{ +public: + RegisterContextLinux_s390x(const lldb_private::ArchSpec &target_arch); + + size_t + GetGPRSize() const override; + + const lldb_private::RegisterInfo * + GetRegisterInfo() const override; + + uint32_t + GetRegisterCount() const override; + + uint32_t + GetUserRegisterCount() const override; + + const std::vector * + 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 d_register_infos; +}; + +#endif diff --git a/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp new file mode 100644 index 000000000000..71ece160d4d4 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.cpp @@ -0,0 +1,357 @@ +//===-- RegisterContextNetBSD_x86_64.cpp ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// + +#include +#include + +#include "llvm/Support/Compiler.h" + +#include "RegisterContextPOSIX_x86.h" +#include "RegisterContextNetBSD_x86_64.h" + +using namespace lldb_private; +using namespace lldb; + +// src/sys/arch/amd64/include/frame_regs.h +typedef struct _GPR +{ + uint64_t rdi; /* 0 */ + uint64_t rsi; /* 1 */ + uint64_t rdx; /* 2 */ + uint64_t rcx; /* 3 */ + uint64_t r8; /* 4 */ + uint64_t r9; /* 5 */ + uint64_t r10; /* 6 */ + uint64_t r11; /* 7 */ + uint64_t r12; /* 8 */ + uint64_t r13; /* 9 */ + uint64_t r14; /* 10 */ + uint64_t r15; /* 11 */ + uint64_t rbp; /* 12 */ + uint64_t rbx; /* 13 */ + uint64_t rax; /* 14 */ + uint64_t gs; /* 15 */ + uint64_t fs; /* 16 */ + uint64_t es; /* 17 */ + uint64_t ds; /* 18 */ + uint64_t trapno; /* 19 */ + uint64_t err; /* 20 */ + uint64_t rip; /* 21 */ + uint64_t cs; /* 22 */ + uint64_t rflags; /* 23 */ + uint64_t rsp; /* 24 */ + uint64_t ss; /* 25 */ +} GPR; + +/* + * As of NetBSD-7.99.25 there is no support for debug registers + * https://en.wikipedia.org/wiki/X86_debug_register + */ + +/* + * src/sys/arch/amd64/include/mcontext.h + * + * typedef struct { + * __gregset_t __gregs; + * __greg_t _mc_tlsbase; + * __fpregset_t __fpregs; + * } mcontext_t; + */ + +struct UserArea { + GPR gpr; + uint64_t mc_tlsbase; + FPR fpr; +}; + + +//--------------------------------------------------------------------------- +// Cherry-pick parts of RegisterInfos_x86_64.h, without debug registers +//--------------------------------------------------------------------------- +// Computes the offset of the given GPR in the user data area. +#define GPR_OFFSET(regname) \ + (LLVM_EXTENSION offsetof(GPR, regname)) + +// Computes the offset of the given FPR in the extended data area. +#define FPR_OFFSET(regname) \ + (LLVM_EXTENSION offsetof(UserArea, fpr) + \ + LLVM_EXTENSION offsetof(FPR, xstate) + \ + LLVM_EXTENSION offsetof(FXSAVE, regname)) + +// Computes the offset of the YMM register assembled from register halves. +// Based on DNBArchImplX86_64.cpp from debugserver +#define YMM_OFFSET(reg_index) \ + (LLVM_EXTENSION offsetof(UserArea, fpr) + \ + LLVM_EXTENSION offsetof(FPR, xstate) + \ + LLVM_EXTENSION offsetof(XSAVE, ymmh[0]) + \ + (32 * reg_index)) + +// Number of bytes needed to represent a FPR. +#define FPR_SIZE(reg) sizeof(((FXSAVE*)NULL)->reg) + +// Number of bytes needed to represent the i'th FP register. +#define FP_SIZE sizeof(((MMSReg*)NULL)->bytes) + +// Number of bytes needed to represent an XMM register. +#define XMM_SIZE sizeof(XMMReg) + +// Number of bytes needed to represent a YMM register. +#define YMM_SIZE sizeof(YMMReg) + +// 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) \ + { #reg, alt, sizeof(((GPR*)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, { kind1, kind2, kind3, kind4, lldb_##reg##_x86_64 }, NULL, NULL } + +#define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \ + { #name, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, { kind1, kind2, kind3, kind4, lldb_##name##_x86_64 }, NULL, NULL } + +#define DEFINE_FP_ST(reg, i) \ + { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(stmm[i]), \ + eEncodingVector, eFormatVectorOfUInt8, \ + { 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, \ + { 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, \ + { 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, \ + { 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_GPR_PSEUDO_32(reg32, reg64) \ + { #reg32, NULL, 4, GPR_OFFSET(reg64), eEncodingUint, \ + eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg32##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } +#define DEFINE_GPR_PSEUDO_16(reg16, reg64) \ + { #reg16, NULL, 2, GPR_OFFSET(reg64), eEncodingUint, \ + eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg16##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } +#define DEFINE_GPR_PSEUDO_8H(reg8, reg64) \ + { #reg8, NULL, 1, GPR_OFFSET(reg64)+1, eEncodingUint, \ + eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg8##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } +#define DEFINE_GPR_PSEUDO_8L(reg8, reg64) \ + { #reg8, NULL, 1, GPR_OFFSET(reg64), eEncodingUint, \ + eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg8##_x86_64 }, RegisterContextPOSIX_x86::g_contained_##reg64, RegisterContextPOSIX_x86::g_invalidate_##reg64 } + +static RegisterInfo +g_register_infos_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), + DEFINE_GPR_PSEUDO_32(ecx, rcx), + DEFINE_GPR_PSEUDO_32(edx, rdx), + DEFINE_GPR_PSEUDO_32(edi, rdi), + DEFINE_GPR_PSEUDO_32(esi, rsi), + DEFINE_GPR_PSEUDO_32(ebp, rbp), + DEFINE_GPR_PSEUDO_32(esp, rsp), + DEFINE_GPR_PSEUDO_32(r8d, r8), + DEFINE_GPR_PSEUDO_32(r9d, r9), + DEFINE_GPR_PSEUDO_32(r10d, r10), + DEFINE_GPR_PSEUDO_32(r11d, r11), + DEFINE_GPR_PSEUDO_32(r12d, r12), + DEFINE_GPR_PSEUDO_32(r13d, r13), + DEFINE_GPR_PSEUDO_32(r14d, r14), + DEFINE_GPR_PSEUDO_32(r15d, r15), + DEFINE_GPR_PSEUDO_16(ax, rax), + DEFINE_GPR_PSEUDO_16(bx, rbx), + DEFINE_GPR_PSEUDO_16(cx, rcx), + DEFINE_GPR_PSEUDO_16(dx, rdx), + DEFINE_GPR_PSEUDO_16(di, rdi), + DEFINE_GPR_PSEUDO_16(si, rsi), + DEFINE_GPR_PSEUDO_16(bp, rbp), + DEFINE_GPR_PSEUDO_16(sp, rsp), + DEFINE_GPR_PSEUDO_16(r8w, r8), + DEFINE_GPR_PSEUDO_16(r9w, r9), + DEFINE_GPR_PSEUDO_16(r10w, r10), + DEFINE_GPR_PSEUDO_16(r11w, r11), + DEFINE_GPR_PSEUDO_16(r12w, r12), + DEFINE_GPR_PSEUDO_16(r13w, r13), + DEFINE_GPR_PSEUDO_16(r14w, r14), + DEFINE_GPR_PSEUDO_16(r15w, r15), + DEFINE_GPR_PSEUDO_8H(ah, rax), + DEFINE_GPR_PSEUDO_8H(bh, rbx), + DEFINE_GPR_PSEUDO_8H(ch, rcx), + DEFINE_GPR_PSEUDO_8H(dh, rdx), + DEFINE_GPR_PSEUDO_8L(al, rax), + DEFINE_GPR_PSEUDO_8L(bl, rbx), + DEFINE_GPR_PSEUDO_8L(cl, rcx), + DEFINE_GPR_PSEUDO_8L(dl, rdx), + DEFINE_GPR_PSEUDO_8L(dil, rdi), + DEFINE_GPR_PSEUDO_8L(sil, rsi), + DEFINE_GPR_PSEUDO_8L(bpl, rbp), + DEFINE_GPR_PSEUDO_8L(spl, rsp), + DEFINE_GPR_PSEUDO_8L(r8l, r8), + DEFINE_GPR_PSEUDO_8L(r9l, r9), + DEFINE_GPR_PSEUDO_8L(r10l, r10), + DEFINE_GPR_PSEUDO_8L(r11l, r11), + DEFINE_GPR_PSEUDO_8L(r12l, r12), + DEFINE_GPR_PSEUDO_8L(r13l, r13), + DEFINE_GPR_PSEUDO_8L(r14l, r14), + DEFINE_GPR_PSEUDO_8L(r15l, r15), + + // 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. + DEFINE_FP_ST(st, 0), + DEFINE_FP_ST(st, 1), + DEFINE_FP_ST(st, 2), + DEFINE_FP_ST(st, 3), + DEFINE_FP_ST(st, 4), + DEFINE_FP_ST(st, 5), + DEFINE_FP_ST(st, 6), + DEFINE_FP_ST(st, 7), + DEFINE_FP_MM(mm, 0), + DEFINE_FP_MM(mm, 1), + DEFINE_FP_MM(mm, 2), + DEFINE_FP_MM(mm, 3), + DEFINE_FP_MM(mm, 4), + DEFINE_FP_MM(mm, 5), + DEFINE_FP_MM(mm, 6), + DEFINE_FP_MM(mm, 7), + + // XMM registers + DEFINE_XMM(xmm, 0), + DEFINE_XMM(xmm, 1), + DEFINE_XMM(xmm, 2), + DEFINE_XMM(xmm, 3), + DEFINE_XMM(xmm, 4), + DEFINE_XMM(xmm, 5), + DEFINE_XMM(xmm, 6), + DEFINE_XMM(xmm, 7), + DEFINE_XMM(xmm, 8), + DEFINE_XMM(xmm, 9), + DEFINE_XMM(xmm, 10), + DEFINE_XMM(xmm, 11), + DEFINE_XMM(xmm, 12), + DEFINE_XMM(xmm, 13), + DEFINE_XMM(xmm, 14), + DEFINE_XMM(xmm, 15), + + // Copy of YMM registers assembled from xmm and ymmh + DEFINE_YMM(ymm, 0), + DEFINE_YMM(ymm, 1), + DEFINE_YMM(ymm, 2), + DEFINE_YMM(ymm, 3), + DEFINE_YMM(ymm, 4), + DEFINE_YMM(ymm, 5), + DEFINE_YMM(ymm, 6), + DEFINE_YMM(ymm, 7), + DEFINE_YMM(ymm, 8), + DEFINE_YMM(ymm, 9), + DEFINE_YMM(ymm, 10), + DEFINE_YMM(ymm, 11), + DEFINE_YMM(ymm, 12), + DEFINE_YMM(ymm, 13), + DEFINE_YMM(ymm, 14), + DEFINE_YMM(ymm, 15), +}; + +//--------------------------------------------------------------------------- +// End of cherry-pick of RegisterInfos_x86_64.h +//--------------------------------------------------------------------------- + +static const RegisterInfo * +PrivateGetRegisterInfoPtr (const lldb_private::ArchSpec& target_arch) +{ + switch (target_arch.GetMachine()) + { + case llvm::Triple::x86_64: + return g_register_infos_x86_64; + default: + assert(false && "Unhandled target architecture."); + return nullptr; + } +} + +static uint32_t +PrivateGetRegisterCount (const lldb_private::ArchSpec& target_arch) +{ + switch (target_arch.GetMachine()) + { + case llvm::Triple::x86_64: + return static_cast (sizeof (g_register_infos_x86_64) / sizeof (g_register_infos_x86_64 [0])); + default: + assert(false && "Unhandled target architecture."); + return 0; + } +} + +RegisterContextNetBSD_x86_64::RegisterContextNetBSD_x86_64(const ArchSpec &target_arch) : + lldb_private::RegisterInfoInterface(target_arch), + m_register_info_p (PrivateGetRegisterInfoPtr (target_arch)), + m_register_count (PrivateGetRegisterCount (target_arch)) +{ +} + +size_t +RegisterContextNetBSD_x86_64::GetGPRSize() const +{ + return sizeof(GPR); +} + +const RegisterInfo * +RegisterContextNetBSD_x86_64::GetRegisterInfo() const +{ + return m_register_info_p; +} + +uint32_t +RegisterContextNetBSD_x86_64::GetRegisterCount () const +{ + return m_register_count; +} diff --git a/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h b/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h new file mode 100644 index 000000000000..c267278c418c --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h @@ -0,0 +1,35 @@ +//===-- RegisterContextNetBSD_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_RegisterContextNetBSD_x86_64_H_ +#define liblldb_RegisterContextNetBSD_x86_64_H_ + +#include "RegisterInfoInterface.h" + +class RegisterContextNetBSD_x86_64: + public lldb_private::RegisterInfoInterface +{ +public: + RegisterContextNetBSD_x86_64(const lldb_private::ArchSpec &target_arch); + + size_t + GetGPRSize() const override; + + const lldb_private::RegisterInfo * + GetRegisterInfo() const override; + + uint32_t + GetRegisterCount () const override; + +private: + const lldb_private::RegisterInfo *m_register_info_p; + const uint32_t m_register_count; +}; + +#endif diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp new file mode 100644 index 000000000000..960be50c7be3 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp @@ -0,0 +1,265 @@ +//===-- RegisterContextPOSIX_x86.cpp ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include +#include +#include + +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/Scalar.h" +#include "lldb/Host/Endian.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "llvm/Support/Compiler.h" + +#include "RegisterContext_s390x.h" +#include "RegisterContextPOSIX_s390x.h" + +using namespace lldb_private; +using namespace lldb; + +// s390x 64-bit general purpose registers. +static const uint32_t g_gpr_regnums_s390x[] = +{ + lldb_r0_s390x, + lldb_r1_s390x, + lldb_r2_s390x, + lldb_r3_s390x, + lldb_r4_s390x, + lldb_r5_s390x, + lldb_r6_s390x, + lldb_r7_s390x, + lldb_r8_s390x, + lldb_r9_s390x, + lldb_r10_s390x, + lldb_r11_s390x, + lldb_r12_s390x, + lldb_r13_s390x, + lldb_r14_s390x, + lldb_r15_s390x, + lldb_acr0_s390x, + lldb_acr1_s390x, + lldb_acr2_s390x, + lldb_acr3_s390x, + lldb_acr4_s390x, + lldb_acr5_s390x, + lldb_acr6_s390x, + lldb_acr7_s390x, + lldb_acr8_s390x, + lldb_acr9_s390x, + lldb_acr10_s390x, + lldb_acr11_s390x, + lldb_acr12_s390x, + lldb_acr13_s390x, + lldb_acr14_s390x, + lldb_acr15_s390x, + lldb_pswm_s390x, + lldb_pswa_s390x, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_gpr_regnums_s390x) / sizeof(g_gpr_regnums_s390x[0])) - 1 == k_num_gpr_registers_s390x, + "g_gpr_regnums_s390x has wrong number of register infos"); + +// s390x 64-bit floating point registers. +static const uint32_t g_fpu_regnums_s390x[] = +{ + lldb_f0_s390x, + lldb_f1_s390x, + lldb_f2_s390x, + lldb_f3_s390x, + lldb_f4_s390x, + lldb_f5_s390x, + lldb_f6_s390x, + lldb_f7_s390x, + lldb_f8_s390x, + lldb_f9_s390x, + lldb_f10_s390x, + lldb_f11_s390x, + lldb_f12_s390x, + lldb_f13_s390x, + lldb_f14_s390x, + lldb_f15_s390x, + lldb_fpc_s390x, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_fpu_regnums_s390x) / sizeof(g_fpu_regnums_s390x[0])) - 1 == k_num_fpr_registers_s390x, + "g_fpu_regnums_s390x has wrong number of register infos"); + +// Number of register sets provided by this context. +enum +{ + k_num_register_sets = 2 +}; + +// Register sets for s390x 64-bit. +static const RegisterSet g_reg_sets_s390x[k_num_register_sets] = +{ + { "General Purpose Registers", "gpr", k_num_gpr_registers_s390x, g_gpr_regnums_s390x }, + { "Floating Point Registers", "fpr", k_num_fpr_registers_s390x, g_fpu_regnums_s390x }, +}; + +bool +RegisterContextPOSIX_s390x::IsGPR(unsigned reg) +{ + return reg <= m_reg_info.last_gpr; // GPRs come first. +} + +bool +RegisterContextPOSIX_s390x::IsFPR(unsigned reg) +{ + return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr); +} + +RegisterContextPOSIX_s390x::RegisterContextPOSIX_s390x(Thread &thread, uint32_t concrete_frame_idx, + RegisterInfoInterface *register_info) + : RegisterContext(thread, concrete_frame_idx) +{ + m_register_info_ap.reset(register_info); + + switch (register_info->m_target_arch.GetMachine()) + { + case llvm::Triple::systemz: + m_reg_info.num_registers = k_num_registers_s390x; + m_reg_info.num_gpr_registers = k_num_gpr_registers_s390x; + m_reg_info.num_fpr_registers = k_num_fpr_registers_s390x; + m_reg_info.last_gpr = k_last_gpr_s390x; + m_reg_info.first_fpr = k_first_fpr_s390x; + m_reg_info.last_fpr = k_last_fpr_s390x; + break; + default: + assert(false && "Unhandled target architecture."); + break; + } +} + +RegisterContextPOSIX_s390x::~RegisterContextPOSIX_s390x() +{ +} + +void +RegisterContextPOSIX_s390x::Invalidate() +{ +} + +void +RegisterContextPOSIX_s390x::InvalidateAllRegisters() +{ +} + +const RegisterInfo * +RegisterContextPOSIX_s390x::GetRegisterInfo() +{ + return m_register_info_ap->GetRegisterInfo(); +} + +const RegisterInfo * +RegisterContextPOSIX_s390x::GetRegisterInfoAtIndex(size_t reg) +{ + if (reg < m_reg_info.num_registers) + return &GetRegisterInfo()[reg]; + else + return NULL; +} + +size_t +RegisterContextPOSIX_s390x::GetRegisterCount() +{ + return m_reg_info.num_registers; +} + +unsigned +RegisterContextPOSIX_s390x::GetRegisterOffset(unsigned reg) +{ + assert(reg < m_reg_info.num_registers && "Invalid register number."); + return GetRegisterInfo()[reg].byte_offset; +} + +unsigned +RegisterContextPOSIX_s390x::GetRegisterSize(unsigned reg) +{ + assert(reg < m_reg_info.num_registers && "Invalid register number."); + return GetRegisterInfo()[reg].byte_size; +} + +const char * +RegisterContextPOSIX_s390x::GetRegisterName(unsigned reg) +{ + assert(reg < m_reg_info.num_registers && "Invalid register offset."); + return GetRegisterInfo()[reg].name; +} + +bool +RegisterContextPOSIX_s390x::IsRegisterSetAvailable(size_t set_index) +{ + return set_index < k_num_register_sets; +} + +size_t +RegisterContextPOSIX_s390x::GetRegisterSetCount() +{ + size_t sets = 0; + for (size_t set = 0; set < k_num_register_sets; ++set) + { + if (IsRegisterSetAvailable(set)) + ++sets; + } + + return sets; +} + +const RegisterSet * +RegisterContextPOSIX_s390x::GetRegisterSet(size_t set) +{ + if (IsRegisterSetAvailable(set)) + { + switch (m_register_info_ap->m_target_arch.GetMachine()) + { + case llvm::Triple::systemz: + return &g_reg_sets_s390x[set]; + default: + assert(false && "Unhandled target architecture."); + return NULL; + } + } + return NULL; +} + +lldb::ByteOrder +RegisterContextPOSIX_s390x::GetByteOrder() +{ + // Get the target process whose privileged thread was used for the register read. + lldb::ByteOrder byte_order = eByteOrderInvalid; + Process *process = CalculateProcess().get(); + + if (process) + byte_order = process->GetByteOrder(); + return byte_order; +} + +// Used when parsing DWARF and EH frame information and any other +// object file sections that contain register numbers in them. +uint32_t +RegisterContextPOSIX_s390x::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) +{ + const uint32_t num_regs = GetRegisterCount(); + + assert(kind < kNumRegisterKinds); + for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) + { + const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx); + + if (reg_info->kinds[kind] == num) + return reg_idx; + } + + return LLDB_INVALID_REGNUM; +} diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h new file mode 100644 index 000000000000..4904b2857c43 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h @@ -0,0 +1,103 @@ +//===-- RegisterContextPOSIX_s390x.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_RegisterContextPOSIX_s390x_h_ +#define liblldb_RegisterContextPOSIX_s390x_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 "RegisterContext_s390x.h" +#include "lldb-s390x-register-enums.h" + +class ProcessMonitor; + +class RegisterContextPOSIX_s390x : public lldb_private::RegisterContext +{ +public: + RegisterContextPOSIX_s390x(lldb_private::Thread &thread, uint32_t concrete_frame_idx, + lldb_private::RegisterInfoInterface *register_info); + + ~RegisterContextPOSIX_s390x() override; + + void + Invalidate(); + + void + InvalidateAllRegisters() override; + + size_t + GetRegisterCount() override; + + virtual unsigned + GetRegisterSize(unsigned reg); + + virtual unsigned + GetRegisterOffset(unsigned reg); + + const lldb_private::RegisterInfo * + GetRegisterInfoAtIndex(size_t reg) override; + + size_t + GetRegisterSetCount() override; + + const lldb_private::RegisterSet * + GetRegisterSet(size_t set) override; + + const char * + GetRegisterName(unsigned reg); + + uint32_t + ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override; + +protected: + struct RegInfo + { + uint32_t num_registers; + uint32_t num_gpr_registers; + uint32_t num_fpr_registers; + + uint32_t last_gpr; + uint32_t first_fpr; + uint32_t last_fpr; + }; + + RegInfo m_reg_info; + std::unique_ptr m_register_info_ap; + + virtual bool + IsRegisterSetAvailable(size_t set_index); + + virtual const lldb_private::RegisterInfo * + GetRegisterInfo(); + + bool + IsGPR(unsigned reg); + + bool + IsFPR(unsigned reg); + + lldb::ByteOrder + GetByteOrder(); + + virtual bool + ReadGPR() = 0; + virtual bool + ReadFPR() = 0; + virtual bool + WriteGPR() = 0; + virtual bool + WriteFPR() = 0; +}; + +#endif // liblldb_RegisterContextPOSIX_s390x_h_ diff --git a/source/Plugins/Process/Utility/RegisterContext_s390x.h b/source/Plugins/Process/Utility/RegisterContext_s390x.h new file mode 100644 index 000000000000..9777c7744409 --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterContext_s390x.h @@ -0,0 +1,93 @@ +//===-- RegisterContext_s390x.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_RegisterContext_s390x_h_ +#define liblldb_RegisterContext_s390x_h_ + +//--------------------------------------------------------------------------- +// SystemZ ehframe, dwarf regnums +//--------------------------------------------------------------------------- + +// EHFrame and DWARF Register numbers (eRegisterKindEHFrame & eRegisterKindDWARF) +enum +{ + // General Purpose Registers + dwarf_r0_s390x = 0, + dwarf_r1_s390x, + dwarf_r2_s390x, + dwarf_r3_s390x, + dwarf_r4_s390x, + dwarf_r5_s390x, + dwarf_r6_s390x, + dwarf_r7_s390x, + dwarf_r8_s390x, + dwarf_r9_s390x, + dwarf_r10_s390x, + dwarf_r11_s390x, + dwarf_r12_s390x, + dwarf_r13_s390x, + dwarf_r14_s390x, + dwarf_r15_s390x, + // Floating Point Registers / Vector Registers 0-15 + dwarf_f0_s390x = 16, + dwarf_f2_s390x, + dwarf_f4_s390x, + dwarf_f6_s390x, + dwarf_f1_s390x, + dwarf_f3_s390x, + dwarf_f5_s390x, + dwarf_f7_s390x, + dwarf_f8_s390x, + dwarf_f10_s390x, + dwarf_f12_s390x, + dwarf_f14_s390x, + dwarf_f9_s390x, + dwarf_f11_s390x, + dwarf_f13_s390x, + dwarf_f15_s390x, + // Access Registers + dwarf_acr0_s390x = 48, + dwarf_acr1_s390x, + dwarf_acr2_s390x, + dwarf_acr3_s390x, + dwarf_acr4_s390x, + dwarf_acr5_s390x, + dwarf_acr6_s390x, + dwarf_acr7_s390x, + dwarf_acr8_s390x, + dwarf_acr9_s390x, + dwarf_acr10_s390x, + dwarf_acr11_s390x, + dwarf_acr12_s390x, + dwarf_acr13_s390x, + dwarf_acr14_s390x, + dwarf_acr15_s390x, + // Program Status Word + dwarf_pswm_s390x = 64, + dwarf_pswa_s390x, + // Vector Registers 16-31 + dwarf_v16_s390x = 68, + dwarf_v18_s390x, + dwarf_v20_s390x, + dwarf_v22_s390x, + dwarf_v17_s390x, + dwarf_v19_s390x, + dwarf_v21_s390x, + dwarf_v23_s390x, + dwarf_v24_s390x, + dwarf_v26_s390x, + dwarf_v28_s390x, + dwarf_v30_s390x, + dwarf_v25_s390x, + dwarf_v27_s390x, + dwarf_v29_s390x, + dwarf_v31_s390x, +}; + +#endif diff --git a/source/Plugins/Process/Utility/RegisterInfos_mips.h b/source/Plugins/Process/Utility/RegisterInfos_mips.h index eef27f0208e0..3b81acf26146 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_mips.h +++ b/source/Plugins/Process/Utility/RegisterInfos_mips.h @@ -39,8 +39,12 @@ eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_mips }, NULL, NULL } #define DEFINE_FPR(reg, alt, kind1, kind2, kind3, kind4) \ - { #reg, alt, sizeof(((FPR_linux_mips*)NULL)->reg), FPR_OFFSET(reg), eEncodingUint, \ - eFormatHex, { kind1, kind2, kind3, kind4, fpr_##reg##_mips }, NULL, NULL } + { #reg, alt, sizeof(((FPR_linux_mips*)NULL)->reg), FPR_OFFSET(reg), eEncodingIEEE754, \ + eFormatFloat, { kind1, kind2, kind3, kind4, fpr_##reg##_mips }, NULL, NULL } + +#define DEFINE_FPR_INFO(reg, alt, kind1, kind2, kind3, kind4) \ + { #reg, alt, sizeof(((FPR_linux_mips*)NULL)->reg), FPR_OFFSET(reg), eEncodingUint, \ + eFormatHex, { kind1, kind2, kind3, kind4, fpr_##reg##_mips }, NULL, NULL } #define DEFINE_MSA(reg, alt, kind1, kind2, kind3, kind4) \ { #reg, alt, sizeof(((MSA_linux_mips*)0)->reg), MSA_OFFSET(reg), eEncodingVector, \ @@ -126,9 +130,9 @@ g_register_infos_mips[] = 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_FPR_INFO (fcsr, nullptr, dwarf_fcsr_mips, dwarf_fcsr_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR_INFO (fir, nullptr, dwarf_fir_mips, dwarf_fir_mips, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR_INFO (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), @@ -176,6 +180,7 @@ static_assert((sizeof(g_register_infos_mips) / sizeof(g_register_infos_mips[0])) #undef MSA_OFFSET #undef DEFINE_GPR #undef DEFINE_FPR +#undef DEFINE_FPR_INFO #undef DEFINE_MSA #undef DEFINE_MSA_INFO diff --git a/source/Plugins/Process/Utility/RegisterInfos_mips64.h b/source/Plugins/Process/Utility/RegisterInfos_mips64.h index 45853d7931dd..8dbfa6da94a2 100644 --- a/source/Plugins/Process/Utility/RegisterInfos_mips64.h +++ b/source/Plugins/Process/Utility/RegisterInfos_mips64.h @@ -56,6 +56,10 @@ eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg##_mips64 }, NULL, NULL } #define DEFINE_FPR(reg, alt, kind1, kind2, kind3, kind4) \ + { #reg, alt, sizeof(((FPR_linux_mips*)0)->reg), FPR_OFFSET(reg), eEncodingIEEE754, \ + eFormatFloat, { kind1, kind2, kind3, kind4, fpr_##reg##_mips64 }, NULL, NULL } + +#define DEFINE_FPR_INFO(reg, alt, kind1, kind2, kind3, kind4) \ { #reg, alt, sizeof(((FPR_linux_mips*)0)->reg), FPR_OFFSET(reg), eEncodingUint, \ eFormatHex, { kind1, kind2, kind3, kind4, fpr_##reg##_mips64 }, NULL, NULL } @@ -184,9 +188,9 @@ g_register_infos_mips64[] = 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_FPR_INFO (fcsr, nullptr, dwarf_fcsr_mips64, dwarf_fcsr_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR_INFO (fir, nullptr, dwarf_fir_mips64, dwarf_fir_mips64, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_FPR_INFO (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), @@ -233,6 +237,7 @@ static_assert((sizeof(g_register_infos_mips64) / sizeof(g_register_infos_mips64[ #undef DEFINE_GPR #undef DEFINE_GPR_INFO #undef DEFINE_FPR +#undef DEFINE_FPR_INFO #undef DEFINE_MSA #undef DEFINE_MSA_INFO #undef GPR_OFFSET diff --git a/source/Plugins/Process/Utility/RegisterInfos_s390x.h b/source/Plugins/Process/Utility/RegisterInfos_s390x.h new file mode 100644 index 000000000000..43152640297e --- /dev/null +++ b/source/Plugins/Process/Utility/RegisterInfos_s390x.h @@ -0,0 +1,132 @@ +//===-- RegisterInfos_s390x.h -----------------------------------*- 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 + +// C++ Includes +// Other libraries and framework includes +#include "llvm/Support/Compiler.h" + +// Project includes + +#ifdef DECLARE_REGISTER_INFOS_S390X_STRUCT + +// Computes the offset of the given GPR in the user data area. +#define GPR_OFFSET(num) (16 + 8 * num) +// Computes the offset of the given ACR in the user data area. +#define ACR_OFFSET(num) (16 + 8 * 16 + 4 * num) +// Computes the offset of the given FPR in the extended data area. +#define FPR_OFFSET(num) (8 + 8 * num) + +// RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB + +#define DEFINE_GPR(name, size, offset, alt, generic) \ + { \ + #name, alt, size, offset, eEncodingUint, eFormatHex, \ + { dwarf_##name##_s390x, dwarf_##name##_s390x, generic, LLDB_INVALID_REGNUM, lldb_##name##_s390x }, \ + NULL, NULL, \ + } + +#define DEFINE_GPR_NODWARF(name, size, offset, alt, generic) \ + { \ + #name, alt, size, offset, eEncodingUint, eFormatHex, \ + { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, generic, LLDB_INVALID_REGNUM, lldb_##name##_s390x }, \ + NULL, NULL, \ + } + +#define DEFINE_FPR(name, size, offset) \ + { \ + #name, NULL, size, offset, eEncodingUint, eFormatHex, \ + { dwarf_##name##_s390x, dwarf_##name##_s390x, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##name##_s390x }, \ + NULL, NULL, \ + } + +#define DEFINE_FPR_NODWARF(name, size, offset) \ + { \ + #name, NULL, size, offset, eEncodingUint, eFormatHex, \ + { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##name##_s390x }, \ + NULL, NULL, \ + } + +static RegisterInfo g_register_infos_s390x[] = +{ + // General purpose registers. + DEFINE_GPR(r0, 8, GPR_OFFSET(0), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(r1, 8, GPR_OFFSET(1), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(r2, 8, GPR_OFFSET(2), "arg1", LLDB_REGNUM_GENERIC_ARG1), + DEFINE_GPR(r3, 8, GPR_OFFSET(3), "arg2", LLDB_REGNUM_GENERIC_ARG2), + DEFINE_GPR(r4, 8, GPR_OFFSET(4), "arg3", LLDB_REGNUM_GENERIC_ARG3), + DEFINE_GPR(r5, 8, GPR_OFFSET(5), "arg4", LLDB_REGNUM_GENERIC_ARG4), + DEFINE_GPR(r6, 8, GPR_OFFSET(6), "arg5", LLDB_REGNUM_GENERIC_ARG5), + DEFINE_GPR(r7, 8, GPR_OFFSET(7), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(r8, 8, GPR_OFFSET(8), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(r9, 8, GPR_OFFSET(9), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(r10, 8, GPR_OFFSET(10), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(r11, 8, GPR_OFFSET(11), "fp", LLDB_REGNUM_GENERIC_FP), + DEFINE_GPR(r12, 8, GPR_OFFSET(12), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(r13, 8, GPR_OFFSET(13), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(r14, 8, GPR_OFFSET(14), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(r15, 8, GPR_OFFSET(15), "sp", LLDB_REGNUM_GENERIC_SP), + DEFINE_GPR(acr0, 4, ACR_OFFSET(0), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(acr1, 4, ACR_OFFSET(1), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(acr2, 4, ACR_OFFSET(2), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(acr3, 4, ACR_OFFSET(3), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(acr4, 4, ACR_OFFSET(4), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(acr5, 4, ACR_OFFSET(5), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(acr6, 4, ACR_OFFSET(6), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(acr7, 4, ACR_OFFSET(7), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(acr8, 4, ACR_OFFSET(8), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(acr9, 4, ACR_OFFSET(9), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(acr10, 4, ACR_OFFSET(10), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(acr11, 4, ACR_OFFSET(11), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(acr12, 4, ACR_OFFSET(12), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(acr13, 4, ACR_OFFSET(13), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(acr14, 4, ACR_OFFSET(14), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(acr15, 4, ACR_OFFSET(15), nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR(pswm, 8, 0, "flags", LLDB_REGNUM_GENERIC_FLAGS), + DEFINE_GPR(pswa, 8, 8, "pc", LLDB_REGNUM_GENERIC_PC), + + // Floating point registers. + DEFINE_FPR(f0, 8, FPR_OFFSET(0)), + DEFINE_FPR(f1, 8, FPR_OFFSET(1)), + DEFINE_FPR(f2, 8, FPR_OFFSET(2)), + DEFINE_FPR(f3, 8, FPR_OFFSET(3)), + DEFINE_FPR(f4, 8, FPR_OFFSET(4)), + DEFINE_FPR(f5, 8, FPR_OFFSET(5)), + DEFINE_FPR(f6, 8, FPR_OFFSET(6)), + DEFINE_FPR(f7, 8, FPR_OFFSET(7)), + DEFINE_FPR(f8, 8, FPR_OFFSET(8)), + DEFINE_FPR(f9, 8, FPR_OFFSET(9)), + DEFINE_FPR(f10, 8, FPR_OFFSET(10)), + DEFINE_FPR(f11, 8, FPR_OFFSET(11)), + DEFINE_FPR(f12, 8, FPR_OFFSET(12)), + DEFINE_FPR(f13, 8, FPR_OFFSET(13)), + DEFINE_FPR(f14, 8, FPR_OFFSET(14)), + DEFINE_FPR(f15, 8, FPR_OFFSET(15)), + DEFINE_FPR_NODWARF(fpc, 4, 0), + + // Linux operating-specific info. + DEFINE_GPR_NODWARF(orig_r2, 8, 16 + 16 * 8 + 16 * 4, nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR_NODWARF(last_break, 8, 0, nullptr, LLDB_INVALID_REGNUM), + DEFINE_GPR_NODWARF(system_call, 4, 0, nullptr, LLDB_INVALID_REGNUM), +}; + +static_assert((sizeof(g_register_infos_s390x) / sizeof(g_register_infos_s390x[0])) == k_num_registers_s390x, + "g_register_infos_s390x has wrong number of register infos"); + +#undef GPR_OFFSET +#undef ACR_OFFSET +#undef FPR_OFFSET +#undef DEFINE_GPR +#undef DEFINE_GPR_NODWARF +#undef DEFINE_FPR +#undef DEFINE_FPR_NODWARF + +#endif // DECLARE_REGISTER_INFOS_S390X_STRUCT diff --git a/source/Plugins/Process/Utility/StopInfoMachException.cpp b/source/Plugins/Process/Utility/StopInfoMachException.cpp index 3bf766e875c9..7c0487b1d43b 100644 --- a/source/Plugins/Process/Utility/StopInfoMachException.cpp +++ b/source/Plugins/Process/Utility/StopInfoMachException.cpp @@ -507,6 +507,8 @@ StopInfoMachException::CreateStopReasonWithMachException // report the breakpoint regardless of the thread. if (bp_site_sp->ValidForThisThread (&thread) || thread.GetProcess()->GetOperatingSystem () != NULL) return StopInfo::CreateStopReasonWithBreakpointSiteID (thread, bp_site_sp->GetID()); + else if (is_trace_if_actual_breakpoint_missing) + return StopInfo::CreateStopReasonToTrace (thread); else return StopInfoSP(); } diff --git a/source/Plugins/Process/Utility/lldb-s390x-register-enums.h b/source/Plugins/Process/Utility/lldb-s390x-register-enums.h new file mode 100644 index 000000000000..174daa25e21b --- /dev/null +++ b/source/Plugins/Process/Utility/lldb-s390x-register-enums.h @@ -0,0 +1,94 @@ +//===-- lldb-s390x-register-enums.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_s390x_register_enums_h +#define lldb_s390x_register_enums_h + +namespace lldb_private +{ +// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) + +//--------------------------------------------------------------------------- +// Internal codes for all s390x registers. +//--------------------------------------------------------------------------- +enum +{ + k_first_gpr_s390x, + lldb_r0_s390x = k_first_gpr_s390x, + lldb_r1_s390x, + lldb_r2_s390x, + lldb_r3_s390x, + lldb_r4_s390x, + lldb_r5_s390x, + lldb_r6_s390x, + lldb_r7_s390x, + lldb_r8_s390x, + lldb_r9_s390x, + lldb_r10_s390x, + lldb_r11_s390x, + lldb_r12_s390x, + lldb_r13_s390x, + lldb_r14_s390x, + lldb_r15_s390x, + lldb_acr0_s390x, + lldb_acr1_s390x, + lldb_acr2_s390x, + lldb_acr3_s390x, + lldb_acr4_s390x, + lldb_acr5_s390x, + lldb_acr6_s390x, + lldb_acr7_s390x, + lldb_acr8_s390x, + lldb_acr9_s390x, + lldb_acr10_s390x, + lldb_acr11_s390x, + lldb_acr12_s390x, + lldb_acr13_s390x, + lldb_acr14_s390x, + lldb_acr15_s390x, + lldb_pswm_s390x, + lldb_pswa_s390x, + k_last_gpr_s390x = lldb_pswa_s390x, + + k_first_fpr_s390x, + lldb_f0_s390x = k_first_fpr_s390x, + lldb_f1_s390x, + lldb_f2_s390x, + lldb_f3_s390x, + lldb_f4_s390x, + lldb_f5_s390x, + lldb_f6_s390x, + lldb_f7_s390x, + lldb_f8_s390x, + lldb_f9_s390x, + lldb_f10_s390x, + lldb_f11_s390x, + lldb_f12_s390x, + lldb_f13_s390x, + lldb_f14_s390x, + lldb_f15_s390x, + lldb_fpc_s390x, + k_last_fpr_s390x = lldb_fpc_s390x, + + // These are only available on Linux. + k_first_linux_s390x, + lldb_orig_r2_s390x = k_first_linux_s390x, + lldb_last_break_s390x, + lldb_system_call_s390x, + k_last_linux_s390x = lldb_system_call_s390x, + + k_num_registers_s390x, + k_num_gpr_registers_s390x = k_last_gpr_s390x - k_first_gpr_s390x + 1, + k_num_fpr_registers_s390x = k_last_fpr_s390x - k_first_fpr_s390x + 1, + k_num_linux_registers_s390x = k_last_linux_s390x - k_first_linux_s390x + 1, + k_num_user_registers_s390x = k_num_gpr_registers_s390x + k_num_fpr_registers_s390x, +}; +} + +#endif // #ifndef lldb_s390x_register_enums_h diff --git a/source/Plugins/Process/Windows/Common/NtStructures.h b/source/Plugins/Process/Windows/Common/NtStructures.h new file mode 100644 index 000000000000..6c688d9068d5 --- /dev/null +++ b/source/Plugins/Process/Windows/Common/NtStructures.h @@ -0,0 +1,32 @@ +//===-- NtStructures.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_Plugins_Process_Windows_Common_NtStructures_h_ +#define liblldb_Plugins_Process_Windows_Common_NtStructures_h_ + +#include "lldb/Host/windows/windows.h" + +// This describes the layout of a TEB (Thread Environment Block) for a 64-bit +// process. It's adapted from the 32-bit TEB in winternl.h. Currently, we care +// only about the position of the TlsSlots. +struct TEB64 +{ + ULONG64 Reserved1[12]; + ULONG64 ProcessEnvironmentBlock; + ULONG64 Reserved2[399]; + BYTE Reserved3[1952]; + ULONG64 TlsSlots[64]; + BYTE Reserved4[8]; + ULONG64 Reserved5[26]; + ULONG64 ReservedForOle; // Windows 2000 only + ULONG64 Reserved6[4]; + ULONG64 TlsExpansionSlots; +}; + +#endif diff --git a/source/Plugins/Process/Windows/Common/ProcessWindows.cpp b/source/Plugins/Process/Windows/Common/ProcessWindows.cpp index 0e6900d8fb7f..2c3f9fbecf92 100644 --- a/source/Plugins/Process/Windows/Common/ProcessWindows.cpp +++ b/source/Plugins/Process/Windows/Common/ProcessWindows.cpp @@ -29,8 +29,8 @@ namespace lldb_private //------------------------------------------------------------------------------ // Constructors and destructors. -ProcessWindows::ProcessWindows(lldb::TargetSP target_sp, Listener &listener) - : lldb_private::Process(target_sp, listener) +ProcessWindows::ProcessWindows(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp) + : lldb_private::Process(target_sp, listener_sp) { } diff --git a/source/Plugins/Process/Windows/Common/ProcessWindows.h b/source/Plugins/Process/Windows/Common/ProcessWindows.h index 2a437c0ca909..0ee42e2ae1f1 100644 --- a/source/Plugins/Process/Windows/Common/ProcessWindows.h +++ b/source/Plugins/Process/Windows/Common/ProcessWindows.h @@ -25,7 +25,7 @@ public: // Constructors and destructors //------------------------------------------------------------------ ProcessWindows(lldb::TargetSP target_sp, - lldb_private::Listener &listener); + lldb::ListenerSP listener_sp); ~ProcessWindows(); diff --git a/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp b/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp index 103cff4a2a56..3a9c31a0b776 100644 --- a/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp +++ b/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp @@ -136,6 +136,8 @@ RegisterInfo g_register_infos[] = { nullptr}, }; +static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos); + // Array of lldb register numbers used to define the set of all General Purpose Registers uint32_t g_gpr_reg_indices[] = {eRegisterIndexRax, eRegisterIndexRbx, eRegisterIndexRcx, eRegisterIndexRdx, eRegisterIndexRdi, eRegisterIndexRsi, eRegisterIndexR8, eRegisterIndexR9, @@ -169,7 +171,9 @@ RegisterContextWindows_x64::GetRegisterCount() const RegisterInfo * RegisterContextWindows_x64::GetRegisterInfoAtIndex(size_t reg) { - return &g_register_infos[reg]; + if (reg < k_num_register_infos) + return &g_register_infos[reg]; + return NULL; } size_t diff --git a/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp b/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp index e57e1effec9c..11733eee7cb4 100644 --- a/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp +++ b/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp @@ -64,6 +64,7 @@ RegisterInfo g_register_infos[] = { DEFINE_GPR(eip, "pc"), { ehframe_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, lldb_eip_i386 }, nullptr, nullptr}, { DEFINE_GPR_BIN(eflags, "flags"), { ehframe_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, lldb_eflags_i386}, nullptr, nullptr}, }; +static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos); // Array of lldb register numbers used to define the set of all General Purpose Registers uint32_t g_gpr_reg_indices[] = @@ -106,7 +107,9 @@ RegisterContextWindows_x86::GetRegisterCount() const RegisterInfo * RegisterContextWindows_x86::GetRegisterInfoAtIndex(size_t reg) { - return &g_register_infos[reg]; + if (reg < k_num_register_infos) + return &g_register_infos[reg]; + return NULL; } size_t @@ -131,48 +134,42 @@ RegisterContextWindows_x86::ReadRegister(const RegisterInfo *reg_info, RegisterV switch (reg) { case lldb_eax_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from EAX", m_context.Eax); - reg_value.SetUInt32(m_context.Eax); - break; + return ReadRegisterHelper(CONTEXT_INTEGER, "EAX", m_context.Eax, reg_value); case lldb_ebx_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from EBX", m_context.Ebx); - reg_value.SetUInt32(m_context.Ebx); - break; + return ReadRegisterHelper(CONTEXT_INTEGER, "EBX", m_context.Ebx, reg_value); case lldb_ecx_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from ECX", m_context.Ecx); - reg_value.SetUInt32(m_context.Ecx); - break; + return ReadRegisterHelper(CONTEXT_INTEGER, "ECX", m_context.Ecx, reg_value); case lldb_edx_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from EDX", m_context.Edx); - reg_value.SetUInt32(m_context.Edx); - break; + return ReadRegisterHelper(CONTEXT_INTEGER, "EDX", m_context.Edx, reg_value); case lldb_edi_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from EDI", m_context.Edi); - reg_value.SetUInt32(m_context.Edi); - break; + return ReadRegisterHelper(CONTEXT_INTEGER, "EDI", m_context.Edi, reg_value); case lldb_esi_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from ESI", m_context.Esi); - reg_value.SetUInt32(m_context.Esi); - break; + return ReadRegisterHelper(CONTEXT_INTEGER, "ESI", m_context.Esi, reg_value); case lldb_ebp_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from EBP", m_context.Ebp); - reg_value.SetUInt32(m_context.Ebp); - break; + return ReadRegisterHelper(CONTEXT_CONTROL, "EBP", m_context.Ebp, reg_value); case lldb_esp_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from ESP", m_context.Esp); - reg_value.SetUInt32(m_context.Esp); - break; + return ReadRegisterHelper(CONTEXT_CONTROL, "ESP", m_context.Esp, reg_value); case lldb_eip_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from EIP", m_context.Eip); - reg_value.SetUInt32(m_context.Eip); - break; + return ReadRegisterHelper(CONTEXT_CONTROL, "EIP", m_context.Eip, reg_value); case lldb_eflags_i386: - WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from EFLAGS", m_context.EFlags); - reg_value.SetUInt32(m_context.EFlags); - break; + return ReadRegisterHelper(CONTEXT_CONTROL, "EFLAGS", m_context.EFlags, reg_value); default: WINWARN_IFALL(WINDOWS_LOG_REGISTERS, "Requested unknown register %u", reg); break; } + return false; +} + +bool +RegisterContextWindows_x86::ReadRegisterHelper(DWORD flags_required, const char *reg_name, DWORD value, + RegisterValue ®_value) const +{ + if ((m_context.ContextFlags & flags_required) != flags_required) + { + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Thread context doesn't have %s", reg_name); + return false; + } + WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Read value 0x%x from %s", value, reg_name); + reg_value.SetUInt32(value); return true; } diff --git a/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h b/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h index 7d854ef64a5c..6c29d54dcae2 100644 --- a/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h +++ b/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h @@ -41,6 +41,9 @@ class RegisterContextWindows_x86 : public RegisterContextWindows bool ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) override; +private: + bool + ReadRegisterHelper(DWORD flags_required, const char *reg_name, DWORD value, RegisterValue ®_value) const; }; } diff --git a/source/Plugins/Process/Windows/Live/DebuggerThread.cpp b/source/Plugins/Process/Windows/Live/DebuggerThread.cpp index d058a412c896..2823474cbd5e 100644 --- a/source/Plugins/Process/Windows/Live/DebuggerThread.cpp +++ b/source/Plugins/Process/Windows/Live/DebuggerThread.cpp @@ -27,6 +27,7 @@ #include "Plugins/Process/Windows/Common/ProcessWindowsLog.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/ConvertUTF.h" #include "llvm/Support/raw_ostream.h" using namespace lldb; @@ -378,7 +379,7 @@ DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, DWORD thr { WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_PROCESS, "Breakpoint exception is cue to detach from process 0x%x", - m_pid_to_detach); + m_pid_to_detach.load()); ::DebugActiveProcessStop(m_pid_to_detach); m_detached = true; } @@ -484,13 +485,15 @@ DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread return DBG_CONTINUE; } - std::vector buffer(1); - DWORD required_size = GetFinalPathNameByHandle(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS); + std::vector buffer(1); + DWORD required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS); if (required_size > 0) { buffer.resize(required_size + 1); - required_size = GetFinalPathNameByHandle(info.hFile, &buffer[0], required_size + 1, VOLUME_NAME_DOS); - llvm::StringRef path_str(&buffer[0]); + required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0], required_size, VOLUME_NAME_DOS); + std::string path_str_utf8; + llvm::convertWideToUTF8(buffer.data(), path_str_utf8); + llvm::StringRef path_str = path_str_utf8; const char *path = path_str.data(); if (path_str.startswith("\\\\?\\")) path += 4; diff --git a/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp b/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp index 855289d67bc7..300e0caa4378 100644 --- a/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp +++ b/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp @@ -47,6 +47,7 @@ #include "ProcessWindowsLive.h" #include "TargetThreadWindowsLive.h" +#include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" @@ -61,17 +62,19 @@ namespace std::string GetProcessExecutableName(HANDLE process_handle) { - std::vector file_name; + std::vector file_name; DWORD file_name_size = MAX_PATH; // first guess, not an absolute limit DWORD copied = 0; do { file_name_size *= 2; file_name.resize(file_name_size); - copied = ::GetModuleFileNameEx(process_handle, NULL, file_name.data(), file_name_size); + copied = ::GetModuleFileNameExW(process_handle, NULL, file_name.data(), file_name_size); } while (copied >= file_name_size); file_name.resize(copied); - return std::string(file_name.begin(), file_name.end()); + std::string result; + llvm::convertWideToUTF8(file_name.data(), result); + return result; } std::string @@ -121,9 +124,9 @@ class ProcessWindowsData // Static functions. ProcessSP -ProcessWindowsLive::CreateInstance(lldb::TargetSP target_sp, Listener &listener, const FileSpec *) +ProcessWindowsLive::CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec *) { - return ProcessSP(new ProcessWindowsLive(target_sp, listener)); + return ProcessSP(new ProcessWindowsLive(target_sp, listener_sp)); } void @@ -142,8 +145,8 @@ ProcessWindowsLive::Initialize() //------------------------------------------------------------------------------ // Constructors and destructors. -ProcessWindowsLive::ProcessWindowsLive(lldb::TargetSP target_sp, Listener &listener) - : lldb_private::ProcessWindows(target_sp, listener) +ProcessWindowsLive::ProcessWindowsLive(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp) + : lldb_private::ProcessWindows(target_sp, listener_sp) { } @@ -189,7 +192,7 @@ ProcessWindowsLive::DisableBreakpointSite(BreakpointSite *bp_site) { WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS, "DisableBreakpointSite called with bp_site 0x%p " "(id=%d, addr=0x%x)", - bp_site->GetID(), bp_site->GetLoadAddress()); + bp_site, bp_site->GetID(), bp_site->GetLoadAddress()); Error error = DisableSoftwareBreakpoint(bp_site); @@ -554,11 +557,25 @@ ProcessWindowsLive::RefreshStateAfterStop() { case EXCEPTION_SINGLE_STEP: { - stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread); - stop_thread->SetStopInfo(stop_info); - WINLOG_IFANY(WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_STEP, "RefreshStateAfterStop single stepping thread %u", - stop_thread->GetID()); - stop_thread->SetStopInfo(stop_info); + RegisterContextSP register_context = stop_thread->GetRegisterContext(); + const uint64_t pc = register_context->GetPC(); + BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc)); + if (site && site->ValidForThisThread(stop_thread.get())) + { + WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_STEP, + "Single-stepped onto a breakpoint in process %I64u at " + "address 0x%I64x with breakpoint site %d", + m_session_data->m_debugger->GetProcess().GetProcessId(), pc, site->GetID()); + stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread, site->GetID()); + stop_thread->SetStopInfo(stop_info); + } + else + { + WINLOG_IFANY(WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_STEP, + "RefreshStateAfterStop single stepping thread %u", stop_thread->GetID()); + stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread); + stop_thread->SetStopInfo(stop_info); + } return; } @@ -731,6 +748,7 @@ ProcessWindowsLive::GetMemoryRegionInfo(lldb::addr_t vm_addr, MemoryRegionInfo & { Error error; llvm::sys::ScopedLock lock(m_mutex); + info.Clear(); if (!m_session_data) { @@ -738,7 +756,6 @@ ProcessWindowsLive::GetMemoryRegionInfo(lldb::addr_t vm_addr, MemoryRegionInfo & WINERR_IFALL(WINDOWS_LOG_MEMORY, error.AsCString()); return error; } - HostProcess process = m_session_data->m_debugger->GetProcess(); lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); if (handle == nullptr || handle == LLDB_INVALID_PROCESS) @@ -755,22 +772,67 @@ ProcessWindowsLive::GetMemoryRegionInfo(lldb::addr_t vm_addr, MemoryRegionInfo & SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info)); if (result == 0) { - error.SetError(::GetLastError(), eErrorTypeWin32); - WINERR_IFALL(WINDOWS_LOG_MEMORY, - "VirtualQueryEx returned error %u while getting memory region info for address 0x%I64x", - error.GetError(), vm_addr); - return error; + if (::GetLastError() == ERROR_INVALID_PARAMETER) + { + // ERROR_INVALID_PARAMETER is returned if VirtualQueryEx is called with an address + // past the highest accessible address. We should return a range from the vm_addr + // to LLDB_INVALID_ADDRESS + info.GetRange().SetRangeBase(vm_addr); + info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); + info.SetReadable(MemoryRegionInfo::eNo); + info.SetExecutable(MemoryRegionInfo::eNo); + info.SetWritable(MemoryRegionInfo::eNo); + info.SetMapped(MemoryRegionInfo::eNo); + return error; + } + else + { + error.SetError(::GetLastError(), eErrorTypeWin32); + WINERR_IFALL(WINDOWS_LOG_MEMORY, + "VirtualQueryEx returned error %u while getting memory region info for address 0x%I64x", + error.GetError(), vm_addr); + return error; + } + } + + // Protect bits are only valid for MEM_COMMIT regions. + if (mem_info.State == MEM_COMMIT) { + const bool readable = IsPageReadable(mem_info.Protect); + const bool executable = IsPageExecutable(mem_info.Protect); + const bool writable = IsPageWritable(mem_info.Protect); + info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); + info.SetExecutable(executable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); + info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); + } + else + { + info.SetReadable(MemoryRegionInfo::eNo); + info.SetExecutable(MemoryRegionInfo::eNo); + info.SetWritable(MemoryRegionInfo::eNo); + } + + // AllocationBase is defined for MEM_COMMIT and MEM_RESERVE but not MEM_FREE. + if (mem_info.State != MEM_FREE) { + info.GetRange().SetRangeBase(reinterpret_cast(mem_info.AllocationBase)); + info.GetRange().SetRangeEnd(reinterpret_cast(mem_info.BaseAddress) + mem_info.RegionSize); + info.SetMapped(MemoryRegionInfo::eYes); + } + else + { + // In the unmapped case we need to return the distance to the next block of memory. + // VirtualQueryEx nearly does that except that it gives the distance from the start + // of the page containing vm_addr. + SYSTEM_INFO data; + GetSystemInfo(&data); + DWORD page_offset = vm_addr % data.dwPageSize; + info.GetRange().SetRangeBase(vm_addr); + info.GetRange().SetByteSize(mem_info.RegionSize - page_offset); + info.SetMapped(MemoryRegionInfo::eNo); } - const bool readable = IsPageReadable(mem_info.Protect); - const bool executable = IsPageExecutable(mem_info.Protect); - const bool writable = IsPageWritable(mem_info.Protect); - info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - info.SetExecutable(executable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); error.SetError(::GetLastError(), eErrorTypeWin32); WINLOGV_IFALL(WINDOWS_LOG_MEMORY, "Memory region info for address 0x%I64u: readable=%s, executable=%s, writable=%s", - BOOL_STR(readable), BOOL_STR(executable), BOOL_STR(writable)); + BOOL_STR(info.GetReadable()), BOOL_STR(info.GetExecutable()), BOOL_STR(info.GetWritable())); return error; } @@ -803,7 +865,7 @@ ProcessWindowsLive::OnExitProcess(uint32_t exit_code) target->ModulesDidUnload(unloaded_modules, true); } - SetProcessExitStatus(nullptr, GetID(), true, 0, exit_code); + SetProcessExitStatus(GetID(), true, 0, exit_code); SetPrivateState(eStateExited); } diff --git a/source/Plugins/Process/Windows/Live/ProcessWindowsLive.h b/source/Plugins/Process/Windows/Live/ProcessWindowsLive.h index 2429f873c823..657877f529b2 100644 --- a/source/Plugins/Process/Windows/Live/ProcessWindowsLive.h +++ b/source/Plugins/Process/Windows/Live/ProcessWindowsLive.h @@ -43,7 +43,7 @@ public: //------------------------------------------------------------------ static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp, - lldb_private::Listener &listener, + lldb::ListenerSP listener_sp, const lldb_private::FileSpec *); static void @@ -62,7 +62,7 @@ public: // Constructors and destructors //------------------------------------------------------------------ ProcessWindowsLive(lldb::TargetSP target_sp, - lldb_private::Listener &listener); + lldb::ListenerSP listener_sp); ~ProcessWindowsLive(); diff --git a/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp b/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp index fbc96f085ed4..05839667688f 100644 --- a/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp +++ b/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp @@ -35,137 +35,131 @@ #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" +#include "Plugins/Process/Windows/Common/NtStructures.h" +#include "Plugins/Process/Windows/Common/ProcessWindowsLog.h" + #include "ExceptionRecord.h" #include "ThreadWinMiniDump.h" using namespace lldb_private; -namespace +// Implementation class for ProcessWinMiniDump encapsulates the Windows-specific +// code, keeping non-portable types out of the header files. +// TODO(amccarth): Determine if we need a mutex for access. Given that this is +// postmortem debugging, I don't think so. +class ProcessWinMiniDump::Impl { +public: + Impl(const FileSpec &core_file, ProcessWinMiniDump *self); + ~Impl(); -// Getting a string out of a mini dump is a chore. You're usually given a -// relative virtual address (RVA), which points to a counted string that's in -// Windows Unicode (UTF-16). This wrapper handles all the redirection and -// returns a UTF-8 copy of the string. -std::string -GetMiniDumpString(const void *base_addr, const RVA rva) -{ - std::string result; - if (!base_addr) + Error + DoLoadCore(); + + bool + UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list); + + void + RefreshStateAfterStop(); + + size_t + DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error); + + Error + GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &info); + +private: + // Describes a range of memory captured in the mini dump. + struct Range { - return result; - } - auto md_string = reinterpret_cast(static_cast(base_addr) + rva); - auto source_start = reinterpret_cast(md_string->Buffer); - const auto source_length = ::wcslen(md_string->Buffer); - const auto source_end = source_start + source_length; - result.resize(4*source_length); // worst case length - auto result_start = reinterpret_cast(&result[0]); - const auto result_end = result_start + result.size(); - ConvertUTF16toUTF8(&source_start, source_end, &result_start, result_end, strictConversion); - const auto result_size = std::distance(reinterpret_cast(&result[0]), result_start); - result.resize(result_size); // shrink to actual length - return result; -} + lldb::addr_t start; // virtual address of the beginning of the range + size_t size; // size of the range in bytes + const uint8_t *ptr; // absolute pointer to the first byte of the range + }; -} // anonymous namespace + // If the mini dump has a memory range that contains the desired address, it + // returns true with the details of the range in *range_out. Otherwise, it + // returns false. + bool + FindMemoryRange(lldb::addr_t addr, Range *range_out) const; -// Encapsulates the private data for ProcessWinMiniDump. -// TODO(amccarth): Determine if we need a mutex for access. -class ProcessWinMiniDump::Data -{ -public: - Data(); - ~Data(); + lldb_private::Error + MapMiniDumpIntoMemory(); + lldb_private::ArchSpec + DetermineArchitecture(); + + void + ReadExceptionRecord(); + + void + ReadMiscInfo(); + + void + ReadModuleList(); + + // A thin wrapper around WinAPI's MiniDumpReadDumpStream to avoid redundant + // checks. If there's a failure (e.g., if the requested stream doesn't exist), + // the function returns nullptr and sets *size_out to 0. + void * + FindDumpStream(unsigned stream_number, size_t *size_out) const; + + // Getting a string out of a mini dump is a chore. You're usually given a + // relative virtual address (RVA), which points to a counted string that's in + // Windows Unicode (UTF-16). This wrapper handles all the redirection and + // returns a UTF-8 copy of the string. + std::string + GetMiniDumpString(RVA rva) const; + + ProcessWinMiniDump *m_self; // non-owning back pointer FileSpec m_core_file; HANDLE m_dump_file; // handle to the open minidump file HANDLE m_mapping; // handle to the file mapping for the minidump file void * m_base_addr; // base memory address of the minidump std::shared_ptr m_exception_sp; + bool m_is_wow64; // minidump is of a 32-bit process captured with a 64-bit debugger }; -ConstString -ProcessWinMiniDump::GetPluginNameStatic() +ProcessWinMiniDump::Impl::Impl(const FileSpec &core_file, ProcessWinMiniDump *self) + : m_self(self), + m_core_file(core_file), + m_dump_file(INVALID_HANDLE_VALUE), + m_mapping(NULL), + m_base_addr(nullptr), + m_exception_sp(), + m_is_wow64(false) { - static ConstString g_name("win-minidump"); - return g_name; } -const char * -ProcessWinMiniDump::GetPluginDescriptionStatic() +ProcessWinMiniDump::Impl::~Impl() { - return "Windows minidump plug-in."; -} - -void -ProcessWinMiniDump::Terminate() -{ - PluginManager::UnregisterPlugin(ProcessWinMiniDump::CreateInstance); -} - - -lldb::ProcessSP -ProcessWinMiniDump::CreateInstance(lldb::TargetSP target_sp, Listener &listener, const FileSpec *crash_file) -{ - lldb::ProcessSP process_sp; - if (crash_file) + if (m_base_addr) { - process_sp.reset(new ProcessWinMiniDump(target_sp, listener, *crash_file)); + ::UnmapViewOfFile(m_base_addr); + m_base_addr = nullptr; + } + if (m_mapping) + { + ::CloseHandle(m_mapping); + m_mapping = NULL; + } + if (m_dump_file != INVALID_HANDLE_VALUE) + { + ::CloseHandle(m_dump_file); + m_dump_file = INVALID_HANDLE_VALUE; } - return process_sp; -} - -bool -ProcessWinMiniDump::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) -{ - // TODO(amccarth): Eventually, this needs some actual logic. - return true; -} - -ProcessWinMiniDump::ProcessWinMiniDump(lldb::TargetSP target_sp, Listener &listener, - const FileSpec &core_file) : - ProcessWindows(target_sp, listener), - m_data_up(new Data) -{ - m_data_up->m_core_file = core_file; -} - -ProcessWinMiniDump::~ProcessWinMiniDump() -{ - Clear(); - // We need to call finalize on the process before destroying ourselves - // to make sure all of the broadcaster cleanup goes as planned. If we - // destruct this class, then Process::~Process() might have problems - // trying to fully destroy the broadcaster. - Finalize(); -} - -ConstString -ProcessWinMiniDump::GetPluginName() -{ - return GetPluginNameStatic(); -} - -uint32_t -ProcessWinMiniDump::GetPluginVersion() -{ - return 1; } - Error -ProcessWinMiniDump::DoLoadCore() +ProcessWinMiniDump::Impl::DoLoadCore() { - Error error; - - error = MapMiniDumpIntoMemory(m_data_up->m_core_file.GetCString()); + Error error = MapMiniDumpIntoMemory(); if (error.Fail()) { return error; } - GetTarget().SetArchitecture(DetermineArchitecture()); + m_self->GetTarget().SetArchitecture(DetermineArchitecture()); ReadMiscInfo(); // notably for process ID ReadModuleList(); ReadExceptionRecord(); @@ -174,16 +168,8 @@ ProcessWinMiniDump::DoLoadCore() } -DynamicLoader * -ProcessWinMiniDump::GetDynamicLoader() -{ - if (m_dyld_ap.get() == NULL) - m_dyld_ap.reset (DynamicLoader::FindPlugin(this, DynamicLoaderWindowsDYLD::GetPluginNameStatic().GetCString())); - return m_dyld_ap.get(); -} - bool -ProcessWinMiniDump::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) +ProcessWinMiniDump::Impl::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) { size_t size = 0; auto thread_list_ptr = static_cast(FindDumpStream(ThreadListStream, &size)); @@ -192,10 +178,50 @@ ProcessWinMiniDump::UpdateThreadList(ThreadList &old_thread_list, ThreadList &ne const ULONG32 thread_count = thread_list_ptr->NumberOfThreads; for (ULONG32 i = 0; i < thread_count; ++i) { const auto &mini_dump_thread = thread_list_ptr->Threads[i]; - auto thread_sp = std::make_shared(*this, mini_dump_thread.ThreadId); + auto thread_sp = std::make_shared(*m_self, mini_dump_thread.ThreadId); if (mini_dump_thread.ThreadContext.DataSize >= sizeof(CONTEXT)) { - const CONTEXT *context = reinterpret_cast(static_cast(m_data_up->m_base_addr) + mini_dump_thread.ThreadContext.Rva); + const CONTEXT *context = reinterpret_cast(static_cast(m_base_addr) + + mini_dump_thread.ThreadContext.Rva); + + if (m_is_wow64) + { + // On Windows, a 32-bit process can run on a 64-bit machine under WOW64. + // If the minidump was captured with a 64-bit debugger, then the CONTEXT + // we just grabbed from the mini_dump_thread is the one for the 64-bit + // "native" process rather than the 32-bit "guest" process we care about. + // In this case, we can get the 32-bit CONTEXT from the TEB (Thread + // Environment Block) of the 64-bit process. + Error error; + TEB64 wow64teb = {0}; + m_self->ReadMemory(mini_dump_thread.Teb, &wow64teb, sizeof(wow64teb), error); + if (error.Success()) + { + // Slot 1 of the thread-local storage in the 64-bit TEB points to a structure + // that includes the 32-bit CONTEXT (after a ULONG). + // See: https://msdn.microsoft.com/en-us/library/ms681670.aspx + const size_t addr = wow64teb.TlsSlots[1]; + Range range = {0}; + if (FindMemoryRange(addr, &range)) + { + lldbassert(range.start <= addr); + const size_t offset = addr - range.start + sizeof(ULONG); + if (offset < range.size) + { + const size_t overlap = range.size - offset; + if (overlap >= sizeof(CONTEXT)) + { + context = reinterpret_cast(range.ptr + offset); + } + } + } + } + + // NOTE: We don't currently use the TEB for anything else. If we need it in + // the future, the 32-bit TEB is located according to the address stored in the + // first slot of the 64-bit TEB (wow64teb.Reserved1[0]). + } + thread_sp->SetContext(context); } new_thread_list.AddThread(thread_sp); @@ -206,54 +232,24 @@ ProcessWinMiniDump::UpdateThreadList(ThreadList &old_thread_list, ThreadList &ne } void -ProcessWinMiniDump::RefreshStateAfterStop() +ProcessWinMiniDump::Impl::RefreshStateAfterStop() { - if (!m_data_up) return; - if (!m_data_up->m_exception_sp) return; + if (!m_exception_sp) + return; - auto active_exception = m_data_up->m_exception_sp; + auto active_exception = m_exception_sp; std::string desc; llvm::raw_string_ostream desc_stream(desc); - desc_stream << "Exception " - << llvm::format_hex(active_exception->GetExceptionCode(), 8) - << " encountered at address " - << llvm::format_hex(active_exception->GetExceptionAddress(), 8); - m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID()); - auto stop_thread = m_thread_list.GetSelectedThread(); + desc_stream << "Exception " << llvm::format_hex(active_exception->GetExceptionCode(), 8) + << " encountered at address " << llvm::format_hex(active_exception->GetExceptionAddress(), 8); + m_self->m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID()); + auto stop_thread = m_self->m_thread_list.GetSelectedThread(); auto stop_info = StopInfo::CreateStopReasonWithException(*stop_thread, desc_stream.str().c_str()); stop_thread->SetStopInfo(stop_info); } -Error -ProcessWinMiniDump::DoDestroy() -{ - return Error(); -} - -bool -ProcessWinMiniDump::IsAlive() -{ - return true; -} - -bool -ProcessWinMiniDump::WarnBeforeDetach () const -{ - // Since this is post-mortem debugging, there's no need to warn the user - // that quitting the debugger will terminate the process. - return false; -} - size_t -ProcessWinMiniDump::ReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error) -{ - // Don't allow the caching that lldb_private::Process::ReadMemory does - // since we have it all cached our our dump file anyway. - return DoReadMemory(addr, buf, size, error); -} - -size_t -ProcessWinMiniDump::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error) +ProcessWinMiniDump::Impl::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error) { // I don't have a sense of how frequently this is called or how many memory // ranges a mini dump typically has, so I'm not sure if searching for the @@ -277,10 +273,11 @@ ProcessWinMiniDump::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Erro } Error -ProcessWinMiniDump::GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &info) +ProcessWinMiniDump::Impl::GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &info) { Error error; size_t size; + info.Clear(); const auto list = reinterpret_cast(FindDumpStream(MemoryInfoListStream, &size)); if (list == nullptr || size < sizeof(MINIDUMP_MEMORY_INFO_LIST)) { @@ -300,6 +297,8 @@ ProcessWinMiniDump::GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::Me return error; } + const MINIDUMP_MEMORY_INFO *next_entry = nullptr; + for (int i = 0; i < list->NumberOfEntries; ++i) { const auto entry = reinterpret_cast(reinterpret_cast(list) + @@ -308,80 +307,46 @@ ProcessWinMiniDump::GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::Me const auto tail = head + entry->RegionSize; if (head <= load_addr && load_addr < tail) { + info.GetRange().SetRangeBase((entry->State != MEM_FREE) ? head : load_addr); + info.GetRange().SetRangeEnd(tail); info.SetReadable(IsPageReadable(entry->Protect) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); info.SetWritable(IsPageWritable(entry->Protect) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); info.SetExecutable(IsPageExecutable(entry->Protect) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); + info.SetMapped((entry->State != MEM_FREE) ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); return error; } + else if (head > load_addr && (next_entry == nullptr || head < next_entry->BaseAddress) ) + { + // In case there is no region containing load_addr keep track of the nearest region + // after load_addr so we can return the distance to it. + next_entry = entry; + } } + + // No containing region found. Create an unmapped region that extends to the next region + // or LLDB_INVALID_ADDRESS + info.GetRange().SetRangeBase(load_addr); + info.GetRange().SetRangeEnd((next_entry != nullptr)?next_entry->BaseAddress:LLDB_INVALID_ADDRESS); + info.SetReadable(MemoryRegionInfo::eNo); + info.SetWritable(MemoryRegionInfo::eNo); + info.SetExecutable(MemoryRegionInfo::eNo); + info.SetMapped(MemoryRegionInfo::eNo); + // Note that the memory info list doesn't seem to contain ranges in kernel space, // so if you're walking a stack that has kernel frames, the stack may appear // truncated. - error.SetErrorString("address is not in a known range"); return error; } -void -ProcessWinMiniDump::Clear() -{ - m_thread_list.Clear(); -} - -void -ProcessWinMiniDump::Initialize() -{ - static std::once_flag g_once_flag; - - std::call_once(g_once_flag, []() - { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), - CreateInstance); - }); -} - -ArchSpec -ProcessWinMiniDump::GetArchitecture() -{ - // TODO - return ArchSpec(); -} - - -ProcessWinMiniDump::Data::Data() : - m_dump_file(INVALID_HANDLE_VALUE), - m_mapping(NULL), - m_base_addr(nullptr) -{ -} - -ProcessWinMiniDump::Data::~Data() -{ - if (m_base_addr) - { - ::UnmapViewOfFile(m_base_addr); - m_base_addr = nullptr; - } - if (m_mapping) - { - ::CloseHandle(m_mapping); - m_mapping = NULL; - } - if (m_dump_file != INVALID_HANDLE_VALUE) - { - ::CloseHandle(m_dump_file); - m_dump_file = INVALID_HANDLE_VALUE; - } -} - bool -ProcessWinMiniDump::FindMemoryRange(lldb::addr_t addr, Range *range_out) const +ProcessWinMiniDump::Impl::FindMemoryRange(lldb::addr_t addr, Range *range_out) const { size_t stream_size = 0; auto mem_list_stream = static_cast(FindDumpStream(MemoryListStream, &stream_size)); if (mem_list_stream) { - for (ULONG32 i = 0; i < mem_list_stream->NumberOfMemoryRanges; ++i) { + for (ULONG32 i = 0; i < mem_list_stream->NumberOfMemoryRanges; ++i) + { const MINIDUMP_MEMORY_DESCRIPTOR &mem_desc = mem_list_stream->MemoryRanges[i]; const MINIDUMP_LOCATION_DESCRIPTOR &loc_desc = mem_desc.Memory; const lldb::addr_t range_start = mem_desc.StartOfMemoryRange; @@ -390,7 +355,7 @@ ProcessWinMiniDump::FindMemoryRange(lldb::addr_t addr, Range *range_out) const { range_out->start = range_start; range_out->size = range_size; - range_out->ptr = reinterpret_cast(m_data_up->m_base_addr) + loc_desc.Rva; + range_out->ptr = reinterpret_cast(m_base_addr) + loc_desc.Rva; return true; } } @@ -411,7 +376,7 @@ ProcessWinMiniDump::FindMemoryRange(lldb::addr_t addr, Range *range_out) const { range_out->start = range_start; range_out->size = range_size; - range_out->ptr = reinterpret_cast(m_data_up->m_base_addr) + base_rva; + range_out->ptr = reinterpret_cast(m_base_addr) + base_rva; return true; } base_rva += range_size; @@ -421,31 +386,34 @@ ProcessWinMiniDump::FindMemoryRange(lldb::addr_t addr, Range *range_out) const return false; } - Error -ProcessWinMiniDump::MapMiniDumpIntoMemory(const char *file) +ProcessWinMiniDump::Impl::MapMiniDumpIntoMemory() { Error error; - - m_data_up->m_dump_file = ::CreateFile(file, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL); - if (m_data_up->m_dump_file == INVALID_HANDLE_VALUE) + const char *file = m_core_file.GetCString(); + std::wstring wfile; + if (!llvm::ConvertUTF8toWide(file, wfile)) + { + error.SetErrorString("Error converting path to UTF-16"); + return error; + } + m_dump_file = + ::CreateFileW(wfile.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (m_dump_file == INVALID_HANDLE_VALUE) { error.SetError(::GetLastError(), lldb::eErrorTypeWin32); return error; } - m_data_up->m_mapping = ::CreateFileMapping(m_data_up->m_dump_file, NULL, - PAGE_READONLY, 0, 0, NULL); - if (m_data_up->m_mapping == NULL) + m_mapping = ::CreateFileMappingW(m_dump_file, NULL, PAGE_READONLY, 0, 0, NULL); + if (m_mapping == NULL) { error.SetError(::GetLastError(), lldb::eErrorTypeWin32); return error; } - m_data_up->m_base_addr = ::MapViewOfFile(m_data_up->m_mapping, FILE_MAP_READ, 0, 0, 0); - if (m_data_up->m_base_addr == NULL) + m_base_addr = ::MapViewOfFile(m_mapping, FILE_MAP_READ, 0, 0, 0); + if (m_base_addr == nullptr) { error.SetError(::GetLastError(), lldb::eErrorTypeWin32); return error; @@ -454,9 +422,8 @@ ProcessWinMiniDump::MapMiniDumpIntoMemory(const char *file) return error; } - ArchSpec -ProcessWinMiniDump::DetermineArchitecture() +ProcessWinMiniDump::Impl::DetermineArchitecture() { size_t size = 0; auto system_info_ptr = static_cast(FindDumpStream(SystemInfoStream, &size)); @@ -465,9 +432,17 @@ ProcessWinMiniDump::DetermineArchitecture() switch (system_info_ptr->ProcessorArchitecture) { case PROCESSOR_ARCHITECTURE_INTEL: - return ArchSpec(eArchTypeCOFF, IMAGE_FILE_MACHINE_I386, LLDB_INVALID_CPUTYPE); + if (system_info_ptr->ProcessorLevel == 6) + { + return ArchSpec("i686-pc-windows"); + } + else + { + return ArchSpec("i386-pc-windows"); + } + break; case PROCESSOR_ARCHITECTURE_AMD64: - return ArchSpec(eArchTypeCOFF, IMAGE_FILE_MACHINE_AMD64, LLDB_INVALID_CPUTYPE); + return ArchSpec("x86_64-pc-windows"); default: break; } @@ -477,18 +452,24 @@ ProcessWinMiniDump::DetermineArchitecture() } void -ProcessWinMiniDump::ReadExceptionRecord() +ProcessWinMiniDump::Impl::ReadExceptionRecord() { size_t size = 0; auto exception_stream_ptr = static_cast(FindDumpStream(ExceptionStream, &size)); if (exception_stream_ptr) { - m_data_up->m_exception_sp.reset(new ExceptionRecord(exception_stream_ptr->ExceptionRecord, exception_stream_ptr->ThreadId)); + m_exception_sp.reset( + new ExceptionRecord(exception_stream_ptr->ExceptionRecord, exception_stream_ptr->ThreadId)); + } + else + { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Minidump has no exception record."); + // TODO: See if we can recover the exception from the TEB. } } void -ProcessWinMiniDump::ReadMiscInfo() +ProcessWinMiniDump::Impl::ReadMiscInfo() { size_t size = 0; const auto misc_info_ptr = static_cast(FindDumpStream(MiscInfoStream, &size)); @@ -498,12 +479,12 @@ ProcessWinMiniDump::ReadMiscInfo() if ((misc_info_ptr->Flags1 & MINIDUMP_MISC1_PROCESS_ID) != 0) { // This misc info record has the process ID. - SetID(misc_info_ptr->ProcessId); + m_self->SetID(misc_info_ptr->ProcessId); } } void -ProcessWinMiniDump::ReadModuleList() +ProcessWinMiniDump::Impl::ReadModuleList() { size_t size = 0; auto module_list_ptr = static_cast(FindDumpStream(ModuleListStream, &size)); @@ -515,36 +496,215 @@ ProcessWinMiniDump::ReadModuleList() for (ULONG32 i = 0; i < module_list_ptr->NumberOfModules; ++i) { const auto &module = module_list_ptr->Modules[i]; - const auto file_name = GetMiniDumpString(m_data_up->m_base_addr, module.ModuleNameRva); - ModuleSpec module_spec = FileSpec(file_name, true); + const auto file_name = GetMiniDumpString(module.ModuleNameRva); + const auto file_spec = FileSpec(file_name, true); + if (FileSpec::Compare(file_spec, FileSpec("wow64.dll", false), false) == 0) + { + WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Minidump is for a WOW64 process."); + m_is_wow64 = true; + } + ModuleSpec module_spec = file_spec; - lldb::ModuleSP module_sp = GetTarget().GetSharedModule(module_spec); + lldb::ModuleSP module_sp = m_self->GetTarget().GetSharedModule(module_spec); if (!module_sp) { continue; } bool load_addr_changed = false; - module_sp->SetLoadAddress(GetTarget(), module.BaseOfImage, false, load_addr_changed); + module_sp->SetLoadAddress(m_self->GetTarget(), module.BaseOfImage, false, load_addr_changed); } } void * -ProcessWinMiniDump::FindDumpStream(unsigned stream_number, size_t *size_out) const +ProcessWinMiniDump::Impl::FindDumpStream(unsigned stream_number, size_t *size_out) const { void *stream = nullptr; *size_out = 0; - assert(m_data_up != nullptr); - assert(m_data_up->m_base_addr != 0); - MINIDUMP_DIRECTORY *dir = nullptr; - if (::MiniDumpReadDumpStream(m_data_up->m_base_addr, stream_number, &dir, nullptr, nullptr) && - dir != nullptr && dir->Location.DataSize > 0) + if (::MiniDumpReadDumpStream(m_base_addr, stream_number, &dir, nullptr, nullptr) && dir != nullptr && + dir->Location.DataSize > 0) { assert(dir->StreamType == stream_number); *size_out = dir->Location.DataSize; - stream = static_cast(static_cast(m_data_up->m_base_addr) + dir->Location.Rva); + stream = static_cast(static_cast(m_base_addr) + dir->Location.Rva); } return stream; } + +std::string +ProcessWinMiniDump::Impl::GetMiniDumpString(RVA rva) const +{ + std::string result; + if (!m_base_addr) + { + return result; + } + auto md_string = reinterpret_cast(static_cast(m_base_addr) + rva); + auto source_start = reinterpret_cast(md_string->Buffer); + const auto source_length = ::wcslen(md_string->Buffer); + const auto source_end = source_start + source_length; + result.resize(UNI_MAX_UTF8_BYTES_PER_CODE_POINT * source_length); // worst case length + auto result_start = reinterpret_cast(&result[0]); + const auto result_end = result_start + result.size(); + ConvertUTF16toUTF8(&source_start, source_end, &result_start, result_end, strictConversion); + const auto result_size = std::distance(reinterpret_cast(&result[0]), result_start); + result.resize(result_size); // shrink to actual length + return result; +} + +ConstString +ProcessWinMiniDump::GetPluginNameStatic() +{ + static ConstString g_name("win-minidump"); + return g_name; +} + +const char * +ProcessWinMiniDump::GetPluginDescriptionStatic() +{ + return "Windows minidump plug-in."; +} + +void +ProcessWinMiniDump::Terminate() +{ + PluginManager::UnregisterPlugin(ProcessWinMiniDump::CreateInstance); +} + +lldb::ProcessSP +ProcessWinMiniDump::CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec *crash_file) +{ + lldb::ProcessSP process_sp; + if (crash_file) + { + process_sp.reset(new ProcessWinMiniDump(target_sp, listener_sp, *crash_file)); + } + return process_sp; +} + +bool +ProcessWinMiniDump::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) +{ + // TODO(amccarth): Eventually, this needs some actual logic. + return true; +} + +ProcessWinMiniDump::ProcessWinMiniDump(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec &core_file) + : ProcessWindows(target_sp, listener_sp), m_impl_up(new Impl(core_file, this)) +{ +} + +ProcessWinMiniDump::~ProcessWinMiniDump() +{ + Clear(); + // We need to call finalize on the process before destroying ourselves + // to make sure all of the broadcaster cleanup goes as planned. If we + // destruct this class, then Process::~Process() might have problems + // trying to fully destroy the broadcaster. + Finalize(); +} + +ConstString +ProcessWinMiniDump::GetPluginName() +{ + return GetPluginNameStatic(); +} + +uint32_t +ProcessWinMiniDump::GetPluginVersion() +{ + return 1; +} + +Error +ProcessWinMiniDump::DoLoadCore() +{ + return m_impl_up->DoLoadCore(); +} + +DynamicLoader * +ProcessWinMiniDump::GetDynamicLoader() +{ + if (m_dyld_ap.get() == NULL) + m_dyld_ap.reset(DynamicLoader::FindPlugin(this, DynamicLoaderWindowsDYLD::GetPluginNameStatic().GetCString())); + return m_dyld_ap.get(); +} + +bool +ProcessWinMiniDump::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) +{ + return m_impl_up->UpdateThreadList(old_thread_list, new_thread_list); +} + +void +ProcessWinMiniDump::RefreshStateAfterStop() +{ + if (!m_impl_up) + return; + return m_impl_up->RefreshStateAfterStop(); +} + +Error +ProcessWinMiniDump::DoDestroy() +{ + return Error(); +} + +bool +ProcessWinMiniDump::IsAlive() +{ + return true; +} + +bool +ProcessWinMiniDump::WarnBeforeDetach() const +{ + // Since this is post-mortem debugging, there's no need to warn the user + // that quitting the debugger will terminate the process. + return false; +} + +size_t +ProcessWinMiniDump::ReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error) +{ + // Don't allow the caching that lldb_private::Process::ReadMemory does + // since we have it all cached our our dump file anyway. + return DoReadMemory(addr, buf, size, error); +} + +size_t +ProcessWinMiniDump::DoReadMemory(lldb::addr_t addr, void *buf, size_t size, Error &error) +{ + return m_impl_up->DoReadMemory(addr, buf, size, error); +} + +Error +ProcessWinMiniDump::GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo &info) +{ + return m_impl_up->GetMemoryRegionInfo(load_addr, info); +} + +void +ProcessWinMiniDump::Clear() +{ + m_thread_list.Clear(); +} + +void +ProcessWinMiniDump::Initialize() +{ + static std::once_flag g_once_flag; + + std::call_once(g_once_flag, []() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance); + }); +} + +ArchSpec +ProcessWinMiniDump::GetArchitecture() +{ + // TODO + return ArchSpec(); +} diff --git a/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h b/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h index 12864be37127..3e1ac4bffbe3 100644 --- a/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h +++ b/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.h @@ -26,7 +26,7 @@ class ProcessWinMiniDump : public lldb_private::ProcessWindows public: static lldb::ProcessSP CreateInstance (lldb::TargetSP target_sp, - lldb_private::Listener &listener, + lldb::ListenerSP listener_sp, const lldb_private::FileSpec *crash_file_path); static void @@ -42,7 +42,7 @@ class ProcessWinMiniDump : public lldb_private::ProcessWindows GetPluginDescriptionStatic(); ProcessWinMiniDump(lldb::TargetSP target_sp, - lldb_private::Listener &listener, + lldb::ListenerSP listener_sp, const lldb_private::FileSpec &core_file); virtual @@ -96,45 +96,9 @@ class ProcessWinMiniDump : public lldb_private::ProcessWindows lldb_private::ThreadList &new_thread_list) override; private: - // Describes a range of memory captured in the mini dump. - struct Range { - lldb::addr_t start; // virtual address of the beginning of the range - size_t size; // size of the range in bytes - const uint8_t *ptr; // absolute pointer to the first byte of the range - }; - - // If the mini dump has a memory range that contains the desired address, it - // returns true with the details of the range in *range_out. Otherwise, it - // returns false. - bool - FindMemoryRange(lldb::addr_t addr, Range *range_out) const; - - lldb_private::Error - MapMiniDumpIntoMemory(const char *file); - - lldb_private::ArchSpec - DetermineArchitecture(); - - void - ReadExceptionRecord(); - - void - ReadMiscInfo(); - - void - ReadModuleList(); - - // A thin wrapper around WinAPI's MiniDumpReadDumpStream to avoid redundant - // checks. If there's a failure (e.g., if the requested stream doesn't exist), - // the function returns nullptr and sets *size_out to 0. - void * - FindDumpStream(unsigned stream_number, size_t *size_out) const; - - // Isolate the data to keep Windows-specific types out of this header. Can't - // use the typical pimpl idiom because the implementation of this class also - // needs access to public and protected members of the base class. - class Data; - std::unique_ptr m_data_up; + // Keep Windows-specific types out of this header. + class Impl; + std::unique_ptr m_impl_up; }; #endif // liblldb_ProcessWinMiniDump_h_ diff --git a/source/Plugins/Process/elf-core/CMakeLists.txt b/source/Plugins/Process/elf-core/CMakeLists.txt index 1a4dd7e9d333..b9f0b6cdfb7c 100644 --- a/source/Plugins/Process/elf-core/CMakeLists.txt +++ b/source/Plugins/Process/elf-core/CMakeLists.txt @@ -7,5 +7,6 @@ add_lldb_library(lldbPluginProcessElfCore RegisterContextPOSIXCore_arm64.cpp RegisterContextPOSIXCore_mips64.cpp RegisterContextPOSIXCore_powerpc.cpp + RegisterContextPOSIXCore_s390x.cpp RegisterContextPOSIXCore_x86_64.cpp ) diff --git a/source/Plugins/Process/elf-core/Makefile b/source/Plugins/Process/elf-core/Makefile deleted file mode 100644 index 8c5b3b800f5a..000000000000 --- a/source/Plugins/Process/elf-core/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Process/elf-core/Makefile -----------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginProcessElfCore -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp index 5b5d98a86d5e..a729d2beee77 100644 --- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -14,15 +14,16 @@ #include // Other libraries and framework includes -#include "lldb/Core/PluginManager.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" #include "lldb/Core/State.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Log.h" -#include "lldb/Target/Target.h" #include "lldb/Target/DynamicLoader.h" +#include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Target/Target.h" #include "lldb/Target/UnixSignals.h" #include "llvm/Support/ELF.h" @@ -57,7 +58,7 @@ ProcessElfCore::Terminate() lldb::ProcessSP -ProcessElfCore::CreateInstance (lldb::TargetSP target_sp, Listener &listener, const FileSpec *crash_file) +ProcessElfCore::CreateInstance (lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec *crash_file) { lldb::ProcessSP process_sp; if (crash_file) @@ -75,7 +76,7 @@ ProcessElfCore::CreateInstance (lldb::TargetSP target_sp, Listener &listener, co if (elf_header.Parse(data, &data_offset)) { if (elf_header.e_type == llvm::ELF::ET_CORE) - process_sp.reset(new ProcessElfCore (target_sp, listener, *crash_file)); + process_sp.reset(new ProcessElfCore (target_sp, listener_sp, *crash_file)); } } } @@ -104,9 +105,9 @@ ProcessElfCore::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name //---------------------------------------------------------------------- // ProcessElfCore constructor //---------------------------------------------------------------------- -ProcessElfCore::ProcessElfCore(lldb::TargetSP target_sp, Listener &listener, +ProcessElfCore::ProcessElfCore(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, const FileSpec &core_file) : - Process (target_sp, listener), + Process (target_sp, listener_sp), m_core_module_sp (), m_core_file (core_file), m_dyld_plugin_name (), @@ -148,7 +149,7 @@ ProcessElfCore::GetPluginVersion() lldb::addr_t ProcessElfCore::AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *header) { - lldb::addr_t addr = header->p_vaddr; + const lldb::addr_t addr = header->p_vaddr; FileRange file_range (header->p_offset, header->p_filesz); VMRangeToFileOffset::Entry range_entry(addr, header->p_memsz, file_range); @@ -166,6 +167,14 @@ ProcessElfCore::AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *head m_core_aranges.Append(range_entry); } + // Keep a separate map of permissions that that isn't coalesced so all ranges + // are maintained. + const uint32_t permissions = ((header->p_flags & llvm::ELF::PF_R) ? lldb::ePermissionsReadable : 0) | + ((header->p_flags & llvm::ELF::PF_W) ? lldb::ePermissionsWritable : 0) | + ((header->p_flags & llvm::ELF::PF_X) ? lldb::ePermissionsExecutable : 0); + + m_core_range_infos.Append(VMRangeToPermissions::Entry(addr, header->p_memsz, permissions)); + return addr; } @@ -227,7 +236,10 @@ ProcessElfCore::DoLoadCore () } if (!ranges_are_sorted) + { m_core_aranges.Sort(); + m_core_range_infos.Sort(); + } // Even if the architecture is set in the target, we need to override // it to match the core file which is always single arch. @@ -315,6 +327,47 @@ ProcessElfCore::ReadMemory (lldb::addr_t addr, void *buf, size_t size, Error &er return DoReadMemory (addr, buf, size, error); } +Error +ProcessElfCore::GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo ®ion_info) +{ + region_info.Clear(); + const VMRangeToPermissions::Entry *permission_entry = m_core_range_infos.FindEntryThatContainsOrFollows(load_addr); + if (permission_entry) + { + if (permission_entry->Contains(load_addr)) + { + region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase()); + region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd()); + const Flags permissions(permission_entry->data); + region_info.SetReadable(permissions.Test(lldb::ePermissionsReadable) ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + region_info.SetWritable(permissions.Test(lldb::ePermissionsWritable) ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + region_info.SetExecutable(permissions.Test(lldb::ePermissionsExecutable) ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + region_info.SetMapped(MemoryRegionInfo::eYes); + } + else if (load_addr < permission_entry->GetRangeBase()) + { + region_info.GetRange().SetRangeBase(load_addr); + region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase()); + region_info.SetReadable(MemoryRegionInfo::eNo); + region_info.SetWritable(MemoryRegionInfo::eNo); + region_info.SetExecutable(MemoryRegionInfo::eNo); + region_info.SetMapped(MemoryRegionInfo::eNo); + } + return Error(); + } + + region_info.GetRange().SetRangeBase(load_addr); + region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); + region_info.SetReadable(MemoryRegionInfo::eNo); + region_info.SetWritable(MemoryRegionInfo::eNo); + region_info.SetExecutable(MemoryRegionInfo::eNo); + region_info.SetMapped(MemoryRegionInfo::eNo); + return Error(); +} + size_t ProcessElfCore::DoReadMemory (lldb::addr_t addr, void *buf, size_t size, Error &error) { @@ -517,7 +570,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader * size_t note_start, note_size; note_start = offset; - note_size = llvm::RoundUpToAlignment(note.n_descsz, 4); + note_size = llvm::alignTo(note.n_descsz, 4); // Store the NOTE information in the current thread DataExtractor note_data (segment_data, note_start, note_size); @@ -559,11 +612,10 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader * have_prstatus = true; prstatus.Parse(note_data, arch); thread_data->signo = prstatus.pr_cursig; + thread_data->tid = prstatus.pr_pid; 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; @@ -572,6 +624,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader * have_prpsinfo = true; prpsinfo.Parse(note_data, arch); thread_data->name = prpsinfo.pr_fname; + SetID(prpsinfo.pr_pid); break; case NT_AUXV: m_auxv = DataExtractor(note_data); @@ -637,3 +690,18 @@ ProcessElfCore::GetAuxvData() lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(start, len)); return buffer; } + +bool +ProcessElfCore::GetProcessInfo(ProcessInstanceInfo &info) +{ + info.Clear(); + info.SetProcessID(GetID()); + info.SetArchitecture(GetArchitecture()); + lldb::ModuleSP module_sp = GetTarget().GetExecutableModule(); + if (module_sp) + { + const bool add_exe_file_as_first_arg = false; + info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(), add_exe_file_as_first_arg); + } + return true; +} diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.h b/source/Plugins/Process/elf-core/ProcessElfCore.h index 12ce04c5ce38..4bcbb363d3f8 100644 --- a/source/Plugins/Process/elf-core/ProcessElfCore.h +++ b/source/Plugins/Process/elf-core/ProcessElfCore.h @@ -40,7 +40,7 @@ public: //------------------------------------------------------------------ static lldb::ProcessSP CreateInstance (lldb::TargetSP target_sp, - lldb_private::Listener &listener, + lldb::ListenerSP listener_sp, const lldb_private::FileSpec *crash_file_path); static void @@ -59,7 +59,7 @@ public: // Constructors and Destructors //------------------------------------------------------------------ ProcessElfCore(lldb::TargetSP target_sp, - lldb_private::Listener &listener, + lldb::ListenerSP listener_sp, const lldb_private::FileSpec &core_file); ~ProcessElfCore() override; @@ -102,6 +102,9 @@ public: size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override; + lldb_private::Error + GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo ®ion_info) override; + lldb::addr_t GetImageInfoAddress() override; lldb_private::ArchSpec @@ -111,6 +114,9 @@ public: const lldb::DataBufferSP GetAuxvData() override; + bool + GetProcessInfo(lldb_private::ProcessInstanceInfo &info) override; + protected: void Clear ( ); @@ -132,6 +138,7 @@ private: //------------------------------------------------------------------ typedef lldb_private::Range FileRange; typedef lldb_private::RangeDataArray VMRangeToFileOffset; + typedef lldb_private::RangeDataVector VMRangeToPermissions; lldb::ModuleSP m_core_module_sp; lldb_private::FileSpec m_core_file; @@ -152,6 +159,9 @@ private: // Address ranges found in the core VMRangeToFileOffset m_core_aranges; + // Permissions for all ranges + VMRangeToPermissions m_core_range_infos; + // NT_FILE entries found from the NOTE segment std::vector m_nt_file_entries; diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp new file mode 100644 index 000000000000..d2f0a8dd3671 --- /dev/null +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp @@ -0,0 +1,115 @@ +//===-- RegisterContextCorePOSIX_s390x.cpp ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Target/Thread.h" +#include "RegisterContextPOSIXCore_s390x.h" + +using namespace lldb_private; + +RegisterContextCorePOSIX_s390x::RegisterContextCorePOSIX_s390x(Thread &thread, RegisterInfoInterface *register_info, + const DataExtractor &gpregset, + const DataExtractor &fpregset) + : RegisterContextPOSIX_s390x(thread, 0, register_info) +{ + m_gpr_buffer.reset(new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize())); + m_gpr.SetData(m_gpr_buffer); + m_gpr.SetByteOrder(gpregset.GetByteOrder()); + + m_fpr_buffer.reset(new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize())); + m_fpr.SetData(m_fpr_buffer); + m_fpr.SetByteOrder(fpregset.GetByteOrder()); +} + +RegisterContextCorePOSIX_s390x::~RegisterContextCorePOSIX_s390x() +{ +} + +bool +RegisterContextCorePOSIX_s390x::ReadGPR() +{ + return true; +} + +bool +RegisterContextCorePOSIX_s390x::ReadFPR() +{ + return true; +} + +bool +RegisterContextCorePOSIX_s390x::WriteGPR() +{ + assert(0); + return false; +} + +bool +RegisterContextCorePOSIX_s390x::WriteFPR() +{ + assert(0); + return false; +} + +bool +RegisterContextCorePOSIX_s390x::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value) +{ + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg == LLDB_INVALID_REGNUM) + return false; + + if (IsGPR(reg)) + { + lldb::offset_t offset = reg_info->byte_offset; + uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size); + if (offset == reg_info->byte_offset + reg_info->byte_size) + { + value.SetUInt(v, reg_info->byte_size); + return true; + } + } + + if (IsFPR(reg)) + { + lldb::offset_t offset = reg_info->byte_offset; + uint64_t v = m_fpr.GetMaxU64(&offset, reg_info->byte_size); + if (offset == reg_info->byte_offset + reg_info->byte_size) + { + value.SetUInt(v, reg_info->byte_size); + return true; + } + } + + return false; +} + +bool +RegisterContextCorePOSIX_s390x::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) +{ + return false; +} + +bool +RegisterContextCorePOSIX_s390x::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value) +{ + return false; +} + +bool +RegisterContextCorePOSIX_s390x::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) +{ + return false; +} + +bool +RegisterContextCorePOSIX_s390x::HardwareSingleStep(bool enable) +{ + return false; +} diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h new file mode 100644 index 000000000000..8bb6fe1771ef --- /dev/null +++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h @@ -0,0 +1,65 @@ +//===-- RegisterContextCorePOSIX_s390x.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_s390x_h_ +#define liblldb_RegisterContextCorePOSIX_s390x_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Core/DataBufferHeap.h" +#include "Plugins/Process/Utility/RegisterContextPOSIX_s390x.h" + +class RegisterContextCorePOSIX_s390x : public RegisterContextPOSIX_s390x +{ +public: + RegisterContextCorePOSIX_s390x(lldb_private::Thread &thread, lldb_private::RegisterInfoInterface *register_info, + const lldb_private::DataExtractor &gpregset, + const lldb_private::DataExtractor &fpregset); + + ~RegisterContextCorePOSIX_s390x() override; + + bool + ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value) override; + + bool + WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value) override; + + bool + ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + + bool + WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + + bool + HardwareSingleStep(bool enable) override; + +protected: + bool + ReadGPR() override; + + bool + ReadFPR() override; + + bool + WriteGPR() override; + + bool + WriteFPR() override; + +private: + lldb::DataBufferSP m_gpr_buffer; + lldb_private::DataExtractor m_gpr; + + lldb::DataBufferSP m_fpr_buffer; + lldb_private::DataExtractor m_fpr; +}; + +#endif // liblldb_RegisterContextCorePOSIX_s390x_h_ diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp index 9cc7829fc391..e4cfa68044f1 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp +++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp @@ -18,6 +18,7 @@ #include "ProcessElfCore.h" #include "Plugins/Process/Utility/RegisterContextLinux_arm.h" #include "Plugins/Process/Utility/RegisterContextLinux_arm64.h" +#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h" #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_arm.h" #include "Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h" @@ -29,6 +30,7 @@ #include "RegisterContextPOSIXCore_arm64.h" #include "RegisterContextPOSIXCore_mips64.h" #include "RegisterContextPOSIXCore_powerpc.h" +#include "RegisterContextPOSIXCore_s390x.h" #include "RegisterContextPOSIXCore_x86_64.h" using namespace lldb; @@ -139,6 +141,9 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame) case llvm::Triple::aarch64: reg_interface = new RegisterContextLinux_arm64(arch); break; + case llvm::Triple::systemz: + reg_interface = new RegisterContextLinux_s390x(arch); + break; case llvm::Triple::x86_64: reg_interface = new RegisterContextLinux_x86_64(arch); break; @@ -174,6 +179,9 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame) case llvm::Triple::ppc64: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc (*this, reg_interface, m_gpregset_data, m_fpregset_data, m_vregset_data)); break; + case llvm::Triple::systemz: + m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_s390x (*this, reg_interface, m_gpregset_data, m_fpregset_data)); + break; case llvm::Triple::x86: case llvm::Triple::x86_64: m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64 (*this, reg_interface, m_gpregset_data, m_fpregset_data)); @@ -218,6 +226,7 @@ ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch) size_t len; switch(arch.GetCore()) { + case ArchSpec::eCore_s390x_generic: case ArchSpec::eCore_x86_64_x86_64: len = data.ExtractBytes(0, ELFLINUXPRSTATUS64_SIZE, byteorder, this); return len == ELFLINUXPRSTATUS64_SIZE; @@ -241,6 +250,7 @@ ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch) size_t len; switch(arch.GetCore()) { + case ArchSpec::eCore_s390x_generic: case ArchSpec::eCore_x86_64_x86_64: len = data.ExtractBytes(0, ELFLINUXPRPSINFO64_SIZE, byteorder, this); return len == ELFLINUXPRPSINFO64_SIZE; diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.h b/source/Plugins/Process/elf-core/ThreadElfCore.h index d3a42e0eb54d..b4e990140675 100644 --- a/source/Plugins/Process/elf-core/ThreadElfCore.h +++ b/source/Plugins/Process/elf-core/ThreadElfCore.h @@ -68,6 +68,7 @@ struct ELFLinuxPrStatus { switch(arch.GetCore()) { + case lldb_private::ArchSpec::eCore_s390x_generic: case lldb_private::ArchSpec::eCore_x86_64_x86_64: return ELFLINUXPRSTATUS64_SIZE; default: @@ -102,6 +103,7 @@ struct ELFLinuxPrPsInfo { switch(arch.GetCore()) { + case lldb_private::ArchSpec::eCore_s390x_generic: case lldb_private::ArchSpec::eCore_x86_64_x86_64: return ELFLINUXPRPSINFO64_SIZE; default: diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 2ea1f206008a..f164b1411be8 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -793,8 +793,8 @@ GDBRemoteCommunication::PacketType GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, StringExtractorGDBRemote &packet) { // Put the packet data into the buffer in a thread safe fashion - Mutex::Locker locker(m_bytes_mutex); - + std::lock_guard guard(m_bytes_mutex); + Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); if (src && src_len > 0) @@ -845,7 +845,7 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri case '%': // Async notify packet isNotifyPacket = true; - // Intentional fall through + LLVM_FALLTHROUGH; case '$': // Look for a standard gdb packet? @@ -1120,7 +1120,7 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *url, { Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); if (log) - log->Printf ("GDBRemoteCommunication::%s(url=%s, port=%" PRIu16, __FUNCTION__, url ? url : "", port ? *port : uint16_t(0)); + log->Printf ("GDBRemoteCommunication::%s(url=%s, port=%" PRIu16 ")", __FUNCTION__, url ? url : "", port ? *port : uint16_t(0)); Error error; // If we locate debugserver, keep that located version around @@ -1352,7 +1352,14 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *url, launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false); launch_info.AppendSuppressFileAction (STDOUT_FILENO, false, true); launch_info.AppendSuppressFileAction (STDERR_FILENO, false, true); - + + if (log) + { + StreamString string_stream; + Platform *const platform = nullptr; + launch_info.Dump(string_stream, platform); + log->Printf("launch info for gdb-remote stub:\n%s", string_stream.GetString().c_str()); + } error = Host::LaunchProcess(launch_info); if (error.Success() && diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index c0ea9cceea2e..c90706a88b84 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -55,79 +55,79 @@ using namespace lldb_private::process_gdb_remote; //---------------------------------------------------------------------- // GDBRemoteCommunicationClient constructor //---------------------------------------------------------------------- -GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() : - GDBRemoteCommunication("gdb-remote.client", "gdb-remote.client.rx_packet"), - m_supports_not_sending_acks (eLazyBoolCalculate), - m_supports_thread_suffix (eLazyBoolCalculate), - m_supports_threads_in_stop_reply (eLazyBoolCalculate), - m_supports_vCont_all (eLazyBoolCalculate), - m_supports_vCont_any (eLazyBoolCalculate), - m_supports_vCont_c (eLazyBoolCalculate), - m_supports_vCont_C (eLazyBoolCalculate), - m_supports_vCont_s (eLazyBoolCalculate), - m_supports_vCont_S (eLazyBoolCalculate), - m_qHostInfo_is_valid (eLazyBoolCalculate), - m_curr_pid_is_valid (eLazyBoolCalculate), - m_qProcessInfo_is_valid (eLazyBoolCalculate), - m_qGDBServerVersion_is_valid (eLazyBoolCalculate), - m_supports_alloc_dealloc_memory (eLazyBoolCalculate), - m_supports_memory_region_info (eLazyBoolCalculate), - m_supports_watchpoint_support_info (eLazyBoolCalculate), - m_supports_detach_stay_stopped (eLazyBoolCalculate), - m_watchpoints_trigger_after_instruction(eLazyBoolCalculate), - m_attach_or_wait_reply(eLazyBoolCalculate), - m_prepare_for_reg_writing_reply (eLazyBoolCalculate), - m_supports_p (eLazyBoolCalculate), - m_supports_x (eLazyBoolCalculate), - m_avoid_g_packets (eLazyBoolCalculate), - m_supports_QSaveRegisterState (eLazyBoolCalculate), - m_supports_qXfer_auxv_read (eLazyBoolCalculate), - m_supports_qXfer_libraries_read (eLazyBoolCalculate), - m_supports_qXfer_libraries_svr4_read (eLazyBoolCalculate), - m_supports_qXfer_features_read (eLazyBoolCalculate), - m_supports_augmented_libraries_svr4_read (eLazyBoolCalculate), - m_supports_jThreadExtendedInfo (eLazyBoolCalculate), - m_supports_jLoadedDynamicLibrariesInfos (eLazyBoolCalculate), - m_supports_qProcessInfoPID (true), - m_supports_qfProcessInfo (true), - m_supports_qUserName (true), - m_supports_qGroupName (true), - m_supports_qThreadStopInfo (true), - m_supports_z0 (true), - m_supports_z1 (true), - m_supports_z2 (true), - m_supports_z3 (true), - m_supports_z4 (true), - m_supports_QEnvironment (true), - m_supports_QEnvironmentHexEncoded (true), - m_supports_qSymbol (true), - m_qSymbol_requests_done (false), - m_supports_qModuleInfo (true), - m_supports_jThreadsInfo (true), - m_curr_pid (LLDB_INVALID_PROCESS_ID), - m_curr_tid (LLDB_INVALID_THREAD_ID), - m_curr_tid_run (LLDB_INVALID_THREAD_ID), - m_num_supported_hardware_watchpoints (0), - m_async_mutex (Mutex::eMutexTypeRecursive), - m_async_packet_predicate (false), - m_async_packet (), - m_async_result (PacketResult::Success), - m_async_response (), - m_async_signal (-1), - m_interrupt_sent (false), - m_thread_id_to_used_usec_map (), - m_host_arch(), - m_process_arch(), - m_os_version_major (UINT32_MAX), - m_os_version_minor (UINT32_MAX), - m_os_version_update (UINT32_MAX), - m_os_build (), - m_os_kernel (), - m_hostname (), - m_gdb_server_name(), - m_gdb_server_version(UINT32_MAX), - m_default_packet_timeout (0), - m_max_packet_size (0) +GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() + : GDBRemoteCommunication("gdb-remote.client", "gdb-remote.client.rx_packet"), + m_supports_not_sending_acks(eLazyBoolCalculate), + m_supports_thread_suffix(eLazyBoolCalculate), + m_supports_threads_in_stop_reply(eLazyBoolCalculate), + m_supports_vCont_all(eLazyBoolCalculate), + m_supports_vCont_any(eLazyBoolCalculate), + m_supports_vCont_c(eLazyBoolCalculate), + m_supports_vCont_C(eLazyBoolCalculate), + m_supports_vCont_s(eLazyBoolCalculate), + m_supports_vCont_S(eLazyBoolCalculate), + m_qHostInfo_is_valid(eLazyBoolCalculate), + m_curr_pid_is_valid(eLazyBoolCalculate), + m_qProcessInfo_is_valid(eLazyBoolCalculate), + m_qGDBServerVersion_is_valid(eLazyBoolCalculate), + m_supports_alloc_dealloc_memory(eLazyBoolCalculate), + m_supports_memory_region_info(eLazyBoolCalculate), + m_supports_watchpoint_support_info(eLazyBoolCalculate), + m_supports_detach_stay_stopped(eLazyBoolCalculate), + m_watchpoints_trigger_after_instruction(eLazyBoolCalculate), + m_attach_or_wait_reply(eLazyBoolCalculate), + m_prepare_for_reg_writing_reply(eLazyBoolCalculate), + m_supports_p(eLazyBoolCalculate), + m_supports_x(eLazyBoolCalculate), + m_avoid_g_packets(eLazyBoolCalculate), + m_supports_QSaveRegisterState(eLazyBoolCalculate), + m_supports_qXfer_auxv_read(eLazyBoolCalculate), + m_supports_qXfer_libraries_read(eLazyBoolCalculate), + m_supports_qXfer_libraries_svr4_read(eLazyBoolCalculate), + m_supports_qXfer_features_read(eLazyBoolCalculate), + m_supports_augmented_libraries_svr4_read(eLazyBoolCalculate), + m_supports_jThreadExtendedInfo(eLazyBoolCalculate), + m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate), + m_supports_qProcessInfoPID(true), + m_supports_qfProcessInfo(true), + m_supports_qUserName(true), + m_supports_qGroupName(true), + m_supports_qThreadStopInfo(true), + m_supports_z0(true), + m_supports_z1(true), + m_supports_z2(true), + m_supports_z3(true), + m_supports_z4(true), + m_supports_QEnvironment(true), + m_supports_QEnvironmentHexEncoded(true), + m_supports_qSymbol(true), + m_qSymbol_requests_done(false), + m_supports_qModuleInfo(true), + m_supports_jThreadsInfo(true), + m_curr_pid(LLDB_INVALID_PROCESS_ID), + m_curr_tid(LLDB_INVALID_THREAD_ID), + m_curr_tid_run(LLDB_INVALID_THREAD_ID), + m_num_supported_hardware_watchpoints(0), + m_async_mutex(), + m_async_packet_predicate(false), + m_async_packet(), + m_async_result(PacketResult::Success), + m_async_response(), + m_async_signal(-1), + m_interrupt_sent(false), + m_thread_id_to_used_usec_map(), + m_host_arch(), + m_process_arch(), + m_os_version_major(UINT32_MAX), + m_os_version_minor(UINT32_MAX), + m_os_version_update(UINT32_MAX), + m_os_build(), + m_os_kernel(), + m_hostname(), + m_gdb_server_name(), + m_gdb_server_version(UINT32_MAX), + m_default_packet_timeout(0), + m_max_packet_size(0) { } @@ -623,6 +623,7 @@ GDBRemoteCommunicationClient::GetThreadsInfo() if (m_supports_jThreadsInfo) { StringExtractorGDBRemote response; + response.SetResponseValidatorToJSON(); if (SendPacketAndWaitForResponse("jThreadsInfo", response, false) == PacketResult::Success) { if (response.IsUnsupportedResponse()) @@ -765,9 +766,29 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponseNoLock (const char *pa size_t payload_length, StringExtractorGDBRemote &response) { - PacketResult packet_result = SendPacketNoLock (payload, payload_length); + PacketResult packet_result = SendPacketNoLock(payload, payload_length); if (packet_result == PacketResult::Success) - packet_result = ReadPacket (response, GetPacketTimeoutInMicroSeconds (), true); + { + const size_t max_response_retries = 3; + for (size_t i=0; iPrintf("error: packet with payload \"%*s\" got invalid response \"%s\": %s", + (int)payload_length, + payload, + response.GetStringRef().c_str(), + (i == (max_response_retries - 1)) ? "using invalid response and giving up" : "ignoring response and waiting for another"); + } + } return packet_result; } @@ -786,8 +807,8 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse // In order to stop async notifications from being processed in the middle of the // send/receive sequence Hijack the broadcast. Then rebroadcast any events when we are done. - static Listener hijack_listener("lldb.NotifyHijacker"); - HijackBroadcaster(&hijack_listener, eBroadcastBitGdbReadThreadGotNotify); + static ListenerSP hijack_listener_sp(Listener::MakeListener("lldb.NotifyHijacker")); + HijackBroadcaster(hijack_listener_sp, eBroadcastBitGdbReadThreadGotNotify); if (GetSequenceMutex (locker)) { @@ -799,8 +820,9 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse { if (IsRunning()) { - Mutex::Locker async_locker (m_async_mutex); + std::lock_guard guard(m_async_mutex); m_async_packet.assign(payload, payload_length); + m_async_response.CopyResponseValidator(response); m_async_packet_predicate.SetValue (true, eBroadcastNever); if (log) @@ -867,6 +889,9 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse if (log) log->Printf ("async: failed to interrupt"); } + + m_async_response.SetResponseValidator(nullptr, nullptr); + } else { @@ -886,7 +911,7 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse // If a notification event occurred, rebroadcast since it can now be processed safely. EventSP event_sp; - if (hijack_listener.GetNextEvent(event_sp)) + if (hijack_listener_sp->GetNextEvent(event_sp)) BroadcastEvent(event_sp); return packet_result; @@ -1136,13 +1161,17 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse // which will just re-send a copy of the last stop reply // packet. If we don't do this, then the reply for our // async packet will be the repeat stop reply packet and cause - // a lot of trouble for us! - if (signo != sigint_signo && signo != sigstop_signo) + // a lot of trouble for us! We also have some debugserver + // binaries that would send two stop replies anytime the process + // was interrupted, so we need to also check for an extra + // stop reply packet if we interrupted the process + const bool received_nonstop_signal = signo != sigint_signo && signo != sigstop_signo; + if (m_interrupt_sent || received_nonstop_signal) { - continue_after_async = false; + if (received_nonstop_signal) + continue_after_async = false; - // We didn't get a SIGINT or SIGSTOP, so try for a - // very brief time (0.1s) to get another stop reply + // Try for a 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 = 100000; @@ -1343,7 +1372,7 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse bool GDBRemoteCommunicationClient::SendAsyncSignal (int signo) { - Mutex::Locker async_locker (m_async_mutex); + std::lock_guard guard(m_async_mutex); m_async_signal = signo; bool timed_out = false; Mutex::Locker locker; @@ -2064,7 +2093,8 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force) if (pointer_byte_size != 0) ++num_keys_decoded; } - else if (name.compare("os_version") == 0) + else if ((name.compare("os_version") == 0) || + (name.compare("version") == 0)) // Older debugserver binaries used the "version" key instead of "os_version"... { Args::StringToVersion (value.c_str(), m_os_version_major, @@ -2114,20 +2144,6 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force) assert (byte_order == m_host_arch.GetByteOrder()); } - if (!os_name.empty() && vendor_name.compare("apple") == 0 && os_name.find("darwin") == 0) - { - switch (m_host_arch.GetMachine()) - { - case llvm::Triple::aarch64: - case llvm::Triple::arm: - case llvm::Triple::thumb: - os_name = "ios"; - break; - default: - os_name = "macosx"; - break; - } - } if (!vendor_name.empty()) m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name)); if (!os_name.empty()) @@ -2411,6 +2427,8 @@ GDBRemoteCommunicationClient::GetMemoryRegionInfo (lldb::addr_t addr, region_info.SetExecutable (MemoryRegionInfo::eYes); else region_info.SetExecutable (MemoryRegionInfo::eNo); + + region_info.SetMapped(MemoryRegionInfo::eYes); } else { @@ -2418,6 +2436,7 @@ GDBRemoteCommunicationClient::GetMemoryRegionInfo (lldb::addr_t addr, region_info.SetReadable (MemoryRegionInfo::eNo); region_info.SetWritable (MemoryRegionInfo::eNo); region_info.SetExecutable (MemoryRegionInfo::eNo); + region_info.SetMapped(MemoryRegionInfo::eNo); } } else if (name.compare ("error") == 0) @@ -2437,6 +2456,7 @@ GDBRemoteCommunicationClient::GetMemoryRegionInfo (lldb::addr_t addr, region_info.SetReadable (MemoryRegionInfo::eNo); region_info.SetWritable (MemoryRegionInfo::eNo); region_info.SetExecutable (MemoryRegionInfo::eNo); + region_info.SetMapped(MemoryRegionInfo::eNo); } } else @@ -3571,6 +3591,8 @@ GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type, // Check we haven't overwritten the end of the packet buffer assert (packet_len + 1 < (int)sizeof(packet)); StringExtractorGDBRemote response; + // Make sure the response is either "OK", "EXX" where XX are two hex digits, or "" (unsupported) + response.SetResponseValidatorToOKErrorNotSupported(); // Try to send the breakpoint packet, and check that it was correctly sent if (SendPacketAndWaitForResponse(packet, packet_len, response, true) == PacketResult::Success) { @@ -4417,7 +4439,7 @@ GDBRemoteCommunicationClient::ReadExtFeature (const lldb_private::ConstString ob // last chunk case ( 'l' ): active = false; - // fall through intentional + LLVM_FALLTHROUGH; // more chunks case ( 'm' ) : diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 311b0f3267c8..096c4cf81015 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -13,6 +13,7 @@ // C Includes // C++ Includes #include +#include #include #include @@ -527,7 +528,7 @@ public: bool ReadRegister(lldb::tid_t tid, - uint32_t reg_num, + uint32_t reg_num, // Must be the eRegisterKindProcessPlugin register number, to be sent to the remote StringExtractorGDBRemote &response); bool @@ -631,7 +632,7 @@ protected: // If we need to send a packet while the target is running, the m_async_XXX // member variables take care of making this happen. - Mutex m_async_mutex; + std::recursive_mutex m_async_mutex; Predicate m_async_packet_predicate; std::string m_async_packet; PacketResult m_async_result; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h index f55b2eb3f4dc..d2fd70042ccc 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h @@ -17,7 +17,6 @@ // Other libraries and framework includes // Project includes #include "lldb/lldb-private-forward.h" -#include "lldb/Host/Mutex.h" #include "lldb/Target/Process.h" #include "GDBRemoteCommunicationServer.h" diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 921369c7ef21..fc6b31ec088e 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -39,7 +39,6 @@ #include "lldb/Host/TimeValue.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/MemoryRegionInfo.h" -#include "lldb/Target/Platform.h" #include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Host/common/NativeThreadProtocol.h" @@ -76,25 +75,21 @@ namespace //---------------------------------------------------------------------- // GDBRemoteCommunicationServerLLGS constructor //---------------------------------------------------------------------- -GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS( - const lldb::PlatformSP& platform_sp, - MainLoop &mainloop) : - GDBRemoteCommunicationServerCommon ("gdb-remote.server", "gdb-remote.server.rx_packet"), - m_platform_sp (platform_sp), - m_mainloop (mainloop), - m_current_tid (LLDB_INVALID_THREAD_ID), - m_continue_tid (LLDB_INVALID_THREAD_ID), - m_debugged_process_mutex (Mutex::eMutexTypeRecursive), - m_debugged_process_sp (), - m_stdio_communication ("process.stdio"), - m_inferior_prev_state (StateType::eStateInvalid), - m_active_auxv_buffer_sp (), - m_saved_registers_mutex (), - m_saved_registers_map (), - m_next_saved_registers_id (1), - m_handshake_completed (false) -{ - assert(platform_sp); +GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS(MainLoop &mainloop) + : GDBRemoteCommunicationServerCommon("gdb-remote.server", "gdb-remote.server.rx_packet"), + m_mainloop(mainloop), + m_current_tid(LLDB_INVALID_THREAD_ID), + m_continue_tid(LLDB_INVALID_THREAD_ID), + m_debugged_process_mutex(), + m_debugged_process_sp(), + m_stdio_communication("process.stdio"), + m_inferior_prev_state(StateType::eStateInvalid), + m_active_auxv_buffer_sp(), + m_saved_registers_mutex(), + m_saved_registers_map(), + m_next_saved_registers_id(1), + m_handshake_completed(false) +{ RegisterPacketHandlers(); } @@ -210,7 +205,7 @@ GDBRemoteCommunicationServerLLGS::LaunchProcess () Error error; { - Mutex::Locker locker (m_debugged_process_mutex); + std::lock_guard guard(m_debugged_process_mutex); assert (!m_debugged_process_sp && "lldb-gdbserver creating debugged process but one already exists"); error = NativeProcessProtocol::Launch( m_process_launch_info, @@ -1367,7 +1362,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont (StringExtractorGDBRemote &packet thread_action.signal = packet.GetHexMaxU32 (false, 0); if (thread_action.signal == 0) return SendIllFormedResponse (packet, "Could not parse signal in vCont packet C action"); - // Fall through to next case... + LLVM_FALLTHROUGH; case 'c': // Continue @@ -1378,7 +1373,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont (StringExtractorGDBRemote &packet thread_action.signal = packet.GetHexMaxU32 (false, 0); if (thread_action.signal == 0) return SendIllFormedResponse (packet, "Could not parse signal in vCont packet S action"); - // Fall through to next case... + LLVM_FALLTHROUGH; case 's': // Step @@ -2593,7 +2588,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState (StringExtractorGDBR // Save the register data buffer under the save id. { - Mutex::Locker locker (m_saved_registers_mutex); + std::lock_guard guard(m_saved_registers_mutex); m_saved_registers_map[save_id] = register_data_sp; } @@ -2643,7 +2638,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState (StringExtractorG // Retrieve register state buffer, then remove from the list. DataBufferSP register_data_sp; { - Mutex::Locker locker (m_saved_registers_mutex); + std::lock_guard guard(m_saved_registers_mutex); // Find the register set buffer for the given save id. auto it = m_saved_registers_map.find (save_id); @@ -2947,7 +2942,7 @@ GDBRemoteCommunicationServerLLGS::GetCurrentThreadID () const uint32_t GDBRemoteCommunicationServerLLGS::GetNextSavedRegistersID () { - Mutex::Locker locker (m_saved_registers_mutex); + std::lock_guard guard(m_saved_registers_mutex); return m_next_saved_registers_id++; } diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index f16057781ddc..caf6eb319e63 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -12,12 +12,12 @@ // C Includes // C++ Includes +#include #include // Other libraries and framework includes #include "lldb/lldb-private-forward.h" #include "lldb/Core/Communication.h" -#include "lldb/Host/Mutex.h" #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Host/MainLoop.h" @@ -40,7 +40,7 @@ public: //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ - GDBRemoteCommunicationServerLLGS(const lldb::PlatformSP& platform_sp, MainLoop &mainloop); + GDBRemoteCommunicationServerLLGS(MainLoop &mainloop); //------------------------------------------------------------------ /// Specify the program to launch and its arguments. @@ -114,12 +114,11 @@ public: InitializeConnection (std::unique_ptr &&connection); protected: - lldb::PlatformSP m_platform_sp; MainLoop &m_mainloop; MainLoop::ReadHandleUP m_network_handle_up; lldb::tid_t m_current_tid; lldb::tid_t m_continue_tid; - Mutex m_debugged_process_mutex; + std::recursive_mutex m_debugged_process_mutex; NativeProcessProtocolSP m_debugged_process_sp; Communication m_stdio_communication; @@ -127,7 +126,7 @@ protected: lldb::StateType m_inferior_prev_state; lldb::DataBufferSP m_active_auxv_buffer_sp; - Mutex m_saved_registers_mutex; + std::mutex m_saved_registers_mutex; std::unordered_map m_saved_registers_map; uint32_t m_next_saved_registers_id; bool m_handshake_completed : 1; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index f88ac1247526..d6900c27293c 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -48,14 +48,13 @@ using namespace lldb_private::process_gdb_remote; // GDBRemoteCommunicationServerPlatform constructor //---------------------------------------------------------------------- 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) + 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(), + m_port_map(), + m_port_offset(0) { m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID; m_pending_gdb_server.port = 0; @@ -78,11 +77,7 @@ GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(const &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo); RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt, - [this](StringExtractorGDBRemote packet, - Error &error, - bool &interrupt, - bool &quit) - { + [this](StringExtractorGDBRemote packet, Error &error, bool &interrupt, bool &quit) { error.SetErrorString("interrupt received"); interrupt = true; return PacketResult::Success; @@ -124,7 +119,8 @@ GDBRemoteCommunicationServerPlatform::LaunchGDBServer(const lldb_private::Args& // Do not run in a new session so that it can not linger after the // platform closes. debugserver_launch_info.SetLaunchInSeparateProcessGroup(false); - debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false); + debugserver_launch_info.SetMonitorProcessCallback( + std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, this, std::placeholders::_1), false); std::string platform_scheme; std::string platform_ip; @@ -135,6 +131,10 @@ GDBRemoteCommunicationServerPlatform::LaunchGDBServer(const lldb_private::Args& assert(ok); std::ostringstream url; + // debugserver does not accept the URL scheme prefix. +#if !defined(__APPLE__) + url << m_socket_scheme << "://"; +#endif uint16_t* port_ptr = &port; if (m_socket_protocol == Socket::ProtocolTcp) url << platform_ip << ":" << port; @@ -154,7 +154,7 @@ GDBRemoteCommunicationServerPlatform::LaunchGDBServer(const lldb_private::Args& pid = debugserver_launch_info.GetProcessID(); if (pid != LLDB_INVALID_PROCESS_ID) { - Mutex::Locker locker (m_spawned_pids_mutex); + std::lock_guard guard(m_spawned_pids_mutex); m_spawned_pids.insert(pid); if (port > 0) AssociatePortWithProcess(port, pid); @@ -259,7 +259,7 @@ GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess (StringExtracto // verify that we know anything about this pid. // Scope for locker { - Mutex::Locker locker (m_spawned_pids_mutex); + std::lock_guard guard(m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) { // not a pid we know about @@ -279,7 +279,7 @@ GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid) { // make sure we know about this process { - Mutex::Locker locker (m_spawned_pids_mutex); + std::lock_guard guard(m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) return false; } @@ -291,7 +291,7 @@ GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid) for (size_t i=0; i<10; ++i) { { - Mutex::Locker locker (m_spawned_pids_mutex); + std::lock_guard guard(m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) { // it is now killed @@ -303,7 +303,7 @@ GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid) // check one more time after the final usleep { - Mutex::Locker locker (m_spawned_pids_mutex); + std::lock_guard guard(m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) return true; } @@ -315,7 +315,7 @@ GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid) for (size_t i=0; i<10; ++i) { { - Mutex::Locker locker (m_spawned_pids_mutex); + std::lock_guard guard(m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) { // it is now killed @@ -328,7 +328,7 @@ GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid) // check one more time after the final usleep // Scope for locker { - Mutex::Locker locker (m_spawned_pids_mutex); + std::lock_guard guard(m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) return true; } @@ -442,20 +442,9 @@ GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(StringExtractorGDBRemo bool GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped (lldb::pid_t pid) { - Mutex::Locker locker (m_spawned_pids_mutex); + std::lock_guard guard(m_spawned_pids_mutex); FreePortForProcess(pid); - return m_spawned_pids.erase(pid) > 0; -} - -bool -GDBRemoteCommunicationServerPlatform::ReapDebugserverProcess (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 -{ - GDBRemoteCommunicationServerPlatform *server = (GDBRemoteCommunicationServerPlatform *)callback_baton; - server->DebugserverProcessReaped (pid); + m_spawned_pids.erase(pid); return true; } @@ -469,9 +458,11 @@ GDBRemoteCommunicationServerPlatform::LaunchProcess () // generally be what happens since we need to reap started // processes. if (!m_process_launch_info.GetMonitorProcessCallback ()) - m_process_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false); + m_process_launch_info.SetMonitorProcessCallback( + std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, this, std::placeholders::_1), + false); - Error error = m_platform_sp->LaunchProcess (m_process_launch_info); + Error error = Host::LaunchProcess(m_process_launch_info); if (!error.Success ()) { fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0)); @@ -486,7 +477,7 @@ GDBRemoteCommunicationServerPlatform::LaunchProcess () if (pid != LLDB_INVALID_PROCESS_ID) { // add to spawned pids - Mutex::Locker locker (m_spawned_pids_mutex); + std::lock_guard guard(m_spawned_pids_mutex); m_spawned_pids.insert(pid); } diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h index 1fe7207d2bc2..1f4d08c64e00 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h @@ -13,6 +13,7 @@ // C Includes // C++ Includes #include +#include #include // Other libraries and framework includes @@ -82,9 +83,8 @@ public: protected: const Socket::SocketProtocol m_socket_protocol; const std::string m_socket_scheme; - Mutex m_spawned_pids_mutex; + std::recursive_mutex m_spawned_pids_mutex; std::set m_spawned_pids; - lldb::PlatformSP m_platform_sp; PortMap m_port_map; uint16_t m_port_offset; @@ -121,13 +121,6 @@ private: bool DebugserverProcessReaped (lldb::pid_t pid); - static bool - ReapDebugserverProcess (void *callback_baton, - lldb::pid_t pid, - bool exited, - int signal, - int status); - static const FileSpec& GetDomainSocketDir(); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index b0a1eaaeb79c..e5b347c9f72d 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -198,10 +198,11 @@ bool GDBRemoteRegisterContext::GetPrimordialRegister(const RegisterInfo *reg_info, GDBRemoteCommunicationClient &gdb_comm) { - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + const uint32_t lldb_reg = reg_info->kinds[eRegisterKindLLDB]; + const uint32_t remote_reg = reg_info->kinds[eRegisterKindProcessPlugin]; StringExtractorGDBRemote response; - if (gdb_comm.ReadRegister(m_thread.GetProtocolID(), reg, response)) - return PrivateSetRegisterValue (reg, response); + if (gdb_comm.ReadRegister(m_thread.GetProtocolID(), remote_reg, response)) + return PrivateSetRegisterValue (lldb_reg, response); return false; } @@ -316,7 +317,7 @@ GDBRemoteRegisterContext::SetPrimordialRegister(const RegisterInfo *reg_info, StreamString packet; StringExtractorGDBRemote response; const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - packet.Printf ("P%x=", reg); + packet.Printf ("P%x=", reg_info->kinds[eRegisterKindProcessPlugin]); packet.PutBytesAsRawHex8 (m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size), reg_info->byte_size, endian::InlHostByteOrder(), @@ -813,7 +814,7 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data if (restore_src) { StreamString packet; - packet.Printf ("P%x=", reg); + packet.Printf ("P%x=", reg_info->kinds[eRegisterKindProcessPlugin]); packet.PutBytesAsRawHex8 (restore_src, reg_byte_size, endian::InlHostByteOrder(), @@ -836,7 +837,7 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data if (write_reg) { StreamString packet; - packet.Printf ("P%x=", reg); + packet.Printf ("P%x=", reg_info->kinds[eRegisterKindProcessPlugin]); packet.PutBytesAsRawHex8 (restore_src, reg_byte_size, endian::InlHostByteOrder(), @@ -894,7 +895,7 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data continue; } StreamString packet; - packet.Printf ("P%x=", reg_info->kinds[eRegisterKindLLDB]); + packet.Printf ("P%x=", reg_info->kinds[eRegisterKindProcessPlugin]); 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()); diff --git a/source/Plugins/Process/gdb-remote/Makefile b/source/Plugins/Process/gdb-remote/Makefile deleted file mode 100644 index 8a9b61077875..000000000000 --- a/source/Plugins/Process/gdb-remote/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Process/gdb-remote/Makefile -------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginProcessGDBRemote -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 856ea35aef99..4d56f6ea3ba1 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -223,11 +223,11 @@ ProcessGDBRemote::Terminate() lldb::ProcessSP -ProcessGDBRemote::CreateInstance (lldb::TargetSP target_sp, Listener &listener, const FileSpec *crash_file_path) +ProcessGDBRemote::CreateInstance (lldb::TargetSP target_sp, ListenerSP listener_sp, const FileSpec *crash_file_path) { lldb::ProcessSP process_sp; if (crash_file_path == NULL) - process_sp.reset (new ProcessGDBRemote (target_sp, listener)); + process_sp.reset (new ProcessGDBRemote (target_sp, listener_sp)); return process_sp; } @@ -267,51 +267,51 @@ ProcessGDBRemote::CanDebug (lldb::TargetSP target_sp, bool plugin_specified_by_n //---------------------------------------------------------------------- // ProcessGDBRemote constructor //---------------------------------------------------------------------- -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_thread_pcs (), - m_jstopinfo_sp (), - m_jthreadsinfo_sp (), - m_continue_c_tids (), - m_continue_C_tids (), - m_continue_s_tids (), - m_continue_S_tids (), - m_max_memory_size (0), - m_remote_stub_max_memory_size (0), - m_addr_to_mmap_size (), - m_thread_create_bp_sp (), - m_waiting_for_attach (false), - m_destroy_tried_resuming (false), - m_command_sp (), - m_breakpoint_pc_offset (0), - m_initial_tid (LLDB_INVALID_THREAD_ID) +ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, ListenerSP listener_sp) + : Process(target_sp, listener_sp), + m_flags(0), + m_gdb_comm(), + m_debugserver_pid(LLDB_INVALID_PROCESS_ID), + m_last_stop_packet_mutex(), + m_register_info(), + m_async_broadcaster(NULL, "lldb.process.gdb-remote.async-broadcaster"), + m_async_listener_sp(Listener::MakeListener("lldb.process.gdb-remote.async-listener")), + m_async_thread_state_mutex(), + m_thread_ids(), + m_thread_pcs(), + m_jstopinfo_sp(), + m_jthreadsinfo_sp(), + m_continue_c_tids(), + m_continue_C_tids(), + m_continue_s_tids(), + m_continue_S_tids(), + m_max_memory_size(0), + m_remote_stub_max_memory_size(0), + m_addr_to_mmap_size(), + m_thread_create_bp_sp(), + m_waiting_for_attach(false), + m_destroy_tried_resuming(false), + m_command_sp(), + m_breakpoint_pc_offset(0), + m_initial_tid(LLDB_INVALID_THREAD_ID) { - 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"); + 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)); + 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 (m_async_listener_sp->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) + const uint32_t gdb_event_mask = + Communication::eBroadcastBitReadThreadDidExit | GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify; + if (m_async_listener_sp->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__); @@ -500,7 +500,21 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) } } - if (GetGDBServerRegisterInfo ()) + const ArchSpec &target_arch = GetTarget().GetArchitecture(); + const ArchSpec &remote_host_arch = m_gdb_comm.GetHostArchitecture(); + const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture(); + + // Use the process' architecture instead of the host arch, if available + ArchSpec arch_to_use; + if (remote_process_arch.IsValid ()) + arch_to_use = remote_process_arch; + else + arch_to_use = remote_host_arch; + + if (!arch_to_use.IsValid()) + arch_to_use = target_arch; + + if (GetGDBServerRegisterInfo (arch_to_use)) return; char packet[128]; @@ -640,7 +654,12 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) reg_info.invalidate_regs = invalidate_regs.data(); } - AugmentRegisterInfoViaABI (reg_info, reg_name, GetABI ()); + // We have to make a temporary ABI here, and not use the GetABI because this code + // gets called in DidAttach, when the target architecture (and consequently the ABI we'll get from + // the process) may be wrong. + ABISP abi_to_use = ABI::FindPlugin(arch_to_use); + + AugmentRegisterInfoViaABI (reg_info, reg_name, abi_to_use); m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name); } @@ -668,22 +687,11 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) // add composite registers to the existing primordial ones. bool from_scratch = (m_register_info.GetNumRegisters() == 0); - const ArchSpec &target_arch = GetTarget().GetArchitecture(); - const ArchSpec &remote_host_arch = m_gdb_comm.GetHostArchitecture(); - const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture(); - - // Use the process' architecture instead of the host arch, if available - ArchSpec remote_arch; - if (remote_process_arch.IsValid ()) - remote_arch = remote_process_arch; - else - remote_arch = remote_host_arch; - if (!target_arch.IsValid()) { - if (remote_arch.IsValid() - && (remote_arch.GetMachine() == llvm::Triple::arm || remote_arch.GetMachine() == llvm::Triple::thumb) - && remote_arch.GetTriple().getVendor() == llvm::Triple::Apple) + if (arch_to_use.IsValid() + && (arch_to_use.GetMachine() == llvm::Triple::arm || arch_to_use.GetMachine() == llvm::Triple::thumb) + && arch_to_use.GetTriple().getVendor() == llvm::Triple::Apple) m_register_info.HardcodeARMRegisters(from_scratch); } else if (target_arch.GetMachine() == llvm::Triple::arm @@ -1360,10 +1368,10 @@ ProcessGDBRemote::DoResume () if (log) log->Printf ("ProcessGDBRemote::Resume()"); - Listener listener ("gdb-remote.resume-packet-sent"); - if (listener.StartListeningForEvents (&m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent)) + ListenerSP listener_sp (Listener::MakeListener("gdb-remote.resume-packet-sent")); + if (listener_sp->StartListeningForEvents (&m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent)) { - listener.StartListeningForEvents (&m_async_broadcaster, ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit); + listener_sp->StartListeningForEvents (&m_async_broadcaster, ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit); const size_t num_threads = GetThreadList().GetSize(); @@ -1595,7 +1603,7 @@ ProcessGDBRemote::DoResume () m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (continue_packet.GetData(), continue_packet.GetSize())); - if (listener.WaitForEvent (&timeout, event_sp) == false) + if (listener_sp->WaitForEvent (&timeout, event_sp) == false) { error.SetErrorString("Resume timed out."); if (log) @@ -1638,7 +1646,7 @@ ProcessGDBRemote::HandleStopReplySequence () void ProcessGDBRemote::ClearThreadIDList () { - Mutex::Locker locker(m_thread_list_real.GetMutex()); + std::lock_guard guard(m_thread_list_real.GetMutex()); m_thread_ids.clear(); m_thread_pcs.clear(); } @@ -1688,7 +1696,7 @@ ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue (std::string &value) bool ProcessGDBRemote::UpdateThreadIDList () { - Mutex::Locker locker(m_thread_list_real.GetMutex()); + std::lock_guard guard(m_thread_list_real.GetMutex()); if (m_jthreadsinfo_sp) { @@ -1721,8 +1729,8 @@ ProcessGDBRemote::UpdateThreadIDList () // Lock the thread stack while we access it //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)) + std::unique_lock stop_stack_lock(m_last_stop_packet_mutex, std::defer_lock); + if (stop_stack_lock.try_lock()) { // Get the number of stop packets on the stack int nItems = m_stop_packet_stack.size(); @@ -1832,7 +1840,7 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new } } } - new_thread_list.AddThread(thread_sp); + new_thread_list.AddThreadSortedByIndexID (thread_sp); } } @@ -1936,7 +1944,7 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid, // m_thread_list_real does have its own mutex, but we need to // hold onto the mutex between the call to m_thread_list_real.FindThreadByID(...) // and the m_thread_list_real.AddThread(...) so it doesn't change on us - Mutex::Locker locker (m_thread_list_real.GetMutex ()); + std::lock_guard guard(m_thread_list_real.GetMutex()); thread_sp = m_thread_list_real.FindThreadByProtocolID(tid, false); if (!thread_sp) @@ -2001,7 +2009,18 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid, { if (reason.compare("trace") == 0) { - thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); + addr_t pc = thread_sp->GetRegisterContext()->GetPC(); + lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); + + // If the current pc is a breakpoint site then the StopInfo should be set to Breakpoint + // Otherwise, it will be set to Trace. + if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get())) + { + thread_sp->SetStopInfo( + StopInfo::CreateStopReasonWithBreakpointSiteID(*thread_sp, bp_site_sp->GetID())); + } + else + thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); handled = true; } else if (reason.compare("breakpoint") == 0) @@ -2040,7 +2059,8 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid, { WatchpointSP wp_sp; ArchSpec::Core core = GetTarget().GetArchitecture().GetCore(); - if (core >= ArchSpec::kCore_mips_first && core <= ArchSpec::kCore_mips_last) + if ((core >= ArchSpec::kCore_mips_first && core <= ArchSpec::kCore_mips_last) || + (core >= ArchSpec::eCore_arm_generic && core <= ArchSpec::eCore_arm_aarch64)) wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_hit_addr); if (!wp_sp) wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr); @@ -2070,6 +2090,23 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid, handled = true; } } + else if (!signo) + { + addr_t pc = thread_sp->GetRegisterContext()->GetPC(); + lldb::BreakpointSiteSP bp_site_sp = + thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); + + // If the current pc is a breakpoint site then the StopInfo should be set to Breakpoint + // even though the remote stub did not set it as such. This can happen when + // the thread is involuntarily interrupted (e.g. due to stops on other + // threads) just as it is about to execute the breakpoint instruction. + if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get())) + { + thread_sp->SetStopInfo( + StopInfo::CreateStopReasonWithBreakpointSiteID(*thread_sp, bp_site_sp->GetID())); + handled = true; + } + } if (!handled && signo && did_exec == false) { @@ -2404,7 +2441,8 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) } else if (key.compare("threads") == 0) { - Mutex::Locker locker(m_thread_list_real.GetMutex()); + std::lock_guard guard(m_thread_list_real.GetMutex()); + m_thread_ids.clear(); // A comma separated list of all threads in the current // process that includes the thread for this stop reply @@ -2627,7 +2665,8 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) void ProcessGDBRemote::RefreshStateAfterStop () { - Mutex::Locker locker(m_thread_list_real.GetMutex()); + std::lock_guard guard(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 @@ -2637,7 +2676,7 @@ ProcessGDBRemote::RefreshStateAfterStop () // Scope for the lock { // Lock the thread stack while we access it - Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex); + std::lock_guard guard(m_last_stop_packet_mutex); // Get the number of stop packets on the stack int nItems = m_stop_packet_stack.size(); // Iterate over them @@ -2782,7 +2821,7 @@ ProcessGDBRemote::DoDestroy () ThreadList &threads = GetThreadList(); { - Mutex::Locker locker(threads.GetMutex()); + std::lock_guard guard(threads.GetMutex()); size_t num_threads = threads.GetSize(); for (size_t i = 0; i < num_threads; i++) @@ -2817,7 +2856,7 @@ ProcessGDBRemote::DoDestroy () // have to run the risk of letting those threads proceed a bit. { - Mutex::Locker locker(threads.GetMutex()); + std::lock_guard guard(threads.GetMutex()); size_t num_threads = threads.GetSize(); for (size_t i = 0; i < num_threads; i++) @@ -2939,7 +2978,7 @@ ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response) // Scope the lock { // Lock the thread stack while we access it - Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex); + std::lock_guard guard(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. @@ -3119,35 +3158,33 @@ ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &er Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_EXPRESSIONS)); addr_t allocated_addr = LLDB_INVALID_ADDRESS; - LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory(); - switch (supported) + if (m_gdb_comm.SupportsAllocDeallocMemory() != eLazyBoolNo) { - case eLazyBoolCalculate: - case eLazyBoolYes: - allocated_addr = m_gdb_comm.AllocateMemory (size, permissions); - if (allocated_addr != LLDB_INVALID_ADDRESS || supported == eLazyBoolYes) - return allocated_addr; + allocated_addr = m_gdb_comm.AllocateMemory (size, permissions); + if (allocated_addr != LLDB_INVALID_ADDRESS || m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolYes) + return allocated_addr; + } - case eLazyBoolNo: - // Call mmap() to create memory in the inferior.. - 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; - else - { - allocated_addr = LLDB_INVALID_ADDRESS; - if (log) - log->Printf ("ProcessGDBRemote::%s no direct stub support for memory allocation, and InferiorCallMmap also failed - is stub missing register context save/restore capability?", __FUNCTION__); - } - break; + if (m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolNo) + { + // Call mmap() to create memory in the inferior.. + 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; + else + { + allocated_addr = LLDB_INVALID_ADDRESS; + if (log) + log->Printf ("ProcessGDBRemote::%s no direct stub support for memory allocation, and InferiorCallMmap also failed - is stub missing register context save/restore capability?", __FUNCTION__); + } } if (allocated_addr == LLDB_INVALID_ADDRESS) @@ -3273,7 +3310,8 @@ ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site) if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware) && (!bp_site->HardwareRequired())) { // Try to send off a software breakpoint packet ($Z0) - if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size) == 0) + uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size); + if (error_no == 0) { // The breakpoint was placed successfully bp_site->SetEnabled(true); @@ -3289,7 +3327,13 @@ ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site) // with the error code. If they are now unsupported, then we would like to fall through // and try another form of breakpoint. if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) + { + if (error_no != UINT8_MAX) + error.SetErrorStringWithFormat("error: %d sending the breakpoint request", errno); + else + error.SetErrorString("error sending the breakpoint request"); return error; + } // We reach here when software breakpoints have been found to be unsupported. For future // calls to set a breakpoint, we will not attempt to set a breakpoint with a type that is @@ -3306,7 +3350,8 @@ ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site) if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) { // Try to send off a hardware breakpoint packet ($Z1) - if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, true, addr, bp_op_size) == 0) + uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, true, addr, bp_op_size); + if (error_no == 0) { // The breakpoint was placed successfully bp_site->SetEnabled(true); @@ -3318,7 +3363,13 @@ ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site) if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) { // Unable to set this hardware breakpoint - error.SetErrorString("failed to set hardware breakpoint (hardware breakpoint resources might be exhausted or unavailable)"); + if (error_no != UINT8_MAX) + error.SetErrorStringWithFormat("error: %d sending the hardware breakpoint request " + "(hardware breakpoint resources might be exhausted or unavailable)", + error_no); + else + error.SetErrorString("error sending the hardware breakpoint request (hardware breakpoint resources " + "might be exhausted or unavailable)"); return error; } @@ -3550,6 +3601,8 @@ ProcessGDBRemote::EstablishConnectionIfNeeded (const ProcessInfo &process_info) Error ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info) { + using namespace std::placeholders; // For _1, _2, etc. + Error error; if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID) { @@ -3561,7 +3614,9 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info // special terminal key sequences (^C) don't affect debugserver. debugserver_launch_info.SetLaunchInSeparateProcessGroup(true); - debugserver_launch_info.SetMonitorProcessCallback (MonitorDebugserverProcess, this, false); + const std::weak_ptr this_wp = std::static_pointer_cast(shared_from_this()); + debugserver_launch_info.SetMonitorProcessCallback(std::bind(MonitorDebugserverProcess, this_wp, _1, _2, _3, _4), + false); debugserver_launch_info.SetUserID(process_info.GetUserID()); #if defined (__APPLE__) && (defined (__arm__) || defined (__arm64__) || defined (__aarch64__)) @@ -3623,91 +3678,58 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info } bool -ProcessGDBRemote::MonitorDebugserverProcess -( - void *callback_baton, - lldb::pid_t debugserver_pid, - bool exited, // True if the process did exit - int signo, // Zero for no signal - int exit_status // Exit value of process if signal is zero -) +ProcessGDBRemote::MonitorDebugserverProcess(std::weak_ptr process_wp, lldb::pid_t debugserver_pid, + bool exited, // True if the process did exit + int signo, // Zero for no signal + int exit_status // Exit value of process if signal is zero + ) { - // The baton is a "ProcessGDBRemote *". Now this class might be gone - // and might not exist anymore, so we need to carefully try to get the - // target for this process first since we have a race condition when - // we are done running between getting the notice that the inferior - // process has died and the debugserver that was debugging this process. - // In our test suite, we are also continually running process after - // process, so we must be very careful to make sure: - // 1 - process object hasn't been deleted already - // 2 - that a new process object hasn't been recreated in its place - // "debugserver_pid" argument passed in is the process ID for // debugserver that we are tracking... Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + const bool handled = true; - ProcessGDBRemote *process = (ProcessGDBRemote *)callback_baton; - - // Get a shared pointer to the target that has a matching process pointer. - // This target could be gone, or the target could already have a new process - // object inside of it - TargetSP target_sp (Debugger::FindTargetWithProcess(process)); + if (log) + log->Printf("ProcessGDBRemote::%s(process_wp, pid=%" PRIu64 ", signo=%i (0x%x), exit_status=%i)", __FUNCTION__, + debugserver_pid, signo, signo, exit_status); + std::shared_ptr process_sp = process_wp.lock(); if (log) - log->Printf ("ProcessGDBRemote::MonitorDebugserverProcess (baton=%p, pid=%" PRIu64 ", signo=%i (0x%x), exit_status=%i)", callback_baton, debugserver_pid, signo, signo, exit_status); - - if (target_sp) - { - // We found a process in a target that matches, but another thread - // might be in the process of launching a new process that will - // soon replace it, so get a shared pointer to the process so we - // can keep it alive. - ProcessSP process_sp (target_sp->GetProcessSP()); - // Now we have a shared pointer to the process that can't go away on us - // so we now make sure it was the same as the one passed in, and also make - // sure that our previous "process *" didn't get deleted and have a new - // "process *" created in its place with the same pointer. To verify this - // we make sure the process has our debugserver process ID. If we pass all - // of these tests, then we are sure that this process is the one we were - // looking for. - if (process_sp && process == process_sp.get() && process->m_debugserver_pid == debugserver_pid) + log->Printf("ProcessGDBRemote::%s(process = %p)", __FUNCTION__, static_cast(process_sp.get())); + if (!process_sp || process_sp->m_debugserver_pid != debugserver_pid) + return handled; + + // Sleep for a half a second to make sure our inferior process has + // time to set its exit status before we set it incorrectly when + // both the debugserver and the inferior process shut down. + usleep(500000); + // If our process hasn't yet exited, debugserver might have died. + // If the process did exit, then we are reaping it. + const StateType state = process_sp->GetState(); + + if (state != eStateInvalid && state != eStateUnloaded && state != eStateExited && state != eStateDetached) + { + char error_str[1024]; + if (signo) { - // Sleep for a half a second to make sure our inferior process has - // time to set its exit status before we set it incorrectly when - // both the debugserver and the inferior process shut down. - usleep (500000); - // If our process hasn't yet exited, debugserver might have died. - // If the process did exit, the we are reaping it. - const StateType state = process->GetState(); - - if (process->m_debugserver_pid != LLDB_INVALID_PROCESS_ID && - state != eStateInvalid && - state != eStateUnloaded && - state != eStateExited && - state != eStateDetached) - { - char error_str[1024]; - if (signo) - { - const char *signal_cstr = process->GetUnixSignals()->GetSignalAsCString(signo); - if (signal_cstr) - ::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with signal %s", signal_cstr); - else - ::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with signal %i", signo); - } - else - { - ::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with an exit status of 0x%8.8x", exit_status); - } - - process->SetExitStatus (-1, error_str); - } - // Debugserver has exited we need to let our ProcessGDBRemote - // know that it no longer has a debugserver instance - process->m_debugserver_pid = LLDB_INVALID_PROCESS_ID; + const char *signal_cstr = process_sp->GetUnixSignals()->GetSignalAsCString(signo); + if (signal_cstr) + ::snprintf(error_str, sizeof(error_str), DEBUGSERVER_BASENAME " died with signal %s", signal_cstr); + else + ::snprintf(error_str, sizeof(error_str), DEBUGSERVER_BASENAME " died with signal %i", signo); } + else + { + ::snprintf(error_str, sizeof(error_str), DEBUGSERVER_BASENAME " died with an exit status of 0x%8.8x", + exit_status); + } + + process_sp->SetExitStatus(-1, error_str); } - return true; + // Debugserver has exited we need to let our ProcessGDBRemote + // know that it no longer has a debugserver instance + process_sp->m_debugserver_pid = LLDB_INVALID_PROCESS_ID; + return handled; } void @@ -3756,7 +3778,7 @@ ProcessGDBRemote::StartAsyncThread () if (log) log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__); - Mutex::Locker start_locker(m_async_thread_state_mutex); + std::lock_guard guard(m_async_thread_state_mutex); if (!m_async_thread.IsJoinable()) { // Create a thread that watches our internal state and controls which @@ -3778,7 +3800,7 @@ ProcessGDBRemote::StopAsyncThread () if (log) log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__); - Mutex::Locker start_locker(m_async_thread_state_mutex); + std::lock_guard guard(m_async_thread_state_mutex); if (m_async_thread.IsJoinable()) { m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit); @@ -3838,7 +3860,7 @@ ProcessGDBRemote::AsyncThread (void *arg) { 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 (process->m_async_listener_sp->WaitForEvent (NULL, event_sp)) { const uint32_t event_type = event_sp->GetType(); if (event_sp->BroadcasterIs (&process->m_async_broadcaster)) @@ -4153,6 +4175,7 @@ ProcessGDBRemote::GetExtendedInfoForThread (lldb::tid_t tid) packet << (char) (0x7d ^ 0x20); StringExtractorGDBRemote response; + response.SetResponseValidatorToJSON(); if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == GDBRemoteCommunication::PacketResult::Success) { StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType(); @@ -4194,6 +4217,7 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres packet << (char) (0x7d ^ 0x20); StringExtractorGDBRemote response; + response.SetResponseValidatorToJSON(); if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == GDBRemoteCommunication::PacketResult::Success) { StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType(); @@ -4336,14 +4360,11 @@ struct GdbServerTargetInfo }; bool -ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp) +ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp, uint32_t &cur_reg_num, uint32_t ®_offset) { if (!feature_node) return false; - uint32_t cur_reg_num = 0; - uint32_t reg_offset = 0; - feature_node.ForEachChildElementWithName("reg", [&target_info, &dyn_reg_info, &cur_reg_num, ®_offset, &abi_sp](const XMLNode ®_node) -> bool { std::string gdb_group; std::string gdb_type; @@ -4520,7 +4541,7 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot // return: 'true' on success // 'false' on failure bool -ProcessGDBRemote::GetGDBServerRegisterInfo () +ProcessGDBRemote::GetGDBServerRegisterInfo (ArchSpec &arch_to_use) { // Make sure LLDB has an XML parser it can use first if (!XMLDocument::XMLEnabled()) @@ -4599,9 +4620,16 @@ ProcessGDBRemote::GetGDBServerRegisterInfo () return true; // Keep iterating through all children of the target_node }); + // Initialize these outside of ParseRegisters, since they should not be reset inside each include feature + uint32_t cur_reg_num = 0; + uint32_t reg_offset = 0; + + // Don't use Process::GetABI, this code gets called from DidAttach, and in that context we haven't + // set the Target's architecture yet, so the ABI is also potentially incorrect. + ABISP abi_to_use_sp = ABI::FindPlugin(arch_to_use); if (feature_node) { - ParseRegisters(feature_node, target_info, this->m_register_info, GetABI()); + ParseRegisters(feature_node, target_info, this->m_register_info, abi_to_use_sp, cur_reg_num, reg_offset); } for (const auto &include : target_info.includes) @@ -4619,10 +4647,10 @@ 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, GetABI()); + ParseRegisters(include_feature_node, target_info, this->m_register_info, abi_to_use_sp, cur_reg_num, reg_offset); } } - this->m_register_info.Finalize(GetTarget().GetArchitecture()); + this->m_register_info.Finalize(arch_to_use); } } @@ -4784,25 +4812,14 @@ ProcessGDBRemote::GetLoadedModuleList (LoadedModuleInfoList & list) } lldb::ModuleSP -ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr, bool value_is_offset) +ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t link_map, + lldb::addr_t base_addr, bool value_is_offset) { - Target &target = m_process->GetTarget(); - ModuleList &modules = target.GetImages(); - ModuleSP module_sp; - - bool changed = false; - - ModuleSpec module_spec (file, target.GetArchitecture()); - if ((module_sp = modules.FindFirstModule (module_spec))) - { - module_sp->SetLoadAddress (target, base_addr, value_is_offset, changed); - } - else if ((module_sp = target.GetSharedModule (module_spec))) - { - module_sp->SetLoadAddress (target, base_addr, value_is_offset, changed); - } + DynamicLoader *loader = GetDynamicLoader(); + if (!loader) + return nullptr; - return module_sp; + return loader->LoadModuleAtAddress(file, link_map, base_addr, value_is_offset); } size_t @@ -4821,6 +4838,7 @@ ProcessGDBRemote::LoadModules (LoadedModuleInfoList &module_list) { std::string mod_name; lldb::addr_t mod_base; + lldb::addr_t link_map; bool mod_base_is_offset; bool valid = true; @@ -4830,15 +4848,12 @@ ProcessGDBRemote::LoadModules (LoadedModuleInfoList &module_list) if (!valid) continue; - // hack (cleaner way to get file name only?) (win/unix compat?) - size_t marker = mod_name.rfind ('/'); - if (marker == std::string::npos) - marker = 0; - else - marker += 1; + if (!modInfo.get_link_map (link_map)) + link_map = LLDB_INVALID_ADDRESS; - FileSpec file (mod_name.c_str()+marker, true); - lldb::ModuleSP module_sp = LoadModuleAtAddress (file, mod_base, mod_base_is_offset); + FileSpec file (mod_name.c_str(), true); + lldb::ModuleSP module_sp = LoadModuleAtAddress (file, link_map, mod_base, + mod_base_is_offset); if (module_sp.get()) new_modules.Append (module_sp); @@ -4846,7 +4861,30 @@ ProcessGDBRemote::LoadModules (LoadedModuleInfoList &module_list) if (new_modules.GetSize() > 0) { + ModuleList removed_modules; Target &target = GetTarget(); + ModuleList &loaded_modules = m_process->GetTarget().GetImages(); + + for (size_t i = 0; i < loaded_modules.GetSize(); ++i) + { + const lldb::ModuleSP loaded_module = loaded_modules.GetModuleAtIndex(i); + + bool found = false; + for (size_t j = 0; j < new_modules.GetSize(); ++j) + { + if (new_modules.GetModuleAtIndex(j).get() == loaded_module.get()) + found = true; + } + + // The main executable will never be included in libraries-svr4, don't remove it + if (!found && loaded_module.get() != target.GetExecutableModulePointer()) + { + removed_modules.Append (loaded_module); + } + } + + loaded_modules.Remove (removed_modules); + m_process->GetTarget().ModulesDidUnload (removed_modules, false); new_modules.ForEach ([&target](const lldb::ModuleSP module_sp) -> bool { @@ -4862,13 +4900,11 @@ ProcessGDBRemote::LoadModules (LoadedModuleInfoList &module_list) return false; }); - ModuleList &loaded_modules = m_process->GetTarget().GetImages(); loaded_modules.AppendIfNeeded (new_modules); m_process->GetTarget().ModulesDidLoad (new_modules); } return new_modules.GetSize(); - } size_t @@ -5230,11 +5266,9 @@ public: class CommandObjectMultiwordProcessGDBRemote : public CommandObjectMultiword { public: - CommandObjectMultiwordProcessGDBRemote (CommandInterpreter &interpreter) : - CommandObjectMultiword (interpreter, - "process plugin", - "A set of commands for operating on a ProcessGDBRemote process.", - "process plugin []") + CommandObjectMultiwordProcessGDBRemote(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "process plugin", "Commands for operating on a ProcessGDBRemote process.", + "process plugin []") { LoadSubCommand ("packet", CommandObjectSP (new CommandObjectProcessGDBRemotePacket (interpreter))); } diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index b48edd836a74..6d373965fc42 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -14,6 +14,7 @@ // C++ Includes #include #include +#include #include #include @@ -45,13 +46,13 @@ class ThreadGDBRemote; class ProcessGDBRemote : public Process { public: - ProcessGDBRemote(lldb::TargetSP target_sp, Listener &listener); + ProcessGDBRemote(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp); ~ProcessGDBRemote() override; static lldb::ProcessSP CreateInstance (lldb::TargetSP target_sp, - Listener &listener, + lldb::ListenerSP listener_sp, const FileSpec *crash_file_path); static void @@ -279,12 +280,12 @@ protected: GDBRemoteCommunicationClient m_gdb_comm; std::atomic m_debugserver_pid; std::vector m_stop_packet_stack; // The stop packet stack replaces the last stop packet variable - Mutex m_last_stop_packet_mutex; + std::recursive_mutex m_last_stop_packet_mutex; GDBRemoteDynamicRegisterInfo m_register_info; Broadcaster m_async_broadcaster; - Listener m_async_listener; + lldb::ListenerSP m_async_listener_sp; HostThread m_async_thread; - Mutex m_async_thread_state_mutex; + std::recursive_mutex m_async_thread_state_mutex; typedef std::vector tid_collection; typedef std::vector< std::pair > tid_sig_collection; typedef std::map MMapMap; @@ -405,11 +406,8 @@ protected: AsyncThread (void *arg); static bool - MonitorDebugserverProcess (void *callback_baton, - lldb::pid_t pid, - bool exited, - int signo, - int exit_status); + MonitorDebugserverProcess(std::weak_ptr process_wp, lldb::pid_t pid, bool exited, int signo, + int exit_status); lldb::StateType SetThreadStopInfo (StringExtractor& stop_packet); @@ -461,14 +459,15 @@ protected: // Query remote GDBServer for register information bool - GetGDBServerRegisterInfo (); + GetGDBServerRegisterInfo (ArchSpec &arch); // Query remote GDBServer for a detailed loaded library list Error GetLoadedModuleList (LoadedModuleInfoList &); lldb::ModuleSP - LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr, bool value_is_offset); + LoadModuleAtAddress (const FileSpec &file, lldb::addr_t link_map, lldb::addr_t base_addr, + bool value_is_offset); private: //------------------------------------------------------------------ diff --git a/source/Plugins/Process/mach-core/Makefile b/source/Plugins/Process/mach-core/Makefile deleted file mode 100644 index 6db849872267..000000000000 --- a/source/Plugins/Process/mach-core/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Process/mach-core/Makefile -----------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginProcessMachCore -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/source/Plugins/Process/mach-core/ProcessMachCore.cpp index b199ec606367..6bf198ca2f37 100644 --- a/source/Plugins/Process/mach-core/ProcessMachCore.cpp +++ b/source/Plugins/Process/mach-core/ProcessMachCore.cpp @@ -18,13 +18,15 @@ // Other libraries and framework includes #include "lldb/Core/DataBuffer.h" #include "lldb/Core/Debugger.h" -#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" #include "lldb/Core/State.h" #include "lldb/Host/Host.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" @@ -64,7 +66,7 @@ ProcessMachCore::Terminate() lldb::ProcessSP -ProcessMachCore::CreateInstance (lldb::TargetSP target_sp, Listener &listener, const FileSpec *crash_file) +ProcessMachCore::CreateInstance (lldb::TargetSP target_sp, ListenerSP listener_sp, const FileSpec *crash_file) { lldb::ProcessSP process_sp; if (crash_file) @@ -80,7 +82,7 @@ ProcessMachCore::CreateInstance (lldb::TargetSP target_sp, Listener &listener, c if (ObjectFileMachO::ParseHeader(data, &data_offset, mach_header)) { if (mach_header.filetype == llvm::MachO::MH_CORE) - process_sp.reset(new ProcessMachCore (target_sp, listener, *crash_file)); + process_sp.reset(new ProcessMachCore (target_sp, listener_sp, *crash_file)); } } @@ -121,14 +123,15 @@ ProcessMachCore::CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_nam //---------------------------------------------------------------------- // ProcessMachCore constructor //---------------------------------------------------------------------- -ProcessMachCore::ProcessMachCore(lldb::TargetSP target_sp, Listener &listener, const FileSpec &core_file) : - Process (target_sp, listener), - m_core_aranges (), - m_core_module_sp (), - m_core_file (core_file), - m_dyld_addr (LLDB_INVALID_ADDRESS), - m_mach_kernel_addr (LLDB_INVALID_ADDRESS), - m_dyld_plugin_name () +ProcessMachCore::ProcessMachCore(lldb::TargetSP target_sp, ListenerSP listener_sp, const FileSpec &core_file) + : Process(target_sp, listener_sp), + m_core_aranges(), + m_core_range_infos(), + m_core_module_sp(), + m_core_file(core_file), + m_dyld_addr(LLDB_INVALID_ADDRESS), + m_mach_kernel_addr(LLDB_INVALID_ADDRESS), + m_dyld_plugin_name() { } @@ -163,6 +166,7 @@ ProcessMachCore::GetPluginVersion() bool ProcessMachCore::GetDynamicLoaderAddress (lldb::addr_t addr) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_PROCESS)); llvm::MachO::mach_header header; Error error; if (DoReadMemory (addr, &header, sizeof(header), error) != sizeof(header)) @@ -194,6 +198,8 @@ ProcessMachCore::GetDynamicLoaderAddress (lldb::addr_t addr) case llvm::MachO::MH_DYLINKER: //printf("0x%16.16" PRIx64 ": file_type = MH_DYLINKER\n", vaddr); // Address of dyld "struct mach_header" in the core file + if (log) + log->Printf ("ProcessMachCore::GetDynamicLoaderAddress found a user process dyld binary image at 0x%" PRIx64, addr); m_dyld_addr = addr; return true; @@ -203,6 +209,8 @@ ProcessMachCore::GetDynamicLoaderAddress (lldb::addr_t addr) // is NOT set. If it isn't, then we have a mach_kernel. if ((header.flags & llvm::MachO::MH_DYLDLINK) == 0) { + if (log) + log->Printf ("ProcessMachCore::GetDynamicLoaderAddress found a mach kernel binary image at 0x%" PRIx64, addr); // Address of the mach kernel "struct mach_header" in the core file. m_mach_kernel_addr = addr; return true; @@ -219,6 +227,7 @@ ProcessMachCore::GetDynamicLoaderAddress (lldb::addr_t addr) Error ProcessMachCore::DoLoadCore () { + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_PROCESS)); Error error; if (!m_core_module_sp) { @@ -297,11 +306,21 @@ ProcessMachCore::DoLoadCore () { m_core_aranges.Append(range_entry); } + // Some core files don't fill in the permissions correctly. If that is the case + // assume read + execute so clients don't think the memory is not readable, + // or executable. The memory isn't writable since this plug-in doesn't implement + // DoWriteMemory. + uint32_t permissions = section->GetPermissions(); + if (permissions == 0) + permissions = lldb::ePermissionsReadable | lldb::ePermissionsExecutable; + m_core_range_infos.Append( + VMRangeToPermissions::Entry(section_vm_addr, section->GetByteSize(), permissions)); } } if (!ranges_are_sorted) { m_core_aranges.Sort(); + m_core_range_infos.Sort(); } if (m_dyld_addr == LLDB_INVALID_ADDRESS || m_mach_kernel_addr == LLDB_INVALID_ADDRESS) @@ -314,9 +333,7 @@ ProcessMachCore::DoLoadCore () // later if both are present. const size_t num_core_aranges = m_core_aranges.GetSize(); - for (size_t i = 0; - i < num_core_aranges && (m_dyld_addr == LLDB_INVALID_ADDRESS || m_mach_kernel_addr == LLDB_INVALID_ADDRESS); - ++i) + for (size_t i = 0; i < num_core_aranges; ++i) { const VMRangeToFileOffset::Entry *entry = m_core_aranges.GetEntryAtIndex(i); lldb::addr_t section_vm_addr_start = entry->GetRangeBase(); @@ -330,16 +347,58 @@ ProcessMachCore::DoLoadCore () } } + + if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) + { + // In the case of multiple kernel images found in the core file via exhaustive + // search, we may not pick the correct one. See if the DynamicLoaderDarwinKernel's + // search heuristics might identify the correct one. + // Most of the time, I expect the address from SearchForDarwinKernel() will be the + // same as the address we found via exhaustive search. + + if (GetTarget().GetArchitecture().IsValid() == false && m_core_module_sp.get()) + { + GetTarget().SetArchitecture (m_core_module_sp->GetArchitecture()); + } + + // SearchForDarwinKernel will end up calling back into this this class in the GetImageInfoAddress + // method which will give it the m_mach_kernel_addr/m_dyld_addr it already has. Save that aside + // and set m_mach_kernel_addr/m_dyld_addr to an invalid address temporarily so + // DynamicLoaderDarwinKernel does a real search for the kernel using its own heuristics. + + addr_t saved_mach_kernel_addr = m_mach_kernel_addr; + addr_t saved_user_dyld_addr = m_dyld_addr; + m_mach_kernel_addr = LLDB_INVALID_ADDRESS; + m_dyld_addr = LLDB_INVALID_ADDRESS; + + addr_t better_kernel_address = DynamicLoaderDarwinKernel::SearchForDarwinKernel (this); + + m_mach_kernel_addr = saved_mach_kernel_addr; + m_dyld_addr = saved_user_dyld_addr; + + if (better_kernel_address != LLDB_INVALID_ADDRESS) + { + if (log) + log->Printf ("ProcessMachCore::DoLoadCore: Using the kernel address from DynamicLoaderDarwinKernel"); + m_mach_kernel_addr = better_kernel_address; + } + } + + // If we found both a user-process dyld and a kernel binary, we need to decide // which to prefer. if (GetCorefilePreference() == eKernelCorefile) { if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) { + if (log) + log->Printf ("ProcessMachCore::DoLoadCore: Using kernel corefile image at 0x%" PRIx64, m_mach_kernel_addr); m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); } else if (m_dyld_addr != LLDB_INVALID_ADDRESS) { + if (log) + log->Printf ("ProcessMachCore::DoLoadCore: Using user process dyld image at 0x%" PRIx64, m_dyld_addr); m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); } } @@ -347,10 +406,14 @@ ProcessMachCore::DoLoadCore () { if (m_dyld_addr != LLDB_INVALID_ADDRESS) { + if (log) + log->Printf ("ProcessMachCore::DoLoadCore: Using user process dyld image at 0x%" PRIx64, m_dyld_addr); m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic(); } else if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS) { + if (log) + log->Printf ("ProcessMachCore::DoLoadCore: Using kernel corefile image at 0x%" PRIx64, m_mach_kernel_addr); m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic(); } } @@ -450,25 +513,95 @@ size_t ProcessMachCore::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error) { ObjectFile *core_objfile = m_core_module_sp->GetObjectFile(); + size_t bytes_read = 0; if (core_objfile) { - const VMRangeToFileOffset::Entry *core_memory_entry = m_core_aranges.FindEntryThatContains (addr); - if (core_memory_entry) + //---------------------------------------------------------------------- + // Segments are not always contiguous in mach-o core files. We have core + // files that have segments like: + // Address Size File off File size + // ---------- ---------- ---------- ---------- + // LC_SEGMENT 0x000f6000 0x00001000 0x1d509ee8 0x00001000 --- --- 0 0x00000000 __TEXT + // LC_SEGMENT 0x0f600000 0x00100000 0x1d50aee8 0x00100000 --- --- 0 0x00000000 __TEXT + // LC_SEGMENT 0x000f7000 0x00001000 0x1d60aee8 0x00001000 --- --- 0 0x00000000 __TEXT + // + // Any if the user executes the following command: + // + // (lldb) mem read 0xf6ff0 + // + // We would attempt to read 32 bytes from 0xf6ff0 but would only + // get 16 unless we loop through consecutive memory ranges that are + // contiguous in the address space, but not in the file data. + //---------------------------------------------------------------------- + while (bytes_read < size) { - const addr_t offset = addr - core_memory_entry->GetRangeBase(); - const addr_t bytes_left = core_memory_entry->GetRangeEnd() - addr; - size_t bytes_to_read = size; - if (bytes_to_read > bytes_left) - bytes_to_read = bytes_left; - return core_objfile->CopyData (core_memory_entry->data.GetRangeBase() + offset, bytes_to_read, buf); + const addr_t curr_addr = addr + bytes_read; + const VMRangeToFileOffset::Entry *core_memory_entry = m_core_aranges.FindEntryThatContains(curr_addr); + + if (core_memory_entry) + { + const addr_t offset = curr_addr - core_memory_entry->GetRangeBase(); + const addr_t bytes_left = core_memory_entry->GetRangeEnd() - curr_addr; + const size_t bytes_to_read = std::min(size - bytes_read, (size_t)bytes_left); + const size_t curr_bytes_read = core_objfile->CopyData(core_memory_entry->data.GetRangeBase() + offset, + bytes_to_read, (char *)buf + bytes_read); + if (curr_bytes_read == 0) + break; + bytes_read += curr_bytes_read; + } + else + { + // Only set the error if we didn't read any bytes + if (bytes_read == 0) + error.SetErrorStringWithFormat("core file does not contain 0x%" PRIx64, curr_addr); + break; + } } - else + } + + return bytes_read; +} + +Error +ProcessMachCore::GetMemoryRegionInfo(addr_t load_addr, MemoryRegionInfo ®ion_info) +{ + region_info.Clear(); + const VMRangeToPermissions::Entry *permission_entry = m_core_range_infos.FindEntryThatContainsOrFollows(load_addr); + if (permission_entry) + { + if (permission_entry->Contains(load_addr)) { - error.SetErrorStringWithFormat ("core file does not contain 0x%" PRIx64, addr); + region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase()); + region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd()); + const Flags permissions(permission_entry->data); + region_info.SetReadable(permissions.Test(ePermissionsReadable) ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + region_info.SetWritable(permissions.Test(ePermissionsWritable) ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + region_info.SetExecutable(permissions.Test(ePermissionsExecutable) ? MemoryRegionInfo::eYes + : MemoryRegionInfo::eNo); + region_info.SetMapped(MemoryRegionInfo::eYes); } + else if (load_addr < permission_entry->GetRangeBase()) + { + region_info.GetRange().SetRangeBase(load_addr); + region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase()); + region_info.SetReadable(MemoryRegionInfo::eNo); + region_info.SetWritable(MemoryRegionInfo::eNo); + region_info.SetExecutable(MemoryRegionInfo::eNo); + region_info.SetMapped(MemoryRegionInfo::eNo); + } + return Error(); } - return 0; + + region_info.GetRange().SetRangeBase(load_addr); + region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); + region_info.SetReadable(MemoryRegionInfo::eNo); + region_info.SetWritable(MemoryRegionInfo::eNo); + region_info.SetExecutable(MemoryRegionInfo::eNo); + region_info.SetMapped(MemoryRegionInfo::eNo); + return Error(); } void diff --git a/source/Plugins/Process/mach-core/ProcessMachCore.h b/source/Plugins/Process/mach-core/ProcessMachCore.h index 2de0b772370c..21a0083b2d12 100644 --- a/source/Plugins/Process/mach-core/ProcessMachCore.h +++ b/source/Plugins/Process/mach-core/ProcessMachCore.h @@ -30,14 +30,14 @@ public: // Constructors and Destructors //------------------------------------------------------------------ ProcessMachCore(lldb::TargetSP target_sp, - lldb_private::Listener &listener, + lldb::ListenerSP listener, const lldb_private::FileSpec &core_file); ~ProcessMachCore() override; static lldb::ProcessSP CreateInstance (lldb::TargetSP target_sp, - lldb_private::Listener &listener, + lldb::ListenerSP listener, const lldb_private::FileSpec *crash_file_path); static void @@ -103,7 +103,10 @@ public: size_t DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override; - + + lldb_private::Error + GetMemoryRegionInfo(lldb::addr_t load_addr, lldb_private::MemoryRegionInfo ®ion_info) override; + lldb::addr_t GetImageInfoAddress () override; @@ -131,7 +134,7 @@ private: /// /// If a core file contains both a kernel binary and a user-process /// dynamic loader, lldb needs to pick one over the other. This could - /// be a kernel corefile that happens to have a coyp of dyld in its + /// be a kernel corefile that happens to have a copy of dyld in its /// memory. Or it could be a user process coredump of lldb while doing /// kernel debugging - so a copy of the kernel is in its heap. This /// should become a setting so it can be over-ridden when necessary. @@ -150,8 +153,10 @@ private: //------------------------------------------------------------------ typedef lldb_private::Range FileRange; typedef lldb_private::RangeDataVector VMRangeToFileOffset; + typedef lldb_private::RangeDataVector VMRangeToPermissions; VMRangeToFileOffset m_core_aranges; + VMRangeToPermissions m_core_range_infos; lldb::ModuleSP m_core_module_sp; lldb_private::FileSpec m_core_file; lldb::addr_t m_dyld_addr; diff --git a/source/Plugins/ScriptInterpreter/None/Makefile b/source/Plugins/ScriptInterpreter/None/Makefile deleted file mode 100644 index 1e2523198520..000000000000 --- a/source/Plugins/ScriptInterpreter/None/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ScriptInterpreter/None/Makefile ------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginScriptInterpreterNone -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ScriptInterpreter/Python/Makefile b/source/Plugins/ScriptInterpreter/Python/Makefile deleted file mode 100644 index cf605014d458..000000000000 --- a/source/Plugins/ScriptInterpreter/Python/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/ScriptInterpreter/Python/Makefile ------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginScriptInterpreterPython -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index 23bacc932c03..1fdf4c70a5dc 100644 --- a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -19,10 +19,15 @@ #include "lldb/Core/Stream.h" #include "lldb/Host/File.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Interpreter/ScriptInterpreter.h" +#include "llvm/Support/ConvertUTF.h" + #include +#include "llvm/ADT/StringSwitch.h" + using namespace lldb_private; using namespace lldb; @@ -81,6 +86,8 @@ PythonObject::GetObjectType() const if (PythonBytes::Check(m_py_obj)) return PyObjectType::Bytes; #endif + if (PythonByteArray::Check(m_py_obj)) + return PyObjectType::ByteArray; if (PythonInteger::Check(m_py_obj)) return PyObjectType::Integer; if (PythonFile::Check(m_py_obj)) @@ -216,6 +223,8 @@ PythonObject::CreateStructuredObject() const return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); case PyObjectType::Bytes: return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); + case PyObjectType::ByteArray: + return PythonByteArray(PyRefType::Borrowed, m_py_obj).CreateStructuredString(); case PyObjectType::None: return StructuredData::ObjectSP(); default: @@ -321,6 +330,87 @@ PythonBytes::CreateStructuredString() const return result; } +PythonByteArray::PythonByteArray(llvm::ArrayRef bytes) : PythonByteArray(bytes.data(), bytes.size()) +{ +} + +PythonByteArray::PythonByteArray(const uint8_t *bytes, size_t length) +{ + const char *str = reinterpret_cast(bytes); + Reset(PyRefType::Owned, PyByteArray_FromStringAndSize(str, length)); +} + +PythonByteArray::PythonByteArray(PyRefType type, PyObject *o) +{ + Reset(type, o); +} + +PythonByteArray::PythonByteArray(const PythonBytes &object) : PythonObject(object) +{ +} + +PythonByteArray::~PythonByteArray() +{ +} + +bool +PythonByteArray::Check(PyObject *py_obj) +{ + if (!py_obj) + return false; + if (PyByteArray_Check(py_obj)) + return true; + return false; +} + +void +PythonByteArray::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 (!PythonByteArray::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()); +} + +llvm::ArrayRef +PythonByteArray::GetBytes() const +{ + if (!IsValid()) + return llvm::ArrayRef(); + + char *c = PyByteArray_AsString(m_py_obj); + size_t size = GetSize(); + return llvm::ArrayRef(reinterpret_cast(c), size); +} + +size_t +PythonByteArray::GetSize() const +{ + if (!IsValid()) + return 0; + + return PyByteArray_Size(m_py_obj); +} + +StructuredData::StringSP +PythonByteArray::CreateStructuredString() const +{ + StructuredData::StringSP result(new StructuredData::String); + llvm::ArrayRef bytes = GetBytes(); + const char *str = reinterpret_cast(bytes.data()); + result->SetValue(std::string(str, bytes.size())); + return result; +} + //---------------------------------------------------------------------- // PythonString //---------------------------------------------------------------------- @@ -1019,13 +1109,37 @@ PythonCallable::Reset(PyRefType type, PyObject *py_obj) PythonCallable::ArgInfo PythonCallable::GetNumArguments() const { - ArgInfo result = { 0, false, false }; + ArgInfo result = { 0, false, 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); + PythonObject im_self = GetAttributeValue("im_self"); + if (im_self.IsValid() && !im_self.IsNone()) + result.is_bound_method = true; + } + else + { + // see if this is a callable object with an __call__ method + if (!PyFunction_Check(py_func_obj)) + { + PythonObject __call__ = GetAttributeValue("__call__"); + if (__call__.IsValid()) + { + auto __callable__ = __call__.AsType(); + if (__callable__.IsValid()) + { + py_func_obj = PyMethod_GET_FUNCTION(__callable__.get()); + PythonObject im_self = GetAttributeValue("im_self"); + if (im_self.IsValid() && !im_self.IsNone()) + result.is_bound_method = true; + } + } + } + } if (!py_func_obj) return result; @@ -1075,9 +1189,7 @@ PythonFile::PythonFile(File &file, const char *mode) PythonFile::PythonFile(const char *path, const char *mode) { - FILE *fp = nullptr; - fp = fopen(path, mode); - lldb_private::File file(fp, true); + lldb_private::File file(path, GetOptionsFromMode(mode)); Reset(file, mode); } @@ -1156,6 +1268,22 @@ PythonFile::Reset(File &file, const char *mode) #endif } +uint32_t +PythonFile::GetOptionsFromMode(llvm::StringRef mode) +{ + if (mode.empty()) + return 0; + + return llvm::StringSwitch(mode.str().c_str()) + .Case("r", File::eOpenOptionRead) + .Case("w", File::eOpenOptionWrite) + .Case("a", File::eOpenOptionWrite|File::eOpenOptionAppend|File::eOpenOptionCanCreate) + .Case("r+", File::eOpenOptionRead|File::eOpenOptionWrite) + .Case("w+", File::eOpenOptionRead|File::eOpenOptionWrite|File::eOpenOptionCanCreate|File::eOpenOptionTruncate) + .Case("a+", File::eOpenOptionRead|File::eOpenOptionWrite|File::eOpenOptionAppend|File::eOpenOptionCanCreate) + .Default(0); +} + bool PythonFile::GetUnderlyingFile(File &file) const { @@ -1166,6 +1294,8 @@ PythonFile::GetUnderlyingFile(File &file) const // 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); + PythonString py_mode = GetAttributeValue("mode").AsType(); + file.SetOptions(PythonFile::GetOptionsFromMode(py_mode.GetString())); return file.IsValid(); } diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h index 06264b66c283..78245a98d0b8 100644 --- a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h +++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h @@ -75,6 +75,7 @@ enum class PyObjectType List, String, Bytes, + ByteArray, Module, Callable, Tuple, @@ -293,6 +294,39 @@ public: CreateStructuredString() const; }; +class PythonByteArray : public PythonObject +{ +public: + PythonByteArray(); + explicit PythonByteArray(llvm::ArrayRef bytes); + PythonByteArray(const uint8_t *bytes, size_t length); + PythonByteArray(PyRefType type, PyObject *o); + PythonByteArray(const PythonBytes &object); + + ~PythonByteArray() 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::ArrayRef + GetBytes() const; + + size_t + GetSize() const; + + void + SetBytes(llvm::ArrayRef stringbytes); + + StructuredData::StringSP + CreateStructuredString() const; +}; + class PythonString : public PythonObject { public: @@ -468,6 +502,7 @@ class PythonCallable : public PythonObject public: struct ArgInfo { size_t count; + bool is_bound_method : 1; bool has_varargs : 1; bool has_kwargs : 1; }; @@ -525,6 +560,8 @@ class PythonFile : public PythonObject void Reset(PyRefType type, PyObject *py_obj) override; void Reset(File &file, const char *mode); + static uint32_t GetOptionsFromMode(llvm::StringRef mode); + bool GetUnderlyingFile(File &file) const; }; diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 19ad86db240a..788167370593 100644 --- a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -146,7 +146,7 @@ private: 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; + static char g_python_home[] = LLDB_PYTHON_HOME; #endif Py_SetPythonHome(g_python_home); #endif @@ -274,7 +274,7 @@ ScriptInterpreterPython::ScriptInterpreterPython(CommandInterpreter &interpreter m_lock_count(0), m_command_thread_state(nullptr) { - assert(g_initialized && "ScriptInterpreterPython created but InitializePrivate has not been called!"); + InitializePrivate(); m_dictionary_name.append("_dict"); StreamString run_string; @@ -330,8 +330,6 @@ ScriptInterpreterPython::Initialize() std::call_once(g_once_flag, []() { - InitializePrivate(); - PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), lldb::eScriptLanguagePython, @@ -546,6 +544,27 @@ ScriptInterpreterPython::LeaveSession () m_session_is_active = false; } +bool +ScriptInterpreterPython::SetStdHandle(File &file, const char *py_name, PythonFile &save_file, const char *mode) +{ + if (file.IsValid()) + { + // Flush the file before giving it to python to avoid interleaved output. + file.Flush(); + + PythonDictionary &sys_module_dict = GetSysModuleDictionary(); + + save_file = sys_module_dict.GetItemForKey(PythonString(py_name)).AsType(); + + PythonFile new_file(file, mode); + sys_module_dict.SetItemForKey(PythonString(py_name), new_file); + return true; + } + else + save_file.Reset(); + return false; +} + bool ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags, FILE *in, @@ -604,54 +623,31 @@ ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags, 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) + if (on_entry_flags & Locker::NoSTDIN) + { + m_saved_stdin.Reset(); + } + else { - // STDIN is enabled - if (!in_file.IsValid() && in_sp) - in_file = in_sp->GetFile(); - if (in_file.IsValid()) + if (!SetStdHandle(in_file, "stdin", m_saved_stdin, "r")) { - // 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(); - // 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 (in_sp) + SetStdHandle(in_sp->GetFile(), "stdin", m_saved_stdin, "r"); } } - if (!out_file.IsValid() && out_sp) - out_file = out_sp->GetFile(); - if (out_file.IsValid()) + if (!SetStdHandle(out_file, "stdout", m_saved_stdout, "w")) { - // 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 new_file(out_file, "w"); - sys_module_dict.SetItemForKey (PythonString("stdout"), new_file); + if (out_sp) + SetStdHandle(out_sp->GetFile(), "stdout", m_saved_stdout, "w"); } - else - m_saved_stdout.Reset(); - if (!err_file.IsValid() && err_sp) - err_file = err_sp->GetFile(); - if (err_file.IsValid()) + if (!SetStdHandle(err_file, "stderr", m_saved_stderr, "w")) { - // 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 new_file(err_file, "w"); - sys_module_dict.SetItemForKey (PythonString("stderr"), new_file); + if (err_sp) + SetStdHandle(err_sp->GetFile(), "stderr", m_saved_stderr, "w"); } - else - m_saved_stderr.Reset(); } if (PyErr_Occurred()) @@ -1019,7 +1015,7 @@ ScriptInterpreterPython::Interrupt() if (IsExecutingPython()) { - PyThreadState *state = PyThreadState_Get(); + PyThreadState *state = PyThreadState_GET(); if (!state) state = GetThreadState(); if (state) @@ -1555,10 +1551,12 @@ ScriptInterpreterPython::OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugi 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(); + if (py_return.get()) + { + PythonDictionary result_dict(PyRefType::Borrowed, py_return.get()); + return result_dict.CreateStructuredDictionary(); + } + return StructuredData::DictionarySP(); } StructuredData::ArraySP @@ -1611,10 +1609,12 @@ ScriptInterpreterPython::OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin 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(); + if (py_return.get()) + { + PythonList result_list(PyRefType::Borrowed, py_return.get()); + return result_list.CreateStructuredArray(); + } + return StructuredData::ArraySP(); } // GetPythonValueFormatString provides a system independent type safe way to @@ -1692,10 +1692,12 @@ ScriptInterpreterPython::OSPlugin_RegisterContextData(StructuredData::ObjectSP o PyErr_Clear(); } - assert(PythonBytes::Check(py_return.get()) && "get_register_data returned unknown object type!"); - - PythonBytes result(PyRefType::Borrowed, py_return.get()); - return result.CreateStructuredString(); + if (py_return.get()) + { + PythonBytes result(PyRefType::Borrowed, py_return.get()); + return result.CreateStructuredString(); + } + return StructuredData::StringSP(); } StructuredData::DictionarySP @@ -1750,10 +1752,12 @@ ScriptInterpreterPython::OSPlugin_CreateThread(StructuredData::ObjectSP os_plugi 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(); + if (py_return.get()) + { + PythonDictionary result_dict(PyRefType::Borrowed, py_return.get()); + return result_dict.CreateStructuredDictionary(); + } + return StructuredData::DictionarySP(); } StructuredData::ObjectSP @@ -2353,6 +2357,72 @@ ScriptInterpreterPython::GetSyntheticValue(const StructuredData::ObjectSP &imple return ret_val; } +ConstString +ScriptInterpreterPython::GetSyntheticTypeName (const StructuredData::ObjectSP &implementor_sp) +{ + Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + + static char callee_name[] = "get_type_name"; + + ConstString ret_val; + bool got_string = false; + std::string buffer; + + if (!implementor_sp) + return ret_val; + + StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); + if (!generic) + return ret_val; + PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); + if (!implementor.IsAllocated()) + return ret_val; + + PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name)); + + if (PyErr_Occurred()) + PyErr_Clear(); + + if (!pmeth.IsAllocated()) + return ret_val; + + if (PyCallable_Check(pmeth.get()) == 0) + { + if (PyErr_Occurred()) + PyErr_Clear(); + return ret_val; + } + + 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()); + if (!return_data.empty()) + { + buffer.assign(return_data.data(), return_data.size()); + got_string = true; + } + } + + if (got_string) + ret_val.SetCStringWithLength(buffer.c_str(), buffer.size()); + + return ret_val; +} + bool ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function, Process* process, @@ -2550,7 +2620,7 @@ ScriptInterpreterPython::LoadScriptingModule(const char *pathname, bool can_relo StreamString command_stream; - // Before executing Pyton code, lock the GIL. + // Before executing Python code, lock the GIL. Locker py_lock (this, Locker::AcquireLock | (init_session ? Locker::InitSession : 0) | Locker::NoSTDIN, Locker::FreeAcquiredLock | (init_session ? Locker::TearDownSession : 0)); @@ -2571,9 +2641,10 @@ ScriptInterpreterPython::LoadScriptingModule(const char *pathname, bool can_relo target_file.GetFileType() == FileSpec::eFileTypeRegular || target_file.GetFileType() == FileSpec::eFileTypeSymbolicLink) { - std::string directory(target_file.GetDirectory().GetCString()); - replace_all(directory,"'","\\'"); - + std::string directory = target_file.GetDirectory().GetCString(); + replace_all(directory, "\\", "\\\\"); + 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", @@ -2585,7 +2656,7 @@ ScriptInterpreterPython::LoadScriptingModule(const char *pathname, bool can_relo error.SetErrorString("Python sys.path handling failed"); return false; } - + // strip .py or .pyc extension ConstString extension = target_file.GetFileNameExtension(); if (extension) @@ -2636,8 +2707,8 @@ ScriptInterpreterPython::LoadScriptingModule(const char *pathname, bool can_relo command_stream.Printf("reload_module(%s)",basename.c_str()); } else - command_stream.Printf("import %s",basename.c_str()); - + command_stream.Printf("import %s", basename.c_str()); + error = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)); if (error.Fail()) return false; @@ -3098,7 +3169,9 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callb void ScriptInterpreterPython::InitializePrivate () { - assert(!g_initialized && "ScriptInterpreterPython::InitializePrivate() called more than once!"); + if (g_initialized) + return; + g_initialized = true; Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h index 4c6eb3949898..263bb527d833 100644 --- a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h +++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h @@ -228,6 +228,8 @@ public: lldb::ValueObjectSP GetSyntheticValue(const StructuredData::ObjectSP &implementor) override; + ConstString GetSyntheticTypeName (const StructuredData::ObjectSP &implementor) override; + bool RunScriptBasedCommand(const char* impl_function, const char* args, @@ -581,6 +583,9 @@ protected: bool GetEmbeddedInterpreterModuleObjects (); + bool + SetStdHandle(File &file, const char *py_name, PythonFile &save_file, const char *mode); + PythonFile m_saved_stdin; PythonFile m_saved_stdout; PythonFile m_saved_stderr; diff --git a/source/Plugins/SymbolFile/CMakeLists.txt b/source/Plugins/SymbolFile/CMakeLists.txt index add6697389f9..98510704ce73 100644 --- a/source/Plugins/SymbolFile/CMakeLists.txt +++ b/source/Plugins/SymbolFile/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(DWARF) add_subdirectory(Symtab) +add_subdirectory(PDB) diff --git a/source/Plugins/SymbolFile/DWARF/CMakeLists.txt b/source/Plugins/SymbolFile/DWARF/CMakeLists.txt index b4658115dfeb..ac69243b65c0 100644 --- a/source/Plugins/SymbolFile/DWARF/CMakeLists.txt +++ b/source/Plugins/SymbolFile/DWARF/CMakeLists.txt @@ -3,6 +3,7 @@ add_lldb_library(lldbPluginSymbolFileDWARF DWARFAbbreviationDeclaration.cpp DWARFASTParserClang.cpp DWARFASTParserGo.cpp + DWARFASTParserJava.cpp DWARFAttribute.cpp DWARFCompileUnit.cpp DWARFDataExtractor.cpp diff --git a/source/Plugins/SymbolFile/DWARF/DIERef.cpp b/source/Plugins/SymbolFile/DWARF/DIERef.cpp index c0754a1fdd54..5fe0cc4d416e 100644 --- a/source/Plugins/SymbolFile/DWARF/DIERef.cpp +++ b/source/Plugins/SymbolFile/DWARF/DIERef.cpp @@ -10,26 +10,49 @@ #include "DIERef.h" #include "DWARFCompileUnit.h" #include "DWARFFormValue.h" +#include "DWARFDebugInfo.h" +#include "SymbolFileDWARF.h" +#include "SymbolFileDWARFDebugMap.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), +DIERef::DIERef(lldb::user_id_t uid, SymbolFileDWARF *dwarf) : + cu_offset(DW_INVALID_OFFSET), die_offset(uid&0xffffffff) -{} +{ + SymbolFileDWARFDebugMap *debug_map = dwarf->GetDebugMapSymfile(); + if (debug_map) + { + const uint32_t oso_idx = debug_map->GetOSOIndexFromUserID(uid); + SymbolFileDWARF *actual_dwarf = debug_map->GetSymbolFileByOSOIndex(oso_idx); + if (actual_dwarf) + { + DWARFDebugInfo *debug_info = actual_dwarf->DebugInfo(); + if (debug_info) + { + DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitContainingDIEOffset(die_offset); + if (dwarf_cu) + { + cu_offset = dwarf_cu->GetOffset(); + return; + } + } + } + die_offset = DW_INVALID_OFFSET; + } + else + { + cu_offset = uid>>32; + } +} DIERef::DIERef(const DWARFFormValue& form_value) : cu_offset(DW_INVALID_OFFSET), @@ -50,7 +73,19 @@ DIERef::DIERef(const DWARFFormValue& form_value) : } lldb::user_id_t -DIERef::GetUID() const +DIERef::GetUID(SymbolFileDWARF *dwarf) const { - return ((lldb::user_id_t)cu_offset) << 32 | die_offset; + //---------------------------------------------------------------------- + // Each SymbolFileDWARF will set its ID to what is expected. + // + // SymbolFileDWARF, when used for DWARF with .o files on MacOSX, has the + // ID set to the compile unit index. + // + // SymbolFileDWARFDwo sets the ID to the compile unit offset. + //---------------------------------------------------------------------- + if (dwarf) + return dwarf->GetID() | die_offset; + else + return LLDB_INVALID_UID; } + diff --git a/source/Plugins/SymbolFile/DWARF/DIERef.h b/source/Plugins/SymbolFile/DWARF/DIERef.h index 3df07d511749..ad4ad45623a3 100644 --- a/source/Plugins/SymbolFile/DWARF/DIERef.h +++ b/source/Plugins/SymbolFile/DWARF/DIERef.h @@ -14,24 +14,34 @@ #include "lldb/lldb-defines.h" class DWARFFormValue; +class SymbolFileDWARF; struct DIERef { DIERef(); - explicit - DIERef(dw_offset_t d); - DIERef(dw_offset_t c, dw_offset_t d); + //---------------------------------------------------------------------- + // In order to properly decode a lldb::user_id_t back into a DIERef we + // need the DWARF file since it knows if DWARF in .o files is being used + // (MacOSX) or if DWO files are being used. The encoding of the user ID + // differs between the two types of DWARF. + //---------------------------------------------------------------------- explicit - DIERef(lldb::user_id_t uid); + DIERef(lldb::user_id_t uid, SymbolFileDWARF *dwarf); explicit DIERef(const DWARFFormValue& form_value); + //---------------------------------------------------------------------- + // In order to properly encode a DIERef unto a lldb::user_id_t we need + // the DWARF file since it knows if DWARF in .o files is being used + // (MacOSX) or if DWO files are being used. The encoding of the user ID + // differs between the two types of DWARF. + //---------------------------------------------------------------------- lldb::user_id_t - GetUID() const; + GetUID(SymbolFileDWARF *dwarf) const; bool operator< (const DIERef &ref) const diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h index ab20844bfcfd..2fb360440f63 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h @@ -32,18 +32,6 @@ public: 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, diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 74b54d614aa2..23381df3297a 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +#include + #include "DWARFASTParserClang.h" #include "DWARFCompileUnit.h" #include "DWARFDebugInfo.h" @@ -18,14 +20,16 @@ #include "SymbolFileDWARFDebugMap.h" #include "UniqueDWARFASTType.h" -#include "lldb/Interpreter/Args.h" +#include "Plugins/Language/ObjC/ObjCLanguage.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/Interpreter/Args.h" #include "lldb/Symbol/ClangASTImporter.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" +#include "lldb/Symbol/ClangUtil.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" @@ -33,7 +37,7 @@ #include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/TypeMap.h" #include "lldb/Target/Language.h" -#include "Plugins/Language/ObjC/ObjCLanguage.h" +#include "lldb/Utility/LLDBAssert.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" @@ -97,9 +101,9 @@ struct BitfieldInfo uint64_t bit_size; uint64_t bit_offset; - BitfieldInfo () : - bit_size (LLDB_INVALID_ADDRESS), - bit_offset (LLDB_INVALID_ADDRESS) + BitfieldInfo() : + bit_size(LLDB_INVALID_ADDRESS), + bit_offset(LLDB_INVALID_ADDRESS) { } @@ -110,10 +114,28 @@ struct BitfieldInfo bit_offset = LLDB_INVALID_ADDRESS; } - bool IsValid () + bool + IsValid() const { return (bit_size != LLDB_INVALID_ADDRESS) && - (bit_offset != LLDB_INVALID_ADDRESS); + (bit_offset != LLDB_INVALID_ADDRESS); + } + + bool + NextBitfieldOffsetIsValid(const uint64_t next_bit_offset) const + { + if (IsValid()) + { + // This bitfield info is valid, so any subsequent bitfields + // must not overlap and must be at a higher bit offset than + // any previous bitfield + size. + return (bit_size + bit_offset) <= next_bit_offset; + } + else + { + // If the this BitfieldInfo is not valid, then any offset isOK + return true; + } } }; @@ -252,11 +274,11 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, switch (tag) { + case DW_TAG_typedef: 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: @@ -267,7 +289,7 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, const size_t num_attributes = die.GetAttributes (attributes); uint32_t encoding = 0; - lldb::user_id_t encoding_uid = LLDB_INVALID_UID; + DWARFFormValue encoding_uid; if (num_attributes > 0) { @@ -297,7 +319,7 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, 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; + case DW_AT_type: encoding_uid = form_value; break; default: case DW_AT_sibling: break; @@ -306,7 +328,43 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, } } - 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); + if (tag == DW_TAG_typedef && encoding_uid.IsValid()) + { + // Try to parse a typedef from the DWO file first as modules + // can contain typedef'ed structures that have no names like: + // + // typedef struct { int a; } Foo; + // + // In this case we will have a structure with no name and a + // typedef named "Foo" that points to this unnamed structure. + // The name in the typedef is the only identifier for the struct, + // so always try to get typedefs from DWO files if possible. + // + // The type_sp returned will be empty if the typedef doesn't exist + // in a DWO file, so it is cheap to call this function just to check. + // + // If we don't do this we end up creating a TypeSP that says this + // is a typedef to type 0x123 (the DW_AT_type value would be 0x123 + // in the DW_TAG_typedef), and this is the unnamed structure type. + // We will have a hard time tracking down an unnammed structure + // type in the module DWO file, so we make sure we don't get into + // this situation by always resolving typedefs from the DWO file. + const DWARFDIE encoding_die = dwarf->GetDIE(DIERef(encoding_uid)); + + // First make sure that the die that this is typedef'ed to _is_ + // just a declaration (DW_AT_declaration == 1), not a full definition + // since template types can't be represented in modules since only + // concrete instances of templates are ever emitted and modules + // won't contain those + if (encoding_die && encoding_die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 1) + { + type_sp = ParseTypeFromDWO(die, log); + if (type_sp) + return type_sp; + } + } + + DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr, encoding_uid.Reference()); switch (tag) { @@ -322,6 +380,7 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, break; } // Fall through to base type below in case we can handle the type there... + LLVM_FALLTHROUGH; case DW_TAG_base_type: resolve_state = Type::eResolveStateFull; @@ -341,6 +400,44 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID || encoding_data_type == Type::eEncodingIsTypedefUID) && sc.comp_unit != NULL) { + if (tag == DW_TAG_pointer_type) + { + DWARFDIE target_die = die.GetReferencedDIE(DW_AT_type); + + if (target_die.GetAttributeValueAsUnsigned(DW_AT_APPLE_block, 0)) + { + // Blocks have a __FuncPtr inside them which is a pointer to a function of the proper type. + + for (DWARFDIE child_die = target_die.GetFirstChild(); + child_die.IsValid(); + child_die = child_die.GetSibling()) + { + if (!strcmp(child_die.GetAttributeValueAsString(DW_AT_name, ""), "__FuncPtr")) + { + DWARFDIE function_pointer_type = child_die.GetReferencedDIE(DW_AT_type); + + if (function_pointer_type) + { + DWARFDIE function_type = function_pointer_type.GetReferencedDIE(DW_AT_type); + + bool function_type_is_new_pointer; + TypeSP lldb_function_type_sp = ParseTypeFromDWARF(sc, function_type, log, &function_type_is_new_pointer); + + if (lldb_function_type_sp) + { + clang_type = m_ast.CreateBlockPointerType(lldb_function_type_sp->GetForwardCompilerType()); + encoding_data_type = Type::eEncodingIsUID; + encoding_uid.Clear(); + resolve_state = Type::eResolveStateFull; + } + } + + break; + } + } + } + } + bool translation_unit_is_objc = (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus); if (translation_unit_is_objc) @@ -361,7 +458,7 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, die.GetName()); clang_type = m_ast.GetBasicType(eBasicTypeObjCID); encoding_data_type = Type::eEncodingIsUID; - encoding_uid = LLDB_INVALID_UID; + encoding_uid.Clear(); resolve_state = Type::eResolveStateFull; } @@ -375,7 +472,7 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, die.GetName()); clang_type = m_ast.GetBasicType(eBasicTypeObjCClass); encoding_data_type = Type::eEncodingIsUID; - encoding_uid = LLDB_INVALID_UID; + encoding_uid.Clear(); resolve_state = Type::eResolveStateFull; } else if (type_name_const_str == g_objc_type_name_selector) @@ -388,15 +485,15 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, die.GetName()); clang_type = m_ast.GetBasicType(eBasicTypeObjCSel); encoding_data_type = Type::eEncodingIsUID; - encoding_uid = LLDB_INVALID_UID; + encoding_uid.Clear(); resolve_state = Type::eResolveStateFull; } } - else if (encoding_data_type == Type::eEncodingIsPointerUID && encoding_uid != LLDB_INVALID_UID) + else if (encoding_data_type == Type::eEncodingIsPointerUID && encoding_uid.IsValid()) { // 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); + const DWARFDIE encoding_die = dwarf->GetDIE(DIERef(encoding_uid)); if (encoding_die && encoding_die.Tag() == DW_TAG_structure_type) { @@ -412,7 +509,7 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, die.GetName()); clang_type = m_ast.GetBasicType(eBasicTypeObjCID); encoding_data_type = Type::eEncodingIsUID; - encoding_uid = LLDB_INVALID_UID; + encoding_uid.Clear(); resolve_state = Type::eResolveStateFull; } } @@ -426,7 +523,7 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, type_name_const_str, byte_size, NULL, - encoding_uid, + DIERef(encoding_uid).GetUID(dwarf), encoding_data_type, &decl, clang_type, @@ -532,43 +629,32 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, // and clang isn't good and sharing the stack space for variables in different blocks. std::unique_ptr unique_ast_entry_ap(new UniqueDWARFASTType()); + ConstString unique_typename(type_name_const_str); + Declaration unique_decl(decl); + if (type_name_const_str) { LanguageType die_language = die.GetLanguage(); - bool handled = false; if (Language::LanguageIsCPlusPlus(die_language)) { + // For C++, we rely solely upon the one definition rule that says only + // one thing can exist at a given decl context. We ignore the file and + // line that things are declared on. 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; - } - } - } + unique_typename = ConstString(qualified_name); + unique_decl.Clear(); } - if (!handled) + if (dwarf->GetUniqueDWARFASTTypeMap().Find(unique_typename, die, unique_decl, + byte_size_valid ? byte_size : -1, + *unique_ast_entry_ap)) { - 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) { - type_sp = unique_ast_entry_ap->m_type_sp; - if (type_sp) - { - dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); - return type_sp; - } + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + return type_sp; } } } @@ -716,7 +802,7 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, // 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()))); + dwarf->DebugInfo()->GetDIE(DIERef(type_sp->GetID(), dwarf))); if (defn_decl_ctx) LinkDeclContextToDIE(defn_decl_ctx, die); return type_sp; @@ -799,9 +885,9 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, // 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_declaration = unique_decl; unique_ast_entry_ap->m_byte_size = byte_size; - dwarf->GetUniqueDWARFASTTypeMap().Insert (type_name_const_str, + dwarf->GetUniqueDWARFASTTypeMap().Insert (unique_typename, *unique_ast_entry_ap); if (is_forward_declaration && die.HasChildren()) @@ -842,15 +928,25 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, if (die.HasChildren() == false) { // No children for this struct/union/class, lets finish it - ClangASTContext::StartTagDeclarationDefinition (clang_type); - ClangASTContext::CompleteTagDeclarationDefinition (clang_type); + if (ClangASTContext::StartTagDeclarationDefinition (clang_type)) + { + ClangASTContext::CompleteTagDeclarationDefinition (clang_type); + } + else + { + dwarf->GetObjectFile()->GetModule()->ReportError("DWARF DIE at 0x%8.8x named \"%s\" was not able to start its definition.\nPlease file a bug and attach the file at the start of this error message", + die.GetOffset(), + type_name_cstr); + } 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())); + { + GetClangASTImporter().InsertRecordDecl(record_decl, ClangASTImporter::LayoutInfo()); + } } } else if (clang_type_was_created) @@ -872,12 +968,14 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, // 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()) && + assert(!dwarf->GetForwardDeclClangTypeToDie().count( + ClangUtil::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"); + // Can't assume m_ast.GetSymbolFile() is actually a SymbolFileDWARF, it can be a + // SymbolFileDWARFDebugMap for Apple binaries. dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = clang_type.GetOpaqueQualType(); - dwarf->GetForwardDeclClangTypeToDie()[ClangASTContext::RemoveFastQualifiers(clang_type).GetOpaqueQualType()] = die.GetDIERef(); + dwarf->GetForwardDeclClangTypeToDie()[ClangUtil::RemoveFastQualifiers(clang_type) + .GetOpaqueQualType()] = die.GetDIERef(); m_ast.SetHasExternalStorage (clang_type.GetOpaqueQualType(), true); } } @@ -970,8 +1068,7 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, // 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()))); + clang::DeclContext *defn_decl_ctx = GetCachedClangDeclContextForDIE(dwarf->DebugInfo()->GetDIE(DIERef(type_sp->GetID(), dwarf))); if (defn_decl_ctx) LinkDeclContextToDIE(defn_decl_ctx, die); return type_sp; @@ -986,15 +1083,24 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, { if (encoding_form.IsValid()) { - Type *enumerator_type = dwarf->ResolveTypeUID(DIERef(encoding_form).GetUID()); + Type *enumerator_type = dwarf->ResolveTypeUID(DIERef(encoding_form)); 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); + { + if (byte_size > 0) + { + enumerator_clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize(NULL, + DW_ATE_signed, + byte_size * 8); + } + else + { + enumerator_clang_type = m_ast.GetBasicType(eBasicTypeInt); + } + } clang_type = m_ast.CreateEnumerationType (type_name_cstr, GetClangDeclContextContainingDIE (die, nullptr), @@ -1013,21 +1119,29 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, type_name_const_str, byte_size, NULL, - DIERef(encoding_form).GetUID(), + DIERef(encoding_form).GetUID(dwarf), Type::eEncodingIsUID, &decl, clang_type, Type::eResolveStateForward)); - ClangASTContext::StartTagDeclarationDefinition (clang_type); - if (die.HasChildren()) + if (ClangASTContext::StartTagDeclarationDefinition (clang_type)) { - 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); + 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); + } + else + { + dwarf->GetObjectFile()->GetModule()->ReportError("DWARF DIE at 0x%8.8x named \"%s\" was not able to start its definition.\nPlease file a bug and attach the file at the start of this error message", + die.GetOffset(), + type_name_cstr); } - ClangASTContext::CompleteTagDeclarationDefinition (clang_type); } } break; @@ -1046,6 +1160,7 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, bool is_virtual = false; bool is_explicit = false; bool is_artificial = false; + bool has_template_params = false; DWARFFormValue specification_die_form; DWARFFormValue abstract_origin_die_form; dw_offset_t object_pointer_die_offset = DW_INVALID_OFFSET; @@ -1153,7 +1268,7 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, Type *func_type = NULL; if (type_die_form.IsValid()) - func_type = dwarf->ResolveTypeUID(DIERef(type_die_form).GetUID()); + func_type = dwarf->ResolveTypeUID(DIERef(type_die_form)); if (func_type) return_clang_type = func_type->GetForwardCompilerType (); @@ -1170,11 +1285,13 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, 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); + 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()) { @@ -1185,11 +1302,26 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, skip_artificial, is_static, is_variadic, + has_template_params, function_param_types, function_param_decls, type_quals); } + bool ignore_containing_context = false; + // Check for templatized class member functions. If we had any DW_TAG_template_type_parameter + // or DW_TAG_template_value_parameter the DW_TAG_subprogram DIE, then we can't let this become + // a method in a class. Why? Because templatized functions are only emitted if one of the + // templatized methods is used in the current compile unit and we will end up with classes + // that may or may not include these member functions and this means one class won't match another + // class definition and it affects our ability to use a class in the clang expression parser. So + // for the greater good, we currently must not allow any template member functions in a class definition. + if (is_cxx_method && has_template_params) + { + ignore_containing_context = true; + is_cxx_method = false; + } + // clang_type will get the function prototype clang type after this call clang_type = m_ast.CreateFunctionType (return_clang_type, function_param_types.data(), @@ -1197,7 +1329,6 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, is_variadic, type_quals); - bool ignore_containing_context = false; if (type_name_cstr) { @@ -1233,7 +1364,8 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, type_name_cstr, clang_type, accessibility, - is_artificial); + is_artificial, + is_variadic); type_handled = objc_method_decl != NULL; if (type_handled) { @@ -1272,12 +1404,12 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, 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())); + class_type_die = class_symfile->DebugInfo()->GetDIE (DIERef(class_type->GetID(), dwarf)); } else { class_symfile = dwarf; - class_type_die = dwarf->DebugInfo()->GetDIE (DIERef(class_type->GetID())); + class_type_die = dwarf->DebugInfo()->GetDIE (DIERef(class_type->GetID(), dwarf)); } if (class_type_die) { @@ -1378,7 +1510,8 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, clang::CXXMethodDecl *method_decl = *method_iter; if (method_decl->getNameInfo().getAsString() == std::string(type_name_cstr)) { - if (method_decl->getType() == ClangASTContext::GetQualType(clang_type)) + if (method_decl->getType() == + ClangUtil::GetQualType(clang_type)) { add_method = false; LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(method_decl), die); @@ -1483,44 +1616,72 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, 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()); + clang::FunctionDecl *function_decl = nullptr; + + if (abstract_origin_die_form.IsValid()) + { + DWARFDIE abs_die = dwarf->DebugInfo()->GetDIE (DIERef(abstract_origin_die_form)); - ClangASTMetadata metadata; - metadata.SetUserID(die.GetID()); + SymbolContext sc; + + if (dwarf->ResolveType (abs_die)) + { + function_decl = llvm::dyn_cast_or_null(GetCachedClangDeclContextForDIE(abs_die)); + + if (function_decl) + { + LinkDeclContextToDIE(function_decl, die); + } + } + } - if (!object_pointer_name.empty()) + if (!function_decl) { - 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(function_decl)); + // We just have a function that isn't part of a class + function_decl = m_ast.CreateFunctionDeclaration (ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, + 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 + + lldbassert (function_decl); + + if (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(function_decl)); + } + m_ast.SetMetadata (function_decl, metadata); + } } - m_ast.SetMetadata (function_decl, metadata); } } type_sp.reset( new Type (die.GetID(), @@ -1591,7 +1752,8 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, 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()); + DIERef type_die_ref(type_die_form); + Type *element_type = dwarf->ResolveTypeUID(type_die_ref); if (element_type) { @@ -1600,6 +1762,39 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, if (byte_stride == 0 && bit_stride == 0) byte_stride = element_type->GetByteSize(); CompilerType array_element_type = element_type->GetForwardCompilerType (); + + if (ClangASTContext::IsCXXClassType(array_element_type) && array_element_type.GetCompleteType() == false) + { + ModuleSP module_sp = die.GetModule(); + if (module_sp) + { + if (die.GetCU()->GetProducer() == DWARFCompileUnit::eProducerClang) + module_sp->ReportError ("DWARF DW_TAG_array_type DIE at 0x%8.8x has a class/union/struct element type DIE 0x%8.8x that is a forward declaration, not a complete definition.\nTry compiling the source file with -fno-limit-debug-info or disable -gmodule", + die.GetOffset(), + type_die_ref.die_offset); + else + module_sp->ReportError ("DWARF DW_TAG_array_type DIE at 0x%8.8x has a class/union/struct element type DIE 0x%8.8x that is a forward declaration, not a complete definition.\nPlease file a bug against the compiler and include the preprocessed output for %s", + die.GetOffset(), + type_die_ref.die_offset, + die.GetLLDBCompileUnit() ? die.GetLLDBCompileUnit()->GetPath().c_str() : "the source file"); + } + + // We have no choice other than to pretend that the element class type + // is complete. If we don't do this, clang will crash when trying + // to layout the class. Since we provide layout assistance, all + // ivars in this class and other classes will be fine, this is + // the best we can do short of crashing. + if (ClangASTContext::StartTagDeclarationDefinition(array_element_type)) + { + ClangASTContext::CompleteTagDeclarationDefinition(array_element_type); + } + else + { + module_sp->ReportError ("DWARF DIE at 0x%8.8x was not able to start its definition.\nPlease file a bug and attach the file at the start of this error message", + type_die_ref.die_offset); + } + } + uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride; if (element_orders.size() > 0) { @@ -1628,7 +1823,7 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, empty_name, array_element_bit_stride / 8, NULL, - DIERef(type_die_form).GetUID(), + DIERef(type_die_form).GetUID(dwarf), Type::eEncodingIsUID, &decl, clang_type, @@ -1663,8 +1858,8 @@ DWARFASTParserClang::ParseTypeFromDWARF (const SymbolContext& sc, } } - Type *pointee_type = dwarf->ResolveTypeUID(DIERef(type_die_form).GetUID()); - Type *class_type = dwarf->ResolveTypeUID(DIERef(containing_type_die_form).GetUID()); + Type *pointee_type = dwarf->ResolveTypeUID(DIERef(type_die_form)); + Type *class_type = dwarf->ResolveTypeUID(DIERef(containing_type_die_form)); CompilerType pointee_clang_type = pointee_type->GetForwardCompilerType (); CompilerType class_clang_type = class_type->GetLayoutCompilerType (); @@ -1812,8 +2007,7 @@ DWARFASTParserClang::ParseTemplateDIE (const DWARFDIE &die, { DWARFAttributes attributes; const size_t num_attributes = die.GetAttributes (attributes); - const char *name = NULL; - Type *lldb_type = NULL; + const char *name = nullptr; CompilerType clang_type; uint64_t uval64 = 0; bool uval64_valid = false; @@ -1834,7 +2028,7 @@ DWARFASTParserClang::ParseTemplateDIE (const DWARFDIE &die, case DW_AT_type: if (attributes.ExtractFormValueAtIndex(i, form_value)) { - lldb_type = die.ResolveTypeUID(DIERef(form_value).GetUID()); + Type *lldb_type = die.ResolveTypeUID(DIERef(form_value)); if (lldb_type) clang_type = lldb_type->GetForwardCompilerType (); } @@ -1864,19 +2058,19 @@ DWARFASTParserClang::ParseTemplateDIE (const DWARFDIE &die, 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) + // Get the signed value for any integer or enumeration if available + clang_type.IsIntegerOrEnumerationType (is_signed); + + if (tag == DW_TAG_template_value_parameter && 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))); + llvm::APInt apint (clang_type.GetBitSize(nullptr), uval64, is_signed); + template_param_infos.args.push_back( + clang::TemplateArgument(*ast, llvm::APSInt(apint, !is_signed), ClangUtil::GetQualType(clang_type))); } else { - template_param_infos.args.push_back (clang::TemplateArgument (ClangASTContext::GetQualType(clang_type))); + template_param_infos.args.push_back( + clang::TemplateArgument(ClangUtil::GetQualType(clang_type))); } } else @@ -1926,37 +2120,12 @@ DWARFASTParserClang::ParseTemplateParameterInfos (const DWARFDIE &parent_die, } bool -DWARFASTParserClang::CanCompleteType (const lldb_private::CompilerType &compiler_type) +DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type, CompilerType &clang_type) { - if (m_clang_ast_importer_ap) - return ClangASTContext::CanImport(compiler_type, GetClangASTImporter()); - else - return false; -} + SymbolFileDWARF *dwarf = die.GetDWARF(); -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; -} + std::lock_guard guard(dwarf->GetObjectFile()->GetModule()->GetMutex()); -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); @@ -1964,9 +2133,45 @@ DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die, if (!die) return false; - const dw_tag_t tag = die.Tag(); +#if defined LLDB_CONFIGURATION_DEBUG + //---------------------------------------------------------------------- + // For debugging purposes, the LLDB_DWARF_DONT_COMPLETE_TYPENAMES + // environment variable can be set with one or more typenames separated + // by ';' characters. This will cause this function to not complete any + // types whose names match. + // + // Examples of setting this environment variable: + // + // LLDB_DWARF_DONT_COMPLETE_TYPENAMES=Foo + // LLDB_DWARF_DONT_COMPLETE_TYPENAMES=Foo;Bar;Baz + //---------------------------------------------------------------------- + const char *dont_complete_typenames_cstr = getenv("LLDB_DWARF_DONT_COMPLETE_TYPENAMES"); + if (dont_complete_typenames_cstr && dont_complete_typenames_cstr[0]) + { + const char *die_name = die.GetName(); + if (die_name && die_name[0]) + { + const char *match = strstr(dont_complete_typenames_cstr, die_name); + if (match) + { + size_t die_name_length = strlen(die_name); + while (match) + { + const char separator_char = ';'; + const char next_char = match[die_name_length]; + if (next_char == '\0' || next_char == separator_char) + { + if (match == dont_complete_typenames_cstr || match[-1] == separator_char) + return false; + } + match = strstr(match+1, die_name); + } + } + } + } +#endif - SymbolFileDWARF *dwarf = die.GetDWARF(); + const dw_tag_t tag = die.Tag(); Log *log = nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION)); if (log) @@ -1983,7 +2188,7 @@ DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die, case DW_TAG_union_type: case DW_TAG_class_type: { - LayoutInfo layout_info; + ClangASTImporter::LayoutInfo layout_info; { if (die.HasChildren()) @@ -2080,7 +2285,7 @@ DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die, if (class_language != eLanguageTypeObjC) { if (is_a_class && tag_decl_kind != clang::TTK_Class) - m_ast.SetTagTypeKind (ClangASTContext::GetQualType(clang_type), clang::TTK_Class); + m_ast.SetTagTypeKind(ClangUtil::GetQualType(clang_type), clang::TTK_Class); } // Since DW_TAG_structure_type gets used for both classes @@ -2130,8 +2335,10 @@ DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die, // 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); + if (ClangASTContext::StartTagDeclarationDefinition (base_class_type)) + { + ClangASTContext::CompleteTagDeclarationDefinition (base_class_type); + } } } } @@ -2219,7 +2426,7 @@ DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die, } } - m_record_decl_to_layout_map.insert(std::make_pair(record_decl, layout_info)); + GetClangASTImporter().InsertRecordDecl(record_decl, layout_info); } } } @@ -2227,15 +2434,17 @@ DWARFASTParserClang::CompleteTypeFromDWARF (const DWARFDIE &die, return (bool)clang_type; case DW_TAG_enumeration_type: - ClangASTContext::StartTagDeclarationDefinition (clang_type); - if (die.HasChildren()) + if (ClangASTContext::StartTagDeclarationDefinition (clang_type)) { - SymbolContext sc(die.GetLLDBCompileUnit()); - bool is_signed = false; - clang_type.IsIntegerType(is_signed); - ParseChildEnumerators(sc, clang_type, is_signed, type->GetByteSize(), die); + 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); } - ClangASTContext::CompleteTagDeclarationDefinition (clang_type); return (bool)clang_type; default: @@ -2484,6 +2693,7 @@ DWARFASTParserClang::ParseFunctionFromDWARF (const SymbolContext& sc, // never mangled. bool is_static = false; bool is_variadic = false; + bool has_template_params = false; unsigned type_quals = 0; std::vector param_types; std::vector param_decls; @@ -2500,6 +2710,7 @@ DWARFASTParserClang::ParseFunctionFromDWARF (const SymbolContext& sc, true, is_static, is_variadic, + has_template_params, param_types, param_decls, type_quals); @@ -2557,23 +2768,22 @@ DWARFASTParserClang::ParseFunctionFromDWARF (const SymbolContext& sc, return NULL; } - bool -DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, - const DWARFDIE &parent_die, - CompilerType &class_clang_type, - const LanguageType class_language, - std::vector& base_classes, - std::vector& member_accessibilities, - DWARFDIECollection& member_function_dies, - DelayedPropertyList& delayed_properties, - AccessType& default_accessibility, - bool &is_a_class, - LayoutInfo &layout_info) +DWARFASTParserClang::ParseChildMembers(const SymbolContext &sc, const DWARFDIE &parent_die, + CompilerType &class_clang_type, const LanguageType class_language, + std::vector &base_classes, + std::vector &member_accessibilities, + DWARFDIECollection &member_function_dies, + DelayedPropertyList &delayed_properties, AccessType &default_accessibility, + bool &is_a_class, ClangASTImporter::LayoutInfo &layout_info) { if (!parent_die) return 0; + // Get the parent byte size so we can verify any members will fit + const uint64_t parent_byte_size = parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size, UINT64_MAX) * 8; + const uint64_t parent_bit_size = parent_byte_size == UINT64_MAX ? UINT64_MAX : parent_byte_size * 8; + uint32_t member_idx = 0; BitfieldInfo last_field_info; @@ -2607,9 +2817,10 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, bool is_artificial = false; DWARFFormValue encoding_form; AccessType accessibility = eAccessNone; - uint32_t member_byte_offset = UINT32_MAX; + uint32_t member_byte_offset = (parent_die.Tag() == DW_TAG_union_type) ? 0 : UINT32_MAX; size_t byte_size = 0; - size_t bit_offset = 0; + int64_t bit_offset = 0; + uint64_t data_bit_offset = UINT64_MAX; size_t bit_size = 0; bool is_external = false; // On DW_TAG_members, this means the member is static uint32_t i; @@ -2626,9 +2837,10 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, 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_offset: bit_offset = form_value.Signed(); break; case DW_AT_bit_size: bit_size = form_value.Unsigned(); break; case DW_AT_byte_size: byte_size = form_value.Unsigned(); break; + case DW_AT_data_bit_offset: data_bit_offset = form_value.Unsigned(); break; case DW_AT_data_member_location: if (form_value.BlockData()) { @@ -2637,10 +2849,10 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, 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 * + if (DWARFExpression::Evaluate(nullptr, // ExecutionContext * + nullptr, // ClangExpressionVariableList * + nullptr, // ClangExpressionDeclMap * + nullptr, // RegisterContext * module_sp, debug_info_data, die.GetCU(), @@ -2648,8 +2860,9 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, block_length, eRegisterKindDWARF, &initialValue, + nullptr, memberOffset, - NULL)) + nullptr)) { member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); } @@ -2739,7 +2952,7 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, // type in an expression when clang becomes unhappy with its // recycled debug info. - if (bit_offset > 128) + if (byte_size == 0 && bit_offset < 0) { bit_size = 0; bit_offset = 0; @@ -2764,7 +2977,7 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, // Handle static members if (is_external && member_byte_offset == UINT32_MAX) { - Type *var_type = die.ResolveTypeUID(DIERef(encoding_form).GetUID()); + Type *var_type = die.ResolveTypeUID(DIERef(encoding_form)); if (var_type) { @@ -2780,7 +2993,7 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, if (is_artificial == false) { - Type *member_type = die.ResolveTypeUID(DIERef(encoding_form).GetUID()); + Type *member_type = die.ResolveTypeUID(DIERef(encoding_form)); clang::FieldDecl *field_decl = NULL; if (tag == DW_TAG_member) @@ -2815,17 +3028,38 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, // 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) + if (data_bit_offset != UINT64_MAX) { - this_field_info.bit_offset += byte_size * 8; - this_field_info.bit_offset -= (bit_offset + bit_size); + this_field_info.bit_offset = data_bit_offset; } else { - this_field_info.bit_offset += bit_offset; + if (byte_size == 0) + byte_size = member_type->GetByteSize(); + + ObjectFile *objfile = die.GetDWARF()->GetObjectFile(); + if (objfile->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; + } + } + + if ((this_field_info.bit_offset >= parent_bit_size) || !last_field_info.NextBitfieldOffsetIsValid(this_field_info.bit_offset)) + { + ObjectFile *objfile = die.GetDWARF()->GetObjectFile(); + objfile->GetModule()->ReportWarning("0x%8.8" PRIx64 ": %s bitfield named \"%s\" has invalid bit offset (0x%8.8" PRIx64 ") member will be ignored. Please file a bug against the compiler and include the preprocessed output for %s\n", + die.GetID(), + DW_TAG_value_to_name(tag), + name, + this_field_info.bit_offset, + sc.comp_unit ? sc.comp_unit->GetPath().c_str() : "the source file"); + this_field_info.Clear(); + continue; } // Update the field bit offset we will report for layout @@ -2962,8 +3196,18 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, // 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); + if (ClangASTContext::StartTagDeclarationDefinition(member_clang_type)) + { + ClangASTContext::CompleteTagDeclarationDefinition(member_clang_type); + } + else + { + module_sp->ReportError ("DWARF DIE at 0x%8.8x (class %s) has a member variable 0x%8.8x (%s) whose type claims to be a C++ class but we were not able to start its definition.\nPlease file a bug and attach the file at the start of this error message", + parent_die.GetOffset(), + parent_die.GetName(), + die.GetOffset(), + name); + } } field_decl = ClangASTContext::AddFieldToRecordType (class_clang_type, @@ -3063,10 +3307,10 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, 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, + if (DWARFExpression::Evaluate (nullptr, + nullptr, + nullptr, + nullptr, module_sp, debug_info_data, die.GetCU(), @@ -3074,8 +3318,9 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, block_length, eRegisterKindDWARF, &initialValue, + nullptr, memberOffset, - NULL)) + nullptr)) { member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); } @@ -3106,7 +3351,7 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc, } } - Type *base_class_type = die.ResolveTypeUID(DIERef(encoding_form).GetUID()); + Type *base_class_type = die.ResolveTypeUID(DIERef(encoding_form)); 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", @@ -3166,6 +3411,7 @@ DWARFASTParserClang::ParseChildParameters (const SymbolContext& sc, bool skip_artificial, bool &is_static, bool &is_variadic, + bool &has_template_params, std::vector& function_param_types, std::vector& function_param_decls, unsigned &type_quals) @@ -3251,7 +3497,7 @@ DWARFASTParserClang::ParseChildParameters (const SymbolContext& sc, // being in the formal parameter DIE... if (name == NULL || ::strcmp(name, "this")==0) { - Type *this_type = die.ResolveTypeUID (DIERef(param_type_die_form).GetUID()); + Type *this_type = die.ResolveTypeUID (DIERef(param_type_die_form)); if (this_type) { uint32_t encoding_mask = this_type->GetEncodingMask(); @@ -3294,7 +3540,7 @@ DWARFASTParserClang::ParseChildParameters (const SymbolContext& sc, if (!skip) { - Type *type = die.ResolveTypeUID(DIERef(param_type_die_form).GetUID()); + Type *type = die.ResolveTypeUID(DIERef(param_type_die_form)); if (type) { function_param_types.push_back (type->GetForwardCompilerType ()); @@ -3324,6 +3570,7 @@ DWARFASTParserClang::ParseChildParameters (const SymbolContext& sc, // 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); + has_template_params = true; break; default: @@ -3440,7 +3687,7 @@ DWARFASTParserClang::GetTypeForDIE (const DWARFDIE &die) DWARFFormValue form_value; if (attr == DW_AT_type && attributes.ExtractFormValueAtIndex(i, form_value)) - return dwarf->ResolveTypeUID(DIERef(form_value).GetUID()); + return dwarf->ResolveTypeUID(dwarf->GetDIE (DIERef(form_value)), true); } } } @@ -3477,6 +3724,14 @@ DWARFASTParserClang::GetClangDeclForDIE (const DWARFDIE &die) m_decl_to_die[decl].insert(die.GetDIE()); return decl; } + + if (DWARFDIE abstract_origin_die = die.GetReferencedDIE(DW_AT_abstract_origin)) + { + clang::Decl *decl = GetClangDeclForDIE(abstract_origin_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()) @@ -3487,22 +3742,23 @@ DWARFASTParserClang::GetClangDeclForDIE (const DWARFDIE &die) { 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())); + if (dwarf && type) + { + const char *name = die.GetName(); + clang::DeclContext *decl_context = + ClangASTContext::DeclContextGetAsDeclContext(dwarf->GetDeclContextContainingUID(die.GetID())); + decl = m_ast.CreateVariableDeclaration(decl_context, name, + ClangUtil::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)) + DWARFDIE imported_uid = die.GetAttributeValueAsReferenceDIE(DW_AT_import); + if (imported_uid) { - CompilerDecl imported_decl = dwarf->GetDeclForUID(imported_uid); + CompilerDecl imported_decl = imported_uid.GetDecl(); if (imported_decl) { clang::DeclContext *decl_context = ClangASTContext::DeclContextGetAsDeclContext(dwarf->GetDeclContextContainingUID(die.GetID())); @@ -3515,15 +3771,15 @@ DWARFASTParserClang::GetClangDeclForDIE (const DWARFDIE &die) case DW_TAG_imported_module: { SymbolFileDWARF *dwarf = die.GetDWARF(); - lldb::user_id_t imported_uid = die.GetAttributeValueAsReference(DW_AT_import, DW_INVALID_OFFSET); + DWARFDIE imported_uid = die.GetAttributeValueAsReferenceDIE(DW_AT_import); - if (dwarf->UserIDMatches(imported_uid)) + if (imported_uid) { - CompilerDeclContext imported_decl = dwarf->GetDeclContextForUID(imported_uid); - if (imported_decl) + CompilerDeclContext imported_decl_ctx = imported_uid.GetDeclContext(); + if (imported_decl_ctx) { clang::DeclContext *decl_context = ClangASTContext::DeclContextGetAsDeclContext(dwarf->GetDeclContextContainingUID(die.GetID())); - if (clang::NamespaceDecl *ns_decl = ClangASTContext::DeclContextGetAsNamespaceDecl(imported_decl)) + if (clang::NamespaceDecl *ns_decl = ClangASTContext::DeclContextGetAsNamespaceDecl(imported_decl_ctx)) decl = m_ast.CreateUsingDirectiveDeclaration(decl_context, ns_decl); } } @@ -4001,34 +4257,3 @@ DWARFASTParserClang::CopyUniqueClassMethodTypes (const DWARFDIE &src_class_die, return (failures.Size() != 0); } - -bool -DWARFASTParserClang::LayoutRecordType(const clang::RecordDecl *record_decl, - uint64_t &bit_size, - uint64_t &alignment, - llvm::DenseMap &field_offsets, - llvm::DenseMap &base_offsets, - llvm::DenseMap &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 index 3814758fdd2c..0826423b0359 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -19,11 +19,12 @@ #include "clang/AST/CharUnits.h" // Project includes +#include "DWARFASTParser.h" +#include "DWARFDefines.h" #include "lldb/Core/ClangForward.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Symbol/ClangASTContext.h" -#include "DWARFDefines.h" -#include "DWARFASTParser.h" +#include "lldb/Symbol/ClangASTImporter.h" class DWARFDebugInfoEntry; class DWARFDIECollection; @@ -35,6 +36,7 @@ public: ~DWARFASTParserClang() override; + // DWARFASTParser interface. lldb::TypeSP ParseTypeFromDWARF (const lldb_private::SymbolContext& sc, const DWARFDIE &die, @@ -46,12 +48,6 @@ public: 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, @@ -69,43 +65,19 @@ public: lldb_private::CompilerDeclContext GetDeclContextContainingUIDFromDWARF (const DWARFDIE &die) override; - bool - LayoutRecordType(const clang::RecordDecl *record_decl, - uint64_t &bit_size, - uint64_t &alignment, - llvm::DenseMap &field_offsets, - llvm::DenseMap &base_offsets, - llvm::DenseMap &vbase_offsets); + lldb_private::ClangASTImporter & + GetClangASTImporter(); protected: class DelayedAddObjCClassProperty; typedef std::vector DelayedPropertyList; - struct LayoutInfo - { - LayoutInfo () : - bit_size(0), - alignment(0), - field_offsets(), - base_offsets(), - vbase_offsets() - { - } - uint64_t bit_size; - uint64_t alignment; - llvm::DenseMap field_offsets; - llvm::DenseMap base_offsets; - llvm::DenseMap vbase_offsets; - }; - clang::BlockDecl * ResolveBlockDIE (const DWARFDIE &die); clang::NamespaceDecl * ResolveNamespaceDIE (const DWARFDIE &die); - typedef llvm::DenseMap RecordDeclToLayoutMap; - bool ParseTemplateDIE (const DWARFDIE &die, lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos); @@ -114,17 +86,12 @@ protected: 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& base_classes, - std::vector& member_accessibilities, - DWARFDIECollection& member_function_dies, - DelayedPropertyList& delayed_properties, - lldb::AccessType &default_accessibility, - bool &is_a_class, - LayoutInfo &layout_info); + ParseChildMembers(const lldb_private::SymbolContext &sc, const DWARFDIE &die, + lldb_private::CompilerType &class_compiler_type, const lldb::LanguageType class_language, + std::vector &base_classes, std::vector &member_accessibilities, + DWARFDIECollection &member_function_dies, DelayedPropertyList &delayed_properties, + lldb::AccessType &default_accessibility, bool &is_a_class, + lldb_private::ClangASTImporter::LayoutInfo &layout_info); size_t ParseChildParameters (const lldb_private::SymbolContext& sc, @@ -133,6 +100,7 @@ protected: bool skip_artificial, bool &is_static, bool &is_variadic, + bool &has_template_params, std::vector& function_args, std::vector& function_param_decls, unsigned &type_quals); @@ -181,9 +149,6 @@ protected: void LinkDeclToDIE (clang::Decl *decl, const DWARFDIE &die); - lldb_private::ClangASTImporter & - GetClangASTImporter(); - lldb::TypeSP ParseTypeFromDWO (const DWARFDIE &die, lldb_private::Log *log); @@ -206,7 +171,6 @@ protected: 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 m_clang_ast_importer_ap; }; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp index bde2694461e2..346e2d63b908 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp @@ -144,7 +144,7 @@ DWARFASTParserGo::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, cons } } - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", dwarf->MakeUserID(die.GetOffset()), + 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) @@ -183,7 +183,7 @@ DWARFASTParserGo::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, cons break; } - type_sp.reset(new Type(dwarf->MakeUserID(die.GetOffset()), dwarf, type_name_const_str, byte_size, + type_sp.reset(new Type(die.GetID(), 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(); @@ -254,7 +254,7 @@ DWARFASTParserGo::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, cons } } - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()), + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr); bool compiler_type_was_created = false; @@ -265,7 +265,7 @@ DWARFASTParserGo::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, cons 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, + type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, byte_size, NULL, LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, compiler_type, Type::eResolveStateForward)); @@ -347,7 +347,7 @@ DWARFASTParserGo::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, cons } } - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()), + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr); std::vector function_param_types; @@ -363,7 +363,7 @@ DWARFASTParserGo::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, cons 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, + type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, 0, NULL, LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, compiler_type, Type::eResolveStateFull)); assert(type_sp.get()); @@ -410,7 +410,7 @@ DWARFASTParserGo::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, cons } } - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", dwarf->MakeUserID(die.GetOffset()), + 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(type_die_offset); @@ -433,7 +433,7 @@ DWARFASTParserGo::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, cons { 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, + type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, byte_stride, NULL, type_die_offset, Type::eEncodingIsUID, &decl, compiler_type, Type::eResolveStateFull)); type_sp->SetEncodingType(element_type); @@ -463,7 +463,7 @@ DWARFASTParserGo::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, cons else if (sc.function != NULL && sc_parent_die) { symbol_context_scope = - sc.function->GetBlock(true).FindBlockByID(dwarf->MakeUserID(sc_parent_die.GetOffset())); + sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); if (symbol_context_scope == NULL) symbol_context_scope = sc.function; } @@ -510,7 +510,7 @@ DWARFASTParserGo::ParseChildParameters(const SymbolContext &sc, if (num_attributes > 0) { Declaration decl; - dw_offset_t param_type_die_offset = DW_INVALID_OFFSET; + DWARFFormValue param_type_die_offset; uint32_t i; for (i = 0; i < num_attributes; ++i) @@ -525,7 +525,7 @@ DWARFASTParserGo::ParseChildParameters(const SymbolContext &sc, // = form_value.AsCString(); break; case DW_AT_type: - param_type_die_offset = form_value.Reference(); + param_type_die_offset = form_value; break; case DW_AT_location: // if (form_value.BlockData()) @@ -547,7 +547,7 @@ DWARFASTParserGo::ParseChildParameters(const SymbolContext &sc, } } - Type *type = parent_die.ResolveTypeUID(param_type_die_offset); + Type *type = parent_die.ResolveTypeUID(DIERef(param_type_die_offset)); if (type) { function_param_types.push_back(type->GetForwardCompilerType()); @@ -628,7 +628,7 @@ DWARFASTParserGo::CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type 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()), + log, "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...", die.GetID(), DW_TAG_value_to_name(tag), type->GetName().AsCString()); assert(compiler_type); DWARFAttributes attributes; @@ -683,7 +683,7 @@ DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc, const DWARFDIE &par Declaration decl; const char *name = NULL; - lldb::user_id_t encoding_uid = LLDB_INVALID_UID; + DWARFFormValue encoding_uid; uint32_t member_byte_offset = UINT32_MAX; uint32_t i; for (i = 0; i < num_attributes; ++i) @@ -698,7 +698,7 @@ DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc, const DWARFDIE &par name = form_value.AsCString(); break; case DW_AT_type: - encoding_uid = form_value.Reference(); + encoding_uid = form_value; break; case DW_AT_data_member_location: if (form_value.BlockData()) @@ -715,7 +715,7 @@ DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc, const DWARFDIE &par NULL, // RegisterContext * module_sp, debug_info_data, die.GetCU(), block_offset, block_length, eRegisterKindDWARF, - &initialValue, memberOffset, NULL)) + &initialValue, NULL, memberOffset, NULL)) { member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); } @@ -735,7 +735,7 @@ DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc, const DWARFDIE &par } } - Type *member_type = die.ResolveTypeUID(encoding_uid); + Type *member_type = die.ResolveTypeUID(DIERef(encoding_uid)); if (member_type) { CompilerType member_go_type = member_type->GetFullCompilerType(); @@ -808,10 +808,12 @@ DWARFASTParserGo::ParseFunctionFromDWARF(const SymbolContext &sc, const DWARFDIE if (dwarf->FixupAddress(func_range.GetBaseAddress())) { - const user_id_t func_user_id = dwarf->MakeUserID(die.GetOffset()); + const user_id_t func_user_id = die.GetID(); 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_user_id, // UserID is the DIE offset + func_user_id, + func_name, + func_type, func_range)); // first address range if (func_sp.get() != NULL) diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp new file mode 100644 index 000000000000..b21bf2ded489 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp @@ -0,0 +1,555 @@ +//===-- DWARFASTParserJava.cpp ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFASTParserJava.h" +#include "DWARFAttribute.h" +#include "DWARFCompileUnit.h" +#include "DWARFDebugInfoEntry.h" +#include "DWARFDebugInfoEntry.h" +#include "DWARFDeclContext.h" +#include "SymbolFileDWARF.h" + +#include "lldb/Core/Module.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/SymbolContextScope.h" +#include "lldb/Symbol/TypeList.h" + +using namespace lldb; +using namespace lldb_private; + +DWARFASTParserJava::DWARFASTParserJava(JavaASTContext &ast) : m_ast(ast) +{ +} + +DWARFASTParserJava::~DWARFASTParserJava() +{ +} + +TypeSP +DWARFASTParserJava::ParseBaseTypeFromDIE(const DWARFDIE &die) +{ + SymbolFileDWARF *dwarf = die.GetDWARF(); + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + + ConstString type_name; + uint64_t byte_size = 0; + + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + for (uint32_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_name: + type_name.SetCString(form_value.AsCString()); + break; + case DW_AT_byte_size: + byte_size = form_value.Unsigned(); + break; + case DW_AT_encoding: + break; + default: + assert(false && "Unsupported attribute for DW_TAG_base_type"); + } + } + } + + Declaration decl; + CompilerType compiler_type = m_ast.CreateBaseType(type_name); + return std::make_shared(die.GetID(), dwarf, type_name, byte_size, nullptr, LLDB_INVALID_UID, + Type::eEncodingIsUID, decl, compiler_type, Type::eResolveStateFull); +} + +TypeSP +DWARFASTParserJava::ParseArrayTypeFromDIE(const DWARFDIE &die) +{ + SymbolFileDWARF *dwarf = die.GetDWARF(); + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + + ConstString linkage_name; + DWARFFormValue type_attr_value; + lldb::addr_t data_offset = LLDB_INVALID_ADDRESS; + DWARFExpression length_expression(die.GetCU()); + + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + for (uint32_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_linkage_name: + linkage_name.SetCString(form_value.AsCString()); + break; + case DW_AT_type: + type_attr_value = form_value; + break; + case DW_AT_data_member_location: + data_offset = form_value.Unsigned(); + break; + case DW_AT_declaration: + break; + default: + assert(false && "Unsupported attribute for DW_TAG_array_type"); + } + } + } + + for (DWARFDIE child_die = die.GetFirstChild(); child_die.IsValid(); child_die = child_die.GetSibling()) + { + if (child_die.Tag() == DW_TAG_subrange_type) + { + DWARFAttributes attributes; + const size_t num_attributes = child_die.GetAttributes(attributes); + for (uint32_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_count: + if (form_value.BlockData()) + length_expression.CopyOpcodeData(form_value.BlockData(), form_value.Unsigned(), + child_die.GetCU()->GetByteOrder(), + child_die.GetCU()->GetAddressByteSize()); + break; + default: + assert(false && "Unsupported attribute for DW_TAG_subrange_type"); + } + } + } + } + else + { + assert(false && "Unsupported child for DW_TAG_array_type"); + } + } + + DIERef type_die_ref(type_attr_value); + Type *element_type = dwarf->ResolveTypeUID(type_die_ref); + if (!element_type) + return nullptr; + + CompilerType element_compiler_type = element_type->GetForwardCompilerType(); + CompilerType array_compiler_type = + m_ast.CreateArrayType(linkage_name, element_compiler_type, length_expression, data_offset); + + Declaration decl; + TypeSP type_sp(new Type(die.GetID(), dwarf, array_compiler_type.GetTypeName(), -1, nullptr, + type_die_ref.GetUID(dwarf), Type::eEncodingIsUID, &decl, + array_compiler_type, Type::eResolveStateFull)); + type_sp->SetEncodingType(element_type); + return type_sp; +} + +TypeSP +DWARFASTParserJava::ParseReferenceTypeFromDIE(const DWARFDIE &die) +{ + SymbolFileDWARF *dwarf = die.GetDWARF(); + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + + Declaration decl; + DWARFFormValue type_attr_value; + + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + for (uint32_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_type: + type_attr_value = form_value; + break; + default: + assert(false && "Unsupported attribute for DW_TAG_array_type"); + } + } + } + + DIERef type_die_ref(type_attr_value); + Type *pointee_type = dwarf->ResolveTypeUID(type_die_ref); + if (!pointee_type) + return nullptr; + + CompilerType pointee_compiler_type = pointee_type->GetForwardCompilerType(); + CompilerType reference_compiler_type = m_ast.CreateReferenceType(pointee_compiler_type); + TypeSP type_sp(new Type(die.GetID(), dwarf, reference_compiler_type.GetTypeName(), -1, nullptr, + type_die_ref.GetUID(dwarf), Type::eEncodingIsUID, &decl, + reference_compiler_type, Type::eResolveStateFull)); + type_sp->SetEncodingType(pointee_type); + return type_sp; +} + +lldb::TypeSP +DWARFASTParserJava::ParseClassTypeFromDIE(const DWARFDIE &die, bool &is_new_type) +{ + SymbolFileDWARF *dwarf = die.GetDWARF(); + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + + Declaration decl; + ConstString name; + ConstString linkage_name; + bool is_forward_declaration = false; + uint32_t byte_size = 0; + + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + for (uint32_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_name: + name.SetCString(form_value.AsCString()); + break; + case DW_AT_declaration: + is_forward_declaration = form_value.Boolean(); + break; + case DW_AT_byte_size: + byte_size = form_value.Unsigned(); + break; + case DW_AT_linkage_name: + linkage_name.SetCString(form_value.AsCString()); + break; + default: + assert(false && "Unsupported attribute for DW_TAG_class_type"); + } + } + } + + UniqueDWARFASTType unique_ast_entry; + if (name) + { + std::string qualified_name; + if (die.GetQualifiedName(qualified_name)) + { + name.SetCString(qualified_name.c_str()); + if (dwarf->GetUniqueDWARFASTTypeMap().Find(name, die, Declaration(), -1, unique_ast_entry)) + { + if (unique_ast_entry.m_type_sp) + { + dwarf->GetDIEToType()[die.GetDIE()] = unique_ast_entry.m_type_sp.get(); + is_new_type = false; + return unique_ast_entry.m_type_sp; + } + } + } + } + + if (is_forward_declaration) + { + DWARFDeclContext die_decl_ctx; + die.GetDWARFDeclContext(die_decl_ctx); + + TypeSP type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); + if (type_sp) + { + // We found a real definition for this type elsewhere so lets use it + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + is_new_type = false; + return type_sp; + } + } + + CompilerType compiler_type(&m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); + if (!compiler_type) + compiler_type = m_ast.CreateObjectType(name, linkage_name, byte_size); + + is_new_type = true; + TypeSP type_sp(new Type(die.GetID(), dwarf, name, + -1, // byte size isn't specified + nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, compiler_type, + Type::eResolveStateForward)); + + // Add our type to the unique type map + unique_ast_entry.m_type_sp = type_sp; + unique_ast_entry.m_die = die; + unique_ast_entry.m_declaration = decl; + unique_ast_entry.m_byte_size = -1; + dwarf->GetUniqueDWARFASTTypeMap().Insert(name, unique_ast_entry); + + if (!is_forward_declaration) + { + // Leave this as a forward declaration until we need to know the details of the type + dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = compiler_type.GetOpaqueQualType(); + dwarf->GetForwardDeclClangTypeToDie()[compiler_type.GetOpaqueQualType()] = die.GetDIERef(); + } + return type_sp; +} + +lldb::TypeSP +DWARFASTParserJava::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, + lldb_private::Log *log, bool *type_is_new_ptr) +{ + if (type_is_new_ptr) + *type_is_new_ptr = false; + + if (!die) + return nullptr; + + SymbolFileDWARF *dwarf = die.GetDWARF(); + + Type *type_ptr = dwarf->m_die_to_type.lookup(die.GetDIE()); + if (type_ptr == DIE_IS_BEING_PARSED) + return nullptr; + if (type_ptr != nullptr) + return type_ptr->shared_from_this(); + + TypeSP type_sp; + if (type_is_new_ptr) + *type_is_new_ptr = true; + + switch (die.Tag()) + { + case DW_TAG_base_type: + { + type_sp = ParseBaseTypeFromDIE(die); + break; + } + case DW_TAG_array_type: + { + type_sp = ParseArrayTypeFromDIE(die); + break; + } + case DW_TAG_class_type: + { + bool is_new_type = false; + type_sp = ParseClassTypeFromDIE(die, is_new_type); + if (!is_new_type) + return type_sp; + break; + } + case DW_TAG_reference_type: + { + type_sp = ParseReferenceTypeFromDIE(die); + break; + } + } + + if (!type_sp) + return nullptr; + + DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die); + dw_tag_t sc_parent_tag = sc_parent_die.Tag(); + + SymbolContextScope *symbol_context_scope = nullptr; + if (sc_parent_tag == DW_TAG_compile_unit) + { + symbol_context_scope = sc.comp_unit; + } + else if (sc.function != nullptr && sc_parent_die) + { + symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); + if (symbol_context_scope == nullptr) + symbol_context_scope = sc.function; + } + + if (symbol_context_scope != nullptr) + type_sp->SetSymbolContextScope(symbol_context_scope); + + dwarf->GetTypeList()->Insert(type_sp); + dwarf->m_die_to_type[die.GetDIE()] = type_sp.get(); + + return type_sp; +} + +lldb_private::Function * +DWARFASTParserJava::ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die) +{ + assert(die.Tag() == DW_TAG_subprogram); + + const char *name = nullptr; + const char *mangled = nullptr; + int decl_file = 0; + int decl_line = 0; + int decl_column = 0; + int call_file = 0; + int call_line = 0; + int call_column = 0; + DWARFRangeList func_ranges; + DWARFExpression frame_base(die.GetCU()); + + 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()) + { + std::unique_ptr 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)); + + if (die.GetDWARF()->FixupAddress(func_range.GetBaseAddress())) + { + FunctionSP func_sp(new Function(sc.comp_unit, die.GetID(), die.GetID(), + Mangled(ConstString(name), false), + nullptr, // No function types in java + func_range)); + if (frame_base.IsValid()) + func_sp->GetFrameBaseExpression() = frame_base; + sc.comp_unit->AddFunction(func_sp); + + return func_sp.get(); + } + } + } + return nullptr; +} + +bool +DWARFASTParserJava::CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type, + lldb_private::CompilerType &java_type) +{ + switch (die.Tag()) + { + case DW_TAG_class_type: + { + if (die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 0) + { + if (die.HasChildren()) + ParseChildMembers(die, java_type); + m_ast.CompleteObjectType(java_type); + return java_type.IsValid(); + } + } + break; + default: + assert(false && "Not a forward java type declaration!"); + break; + } + return false; +} + +void +DWARFASTParserJava::ParseChildMembers(const DWARFDIE &parent_die, CompilerType &compiler_type) +{ + DWARFCompileUnit *dwarf_cu = parent_die.GetCU(); + for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) + { + switch (die.Tag()) + { + case DW_TAG_member: + { + const char *name = nullptr; + DWARFFormValue encoding_uid; + uint32_t member_byte_offset = UINT32_MAX; + DWARFExpression member_location_expression(dwarf_cu); + + DWARFAttributes attributes; + size_t num_attributes = die.GetAttributes(attributes); + for (size_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attributes.AttributeAtIndex(i)) + { + case DW_AT_name: + name = form_value.AsCString(); + break; + case DW_AT_type: + encoding_uid = form_value; + break; + case DW_AT_data_member_location: + if (form_value.BlockData()) + member_location_expression.CopyOpcodeData( + form_value.BlockData(), form_value.Unsigned(), dwarf_cu->GetByteOrder(), + dwarf_cu->GetAddressByteSize()); + else + member_byte_offset = form_value.Unsigned(); + break; + case DW_AT_artificial: + static_cast(form_value.Boolean()); + break; + case DW_AT_accessibility: + // TODO: Handle when needed + break; + default: + assert(false && "Unhandled attribute for DW_TAG_member"); + break; + } + } + } + + if (strcmp(name, ".dynamic_type") == 0) + m_ast.SetDynamicTypeId(compiler_type, member_location_expression); + else + { + if (Type *member_type = die.ResolveTypeUID(DIERef(encoding_uid))) + m_ast.AddMemberToObject(compiler_type, ConstString(name), member_type->GetFullCompilerType(), + member_byte_offset); + } + break; + } + case DW_TAG_inheritance: + { + DWARFFormValue encoding_uid; + uint32_t member_byte_offset = UINT32_MAX; + + DWARFAttributes attributes; + size_t num_attributes = die.GetAttributes(attributes); + for (size_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attributes.AttributeAtIndex(i)) + { + case DW_AT_type: + encoding_uid = form_value; + break; + case DW_AT_data_member_location: + member_byte_offset = form_value.Unsigned(); + break; + case DW_AT_accessibility: + // In java all base class is public so we can ignore this attribute + break; + default: + assert(false && "Unhandled attribute for DW_TAG_member"); + break; + } + } + } + if (Type *base_type = die.ResolveTypeUID(DIERef(encoding_uid))) + m_ast.AddBaseClassToObject(compiler_type, base_type->GetFullCompilerType(), member_byte_offset); + break; + } + default: + break; + } + } +} diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.h new file mode 100644 index 000000000000..6a7eee75e6f7 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.h @@ -0,0 +1,90 @@ +//===-- DWARFASTParserJava.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_DWARFASTParserJava_h_ +#define SymbolFileDWARF_DWARFASTParserJava_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 "DWARFASTParser.h" +#include "DWARFDIE.h" +#include "DWARFDefines.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Symbol/JavaASTContext.h" + +class DWARFDebugInfoEntry; +class DWARFDIECollection; + +class DWARFASTParserJava : public DWARFASTParser +{ +public: + DWARFASTParserJava(lldb_private::JavaASTContext &ast); + ~DWARFASTParserJava() 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 &java_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 + GetDIEForDeclContext(lldb_private::CompilerDeclContext decl_context) override + { + return std::vector(); + } + + void + ParseChildMembers(const DWARFDIE &parent_die, lldb_private::CompilerType &class_compiler_type); + +private: + lldb_private::JavaASTContext &m_ast; + + lldb::TypeSP + ParseBaseTypeFromDIE(const DWARFDIE &die); + + lldb::TypeSP + ParseArrayTypeFromDIE(const DWARFDIE &die); + + lldb::TypeSP + ParseReferenceTypeFromDIE(const DWARFDIE &die); + + lldb::TypeSP + ParseClassTypeFromDIE(const DWARFDIE &die, bool &is_new_type); +}; + +#endif // SymbolFileDWARF_DWARFASTParserJava_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp index e7cb2b413ad7..c5d7568b5272 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -311,46 +311,12 @@ 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) + const DWARFDebugInfoEntry &cu_die = m_die_array.front(); + std::unique_ptr dwo_symbol_file = m_dwarf2Data->GetDwoSymbolFileForCompileUnit(*this, cu_die); + if (!dwo_symbol_file) return; - std::unique_ptr 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. @@ -467,7 +433,7 @@ 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); + return DIERef(local_id, local_id).GetUID(m_dwarf2Data); else return local_id; } @@ -665,7 +631,7 @@ DWARFCompileUnit::GetDIE (dw_offset_t die_offset) { // 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 m_dwarf2Data->DebugInfo()->GetDIEForDIEOffset(die_offset); } } return DWARFDIE(); // Not found @@ -789,20 +755,21 @@ DWARFCompileUnit::IndexPrivate (DWARFCompileUnit* dwarf_cu, switch (tag) { - case DW_TAG_subprogram: - case DW_TAG_inlined_subroutine: + case DW_TAG_array_type: case DW_TAG_base_type: case DW_TAG_class_type: case DW_TAG_constant: case DW_TAG_enumeration_type: + case DW_TAG_inlined_subroutine: + case DW_TAG_namespace: case DW_TAG_string_type: - case DW_TAG_subroutine_type: case DW_TAG_structure_type: - case DW_TAG_union_type: + case DW_TAG_subprogram: + case DW_TAG_subroutine_type: case DW_TAG_typedef: - case DW_TAG_namespace: - case DW_TAG_variable: + case DW_TAG_union_type: case DW_TAG_unspecified_type: + case DW_TAG_variable: break; default: @@ -977,7 +944,7 @@ DWARFCompileUnit::IndexPrivate (DWARFCompileUnit* dwarf_cu, // as our name. If it starts with '_', then it is ok, else compare // the string to make sure it isn't the same and we don't end up // with duplicate entries - if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (name && ::strcmp(name, mangled_cstr) != 0))) + if (name && name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) { Mangled mangled (ConstString(mangled_cstr), true); func_fullnames.Insert (mangled.GetMangledName(), DIERef(cu_offset, die.GetOffset())); @@ -1000,7 +967,7 @@ DWARFCompileUnit::IndexPrivate (DWARFCompileUnit* dwarf_cu, // as our name. If it starts with '_', then it is ok, else compare // the string to make sure it isn't the same and we don't end up // with duplicate entries - if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) + if (name && name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) { Mangled mangled (ConstString(mangled_cstr), true); func_fullnames.Insert (mangled.GetMangledName(), DIERef(cu_offset, die.GetOffset())); @@ -1014,20 +981,21 @@ DWARFCompileUnit::IndexPrivate (DWARFCompileUnit* dwarf_cu, } break; + case DW_TAG_array_type: case DW_TAG_base_type: case DW_TAG_class_type: case DW_TAG_constant: case DW_TAG_enumeration_type: case DW_TAG_string_type: - case DW_TAG_subroutine_type: case DW_TAG_structure_type: - case DW_TAG_union_type: + case DW_TAG_subroutine_type: case DW_TAG_typedef: + case DW_TAG_union_type: case DW_TAG_unspecified_type: - if (name && is_declaration == false) - { + if (name && !is_declaration) types.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset())); - } + if (mangled_cstr && !is_declaration) + types.Insert (ConstString(mangled_cstr), DIERef(cu_offset, die.GetOffset())); break; case DW_TAG_namespace: @@ -1180,7 +1148,7 @@ DWARFCompileUnit::LanguageTypeFromDWARF(uint64_t val) { case DW_LANG_Mips_Assembler: return eLanguageTypeMipsAssembler; - case 0x8e57: // FIXME: needs to be added to llvm + case DW_LANG_GOOGLE_RenderScript: return eLanguageTypeExtRenderScript; default: return static_cast(val); @@ -1259,3 +1227,9 @@ 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; } + +lldb::ByteOrder +DWARFCompileUnit::GetByteOrder() const +{ + return m_dwarf2Data->GetObjectFile()->GetByteOrder(); +} diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h index 0fcaaca09ed8..8d96e3698ab2 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h @@ -59,6 +59,8 @@ public: void BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data, DWARFDebugAranges* debug_aranges); + lldb::ByteOrder + GetByteOrder() const; lldb_private::TypeSystem * GetTypeSystem(); diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index 0564de9e5dd1..0f02c74fd2eb 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -9,6 +9,7 @@ #include "DWARFDIE.h" +#include "DWARFASTParser.h" #include "DWARFCompileUnit.h" #include "DWARFDebugAbbrev.h" #include "DWARFDebugAranges.h" @@ -127,6 +128,21 @@ DWARFDIE::GetAttributeValueAsSigned (const dw_attr_t attr, int64_t fail_value) c return fail_value; } +DWARFDIE +DWARFDIE::GetAttributeValueAsReferenceDIE (const dw_attr_t attr) const +{ + if (IsValid()) + { + DWARFCompileUnit *cu = GetCU(); + SymbolFileDWARF *dwarf = cu->GetSymbolFileDWARF(); + const bool check_specification_or_abstract_origin = true; + DWARFFormValue form_value; + if (m_die->GetAttributeValue(dwarf, cu, attr, form_value, nullptr, check_specification_or_abstract_origin)) + return dwarf->GetDIE(DIERef(form_value)); + } + return DWARFDIE(); +} + uint64_t DWARFDIE::GetAttributeValueAsReference (const dw_attr_t attr, uint64_t fail_value) const { @@ -166,7 +182,7 @@ DWARFDIE::LookupDeepestBlock (lldb::addr_t file_addr) const 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(dwarf->DebugInfo()->GetCompileUnit(DIERef(cu->GetOffset(), block_die->GetOffset())), block_die); } } } @@ -176,27 +192,7 @@ DWARFDIE::LookupDeepestBlock (lldb::addr_t file_addr) const 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; + return GetDIERef().GetUID(GetDWARF()); } const char * @@ -274,11 +270,11 @@ DWARFDIE::ResolveType () const } lldb_private::Type * -DWARFDIE::ResolveTypeUID (lldb::user_id_t uid) const +DWARFDIE::ResolveTypeUID (const DIERef &die_ref) const { SymbolFileDWARF *dwarf = GetDWARF(); if (dwarf) - return dwarf->ResolveTypeUID(uid); + return dwarf->ResolveTypeUID(dwarf->GetDIE(die_ref), true); else return nullptr; } @@ -302,6 +298,7 @@ DWARFDIE::GetDWARFDeclContext (DWARFDeclContext &dwarf_decl_ctx) const { if (IsValid()) { + dwarf_decl_ctx.SetLanguage(GetLanguage()); m_die->GetDWARFDeclContext (GetDWARF(), GetCU(), dwarf_decl_ctx); } else @@ -530,6 +527,36 @@ DWARFDIE::Dump (lldb_private::Stream *s, const uint32_t recurse_depth) const } +CompilerDecl +DWARFDIE::GetDecl () const +{ + DWARFASTParser *dwarf_ast = GetDWARFParser(); + if (dwarf_ast) + return dwarf_ast->GetDeclForUIDFromDWARF(*this); + else + return CompilerDecl(); +} + +CompilerDeclContext +DWARFDIE::GetDeclContext () const +{ + DWARFASTParser *dwarf_ast = GetDWARFParser(); + if (dwarf_ast) + return dwarf_ast->GetDeclContextForUIDFromDWARF(*this); + else + return CompilerDeclContext(); +} + +CompilerDeclContext +DWARFDIE::GetContainingDeclContext () const +{ + DWARFASTParser *dwarf_ast = GetDWARFParser(); + if (dwarf_ast) + return dwarf_ast->GetDeclContextContainingUIDFromDWARF(*this); + else + return CompilerDeclContext(); +} + 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 index db37a45ad01a..2dcd1d7dc43e 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -58,7 +58,7 @@ public: //---------------------------------------------------------------------- // Tests //---------------------------------------------------------------------- - operator bool () const + explicit operator bool () const { return IsValid(); } @@ -180,9 +180,11 @@ public: 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; + ResolveTypeUID (const DIERef &die_ref) const; //---------------------------------------------------------------------- // Functions for obtaining DIE relations and references @@ -245,6 +247,9 @@ public: uint64_t GetAttributeValueAsReference (const dw_attr_t attr, uint64_t fail_value) const; + DWARFDIE + GetAttributeValueAsReferenceDIE (const dw_attr_t attr) const; + uint64_t GetAttributeValueAsAddress (const dw_attr_t attr, uint64_t fail_value) const; @@ -270,6 +275,15 @@ public: void Dump (lldb_private::Stream *s, const uint32_t recurse_depth) const; + lldb_private::CompilerDecl + GetDecl () const; + + lldb_private::CompilerDeclContext + GetDeclContext() const; + + lldb_private::CompilerDeclContext + GetContainingDeclContext() const; + protected: DWARFCompileUnit *m_cu; DWARFDebugInfoEntry *m_die; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp index 9e021c7185bd..e9f09fd8776c 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp @@ -16,17 +16,6 @@ using namespace lldb_private; using namespace std; -bool -DWARFDIECollection::Insert(const DWARFDIE &die) -{ - iterator end_pos = m_dies.end(); - iterator insert_pos = upper_bound(m_dies.begin(), end_pos, die); - if (insert_pos != end_pos && (*insert_pos == die)) - return false; - m_dies.insert(insert_pos, die); - return true; -} - void DWARFDIECollection::Append (const DWARFDIE &die) { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h index e39e1aa4ccda..83d58ec49300 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h @@ -33,9 +33,6 @@ public: DWARFDIE GetDIEAtIndex (uint32_t idx) const; - bool - Insert(const DWARFDIE &die); - size_t Size() const; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index a1b00d1892e9..417f2cd79bda 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -209,48 +209,51 @@ DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr) } DWARFCompileUnit * -DWARFDebugInfo::GetCompileUnitContainingDIE (const DIERef& die_ref) +DWARFDebugInfo::GetCompileUnit (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; - } + if (die_ref.cu_offset == DW_INVALID_OFFSET) + return GetCompileUnitContainingDIEOffset(die_ref.die_offset); + else + return GetCompileUnit(die_ref.cu_offset); +} + +DWARFCompileUnit* +DWARFDebugInfo::GetCompileUnitContainingDIEOffset(dw_offset_t die_offset) +{ + ParseCompileUnitHeadersIfNeeded(); DWARFCompileUnitSP cu_sp; - if (search_offset != DW_INVALID_OFFSET) - { - ParseCompileUnitHeadersIfNeeded(); - // 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) - { - if ((is_cu_offset && m_compile_units[0]->GetOffset() == search_offset) || - (!is_cu_offset && m_compile_units[0]->ContainsDIEOffset(search_offset))) - { - cu_sp = m_compile_units[0]; - } - } - else if (num_cus) + // 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) + { + if (m_compile_units[0]->ContainsDIEOffset(die_offset)) + return m_compile_units[0].get(); + } + 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, die_offset, OffsetLessThanCompileUnitOffset); + if (pos != begin_pos) { - 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; - } - } + --pos; + if ((*pos)->ContainsDIEOffset(die_offset)) + return (*pos).get(); } } - return cu_sp.get(); + + return nullptr; +} + +DWARFDIE +DWARFDebugInfo::GetDIEForDIEOffset(dw_offset_t die_offset) +{ + DWARFCompileUnit* cu = GetCompileUnitContainingDIEOffset(die_offset); + if (cu) + return cu->GetDIE(die_offset); + return DWARFDIE(); } //---------------------------------------------------------------------- @@ -261,7 +264,7 @@ DWARFDebugInfo::GetCompileUnitContainingDIE (const DIERef& die_ref) DWARFDIE DWARFDebugInfo::GetDIE(const DIERef& die_ref) { - DWARFCompileUnit *cu = GetCompileUnitContainingDIE(die_ref); + DWARFCompileUnit *cu = GetCompileUnit(die_ref); if (cu) return cu->GetDIE (die_ref.die_offset); return DWARFDIE(); // Not found diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h index ea2e204db702..7783135bdb95 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h @@ -39,9 +39,10 @@ public: size_t GetNumCompileUnits(); bool ContainsCompileUnit (const DWARFCompileUnit *cu) const; DWARFCompileUnit* GetCompileUnitAtIndex (uint32_t idx); - DWARFCompileUnit* GetCompileUnit (dw_offset_t cu_offset, uint32_t* idx_ptr = NULL); - DWARFCompileUnit* GetCompileUnitContainingDIE (const DIERef& die_ref); - + DWARFCompileUnit* GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr = NULL); + DWARFCompileUnit* GetCompileUnitContainingDIEOffset (dw_offset_t die_offset); + DWARFCompileUnit* GetCompileUnit(const DIERef& die_ref); + DWARFDIE GetDIEForDIEOffset(dw_offset_t die_offset); DWARFDIE GetDIE (const DIERef& die_ref); void Dump(lldb_private::Stream *s, const uint32_t die_offset, const uint32_t recurse_depth); diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index b9d825489aef..f48d8fc9eeb2 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -482,11 +482,19 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges case DW_AT_ranges: { const DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges(); - debug_ranges->FindRanges(form_value.Unsigned(), ranges); - // All DW_AT_ranges are relative to the base address of the - // compile unit. We add the compile unit base address to make - // sure all the addresses are properly fixed up. - ranges.Slide(cu->GetBaseAddress()); + if (debug_ranges) + { + debug_ranges->FindRanges(form_value.Unsigned(), ranges); + // All DW_AT_ranges are relative to the base address of the + // compile unit. We add the compile unit base address to make + // sure all the addresses are properly fixed up. + ranges.Slide(cu->GetBaseAddress()); + } + else + { + cu->GetSymbolFileDWARF()->GetObjectFile()->GetModule()->ReportError ("{0x%8.8x}: DIE has DW_AT_ranges(0x%" PRIx64 ") attribute yet DWARF has no .debug_ranges, please file a bug and attach the file at the start of this error message", + m_offset, form_value.Unsigned()); + } } break; @@ -602,7 +610,7 @@ DWARFDebugInfoEntry::GetDIENamesAndRanges { if (die_ref.die_offset != DW_INVALID_OFFSET) { - DWARFDIE die = dwarf2Data->DebugInfo()->GetDIE(die_ref); + DWARFDIE die = dwarf2Data->GetDIE(die_ref); if (die) die.GetDIE()->GetDIENamesAndRanges(die.GetDWARF(), die.GetCU(), name, mangled, ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column); } @@ -934,7 +942,7 @@ DWARFDebugInfoEntry::GetAttributes (const DWARFCompileUnit* cu, // referencing this DIE because curr_depth is not zero break; } - // Fall through... + LLVM_FALLTHROUGH; default: attributes.Append(cu, offset, attr, form); break; diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index 02bbff8defc0..27b4fe93bc33 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -115,6 +115,13 @@ public: 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 = nullptr, + bool check_specification_or_abstract_origin = false) const; + const char* GetAttributeValueAsString( SymbolFileDWARF* dwarf2Data, const DWARFCompileUnit* cu, @@ -382,12 +389,6 @@ 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 diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h index 4c29447b47bb..2452274a293b 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h @@ -64,7 +64,8 @@ public: }; DWARFDeclContext () : - m_entries() + m_entries(), + m_language(lldb::eLanguageTypeUnknown) { } @@ -115,10 +116,23 @@ public: m_qualified_name.clear(); } + lldb::LanguageType + GetLanguage() const + { + return m_language; + } + + void + SetLanguage(lldb::LanguageType language) + { + m_language = language; + } + protected: typedef std::vector collection; collection m_entries; mutable std::string m_qualified_name; + lldb::LanguageType m_language; }; #endif // SymbolFileDWARF_DWARFDeclContext_h_ diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp index a0ed9731a565..addc14858461 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -167,6 +167,14 @@ DWARFFormValue::DWARFFormValue(const DWARFCompileUnit* cu, dw_form_t form) : { } +void +DWARFFormValue::Clear() +{ + m_cu = nullptr; + m_form = 0; + memset(&m_value, 0, sizeof(m_value)); +} + bool DWARFFormValue::ExtractValue(const DWARFDataExtractor& data, lldb::offset_t* offset_ptr) { diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h index b10f4d3a0ac9..07bd038d9486 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h +++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h @@ -101,6 +101,7 @@ public: static FixedFormSizes GetFixedFormSizesForAddressSize (uint8_t addr_size, bool is_dwarf64); static int Compare (const DWARFFormValue& a, const DWARFFormValue& b); + void Clear(); 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/HashedNameToDIE.cpp b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp index 0db416054ae8..12e1e89c36bd 100644 --- a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp +++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp @@ -220,7 +220,7 @@ DWARFMappedHash::Prologue::AppendAtom (AtomType type, dw_form_t form) 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... + LLVM_FALLTHROUGH; case DW_FORM_flag: case DW_FORM_data1: case DW_FORM_ref1: @@ -230,7 +230,7 @@ DWARFMappedHash::Prologue::AppendAtom (AtomType type, dw_form_t form) case DW_FORM_block2: hash_data_has_fixed_byte_size = false; - // Fall through to the cases below... + LLVM_FALLTHROUGH; case DW_FORM_data2: case DW_FORM_ref2: min_hash_data_byte_size += 2; @@ -238,7 +238,7 @@ DWARFMappedHash::Prologue::AppendAtom (AtomType type, dw_form_t form) case DW_FORM_block4: hash_data_has_fixed_byte_size = false; - // Fall through to the cases below... + LLVM_FALLTHROUGH; case DW_FORM_data4: case DW_FORM_ref4: case DW_FORM_addr: @@ -346,7 +346,8 @@ DWARFMappedHash::Header::Read (const lldb_private::DWARFDataExtractor &data, case eAtomTypeTag: // DW_TAG value for the DIE hash_data.tag = (dw_tag_t)form_value.Unsigned (); - + break; + case eAtomTypeTypeFlags: // Flags from enum TypeFlags hash_data.type_flags = (uint32_t)form_value.Unsigned (); break; @@ -671,6 +672,9 @@ DWARFMappedHash::MemoryTable::AppendAllDIEsInRange (const uint32_t die_offset_st size_t DWARFMappedHash::MemoryTable::FindByName (const char *name, DIEArray &die_offsets) { + if (!name || !name[0]) + return 0; + DIEInfoArray die_info_array; if (FindByName(name, die_info_array)) DWARFMappedHash::ExtractDIEArray (die_info_array, die_offsets); @@ -736,6 +740,9 @@ DWARFMappedHash::MemoryTable::FindCompleteObjCClassByName (const char *name, size_t DWARFMappedHash::MemoryTable::FindByName (const char *name, DIEInfoArray &die_info_array) { + if (!name || !name[0]) + return 0; + Pair kv_pair; size_t old_size = die_info_array.size(); if (Find (name, kv_pair)) diff --git a/source/Plugins/SymbolFile/DWARF/Makefile b/source/Plugins/SymbolFile/DWARF/Makefile deleted file mode 100644 index 509065650ab9..000000000000 --- a/source/Plugins/SymbolFile/DWARF/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/SymbolFile/DWARF/Makefile ------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginSymbolFileDWARF -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 2088864bf6b1..942a5d62d9b4 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -35,16 +35,17 @@ #include "lldb/Symbol/Block.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ClangUtil.h" +#include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/CompilerDecl.h" #include "lldb/Symbol/CompilerDeclContext.h" -#include "lldb/Symbol/CompileUnit.h" -#include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/DebugMacros.h" +#include "lldb/Symbol/LineTable.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/TypeMap.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" @@ -54,7 +55,9 @@ #include "lldb/Utility/TaskPool.h" #include "DWARFASTParser.h" +#include "DWARFASTParserClang.h" #include "DWARFCompileUnit.h" +#include "DWARFDIECollection.h" #include "DWARFDebugAbbrev.h" #include "DWARFDebugAranges.h" #include "DWARFDebugInfo.h" @@ -63,11 +66,10 @@ #include "DWARFDebugPubnames.h" #include "DWARFDebugRanges.h" #include "DWARFDeclContext.h" -#include "DWARFDIECollection.h" #include "DWARFFormValue.h" #include "LogChannelDWARF.h" -#include "SymbolFileDWARFDwo.h" #include "SymbolFileDWARFDebugMap.h" +#include "SymbolFileDWARFDwo.h" #include @@ -277,9 +279,11 @@ SymbolFileDWARF::CreateInstance (ObjectFile* obj_file) TypeList * SymbolFileDWARF::GetTypeList () { - if (GetDebugMapSymfile ()) - return m_debug_map_symfile->GetTypeList(); - return m_obj_file->GetModule()->GetTypeList(); + SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); + if (debug_map_symfile) + return debug_map_symfile->GetTypeList(); + else + return m_obj_file->GetModule()->GetTypeList(); } void @@ -483,15 +487,17 @@ GetDWARFMachOSegmentName () UniqueDWARFASTTypeMap & SymbolFileDWARF::GetUniqueDWARFASTTypeMap () { - if (GetDebugMapSymfile ()) - return m_debug_map_symfile->GetUniqueDWARFASTTypeMap (); - return m_unique_ast_type_map; + SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); + if (debug_map_symfile) + return debug_map_symfile->GetUniqueDWARFASTTypeMap (); + else + return m_unique_ast_type_map; } TypeSystem * SymbolFileDWARF::GetTypeSystemForLanguage (LanguageType language) { - SymbolFileDWARFDebugMap * debug_map_symfile = GetDebugMapSymfile (); + SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); TypeSystem *type_system; if (debug_map_symfile) { @@ -823,30 +829,13 @@ SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) DWARFDebugInfo* info = DebugInfo(); if (info) { - if (GetDebugMapSymfile ()) - { - // The debug map symbol file made the compile units for this DWARF - // file which is .o file with DWARF in it, and we should have - // only 1 compile unit which is at offset zero in the DWARF. - // 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); - if (dwarf_cu && dwarf_cu->GetUserData() == NULL) - dwarf_cu->SetUserData(comp_unit); - return dwarf_cu; - } - else - { - // Just a normal DWARF file whose user ID for the compile unit is - // the DWARF offset itself + // 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()); - if (dwarf_cu && dwarf_cu->GetUserData() == NULL) - dwarf_cu->SetUserData(comp_unit); - return dwarf_cu; - - } + 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; } return NULL; } @@ -893,7 +882,7 @@ SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx) { return dwarf_cu->GetSymbolFileDWARF()->ParseCompileUnit(dwarf_cu, cu_idx); } - else if (GetDebugMapSymfile ()) + else if (dwarf_cu->GetOffset() == 0 && GetDebugMapSymfile ()) { // Let the debug map create the compile unit cu_sp = m_debug_map_symfile->GetCompileUnit(this); @@ -926,12 +915,8 @@ SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx) 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, - dwarf_cu->GetID(), - cu_language, - is_optimized)); + cu_sp.reset(new CompileUnit(module_sp, dwarf_cu, cu_file_spec, dwarf_cu->GetID(), cu_language, + is_optimized ? eLazyBoolYes : eLazyBoolNo)); if (cu_sp) { // If we just created a compile unit with an invalid file spec, try and get the @@ -1007,7 +992,7 @@ SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, const DWARFD bool SymbolFileDWARF::FixupAddress (Address &addr) { - SymbolFileDWARFDebugMap * debug_map_symfile = GetDebugMapSymfile (); + SymbolFileDWARFDebugMap * debug_map_symfile = GetDebugMapSymfile(); if (debug_map_symfile) { return debug_map_symfile->LinkOSOAddress(addr); @@ -1063,7 +1048,6 @@ SymbolFileDWARF::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpec if (cu_die) { const char * cu_comp_dir = resolveCompDir(cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr)); - const dw_offset_t stmt_list = cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list, DW_INVALID_OFFSET); if (stmt_list != DW_INVALID_OFFSET) { @@ -1082,7 +1066,17 @@ SymbolFileDWARF::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpec } bool -SymbolFileDWARF::ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector &imported_modules) +SymbolFileDWARF::ParseCompileUnitIsOptimized(const lldb_private::SymbolContext &sc) +{ + DWARFCompileUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); + if (dwarf_cu) + return dwarf_cu->GetIsOptimized(); + return false; +} + +bool +SymbolFileDWARF::ParseImportedModules(const lldb_private::SymbolContext &sc, + std::vector &imported_modules) { assert (sc.comp_unit); DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit); @@ -1091,9 +1085,40 @@ SymbolFileDWARF::ParseImportedModules (const lldb_private::SymbolContext &sc, st if (ClangModulesDeclVendor::LanguageSupportsClangModules(sc.comp_unit->GetLanguage())) { UpdateExternalModuleListIfNeeded(); - for (const auto &pair : m_external_type_modules) + + if (sc.comp_unit) { - imported_modules.push_back(pair.first); + const DWARFDIE die = dwarf_cu->GetCompileUnitDIEOnly(); + + if (die) + { + for (DWARFDIE child_die = die.GetFirstChild(); + child_die; + child_die = child_die.GetSibling()) + { + if (child_die.Tag() == DW_TAG_imported_declaration) + { + if (DWARFDIE module_die = child_die.GetReferencedDIE(DW_AT_import)) + { + if (module_die.Tag() == DW_TAG_module) + { + if (const char *name = module_die.GetAttributeValueAsString(DW_AT_name, nullptr)) + { + ConstString const_name(name); + imported_modules.push_back(const_name); + } + } + } + } + } + } + } + else + { + for (const auto &pair : m_external_type_modules) + { + imported_modules.push_back(pair.first); + } } } } @@ -1198,13 +1223,14 @@ SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc) lldb::offset_t offset = cu_line_offset; DWARFDebugLine::ParseStatementTable(get_debug_line_data(), &offset, ParseDWARFLineTableCallback, &info); - if (m_debug_map_symfile) + SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); + if (debug_map_symfile) { // We have an object file that has a line table with addresses // that are not linked. We need to link the line table and convert // the addresses that are relative to the .o file into addresses // for the main executable. - sc.comp_unit->SetLineTable (m_debug_map_symfile->LinkOSOLineTable (this, line_table_ap.get())); + sc.comp_unit->SetLineTable (debug_map_symfile->LinkOSOLineTable (this, line_table_ap.get())); } else { @@ -1439,63 +1465,71 @@ SymbolFileDWARF::ParseDeclsForContext (CompilerDeclContext decl_ctx) ast_parser->GetDeclForUIDFromDWARF(decl); } +SymbolFileDWARF * +SymbolFileDWARF::GetDWARFForUID (lldb::user_id_t uid) +{ + // Anytime we get a "lldb::user_id_t" from an lldb_private::SymbolFile API + // we must make sure we use the correct DWARF file when resolving things. + // On MacOSX, when using SymbolFileDWARFDebugMap, we will use multiple + // SymbolFileDWARF classes, one for each .o file. We can often end up + // with references to other DWARF objects and we must be ready to receive + // a "lldb::user_id_t" that specifies a DIE from another SymbolFileDWARF + // instance. + SymbolFileDWARFDebugMap *debug_map = GetDebugMapSymfile(); + if (debug_map) + return debug_map->GetSymbolFileByOSOIndex(debug_map->GetOSOIndexFromUserID(uid)); + return this; +} + +DWARFDIE +SymbolFileDWARF::GetDIEFromUID (lldb::user_id_t uid) +{ + // Anytime we get a "lldb::user_id_t" from an lldb_private::SymbolFile API + // we must make sure we use the correct DWARF file when resolving things. + // On MacOSX, when using SymbolFileDWARFDebugMap, we will use multiple + // SymbolFileDWARF classes, one for each .o file. We can often end up + // with references to other DWARF objects and we must be ready to receive + // a "lldb::user_id_t" that specifies a DIE from another SymbolFileDWARF + // instance. + SymbolFileDWARF *dwarf = GetDWARFForUID(uid); + if (dwarf) + return dwarf->GetDIE(DIERef(uid, dwarf)); + return DWARFDIE(); +} + CompilerDecl SymbolFileDWARF::GetDeclForUID (lldb::user_id_t type_uid) { - if (UserIDMatches(type_uid)) - { - 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->GetDeclForUIDFromDWARF(die); - } - } - } + // Anytime we have a lldb::user_id_t, we must get the DIE by + // calling SymbolFileDWARF::GetDIEFromUID(). See comments inside + // the SymbolFileDWARF::GetDIEFromUID() for details. + DWARFDIE die = GetDIEFromUID(type_uid); + if (die) + return die.GetDecl(); return CompilerDecl(); } CompilerDeclContext SymbolFileDWARF::GetDeclContextForUID (lldb::user_id_t type_uid) { - if (UserIDMatches(type_uid)) - { - 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); - } - } - } + // Anytime we have a lldb::user_id_t, we must get the DIE by + // calling SymbolFileDWARF::GetDIEFromUID(). See comments inside + // the SymbolFileDWARF::GetDIEFromUID() for details. + DWARFDIE die = GetDIEFromUID(type_uid); + if (die) + return die.GetDeclContext(); return CompilerDeclContext(); } CompilerDeclContext SymbolFileDWARF::GetDeclContextContainingUID (lldb::user_id_t type_uid) { - if (UserIDMatches(type_uid)) - { - 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); - } - } - } + // Anytime we have a lldb::user_id_t, we must get the DIE by + // calling SymbolFileDWARF::GetDIEFromUID(). See comments inside + // the SymbolFileDWARF::GetDIEFromUID() for details. + DWARFDIE die = GetDIEFromUID(type_uid); + if (die) + return die.GetContainingDeclContext(); return CompilerDeclContext(); } @@ -1503,20 +1537,20 @@ SymbolFileDWARF::GetDeclContextContainingUID (lldb::user_id_t type_uid) Type* SymbolFileDWARF::ResolveTypeUID (lldb::user_id_t type_uid) { - if (UserIDMatches(type_uid)) - { - DWARFDebugInfo* debug_info = DebugInfo(); - if (debug_info) - { - 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; + // Anytime we have a lldb::user_id_t, we must get the DIE by + // calling SymbolFileDWARF::GetDIEFromUID(). See comments inside + // the SymbolFileDWARF::GetDIEFromUID() for details. + DWARFDIE type_die = GetDIEFromUID(type_uid); + if (type_die) + return type_die.ResolveType(); + else + return nullptr; +} + +Type* +SymbolFileDWARF::ResolveTypeUID (const DIERef &die_ref) +{ + return ResolveType (GetDIE(die_ref), true); } Type* @@ -1573,35 +1607,36 @@ SymbolFileDWARF::ResolveTypeUID (const DWARFDIE &die, bool assert_not_being_pars bool SymbolFileDWARF::HasForwardDeclForClangType (const CompilerType &compiler_type) { - CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type); + CompilerType compiler_type_no_qualifiers = ClangUtil::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; + + ClangASTContext *clang_type_system = llvm::dyn_cast_or_null(type_system); + if (!clang_type_system) + return false; + DWARFASTParserClang *ast_parser = static_cast(clang_type_system->GetDWARFParser()); + return ast_parser->GetClangASTImporter().CanImport(compiler_type); } bool SymbolFileDWARF::CompleteType (CompilerType &compiler_type) { - TypeSystem *type_system = compiler_type.GetTypeSystem(); - if (type_system) + std::lock_guard guard(GetObjectFile()->GetModule()->GetMutex()); + + ClangASTContext *clang_type_system = llvm::dyn_cast_or_null(compiler_type.GetTypeSystem()); + if (clang_type_system) { - DWARFASTParser *dwarf_ast = type_system->GetDWARFParser(); - if (dwarf_ast && dwarf_ast->CanCompleteType(compiler_type)) - return dwarf_ast->CompleteType(compiler_type); + DWARFASTParserClang *ast_parser = static_cast(clang_type_system->GetDWARFParser()); + if (ast_parser && ast_parser->GetClangASTImporter().CanImport(compiler_type)) + return ast_parser->GetClangASTImporter().CompleteType(compiler_type); } // We have a struct/union/class/enum that needs to be fully resolved. - CompilerType compiler_type_no_qualifiers = ClangASTContext::RemoveFastQualifiers(compiler_type); + CompilerType compiler_type_no_qualifiers = ClangUtil::RemoveFastQualifiers(compiler_type); auto die_it = GetForwardDeclClangTypeToDie().find (compiler_type_no_qualifiers.GetOpaqueQualType()); if (die_it == GetForwardDeclClangTypeToDie().end()) { @@ -1609,30 +1644,29 @@ SymbolFileDWARF::CompleteType (CompilerType &compiler_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. - GetForwardDeclClangTypeToDie().erase (die_it); + DWARFDIE dwarf_die = GetDIE(die_it->getSecond()); + if (dwarf_die) + { + // 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. + GetForwardDeclClangTypeToDie().erase (die_it); - Type *type = GetDIEToType().lookup (dwarf_die.GetDIE()); + 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...", - dwarf_die.GetID(), - dwarf_die.GetTagAsCString(), - type->GetName().AsCString()); - assert (compiler_type); - DWARFASTParser *dwarf_ast = dwarf_die.GetDWARFParser(); - if (dwarf_ast) - return dwarf_ast->CompleteTypeFromDWARF (dwarf_die, type, compiler_type); + 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...", + dwarf_die.GetID(), + dwarf_die.GetTagAsCString(), + type->GetName().AsCString()); + assert (compiler_type); + DWARFASTParser *dwarf_ast = dwarf_die.GetDWARFParser(); + if (dwarf_ast) + return dwarf_ast->CompleteTypeFromDWARF (dwarf_die, type, compiler_type); + } return false; } @@ -1641,10 +1675,7 @@ SymbolFileDWARF::ResolveType (const DWARFDIE &die, bool assert_not_being_parsed, { if (die) { - Type *type = GetDIEToType().lookup (die.GetDIE()); - - if (type == NULL) - type = GetTypeForDIE (die, resolve_function_context).get(); + Type *type = GetTypeForDIE (die, resolve_function_context).get(); if (assert_not_being_parsed) { @@ -1730,6 +1761,55 @@ SymbolFileDWARF::GetDWOModule (ConstString name) return lldb::ModuleSP(); } +DWARFDIE +SymbolFileDWARF::GetDIE (const DIERef &die_ref) +{ + DWARFDebugInfo * debug_info = DebugInfo(); + if (debug_info) + return debug_info->GetDIE(die_ref); + else + return DWARFDIE(); +} + + +std::unique_ptr +SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(DWARFCompileUnit &dwarf_cu, const DWARFDebugInfoEntry &cu_die) +{ + // If we are using a dSYM file, we never want the standard DWO files since + // the -gmodule support uses the same DWO machanism to specify full debug + // info files for modules. + if (GetDebugMapSymfile()) + return nullptr; + + const char *dwo_name = cu_die.GetAttributeValueAsString(this, &dwarf_cu, DW_AT_GNU_dwo_name, nullptr); + if (!dwo_name) + return nullptr; + + FileSpec dwo_file(dwo_name, true); + if (dwo_file.IsRelative()) + { + const char *comp_dir = cu_die.GetAttributeValueAsString(this, &dwarf_cu, DW_AT_comp_dir, nullptr); + if (!comp_dir) + return nullptr; + + dwo_file.SetFile(comp_dir, true); + dwo_file.AppendPathComponent(dwo_name); + } + + if (!dwo_file.Exists()) + return nullptr; + + const lldb::offset_t file_offset = 0; + DataBufferSP dwo_file_data_sp; + lldb::offset_t dwo_file_data_offset = 0; + ObjectFileSP dwo_obj_file = ObjectFile::FindPlugin(GetObjectFile()->GetModule(), &dwo_file, file_offset, + dwo_file.GetByteSize(), dwo_file_data_sp, dwo_file_data_offset); + if (dwo_obj_file == nullptr) + return nullptr; + + return llvm::make_unique(dwo_obj_file, &dwarf_cu); +} + void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { @@ -1760,9 +1840,25 @@ SymbolFileDWARF::UpdateExternalModuleListIfNeeded() { ModuleSpec dwo_module_spec; dwo_module_spec.GetFileSpec().SetFile(dwo_path, false); + if (dwo_module_spec.GetFileSpec().IsRelative()) + { + const char *comp_dir = die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr); + if (comp_dir) + { + dwo_module_spec.GetFileSpec().SetFile(comp_dir, true); + dwo_module_spec.GetFileSpec().AppendPathComponent(dwo_path); + } + } 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 (!module_sp) + { + GetObjectFile()->GetModule()->ReportWarning ("0x%8.8x: unable to locate module needed for external types: %s\nerror: %s\nDebugging will be degraded due to missing types. Rebuilding your project will regenerate the needed module files.", + die.GetOffset(), + dwo_module_spec.GetFileSpec().GetPath().c_str(), + error.AsCString("unknown error")); + } } m_external_type_modules[const_name] = module_sp; } @@ -1799,7 +1895,7 @@ SymbolFileDWARF::GetGlobalAranges() const DWARFExpression &location = var_sp->LocationExpression(); Value location_result; Error error; - if (location.Evaluate(NULL, NULL, NULL, LLDB_INVALID_ADDRESS, NULL, location_result, &error)) + if (location.Evaluate(nullptr, nullptr, nullptr, LLDB_INVALID_ADDRESS, nullptr, nullptr, location_result, &error)) { if (location_result.GetValueType() == Value::eValueTypeFileAddress) { @@ -2094,6 +2190,9 @@ SymbolFileDWARF::Index () if (debug_info) { const uint32_t num_compile_units = GetNumCompileUnits(); + if (num_compile_units == 0) + return; + std::vector function_basename_index(num_compile_units); std::vector function_fullname_index(num_compile_units); std::vector function_method_index(num_compile_units); @@ -2102,7 +2201,8 @@ SymbolFileDWARF::Index () std::vector global_index(num_compile_units); std::vector type_index(num_compile_units); std::vector namespace_index(num_compile_units); - + + std::vector clear_cu_dies(num_compile_units, false); auto parser_fn = [this, debug_info, &function_basename_index, @@ -2115,25 +2215,62 @@ SymbolFileDWARF::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]); - - // Keep memory down by clearing DIEs if this generate function - // caused them to be parsed - if (clear_dies) - dwarf_cu->ClearDIEs(true); - + if (dwarf_cu) + { + 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]); + } return cu_idx; }; + auto extract_fn = [this, + debug_info, + num_compile_units](uint32_t cu_idx) + { + DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx); + if (dwarf_cu) + { + // dwarf_cu->ExtractDIEsIfNeeded(false) will return zero if the + // DIEs for a compile unit have already been parsed. + return std::make_pair(cu_idx, dwarf_cu->ExtractDIEsIfNeeded(false) > 1); + } + return std::make_pair(cu_idx, false); + }; + + // Create a task runner that extracts dies for each DWARF compile unit in a separate thread + TaskRunner> task_runner_extract; + for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) + task_runner_extract.AddTask(extract_fn, cu_idx); + + //---------------------------------------------------------------------- + // First figure out which compile units didn't have their DIEs already + // parsed and remember this. If no DIEs were parsed prior to this index + // function call, we are going to want to clear the CU dies after we + // are done indexing to make sure we don't pull in all DWARF dies, but + // we need to wait until all compile units have been indexed in case + // a DIE in one compile unit refers to another and the indexes accesses + // those DIEs. + //---------------------------------------------------------------------- + while (true) + { + auto f = task_runner_extract.WaitForNextCompletedTask(); + if (!f.valid()) + break; + unsigned cu_idx; + bool clear; + std::tie(cu_idx, clear) = f.get(); + clear_cu_dies[cu_idx] = clear; + } + + // Now create a task runner that can index each DWARF compile unit in a separate + // thread so we can index quickly. + TaskRunner task_runner; for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) task_runner.AddTask(parser_fn, cu_idx); @@ -2165,6 +2302,16 @@ SymbolFileDWARF::Index () [&]() { m_type_index.Finalize(); }, [&]() { m_namespace_index.Finalize(); }); + //---------------------------------------------------------------------- + // Keep memory down by clearing DIEs for any compile units if indexing + // caused us to load the compile unit's DIEs. + //---------------------------------------------------------------------- + for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) + { + if (clear_cu_dies[cu_idx]) + debug_info->GetCompileUnitAtIndex(cu_idx)->ClearDIEs(true); + } + #if defined (ENABLE_DEBUG_PRINTF) StreamFile s(stdout, false); s.Printf ("DWARF index for '%s':", @@ -2265,12 +2412,11 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const CompilerDec sc.module_sp = m_obj_file->GetModule(); assert (sc.module_sp); - DWARFDebugInfo* debug_info = DebugInfo(); bool done = false; for (size_t i=0; iGetDIE (die_ref); + DWARFDIE die = GetDIE (die_ref); if (die) { @@ -2383,11 +2529,10 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append const size_t num_matches = die_offsets.size(); if (num_matches) { - DWARFDebugInfo* debug_info = DebugInfo(); for (size_t i=0; iGetDIE (die_ref); + DWARFDIE die = GetDIE (die_ref); if (die) { @@ -2971,9 +3116,20 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc, const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, - uint32_t max_matches, + uint32_t max_matches, + llvm::DenseSet &searched_symbol_files, TypeMap& types) { + // If we aren't appending the results to this list, then clear the list + if (!append) + types.Clear(); + + // Make sure we haven't already searched this SymbolFile before... + if (searched_symbol_files.count(this)) + return 0; + else + searched_symbol_files.insert(this); + DWARFDebugInfo* info = DebugInfo(); if (info == NULL) return 0; @@ -2996,10 +3152,6 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc, max_matches); } - // If we aren't appending the results to this list, then clear the list - if (!append) - types.Clear(); - if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) return 0; @@ -3026,11 +3178,10 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc, if (num_die_matches) { const uint32_t initial_types_size = types.GetSize(); - DWARFDebugInfo* debug_info = DebugInfo(); for (size_t i=0; iGetDIE (die_ref); + DWARFDIE die = GetDIE (die_ref); if (die) { @@ -3097,6 +3248,7 @@ SymbolFileDWARF::FindTypes (const SymbolContext& sc, parent_decl_ctx, append, max_matches, + searched_symbol_files, types); if (num_external_matches) return num_external_matches; @@ -3124,6 +3276,9 @@ SymbolFileDWARF::FindTypes (const std::vector &context, ConstString name = context.back().name; + if (!name) + return 0; + if (m_using_apple_tables) { if (m_apple_types_ap.get()) @@ -3145,11 +3300,10 @@ SymbolFileDWARF::FindTypes (const std::vector &context, if (num_die_matches) { size_t num_matches = 0; - DWARFDebugInfo* debug_info = DebugInfo(); for (size_t i=0; iGetDIE (die_ref); + DWARFDIE die = GetDIE (die_ref); if (die) { @@ -3228,11 +3382,10 @@ SymbolFileDWARF::FindNamespace (const SymbolContext& sc, const size_t num_matches = die_offsets.size(); if (num_matches) { - DWARFDebugInfo* debug_info = DebugInfo(); for (size_t i=0; iGetDIE (die_ref); + DWARFDIE die = GetDIE (die_ref); if (die) { @@ -3447,11 +3600,10 @@ SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDIE &die, if (num_matches) { - DWARFDebugInfo* debug_info = DebugInfo(); for (size_t i=0; iGetDIE (die_ref); + DWARFDIE type_die = GetDIE (die_ref); if (type_die) { @@ -3667,18 +3819,26 @@ SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext & } const size_t num_matches = die_offsets.size(); - - + + // Get the type system that we are looking to find a type for. We will use this + // to ensure any matches we find are in a language that this type system supports + const LanguageType language = dwarf_decl_ctx.GetLanguage(); + TypeSystem *type_system = (language == eLanguageTypeUnknown) ? nullptr : GetTypeSystemForLanguage(language); + if (num_matches) { - DWARFDebugInfo* debug_info = DebugInfo(); for (size_t i=0; iGetDIE (die_ref); + DWARFDIE type_die = GetDIE (die_ref); if (type_die) { + // Make sure type_die's langauge matches the type system we are looking for. + // We don't want to find a "Foo" type from Java if we are looking for a "Foo" + // type for C, C++, ObjC, or ObjC++. + if (type_system && !type_system->SupportsLanguage(type_die.GetLanguage())) + continue; bool try_resolving_type = false; // Don't try and resolve the DIE we are looking for with the DIE itself! @@ -3919,7 +4079,7 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc) if (sc.function) { - DWARFDIE function_die = info->GetDIE(DIERef(sc.function->GetID())); + DWARFDIE function_die = info->GetDIE(DIERef(sc.function->GetID(), this)); const dw_addr_t func_lo_pc = function_die.GetAttributeValueAsAddress (DW_AT_low_pc, LLDB_INVALID_ADDRESS); if (func_lo_pc != LLDB_INVALID_ADDRESS) @@ -3974,11 +4134,10 @@ SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc) const size_t num_matches = die_offsets.size(); if (num_matches) { - DWARFDebugInfo* debug_info = DebugInfo(); for (size_t i=0; iGetDIE (die_ref); + DWARFDIE die = GetDIE (die_ref); if (die) { VariableSP var_sp (ParseVariableDIE(sc, die, LLDB_INVALID_ADDRESS)); @@ -4047,6 +4206,7 @@ SymbolFileDWARF::ParseVariableDIE bool location_is_const_value_data = false; bool has_explicit_location = false; DWARFFormValue const_value; + Variable::RangeList scope_ranges; //AccessType accessibility = eAccessNone; for (i=0; iGetDIE(DIERef(form_value)); + spec_die = GetDIE(DIERef(form_value)); + break; + case DW_AT_start_scope: + { + if (form_value.Form() == DW_FORM_sec_offset) + { + DWARFRangeList dwarf_scope_ranges; + const DWARFDebugRanges* debug_ranges = DebugRanges(); + debug_ranges->FindRanges(form_value.Unsigned(), dwarf_scope_ranges); + + // All DW_AT_start_scope are relative to the base address of the + // compile unit. We add the compile unit base address to make + // sure all the addresses are properly fixed up. + for (size_t i = 0, count = dwarf_scope_ranges.GetSize(); i < count; ++i) + { + const DWARFRangeList::Entry& range = dwarf_scope_ranges.GetEntryRef(i); + scope_ranges.Append(range.GetRangeBase() + die.GetCU()->GetBaseAddress(), + range.GetByteSize()); + } + } + else + { + // TODO: Handle the case when DW_AT_start_scope have form constant. The + // dwarf spec is a bit ambiguous about what is the expected behavior in + // case the enclosing block have a non coninious address range and the + // DW_AT_start_scope entry have a form constant. + GetObjectFile()->GetModule()->ReportWarning ("0x%8.8" PRIx64 ": DW_AT_start_scope has unsupported form type (0x%x)\n", + die.GetID(), + form_value.Form()); + } + + scope_ranges.Sort(); + scope_ranges.CombineConsecutiveRanges(); + } 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: case DW_AT_description: case DW_AT_endianity: case DW_AT_segment: - case DW_AT_start_scope: case DW_AT_visibility: default: case DW_AT_abstract_origin: @@ -4232,6 +4420,7 @@ SymbolFileDWARF::ParseVariableDIE GetObjectFile()->GetModule()->ReportError ("0x%8.8x: %s has an invalid location: %s", die.GetOffset(), die.GetTagAsCString(), strm.GetString().c_str()); } } + SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile(); if (location_DW_OP_addr != LLDB_INVALID_ADDRESS) { @@ -4240,9 +4429,6 @@ SymbolFileDWARF::ParseVariableDIE else scope = eValueTypeVariableStatic; - - SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile (); - if (debug_map_symfile) { // When leaving the DWARF in the .o files on darwin, @@ -4320,7 +4506,22 @@ SymbolFileDWARF::ParseVariableDIE if (location_is_const_value_data) scope = eValueTypeVariableStatic; else + { scope = eValueTypeVariableLocal; + if (debug_map_symfile) + { + // We need to check for TLS addresses that we need to fixup + if (location.ContainsThreadLocalStorage()) + { + location.LinkThreadLocalStorage( + debug_map_symfile->GetObjectFile()->GetModule(), + [this, debug_map_symfile](lldb::addr_t unlinked_file_addr) -> lldb::addr_t { + return debug_map_symfile->LinkOSOFileAddress(this, unlinked_file_addr); + }); + scope = eValueTypeVariableThreadLocal; + } + } + } } } @@ -4347,20 +4548,21 @@ SymbolFileDWARF::ParseVariableDIE if (symbol_context_scope) { - SymbolFileTypeSP type_sp(new SymbolFileType(*this, DIERef(type_die_form).GetUID())); - + SymbolFileTypeSP type_sp(new SymbolFileType(*this, DIERef(type_die_form).GetUID(this))); + if (const_value.Form() && type_sp && type_sp->GetType()) location.CopyOpcodeData(const_value.Unsigned(), type_sp->GetType()->GetByteSize(), die.GetCU()->GetAddressByteSize()); - + var_sp.reset (new Variable (die.GetID(), - name, + name, mangled, type_sp, - scope, - symbol_context_scope, - &decl, - location, - is_external, + scope, + symbol_context_scope, + scope_ranges, + &decl, + location, + is_external, is_artificial, is_static_member)); @@ -4505,7 +4707,7 @@ SymbolFileDWARF::ParseVariables (const SymbolContext& sc, // a concrete block counterpart in the current function. We need // to find the concrete block so we can correctly add the // variable to it - const DWARFDIE concrete_block_die = FindBlockContainingSpecification (DIERef(sc.function->GetID()), + const DWARFDIE concrete_block_die = FindBlockContainingSpecification (DIERef(sc.function->GetID(), this), sc_parent_die.GetOffset()); if (concrete_block_die) block = sc.function->GetBlock(true).FindBlockByID(concrete_block_die.GetID()); @@ -4596,7 +4798,7 @@ SymbolFileDWARF::DumpIndexes () SymbolFileDWARFDebugMap * -SymbolFileDWARF::GetDebugMapSymfile () +SymbolFileDWARF::GetDebugMapSymfile() { if (m_debug_map_symfile == NULL && !m_debug_map_module_wp.expired()) { diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index be097595346e..865e58962700 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -58,6 +58,7 @@ class DWARFDeclContext; class DWARFDIECollection; class DWARFFormValue; class SymbolFileDWARFDebugMap; +class SymbolFileDWARFDwo; #define DIE_IS_BEING_PARSED ((lldb_private::Type*)1) @@ -67,9 +68,12 @@ public: friend class SymbolFileDWARFDebugMap; friend class SymbolFileDWARFDwo; friend class DebugMapModule; + friend struct DIERef; friend class DWARFCompileUnit; + friend class DWARFDIE; friend class DWARFASTParserClang; friend class DWARFASTParserGo; + friend class DWARFASTParserJava; //------------------------------------------------------------------ // Static Functions @@ -133,8 +137,11 @@ public: lldb_private::FileSpecList& support_files) override; bool - ParseImportedModules (const lldb_private::SymbolContext &sc, - std::vector &imported_modules) override; + ParseCompileUnitIsOptimized(const lldb_private::SymbolContext &sc) override; + + bool + ParseImportedModules(const lldb_private::SymbolContext &sc, + std::vector &imported_modules) override; size_t ParseFunctionBlocks (const lldb_private::SymbolContext& sc) override; @@ -156,6 +163,12 @@ public: bool assert_not_being_parsed = true, bool resolve_function_context = false); + SymbolFileDWARF * + GetDWARFForUID (lldb::user_id_t uid); + + DWARFDIE + GetDIEFromUID (lldb::user_id_t uid); + lldb_private::CompilerDecl GetDeclForUID (lldb::user_id_t uid) override; @@ -218,6 +231,7 @@ public: const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, + llvm::DenseSet &searched_symbol_files, lldb_private::TypeMap& types) override; size_t @@ -299,12 +313,6 @@ public: GetCompUnitForDWARFCompUnit(DWARFCompileUnit* dwarf_cu, uint32_t cu_idx = UINT32_MAX); - lldb::user_id_t - MakeUserID (dw_offset_t die_offset) const - { - return GetID() | die_offset; - } - size_t GetObjCMethodDIEOffsets (lldb_private::ConstString class_name, DIEArray &method_die_offsets); @@ -327,6 +335,12 @@ public: lldb::ModuleSP GetDWOModule (lldb_private::ConstString name); + virtual DWARFDIE + GetDIE(const DIERef &die_ref); + + virtual std::unique_ptr + GetDwoSymbolFileForCompileUnit(DWARFCompileUnit &dwarf_cu, const DWARFDebugInfoEntry &cu_die); + protected: typedef llvm::DenseMap DIEToTypePtr; typedef llvm::DenseMap DIEToVariableSP; @@ -387,8 +401,10 @@ protected: bool *type_is_new); lldb_private::Type * - ResolveTypeUID (const DWARFDIE &die, - bool assert_not_being_parsed); + ResolveTypeUID(const DWARFDIE &die, bool assert_not_being_parsed); + + lldb_private::Type * + ResolveTypeUID(const DIERef &die_ref); lldb::VariableSP ParseVariableDIE(const lldb_private::SymbolContext& sc, @@ -482,15 +498,6 @@ protected: virtual UniqueDWARFASTTypeMap & GetUniqueDWARFASTTypeMap (); - bool - UserIDMatches (lldb::user_id_t uid) const - { - const lldb::user_id_t high_uid = uid & 0xffffffff00000000ull; - if (high_uid != 0 && GetID() != 0) - return high_uid == GetID(); - return true; - } - bool DIEDeclContextsMatch (const DWARFDIE &die1, const DWARFDIE &die2); diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index be25dfc99dee..ca819624c715 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -123,8 +123,9 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa // Add the inverse OSO file address to debug map entry mapping exe_symfile->AddOSOFileRange (this, exe_symbol->GetAddressRef().GetFileAddress(), + exe_symbol->GetByteSize(), oso_fun_symbol->GetAddressRef().GetFileAddress(), - std::min(exe_symbol->GetByteSize(), oso_fun_symbol->GetByteSize())); + oso_fun_symbol->GetByteSize()); } } @@ -157,8 +158,9 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMa // Add the inverse OSO file address to debug map entry mapping exe_symfile->AddOSOFileRange (this, exe_symbol->GetAddressRef().GetFileAddress(), + exe_symbol->GetByteSize(), oso_gsym_symbol->GetAddressRef().GetFileAddress(), - std::min(exe_symbol->GetByteSize(), oso_gsym_symbol->GetByteSize())); + oso_gsym_symbol->GetByteSize()); } } break; @@ -206,7 +208,7 @@ public: ObjectFile *oso_objfile = GetObjectFile (); if (oso_objfile) { - Mutex::Locker locker (m_mutex); + std::lock_guard guard(m_mutex); SymbolVendor* symbol_vendor = Module::GetSymbolVendor(can_create, feedback_strm); if (symbol_vendor) { @@ -635,13 +637,9 @@ SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx) // zero in each .o file since each .o file can only have // one compile unit for now. lldb::user_id_t cu_id = 0; - m_compile_unit_infos[cu_idx].compile_unit_sp.reset(new CompileUnit (m_obj_file->GetModule(), - NULL, - so_file_spec, - cu_id, - eLanguageTypeUnknown, - false)); - + m_compile_unit_infos[cu_idx].compile_unit_sp.reset(new CompileUnit( + m_obj_file->GetModule(), NULL, so_file_spec, cu_id, eLanguageTypeUnknown, eLazyBoolCalculate)); + if (m_compile_unit_infos[cu_idx].compile_unit_sp) { // Let our symbol vendor know about this compile unit @@ -725,7 +723,16 @@ SymbolFileDWARFDebugMap::ParseCompileUnitSupportFiles (const SymbolContext& sc, } bool -SymbolFileDWARFDebugMap::ParseImportedModules (const SymbolContext &sc, std::vector &imported_modules) +SymbolFileDWARFDebugMap::ParseCompileUnitIsOptimized(const lldb_private::SymbolContext &sc) +{ + SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc); + if (oso_dwarf) + return oso_dwarf->ParseCompileUnitIsOptimized(sc); + return false; +} + +bool +SymbolFileDWARFDebugMap::ParseImportedModules(const SymbolContext &sc, std::vector &imported_modules) { SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc); if (oso_dwarf) @@ -1276,7 +1283,8 @@ SymbolFileDWARFDebugMap::FindTypes const ConstString &name, const CompilerDeclContext *parent_decl_ctx, bool append, - uint32_t max_matches, + uint32_t max_matches, + llvm::DenseSet &searched_symbol_files, TypeMap& types ) { @@ -1290,13 +1298,16 @@ SymbolFileDWARFDebugMap::FindTypes { oso_dwarf = GetSymbolFile (sc); if (oso_dwarf) - return oso_dwarf->FindTypes (sc, name, parent_decl_ctx, append, max_matches, types); + return oso_dwarf->FindTypes (sc, name, parent_decl_ctx, append, max_matches, searched_symbol_files, types); } else { ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - oso_dwarf->FindTypes (sc, name, parent_decl_ctx, append, max_matches, types); - return false; + oso_dwarf->FindTypes (sc, name, parent_decl_ctx, append, max_matches, searched_symbol_files, types); + if (types.GetSize() >= max_matches) + return true; + else + return false; }); } @@ -1452,6 +1463,7 @@ SymbolFileDWARFDebugMap::ParseDeclsForContext (lldb_private::CompilerDeclContext bool SymbolFileDWARFDebugMap::AddOSOFileRange (CompileUnitInfo *cu_info, lldb::addr_t exe_file_addr, + lldb::addr_t exe_byte_size, lldb::addr_t oso_file_addr, lldb::addr_t oso_byte_size) { @@ -1460,7 +1472,14 @@ SymbolFileDWARFDebugMap::AddOSOFileRange (CompileUnitInfo *cu_info, { DebugMap::Entry *debug_map_entry = m_debug_map.FindEntryThatContains(exe_file_addr); debug_map_entry->data.SetOSOFileAddress(oso_file_addr); - cu_info->file_range_map.Append(FileRangeMap::Entry(oso_file_addr, oso_byte_size, exe_file_addr)); + addr_t range_size = std::min(exe_byte_size, oso_byte_size); + if (range_size == 0) + { + range_size = std::max(exe_byte_size, oso_byte_size); + if (range_size == 0) + range_size = 1; + } + cu_info->file_range_map.Append(FileRangeMap::Entry(oso_file_addr, range_size, exe_file_addr)); return true; } return false; diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index 1eb33c927bdf..fcf02975a58f 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -65,6 +65,8 @@ public: 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 + ParseCompileUnitIsOptimized(const lldb_private::SymbolContext &sc) override; bool ParseImportedModules (const lldb_private::SymbolContext &sc, std::vector &imported_modules) override; size_t ParseFunctionBlocks (const lldb_private::SymbolContext& sc) override; size_t ParseTypes (const lldb_private::SymbolContext& sc) override; @@ -82,7 +84,7 @@ public: 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; + 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, llvm::DenseSet &searched_symbol_files, lldb_private::TypeMap& types) override; lldb_private::CompilerDeclContext FindNamespace (const lldb_private::SymbolContext& sc, const lldb_private::ConstString &name, @@ -107,10 +109,11 @@ protected: kNumFlags }; - friend class DWARFCompileUnit; - friend class SymbolFileDWARF; friend class DebugMapModule; + friend struct DIERef; friend class DWARFASTParserClang; + friend class DWARFCompileUnit; + friend class SymbolFileDWARF; struct OSOInfo { lldb::ModuleSP module_sp; @@ -348,6 +351,7 @@ protected: bool AddOSOFileRange (CompileUnitInfo *cu_info, lldb::addr_t exe_file_addr, + lldb::addr_t exe_byte_size, lldb::addr_t oso_file_addr, lldb::addr_t oso_byte_size); diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp index 326c397c83d5..14603aa460c9 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -12,6 +12,7 @@ #include "lldb/Core/Section.h" #include "lldb/Expression/DWARFExpression.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Utility/LLDBAssert.h" #include "DWARFCompileUnit.h" #include "DWARFDebugInfo.h" @@ -129,3 +130,10 @@ SymbolFileDWARFDwo::GetTypeSystemForLanguage(LanguageType language) { return GetBaseSymbolFile()->GetTypeSystemForLanguage(language); } + +DWARFDIE +SymbolFileDWARFDwo::GetDIE(const DIERef &die_ref) +{ + lldbassert(m_base_dwarf_cu->GetOffset() == die_ref.cu_offset); + return DebugInfo()->GetDIEForDIEOffset(die_ref.die_offset); +} diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h index 39ed6502229b..9391a2824948 100644 --- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h +++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -38,6 +38,15 @@ public: lldb_private::TypeSystem* GetTypeSystemForLanguage(lldb::LanguageType language) override; + DWARFDIE + GetDIE(const DIERef &die_ref) override; + + std::unique_ptr + GetDwoSymbolFileForCompileUnit(DWARFCompileUnit &dwarf_cu, const DWARFDebugInfoEntry &cu_die) override + { + return nullptr; + } + protected: void LoadSectionData (lldb::SectionType sect_type, lldb_private::DWARFDataExtractor& data) override; diff --git a/source/Plugins/SymbolFile/PDB/CMakeLists.txt b/source/Plugins/SymbolFile/PDB/CMakeLists.txt new file mode 100644 index 000000000000..79d8a25d6979 --- /dev/null +++ b/source/Plugins/SymbolFile/PDB/CMakeLists.txt @@ -0,0 +1,7 @@ +set(LLVM_PRIVATE_LINK_COMPONENTS + DebugInfoPDB) + +add_lldb_library(lldbPluginSymbolFilePDB + PDBASTParser.cpp + SymbolFilePDB.cpp + ) diff --git a/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp new file mode 100644 index 000000000000..1e8e040fd47c --- /dev/null +++ b/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp @@ -0,0 +1,237 @@ +//===-- PDBASTParser.cpp ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PDBASTParser.h" + +#include "clang/AST/CharUnits.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" + +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ClangUtil.h" +#include "lldb/Symbol/Declaration.h" +#include "lldb/Symbol/SymbolFile.h" +#include "lldb/Symbol/TypeSystem.h" + +#include "llvm/DebugInfo/PDB/PDBSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" + +using namespace lldb; +using namespace lldb_private; +using namespace llvm; +using namespace llvm::pdb; + +namespace +{ +int +TranslateUdtKind(PDB_UdtType pdb_kind) +{ + switch (pdb_kind) + { + case PDB_UdtType::Class: + return clang::TTK_Class; + case PDB_UdtType::Struct: + return clang::TTK_Struct; + case PDB_UdtType::Union: + return clang::TTK_Union; + case PDB_UdtType::Interface: + return clang::TTK_Interface; + } + return clang::TTK_Class; +} + +lldb::Encoding +TranslateBuiltinEncoding(PDB_BuiltinType type) +{ + switch (type) + { + case PDB_BuiltinType::Float: + return lldb::eEncodingIEEE754; + case PDB_BuiltinType::Int: + case PDB_BuiltinType::Long: + case PDB_BuiltinType::Char: + return lldb::eEncodingSint; + case PDB_BuiltinType::Bool: + case PDB_BuiltinType::UInt: + case PDB_BuiltinType::ULong: + case PDB_BuiltinType::HResult: + return lldb::eEncodingUint; + default: + return lldb::eEncodingInvalid; + } +} +} + +PDBASTParser::PDBASTParser(lldb_private::ClangASTContext &ast) : m_ast(ast) +{ +} + +PDBASTParser::~PDBASTParser() +{ +} + +// DebugInfoASTParser interface + +lldb::TypeSP +PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) +{ + // PDB doesn't maintain enough information to robustly rebuild the entire + // tree, and this is most problematic when it comes to figure out the + // right DeclContext to put a type in. So for now, everything goes in + // the translation unit decl as a fully qualified type. + clang::DeclContext *tu_decl_ctx = m_ast.GetTranslationUnitDecl(); + Declaration decl; + + if (auto udt = llvm::dyn_cast(&type)) + { + AccessType access = lldb::eAccessPublic; + PDB_UdtType udt_kind = udt->getUdtKind(); + + if (udt_kind == PDB_UdtType::Class) + access = lldb::eAccessPrivate; + + CompilerType clang_type = + m_ast.CreateRecordType(tu_decl_ctx, access, udt->getName().c_str(), TranslateUdtKind(udt_kind), + lldb::eLanguageTypeC_plus_plus, nullptr); + + m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true); + + return std::make_shared(type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(udt->getName()), + udt->getLength(), nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, + clang_type, Type::eResolveStateForward); + } + else if (auto enum_type = llvm::dyn_cast(&type)) + { + std::string name = enum_type->getName(); + lldb::Encoding encoding = TranslateBuiltinEncoding(enum_type->getBuiltinType()); + uint64_t bytes = enum_type->getLength(); + CompilerType builtin_type = m_ast.GetBuiltinTypeForEncodingAndBitSize(encoding, bytes * 8); + + CompilerType ast_enum = m_ast.CreateEnumerationType(name.c_str(), tu_decl_ctx, decl, builtin_type); + auto enum_values = enum_type->findAllChildren(); + while (auto enum_value = enum_values->getNext()) + { + if (enum_value->getDataKind() != PDB_DataKind::Constant) + continue; + AddEnumValue(ast_enum, *enum_value); + } + + return std::make_shared(type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), bytes, nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ast_enum, Type::eResolveStateFull); + } + else if (auto type_def = llvm::dyn_cast(&type)) + { + Type *target_type = m_ast.GetSymbolFile()->ResolveTypeUID(type_def->getTypeId()); + std::string name = type_def->getName(); + uint64_t bytes = type_def->getLength(); + if (!target_type) + return nullptr; + CompilerType target_ast_type = target_type->GetFullCompilerType(); + CompilerDeclContext target_decl_ctx = m_ast.GetSymbolFile()->GetDeclContextForUID(target_type->GetID()); + CompilerType ast_typedef = m_ast.CreateTypedefType(target_ast_type, name.c_str(), target_decl_ctx); + return std::make_shared(type_def->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name), bytes, + nullptr, target_type->GetID(), Type::eEncodingIsTypedefUID, decl, ast_typedef, + Type::eResolveStateFull); + } + else if (auto func_sig = llvm::dyn_cast(&type)) + { + auto arg_enum = func_sig->getArguments(); + uint32_t num_args = arg_enum->getChildCount(); + std::vector arg_list(num_args); + while (auto arg = arg_enum->getNext()) + { + Type *arg_type = m_ast.GetSymbolFile()->ResolveTypeUID(arg->getSymIndexId()); + // If there's some error looking up one of the dependent types of this function signature, bail. + if (!arg_type) + return nullptr; + CompilerType arg_ast_type = arg_type->GetFullCompilerType(); + arg_list.push_back(arg_ast_type); + } + auto pdb_return_type = func_sig->getReturnType(); + Type *return_type = m_ast.GetSymbolFile()->ResolveTypeUID(pdb_return_type->getSymIndexId()); + // If there's some error looking up one of the dependent types of this function signature, bail. + if (!return_type) + return nullptr; + CompilerType return_ast_type = return_type->GetFullCompilerType(); + uint32_t type_quals = 0; + if (func_sig->isConstType()) + type_quals |= clang::Qualifiers::Const; + if (func_sig->isVolatileType()) + type_quals |= clang::Qualifiers::Volatile; + CompilerType func_sig_ast_type = + m_ast.CreateFunctionType(return_ast_type, &arg_list[0], num_args, false, type_quals); + + return std::make_shared(func_sig->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(), 0, nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, decl, func_sig_ast_type, + Type::eResolveStateFull); + } + else if (auto array_type = llvm::dyn_cast(&type)) + { + uint32_t num_elements = array_type->getCount(); + uint32_t element_uid = array_type->getElementType()->getSymIndexId(); + uint32_t bytes = array_type->getLength(); + + Type *element_type = m_ast.GetSymbolFile()->ResolveTypeUID(element_uid); + CompilerType element_ast_type = element_type->GetFullCompilerType(); + CompilerType array_ast_type = m_ast.CreateArrayType(element_ast_type, num_elements, false); + return std::make_shared(array_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(), bytes, nullptr, + LLDB_INVALID_UID, Type::eEncodingIsUID, decl, array_ast_type, + Type::eResolveStateFull); + } + return nullptr; +} + +bool +PDBASTParser::AddEnumValue(CompilerType enum_type, const PDBSymbolData &enum_value) const +{ + Declaration decl; + Variant v = enum_value.getValue(); + std::string name = enum_value.getName(); + int64_t raw_value; + switch (v.Type) + { + case PDB_VariantType::Int8: + raw_value = v.Value.Int8; + break; + case PDB_VariantType::Int16: + raw_value = v.Value.Int16; + break; + case PDB_VariantType::Int32: + raw_value = v.Value.Int32; + break; + case PDB_VariantType::Int64: + raw_value = v.Value.Int64; + break; + case PDB_VariantType::UInt8: + raw_value = v.Value.UInt8; + break; + case PDB_VariantType::UInt16: + raw_value = v.Value.UInt16; + break; + case PDB_VariantType::UInt32: + raw_value = v.Value.UInt32; + break; + case PDB_VariantType::UInt64: + raw_value = v.Value.UInt64; + break; + default: + return false; + } + CompilerType underlying_type = m_ast.GetEnumerationIntegerType(enum_type.GetOpaqueQualType()); + uint32_t byte_size = m_ast.getASTContext()->getTypeSize(ClangUtil::GetQualType(underlying_type)); + return m_ast.AddEnumerationValueToEnumerationType(enum_type.GetOpaqueQualType(), underlying_type, decl, + name.c_str(), raw_value, byte_size * 8); +} diff --git a/source/Plugins/SymbolFile/PDB/PDBASTParser.h b/source/Plugins/SymbolFile/PDB/PDBASTParser.h new file mode 100644 index 000000000000..ca425c17c451 --- /dev/null +++ b/source/Plugins/SymbolFile/PDB/PDBASTParser.h @@ -0,0 +1,58 @@ +//===-- PDBASTParser.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_SYMBOLFILE_PDB_PDBASTPARSER_H +#define LLDB_PLUGINS_SYMBOLFILE_PDB_PDBASTPARSER_H + +#include "lldb/lldb-forward.h" + +#include "lldb/Symbol/ClangASTImporter.h" + +namespace clang +{ +class CharUnits; +class CXXRecordDecl; +class FieldDecl; +class RecordDecl; +} + +namespace lldb_private +{ +class ClangASTContext; +class CompilerType; +} + +namespace llvm +{ +namespace pdb +{ +class PDBSymbol; +class PDBSymbolData; +class PDBSymbolTypeBuiltin; +} +} + +class PDBASTParser +{ +public: + PDBASTParser(lldb_private::ClangASTContext &ast); + ~PDBASTParser(); + + lldb::TypeSP + CreateLLDBTypeFromPDBType(const llvm::pdb::PDBSymbol &type); + +private: + bool + AddEnumValue(lldb_private::CompilerType enum_type, const llvm::pdb::PDBSymbolData &data) const; + + lldb_private::ClangASTContext &m_ast; + lldb_private::ClangASTImporter m_ast_importer; +}; + +#endif // SymbolFileDWARF_DWARFASTParserClang_h_ diff --git a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp new file mode 100644 index 000000000000..d8092c011acb --- /dev/null +++ b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -0,0 +1,733 @@ +//===-- SymbolFilePDB.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "SymbolFilePDB.h" + +#include "clang/Lex/Lexer.h" + +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/LineTable.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/TypeMap.h" + +#include "llvm/DebugInfo/PDB/GenericError.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBLineNumber.h" +#include "llvm/DebugInfo/PDB/IPDBSourceFile.h" +#include "llvm/DebugInfo/PDB/PDBSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" +#include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h" +#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" +#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" +#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h" +#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" + +#include "Plugins/SymbolFile/PDB/PDBASTParser.h" + +#include + +using namespace lldb_private; +using namespace llvm::pdb; + +namespace +{ +lldb::LanguageType +TranslateLanguage(PDB_Lang lang) +{ + switch (lang) + { + case PDB_Lang::Cpp: + return lldb::LanguageType::eLanguageTypeC_plus_plus; + case PDB_Lang::C: + return lldb::LanguageType::eLanguageTypeC; + default: + return lldb::LanguageType::eLanguageTypeUnknown; + } + } + + bool + ShouldAddLine(uint32_t requested_line, uint32_t actual_line, uint32_t addr_length) + { + return ((requested_line == 0 || actual_line == requested_line) && addr_length > 0); + } +} + +void +SymbolFilePDB::Initialize() +{ + PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, + DebuggerInitialize); +} + +void +SymbolFilePDB::Terminate() +{ + PluginManager::UnregisterPlugin(CreateInstance); +} + +void +SymbolFilePDB::DebuggerInitialize(lldb_private::Debugger &debugger) +{ +} + +lldb_private::ConstString +SymbolFilePDB::GetPluginNameStatic() +{ + static ConstString g_name("pdb"); + return g_name; +} + +const char * +SymbolFilePDB::GetPluginDescriptionStatic() +{ + return "Microsoft PDB debug symbol file reader."; +} + +lldb_private::SymbolFile * +SymbolFilePDB::CreateInstance(lldb_private::ObjectFile *obj_file) +{ + return new SymbolFilePDB(obj_file); +} + +SymbolFilePDB::SymbolFilePDB(lldb_private::ObjectFile *object_file) + : SymbolFile(object_file), m_cached_compile_unit_count(0) +{ +} + +SymbolFilePDB::~SymbolFilePDB() +{ +} + +uint32_t +SymbolFilePDB::CalculateAbilities() +{ + if (!m_session_up) + { + // Lazily load and match the PDB file, but only do this once. + std::string exePath = m_obj_file->GetFileSpec().GetPath(); + auto error = loadDataForEXE(PDB_ReaderType::DIA, llvm::StringRef(exePath), m_session_up); + if (error) + { + llvm::consumeError(std::move(error)); + return 0; + } + } + return CompileUnits | LineTables; +} + +void +SymbolFilePDB::InitializeObject() +{ + lldb::addr_t obj_load_address = m_obj_file->GetFileOffset(); + m_session_up->setLoadAddress(obj_load_address); + + TypeSystem *type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + ClangASTContext *clang_type_system = llvm::dyn_cast_or_null(type_system); + m_tu_decl_ctx_up = llvm::make_unique(type_system, clang_type_system->GetTranslationUnitDecl()); +} + +uint32_t +SymbolFilePDB::GetNumCompileUnits() +{ + if (m_cached_compile_unit_count == 0) + { + auto global = m_session_up->getGlobalScope(); + auto compilands = global->findAllChildren(); + m_cached_compile_unit_count = compilands->getChildCount(); + + // The linker can inject an additional "dummy" compilation unit into the PDB. + // Ignore this special compile unit for our purposes, if it is there. It is + // always the last one. + auto last_cu = compilands->getChildAtIndex(m_cached_compile_unit_count - 1); + std::string name = last_cu->getName(); + if (name == "* Linker *") + --m_cached_compile_unit_count; + } + return m_cached_compile_unit_count; +} + +lldb::CompUnitSP +SymbolFilePDB::ParseCompileUnitAtIndex(uint32_t index) +{ + auto global = m_session_up->getGlobalScope(); + auto compilands = global->findAllChildren(); + auto cu = compilands->getChildAtIndex(index); + + uint32_t id = cu->getSymIndexId(); + + return ParseCompileUnitForSymIndex(id); +} + +lldb::LanguageType +SymbolFilePDB::ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc) +{ + // What fields should I expect to be filled out on the SymbolContext? Is it + // safe to assume that `sc.comp_unit` is valid? + if (!sc.comp_unit) + return lldb::eLanguageTypeUnknown; + + auto cu = m_session_up->getConcreteSymbolById(sc.comp_unit->GetID()); + if (!cu) + return lldb::eLanguageTypeUnknown; + auto details = cu->findOneChild(); + if (!details) + return lldb::eLanguageTypeUnknown; + return TranslateLanguage(details->getLanguage()); +} + +size_t +SymbolFilePDB::ParseCompileUnitFunctions(const lldb_private::SymbolContext &sc) +{ + // TODO: Implement this + return size_t(); +} + +bool +SymbolFilePDB::ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc) +{ + return ParseCompileUnitLineTable(sc, 0); +} + +bool +SymbolFilePDB::ParseCompileUnitDebugMacros(const lldb_private::SymbolContext &sc) +{ + // PDB doesn't contain information about macros + return false; +} + +bool +SymbolFilePDB::ParseCompileUnitSupportFiles(const lldb_private::SymbolContext &sc, + lldb_private::FileSpecList &support_files) +{ + if (!sc.comp_unit) + return false; + + // In theory this is unnecessary work for us, because all of this information is easily + // (and quickly) accessible from DebugInfoPDB, so caching it a second time seems like a waste. + // Unfortunately, there's no good way around this short of a moderate refactor, since SymbolVendor + // depends on being able to cache this list. + auto cu = m_session_up->getConcreteSymbolById(sc.comp_unit->GetID()); + if (!cu) + return false; + auto files = m_session_up->getSourceFilesForCompiland(*cu); + if (!files || files->getChildCount() == 0) + return false; + + while (auto file = files->getNext()) + { + FileSpec spec(file->getFileName(), false); + support_files.Append(spec); + } + return true; +} + +bool +SymbolFilePDB::ParseImportedModules(const lldb_private::SymbolContext &sc, + std::vector &imported_modules) +{ + // PDB does not yet support module debug info + return false; +} + +size_t +SymbolFilePDB::ParseFunctionBlocks(const lldb_private::SymbolContext &sc) +{ + // TODO: Implement this + return size_t(); +} + +size_t +SymbolFilePDB::ParseTypes(const lldb_private::SymbolContext &sc) +{ + // TODO: Implement this + return size_t(); +} + +size_t +SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc) +{ + // TODO: Implement this + return size_t(); +} + +lldb_private::Type * +SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) +{ + auto find_result = m_types.find(type_uid); + if (find_result != m_types.end()) + return find_result->second.get(); + + TypeSystem *type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); + ClangASTContext *clang_type_system = llvm::dyn_cast_or_null(type_system); + if (!clang_type_system) + return nullptr; + PDBASTParser *pdb = llvm::dyn_cast(clang_type_system->GetPDBParser()); + if (!pdb) + return nullptr; + + auto pdb_type = m_session_up->getSymbolById(type_uid); + if (pdb_type == nullptr) + return nullptr; + + lldb::TypeSP result = pdb->CreateLLDBTypeFromPDBType(*pdb_type); + m_types.insert(std::make_pair(type_uid, result)); + return result.get(); +} + +bool +SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type) +{ + // TODO: Implement this + return false; +} + +lldb_private::CompilerDecl +SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid) +{ + return lldb_private::CompilerDecl(); +} + +lldb_private::CompilerDeclContext +SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid) +{ + // PDB always uses the translation unit decl context for everything. We can improve this later + // but it's not easy because PDB doesn't provide a high enough level of type fidelity in this area. + return *m_tu_decl_ctx_up; +} + +lldb_private::CompilerDeclContext +SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid) +{ + return *m_tu_decl_ctx_up; +} + +void +SymbolFilePDB::ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx) +{ +} + +uint32_t +SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr, uint32_t resolve_scope, + lldb_private::SymbolContext &sc) +{ + return uint32_t(); +} + +uint32_t +SymbolFilePDB::ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines, + uint32_t resolve_scope, lldb_private::SymbolContextList &sc_list) +{ + if (resolve_scope & lldb::eSymbolContextCompUnit) + { + // Locate all compilation units with line numbers referencing the specified file. For example, if + // `file_spec` is , then this should return all source files and header files that reference + // , either directly or indirectly. + auto compilands = + m_session_up->findCompilandsForSourceFile(file_spec.GetPath(), PDB_NameSearchFlags::NS_CaseInsensitive); + + // For each one, either find get its previously parsed data, or parse it afresh and add it to + // the symbol context list. + while (auto compiland = compilands->getNext()) + { + // If we're not checking inlines, then don't add line information for this file unless the FileSpec + // matches. + if (!check_inlines) + { + // `getSourceFileName` returns the basename of the original source file used to generate this compiland. + // It does not return the full path. Currently the only way to get that is to do a basename lookup to + // get the IPDBSourceFile, but this is ambiguous in the case of two source files with the same name + // contributing to the same compiland. This is a moderately extreme edge case, so we consider this ok + // for now, although we need to find a long term solution. + std::string source_file = compiland->getSourceFileName(); + auto pdb_file = m_session_up->findOneSourceFile(compiland.get(), source_file, + PDB_NameSearchFlags::NS_CaseInsensitive); + source_file = pdb_file->getFileName(); + FileSpec this_spec(source_file, false, FileSpec::ePathSyntaxWindows); + if (!file_spec.FileEquals(this_spec)) + continue; + } + + SymbolContext sc; + auto cu = ParseCompileUnitForSymIndex(compiland->getSymIndexId()); + sc.comp_unit = cu.get(); + sc.module_sp = cu->GetModule(); + sc_list.Append(sc); + + // If we were asked to resolve line entries, add all entries to the line table that match the requested + // line (or all lines if `line` == 0) + if (resolve_scope & lldb::eSymbolContextLineEntry) + ParseCompileUnitLineTable(sc, line); + } + } + return sc_list.GetSize(); +} + +uint32_t +SymbolFilePDB::FindGlobalVariables(const lldb_private::ConstString &name, + const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, + uint32_t max_matches, lldb_private::VariableList &variables) +{ + return uint32_t(); +} + +uint32_t +SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression ®ex, bool append, uint32_t max_matches, + lldb_private::VariableList &variables) +{ + return uint32_t(); +} + +uint32_t +SymbolFilePDB::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) +{ + return uint32_t(); +} + +uint32_t +SymbolFilePDB::FindFunctions(const lldb_private::RegularExpression ®ex, bool include_inlines, bool append, + lldb_private::SymbolContextList &sc_list) +{ + return uint32_t(); +} + +void +SymbolFilePDB::GetMangledNamesForFunction(const std::string &scope_qualified_name, + std::vector &mangled_names) +{ +} + +uint32_t +SymbolFilePDB::FindTypes(const lldb_private::SymbolContext &sc, const lldb_private::ConstString &name, + const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, uint32_t max_matches, + llvm::DenseSet &searched_symbol_files, + lldb_private::TypeMap &types) +{ + if (!append) + types.Clear(); + if (!name) + return 0; + + searched_symbol_files.clear(); + searched_symbol_files.insert(this); + + std::string name_str = name.AsCString(); + + // If this might be a regex, we have to return EVERY symbol and process them one by one, which is going + // to destroy performance on large PDB files. So try really hard not to use a regex match. + if (name_str.find_first_of("[]?*.-+\\") != std::string::npos) + FindTypesByRegex(name_str, max_matches, types); + else + FindTypesByName(name_str, max_matches, types); + return types.GetSize(); +} + +void +SymbolFilePDB::FindTypesByRegex(const std::string ®ex, uint32_t max_matches, lldb_private::TypeMap &types) +{ + // When searching by regex, we need to go out of our way to limit the search space as much as possible, since + // the way this is implemented is by searching EVERYTHING in the PDB and manually doing a regex compare. PDB + // library isn't optimized for regex searches or searches across multiple symbol types at the same time, so the + // best we can do is to search enums, then typedefs, then classes one by one, and do a regex compare against all + // of them. + PDB_SymType tags_to_search[] = {PDB_SymType::Enum, PDB_SymType::Typedef, PDB_SymType::UDT}; + auto global = m_session_up->getGlobalScope(); + std::unique_ptr results; + + std::regex re(regex); + + uint32_t matches = 0; + + for (auto tag : tags_to_search) + { + results = global->findAllChildren(tag); + while (auto result = results->getNext()) + { + if (max_matches > 0 && matches >= max_matches) + break; + + std::string type_name; + if (auto enum_type = llvm::dyn_cast(result.get())) + type_name = enum_type->getName(); + else if (auto typedef_type = llvm::dyn_cast(result.get())) + type_name = typedef_type->getName(); + else if (auto class_type = llvm::dyn_cast(result.get())) + type_name = class_type->getName(); + else + { + // We're only looking for types that have names. Skip symbols, as well as + // unnamed types such as arrays, pointers, etc. + continue; + } + + if (!std::regex_match(type_name, re)) + continue; + + // This should cause the type to get cached and stored in the `m_types` lookup. + if (!ResolveTypeUID(result->getSymIndexId())) + continue; + + auto iter = m_types.find(result->getSymIndexId()); + if (iter == m_types.end()) + continue; + types.Insert(iter->second); + ++matches; + } + } +} + +void +SymbolFilePDB::FindTypesByName(const std::string &name, uint32_t max_matches, lldb_private::TypeMap &types) +{ + auto global = m_session_up->getGlobalScope(); + std::unique_ptr results; + results = global->findChildren(PDB_SymType::None, name.c_str(), PDB_NameSearchFlags::NS_Default); + + uint32_t matches = 0; + + while (auto result = results->getNext()) + { + if (max_matches > 0 && matches >= max_matches) + break; + switch (result->getSymTag()) + { + case PDB_SymType::Enum: + case PDB_SymType::UDT: + case PDB_SymType::Typedef: + break; + default: + // We're only looking for types that have names. Skip symbols, as well as + // unnamed types such as arrays, pointers, etc. + continue; + } + + // This should cause the type to get cached and stored in the `m_types` lookup. + if (!ResolveTypeUID(result->getSymIndexId())) + continue; + + auto iter = m_types.find(result->getSymIndexId()); + if (iter == m_types.end()) + continue; + types.Insert(iter->second); + ++matches; + } +} + +size_t +SymbolFilePDB::FindTypes(const std::vector &contexts, bool append, + lldb_private::TypeMap &types) +{ + return 0; +} + +lldb_private::TypeList * +SymbolFilePDB::GetTypeList() +{ + return nullptr; +} + +size_t +SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, uint32_t type_mask, + lldb_private::TypeList &type_list) +{ + return size_t(); +} + +lldb_private::TypeSystem * +SymbolFilePDB::GetTypeSystemForLanguage(lldb::LanguageType language) +{ + auto type_system = m_obj_file->GetModule()->GetTypeSystemForLanguage(language); + if (type_system) + type_system->SetSymbolFile(this); + return type_system; +} + +lldb_private::CompilerDeclContext +SymbolFilePDB::FindNamespace(const lldb_private::SymbolContext &sc, const lldb_private::ConstString &name, + const lldb_private::CompilerDeclContext *parent_decl_ctx) +{ + return lldb_private::CompilerDeclContext(); +} + +lldb_private::ConstString +SymbolFilePDB::GetPluginName() +{ + static ConstString g_name("pdb"); + return g_name; +} + +uint32_t +SymbolFilePDB::GetPluginVersion() +{ + return 1; +} + +IPDBSession & +SymbolFilePDB::GetPDBSession() +{ + return *m_session_up; +} + +const IPDBSession & +SymbolFilePDB::GetPDBSession() const +{ + return *m_session_up; +} + +lldb::CompUnitSP +SymbolFilePDB::ParseCompileUnitForSymIndex(uint32_t id) +{ + auto found_cu = m_comp_units.find(id); + if (found_cu != m_comp_units.end()) + return found_cu->second; + + auto cu = m_session_up->getConcreteSymbolById(id); + + // `getSourceFileName` returns the basename of the original source file used to generate this compiland. It does + // not return the full path. Currently the only way to get that is to do a basename lookup to get the + // IPDBSourceFile, but this is ambiguous in the case of two source files with the same name contributing to the + // same compiland. This is a moderately extreme edge case, so we consider this ok for now, although we need to find + // a long term solution. + auto file = + m_session_up->findOneSourceFile(cu.get(), cu->getSourceFileName(), PDB_NameSearchFlags::NS_CaseInsensitive); + std::string path = file->getFileName(); + + lldb::LanguageType lang; + auto details = cu->findOneChild(); + if (!details) + lang = lldb::eLanguageTypeC_plus_plus; + else + lang = TranslateLanguage(details->getLanguage()); + + // Don't support optimized code for now, DebugInfoPDB does not return this information. + LazyBool optimized = eLazyBoolNo; + auto result = std::make_shared(m_obj_file->GetModule(), nullptr, path.c_str(), id, lang, optimized); + m_comp_units.insert(std::make_pair(id, result)); + return result; +} + +bool +SymbolFilePDB::ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc, uint32_t match_line) +{ + auto global = m_session_up->getGlobalScope(); + auto cu = m_session_up->getConcreteSymbolById(sc.comp_unit->GetID()); + + // LineEntry needs the *index* of the file into the list of support files returned by + // ParseCompileUnitSupportFiles. But the underlying SDK gives us a globally unique + // idenfitifier in the namespace of the PDB. So, we have to do a mapping so that we + // can hand out indices. + llvm::DenseMap index_map; + BuildSupportFileIdToSupportFileIndexMap(*cu, index_map); + auto line_table = llvm::make_unique(sc.comp_unit); + + // Find contributions to `cu` from all source and header files. + std::string path = sc.comp_unit->GetPath(); + auto files = m_session_up->getSourceFilesForCompiland(*cu); + + // For each source and header file, create a LineSequence for contributions to the cu + // from that file, and add the sequence. + while (auto file = files->getNext()) + { + std::unique_ptr sequence(line_table->CreateLineSequenceContainer()); + auto lines = m_session_up->findLineNumbers(*cu, *file); + int entry_count = lines->getChildCount(); + + uint64_t prev_addr; + uint32_t prev_length; + uint32_t prev_line; + uint32_t prev_source_idx; + + for (int i = 0; i < entry_count; ++i) + { + auto line = lines->getChildAtIndex(i); + + uint64_t lno = line->getLineNumber(); + uint64_t addr = line->getVirtualAddress(); + uint32_t length = line->getLength(); + uint32_t source_id = line->getSourceFileId(); + uint32_t col = line->getColumnNumber(); + uint32_t source_idx = index_map[source_id]; + + // There was a gap between the current entry and the previous entry if the addresses don't perfectly line + // up. + bool is_gap = (i > 0) && (prev_addr + prev_length < addr); + + // Before inserting the current entry, insert a terminal entry at the end of the previous entry's address + // range if the current entry resulted in a gap from the previous entry. + if (is_gap && ShouldAddLine(match_line, prev_line, prev_length)) + { + line_table->AppendLineEntryToSequence(sequence.get(), prev_addr + prev_length, prev_line, 0, + prev_source_idx, false, false, false, false, true); + } + + if (ShouldAddLine(match_line, lno, length)) + { + bool is_statement = line->isStatement(); + bool is_prologue = false; + bool is_epilogue = false; + auto func = m_session_up->findSymbolByAddress(addr, PDB_SymType::Function); + if (func) + { + auto prologue = func->findOneChild(); + is_prologue = (addr == prologue->getVirtualAddress()); + + auto epilogue = func->findOneChild(); + is_epilogue = (addr == epilogue->getVirtualAddress()); + } + + line_table->AppendLineEntryToSequence(sequence.get(), addr, lno, col, source_idx, is_statement, false, + is_prologue, is_epilogue, false); + } + + prev_addr = addr; + prev_length = length; + prev_line = lno; + prev_source_idx = source_idx; + } + + if (entry_count > 0 && ShouldAddLine(match_line, prev_line, prev_length)) + { + // The end is always a terminal entry, so insert it regardless. + line_table->AppendLineEntryToSequence(sequence.get(), prev_addr + prev_length, prev_line, 0, + prev_source_idx, false, false, false, false, true); + } + + line_table->InsertSequence(sequence.release()); + } + + sc.comp_unit->SetLineTable(line_table.release()); + return true; +} + +void +SymbolFilePDB::BuildSupportFileIdToSupportFileIndexMap(const PDBSymbolCompiland &cu, + llvm::DenseMap &index_map) const +{ + // This is a hack, but we need to convert the source id into an index into the support + // files array. We don't want to do path comparisons to avoid basename / full path + // issues that may or may not even be a problem, so we use the globally unique source + // file identifiers. Ideally we could use the global identifiers everywhere, but LineEntry + // currently assumes indices. + auto source_files = m_session_up->getSourceFilesForCompiland(cu); + int index = 0; + + while (auto file = source_files->getNext()) + { + uint32_t source_id = file->getUniqueId(); + index_map[source_id] = index++; + } +} diff --git a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h new file mode 100644 index 000000000000..cf75de8ac78e --- /dev/null +++ b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h @@ -0,0 +1,204 @@ +//===-- SymbolFilePDB.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_SymbolFile_PDB_SymbolFilePDB_h_ +#define lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_ + +#include "lldb/Core/UserID.h" +#include "lldb/Symbol/SymbolFile.h" + +#include "llvm/ADT/DenseMap.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/DebugInfo/PDB/PDB.h" + +class SymbolFilePDB : public lldb_private::SymbolFile +{ +public: + //------------------------------------------------------------------ + // Static Functions + //------------------------------------------------------------------ + static void + Initialize(); + + static void + Terminate(); + + static void + DebuggerInitialize(lldb_private::Debugger &debugger); + + static lldb_private::ConstString + GetPluginNameStatic(); + + static const char * + GetPluginDescriptionStatic(); + + static lldb_private::SymbolFile * + CreateInstance(lldb_private::ObjectFile *obj_file); + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + SymbolFilePDB(lldb_private::ObjectFile *ofile); + + ~SymbolFilePDB() override; + + uint32_t + CalculateAbilities() override; + + void + InitializeObject() override; + + //------------------------------------------------------------------ + // Compile Unit function calls + //------------------------------------------------------------------ + + uint32_t + GetNumCompileUnits() override; + + 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 &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::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; + + 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 ®ex, 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 ®ex, bool include_inlines, bool append, + lldb_private::SymbolContextList &sc_list) override; + + void + GetMangledNamesForFunction(const std::string &scope_qualified_name, + std::vector &mangled_names) 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, + llvm::DenseSet &searched_symbol_files, lldb_private::TypeMap &types) override; + + size_t + FindTypes(const std::vector &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; + + lldb_private::ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; + + llvm::pdb::IPDBSession & + GetPDBSession(); + + const llvm::pdb::IPDBSession & + GetPDBSession() const; + +private: + lldb::CompUnitSP + ParseCompileUnitForSymIndex(uint32_t id); + + bool + ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc, uint32_t match_line); + + void + BuildSupportFileIdToSupportFileIndexMap(const llvm::pdb::PDBSymbolCompiland &cu, + llvm::DenseMap &index_map) const; + + void + FindTypesByRegex(const std::string ®ex, uint32_t max_matches, lldb_private::TypeMap &types); + + void + FindTypesByName(const std::string &name, uint32_t max_matches, lldb_private::TypeMap &types); + + llvm::DenseMap m_comp_units; + llvm::DenseMap m_types; + + std::vector m_builtin_types; + std::unique_ptr m_session_up; + uint32_t m_cached_compile_unit_count; + std::unique_ptr m_tu_decl_ctx_up; +}; + +#endif // lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_ diff --git a/source/Plugins/SymbolFile/Symtab/Makefile b/source/Plugins/SymbolFile/Symtab/Makefile deleted file mode 100644 index 2c3dbb6d86ab..000000000000 --- a/source/Plugins/SymbolFile/Symtab/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/SymbolFile/Symtab/Makefile -----------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginSymbolFileSymtab -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp index d3dd1ae923e0..24175079c95f 100644 --- a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp +++ b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp @@ -153,7 +153,8 @@ 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, false)); + cu_sp.reset(new CompileUnit(m_obj_file->GetModule(), NULL, cu_symbol->GetName().AsCString(), 0, + eLanguageTypeUnknown, eLazyBoolNo)); } return cu_sp; } diff --git a/source/Plugins/SymbolVendor/ELF/Makefile b/source/Plugins/SymbolVendor/ELF/Makefile deleted file mode 100644 index 47c24a2bda34..000000000000 --- a/source/Plugins/SymbolVendor/ELF/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/SymbolVendor/ELF/Makefile ---------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginSymbolVendorELF -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/SymbolVendor/MacOSX/Makefile b/source/Plugins/SymbolVendor/MacOSX/Makefile deleted file mode 100644 index 9f71ad669aa0..000000000000 --- a/source/Plugins/SymbolVendor/MacOSX/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/SymbolVendor/MacOSX/Makefile ---------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginSymbolVendorMacOSX -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp index 2ca367c0cce8..38998469dcbe 100644 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp +++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/Value.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Symbol/ClangASTContext.h" @@ -95,12 +96,12 @@ extern \"C\" } \n\ "; -AppleGetItemInfoHandler::AppleGetItemInfoHandler (Process *process) : - m_process (process), - m_get_item_info_impl_code (), - m_get_item_info_function_mutex(), - m_get_item_info_return_buffer_addr (LLDB_INVALID_ADDRESS), - m_get_item_info_retbuffer_mutex() +AppleGetItemInfoHandler::AppleGetItemInfoHandler(Process *process) + : m_process(process), + m_get_item_info_impl_code(), + m_get_item_info_function_mutex(), + m_get_item_info_return_buffer_addr(LLDB_INVALID_ADDRESS), + m_get_item_info_retbuffer_mutex() { } @@ -109,14 +110,14 @@ AppleGetItemInfoHandler::~AppleGetItemInfoHandler () } void -AppleGetItemInfoHandler::Detach () +AppleGetItemInfoHandler::Detach() { if (m_process && m_process->IsAlive() && m_get_item_info_return_buffer_addr != LLDB_INVALID_ADDRESS) { - Mutex::Locker locker; - locker.TryLock (m_get_item_info_retbuffer_mutex); // Even if we don't get the lock, deallocate the buffer - m_process->DeallocateMemory (m_get_item_info_return_buffer_addr); + std::unique_lock lock(m_get_item_info_retbuffer_mutex, std::defer_lock); + lock.try_lock(); // Even if we don't get the lock, deallocate the buffer + m_process->DeallocateMemory(m_get_item_info_return_buffer_addr); } } @@ -132,18 +133,18 @@ AppleGetItemInfoHandler::Detach () // make the function call. lldb::addr_t -AppleGetItemInfoHandler::SetupGetItemInfoFunction (Thread &thread, ValueList &get_item_info_arglist) +AppleGetItemInfoHandler::SetupGetItemInfoFunction(Thread &thread, ValueList &get_item_info_arglist) { - ExecutionContext exe_ctx (thread.shared_from_this()); - StreamString errors; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME)); + ExecutionContext exe_ctx(thread.shared_from_this()); + DiagnosticManager diagnostics; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; FunctionCaller *get_item_info_caller = nullptr; // Scope for mutex locker: { - Mutex::Locker locker(m_get_item_info_function_mutex); - + std::lock_guard guard(m_get_item_info_function_mutex); + // First stage is to make the UtilityFunction to hold our injected function: if (!m_get_item_info_impl_code.get()) @@ -161,11 +162,14 @@ AppleGetItemInfoHandler::SetupGetItemInfoFunction (Thread &thread, ValueList &ge log->Printf ("Failed to get utility function: %s.", error.AsCString()); return args_addr; } - - if (!m_get_item_info_impl_code->Install(errors, exe_ctx)) + + if (!m_get_item_info_impl_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install get-item-info introspection: %s.", errors.GetData()); + { + log->Printf("Failed to install get-item-info introspection."); + diagnostics.Dump(log); + } m_get_item_info_impl_code.reset(); return args_addr; } @@ -174,7 +178,6 @@ AppleGetItemInfoHandler::SetupGetItemInfoFunction (Thread &thread, ValueList &ge { if (log) log->Printf("No get-item-info introspection code found."); - errors.Printf ("No get-item-info introspection code found."); return LLDB_INVALID_ADDRESS; } @@ -186,6 +189,7 @@ AppleGetItemInfoHandler::SetupGetItemInfoFunction (Thread &thread, ValueList &ge get_item_info_caller = m_get_item_info_impl_code->MakeFunctionCaller(get_item_info_return_type, get_item_info_arglist, + thread.shared_from_this(), error); if (error.Fail()) { @@ -207,20 +211,24 @@ AppleGetItemInfoHandler::SetupGetItemInfoFunction (Thread &thread, ValueList &ge } } } - - errors.Clear(); - + + diagnostics.Clear(); + // Now write down the argument values for this particular call. This looks like it might be a race condition // if other threads were calling into here, but actually it isn't because we allocate a new args structure for // this call by passing args_addr = LLDB_INVALID_ADDRESS... - if (!get_item_info_caller->WriteFunctionArguments (exe_ctx, args_addr, get_item_info_arglist, errors)) + if (!get_item_info_caller->WriteFunctionArguments(exe_ctx, args_addr, get_item_info_arglist, diagnostics)) { if (log) - log->Printf ("Error writing get-item-info function arguments: \"%s\".", errors.GetData()); + { + log->Printf("Error writing get-item-info function arguments."); + diagnostics.Dump(log); + } + return args_addr; } - + return args_addr; } @@ -288,8 +296,7 @@ AppleGetItemInfoHandler::GetItemInfo (Thread &thread, uint64_t item, addr_t page page_to_free_size_value.SetValueType (Value::eValueTypeScalar); page_to_free_size_value.SetCompilerType (clang_uint64_type); - - Mutex::Locker locker(m_get_item_info_retbuffer_mutex); + std::lock_guard guard(m_get_item_info_retbuffer_mutex); if (m_get_item_info_return_buffer_addr == LLDB_INVALID_ADDRESS) { addr_t bufaddr = process_sp->AllocateMemory (32, ePermissionsReadable | ePermissionsWritable, error); @@ -322,12 +329,12 @@ AppleGetItemInfoHandler::GetItemInfo (Thread &thread, uint64_t item, addr_t page page_to_free_size_value.GetScalar() = page_to_free_size; argument_values.PushValue (page_to_free_size_value); - addr_t args_addr = SetupGetItemInfoFunction (thread, argument_values); + addr_t args_addr = SetupGetItemInfoFunction(thread, argument_values); - StreamString errors; + DiagnosticManager diagnostics; ExecutionContext exe_ctx; EvaluateExpressionOptions options; - options.SetUnwindOnError (true); + options.SetUnwindOnError(true); options.SetIgnoreBreakpoints (true); options.SetStopOthers (true); options.SetTimeoutUsec(500000); @@ -351,8 +358,8 @@ AppleGetItemInfoHandler::GetItemInfo (Thread &thread, uint64_t item, addr_t page error.SetErrorString("Could not retrieve function caller for __introspection_dispatch_queue_item_get_info."); return return_value; } - - func_call_ret = func_caller->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); + + func_call_ret = func_caller->ExecuteFunction(exe_ctx, &args_addr, options, diagnostics, results); if (func_call_ret != eExpressionCompleted || !error.Success()) { if (log) diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h b/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h index 51182a624939..dc341d672d6a 100644 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h +++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h @@ -13,13 +13,14 @@ // C Includes // C++ Includes #include +#include #include + // Other libraries and framework includes // Project includes #include "lldb/lldb-public.h" #include "lldb/Core/Error.h" #include "lldb/Expression/UtilityFunction.h" -#include "lldb/Host/Mutex.h" #include "lldb/Symbol/CompilerType.h" // This class will insert a UtilityFunction into the inferior process for @@ -105,11 +106,10 @@ private: lldb_private::Process *m_process; std::unique_ptr m_get_item_info_impl_code; - Mutex m_get_item_info_function_mutex; + std::mutex m_get_item_info_function_mutex; lldb::addr_t m_get_item_info_return_buffer_addr; - Mutex m_get_item_info_retbuffer_mutex; - + std::mutex m_get_item_info_retbuffer_mutex; }; } // using namespace lldb_private diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp index 97699878f5ee..d311f5fb5f6e 100644 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp +++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/Value.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Symbol/ClangASTContext.h" @@ -99,12 +100,12 @@ extern \"C\" } \n\ "; -AppleGetPendingItemsHandler::AppleGetPendingItemsHandler (Process *process) : - m_process (process), - m_get_pending_items_impl_code (), - m_get_pending_items_function_mutex(), - m_get_pending_items_return_buffer_addr (LLDB_INVALID_ADDRESS), - m_get_pending_items_retbuffer_mutex() +AppleGetPendingItemsHandler::AppleGetPendingItemsHandler(Process *process) + : m_process(process), + m_get_pending_items_impl_code(), + m_get_pending_items_function_mutex(), + m_get_pending_items_return_buffer_addr(LLDB_INVALID_ADDRESS), + m_get_pending_items_retbuffer_mutex() { } @@ -113,14 +114,13 @@ AppleGetPendingItemsHandler::~AppleGetPendingItemsHandler () } void -AppleGetPendingItemsHandler::Detach () +AppleGetPendingItemsHandler::Detach() { - if (m_process && m_process->IsAlive() && m_get_pending_items_return_buffer_addr != LLDB_INVALID_ADDRESS) { - Mutex::Locker locker; - locker.TryLock (m_get_pending_items_retbuffer_mutex); // Even if we don't get the lock, deallocate the buffer - m_process->DeallocateMemory (m_get_pending_items_return_buffer_addr); + std::unique_lock lock(m_get_pending_items_retbuffer_mutex, std::defer_lock); + lock.try_lock(); // Even if we don't get the lock, deallocate the buffer + m_process->DeallocateMemory(m_get_pending_items_return_buffer_addr); } } @@ -136,18 +136,20 @@ AppleGetPendingItemsHandler::Detach () // make the function call. lldb::addr_t -AppleGetPendingItemsHandler::SetupGetPendingItemsFunction (Thread &thread, ValueList &get_pending_items_arglist) +AppleGetPendingItemsHandler::SetupGetPendingItemsFunction(Thread &thread, ValueList &get_pending_items_arglist) { - ExecutionContext exe_ctx (thread.shared_from_this()); - StreamString errors; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME)); + ThreadSP thread_sp (thread.shared_from_this()); + ExecutionContext exe_ctx (thread_sp); + DiagnosticManager diagnostics; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); + lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; FunctionCaller *get_pending_items_caller = nullptr; - + // Scope for mutex locker: { - Mutex::Locker locker(m_get_pending_items_function_mutex); - + std::lock_guard guard(m_get_pending_items_function_mutex); + // First stage is to make the ClangUtility to hold our injected function: if (!m_get_pending_items_impl_code.get()) @@ -165,11 +167,14 @@ AppleGetPendingItemsHandler::SetupGetPendingItemsFunction (Thread &thread, Value log->Printf ("Failed to get UtilityFunction for pending-items introspection: %s.", error.AsCString()); return args_addr; } - - if (!m_get_pending_items_impl_code->Install(errors, exe_ctx)) + + if (!m_get_pending_items_impl_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install pending-items introspection: %s.", errors.GetData()); + { + log->Printf("Failed to install pending-items introspection."); + diagnostics.Dump(log); + } m_get_pending_items_impl_code.reset(); return args_addr; } @@ -187,6 +192,7 @@ AppleGetPendingItemsHandler::SetupGetPendingItemsFunction (Thread &thread, Value CompilerType get_pending_items_return_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); get_pending_items_caller = m_get_pending_items_impl_code->MakeFunctionCaller (get_pending_items_return_type, get_pending_items_arglist, + thread_sp, error); if (error.Fail()) { @@ -196,11 +202,10 @@ AppleGetPendingItemsHandler::SetupGetPendingItemsFunction (Thread &thread, Value return args_addr; } } - } - - errors.Clear(); - + + diagnostics.Clear(); + if (get_pending_items_caller == nullptr) { if (log) @@ -212,13 +217,17 @@ AppleGetPendingItemsHandler::SetupGetPendingItemsFunction (Thread &thread, Value // if other threads were calling into here, but actually it isn't because we allocate a new args structure for // this call by passing args_addr = LLDB_INVALID_ADDRESS... - if (!get_pending_items_caller->WriteFunctionArguments (exe_ctx, args_addr, get_pending_items_arglist, errors)) + if (!get_pending_items_caller->WriteFunctionArguments(exe_ctx, args_addr, get_pending_items_arglist, diagnostics)) { if (log) - log->Printf ("Error writing pending-items function arguments: \"%s\".", errors.GetData()); + { + log->Printf("Error writing pending-items function arguments."); + diagnostics.Dump(log); + } + return args_addr; } - + return args_addr; } @@ -288,8 +297,7 @@ AppleGetPendingItemsHandler::GetPendingItems (Thread &thread, addr_t queue, addr page_to_free_size_value.SetValueType (Value::eValueTypeScalar); page_to_free_size_value.SetCompilerType (clang_uint64_type); - - Mutex::Locker locker(m_get_pending_items_retbuffer_mutex); + std::lock_guard guard(m_get_pending_items_retbuffer_mutex); if (m_get_pending_items_return_buffer_addr == LLDB_INVALID_ADDRESS) { addr_t bufaddr = process_sp->AllocateMemory (32, ePermissionsReadable | ePermissionsWritable, error); @@ -322,12 +330,12 @@ AppleGetPendingItemsHandler::GetPendingItems (Thread &thread, addr_t queue, addr page_to_free_size_value.GetScalar() = page_to_free_size; argument_values.PushValue (page_to_free_size_value); - addr_t args_addr = SetupGetPendingItemsFunction (thread, argument_values); + addr_t args_addr = SetupGetPendingItemsFunction(thread, argument_values); - StreamString errors; + DiagnosticManager diagnostics; ExecutionContext exe_ctx; FunctionCaller *get_pending_items_caller = m_get_pending_items_impl_code->GetFunctionCaller(); - + EvaluateExpressionOptions options; options.SetUnwindOnError (true); options.SetIgnoreBreakpoints (true); @@ -342,10 +350,9 @@ AppleGetPendingItemsHandler::GetPendingItems (Thread &thread, addr_t queue, addr return return_value; } - ExpressionResults func_call_ret; Value results; - func_call_ret = get_pending_items_caller->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); + func_call_ret = get_pending_items_caller->ExecuteFunction(exe_ctx, &args_addr, options, diagnostics, results); if (func_call_ret != eExpressionCompleted || !error.Success()) { if (log) diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h b/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h index 445c4a0fb82b..96fbf4a548c4 100644 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h +++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h @@ -13,12 +13,13 @@ // C Includes // C++ Includes #include +#include #include + // Other libraries and framework includes // Project includes #include "lldb/lldb-public.h" #include "lldb/Core/Error.h" -#include "lldb/Host/Mutex.h" #include "lldb/Symbol/CompilerType.h" // This class will insert a UtilityFunction into the inferior process for @@ -107,11 +108,10 @@ private: lldb_private::Process *m_process; std::unique_ptr m_get_pending_items_impl_code; - Mutex m_get_pending_items_function_mutex; + std::mutex m_get_pending_items_function_mutex; lldb::addr_t m_get_pending_items_return_buffer_addr; - Mutex m_get_pending_items_retbuffer_mutex; - + std::mutex m_get_pending_items_retbuffer_mutex; }; } // using namespace lldb_private diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp index 3370b3257a25..e90fe6d5d17d 100644 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp +++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp @@ -18,6 +18,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/Value.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Symbol/ClangASTContext.h" @@ -95,12 +96,12 @@ extern \"C\" } \n\ "; -AppleGetQueuesHandler::AppleGetQueuesHandler (Process *process) : - m_process (process), - m_get_queues_impl_code_up (), - m_get_queues_function_mutex(), - m_get_queues_return_buffer_addr (LLDB_INVALID_ADDRESS), - m_get_queues_retbuffer_mutex() +AppleGetQueuesHandler::AppleGetQueuesHandler(Process *process) + : m_process(process), + m_get_queues_impl_code_up(), + m_get_queues_function_mutex(), + m_get_queues_return_buffer_addr(LLDB_INVALID_ADDRESS), + m_get_queues_retbuffer_mutex() { } @@ -109,14 +110,14 @@ AppleGetQueuesHandler::~AppleGetQueuesHandler () } void -AppleGetQueuesHandler::Detach () +AppleGetQueuesHandler::Detach() { if (m_process && m_process->IsAlive() && m_get_queues_return_buffer_addr != LLDB_INVALID_ADDRESS) { - Mutex::Locker locker; - locker.TryLock (m_get_queues_retbuffer_mutex); // Even if we don't get the lock, deallocate the buffer - m_process->DeallocateMemory (m_get_queues_return_buffer_addr); + std::unique_lock lock(m_get_queues_retbuffer_mutex, std::defer_lock); + lock.try_lock(); // Even if we don't get the lock, deallocate the buffer + m_process->DeallocateMemory(m_get_queues_return_buffer_addr); } } @@ -146,18 +147,20 @@ AppleGetQueuesHandler::Detach () lldb::addr_t AppleGetQueuesHandler::SetupGetQueuesFunction (Thread &thread, ValueList &get_queues_arglist) { - ExecutionContext exe_ctx (thread.shared_from_this()); + ThreadSP thread_sp(thread.shared_from_this()); + ExecutionContext exe_ctx (thread_sp); + Address impl_code_address; - StreamString errors; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME)); + DiagnosticManager diagnostics; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; - + FunctionCaller *get_queues_caller = nullptr; // Scope for mutex locker: { - Mutex::Locker locker(m_get_queues_function_mutex); - + std::lock_guard guard(m_get_queues_function_mutex); + // First stage is to make the ClangUtility to hold our injected function: if (!m_get_queues_impl_code_up.get()) @@ -175,11 +178,14 @@ AppleGetQueuesHandler::SetupGetQueuesFunction (Thread &thread, ValueList &get_qu log->Printf ("Failed to get UtilityFunction for queues introspection: %s.", error.AsCString()); return args_addr; } - - if (!m_get_queues_impl_code_up->Install(errors, exe_ctx)) + + if (!m_get_queues_impl_code_up->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install queues introspection: %s.", errors.GetData()); + { + log->Printf("Failed to install queues introspection"); + diagnostics.Dump(log); + } m_get_queues_impl_code_up.reset(); return args_addr; } @@ -187,18 +193,21 @@ AppleGetQueuesHandler::SetupGetQueuesFunction (Thread &thread, ValueList &get_qu else { if (log) + { log->Printf("No queues introspection code found."); - errors.Printf ("No queues introspection code found."); + diagnostics.Dump(log); + } return LLDB_INVALID_ADDRESS; } } - + // Next make the runner function for our implementation utility function. ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext(); CompilerType get_queues_return_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); Error error; get_queues_caller = m_get_queues_impl_code_up->MakeFunctionCaller (get_queues_return_type, get_queues_arglist, + thread_sp, error); if (error.Fail()) { @@ -207,20 +216,23 @@ AppleGetQueuesHandler::SetupGetQueuesFunction (Thread &thread, ValueList &get_qu return args_addr; } } - - errors.Clear(); - + + diagnostics.Clear(); + // Now write down the argument values for this particular call. This looks like it might be a race condition // if other threads were calling into here, but actually it isn't because we allocate a new args structure for // this call by passing args_addr = LLDB_INVALID_ADDRESS... - if (!get_queues_caller->WriteFunctionArguments (exe_ctx, args_addr, get_queues_arglist, errors)) + if (!get_queues_caller->WriteFunctionArguments(exe_ctx, args_addr, get_queues_arglist, diagnostics)) { if (log) - log->Printf ("Error writing get-queues function arguments: \"%s\".", errors.GetData()); + { + log->Printf("Error writing get-queues function arguments."); + diagnostics.Dump(log); + } return args_addr; } - + return args_addr; } @@ -285,8 +297,7 @@ AppleGetQueuesHandler::GetCurrentQueues (Thread &thread, addr_t page_to_free, ui page_to_free_size_value.SetValueType (Value::eValueTypeScalar); page_to_free_size_value.SetCompilerType (clang_uint64_type); - - Mutex::Locker locker(m_get_queues_retbuffer_mutex); + std::lock_guard guard(m_get_queues_retbuffer_mutex); if (m_get_queues_return_buffer_addr == LLDB_INVALID_ADDRESS) { addr_t bufaddr = process_sp->AllocateMemory (32, ePermissionsReadable | ePermissionsWritable, error); @@ -332,10 +343,10 @@ AppleGetQueuesHandler::GetCurrentQueues (Thread &thread, addr_t page_to_free, ui return return_value; } - StreamString errors; + DiagnosticManager diagnostics; ExecutionContext exe_ctx; EvaluateExpressionOptions options; - options.SetUnwindOnError (true); + options.SetUnwindOnError(true); options.SetIgnoreBreakpoints (true); options.SetStopOthers (true); options.SetTimeoutUsec(500000); @@ -344,7 +355,7 @@ AppleGetQueuesHandler::GetCurrentQueues (Thread &thread, addr_t page_to_free, ui ExpressionResults func_call_ret; Value results; - func_call_ret = get_queues_caller->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); + func_call_ret = get_queues_caller->ExecuteFunction(exe_ctx, &args_addr, options, diagnostics, results); if (func_call_ret != eExpressionCompleted || !error.Success()) { if (log) diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h b/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h index 6f3df5f62807..b7ca26dafc30 100644 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h +++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h @@ -13,12 +13,13 @@ // C Includes // C++ Includes #include +#include #include + // Other libraries and framework includes // Project includes #include "lldb/lldb-public.h" #include "lldb/Core/Error.h" -#include "lldb/Host/Mutex.h" #include "lldb/Symbol/CompilerType.h" // This class will insert a UtilityFunction into the inferior process for @@ -104,11 +105,10 @@ private: lldb_private::Process *m_process; std::unique_ptr m_get_queues_impl_code_up; - Mutex m_get_queues_function_mutex; + std::mutex m_get_queues_function_mutex; lldb::addr_t m_get_queues_return_buffer_addr; - Mutex m_get_queues_retbuffer_mutex; - + std::mutex m_get_queues_retbuffer_mutex; }; } // using namespace lldb_private diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp index ba03f51152c0..85ad012c59fc 100644 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp +++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp @@ -14,12 +14,12 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/Value.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/Expression.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" @@ -30,6 +30,7 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/lldb-private.h" using namespace lldb; using namespace lldb_private; @@ -102,12 +103,12 @@ extern \"C\" } \n\ "; -AppleGetThreadItemInfoHandler::AppleGetThreadItemInfoHandler (Process *process) : - m_process (process), - m_get_thread_item_info_impl_code (), - m_get_thread_item_info_function_mutex(), - m_get_thread_item_info_return_buffer_addr (LLDB_INVALID_ADDRESS), - m_get_thread_item_info_retbuffer_mutex() +AppleGetThreadItemInfoHandler::AppleGetThreadItemInfoHandler(Process *process) + : m_process(process), + m_get_thread_item_info_impl_code(), + m_get_thread_item_info_function_mutex(), + m_get_thread_item_info_return_buffer_addr(LLDB_INVALID_ADDRESS), + m_get_thread_item_info_retbuffer_mutex() { } @@ -116,14 +117,14 @@ AppleGetThreadItemInfoHandler::~AppleGetThreadItemInfoHandler () } void -AppleGetThreadItemInfoHandler::Detach () +AppleGetThreadItemInfoHandler::Detach() { if (m_process && m_process->IsAlive() && m_get_thread_item_info_return_buffer_addr != LLDB_INVALID_ADDRESS) { - Mutex::Locker locker; - locker.TryLock (m_get_thread_item_info_retbuffer_mutex); // Even if we don't get the lock, deallocate the buffer - m_process->DeallocateMemory (m_get_thread_item_info_return_buffer_addr); + std::unique_lock lock(m_get_thread_item_info_retbuffer_mutex, std::defer_lock); + lock.try_lock(); // Even if we don't get the lock, deallocate the buffer + m_process->DeallocateMemory(m_get_thread_item_info_return_buffer_addr); } } @@ -141,17 +142,18 @@ AppleGetThreadItemInfoHandler::Detach () lldb::addr_t AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction (Thread &thread, ValueList &get_thread_item_info_arglist) { - ExecutionContext exe_ctx (thread.shared_from_this()); + ThreadSP thread_sp(thread.shared_from_this()); + ExecutionContext exe_ctx (thread_sp); Address impl_code_address; - StreamString errors; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME)); + DiagnosticManager diagnostics; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; FunctionCaller *get_thread_item_info_caller = nullptr; // Scope for mutex locker: { - Mutex::Locker locker(m_get_thread_item_info_function_mutex); - + std::lock_guard guard(m_get_thread_item_info_function_mutex); + // First stage is to make the ClangUtility to hold our injected function: if (!m_get_thread_item_info_impl_code.get()) @@ -171,11 +173,15 @@ AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction (Thread &thread, V m_get_thread_item_info_impl_code.reset(); return args_addr; } - - if (!m_get_thread_item_info_impl_code->Install(errors, exe_ctx)) + + if (!m_get_thread_item_info_impl_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install get-thread-item-info introspection: %s.", errors.GetData()); + { + log->Printf("Failed to install get-thread-item-info introspection."); + diagnostics.Dump(log); + } + m_get_thread_item_info_impl_code.reset(); return args_addr; } @@ -184,10 +190,9 @@ AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction (Thread &thread, V { if (log) log->Printf("No get-thread-item-info introspection code found."); - errors.Printf ("No get-thread-item-info introspection code found."); return LLDB_INVALID_ADDRESS; } - + // Also make the FunctionCaller for this UtilityFunction: ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext(); @@ -195,6 +200,7 @@ AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction (Thread &thread, V get_thread_item_info_caller = m_get_thread_item_info_impl_code->MakeFunctionCaller (get_thread_item_info_return_type, get_thread_item_info_arglist, + thread_sp, error); if (error.Fail()) { @@ -210,20 +216,24 @@ AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction (Thread &thread, V get_thread_item_info_caller = m_get_thread_item_info_impl_code->GetFunctionCaller(); } } - - errors.Clear(); - + + diagnostics.Clear(); + // Now write down the argument values for this particular call. This looks like it might be a race condition // if other threads were calling into here, but actually it isn't because we allocate a new args structure for // this call by passing args_addr = LLDB_INVALID_ADDRESS... - if (!get_thread_item_info_caller->WriteFunctionArguments (exe_ctx, args_addr, get_thread_item_info_arglist, errors)) + if (!get_thread_item_info_caller->WriteFunctionArguments(exe_ctx, args_addr, get_thread_item_info_arglist, + diagnostics)) { if (log) - log->Printf ("Error writing get-thread-item-info function arguments: \"%s\".", errors.GetData()); + { + log->Printf("Error writing get-thread-item-info function arguments"); + diagnostics.Dump(log); + } return args_addr; } - + return args_addr; } @@ -290,8 +300,7 @@ AppleGetThreadItemInfoHandler::GetThreadItemInfo (Thread &thread, tid_t thread_i page_to_free_size_value.SetValueType (Value::eValueTypeScalar); page_to_free_size_value.SetCompilerType (clang_uint64_type); - - Mutex::Locker locker(m_get_thread_item_info_retbuffer_mutex); + std::lock_guard guard(m_get_thread_item_info_retbuffer_mutex); if (m_get_thread_item_info_return_buffer_addr == LLDB_INVALID_ADDRESS) { addr_t bufaddr = process_sp->AllocateMemory (32, ePermissionsReadable | ePermissionsWritable, error); @@ -324,13 +333,13 @@ AppleGetThreadItemInfoHandler::GetThreadItemInfo (Thread &thread, tid_t thread_i page_to_free_size_value.GetScalar() = page_to_free_size; argument_values.PushValue (page_to_free_size_value); - addr_t args_addr = SetupGetThreadItemInfoFunction (thread, argument_values); + addr_t args_addr = SetupGetThreadItemInfoFunction(thread, argument_values); - StreamString errors; + DiagnosticManager diagnostics; ExecutionContext exe_ctx; EvaluateExpressionOptions options; FunctionCaller *get_thread_item_info_caller = nullptr; - + options.SetUnwindOnError (true); options.SetIgnoreBreakpoints (true); options.SetStopOthers (true); @@ -354,7 +363,7 @@ AppleGetThreadItemInfoHandler::GetThreadItemInfo (Thread &thread, tid_t thread_i ExpressionResults func_call_ret; Value results; - func_call_ret = get_thread_item_info_caller->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); + func_call_ret = get_thread_item_info_caller->ExecuteFunction(exe_ctx, &args_addr, options, diagnostics, results); if (func_call_ret != eExpressionCompleted || !error.Success()) { if (log) diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h b/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h index c1798fb515b4..21a63e8c225a 100644 --- a/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h +++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h @@ -13,12 +13,13 @@ // C Includes // C++ Includes #include +#include #include + // Other libraries and framework includes // Project includes #include "lldb/lldb-public.h" #include "lldb/Core/Error.h" -#include "lldb/Host/Mutex.h" #include "lldb/Symbol/CompilerType.h" // This class will insert a UtilityFunction into the inferior process for @@ -101,11 +102,10 @@ private: lldb_private::Process *m_process; std::unique_ptr m_get_thread_item_info_impl_code; - Mutex m_get_thread_item_info_function_mutex; + std::mutex m_get_thread_item_info_function_mutex; lldb::addr_t m_get_thread_item_info_return_buffer_addr; - Mutex m_get_thread_item_info_retbuffer_mutex; - + std::mutex m_get_thread_item_info_retbuffer_mutex; }; } // using namespace lldb_private diff --git a/source/Plugins/SystemRuntime/MacOSX/Makefile b/source/Plugins/SystemRuntime/MacOSX/Makefile deleted file mode 100644 index eebfb52073d5..000000000000 --- a/source/Plugins/SystemRuntime/MacOSX/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/SystemRuntime/MacOSX ----*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginSystemRuntimeMacOSX -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp b/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp index 1097ef36960e..9ec36b383af3 100644 --- a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp +++ b/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp @@ -83,25 +83,25 @@ SystemRuntimeMacOSX::CreateInstance (Process* process) //---------------------------------------------------------------------- // Constructor //---------------------------------------------------------------------- -SystemRuntimeMacOSX::SystemRuntimeMacOSX (Process* process) : - SystemRuntime(process), - m_break_id(LLDB_INVALID_BREAK_ID), - m_mutex(Mutex::eMutexTypeRecursive), - m_get_queues_handler(process), - m_get_pending_items_handler(process), - m_get_item_info_handler(process), - m_get_thread_item_info_handler(process), - m_page_to_free(LLDB_INVALID_ADDRESS), - m_page_to_free_size(0), - m_lib_backtrace_recording_info(), - m_dispatch_queue_offsets_addr (LLDB_INVALID_ADDRESS), - m_libdispatch_offsets(), - m_libpthread_layout_offsets_addr (LLDB_INVALID_ADDRESS), - m_libpthread_offsets(), - m_dispatch_tsd_indexes_addr (LLDB_INVALID_ADDRESS), - m_libdispatch_tsd_indexes(), - m_dispatch_voucher_offsets_addr (LLDB_INVALID_ADDRESS), - m_libdispatch_voucher_offsets() +SystemRuntimeMacOSX::SystemRuntimeMacOSX(Process *process) + : SystemRuntime(process), + m_break_id(LLDB_INVALID_BREAK_ID), + m_mutex(), + m_get_queues_handler(process), + m_get_pending_items_handler(process), + m_get_item_info_handler(process), + m_get_thread_item_info_handler(process), + m_page_to_free(LLDB_INVALID_ADDRESS), + m_page_to_free_size(0), + m_lib_backtrace_recording_info(), + m_dispatch_queue_offsets_addr(LLDB_INVALID_ADDRESS), + m_libdispatch_offsets(), + m_libpthread_layout_offsets_addr(LLDB_INVALID_ADDRESS), + m_libpthread_offsets(), + m_dispatch_tsd_indexes_addr(LLDB_INVALID_ADDRESS), + m_libdispatch_tsd_indexes(), + m_dispatch_voucher_offsets_addr(LLDB_INVALID_ADDRESS), + m_libdispatch_voucher_offsets() { } @@ -128,7 +128,7 @@ SystemRuntimeMacOSX::Detach () void SystemRuntimeMacOSX::Clear (bool clear_process) { - Mutex::Locker locker(m_mutex); + std::lock_guard guard(m_mutex); if (m_process->IsAlive() && LLDB_BREAK_ID_IS_VALID(m_break_id)) m_process->ClearBreakpointSiteByID(m_break_id); @@ -486,7 +486,7 @@ SystemRuntimeMacOSX::GetExtendedBacktraceThread (ThreadSP real_thread, ConstStri } else { - ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread()); + ThreadSP cur_thread_sp (m_process->GetThreadList().GetExpressionExecutionThread()); AppleGetThreadItemInfoHandler::GetThreadItemInfoReturnInfo ret = m_get_thread_item_info_handler.GetThreadItemInfo (*cur_thread_sp.get(), real_thread->GetID(), m_page_to_free, m_page_to_free_size, error); m_page_to_free = LLDB_INVALID_ADDRESS; m_page_to_free_size = 0; @@ -524,7 +524,7 @@ SystemRuntimeMacOSX::GetExtendedBacktraceFromItemRef (lldb::addr_t item_ref) ThreadSP return_thread_sp; AppleGetItemInfoHandler::GetItemInfoReturnInfo ret; - ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread()); + ThreadSP cur_thread_sp (m_process->GetThreadList().GetExpressionExecutionThread()); Error error; ret = m_get_item_info_handler.GetItemInfo (*cur_thread_sp.get(), item_ref, m_page_to_free, m_page_to_free_size, error); m_page_to_free = LLDB_INVALID_ADDRESS; @@ -696,7 +696,7 @@ SystemRuntimeMacOSX::PopulateQueueList (lldb_private::QueueList &queue_list) if (BacktraceRecordingHeadersInitialized()) { AppleGetQueuesHandler::GetQueuesReturnInfo queue_info_pointer; - ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread()); + ThreadSP cur_thread_sp (m_process->GetThreadList().GetExpressionExecutionThread()); if (cur_thread_sp) { Error error; @@ -760,7 +760,7 @@ SystemRuntimeMacOSX::GetPendingItemRefsForQueue (lldb::addr_t queue) { PendingItemsForQueue pending_item_refs; AppleGetPendingItemsHandler::GetPendingItemsReturnInfo pending_items_pointer; - ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread()); + ThreadSP cur_thread_sp (m_process->GetThreadList().GetExpressionExecutionThread()); if (cur_thread_sp) { Error error; @@ -859,7 +859,7 @@ SystemRuntimeMacOSX::CompleteQueueItem (QueueItem *queue_item, addr_t item_ref) { AppleGetItemInfoHandler::GetItemInfoReturnInfo ret; - ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread()); + ThreadSP cur_thread_sp (m_process->GetThreadList().GetExpressionExecutionThread()); Error error; ret = m_get_item_info_handler.GetItemInfo (*cur_thread_sp.get(), item_ref, m_page_to_free, m_page_to_free_size, error); m_page_to_free = LLDB_INVALID_ADDRESS; diff --git a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h b/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h index 8fe15fa4d8a5..b685a056f5c2 100644 --- a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h +++ b/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h @@ -12,8 +12,9 @@ // C Includes // C++ Includes -#include +#include #include +#include // Other libraries and framework include // Project includes @@ -23,7 +24,6 @@ #include "lldb/Core/StructuredData.h" #include "lldb/Core/UUID.h" #include "lldb/Host/FileSpec.h" -#include "lldb/Host/Mutex.h" #include "lldb/Target/Process.h" #include "lldb/Target/QueueItem.h" @@ -124,7 +124,7 @@ public: protected: lldb::user_id_t m_break_id; - mutable lldb_private::Mutex m_mutex; + mutable std::recursive_mutex m_mutex; private: struct libBacktraceRecording_info { diff --git a/source/Plugins/UnwindAssembly/InstEmulation/Makefile b/source/Plugins/UnwindAssembly/InstEmulation/Makefile deleted file mode 100644 index e006235864f1..000000000000 --- a/source/Plugins/UnwindAssembly/InstEmulation/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##==- source/Plugins/UnwindAssembly/InstEmulation/Makefile -*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginUnwindAssemblyInstEmulation -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp index eb5fec34fc20..72adf7576270 100644 --- a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -125,6 +125,10 @@ UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& RegisterInfo ra_reg_info; m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, ra_reg_info); + // The architecture dependent condition code of the last processed instruction. + EmulateInstruction::InstructionCondition last_condition = EmulateInstruction::UnconditionalCondition; + lldb::addr_t condition_block_start_offset = 0; + for (size_t idx=0; idxsecond.first; m_curr_row.reset(newrow); - m_register_values = it->second.second;; + m_register_values = it->second.second; + } + + m_inst_emulator_ap->SetInstruction (inst->GetOpcode(), + inst->GetAddress(), + exe_ctx.GetTargetPtr()); + + if (last_condition != m_inst_emulator_ap->GetInstructionCondition()) + { + if (m_inst_emulator_ap->GetInstructionCondition() != EmulateInstruction::UnconditionalCondition && + saved_unwind_states.count(current_offset) == 0) + { + // If we don't have a saved row for the current offset then save our + // current state because we will have to restore it after the + // conditional block. + auto new_row = std::make_shared(*m_curr_row.get()); + saved_unwind_states.insert({current_offset, {new_row, m_register_values}}); + } + + // If the last instruction was conditional with a different condition + // then the then current condition then restore the condition. + if (last_condition != EmulateInstruction::UnconditionalCondition) + { + const auto& saved_state = saved_unwind_states.at(condition_block_start_offset); + m_curr_row = std::make_shared(*saved_state.first); + m_curr_row->SetOffset(current_offset); + m_register_values = saved_state.second; + bool replace_existing = true; // The last instruction might already + // created a row for this offset and + // we want to overwrite it. + unwind_plan.InsertRow(std::make_shared(*m_curr_row), replace_existing); + } + + // We are starting a new conditional block at the catual offset + condition_block_start_offset = current_offset; } if (log && log->GetVerbose ()) @@ -158,9 +196,7 @@ UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& log->PutCString (strm.GetData()); } - m_inst_emulator_ap->SetInstruction (inst->GetOpcode(), - inst->GetAddress(), - exe_ctx.GetTargetPtr()); + last_condition = m_inst_emulator_ap->GetInstructionCondition(); m_inst_emulator_ap->EvaluateInstruction (eEmulateInstructionOptionIgnoreConditions); @@ -193,9 +229,6 @@ UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& } } } - // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions. - // I'll fix that but for now, just clear the list and it will go away nicely. - disasm_sp->GetInstructionList().Clear(); } if (log && log->GetVerbose ()) @@ -503,8 +536,7 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction, log->PutCString(strm.GetData()); } - if (!instruction->IsInstructionConditional()) - SetRegisterValue (*reg_info, reg_value); + SetRegisterValue (*reg_info, reg_value); switch (context.type) { @@ -519,7 +551,6 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction, case EmulateInstruction::eContextTableBranchReadMemory: case EmulateInstruction::eContextWriteRegisterRandomBits: case EmulateInstruction::eContextWriteMemoryRandomBits: - case EmulateInstruction::eContextArithmetic: case EmulateInstruction::eContextAdvancePC: case EmulateInstruction::eContextReturnFromException: case EmulateInstruction::eContextPushRegisterOnStack: @@ -538,6 +569,22 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction, // } break; + case EmulateInstruction::eContextArithmetic: + { + // If we adjusted the current frame pointer by a constant then adjust the CFA offset + // with the same amount. + lldb::RegisterKind kind = m_unwind_plan_ptr->GetRegisterKind(); + if (m_fp_is_cfa && reg_info->kinds[kind] == m_cfa_reg_info.kinds[kind] && + context.info_type == EmulateInstruction::eInfoTypeRegisterPlusOffset && + context.info.RegisterPlusOffset.reg.kinds[kind] == m_cfa_reg_info.kinds[kind]) + { + const int64_t offset = context.info.RegisterPlusOffset.signed_offset; + m_curr_row->GetCFAValue().IncOffset(-1 * offset); + m_curr_row_modified = true; + } + } + break; + case EmulateInstruction::eContextAbsoluteBranchRegister: case EmulateInstruction::eContextRelativeBranchImmediate: { @@ -566,45 +613,42 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction, case EmulateInstruction::eContextPopRegisterOffStack: { - if (!instruction->IsInstructionConditional()) + 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) { - 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) { - 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; - } + 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 && !instruction->IsInstructionConditional()) + if (!m_fp_is_cfa) { m_fp_is_cfa = true; m_cfa_reg_info = *reg_info; @@ -619,7 +663,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 && !instruction->IsInstructionConditional()) + if (!m_fp_is_cfa) { m_curr_row->GetCFAValue().SetIsRegisterPlusOffset( m_curr_row->GetCFAValue().GetRegisterNumber(), diff --git a/source/Plugins/UnwindAssembly/x86/Makefile b/source/Plugins/UnwindAssembly/x86/Makefile deleted file mode 100644 index 24419c044f04..000000000000 --- a/source/Plugins/UnwindAssembly/x86/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##==-- source/Plugins/UnwindAssembly/x86/Makefile ----------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginUnwindAssemblyX86 -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile -- cgit v1.2.3