From e81d9d49145e432d917eea3a70d2ae74dcad1d89 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Wed, 30 Dec 2015 11:55:28 +0000 Subject: Vendor import of stripped lldb trunk r256633: https://llvm.org/svn/llvm-project/lldb/trunk@256633 --- source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp | 317 +- source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h | 81 +- .../Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp | 170 +- source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h | 72 +- source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp | 397 +- source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h | 84 +- source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp | 262 +- source/Plugins/ABI/SysV-arm/ABISysV_arm.h | 16 +- source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp | 31 +- source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h | 17 +- .../Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp | 38 +- source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h | 117 +- source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp | 495 +- source/Plugins/ABI/SysV-i386/ABISysV_i386.h | 37 +- source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp | 327 +- source/Plugins/ABI/SysV-mips/ABISysV_mips.h | 96 +- source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp | 542 +- source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h | 88 +- source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp | 347 +- source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h | 98 +- source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp | 348 +- source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h | 98 +- source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp | 475 +- source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h | 88 +- .../Disassembler/llvm/DisassemblerLLVMC.cpp | 236 +- .../Plugins/Disassembler/llvm/DisassemblerLLVMC.h | 57 +- .../Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp | 37 +- .../Hexagon-DYLD/DynamicLoaderHexagonDYLD.h | 66 +- .../DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp | 42 +- .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp | 63 +- .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.h | 76 +- .../DynamicLoader/Static/DynamicLoaderStatic.h | 42 +- .../Windows-DYLD/DynamicLoaderWindowsDYLD.cpp | 42 +- .../Windows-DYLD/DynamicLoaderWindowsDYLD.h | 25 +- .../Plugins/ExpressionParser/Clang/ASTDumper.cpp | 134 + source/Plugins/ExpressionParser/Clang/ASTDumper.h | 42 + .../Clang/ASTResultSynthesizer.cpp | 514 ++ .../ExpressionParser/Clang/ASTResultSynthesizer.h | 185 + .../ExpressionParser/Clang/ASTStructExtractor.cpp | 221 + .../ExpressionParser/Clang/ASTStructExtractor.h | 158 + .../ExpressionParser/Clang/ClangASTSource.cpp | 2101 +++++ .../ExpressionParser/Clang/ClangASTSource.h | 526 ++ .../Clang/ClangExpressionDeclMap.cpp | 2351 ++++++ .../Clang/ClangExpressionDeclMap.h | 714 ++ .../ExpressionParser/Clang/ClangExpressionHelper.h | 79 + .../Clang/ClangExpressionParser.cpp | 657 ++ .../ExpressionParser/Clang/ClangExpressionParser.h | 136 + .../Clang/ClangExpressionVariable.cpp | 76 + .../Clang/ClangExpressionVariable.h | 265 + .../ExpressionParser/Clang/ClangFunctionCaller.cpp | 221 + .../ExpressionParser/Clang/ClangFunctionCaller.h | 173 + .../Clang/ClangModulesDeclVendor.cpp | 731 ++ .../Clang/ClangModulesDeclVendor.h | 128 + .../Clang/ClangPersistentVariables.cpp | 84 + .../Clang/ClangPersistentVariables.h | 106 + .../ExpressionParser/Clang/ClangUserExpression.cpp | 673 ++ .../ExpressionParser/Clang/ClangUserExpression.h | 218 + .../Clang/ClangUtilityFunction.cpp | 189 + .../ExpressionParser/Clang/ClangUtilityFunction.h | 137 + .../Plugins/ExpressionParser/Clang/IRForTarget.cpp | 2820 +++++++ .../Plugins/ExpressionParser/Clang/IRForTarget.h | 745 ++ source/Plugins/ExpressionParser/Go/GoAST.h | 3225 ++++++++ source/Plugins/ExpressionParser/Go/GoLexer.cpp | 402 + source/Plugins/ExpressionParser/Go/GoLexer.h | 201 + source/Plugins/ExpressionParser/Go/GoParser.cpp | 1035 +++ source/Plugins/ExpressionParser/Go/GoParser.h | 165 + .../ExpressionParser/Go/GoUserExpression.cpp | 756 ++ .../Plugins/ExpressionParser/Go/GoUserExpression.h | 98 + source/Plugins/ExpressionParser/Go/gen_go_ast.py | 356 + .../Instruction/ARM/EmulateInstructionARM.cpp | 406 +- .../Instruction/ARM/EmulateInstructionARM.h | 48 +- .../Instruction/ARM64/EmulateInstructionARM64.cpp | 304 +- .../Instruction/ARM64/EmulateInstructionARM64.h | 93 +- .../Instruction/MIPS/EmulateInstructionMIPS.cpp | 2005 ++++- .../Instruction/MIPS/EmulateInstructionMIPS.h | 132 +- .../MIPS64/EmulateInstructionMIPS64.cpp | 1119 ++- .../Instruction/MIPS64/EmulateInstructionMIPS64.h | 114 +- .../AddressSanitizer/AddressSanitizerRuntime.cpp | 74 +- .../AddressSanitizer/AddressSanitizerRuntime.h | 48 +- source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp | 77 +- source/Plugins/JITLoader/GDB/JITLoaderGDB.h | 36 +- .../Language/CPlusPlus/CPlusPlusLanguage.cpp | 792 ++ .../Plugins/Language/CPlusPlus/CPlusPlusLanguage.h | 186 + .../Plugins/Language/CPlusPlus/CxxStringTypes.cpp | 204 + source/Plugins/Language/CPlusPlus/CxxStringTypes.h | 41 + source/Plugins/Language/CPlusPlus/LibCxx.cpp | 653 ++ source/Plugins/Language/CPlusPlus/LibCxx.h | 141 + .../Language/CPlusPlus/LibCxxInitializerList.cpp | 147 + source/Plugins/Language/CPlusPlus/LibCxxList.cpp | 414 + source/Plugins/Language/CPlusPlus/LibCxxMap.cpp | 478 ++ .../Language/CPlusPlus/LibCxxUnorderedMap.cpp | 172 + source/Plugins/Language/CPlusPlus/LibCxxVector.cpp | 159 + source/Plugins/Language/CPlusPlus/LibStdcpp.cpp | 373 + source/Plugins/Language/CPlusPlus/LibStdcpp.h | 33 + .../Plugins/Language/Go/GoFormatterFunctions.cpp | 173 + source/Plugins/Language/Go/GoFormatterFunctions.h | 43 + source/Plugins/Language/Go/GoLanguage.cpp | 146 + source/Plugins/Language/Go/GoLanguage.h | 66 + source/Plugins/Language/ObjC/CF.cpp | 334 + source/Plugins/Language/ObjC/CF.h | 34 + source/Plugins/Language/ObjC/Cocoa.cpp | 967 +++ source/Plugins/Language/ObjC/Cocoa.h | 97 + source/Plugins/Language/ObjC/CoreMedia.cpp | 89 + source/Plugins/Language/ObjC/CoreMedia.h | 26 + source/Plugins/Language/ObjC/NSArray.cpp | 792 ++ source/Plugins/Language/ObjC/NSDictionary.cpp | 749 ++ source/Plugins/Language/ObjC/NSDictionary.h | 48 + source/Plugins/Language/ObjC/NSError.cpp | 218 + source/Plugins/Language/ObjC/NSException.cpp | 219 + source/Plugins/Language/ObjC/NSIndexPath.cpp | 349 + source/Plugins/Language/ObjC/NSSet.cpp | 758 ++ source/Plugins/Language/ObjC/NSSet.h | 40 + source/Plugins/Language/ObjC/NSString.cpp | 405 + source/Plugins/Language/ObjC/NSString.h | 42 + source/Plugins/Language/ObjC/ObjCLanguage.cpp | 877 ++ source/Plugins/Language/ObjC/ObjCLanguage.h | 210 + .../Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp | 68 + .../Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h | 63 + .../ItaniumABI/ItaniumABILanguageRuntime.cpp | 49 +- .../ItaniumABI/ItaniumABILanguageRuntime.h | 83 +- .../LanguageRuntime/Go/GoLanguageRuntime.cpp | 238 + .../Plugins/LanguageRuntime/Go/GoLanguageRuntime.h | 93 + .../RenderScriptRuntime/RenderScriptRuntime.cpp | 3203 +++++++- .../RenderScriptRuntime/RenderScriptRuntime.h | 229 +- .../MemoryHistory/asan/MemoryHistoryASan.cpp | 108 +- .../Plugins/MemoryHistory/asan/MemoryHistoryASan.h | 34 +- .../BSD-Archive/ObjectContainerBSDArchive.cpp | 10 +- .../BSD-Archive/ObjectContainerBSDArchive.h | 65 +- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 508 +- source/Plugins/ObjectFile/ELF/ObjectFileELF.h | 19 +- source/Plugins/ObjectFile/JIT/ObjectFileJIT.h | 114 +- .../OperatingSystem/Go/OperatingSystemGo.cpp | 559 ++ .../Plugins/OperatingSystem/Go/OperatingSystemGo.h | 87 + .../Python/OperatingSystemPython.cpp | 5 +- .../OperatingSystem/Python/OperatingSystemPython.h | 60 +- source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h | 13 +- source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp | 685 ++ source/Plugins/Platform/NetBSD/PlatformNetBSD.h | 177 + source/Plugins/Platform/POSIX/PlatformPOSIX.cpp | 185 +- source/Plugins/Platform/POSIX/PlatformPOSIX.h | 60 +- .../gdb-server/PlatformRemoteGDBServer.cpp | 125 +- .../Platform/gdb-server/PlatformRemoteGDBServer.h | 33 +- source/Plugins/Process/FreeBSD/FreeBSDThread.cpp | 623 +- source/Plugins/Process/FreeBSD/FreeBSDThread.h | 109 +- source/Plugins/Process/FreeBSD/POSIXStopInfo.cpp | 2 +- source/Plugins/Process/FreeBSD/POSIXStopInfo.h | 8 +- source/Plugins/Process/FreeBSD/POSIXThread.cpp | 661 -- source/Plugins/Process/FreeBSD/POSIXThread.h | 132 - source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp | 829 +- source/Plugins/Process/FreeBSD/ProcessFreeBSD.h | 197 +- source/Plugins/Process/FreeBSD/ProcessMonitor.cpp | 6 +- source/Plugins/Process/FreeBSD/ProcessMonitor.h | 4 +- source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp | 939 --- source/Plugins/Process/FreeBSD/ProcessPOSIX.h | 205 - .../Plugins/Process/FreeBSD/RegisterContextPOSIX.h | 79 + .../RegisterContextPOSIXProcessMonitor_arm.cpp | 4 +- .../RegisterContextPOSIXProcessMonitor_arm.h | 1 + .../RegisterContextPOSIXProcessMonitor_arm64.cpp | 6 +- .../RegisterContextPOSIXProcessMonitor_arm64.h | 1 + .../RegisterContextPOSIXProcessMonitor_mips64.cpp | 4 +- .../RegisterContextPOSIXProcessMonitor_mips64.h | 1 + .../RegisterContextPOSIXProcessMonitor_powerpc.cpp | 4 +- .../RegisterContextPOSIXProcessMonitor_powerpc.h | 1 + .../RegisterContextPOSIXProcessMonitor_x86.cpp | 35 +- .../RegisterContextPOSIXProcessMonitor_x86.h | 2 + source/Plugins/Process/POSIX/CrashReason.cpp | 5 +- .../Process/Utility/DynamicRegisterInfo.cpp | 18 +- source/Plugins/Process/Utility/FreeBSDSignals.cpp | 132 +- source/Plugins/Process/Utility/HistoryThread.h | 47 +- source/Plugins/Process/Utility/HistoryUnwind.h | 20 +- .../Plugins/Process/Utility/InferiorCallPOSIX.cpp | 15 +- source/Plugins/Process/Utility/LinuxSignals.cpp | 134 +- .../Plugins/Process/Utility/MipsLinuxSignals.cpp | 134 +- source/Plugins/Process/Utility/NetBSDSignals.cpp | 34 + source/Plugins/Process/Utility/NetBSDSignals.h | 31 + .../Process/Utility/RegisterContextDarwin_arm.cpp | 184 +- .../Process/Utility/RegisterContextDarwin_arm.h | 76 +- .../Utility/RegisterContextDarwin_arm64.cpp | 114 +- .../Process/Utility/RegisterContextDarwin_arm64.h | 64 +- .../Process/Utility/RegisterContextDarwin_i386.cpp | 228 +- .../Process/Utility/RegisterContextDarwin_i386.h | 55 +- .../Utility/RegisterContextDarwin_x86_64.cpp | 406 +- .../Process/Utility/RegisterContextDarwin_x86_64.h | 52 +- .../Process/Utility/RegisterContextDummy.cpp | 4 +- .../Plugins/Process/Utility/RegisterContextDummy.h | 56 +- .../Process/Utility/RegisterContextFreeBSD_arm.cpp | 1 + .../Process/Utility/RegisterContextFreeBSD_arm.h | 1 - .../Process/Utility/RegisterContextFreeBSD_arm64.h | 2 +- .../Process/Utility/RegisterContextFreeBSD_i386.h | 2 +- .../Utility/RegisterContextFreeBSD_mips64.h | 2 +- .../Utility/RegisterContextFreeBSD_powerpc.h | 18 +- .../Utility/RegisterContextFreeBSD_x86_64.h | 2 +- .../Process/Utility/RegisterContextHistory.cpp | 4 +- .../Process/Utility/RegisterContextHistory.h | 55 +- .../Process/Utility/RegisterContextLLDB.cpp | 93 +- .../Plugins/Process/Utility/RegisterContextLLDB.h | 58 +- .../Process/Utility/RegisterContextLinux_arm.cpp | 1 + .../Process/Utility/RegisterContextLinux_arm.h | 1 - .../Process/Utility/RegisterContextLinux_arm64.cpp | 2 +- .../Process/Utility/RegisterContextLinux_arm64.h | 1 - .../Process/Utility/RegisterContextLinux_i386.cpp | 14 +- .../Process/Utility/RegisterContextLinux_i386.h | 8 +- .../Process/Utility/RegisterContextLinux_mips.cpp | 17 +- .../Process/Utility/RegisterContextLinux_mips.h | 5 +- .../Utility/RegisterContextLinux_mips64.cpp | 16 +- .../Process/Utility/RegisterContextLinux_mips64.h | 2 +- .../Utility/RegisterContextLinux_x86_64.cpp | 11 +- .../Process/Utility/RegisterContextLinux_x86_64.h | 7 +- .../Utility/RegisterContextMacOSXFrameBackchain.h | 57 +- .../Process/Utility/RegisterContextMemory.h | 61 +- .../Plugins/Process/Utility/RegisterContextPOSIX.h | 79 - .../Process/Utility/RegisterContextPOSIX_arm.cpp | 48 + .../Process/Utility/RegisterContextPOSIX_arm.h | 30 +- .../Process/Utility/RegisterContextPOSIX_arm64.h | 27 +- .../Process/Utility/RegisterContextPOSIX_mips64.h | 27 +- .../Process/Utility/RegisterContextPOSIX_powerpc.h | 29 +- .../Process/Utility/RegisterContextPOSIX_x86.h | 29 +- .../Process/Utility/RegisterContextThreadMemory.h | 104 +- .../Plugins/Process/Utility/RegisterContext_mips.h | 663 +- .../Process/Utility/RegisterContext_powerpc.h | 321 +- .../Plugins/Process/Utility/RegisterContext_x86.h | 411 +- .../Process/Utility/RegisterInfoInterface.h | 22 + source/Plugins/Process/Utility/RegisterInfos_arm.h | 334 +- .../Plugins/Process/Utility/RegisterInfos_arm64.h | 156 +- .../Plugins/Process/Utility/RegisterInfos_i386.h | 73 +- .../Plugins/Process/Utility/RegisterInfos_mips.h | 233 +- .../Plugins/Process/Utility/RegisterInfos_mips64.h | 319 +- .../Process/Utility/RegisterInfos_powerpc.h | 14 +- .../Plugins/Process/Utility/RegisterInfos_x86_64.h | 94 +- .../Process/Utility/StopInfoMachException.cpp | 4 + .../Process/Utility/StopInfoMachException.h | 16 +- source/Plugins/Process/Utility/ThreadMemory.h | 92 +- source/Plugins/Process/Utility/UnwindLLDB.cpp | 86 +- source/Plugins/Process/Utility/UnwindLLDB.h | 37 +- .../Process/Utility/UnwindMacOSXFrameBackchain.h | 28 +- .../Process/Utility/lldb-arm-register-enums.h | 50 +- source/Plugins/Process/elf-core/ProcessElfCore.cpp | 77 +- source/Plugins/Process/elf-core/ProcessElfCore.h | 32 +- .../elf-core/RegisterContextPOSIXCore_arm.cpp | 1 - .../elf-core/RegisterContextPOSIXCore_arm.h | 40 +- .../elf-core/RegisterContextPOSIXCore_arm64.cpp | 1 - .../elf-core/RegisterContextPOSIXCore_arm64.h | 40 +- .../elf-core/RegisterContextPOSIXCore_mips64.cpp | 1 - .../elf-core/RegisterContextPOSIXCore_mips64.h | 40 +- .../elf-core/RegisterContextPOSIXCore_powerpc.cpp | 1 - .../elf-core/RegisterContextPOSIXCore_powerpc.h | 42 +- .../elf-core/RegisterContextPOSIXCore_x86_64.cpp | 1 - .../elf-core/RegisterContextPOSIXCore_x86_64.h | 40 +- source/Plugins/Process/elf-core/ThreadElfCore.cpp | 5 +- source/Plugins/Process/elf-core/ThreadElfCore.h | 41 +- .../Process/gdb-remote/GDBRemoteCommunication.cpp | 232 +- .../Process/gdb-remote/GDBRemoteCommunication.h | 77 +- .../gdb-remote/GDBRemoteCommunicationClient.cpp | 287 +- .../gdb-remote/GDBRemoteCommunicationClient.h | 76 +- .../gdb-remote/GDBRemoteCommunicationServer.h | 8 +- .../GDBRemoteCommunicationServerCommon.cpp | 105 +- .../GDBRemoteCommunicationServerCommon.h | 17 +- .../GDBRemoteCommunicationServerLLGS.cpp | 600 +- .../gdb-remote/GDBRemoteCommunicationServerLLGS.h | 41 +- .../GDBRemoteCommunicationServerPlatform.cpp | 305 +- .../GDBRemoteCommunicationServerPlatform.h | 52 +- .../gdb-remote/GDBRemoteRegisterContext.cpp | 290 +- .../Process/gdb-remote/GDBRemoteRegisterContext.h | 22 +- .../Process/gdb-remote/ProcessGDBRemote.cpp | 1080 ++- .../Plugins/Process/gdb-remote/ProcessGDBRemote.h | 138 +- .../Plugins/Process/gdb-remote/ThreadGDBRemote.cpp | 8 + .../Plugins/Process/gdb-remote/ThreadGDBRemote.h | 32 +- .../None/ScriptInterpreterNone.cpp | 93 + .../ScriptInterpreter/None/ScriptInterpreterNone.h | 66 + .../ScriptInterpreter/Python/PythonDataObjects.cpp | 1069 +++ .../ScriptInterpreter/Python/PythonDataObjects.h | 498 ++ .../Python/PythonExceptionState.cpp | 201 + .../Python/PythonExceptionState.h | 70 + .../Python/ScriptInterpreterPython.cpp | 3172 ++++++++ .../Python/ScriptInterpreterPython.h | 607 ++ .../Plugins/ScriptInterpreter/Python/lldb-python.h | 31 + source/Plugins/SymbolFile/DWARF/DIERef.cpp | 56 + source/Plugins/SymbolFile/DWARF/DIERef.h | 42 + source/Plugins/SymbolFile/DWARF/DWARFASTParser.h | 65 + .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 4034 ++++++++++ .../Plugins/SymbolFile/DWARF/DWARFASTParserClang.h | 213 + .../Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp | 828 ++ source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h | 84 + source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp | 90 + source/Plugins/SymbolFile/DWARF/DWARFAttribute.h | 60 +- .../Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp | 459 +- source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h | 124 +- source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp | 543 ++ source/Plugins/SymbolFile/DWARF/DWARFDIE.h | 281 + .../SymbolFile/DWARF/DWARFDIECollection.cpp | 18 +- .../Plugins/SymbolFile/DWARF/DWARFDIECollection.h | 12 +- .../Plugins/SymbolFile/DWARF/DWARFDataExtractor.h | 5 +- source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp | 230 +- source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h | 35 +- .../SymbolFile/DWARF/DWARFDebugInfoEntry.cpp | 953 +-- .../Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h | 138 +- source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp | 95 +- source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h | 9 +- .../Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp | 128 + source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h | 68 + .../SymbolFile/DWARF/DWARFDebugPubnames.cpp | 60 +- .../Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp | 54 +- source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h | 16 +- source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h | 7 + source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp | 114 +- source/Plugins/SymbolFile/DWARF/DWARFFormValue.h | 40 +- .../SymbolFile/DWARF/DWARFLocationDescription.cpp | 172 - .../SymbolFile/DWARF/DWARFLocationDescription.h | 24 - .../Plugins/SymbolFile/DWARF/DWARFLocationList.cpp | 94 - .../Plugins/SymbolFile/DWARF/DWARFLocationList.h | 34 - .../Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp | 747 ++ source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h | 950 +-- source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h | 34 +- source/Plugins/SymbolFile/DWARF/NameToDIE.cpp | 34 +- source/Plugins/SymbolFile/DWARF/NameToDIE.h | 33 +- .../Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 8374 ++++++-------------- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h | 807 +- .../SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp | 212 +- .../SymbolFile/DWARF/SymbolFileDWARFDebugMap.h | 45 +- .../SymbolFile/DWARF/SymbolFileDWARFDwo.cpp | 131 + .../Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h | 70 + .../SymbolFile/DWARF/UniqueDWARFASTType.cpp | 49 +- .../Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h | 35 +- .../Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp | 83 +- .../Plugins/SymbolFile/Symtab/SymbolFileSymtab.h | 129 +- .../Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp | 8 +- source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h | 31 +- .../InstEmulation/UnwindAssemblyInstEmulation.cpp | 56 +- .../InstEmulation/UnwindAssemblyInstEmulation.h | 100 +- .../UnwindAssembly/x86/UnwindAssembly-x86.h | 51 +- 330 files changed, 67443 insertions(+), 20442 deletions(-) create mode 100644 source/Plugins/ExpressionParser/Clang/ASTDumper.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ASTDumper.h create mode 100644 source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h create mode 100644 source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ClangASTSource.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ClangUserExpression.h create mode 100644 source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h create mode 100644 source/Plugins/ExpressionParser/Clang/IRForTarget.cpp create mode 100644 source/Plugins/ExpressionParser/Clang/IRForTarget.h create mode 100644 source/Plugins/ExpressionParser/Go/GoAST.h create mode 100644 source/Plugins/ExpressionParser/Go/GoLexer.cpp create mode 100644 source/Plugins/ExpressionParser/Go/GoLexer.h create mode 100644 source/Plugins/ExpressionParser/Go/GoParser.cpp create mode 100644 source/Plugins/ExpressionParser/Go/GoParser.h create mode 100644 source/Plugins/ExpressionParser/Go/GoUserExpression.cpp create mode 100644 source/Plugins/ExpressionParser/Go/GoUserExpression.h create mode 100644 source/Plugins/ExpressionParser/Go/gen_go_ast.py create mode 100644 source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp create mode 100644 source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h create mode 100644 source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp create mode 100644 source/Plugins/Language/CPlusPlus/CxxStringTypes.h create mode 100644 source/Plugins/Language/CPlusPlus/LibCxx.cpp create mode 100644 source/Plugins/Language/CPlusPlus/LibCxx.h create mode 100644 source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp create mode 100644 source/Plugins/Language/CPlusPlus/LibCxxList.cpp create mode 100644 source/Plugins/Language/CPlusPlus/LibCxxMap.cpp create mode 100644 source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp create mode 100644 source/Plugins/Language/CPlusPlus/LibCxxVector.cpp create mode 100644 source/Plugins/Language/CPlusPlus/LibStdcpp.cpp create mode 100644 source/Plugins/Language/CPlusPlus/LibStdcpp.h create mode 100644 source/Plugins/Language/Go/GoFormatterFunctions.cpp create mode 100644 source/Plugins/Language/Go/GoFormatterFunctions.h create mode 100644 source/Plugins/Language/Go/GoLanguage.cpp create mode 100644 source/Plugins/Language/Go/GoLanguage.h create mode 100644 source/Plugins/Language/ObjC/CF.cpp create mode 100644 source/Plugins/Language/ObjC/CF.h create mode 100644 source/Plugins/Language/ObjC/Cocoa.cpp create mode 100644 source/Plugins/Language/ObjC/Cocoa.h create mode 100644 source/Plugins/Language/ObjC/CoreMedia.cpp create mode 100644 source/Plugins/Language/ObjC/CoreMedia.h create mode 100644 source/Plugins/Language/ObjC/NSArray.cpp create mode 100644 source/Plugins/Language/ObjC/NSDictionary.cpp create mode 100644 source/Plugins/Language/ObjC/NSDictionary.h create mode 100644 source/Plugins/Language/ObjC/NSError.cpp create mode 100644 source/Plugins/Language/ObjC/NSException.cpp create mode 100644 source/Plugins/Language/ObjC/NSIndexPath.cpp create mode 100644 source/Plugins/Language/ObjC/NSSet.cpp create mode 100644 source/Plugins/Language/ObjC/NSSet.h create mode 100644 source/Plugins/Language/ObjC/NSString.cpp create mode 100644 source/Plugins/Language/ObjC/NSString.h create mode 100644 source/Plugins/Language/ObjC/ObjCLanguage.cpp create mode 100644 source/Plugins/Language/ObjC/ObjCLanguage.h create mode 100644 source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp create mode 100644 source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h create mode 100644 source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp create mode 100644 source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h create mode 100644 source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp create mode 100644 source/Plugins/OperatingSystem/Go/OperatingSystemGo.h create mode 100644 source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp create mode 100644 source/Plugins/Platform/NetBSD/PlatformNetBSD.h delete mode 100644 source/Plugins/Process/FreeBSD/POSIXThread.cpp delete mode 100644 source/Plugins/Process/FreeBSD/POSIXThread.h delete mode 100644 source/Plugins/Process/FreeBSD/ProcessPOSIX.cpp delete mode 100644 source/Plugins/Process/FreeBSD/ProcessPOSIX.h create mode 100644 source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h create mode 100644 source/Plugins/Process/Utility/NetBSDSignals.cpp create mode 100644 source/Plugins/Process/Utility/NetBSDSignals.h delete mode 100644 source/Plugins/Process/Utility/RegisterContextPOSIX.h create mode 100644 source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp create mode 100644 source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h create mode 100644 source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp create mode 100644 source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h create mode 100644 source/Plugins/ScriptInterpreter/Python/PythonExceptionState.cpp create mode 100644 source/Plugins/ScriptInterpreter/Python/PythonExceptionState.h create mode 100644 source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp create mode 100644 source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h create mode 100644 source/Plugins/ScriptInterpreter/Python/lldb-python.h create mode 100644 source/Plugins/SymbolFile/DWARF/DIERef.cpp create mode 100644 source/Plugins/SymbolFile/DWARF/DIERef.h create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFASTParser.h create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDIE.h create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.h delete mode 100644 source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp delete mode 100644 source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h delete mode 100644 source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp delete mode 100644 source/Plugins/SymbolFile/DWARF/DWARFLocationList.h create mode 100644 source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp create mode 100644 source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp create mode 100644 source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h (limited to 'source/Plugins') diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp index 700d223fbc6da..3b9b0f3460729 100644 --- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp +++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp @@ -17,7 +17,6 @@ #include "lldb/Core/Scalar.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -28,7 +27,7 @@ #include "llvm/ADT/Triple.h" #include "Utility/ARM_DWARF_Registers.h" -#include "Utility/ARM_GCC_Registers.h" +#include "Utility/ARM_ehframe_Registers.h" #include "Plugins/Process/Utility/ARMDefines.h" #include @@ -38,90 +37,90 @@ using namespace lldb_private; static RegisterInfo g_register_infos[] = { - // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS + // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS // ========== ======= == === ============= ============ ======================= =================== =========================== ======================= ====================== ========== =============== - { "r0", "arg1", 4, 0, eEncodingUint , eFormatHex, { gcc_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, gdb_arm_r0, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r1", "arg2", 4, 0, eEncodingUint , eFormatHex, { gcc_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, gdb_arm_r1, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r2", "arg3", 4, 0, eEncodingUint , eFormatHex, { gcc_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, gdb_arm_r2, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r3", "arg4", 4, 0, eEncodingUint , eFormatHex, { gcc_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, gdb_arm_r3, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r4", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, gdb_arm_r4, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r5", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, gdb_arm_r5, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r6", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, gdb_arm_r6, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r7", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, gdb_arm_r7, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r8", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, gdb_arm_r8, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r9", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, gdb_arm_r9, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r10", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, gdb_arm_r10, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r11", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM, gdb_arm_r11, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r12", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, gdb_arm_r12, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "sp", "r13", 4, 0, eEncodingUint , eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, gdb_arm_sp, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "lr", "r14", 4, 0, eEncodingUint , eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_arm_lr, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "pc", "r15", 4, 0, eEncodingUint , eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_arm_pc, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, gdb_arm_cpsr, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, gdb_arm_s0, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, gdb_arm_s1, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, gdb_arm_s2, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, gdb_arm_s3, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, gdb_arm_s4, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, gdb_arm_s5, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, gdb_arm_s6, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, gdb_arm_s7, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, gdb_arm_s8, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, gdb_arm_s9, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, gdb_arm_s10, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, gdb_arm_s11, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, gdb_arm_s12, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, gdb_arm_s13, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, gdb_arm_s14, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, gdb_arm_s15, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, gdb_arm_s16, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, gdb_arm_s17, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, gdb_arm_s18, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, gdb_arm_s19, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, gdb_arm_s20, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, gdb_arm_s21, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, gdb_arm_s22, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, gdb_arm_s23, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, gdb_arm_s24, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, gdb_arm_s25, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, gdb_arm_s26, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, gdb_arm_s27, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, gdb_arm_s28, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, gdb_arm_s29, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, gdb_arm_s30, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, gdb_arm_s31, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fpscr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, gdb_arm_fpscr, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, gdb_arm_d0, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, gdb_arm_d1, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, gdb_arm_d2, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, gdb_arm_d3, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, gdb_arm_d4, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, gdb_arm_d5, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, gdb_arm_d6, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, gdb_arm_d7, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, gdb_arm_d8, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, gdb_arm_d9, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, gdb_arm_d10, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, gdb_arm_d11, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, gdb_arm_d12, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, gdb_arm_d13, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, gdb_arm_d14, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, gdb_arm_d15, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, gdb_arm_d16, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, gdb_arm_d17, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, gdb_arm_d18, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, gdb_arm_d19, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, gdb_arm_d20, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, gdb_arm_d21, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, gdb_arm_d22, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, gdb_arm_d23, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, gdb_arm_d24, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, gdb_arm_d25, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, gdb_arm_d26, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, gdb_arm_d27, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, gdb_arm_d28, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, gdb_arm_d29, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, gdb_arm_d30, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, gdb_arm_d31, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r0", "arg1", 4, 0, eEncodingUint , eFormatHex, { ehframe_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r1", "arg2", 4, 0, eEncodingUint , eFormatHex, { ehframe_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r2", "arg3", 4, 0, eEncodingUint , eFormatHex, { ehframe_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r3", "arg4", 4, 0, eEncodingUint , eFormatHex, { ehframe_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r4", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r5", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r6", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r7", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r8", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r9", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r10", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r11", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r12", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "sp", "r13", 4, 0, eEncodingUint , eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "lr", "r14", 4, 0, eEncodingUint , eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "pc", "r15", 4, 0, eEncodingUint , eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fpscr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, { "r8_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r8_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, { "r9_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r9_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, { "r10_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r10_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, @@ -239,8 +238,8 @@ ABIMacOSX_arm::PrepareTrivialCall (Thread &thread, size_t num_stack_regs = ae - ai; sp -= (num_stack_regs * 4); - // Keep the stack 8 byte aligned, not that we need to - sp &= ~(8ull-1ull); + // Keep the stack 16 byte aligned + sp &= ~(16ull-1ull); // just using arg1 to get the right size const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); @@ -333,18 +332,18 @@ ABIMacOSX_arm::GetArgumentValues (Thread &thread, if (!value) return false; - ClangASTType clang_type = value->GetClangType(); - if (clang_type) + CompilerType compiler_type = value->GetCompilerType(); + if (compiler_type) { bool is_signed = false; size_t bit_width = 0; - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { - bit_width = clang_type.GetBitSize(&thread); + bit_width = compiler_type.GetBitSize(&thread); } - else if (clang_type.IsPointerOrReferenceType ()) + else if (compiler_type.IsPointerOrReferenceType ()) { - bit_width = clang_type.GetBitSize(&thread); + bit_width = compiler_type.GetBitSize(&thread); } else { @@ -414,22 +413,37 @@ ABIMacOSX_arm::GetArgumentValues (Thread &thread, return true; } +bool +ABIMacOSX_arm::IsArmv7kProcess (Thread *thread) const +{ + bool is_armv7k = false; + if (thread) + { + ProcessSP process_sp (thread->GetProcess()); + if (process_sp) + { + const ArchSpec &arch (process_sp->GetTarget().GetArchitecture()); + const ArchSpec::Core system_core = arch.GetCore(); + if (system_core == ArchSpec::eCore_arm_armv7k) + { + is_armv7k = true; + } + } + } + return is_armv7k; +} + ValueObjectSP ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread, - lldb_private::ClangASTType &clang_type) const + lldb_private::CompilerType &compiler_type) const { Value value; ValueObjectSP return_valobj_sp; - if (!clang_type) - return return_valobj_sp; - - clang::ASTContext *ast_context = clang_type.GetASTContext(); - if (!ast_context) + if (!compiler_type) return return_valobj_sp; - //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType()); - value.SetClangType (clang_type); + value.SetCompilerType (compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) @@ -441,14 +455,68 @@ ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread, // when reading data const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfoByName("r0", 0); - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { - size_t bit_width = clang_type.GetBitSize(&thread); + size_t bit_width = compiler_type.GetBitSize(&thread); switch (bit_width) { default: return return_valobj_sp; + case 128: + if (IsArmv7kProcess (&thread)) + { + // "A composite type not larger than 16 bytes is returned in r0-r3. The format is + // as if the result had been stored in memory at a word-aligned address and then + // loaded into r0-r3 with an ldm instruction" + { + const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfoByName("r1", 0); + const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0); + const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); + if (r1_reg_info && r2_reg_info && r3_reg_info) + { + const size_t byte_size = compiler_type.GetByteSize(&thread); + ProcessSP process_sp (thread.GetProcess()); + if (byte_size <= r0_reg_info->byte_size + r1_reg_info->byte_size + r2_reg_info->byte_size + r3_reg_info->byte_size + && process_sp) + { + std::unique_ptr heap_data_ap (new DataBufferHeap(byte_size, 0)); + const ByteOrder byte_order = process_sp->GetByteOrder(); + RegisterValue r0_reg_value; + RegisterValue r1_reg_value; + RegisterValue r2_reg_value; + RegisterValue r3_reg_value; + if (reg_ctx->ReadRegister(r0_reg_info, r0_reg_value) + && reg_ctx->ReadRegister(r1_reg_info, r1_reg_value) + && reg_ctx->ReadRegister(r2_reg_info, r2_reg_value) + && reg_ctx->ReadRegister(r3_reg_info, r3_reg_value)) + { + Error error; + if (r0_reg_value.GetAsMemoryData (r0_reg_info, heap_data_ap->GetBytes()+0, 4, byte_order, error) + && r1_reg_value.GetAsMemoryData (r1_reg_info, heap_data_ap->GetBytes()+4, 4, byte_order, error) + && r2_reg_value.GetAsMemoryData (r2_reg_info, heap_data_ap->GetBytes()+8, 4, byte_order, error) + && r3_reg_value.GetAsMemoryData (r3_reg_info, heap_data_ap->GetBytes()+12, 4, byte_order, error)) + { + DataExtractor data (DataBufferSP (heap_data_ap.release()), + byte_order, + process_sp->GetAddressByteSize()); + + return_valobj_sp = ValueObjectConstResult::Create (&thread, + compiler_type, + ConstString(""), + data); + return return_valobj_sp; + } + } + } + } + } + } + else + { + return return_valobj_sp; + } + break; case 64: { const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfoByName("r1", 0); @@ -481,7 +549,7 @@ ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread, break; } } - else if (clang_type.IsPointerType ()) + else if (compiler_type.IsPointerType ()) { uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; value.GetScalar() = ptr; @@ -510,8 +578,8 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj return error; } - ClangASTType clang_type = new_value_sp->GetClangType(); - if (!clang_type) + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { error.SetErrorString ("Null clang type for return value."); return error; @@ -526,7 +594,7 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) + if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) { DataExtractor data; Error data_error; @@ -561,12 +629,45 @@ ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj } } } + else if (num_bytes <= 16 && IsArmv7kProcess (frame_sp->GetThread().get())) + { + // "A composite type not larger than 16 bytes is returned in r0-r3. The format is + // as if the result had been stored in memory at a word-aligned address and then + // loaded into r0-r3 with an ldm instruction" + + const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("r0", 0); + const RegisterInfo *r1_info = reg_ctx->GetRegisterInfoByName("r1", 0); + const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0); + const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0); + lldb::offset_t offset = 0; + uint32_t bytes_written = 4; + uint32_t raw_value = data.GetMaxU64(&offset, 4); + if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value) && bytes_written <= num_bytes) + { + bytes_written += 4; + raw_value = data.GetMaxU64(&offset, 4); + if (bytes_written <= num_bytes && reg_ctx->WriteRegisterFromUnsigned (r1_info, raw_value)) + { + bytes_written += 4; + raw_value = data.GetMaxU64(&offset, 4); + if (bytes_written <= num_bytes && reg_ctx->WriteRegisterFromUnsigned (r2_info, raw_value)) + { + bytes_written += 4; + raw_value = data.GetMaxU64(&offset, 4); + if (bytes_written <= num_bytes && reg_ctx->WriteRegisterFromUnsigned (r3_info, raw_value)) + { + set_it_simple = true; + } + } + } + } + } else { error.SetErrorString("We don't support returning longer than 64 bit integer values at present."); } } - else if (clang_type.IsFloatingPointType (count, is_complex)) + else if (compiler_type.IsFloatingPointType (count, is_complex)) { if (is_complex) error.SetErrorString ("We don't support returning complex values at present"); diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h index eee43943d73ac..a4e9dead77946 100644 --- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h +++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h @@ -20,42 +20,36 @@ class ABIMacOSX_arm : public lldb_private::ABI { public: - ~ABIMacOSX_arm() { } + ~ABIMacOSX_arm() override = default; - virtual size_t - GetRedZoneSize () const; + size_t + GetRedZoneSize() const override; - virtual bool - PrepareTrivialCall (lldb_private::Thread &thread, - lldb::addr_t sp, - lldb::addr_t func_addr, - lldb::addr_t returnAddress, - llvm::ArrayRef args) const; + bool + PrepareTrivialCall(lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t func_addr, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const override; - virtual bool - GetArgumentValues (lldb_private::Thread &thread, - lldb_private::ValueList &values) const; + bool + GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; - virtual lldb_private::Error - SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); + lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: - virtual lldb::ValueObjectSP - GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const; - -public: - virtual bool - CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); + bool + RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; - virtual bool - CallFrameAddressIsValid (lldb::addr_t cfa) + bool + CallFrameAddressIsValid(lldb::addr_t cfa) override { // Make sure the stack call frame addresses are are 4 byte aligned if (cfa & (4ull - 1ull)) @@ -65,8 +59,8 @@ public: return true; } - virtual bool - CodeAddressIsValid (lldb::addr_t pc) + bool + CodeAddressIsValid(lldb::addr_t pc) override { // Just make sure the address is a valid 32 bit address. Bit zero // might be set due to Thumb function calls, so don't enforce 2 byte @@ -74,20 +68,24 @@ public: return pc <= UINT32_MAX; } - virtual lldb::addr_t - FixCodeAddress (lldb::addr_t pc) + lldb::addr_t + FixCodeAddress(lldb::addr_t pc) override { // ARM uses bit zero to signify a code address is thumb, so we must // strip bit zero in any code addresses. return pc & ~(lldb::addr_t)1; } - virtual const lldb_private::RegisterInfo * - GetRegisterInfoArray (uint32_t &count); + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; + + bool + IsArmv7kProcess (lldb_private::Thread *thread) const; //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -103,13 +101,18 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); + + lldb_private::ConstString + GetPluginName() override; - virtual uint32_t - GetPluginVersion(); + uint32_t + GetPluginVersion() override; protected: + lldb::ValueObjectSP + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const override; + private: ABIMacOSX_arm() : lldb_private::ABI() @@ -118,4 +121,4 @@ private: } }; -#endif // liblldb_ABIMacOSX_arm_h_ +#endif // liblldb_ABIMacOSX_arm_h_ diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp index 04b96180deb37..0e6f9d663ae8e 100644 --- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp +++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp @@ -19,7 +19,6 @@ #include "lldb/Core/Value.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -37,12 +36,11 @@ using namespace lldb; using namespace lldb_private; static const char *pluginDesc = "Mac OS X ABI for arm64 targets"; -static const char *pluginShort = "abi.macosx-arm64"; static RegisterInfo g_register_infos[] = { - // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE + // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE // ========== ======= == === ============= =================== =================== ====================== =========================== ======================= ====================== { "x0", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, { "x1", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, @@ -77,7 +75,7 @@ static RegisterInfo g_register_infos[] = { "lr", "x30", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x30, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, { "sp", "x31", 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x31, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, { "pc", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, { "v0", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, { "v1", NULL, 16, 0, eEncodingVector , eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, arm64_dwarf::v1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, @@ -115,71 +113,71 @@ static RegisterInfo g_register_infos[] = { "fpsr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, { "fpcr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - - { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, - { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL } + { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + + { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, + { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL } }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -322,7 +320,7 @@ ABIMacOSX_arm64::GetArgumentValues (Thread &thread, ValueList &values) const if (!value) return false; - ClangASTType value_type = value->GetClangType(); + CompilerType value_type = value->GetCompilerType(); if (value_type) { bool is_signed = false; @@ -424,7 +422,7 @@ ABIMacOSX_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueO return error; } - ClangASTType return_value_type = new_value_sp->GetClangType(); + CompilerType return_value_type = new_value_sp->GetCompilerType(); if (!return_value_type) { error.SetErrorString ("Null clang type for return value."); @@ -709,7 +707,7 @@ ABIMacOSX_arm64::RegisterIsVolatile (const RegisterInfo *reg_info) static bool LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, RegisterContext *reg_ctx, - const ClangASTType &value_type, + const CompilerType &value_type, bool is_return_value, // false => parameter, true => return value uint32_t &NGRN, // NGRN (see ABI documentation) uint32_t &NSRN, // NSRN (see ABI documentation) @@ -724,18 +722,16 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder(); Error error; - ClangASTType base_type; + CompilerType base_type; const uint32_t homogeneous_count = value_type.IsHomogeneousAggregate (&base_type); if (homogeneous_count > 0 && homogeneous_count <= 8) { - printf ("ClangASTContext::IsHomogeneousAggregate() => %u\n", homogeneous_count); // Make sure we have enough registers if (NSRN < 8 && (8-NSRN) >= homogeneous_count) { if (!base_type) return false; const size_t base_byte_size = base_type.GetByteSize(nullptr); - printf ("ClangASTContext::IsHomogeneousAggregate() => base_byte_size = %" PRIu64 "\n", (uint64_t) base_byte_size); uint32_t data_offset = 0; for (uint32_t i=0; i args) const; + bool + PrepareTrivialCall(lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const override; - virtual bool - GetArgumentValues (lldb_private::Thread &thread, - lldb_private::ValueList &values) const; + bool + GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; - virtual bool - CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); + bool + RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; // The arm64 ABI requires that stack frames be 16 byte aligned. // When there is a trap handler on the stack, e.g. _sigtramp in userland @@ -57,9 +57,8 @@ public: // Whitelisting the trap handlers for user space would be easy (_sigtramp) but // in other environments there can be a large number of different functions // involved in async traps. - - virtual bool - CallFrameAddressIsValid (lldb::addr_t cfa) + bool + CallFrameAddressIsValid(lldb::addr_t cfa) override { // Make sure the stack call frame addresses are are 8 byte aligned if (cfa & (8ull - 1ull)) @@ -69,8 +68,8 @@ public: return true; } - virtual bool - CodeAddressIsValid (lldb::addr_t pc) + bool + CodeAddressIsValid(lldb::addr_t pc) override { if (pc & (4ull - 1ull)) return false; // Not 4 byte aligned @@ -79,12 +78,13 @@ public: return true; } - virtual const lldb_private::RegisterInfo * - GetRegisterInfoArray (uint32_t &count); + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -97,28 +97,26 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + static lldb_private::ConstString GetPluginNameStatic(); - virtual lldb_private::ConstString - GetPluginName() + lldb_private::ConstString + GetPluginName() override { return GetPluginNameStatic(); } - virtual const char * - GetShortPluginName(); - - virtual uint32_t - GetPluginVersion(); + uint32_t + GetPluginVersion() override; - virtual lldb_private::Error - SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); + lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; protected: - virtual lldb::ValueObjectSP + lldb::ValueObjectSP GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const; + lldb_private::CompilerType &ast_type) const override; private: ABIMacOSX_arm64() : @@ -128,4 +126,4 @@ private: } }; -#endif // liblldb_ABI_h_ +#endif // liblldb_ABIMacOSX_arm64_h_ diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp index 4204d18769b89..75e5fb1558e62 100644 --- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp +++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp @@ -16,13 +16,13 @@ #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" #include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Triple.h" #include @@ -32,16 +32,16 @@ using namespace lldb_private; enum { - gcc_eax = 0, - gcc_ecx, - gcc_edx, - gcc_ebx, - gcc_ebp, - gcc_esp, - gcc_esi, - gcc_edi, - gcc_eip, - gcc_eflags + ehframe_eax = 0, + ehframe_ecx, + ehframe_edx, + ehframe_ebx, + ehframe_ebp, // Different from DWARF the regnums - eh_frame esp/ebp had their regnums switched on i386 darwin + ehframe_esp, // Different from DWARF the regnums - eh_frame esp/ebp had their regnums switched on i386 darwin + ehframe_esi, + ehframe_edi, + ehframe_eip, + ehframe_eflags }; enum @@ -82,121 +82,60 @@ enum dwarf_ymm7 = dwarf_xmm7 }; -enum -{ - gdb_eax = 0, - gdb_ecx = 1, - gdb_edx = 2, - gdb_ebx = 3, - gdb_esp = 4, - gdb_ebp = 5, - gdb_esi = 6, - gdb_edi = 7, - gdb_eip = 8, - gdb_eflags = 9, - gdb_cs = 10, - gdb_ss = 11, - gdb_ds = 12, - gdb_es = 13, - gdb_fs = 14, - gdb_gs = 15, - gdb_stmm0 = 16, - gdb_stmm1 = 17, - gdb_stmm2 = 18, - gdb_stmm3 = 19, - gdb_stmm4 = 20, - gdb_stmm5 = 21, - gdb_stmm6 = 22, - gdb_stmm7 = 23, - gdb_fctrl = 24, gdb_fcw = gdb_fctrl, - gdb_fstat = 25, gdb_fsw = gdb_fstat, - gdb_ftag = 26, gdb_ftw = gdb_ftag, - gdb_fiseg = 27, gdb_fpu_cs = gdb_fiseg, - gdb_fioff = 28, gdb_ip = gdb_fioff, - gdb_foseg = 29, gdb_fpu_ds = gdb_foseg, - gdb_fooff = 30, gdb_dp = gdb_fooff, - gdb_fop = 31, - gdb_xmm0 = 32, - gdb_xmm1 = 33, - gdb_xmm2 = 34, - gdb_xmm3 = 35, - gdb_xmm4 = 36, - gdb_xmm5 = 37, - gdb_xmm6 = 38, - gdb_xmm7 = 39, - gdb_mxcsr = 40, - gdb_mm0 = 41, - gdb_mm1 = 42, - gdb_mm2 = 43, - gdb_mm3 = 44, - gdb_mm4 = 45, - gdb_mm5 = 46, - gdb_mm6 = 47, - gdb_mm7 = 48, - gdb_ymm0 = gdb_xmm0, - gdb_ymm1 = gdb_xmm1, - gdb_ymm2 = gdb_xmm2, - gdb_ymm3 = gdb_xmm3, - gdb_ymm4 = gdb_xmm4, - gdb_ymm5 = gdb_xmm5, - gdb_ymm6 = gdb_xmm6, - gdb_ymm7 = gdb_xmm7 -}; - static RegisterInfo g_register_infos[] = { - // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS + // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS // ====== ======= == === ============= ============ ===================== ===================== ============================ ==================== ====================== ========== =============== - { "eax", NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_eax , dwarf_eax , LLDB_INVALID_REGNUM , gdb_eax , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ebx" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , gdb_ebx , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ecx" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_ecx , dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , gdb_ecx , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "edx" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_edx , dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , gdb_edx , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "esi" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_esi , dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , gdb_esi , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "edi" , NULL, 4, 0, eEncodingUint , eFormatHex , { gcc_edi , dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , gdb_edi , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { gcc_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , gdb_ebp , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { gcc_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , gdb_esp , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { gcc_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , gdb_eip , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "eflags", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "cs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_cs , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ss" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ss , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ds" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ds , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "es" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_es , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fs , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "gs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gs , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm0" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm0 , LLDB_INVALID_REGNUM , gdb_stmm0 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm1" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm1 , LLDB_INVALID_REGNUM , gdb_stmm1 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm2" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm2 , LLDB_INVALID_REGNUM , gdb_stmm2 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm3" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm3 , LLDB_INVALID_REGNUM , gdb_stmm3 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm4" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm4 , LLDB_INVALID_REGNUM , gdb_stmm4 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm5" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm5 , LLDB_INVALID_REGNUM , gdb_stmm5 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm6" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm6 , LLDB_INVALID_REGNUM , gdb_stmm6 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm7" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm7 , LLDB_INVALID_REGNUM , gdb_stmm7 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fctrl" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fctrl , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fstat" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fstat , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ftag" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ftag , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fiseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fiseg , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fioff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fioff , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "foseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_foseg , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fooff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fooff , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fop" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fop , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm0" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm0 , LLDB_INVALID_REGNUM , gdb_xmm0 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm1" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm1 , LLDB_INVALID_REGNUM , gdb_xmm1 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm2" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm2 , LLDB_INVALID_REGNUM , gdb_xmm2 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm3" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm3 , LLDB_INVALID_REGNUM , gdb_xmm3 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm4" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm4 , LLDB_INVALID_REGNUM , gdb_xmm4 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm5" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm5 , LLDB_INVALID_REGNUM , gdb_xmm5 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm6" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm6 , LLDB_INVALID_REGNUM , gdb_xmm6 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm7" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm7 , LLDB_INVALID_REGNUM , gdb_xmm7 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "mxcsr" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_mxcsr , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm0" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm0 , LLDB_INVALID_REGNUM , gdb_ymm0 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm1" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm1 , LLDB_INVALID_REGNUM , gdb_ymm1 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm2" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm2 , LLDB_INVALID_REGNUM , gdb_ymm2 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm3" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm3 , LLDB_INVALID_REGNUM , gdb_ymm3 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm4" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm4 , LLDB_INVALID_REGNUM , gdb_ymm4 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm5" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm5 , LLDB_INVALID_REGNUM , gdb_ymm5 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm6" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm6 , LLDB_INVALID_REGNUM , gdb_ymm6 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm7" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7 , LLDB_INVALID_REGNUM , gdb_ymm7 , LLDB_INVALID_REGNUM }, NULL, NULL} + { "eax", NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_eax , dwarf_eax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ebx" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ecx" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_ecx , dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "edx" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_edx , dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "esi" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_esi , dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "edi" , NULL, 4, 0, eEncodingUint , eFormatHex , { ehframe_edi , dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { ehframe_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { ehframe_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { ehframe_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "eflags", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "cs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ss" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ds" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "es" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "gs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm0" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm1" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm2" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm3" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm4" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm5" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm6" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm7" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fctrl" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fstat" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ftag" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fiseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fioff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "foseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fooff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fop" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm0" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm1" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm2" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm3" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm4" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm5" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm6" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm7" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "mxcsr" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm0" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm1" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm2" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm3" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm4" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm5" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm6" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm7" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL} }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -237,7 +176,7 @@ ABIMacOSX_i386::CreateInstance (const ArchSpec &arch) { static ABISP g_abi_sp; if ((arch.GetTriple().getArch() == llvm::Triple::x86) && - (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS())) + (arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS() || arch.GetTriple().isWatchOS())) { if (!g_abi_sp) g_abi_sp.reset (new ABIMacOSX_i386); @@ -316,184 +255,6 @@ ABIMacOSX_i386::PrepareTrivialCall (Thread &thread, return true; } -bool -ABIMacOSX_i386::PrepareNormalCall (Thread &thread, - addr_t sp, - addr_t func_addr, - addr_t return_addr, - ValueList &args) const -{ - ExecutionContext exe_ctx (thread.shared_from_this()); - RegisterContext *reg_ctx = thread.GetRegisterContext().get(); - if (!reg_ctx) - return false; - - Process *process = exe_ctx.GetProcessPtr(); - Error error; - uint32_t fp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP); - uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); - uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); - - // Do the argument layout - - std::vector argLayout; // 4-byte chunks, as discussed in the ABI Function Call Guide - - size_t numArgs = args.GetSize(); - size_t index; - - for (index = 0; index < numArgs; ++index) - { - Value *val = args.GetValueAtIndex(index); - - if (!val) - return false; - - switch (val->GetValueType()) - { - case Value::eValueTypeScalar: - { - Scalar &scalar = val->GetScalar(); - switch (scalar.GetType()) - { - case Scalar::e_void: - return false; - case Scalar::e_sint: - case Scalar::e_uint: - case Scalar::e_slong: - case Scalar::e_ulong: - case Scalar::e_slonglong: - case Scalar::e_ulonglong: - { - uint64_t data = scalar.ULongLong(); - - switch (scalar.GetByteSize()) - { - default: - return false; - case 1: - argLayout.push_back((uint32_t)(data & 0xffull)); - break; - case 2: - argLayout.push_back((uint32_t)(data & 0xffffull)); - break; - case 4: - argLayout.push_back((uint32_t)(data & 0xffffffffull)); - break; - case 8: - argLayout.push_back((uint32_t)(data & 0xffffffffull)); - argLayout.push_back((uint32_t)(data >> 32)); - break; - } - } - break; - case Scalar::e_float: - { - float data = scalar.Float(); - uint32_t dataRaw = *((uint32_t*)(&data)); - argLayout.push_back(dataRaw); - } - break; - case Scalar::e_double: - { - double data = scalar.Double(); - uint32_t *dataRaw = ((uint32_t*)(&data)); - argLayout.push_back(dataRaw[0]); - argLayout.push_back(dataRaw[1]); - } - break; - case Scalar::e_long_double: - { - long double data = scalar.Double(); - uint32_t *dataRaw = ((uint32_t*)(&data)); - while ((argLayout.size() * 4) & 0xf) - argLayout.push_back(0); - argLayout.push_back(dataRaw[0]); - argLayout.push_back(dataRaw[1]); - argLayout.push_back(dataRaw[2]); - argLayout.push_back(dataRaw[3]); - } - break; - } - } - break; - case Value::eValueTypeHostAddress: - { - ClangASTType clang_type (val->GetClangType()); - if (clang_type) - { - uint32_t cstr_length = 0; - if (clang_type.IsCStringType (cstr_length)) - { - const char *cstr = (const char*)val->GetScalar().ULongLong(); - cstr_length = strlen(cstr); - - // Push the string onto the stack immediately. - - sp -= (cstr_length + 1); - - if (process->WriteMemory(sp, cstr, cstr_length + 1, error) != (cstr_length + 1)) - return false; - - // Put the address of the string into the argument array. - - argLayout.push_back((uint32_t)(sp & 0xffffffff)); - } - else - { - return false; - } - } - break; - } - break; - case Value::eValueTypeFileAddress: - case Value::eValueTypeLoadAddress: - default: - return false; - } - } - - // Make room for the arguments on the stack - - sp -= 4 * argLayout.size(); - - // Align the SP - - sp &= ~(16ull-1ull); // 16-byte alignment - - // Write the arguments on the stack - - size_t numChunks = argLayout.size(); - - for (index = 0; index < numChunks; ++index) - if (process->WriteMemory(sp + (index * 4), &argLayout[index], sizeof(uint32_t), error) != sizeof(uint32_t)) - return false; - - // The return address is pushed onto the stack. - - sp -= 4; - uint32_t returnAddressU32 = return_addr; - if (process->WriteMemory (sp, &returnAddressU32, sizeof(returnAddressU32), error) != sizeof(returnAddressU32)) - return false; - - // %esp is set to the actual stack value. - - if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp)) - return false; - - // %ebp is set to a fake value, in our case 0x0x00000000 - - if (!reg_ctx->WriteRegisterFromUnsigned(fp_reg_num, 0x00000000)) - return false; - - // %eip is set to the address of the called function. - - if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr)) - return false; - - return true; -} - static bool ReadIntegerArgument (Scalar &scalar, unsigned int bit_width, @@ -545,23 +306,23 @@ ABIMacOSX_i386::GetArgumentValues (Thread &thread, // We currently only support extracting values with Clang QualTypes. // Do we care about others? - ClangASTType clang_type (value->GetClangType()); - if (clang_type) + CompilerType compiler_type (value->GetCompilerType()); + if (compiler_type) { bool is_signed; - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), is_signed, thread.GetProcess().get(), current_stack_argument); } - else if (clang_type.IsPointerType()) + else if (compiler_type.IsPointerType()) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), false, thread.GetProcess().get(), current_stack_argument); @@ -582,8 +343,8 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb return error; } - ClangASTType clang_type = new_value_sp->GetClangType(); - if (!clang_type) + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { error.SetErrorString ("Null clang type for return value."); return error; @@ -598,7 +359,7 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) + if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) { DataExtractor data; Error data_error; @@ -638,7 +399,7 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb error.SetErrorString("We don't support returning longer than 64 bit integer values at present."); } } - else if (clang_type.IsFloatingPointType (count, is_complex)) + else if (compiler_type.IsFloatingPointType (count, is_complex)) { if (is_complex) error.SetErrorString ("We don't support returning complex values at present"); @@ -654,16 +415,16 @@ ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb ValueObjectSP ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread, - ClangASTType &clang_type) const + CompilerType &compiler_type) const { Value value; ValueObjectSP return_valobj_sp; - if (!clang_type) + if (!compiler_type) return return_valobj_sp; - //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType()); - value.SetClangType (clang_type); + //value.SetContext (Value::eContextTypeClangType, compiler_type.GetOpaqueQualType()); + value.SetCompilerType (compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) @@ -671,9 +432,9 @@ ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread, bool is_signed; - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { - size_t bit_width = clang_type.GetBitSize(&thread); + size_t bit_width = compiler_type.GetBitSize(&thread); unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB]; @@ -713,7 +474,7 @@ ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread, break; } } - else if (clang_type.IsPointerType ()) + else if (compiler_type.IsPointerType ()) { unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff; diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h index d81b7a7e684b0..6a82fce35bf76 100644 --- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h +++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h @@ -22,48 +22,33 @@ class ABIMacOSX_i386 : public lldb_private::ABI { public: - - ~ABIMacOSX_i386() { } - - virtual size_t - GetRedZoneSize () const; + ~ABIMacOSX_i386() override = default; - virtual bool - PrepareTrivialCall (lldb_private::Thread &thread, - lldb::addr_t sp, - lldb::addr_t func_addr, - lldb::addr_t return_addr, - llvm::ArrayRef args) const; + size_t + GetRedZoneSize() const override; - virtual bool - PrepareNormalCall (lldb_private::Thread &thread, + bool + PrepareTrivialCall(lldb_private::Thread &thread, lldb::addr_t sp, lldb::addr_t func_addr, lldb::addr_t return_addr, - lldb_private::ValueList &args) const; + llvm::ArrayRef args) const override; - virtual bool - GetArgumentValues (lldb_private::Thread &thread, - lldb_private::ValueList &values) const; + bool + GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; - virtual lldb_private::Error - SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); + lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: - virtual lldb::ValueObjectSP - GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const; - -public: - - virtual bool - CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); + bool + RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; // The Darwin i386 ABI requires that stack frames be 16 byte aligned. // When there is a trap handler on the stack, e.g. _sigtramp in userland @@ -78,8 +63,8 @@ public: // // If we were to enforce 16-byte alignment, we also need to relax to 4-byte // alignment for non-darwin i386 targets. - virtual bool - CallFrameAddressIsValid (lldb::addr_t cfa) + bool + CallFrameAddressIsValid(lldb::addr_t cfa) override { // Make sure the stack call frame addresses are are 4 byte aligned if (cfa & (4ull - 1ull)) @@ -89,19 +74,20 @@ public: return true; } - virtual bool - CodeAddressIsValid (lldb::addr_t pc) + bool + CodeAddressIsValid(lldb::addr_t pc) override { // Just make sure the address is a valid 32 bit address. return pc <= UINT32_MAX; } - virtual const lldb_private::RegisterInfo * - GetRegisterInfoArray (uint32_t &count); + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -114,22 +100,30 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + static lldb_private::ConstString GetPluginNameStatic (); - virtual lldb_private::ConstString - GetPluginName(); + lldb_private::ConstString + GetPluginName() override; - virtual uint32_t - GetPluginVersion(); + uint32_t + GetPluginVersion() override; protected: + lldb::ValueObjectSP + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const override; + bool RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); private: - ABIMacOSX_i386() : lldb_private::ABI() { } // Call CreateInstance instead. + ABIMacOSX_i386() : + lldb_private::ABI() + { + // Call CreateInstance instead. + } }; - -#endif // liblldb_ABI_h_ +#endif // liblldb_ABIMacOSX_i386_h_ diff --git a/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp index 50a9863d83e74..ef625dece2656 100644 --- a/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp +++ b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp @@ -17,7 +17,6 @@ #include "lldb/Core/Scalar.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -28,7 +27,7 @@ #include "llvm/ADT/Triple.h" #include "Utility/ARM_DWARF_Registers.h" -#include "Utility/ARM_GCC_Registers.h" +#include "Utility/ARM_ehframe_Registers.h" #include "Plugins/Process/Utility/ARMDefines.h" #include @@ -38,90 +37,90 @@ using namespace lldb_private; static RegisterInfo g_register_infos[] = { - // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS + // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS // ========== ======= == === ============= ============ ======================= =================== =========================== ======================= ====================== ========== =============== - { "r0", "arg1", 4, 0, eEncodingUint , eFormatHex, { gcc_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, gdb_arm_r0, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r1", "arg2", 4, 0, eEncodingUint , eFormatHex, { gcc_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, gdb_arm_r1, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r2", "arg3", 4, 0, eEncodingUint , eFormatHex, { gcc_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, gdb_arm_r2, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r3", "arg4", 4, 0, eEncodingUint , eFormatHex, { gcc_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, gdb_arm_r3, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r4", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, gdb_arm_r4, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r5", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, gdb_arm_r5, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r6", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, gdb_arm_r6, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r7", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, gdb_arm_r7, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r8", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, gdb_arm_r8, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r9", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, gdb_arm_r9, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r10", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, gdb_arm_r10, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r11", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM, gdb_arm_r11, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r12", NULL, 4, 0, eEncodingUint , eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, gdb_arm_r12, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "sp", "r13", 4, 0, eEncodingUint , eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, gdb_arm_sp, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "lr", "r14", 4, 0, eEncodingUint , eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_arm_lr, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "pc", "r15", 4, 0, eEncodingUint , eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_arm_pc, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, gdb_arm_cpsr, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, gdb_arm_s0, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, gdb_arm_s1, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, gdb_arm_s2, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, gdb_arm_s3, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, gdb_arm_s4, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, gdb_arm_s5, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, gdb_arm_s6, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, gdb_arm_s7, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, gdb_arm_s8, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, gdb_arm_s9, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, gdb_arm_s10, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, gdb_arm_s11, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, gdb_arm_s12, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, gdb_arm_s13, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, gdb_arm_s14, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, gdb_arm_s15, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, gdb_arm_s16, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, gdb_arm_s17, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, gdb_arm_s18, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, gdb_arm_s19, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, gdb_arm_s20, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, gdb_arm_s21, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, gdb_arm_s22, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, gdb_arm_s23, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, gdb_arm_s24, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, gdb_arm_s25, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, gdb_arm_s26, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, gdb_arm_s27, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, gdb_arm_s28, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, gdb_arm_s29, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, gdb_arm_s30, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, gdb_arm_s31, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fpscr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, gdb_arm_fpscr, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, gdb_arm_d0, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, gdb_arm_d1, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, gdb_arm_d2, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, gdb_arm_d3, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, gdb_arm_d4, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, gdb_arm_d5, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, gdb_arm_d6, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, gdb_arm_d7, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, gdb_arm_d8, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, gdb_arm_d9, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, gdb_arm_d10, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, gdb_arm_d11, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, gdb_arm_d12, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, gdb_arm_d13, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, gdb_arm_d14, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, gdb_arm_d15, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, gdb_arm_d16, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, gdb_arm_d17, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, gdb_arm_d18, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, gdb_arm_d19, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, gdb_arm_d20, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, gdb_arm_d21, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, gdb_arm_d22, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, gdb_arm_d23, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, gdb_arm_d24, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, gdb_arm_d25, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, gdb_arm_d26, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, gdb_arm_d27, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, gdb_arm_d28, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, gdb_arm_d29, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, gdb_arm_d30, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, gdb_arm_d31, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r0", "arg1", 4, 0, eEncodingUint , eFormatHex, { ehframe_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r1", "arg2", 4, 0, eEncodingUint , eFormatHex, { ehframe_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r2", "arg3", 4, 0, eEncodingUint , eFormatHex, { ehframe_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r3", "arg4", 4, 0, eEncodingUint , eFormatHex, { ehframe_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r4", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r5", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r6", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r7", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r8", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r9", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r10", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r11", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r12", NULL, 4, 0, eEncodingUint , eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "sp", "r13", 4, 0, eEncodingUint , eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "lr", "r14", 4, 0, eEncodingUint , eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "pc", "r15", 4, 0, eEncodingUint , eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "cpsr", "psr", 4, 0, eEncodingUint , eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s0", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s1", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s2", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s3", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s4", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s5", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s6", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s7", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s8", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s9", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s10", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s11", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s12", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s13", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s14", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s15", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s16", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s17", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s18", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s19", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s20", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s21", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s22", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s23", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s24", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s25", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s26", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s27", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s28", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s29", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s30", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "s31", NULL, 4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fpscr", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d0", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d1", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d2", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d3", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d4", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d5", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d6", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d7", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d8", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d9", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d10", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d11", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d12", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d13", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d14", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d15", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d16", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d17", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d18", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d19", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d20", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d21", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d22", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d23", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d24", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d25", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d26", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d27", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d28", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d29", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d30", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "d31", NULL, 8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, { "r8_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r8_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, { "r9_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r9_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, { "r10_usr", NULL, 4, 0, eEncodingUint , eFormatHex, { LLDB_INVALID_REGNUM, dwarf_r10_usr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, @@ -333,18 +332,18 @@ ABISysV_arm::GetArgumentValues (Thread &thread, if (!value) return false; - ClangASTType clang_type = value->GetClangType(); - if (clang_type) + CompilerType compiler_type = value->GetCompilerType(); + if (compiler_type) { bool is_signed = false; size_t bit_width = 0; - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { - bit_width = clang_type.GetBitSize(&thread); + bit_width = compiler_type.GetBitSize(&thread); } - else if (clang_type.IsPointerOrReferenceType ()) + else if (compiler_type.IsPointerOrReferenceType ()) { - bit_width = clang_type.GetBitSize(&thread); + bit_width = compiler_type.GetBitSize(&thread); } else { @@ -398,22 +397,35 @@ ABISysV_arm::GetArgumentValues (Thread &thread, return true; } +static bool +GetReturnValuePassedInMemory(Thread &thread, RegisterContext* reg_ctx, size_t byte_size, Value& value) +{ + Error error; + DataBufferHeap buffer(byte_size, 0); + + const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); + uint32_t address = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; + thread.GetProcess()->ReadMemory(address, buffer.GetBytes(), buffer.GetByteSize(), error); + + if (error.Fail()) + return false; + + value.SetBytes(buffer.GetBytes(), buffer.GetByteSize()); + return true; +} + ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl (Thread &thread, - lldb_private::ClangASTType &clang_type) const + lldb_private::CompilerType &compiler_type) const { Value value; ValueObjectSP return_valobj_sp; - if (!clang_type) + if (!compiler_type) return return_valobj_sp; - clang::ASTContext *ast_context = clang_type.GetASTContext(); - if (!ast_context) - return return_valobj_sp; - - //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType()); - value.SetClangType (clang_type); + //value.SetContext (Value::eContextTypeClangType, compiler_type.GetOpaqueQualType()); + value.SetCompilerType (compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) @@ -427,9 +439,9 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread, // when reading data const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1); - size_t bit_width = clang_type.GetBitSize(&thread); + size_t bit_width = compiler_type.GetBitSize(&thread); - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { switch (bit_width) { @@ -467,12 +479,33 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread, break; } } - else if (clang_type.IsPointerType ()) + else if (compiler_type.IsPointerType ()) { uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; value.GetScalar() = ptr; } - else if (clang_type.IsFloatingPointType(float_count, is_complex)) + else if (compiler_type.IsVectorType(nullptr, nullptr)) + { + size_t byte_size = compiler_type.GetByteSize(&thread); + if (byte_size <= 16) + { + DataBufferHeap buffer(16, 0); + uint32_t* buffer_ptr = (uint32_t*)buffer.GetBytes(); + + for (uint32_t i = 0; 4*i < byte_size; ++i) + { + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i); + buffer_ptr[i] = reg_ctx->ReadRegisterAsUnsigned(reg_info, 0) & UINT32_MAX; + } + value.SetBytes(buffer.GetBytes(), byte_size); + } + else + { + if (!GetReturnValuePassedInMemory(thread, reg_ctx, byte_size, value)) + return return_valobj_sp; + } + } + else if (compiler_type.IsFloatingPointType(float_count, is_complex)) { if (float_count == 1 && !is_complex) { @@ -506,9 +539,9 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread, return return_valobj_sp; } } - else if (clang_type.IsAggregateType()) + else if (compiler_type.IsAggregateType()) { - size_t byte_size = clang_type.GetByteSize(&thread); + size_t byte_size = compiler_type.GetByteSize(&thread); if (byte_size <= 4) { RegisterValue r0_reg_value; @@ -517,16 +550,7 @@ ABISysV_arm::GetReturnValueObjectImpl (Thread &thread, } else { - RegisterValue r0_reg_value; - uint32_t address = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX; - - Error error; - DataBufferHeap buffer(byte_size, 0); - thread.GetProcess()->ReadMemory(address, buffer.GetBytes(), buffer.GetByteSize(), error); - - if (error.Success()) - value.SetBytes(buffer.GetBytes(), buffer.GetByteSize()); - else + if (!GetReturnValuePassedInMemory(thread, reg_ctx, byte_size, value)) return return_valobj_sp; } } @@ -554,8 +578,8 @@ ABISysV_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec return error; } - ClangASTType clang_type = new_value_sp->GetClangType(); - if (!clang_type) + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { error.SetErrorString ("Null clang type for return value."); return error; @@ -570,7 +594,7 @@ ABISysV_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) + if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) { DataExtractor data; Error data_error; @@ -610,7 +634,7 @@ ABISysV_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec error.SetErrorString("We don't support returning longer than 64 bit integer values at present."); } } - else if (clang_type.IsFloatingPointType (count, is_complex)) + else if (compiler_type.IsFloatingPointType (count, is_complex)) { if (is_complex) error.SetErrorString ("We don't support returning complex values at present"); diff --git a/source/Plugins/ABI/SysV-arm/ABISysV_arm.h b/source/Plugins/ABI/SysV-arm/ABISysV_arm.h index 69becd6ec0c26..e3b280296a648 100644 --- a/source/Plugins/ABI/SysV-arm/ABISysV_arm.h +++ b/source/Plugins/ABI/SysV-arm/ABISysV_arm.h @@ -20,7 +20,7 @@ class ABISysV_arm : public lldb_private::ABI { public: - ~ABISysV_arm() { } + ~ABISysV_arm() override = default; size_t GetRedZoneSize () const override; @@ -39,12 +39,6 @@ public: lldb_private::Error SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: - lldb::ValueObjectSP - GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const override; - -public: bool CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan) override; @@ -88,6 +82,7 @@ public: //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -103,6 +98,7 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + lldb_private::ConstString GetPluginName() override; @@ -110,6 +106,10 @@ public: GetPluginVersion() override; protected: + lldb::ValueObjectSP + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const override; + private: ABISysV_arm() : lldb_private::ABI() @@ -118,4 +118,4 @@ private: } }; -#endif // liblldb_ABISysV_arm_h_ +#endif // liblldb_ABISysV_arm_h_ diff --git a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp index ed058ff19d992..bc6df235cb1e7 100644 --- a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp +++ b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp @@ -18,7 +18,6 @@ #include "lldb/Core/Scalar.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" @@ -37,7 +36,7 @@ using namespace lldb_private; static RegisterInfo g_register_infos[] = { - // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE + // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE // ========== ======= == === ============= =================== =================== ====================== =========================== ======================= ====================== { "x0", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x0, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, { "x1", NULL, 8, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM, arm64_dwarf::x1, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }, @@ -313,7 +312,7 @@ ABISysV_arm64::GetArgumentValues (Thread &thread, ValueList &values) const if (!value) return false; - ClangASTType value_type = value->GetClangType(); + CompilerType value_type = value->GetCompilerType(); if (value_type) { bool is_signed = false; @@ -397,7 +396,7 @@ ABISysV_arm64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj return error; } - ClangASTType return_value_type = new_value_sp->GetClangType(); + CompilerType return_value_type = new_value_sp->GetCompilerType(); if (!return_value_type) { error.SetErrorString ("Null clang type for return value."); @@ -686,7 +685,7 @@ ABISysV_arm64::RegisterIsVolatile (const RegisterInfo *reg_info) static bool LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, RegisterContext *reg_ctx, - const ClangASTType &value_type, + const CompilerType &value_type, bool is_return_value, // false => parameter, true => return value uint32_t &NGRN, // NGRN (see ABI documentation) uint32_t &NSRN, // NSRN (see ABI documentation) @@ -701,18 +700,16 @@ LoadValueFromConsecutiveGPRRegisters (ExecutionContext &exe_ctx, const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder(); Error error; - ClangASTType base_type; + CompilerType base_type; const uint32_t homogeneous_count = value_type.IsHomogeneousAggregate (&base_type); if (homogeneous_count > 0 && homogeneous_count <= 8) { - printf ("ClangASTContext::IsHomogeneousAggregate() => %u\n", homogeneous_count); // Make sure we have enough registers if (NSRN < 8 && (8-NSRN) >= homogeneous_count) { if (!base_type) return false; const size_t base_byte_size = base_type.GetByteSize(nullptr); - printf ("ClangASTContext::IsHomogeneousAggregate() => base_byte_size = %" PRIu64 "\n", (uint64_t) base_byte_size); uint32_t data_offset = 0; for (uint32_t i=0; iConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); + if (pc_reg == LLDB_INVALID_REGNUM) + return false; + + uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); + if (ra_reg == LLDB_INVALID_REGNUM) + return false; + + uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); + if (sp_reg == LLDB_INVALID_REGNUM) + return false; + // push host data onto target for ( size_t i = 0; i < args.size( ); i++ ) { @@ -277,11 +293,6 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread, // check if this is a variable argument function bool isVArg = prototype.isFunctionVarArg(); - // get the register context for modifying all of the registers - RegisterContext *reg_ctx = thread.GetRegisterContext().get(); - if (!reg_ctx) - return false; - // number of arguments passed by register int nRegArgs = nVArgRegParams; if (! isVArg ) @@ -324,10 +335,9 @@ ABISysV_hexagon::PrepareTrivialCall ( Thread &thread, } // update registers with current function call state - reg_ctx->WriteRegisterFromUnsigned ( 41, pc ); - reg_ctx->WriteRegisterFromUnsigned ( 31, ra ); - reg_ctx->WriteRegisterFromUnsigned ( 29, sp ); -// reg_ctx->WriteRegisterFromUnsigned ( FP ??? ); + reg_ctx->WriteRegisterFromUnsigned(pc_reg, pc); + reg_ctx->WriteRegisterFromUnsigned(ra_reg, ra); + reg_ctx->WriteRegisterFromUnsigned(sp_reg, sp); #if HEX_ABI_DEBUG // quick and dirty stack dumper for debugging @@ -359,14 +369,14 @@ ABISysV_hexagon::SetReturnValueObject ( lldb::StackFrameSP &frame_sp, lldb::Valu } ValueObjectSP -ABISysV_hexagon::GetReturnValueObjectSimple ( Thread &thread, ClangASTType &return_clang_type ) const +ABISysV_hexagon::GetReturnValueObjectSimple ( Thread &thread, CompilerType &return_compiler_type ) const { ValueObjectSP return_valobj_sp; return return_valobj_sp; } ValueObjectSP -ABISysV_hexagon::GetReturnValueObjectImpl ( Thread &thread, ClangASTType &return_clang_type ) const +ABISysV_hexagon::GetReturnValueObjectImpl ( Thread &thread, CompilerType &return_compiler_type ) const { ValueObjectSP return_valobj_sp; return return_valobj_sp; diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h index 1550a38c4f3b2..337e3fdcf7b54 100644 --- a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h +++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h @@ -21,63 +21,54 @@ class ABISysV_hexagon : public lldb_private::ABI { public: + ~ABISysV_hexagon() override = default; - ~ABISysV_hexagon( void ) - { - } - - virtual size_t - GetRedZoneSize ( void ) const; + size_t + GetRedZoneSize() const override; - virtual bool - PrepareTrivialCall ( lldb_private::Thread &thread, - lldb::addr_t sp, - lldb::addr_t functionAddress, - lldb::addr_t returnAddress, - llvm::ArrayRef args ) const; + bool + PrepareTrivialCall(lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const override; // special thread plan for GDB style non-jit function calls - virtual bool - PrepareTrivialCall ( lldb_private::Thread &thread, - lldb::addr_t sp, - lldb::addr_t functionAddress, - lldb::addr_t returnAddress, - llvm::Type &prototype, - llvm::ArrayRef args ) const; - - virtual bool - GetArgumentValues ( lldb_private::Thread &thread, - lldb_private::ValueList &values ) const; + bool + PrepareTrivialCall(lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::Type &prototype, + llvm::ArrayRef args) const override; + + bool + GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; - virtual lldb_private::Error - SetReturnValueObject ( lldb::StackFrameSP &frame_sp, - lldb::ValueObjectSP &new_value ); + lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, + lldb::ValueObjectSP &new_value) override; -protected: lldb::ValueObjectSP - GetReturnValueObjectSimple ( lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type ) const; - -public: - virtual lldb::ValueObjectSP - GetReturnValueObjectImpl ( lldb_private::Thread &thread, - lldb_private::ClangASTType &type ) const; + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &type) const override; // specialized to work with llvm IR types - virtual lldb::ValueObjectSP - GetReturnValueObjectImpl ( lldb_private::Thread &thread, llvm::Type &type ) const; + lldb::ValueObjectSP + GetReturnValueObjectImpl(lldb_private::Thread &thread, llvm::Type &type) const override; - virtual bool - CreateFunctionEntryUnwindPlan ( lldb_private::UnwindPlan &unwind_plan ); + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - CreateDefaultUnwindPlan ( lldb_private::UnwindPlan &unwind_plan ); + bool + CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - RegisterIsVolatile ( const lldb_private::RegisterInfo *reg_info ); + bool + RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; - virtual bool - CallFrameAddressIsValid ( lldb::addr_t cfa ) + bool + CallFrameAddressIsValid(lldb::addr_t cfa) override { // Make sure the stack call frame addresses are 8 byte aligned if (cfa & 0x07) @@ -87,50 +78,60 @@ public: return true; } - virtual bool - CodeAddressIsValid ( lldb::addr_t pc ) + bool + CodeAddressIsValid(lldb::addr_t pc) override { // We have a 64 bit address space, so anything is valid as opcodes // aren't fixed width... return true; } - virtual const lldb_private::RegisterInfo * - GetRegisterInfoArray ( uint32_t &count ); + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void - Initialize ( void ); + Initialize(); static void - Terminate ( void ); + Terminate(); static lldb::ABISP CreateInstance ( const lldb_private::ArchSpec &arch ); static lldb_private::ConstString - GetPluginNameStatic ( void ); + GetPluginNameStatic(); //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName ( void ); - virtual uint32_t - GetPluginVersion ( void ); + lldb_private::ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; protected: void - CreateRegisterMapIfNeeded ( void ); + CreateRegisterMapIfNeeded(); + + lldb::ValueObjectSP + GetReturnValueObjectSimple(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const; bool RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); private: - ABISysV_hexagon ( void ) : lldb_private::ABI() { } // Call CreateInstance instead. + ABISysV_hexagon() : + lldb_private::ABI() + { + // Call CreateInstance instead. + } }; -#endif // liblldb_ABISysV_hexagon_h_ +#endif // liblldb_ABISysV_hexagon_h_ diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp index 26da9aeb370d0..0a3779a2ce94e 100644 --- a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp +++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp @@ -19,7 +19,6 @@ #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectRegister.h" #include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Target.h" #include "lldb/Target/Process.h" @@ -59,171 +58,109 @@ using namespace lldb_private; // Comment: Table 2.14 is followed till 'mm' entries. // After that, all entries are ignored here. -enum gcc_dwarf_regnums +enum dwarf_regnums { - gcc_dwarf_eax = 0, - gcc_dwarf_ecx, - gcc_dwarf_edx, - gcc_dwarf_ebx, - gcc_dwarf_esp, - gcc_dwarf_ebp, - gcc_dwarf_esi, - gcc_dwarf_edi, - gcc_dwarf_eip, - gcc_dwarf_eflags, - - gcc_dwarf_st0 = 11, - gcc_dwarf_st1, - gcc_dwarf_st2, - gcc_dwarf_st3, - gcc_dwarf_st4, - gcc_dwarf_st5, - gcc_dwarf_st6, - gcc_dwarf_st7, - - gcc_dwarf_xmm0 = 21, - gcc_dwarf_xmm1, - gcc_dwarf_xmm2, - gcc_dwarf_xmm3, - gcc_dwarf_xmm4, - gcc_dwarf_xmm5, - gcc_dwarf_xmm6, - gcc_dwarf_xmm7, - gcc_dwarf_ymm0 = gcc_dwarf_xmm0, - gcc_dwarf_ymm1 = gcc_dwarf_xmm1, - gcc_dwarf_ymm2 = gcc_dwarf_xmm2, - gcc_dwarf_ymm3 = gcc_dwarf_xmm3, - gcc_dwarf_ymm4 = gcc_dwarf_xmm4, - gcc_dwarf_ymm5 = gcc_dwarf_xmm5, - gcc_dwarf_ymm6 = gcc_dwarf_xmm6, - gcc_dwarf_ymm7 = gcc_dwarf_xmm7, - - gcc_dwarf_mm0 = 29, - gcc_dwarf_mm1, - gcc_dwarf_mm2, - gcc_dwarf_mm3, - gcc_dwarf_mm4, - gcc_dwarf_mm5, - gcc_dwarf_mm6, - gcc_dwarf_mm7 -}; - - -enum gdb_regnums -{ - gdb_eax = 0, - gdb_ecx = 1, - gdb_edx = 2, - gdb_ebx = 3, - gdb_esp = 4, - gdb_ebp = 5, - gdb_esi = 6, - gdb_edi = 7, - gdb_eip = 8, - gdb_eflags = 9, - gdb_cs = 10, - gdb_ss = 11, - gdb_ds = 12, - gdb_es = 13, - gdb_fs = 14, - gdb_gs = 15, - gdb_st0 = 16, - gdb_st1 = 17, - gdb_st2 = 18, - gdb_st3 = 19, - gdb_st4 = 20, - gdb_st5 = 21, - gdb_st6 = 22, - gdb_st7 = 23, - gdb_fctrl = 24, gdb_fcw = gdb_fctrl, - gdb_fstat = 25, gdb_fsw = gdb_fstat, - gdb_ftag = 26, gdb_ftw = gdb_ftag, - gdb_fiseg = 27, gdb_fpu_cs = gdb_fiseg, - gdb_fioff = 28, gdb_ip = gdb_fioff, - gdb_foseg = 29, gdb_fpu_ds = gdb_foseg, - gdb_fooff = 30, gdb_dp = gdb_fooff, - gdb_fop = 31, - gdb_xmm0 = 32, - gdb_xmm1 = 33, - gdb_xmm2 = 34, - gdb_xmm3 = 35, - gdb_xmm4 = 36, - gdb_xmm5 = 37, - gdb_xmm6 = 38, - gdb_xmm7 = 39, - gdb_mxcsr = 40, - gdb_mm0 = 41, - gdb_mm1 = 42, - gdb_mm2 = 43, - gdb_mm3 = 44, - gdb_mm4 = 45, - gdb_mm5 = 46, - gdb_mm6 = 47, - gdb_mm7 = 48, - gdb_ymm0 = gdb_xmm0, - gdb_ymm1 = gdb_xmm1, - gdb_ymm2 = gdb_xmm2, - gdb_ymm3 = gdb_xmm3, - gdb_ymm4 = gdb_xmm4, - gdb_ymm5 = gdb_xmm5, - gdb_ymm6 = gdb_xmm6, - gdb_ymm7 = gdb_xmm7 + dwarf_eax = 0, + dwarf_ecx, + dwarf_edx, + dwarf_ebx, + dwarf_esp, + dwarf_ebp, + dwarf_esi, + dwarf_edi, + dwarf_eip, + dwarf_eflags, + + dwarf_st0 = 11, + dwarf_st1, + dwarf_st2, + dwarf_st3, + dwarf_st4, + dwarf_st5, + dwarf_st6, + dwarf_st7, + + dwarf_xmm0 = 21, + dwarf_xmm1, + dwarf_xmm2, + dwarf_xmm3, + dwarf_xmm4, + dwarf_xmm5, + dwarf_xmm6, + dwarf_xmm7, + dwarf_ymm0 = dwarf_xmm0, + dwarf_ymm1 = dwarf_xmm1, + dwarf_ymm2 = dwarf_xmm2, + dwarf_ymm3 = dwarf_xmm3, + dwarf_ymm4 = dwarf_xmm4, + dwarf_ymm5 = dwarf_xmm5, + dwarf_ymm6 = dwarf_xmm6, + dwarf_ymm7 = dwarf_xmm7, + + dwarf_mm0 = 29, + dwarf_mm1, + dwarf_mm2, + dwarf_mm3, + dwarf_mm4, + dwarf_mm5, + dwarf_mm6, + dwarf_mm7 }; static RegisterInfo g_register_infos[] = { - // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS + // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS // ====== ======= == === ============= ============ ===================== ===================== ============================ ==================== ====================== ========== =============== - { "eax", nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_eax , gcc_dwarf_eax , LLDB_INVALID_REGNUM , gdb_eax , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ebx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_ebx , gcc_dwarf_ebx , LLDB_INVALID_REGNUM , gdb_ebx , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ecx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_ecx , gcc_dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , gdb_ecx , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "edx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_edx , gcc_dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , gdb_edx , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "esi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_esi , gcc_dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , gdb_esi , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "edi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_edi , gcc_dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , gdb_edi , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_ebp , gcc_dwarf_ebp , LLDB_REGNUM_GENERIC_FP , gdb_ebp , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_esp , gcc_dwarf_esp , LLDB_REGNUM_GENERIC_SP , gdb_esp , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { gcc_dwarf_eip , gcc_dwarf_eip , LLDB_REGNUM_GENERIC_PC , gdb_eip , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "eflags", nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "cs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_cs , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ss" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ss , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ds" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ds , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "es" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_es , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "fs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fs , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "gs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gs , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "st0" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st0 , LLDB_INVALID_REGNUM , gdb_st0 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "st1" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st1 , LLDB_INVALID_REGNUM , gdb_st1 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "st2" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st2 , LLDB_INVALID_REGNUM , gdb_st2 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "st3" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st3 , LLDB_INVALID_REGNUM , gdb_st3 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "st4" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st4 , LLDB_INVALID_REGNUM , gdb_st4 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "st5" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st5 , LLDB_INVALID_REGNUM , gdb_st5 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "st6" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st6 , LLDB_INVALID_REGNUM , gdb_st6 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "st7" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_st7 , LLDB_INVALID_REGNUM , gdb_st7 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "fctrl" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fctrl , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "fstat" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fstat , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ftag" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ftag , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "fiseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fiseg , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "fioff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fioff , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "foseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_foseg , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "fooff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fooff , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "fop" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fop , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "xmm0" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm0 , LLDB_INVALID_REGNUM , gdb_xmm0 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "xmm1" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm1 , LLDB_INVALID_REGNUM , gdb_xmm1 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "xmm2" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm2 , LLDB_INVALID_REGNUM , gdb_xmm2 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "xmm3" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm3 , LLDB_INVALID_REGNUM , gdb_xmm3 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "xmm4" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm4 , LLDB_INVALID_REGNUM , gdb_xmm4 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "xmm5" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm5 , LLDB_INVALID_REGNUM , gdb_xmm5 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "xmm6" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm6 , LLDB_INVALID_REGNUM , gdb_xmm6 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "xmm7" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_xmm7 , LLDB_INVALID_REGNUM , gdb_xmm7 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "mxcsr" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_mxcsr , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ymm0" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm0 , LLDB_INVALID_REGNUM , gdb_ymm0 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ymm1" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm1 , LLDB_INVALID_REGNUM , gdb_ymm1 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ymm2" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm2 , LLDB_INVALID_REGNUM , gdb_ymm2 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ymm3" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm3 , LLDB_INVALID_REGNUM , gdb_ymm3 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ymm4" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm4 , LLDB_INVALID_REGNUM , gdb_ymm4 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ymm5" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm5 , LLDB_INVALID_REGNUM , gdb_ymm5 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ymm6" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm6 , LLDB_INVALID_REGNUM , gdb_ymm6 , LLDB_INVALID_REGNUM }, nullptr, nullptr}, - { "ymm7" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , gcc_dwarf_ymm7 , LLDB_INVALID_REGNUM , gdb_ymm7 , LLDB_INVALID_REGNUM }, nullptr, nullptr} + { "eax", nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_eax , dwarf_eax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ebx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ecx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_ecx , dwarf_ecx , LLDB_REGNUM_GENERIC_ARG4 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "edx" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_edx , dwarf_edx , LLDB_REGNUM_GENERIC_ARG3 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "esi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_esi , dwarf_esi , LLDB_REGNUM_GENERIC_ARG2 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "edi" , nullptr, 4, 0, eEncodingUint , eFormatHex , { dwarf_edi , dwarf_edi , LLDB_REGNUM_GENERIC_ARG1 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ebp" , "fp", 4, 0, eEncodingUint , eFormatHex , { dwarf_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "esp" , "sp", 4, 0, eEncodingUint , eFormatHex , { dwarf_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "eip" , "pc", 4, 0, eEncodingUint , eFormatHex , { dwarf_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "eflags", nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "cs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ss" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ds" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "es" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "fs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "gs" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "st0" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "st1" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "st2" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "st3" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "st4" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "st5" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "st6" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "st7" , nullptr, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_st7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "fctrl" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "fstat" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ftag" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "fiseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "fioff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "foseg" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "fooff" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "fop" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "xmm0" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "xmm1" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "xmm2" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "xmm3" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "xmm4" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "xmm5" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "xmm6" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "xmm7" , nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "mxcsr" , nullptr, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ymm0" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ymm1" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ymm2" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ymm3" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ymm4" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ymm5" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ymm6" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr}, + { "ymm7" , nullptr, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, nullptr, nullptr} }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -387,22 +324,22 @@ ABISysV_i386::GetArgumentValues (Thread &thread, return false; // Currently: Support for extracting values with Clang QualTypes only. - ClangASTType clang_type (value->GetClangType()); - if (clang_type) + CompilerType compiler_type (value->GetCompilerType()); + if (compiler_type) { bool is_signed; - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), is_signed, thread.GetProcess().get(), current_stack_argument); } - else if (clang_type.IsPointerType()) + else if (compiler_type.IsPointerType()) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), false, thread.GetProcess().get(), current_stack_argument); @@ -418,29 +355,170 @@ Error ABISysV_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp) { Error error; - //ToDo: Yet to be implemented - error.SetErrorString("ABISysV_i386::SetReturnValueObject(): Not implemented yet"); + if (!new_value_sp) + { + error.SetErrorString("Empty value object for return value."); + return error; + } + + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) + { + error.SetErrorString ("Null clang type for return value."); + return error; + } + + const uint32_t type_flags = compiler_type.GetTypeInfo (); + Thread *thread = frame_sp->GetThread().get(); + RegisterContext *reg_ctx = thread->GetRegisterContext().get(); + DataExtractor data; + Error data_error; + size_t num_bytes = new_value_sp->GetData(data, data_error); + bool register_write_successful = true; + + if (data_error.Fail()) + { + error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString()); + return error; + } + + // Following "IF ELSE" block categorizes various 'Fundamental Data Types'. + // The terminology 'Fundamental Data Types' used here is adopted from + // Table 2.1 of the reference document (specified on top of this file) + + if (type_flags & eTypeIsPointer) // 'Pointer' + { + if(num_bytes != sizeof(uint32_t)) + { + error.SetErrorString("Pointer to be returned is not 4 bytes wide"); + return error; + } + lldb::offset_t offset = 0; + const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0); + uint32_t raw_value = data.GetMaxU32(&offset, num_bytes); + register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value); + } + else if ((type_flags & eTypeIsScalar) || (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point' + { + lldb::offset_t offset = 0; + const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0); + + if (type_flags & eTypeIsInteger) // 'Integral' except enum + { + switch (num_bytes) + { + default: + break; + case 16: + // For clang::BuiltinType::UInt128 & Int128 + // ToDo: Need to decide how to handle it + break; + case 8: + { + uint32_t raw_value_low = data.GetMaxU32(&offset, 4); + const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0); + uint32_t raw_value_high = data.GetMaxU32(&offset, num_bytes - offset); + register_write_successful = (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value_low) && + reg_ctx->WriteRegisterFromUnsigned (edx_info, raw_value_high)); + break; + } + case 4: + case 2: + case 1: + { + uint32_t raw_value = data.GetMaxU32(&offset, num_bytes); + register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value); + break; + } + } + } + else if (type_flags & eTypeIsEnumeration) // handles enum + { + uint32_t raw_value = data.GetMaxU32(&offset, num_bytes); + register_write_successful = reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value); + } + else if (type_flags & eTypeIsFloat) // 'Floating Point' + { + RegisterValue st0_value, fstat_value, ftag_value; + const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0); + const RegisterInfo *fstat_info = reg_ctx->GetRegisterInfoByName("fstat", 0); + const RegisterInfo *ftag_info = reg_ctx->GetRegisterInfoByName("ftag", 0); + + /* According to Page 3-12 of document + System V Application Binary Interface, Intel386 Architecture Processor Supplement, Fourth Edition + To return Floating Point values, all st% registers except st0 should be empty after exiting from + a function. This requires setting fstat and ftag registers to specific values. + fstat: The TOP field of fstat should be set to a value [0,7]. ABI doesn't specify the specific + value of TOP in case of function return. Hence, we set the TOP field to 7 by our choice. */ + uint32_t value_fstat_u32 = 0x00003800; + + /* ftag: Implication of setting TOP to 7 and indicating all st% registers empty except st0 is to set + 7th bit of 4th byte of FXSAVE area to 1 and all other bits of this byte to 0. This is in accordance + with the document Intel 64 and IA-32 Architectures Software Developer's Manual, January 2015 */ + uint32_t value_ftag_u32 = 0x00000080; + + if (num_bytes <= 12) // handles float, double, long double, __float80 + { + long double value_long_dbl = 0.0; + if (num_bytes == 4) + value_long_dbl = data.GetFloat(&offset); + else if (num_bytes == 8) + value_long_dbl = data.GetDouble(&offset); + else if (num_bytes == 12) + value_long_dbl = data.GetLongDouble(&offset); + else + { + error.SetErrorString ("Invalid number of bytes for this return type"); + return error; + } + st0_value.SetLongDouble(value_long_dbl); + fstat_value.SetUInt32(value_fstat_u32); + ftag_value.SetUInt32(value_ftag_u32); + register_write_successful = reg_ctx->WriteRegister(st0_info, st0_value) && + reg_ctx->WriteRegister(fstat_info, fstat_value) && + reg_ctx->WriteRegister(ftag_info, ftag_value); + } + else if(num_bytes == 16) // handles __float128 + { + error.SetErrorString ("Implementation is missing for this clang type."); + } + } + else + { + // Neither 'Integral' nor 'Floating Point'. If flow reaches here + // then check type_flags. This type_flags is not a valid type. + error.SetErrorString ("Invalid clang type"); + } + } + else + { + /* 'Complex Floating Point', 'Packed', 'Decimal Floating Point' and 'Aggregate' data types + are yet to be implemented */ + error.SetErrorString ("Currently only Integral and Floating Point clang types are supported."); + } + if(!register_write_successful) + error.SetErrorString ("Register writing failed"); return error; } ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, - ClangASTType &return_clang_type) const + CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; Value value; - if (!return_clang_type) + if (!return_compiler_type) return return_valobj_sp; - value.SetClangType (return_clang_type); + value.SetCompilerType (return_compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; - const uint32_t type_flags = return_clang_type.GetTypeInfo (); + const uint32_t type_flags = return_compiler_type.GetTypeInfo (); unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB]; @@ -463,7 +541,7 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, else if ((type_flags & eTypeIsScalar) || (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point' { value.SetValueType(Value::eValueTypeScalar); - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); bool success = false; if (type_flags & eTypeIsInteger) // 'Integral' except enum @@ -579,7 +657,7 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, return_valobj_sp = ValueObjectMemory::Create (&thread, "", Address (storage_addr, nullptr), - return_clang_type); + return_compiler_type); } } @@ -597,16 +675,12 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, else if (type_flags & eTypeIsVector) // 'Packed' { - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); if (byte_size > 0) { - const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("ymm0", 0); + const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0); if (vec_reg == nullptr) - { - vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0); - if (vec_reg == nullptr) - vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0); - } + vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0); if (vec_reg) { @@ -631,13 +705,52 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, byte_order, process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); return_valobj_sp = ValueObjectConstResult::Create (&thread, - return_clang_type, + return_compiler_type, ConstString(""), data); } } } } + else if (byte_size <= vec_reg->byte_size*2) + { + const RegisterInfo *vec_reg2 = reg_ctx->GetRegisterInfoByName("xmm1", 0); + if (vec_reg2) + { + ProcessSP process_sp (thread.GetProcess()); + if (process_sp) + { + std::unique_ptr heap_data_ap (new DataBufferHeap(byte_size, 0)); + const ByteOrder byte_order = process_sp->GetByteOrder(); + RegisterValue reg_value; + RegisterValue reg_value2; + if (reg_ctx->ReadRegister(vec_reg, reg_value) && reg_ctx->ReadRegister(vec_reg2, reg_value2)) + { + + Error error; + if (reg_value.GetAsMemoryData (vec_reg, + heap_data_ap->GetBytes(), + vec_reg->byte_size, + byte_order, + error) && + reg_value2.GetAsMemoryData (vec_reg2, + heap_data_ap->GetBytes() + vec_reg->byte_size, + heap_data_ap->GetByteSize() - vec_reg->byte_size, + byte_order, + error)) + { + DataExtractor data (DataBufferSP (heap_data_ap.release()), + byte_order, + process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); + return_valobj_sp = ValueObjectConstResult::Create (&thread, + return_compiler_type, + ConstString(""), + data); + } + } + } + } + } } } } @@ -651,15 +764,15 @@ ABISysV_i386::GetReturnValueObjectSimple (Thread &thread, ValueObjectSP -ABISysV_i386::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_i386::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; - if (!return_clang_type) + if (!return_compiler_type) return return_valobj_sp; ExecutionContext exe_ctx (thread.shared_from_this()); - return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type); + return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type); if (return_valobj_sp) return return_valobj_sp; @@ -667,14 +780,14 @@ ABISysV_i386::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cla if (!reg_ctx_sp) return return_valobj_sp; - if (return_clang_type.IsAggregateType()) + if (return_compiler_type.IsAggregateType()) { unsigned eax_id = reg_ctx_sp->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; lldb::addr_t storage_addr = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff); return_valobj_sp = ValueObjectMemory::Create (&thread, "", Address (storage_addr, nullptr), - return_clang_type); + return_compiler_type); } return return_valobj_sp; @@ -690,8 +803,8 @@ ABISysV_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.Clear(); unwind_plan.SetRegisterKind (eRegisterKindDWARF); - uint32_t sp_reg_num = gcc_dwarf_esp; - uint32_t pc_reg_num = gcc_dwarf_eip; + uint32_t sp_reg_num = dwarf_esp; + uint32_t pc_reg_num = dwarf_eip; UnwindPlan::RowSP row(new UnwindPlan::Row); row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 4); @@ -714,9 +827,9 @@ ABISysV_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.Clear(); unwind_plan.SetRegisterKind (eRegisterKindDWARF); - uint32_t fp_reg_num = gcc_dwarf_ebp; - uint32_t sp_reg_num = gcc_dwarf_esp; - uint32_t pc_reg_num = gcc_dwarf_eip; + uint32_t fp_reg_num = dwarf_ebp; + uint32_t sp_reg_num = dwarf_esp; + uint32_t pc_reg_num = dwarf_eip; UnwindPlan::RowSP row(new UnwindPlan::Row); const int32_t ptr_size = 4; diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.h b/source/Plugins/ABI/SysV-i386/ABISysV_i386.h index 9612f900d2cef..2d0f097c328e6 100644 --- a/source/Plugins/ABI/SysV-i386/ABISysV_i386.h +++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.h @@ -21,10 +21,7 @@ class ABISysV_i386 : public lldb_private::ABI { public: - - ~ABISysV_i386() - { - } + ~ABISysV_i386() override = default; size_t GetRedZoneSize () const override @@ -46,18 +43,9 @@ public: lldb_private::Error SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: - lldb::ValueObjectSP - GetReturnValueObjectSimple (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const; - - bool - RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); - -public: lldb::ValueObjectSP GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &type) const override; + lldb_private::CompilerType &type) const override; bool CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan) override; @@ -104,9 +92,11 @@ public: const lldb_private::RegisterInfo * GetRegisterInfoArray (uint32_t &count) override; + //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -119,6 +109,7 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ + static lldb_private::ConstString GetPluginNameStatic(); @@ -126,13 +117,25 @@ public: GetPluginName() override; uint32_t - GetPluginVersion() override + GetPluginVersion() override { return 1; } +protected: + lldb::ValueObjectSP + GetReturnValueObjectSimple(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const; + + bool + RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); + private: - ABISysV_i386() : lldb_private::ABI() { } // Call CreateInstance instead. + ABISysV_i386() : + lldb_private::ABI() + { + // Call CreateInstance instead. + } }; -#endif // liblldb_ABI_h +#endif // liblldb_ABISysV_i386_h_ diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp index e1fc13a691afd..3c7e9495d6ce5 100644 --- a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp +++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp @@ -20,7 +20,6 @@ #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectRegister.h" #include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Target.h" #include "lldb/Target/Process.h" @@ -34,133 +33,91 @@ using namespace lldb; using namespace lldb_private; -enum gcc_dwarf_regnums +enum dwarf_regnums { - gcc_dwarf_r0 = 0, - gcc_dwarf_r1, - gcc_dwarf_r2, - gcc_dwarf_r3, - gcc_dwarf_r4, - gcc_dwarf_r5, - gcc_dwarf_r6, - gcc_dwarf_r7, - gcc_dwarf_r8, - gcc_dwarf_r9, - gcc_dwarf_r10, - gcc_dwarf_r11, - gcc_dwarf_r12, - gcc_dwarf_r13, - gcc_dwarf_r14, - gcc_dwarf_r15, - gcc_dwarf_r16, - gcc_dwarf_r17, - gcc_dwarf_r18, - gcc_dwarf_r19, - gcc_dwarf_r20, - gcc_dwarf_r21, - gcc_dwarf_r22, - gcc_dwarf_r23, - gcc_dwarf_r24, - gcc_dwarf_r25, - gcc_dwarf_r26, - gcc_dwarf_r27, - gcc_dwarf_r28, - gcc_dwarf_r29, - gcc_dwarf_r30, - gcc_dwarf_r31, - gcc_dwarf_sr, - gcc_dwarf_lo, - gcc_dwarf_hi, - gcc_dwarf_bad, - gcc_dwarf_cause, - gcc_dwarf_pc -}; - -enum gdb_regnums -{ - gdb_r0 = 0, - gdb_r1, - gdb_r2, - gdb_r3, - gdb_r4, - gdb_r5, - gdb_r6, - gdb_r7, - gdb_r8, - gdb_r9, - gdb_r10, - gdb_r11, - gdb_r12, - gdb_r13, - gdb_r14, - gdb_r15, - gdb_r16, - gdb_r17, - gdb_r18, - gdb_r19, - gdb_r20, - gdb_r21, - gdb_r22, - gdb_r23, - gdb_r24, - gdb_r25, - gdb_r26, - gdb_r27, - gdb_r28, - gdb_r29, - gdb_r30, - gdb_r31, - gdb_sr, - gdb_lo, - gdb_hi, - gdb_bad, - gdb_cause, - gdb_pc + dwarf_r0 = 0, + dwarf_r1, + dwarf_r2, + dwarf_r3, + dwarf_r4, + dwarf_r5, + dwarf_r6, + dwarf_r7, + dwarf_r8, + dwarf_r9, + dwarf_r10, + dwarf_r11, + dwarf_r12, + dwarf_r13, + dwarf_r14, + dwarf_r15, + dwarf_r16, + dwarf_r17, + dwarf_r18, + dwarf_r19, + dwarf_r20, + dwarf_r21, + dwarf_r22, + dwarf_r23, + dwarf_r24, + dwarf_r25, + dwarf_r26, + dwarf_r27, + dwarf_r28, + dwarf_r29, + dwarf_r30, + dwarf_r31, + dwarf_sr, + dwarf_lo, + dwarf_hi, + dwarf_bad, + dwarf_cause, + dwarf_pc }; static const RegisterInfo g_register_infos[] = { - // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS - // ======== ====== == === ============= =================== ============ ===================== ==================== ================= ====================== ========== =============== - { "r0" , "zero", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r1" , "AT", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r1, gcc_dwarf_r1, LLDB_INVALID_REGNUM, gdb_r1, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r2" , "v0", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r3" , "v1", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r3, gcc_dwarf_r3, LLDB_INVALID_REGNUM, gdb_r3, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r4" , "arg1", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, gdb_r4, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r5" , "arg2", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, gdb_r5, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r6" , "arg3", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, gdb_r6, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r7" , "arg4", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, gdb_r7, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r8" , "arg5", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r8, gcc_dwarf_r8, LLDB_INVALID_REGNUM, gdb_r8, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r9" , "arg6", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r9, gcc_dwarf_r9, LLDB_INVALID_REGNUM, gdb_r9, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r10" , "arg7", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r10, gcc_dwarf_r10, LLDB_INVALID_REGNUM, gdb_r10, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r11" , "arg8", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r11, gcc_dwarf_r11, LLDB_INVALID_REGNUM, gdb_r11, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r12" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r13" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r14" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r15" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r16" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r17" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r18" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r19" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r20" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r21" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r22" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r23" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r24" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r25" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r26" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r27" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r28" , "gp", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r29" , "sp", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r29, gcc_dwarf_r29, LLDB_REGNUM_GENERIC_SP, gdb_r29, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r30" , "fp", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r30, gcc_dwarf_r30, LLDB_REGNUM_GENERIC_FP, gdb_r30, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r31" , "ra", 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r31, gcc_dwarf_r31, LLDB_REGNUM_GENERIC_RA, gdb_r31, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "sr" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_sr, gcc_dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, gdb_sr, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "lo" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_lo, gcc_dwarf_lo, LLDB_INVALID_REGNUM, gdb_lo, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "hi" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_hi, gcc_dwarf_hi, LLDB_INVALID_REGNUM, gdb_hi, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "bad" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_bad, gcc_dwarf_bad, LLDB_INVALID_REGNUM, gdb_bad, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "cause" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cause, gcc_dwarf_cause, LLDB_INVALID_REGNUM, gdb_cause, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "pc" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_pc, LLDB_INVALID_REGNUM }, NULL, NULL}, + // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGINS LLDB NATIVE VALUE REGS INVALIDATE REGS + // ======== ====== == === ============= =========== ============ ============== ============ ================= =================== ========== ================= + { "r0" , "zero", 4, 0, eEncodingUint, eFormatHex, { dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r1" , "AT", 4, 0, eEncodingUint, eFormatHex, { dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r2" , "v0", 4, 0, eEncodingUint, eFormatHex, { dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r3" , "v1", 4, 0, eEncodingUint, eFormatHex, { dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r4" , "arg1", 4, 0, eEncodingUint, eFormatHex, { dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r5" , "arg2", 4, 0, eEncodingUint, eFormatHex, { dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r6" , "arg3", 4, 0, eEncodingUint, eFormatHex, { dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r7" , "arg4", 4, 0, eEncodingUint, eFormatHex, { dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r8" , "arg5", 4, 0, eEncodingUint, eFormatHex, { dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r9" , "arg6", 4, 0, eEncodingUint, eFormatHex, { dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r10" , "arg7", 4, 0, eEncodingUint, eFormatHex, { dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r11" , "arg8", 4, 0, eEncodingUint, eFormatHex, { dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r12" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r13" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r14" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r15" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r16" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r17" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r18" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r19" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r20" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r21" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r22" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r23" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r24" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r25" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r26" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r27" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r28" , "gp", 4, 0, eEncodingUint, eFormatHex, { dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r29" , "sp", 4, 0, eEncodingUint, eFormatHex, { dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r30" , "fp", 4, 0, eEncodingUint, eFormatHex, { dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r31" , "ra", 4, 0, eEncodingUint, eFormatHex, { dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "sr" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "lo" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "hi" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "bad" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "cause" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "pc" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -284,6 +241,7 @@ ABISysV_mips::PrepareTrivialCall (Thread &thread, const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); const RegisterInfo *ra_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA); + const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0); if (log) log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp); @@ -305,7 +263,14 @@ ABISysV_mips::PrepareTrivialCall (Thread &thread, // Set pc to the address of the called function. if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr)) return false; - + + if (log) + log->Printf("Writing r25: 0x%" PRIx64, (uint64_t)func_addr); + + // All callers of position independent functions must place the address of the called function in t9 (r25) + if (!reg_ctx->WriteRegisterFromUnsigned (r25_info, func_addr)) + return false; + return true; } @@ -325,8 +290,8 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje return error; } - ClangASTType clang_type = new_value_sp->GetClangType(); - if (!clang_type) + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { error.SetErrorString ("Null clang type for return value."); return error; @@ -341,7 +306,7 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) + if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) { DataExtractor data; Error data_error; @@ -382,7 +347,7 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje error.SetErrorString("We don't support returning longer than 64 bit integer values at present."); } } - else if (clang_type.IsFloatingPointType (count, is_complex)) + else if (compiler_type.IsFloatingPointType (count, is_complex)) { if (is_complex) error.SetErrorString ("We don't support returning complex values at present"); @@ -398,40 +363,41 @@ ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObje ValueObjectSP -ABISysV_mips::GetReturnValueObjectSimple (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_mips::GetReturnValueObjectSimple (Thread &thread, CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; return return_valobj_sp; } ValueObjectSP -ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; Value value; - if (!return_clang_type) + if (!return_compiler_type) return return_valobj_sp; ExecutionContext exe_ctx (thread.shared_from_this()); if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL) return return_valobj_sp; - value.SetClangType(return_clang_type); + value.SetCompilerType(return_compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; - bool is_signed; + bool is_signed = false; + bool is_complex = false; + uint32_t count = 0; // In MIPS register "r2" (v0) holds the integer function return values const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0); + size_t bit_width = return_compiler_type.GetBitSize(&thread); - if (return_clang_type.IsIntegerType (is_signed)) + if (return_compiler_type.IsIntegerType (is_signed)) { - size_t bit_width = return_clang_type.GetBitSize(&thread); - switch (bit_width) { default: @@ -468,11 +434,57 @@ ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cla break; } } - else if (return_clang_type.IsPointerType ()) + else if (return_compiler_type.IsPointerType ()) { uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX; value.GetScalar() = ptr; } + else if (return_compiler_type.IsAggregateType ()) + { + // Structure/Vector is always passed in memory and pointer to that memory is passed in r2. + uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0); + // We have got the address. Create a memory object out of it + return_valobj_sp = ValueObjectMemory::Create (&thread, + "", + Address (mem_address, NULL), + return_compiler_type); + return return_valobj_sp; + } + else if (return_compiler_type.IsFloatingPointType (count, is_complex)) + { + const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0); + const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); + + if (count == 1 && !is_complex) + { + switch (bit_width) + { + default: + return return_valobj_sp; + case 64: + { + static_assert(sizeof(double) == sizeof(uint64_t), ""); + uint64_t raw_value; + raw_value = reg_ctx->ReadRegisterAsUnsigned(f0_info, 0) & UINT32_MAX; + raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(f1_info, 0) & UINT32_MAX)) << 32; + value.GetScalar() = *reinterpret_cast(&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); + break; + } + } + } + else + { + // not handled yet + return return_valobj_sp; + } + } else { // not handled yet @@ -496,17 +508,17 @@ ABISysV_mips::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) UnwindPlan::RowSP row(new UnwindPlan::Row); // Our Call Frame Address is the stack pointer value - row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0); + row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0); // The previous PC is in the RA - row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true); + row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true); unwind_plan.AppendRow (row); // All other registers are the same. unwind_plan.SetSourceName ("mips at-func-entry default"); unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); - unwind_plan.SetReturnAddressRegister(gcc_dwarf_r31); + unwind_plan.SetReturnAddressRegister(dwarf_r31); return true; } @@ -518,9 +530,9 @@ ABISysV_mips::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) UnwindPlan::RowSP row(new UnwindPlan::Row); - row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0); + row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0); - row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true); + row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true); unwind_plan.AppendRow (row); unwind_plan.SetSourceName ("mips default unwind plan"); @@ -542,13 +554,36 @@ ABISysV_mips::RegisterIsCalleeSaved (const RegisterInfo *reg_info) { // Preserved registers are : // r16-r23, r28, r29, r30, r31 + const char *name = reg_info->name; - int reg = ((reg_info->byte_offset) / 4); - - bool save = (reg >= 16) && (reg <= 23); - save |= (reg >= 28) && (reg <= 31); + if (name[0] == 'r') + { + switch (name[1]) + { + case '1': + if (name[2] == '6' || name[2] == '7' || name[2] == '8' || name[2] == '9') // r16-r19 + return name[3] == '\0'; + break; + case '2': + if (name[2] == '0' || name[2] == '1' || name[2] == '2' || name[2] == '3' // r20-r23 + || name[2] == '8' || name[2] == '9') // r28 and r29 + return name[3] == '\0'; + break; + case '3': + if (name[2] == '0' || name[2] == '1') // r30 and r31 + return name[3] == '\0'; + break; + } - return save; + if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0') // gp (r28) + return true; + if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp (r29) + return true; + if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp (r30) + return true; + if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0') // ra (r31) + return true; + } } return false; } diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.h b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h index ad47ac2229329..709c3bfe3adf5 100644 --- a/source/Plugins/ABI/SysV-mips/ABISysV_mips.h +++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h @@ -21,49 +21,40 @@ class ABISysV_mips : public lldb_private::ABI { public: + ~ABISysV_mips() override = default; - ~ABISysV_mips() - { - } - - virtual size_t - GetRedZoneSize () const; + size_t + GetRedZoneSize() const override; - virtual bool - PrepareTrivialCall (lldb_private::Thread &thread, - lldb::addr_t sp, - lldb::addr_t functionAddress, - lldb::addr_t returnAddress, - llvm::ArrayRef args) const; + bool + PrepareTrivialCall(lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const override; - virtual bool - GetArgumentValues (lldb_private::Thread &thread, - lldb_private::ValueList &values) const; + bool + GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; - virtual lldb_private::Error - SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); + lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: lldb::ValueObjectSP - GetReturnValueObjectSimple (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const; - -public: - virtual lldb::ValueObjectSP - GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &type) const; + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &type) const override; - virtual bool - CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); + bool + RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; - virtual bool - CallFrameAddressIsValid (lldb::addr_t cfa) + bool + CallFrameAddressIsValid(lldb::addr_t cfa) override { // Make sure the stack call frame addresses are 8 byte aligned if (cfa & (8ull - 1ull)) @@ -73,21 +64,21 @@ public: return true; } - virtual bool - CodeAddressIsValid (lldb::addr_t pc)//must- check + bool + CodeAddressIsValid(lldb::addr_t pc) override { - if (pc & (4ull - 1ull)) - return false; // Not 4 byte aligned - - // Anything else if fair game.. - return true; + // Just make sure the address is a valid 32 bit address. Bit zero + // might be set due to MicroMIPS function calls, so don't enforce alignment. + return (pc <= UINT32_MAX); } - virtual const lldb_private::RegisterInfo * - GetRegisterInfoArray (uint32_t &count); + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; + //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -103,21 +94,30 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); - virtual uint32_t - GetPluginVersion(); + lldb_private::ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; protected: void CreateRegisterMapIfNeeded (); + lldb::ValueObjectSP + GetReturnValueObjectSimple(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const; + bool RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); private: - ABISysV_mips() : lldb_private::ABI() { } // Call CreateInstance instead. + ABISysV_mips() : + lldb_private::ABI() + { + // Call CreateInstance instead. + } }; -#endif // liblldb_ABI_h_ +#endif // liblldb_ABISysV_mips_h_ diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp index c790fa7e7bdd0..bc62c9fe82ee0 100644 --- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp +++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp @@ -20,7 +20,6 @@ #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectRegister.h" #include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Target.h" #include "lldb/Target/Process.h" @@ -34,133 +33,91 @@ using namespace lldb; using namespace lldb_private; -enum gcc_dwarf_regnums +enum dwarf_regnums { - gcc_dwarf_r0 = 0, - gcc_dwarf_r1, - gcc_dwarf_r2, - gcc_dwarf_r3, - gcc_dwarf_r4, - gcc_dwarf_r5, - gcc_dwarf_r6, - gcc_dwarf_r7, - gcc_dwarf_r8, - gcc_dwarf_r9, - gcc_dwarf_r10, - gcc_dwarf_r11, - gcc_dwarf_r12, - gcc_dwarf_r13, - gcc_dwarf_r14, - gcc_dwarf_r15, - gcc_dwarf_r16, - gcc_dwarf_r17, - gcc_dwarf_r18, - gcc_dwarf_r19, - gcc_dwarf_r20, - gcc_dwarf_r21, - gcc_dwarf_r22, - gcc_dwarf_r23, - gcc_dwarf_r24, - gcc_dwarf_r25, - gcc_dwarf_r26, - gcc_dwarf_r27, - gcc_dwarf_r28, - gcc_dwarf_r29, - gcc_dwarf_r30, - gcc_dwarf_r31, - gcc_dwarf_sr, - gcc_dwarf_lo, - gcc_dwarf_hi, - gcc_dwarf_bad, - gcc_dwarf_cause, - gcc_dwarf_pc -}; - -enum gdb_regnums -{ - gdb_r0 = 0, - gdb_r1, - gdb_r2, - gdb_r3, - gdb_r4, - gdb_r5, - gdb_r6, - gdb_r7, - gdb_r8, - gdb_r9, - gdb_r10, - gdb_r11, - gdb_r12, - gdb_r13, - gdb_r14, - gdb_r15, - gdb_r16, - gdb_r17, - gdb_r18, - gdb_r19, - gdb_r20, - gdb_r21, - gdb_r22, - gdb_r23, - gdb_r24, - gdb_r25, - gdb_r26, - gdb_r27, - gdb_r28, - gdb_r29, - gdb_r30, - gdb_r31, - gdb_sr, - gdb_lo, - gdb_hi, - gdb_bad, - gdb_cause, - gdb_pc + dwarf_r0 = 0, + dwarf_r1, + dwarf_r2, + dwarf_r3, + dwarf_r4, + dwarf_r5, + dwarf_r6, + dwarf_r7, + dwarf_r8, + dwarf_r9, + dwarf_r10, + dwarf_r11, + dwarf_r12, + dwarf_r13, + dwarf_r14, + dwarf_r15, + dwarf_r16, + dwarf_r17, + dwarf_r18, + dwarf_r19, + dwarf_r20, + dwarf_r21, + dwarf_r22, + dwarf_r23, + dwarf_r24, + dwarf_r25, + dwarf_r26, + dwarf_r27, + dwarf_r28, + dwarf_r29, + dwarf_r30, + dwarf_r31, + dwarf_sr, + dwarf_lo, + dwarf_hi, + dwarf_bad, + dwarf_cause, + dwarf_pc }; static const RegisterInfo g_register_infos_mips64[] = { - // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS - // ======== ====== == === ============= =================== ============ ===================== ==================== ================= ====================== ========== =============== - { "r0" , "zero", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r1" , "AT", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r1, gcc_dwarf_r1, LLDB_INVALID_REGNUM, gdb_r1, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r2" , "v0", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r3" , "v1", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r3, gcc_dwarf_r3, LLDB_INVALID_REGNUM, gdb_r3, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r4" , "arg1", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, gdb_r4, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r5" , "arg2", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, gdb_r5, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r6" , "arg3", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, gdb_r6, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r7" , "arg4", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, gdb_r7, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r8" , "arg5", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r8, gcc_dwarf_r8, LLDB_REGNUM_GENERIC_ARG5, gdb_r8, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r9" , "arg6", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r9, gcc_dwarf_r9, LLDB_REGNUM_GENERIC_ARG6, gdb_r9, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r10" , "arg7", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r10, gcc_dwarf_r10, LLDB_REGNUM_GENERIC_ARG7, gdb_r10, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r11" , "arg8", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r11, gcc_dwarf_r11, LLDB_REGNUM_GENERIC_ARG8, gdb_r11, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r12" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r13" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r14" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r15" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r16" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r17" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r18" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r19" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r20" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r21" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r22" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r23" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r24" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r25" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r26" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r27" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r28" , "gp", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r29" , "sp", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r29, gcc_dwarf_r29, LLDB_REGNUM_GENERIC_SP, gdb_r29, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r30" , "fp", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r30, gcc_dwarf_r30, LLDB_REGNUM_GENERIC_FP, gdb_r30, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r31" , "ra", 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_r31, gcc_dwarf_r31, LLDB_REGNUM_GENERIC_RA, gdb_r31, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "sr" , NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_dwarf_sr, gcc_dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, gdb_sr, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "lo" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_lo, gcc_dwarf_lo, LLDB_INVALID_REGNUM, gdb_lo, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "hi" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_hi, gcc_dwarf_hi, LLDB_INVALID_REGNUM, gdb_hi, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "bad" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_bad, gcc_dwarf_bad, LLDB_INVALID_REGNUM, gdb_bad, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "cause" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cause, gcc_dwarf_cause, LLDB_INVALID_REGNUM, gdb_cause, LLDB_INVALID_REGNUM }, NULL, NULL}, - { "pc" , NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, gdb_pc, LLDB_INVALID_REGNUM }, NULL, NULL}, + // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS + // ======== ====== == === ============= ========== ============= ================= ==================== ================= ==================== ========== =============== + { "r0" , "zero", 8, 0, eEncodingUint, eFormatHex, { dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r1" , "AT", 8, 0, eEncodingUint, eFormatHex, { dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r2" , "v0", 8, 0, eEncodingUint, eFormatHex, { dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r3" , "v1", 8, 0, eEncodingUint, eFormatHex, { dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r4" , "arg1", 8, 0, eEncodingUint, eFormatHex, { dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r5" , "arg2", 8, 0, eEncodingUint, eFormatHex, { dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r6" , "arg3", 8, 0, eEncodingUint, eFormatHex, { dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r7" , "arg4", 8, 0, eEncodingUint, eFormatHex, { dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r8" , "arg5", 8, 0, eEncodingUint, eFormatHex, { dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r9" , "arg6", 8, 0, eEncodingUint, eFormatHex, { dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r10" , "arg7", 8, 0, eEncodingUint, eFormatHex, { dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r11" , "arg8", 8, 0, eEncodingUint, eFormatHex, { dwarf_r11, dwarf_r11, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r12" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r13" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r14" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r15" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r16" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r17" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r18" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r19" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r20" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r21" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r22" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r23" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r24" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r25" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r26" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r27" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r28" , "gp", 8, 0, eEncodingUint, eFormatHex, { dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r29" , "sp", 8, 0, eEncodingUint, eFormatHex, { dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r30" , "fp", 8, 0, eEncodingUint, eFormatHex, { dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r31" , "ra", 8, 0, eEncodingUint, eFormatHex, { dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "sr" , NULL, 4, 0, eEncodingUint, eFormatHex, { dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "lo" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "hi" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "bad" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "cause" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "pc" , NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos_mips64); @@ -290,8 +247,8 @@ ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb return error; } - ClangASTType clang_type = new_value_sp->GetClangType(); - if (!clang_type) + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { error.SetErrorString ("Null clang type for return value."); return error; @@ -313,7 +270,7 @@ ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb return error; } - const uint32_t type_flags = clang_type.GetTypeInfo (NULL); + const uint32_t type_flags = compiler_type.GetTypeInfo (NULL); if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) @@ -368,42 +325,50 @@ ABISysV_mips64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb ValueObjectSP -ABISysV_mips64::GetReturnValueObjectSimple (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_mips64::GetReturnValueObjectSimple (Thread &thread, CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; return return_valobj_sp; } ValueObjectSP -ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; Value value; - + Error error; + ExecutionContext exe_ctx (thread.shared_from_this()); if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL) return return_valobj_sp; - value.SetClangType(return_clang_type); + value.SetCompilerType(return_compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; - const size_t byte_size = return_clang_type.GetByteSize(nullptr); - const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL); + Target *target = exe_ctx.GetTargetPtr(); + ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder(); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); + const uint32_t type_flags = return_compiler_type.GetTypeInfo (NULL); + + const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0); + const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0); - if (type_flags & eTypeIsScalar) + if (type_flags & eTypeIsScalar || + type_flags & eTypeIsPointer) { value.SetValueType(Value::eValueTypeScalar); bool success = false; - if (type_flags & eTypeIsInteger) + if (type_flags & eTypeIsInteger || + type_flags & eTypeIsPointer) { // Extract the register context so we can read arguments from registers // In MIPS register "r2" (v0) holds the integer function return values - uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0); + uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0); const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (byte_size) @@ -444,25 +409,302 @@ ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c break; } } + else if (type_flags & eTypeIsFloat) + { + if (type_flags & eTypeIsComplex) + { + // Don't handle complex yet. + } + else + { + if (byte_size <= sizeof(long double)) + { + const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0); + const RegisterInfo *f2_info = reg_ctx->GetRegisterInfoByName("f2", 0); + RegisterValue f0_value, f2_value; + DataExtractor f0_data, f2_data; + + reg_ctx->ReadRegister (f0_info, f0_value); + reg_ctx->ReadRegister (f2_info, f2_value); + + f0_value.GetData(f0_data); + f2_value.GetData(f2_data); + + lldb::offset_t offset = 0; + if (byte_size == sizeof(float)) + { + value.GetScalar() = (float) f0_data.GetFloat(&offset); + success = true; + } + else if (byte_size == sizeof(double)) + { + value.GetScalar() = (double) f0_data.GetDouble(&offset); + success = true; + } + else if (byte_size == sizeof(long double)) + { + DataExtractor *copy_from_extractor = NULL; + DataBufferSP data_sp (new DataBufferHeap(16, 0)); + DataExtractor return_ext (data_sp, + target_byte_order, + target->GetArchitecture().GetAddressByteSize()); + + if (target_byte_order == eByteOrderLittle) + { + f0_data.Append(f2_data); + copy_from_extractor = &f0_data; + } + else + { + f2_data.Append(f0_data); + copy_from_extractor = &f2_data; + } + + copy_from_extractor->CopyByteOrderedData (0, + byte_size, + data_sp->GetBytes(), + byte_size, + target_byte_order); + + return_valobj_sp = ValueObjectConstResult::Create (&thread, + return_compiler_type, + ConstString(""), + return_ext); + return return_valobj_sp; + + } + } + } + } if (success) return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); } - else if (type_flags & eTypeIsPointer) + else if (type_flags & eTypeIsStructUnion || + type_flags & eTypeIsClass || + type_flags & eTypeIsVector) { - value.SetValueType(Value::eValueTypeScalar); - uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0); - value.GetScalar() = (uint64_t)(raw_value); + // Any structure of up to 16 bytes in size is returned in the registers. + if (byte_size <= 16) + { + DataBufferSP data_sp (new DataBufferHeap(16, 0)); + DataExtractor return_ext (data_sp, + target_byte_order, + target->GetArchitecture().GetAddressByteSize()); + + RegisterValue r2_value, r3_value, f0_value, f1_value, f2_value; + + uint32_t integer_bytes = 0; // Tracks how much bytes of r2 and r3 registers we've consumed so far + bool use_fp_regs = 0; // True if return values are in FP return registers. + bool found_non_fp_field = 0; // True if we found any non floating point field in structure. + bool use_r2 = 0; // True if return values are in r2 register. + bool use_r3 = 0; // True if return values are in r3 register. + bool sucess = 0; // True if the result is copied into our data buffer + std::string name; + bool is_complex; + uint32_t count; + const uint32_t num_children = return_compiler_type.GetNumFields (); + + // A structure consisting of one or two FP values (and nothing else) will be + // returned in the two FP return-value registers i.e fp0 and fp2. + if (num_children <= 2) + { + uint64_t field_bit_offset = 0; - return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), - value, - ConstString("")); - } - else if (type_flags & eTypeIsVector) - { - // TODO: Handle vector types + // Check if this structure contains only floating point fields + for (uint32_t idx = 0; idx < num_children; idx++) + { + CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); + + if (field_compiler_type.IsFloatingPointType (count, is_complex)) + use_fp_regs = 1; + else + found_non_fp_field = 1; + } + + if (use_fp_regs && !found_non_fp_field) + { + // We have one or two FP-only values in this structure. Get it from f0/f2 registers. + DataExtractor f0_data, f1_data, f2_data; + const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0); + const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); + const RegisterInfo *f2_info = reg_ctx->GetRegisterInfoByName("f2", 0); + + reg_ctx->ReadRegister (f0_info, f0_value); + reg_ctx->ReadRegister (f2_info, f2_value); + + f0_value.GetData(f0_data); + f2_value.GetData(f2_data); + + for (uint32_t idx = 0; idx < num_children; idx++) + { + CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); + const size_t field_byte_width = field_compiler_type.GetByteSize(nullptr); + + DataExtractor *copy_from_extractor = NULL; + + if (idx == 0) + { + if (field_byte_width == 16) // This case is for long double type. + { + // If structure contains long double type, then it is returned in fp0/fp1 registers. + reg_ctx->ReadRegister (f1_info, f1_value); + f1_value.GetData(f1_data); + + if (target_byte_order == eByteOrderLittle) + { + f0_data.Append(f1_data); + copy_from_extractor = &f0_data; + } + else + { + f1_data.Append(f0_data); + copy_from_extractor = &f1_data; + } + } + else + copy_from_extractor = &f0_data; // This is in f0, copy from register to our result structure + } + else + copy_from_extractor = &f2_data; // This is in f2, copy from register to our result structure + + // Sanity check to avoid crash + if (!copy_from_extractor || field_byte_width > copy_from_extractor->GetByteSize()) + return return_valobj_sp; + + // copy the register contents into our data buffer + copy_from_extractor->CopyByteOrderedData (0, + field_byte_width, + data_sp->GetBytes() + (field_bit_offset/8), + field_byte_width, + target_byte_order); + } + + // The result is in our data buffer. Create a variable object out of it + return_valobj_sp = ValueObjectConstResult::Create (&thread, + return_compiler_type, + ConstString(""), + return_ext); + + return return_valobj_sp; + } + } + + // If we reach here, it means this structure either contains more than two fields or + // it contains at least one non floating point type. + // In that case, all fields are returned in GP return registers. + for (uint32_t idx = 0; idx < num_children; idx++) + { + uint64_t field_bit_offset = 0; + bool is_signed; + uint32_t padding; + + CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); + const size_t field_byte_width = field_compiler_type.GetByteSize(nullptr); + + // if we don't know the size of the field (e.g. invalid type), just bail out + if (field_byte_width == 0) + break; + + uint32_t field_byte_offset = field_bit_offset/8; + + if (field_compiler_type.IsIntegerType (is_signed) + || field_compiler_type.IsPointerType () + || field_compiler_type.IsFloatingPointType (count, is_complex)) + { + padding = field_byte_offset - integer_bytes; + + if (integer_bytes < 8) + { + // We have not yet consumed r2 completely. + if (integer_bytes + field_byte_width + padding <= 8) + { + // This field fits in r2, copy its value from r2 to our result structure + integer_bytes = integer_bytes + field_byte_width + padding; // Increase the consumed bytes. + use_r2 = 1; + } + else + { + // There isn't enough space left in r2 for this field, so this will be in r3. + integer_bytes = integer_bytes + field_byte_width + padding; // Increase the consumed bytes. + use_r3 = 1; + } + } + // We already have consumed at-least 8 bytes that means r2 is done, and this field will be in r3. + // Check if this field can fit in r3. + else if (integer_bytes + field_byte_width + padding <= 16) + { + integer_bytes = integer_bytes + field_byte_width + padding; + use_r3 = 1; + } + else + { + // There isn't any space left for this field, this should not happen as we have already checked + // the overall size is not greater than 16 bytes. For now, return a NULL return value object. + return return_valobj_sp; + } + } + } + // Vector types upto 16 bytes are returned in GP return registers + if (type_flags & eTypeIsVector) + { + if (byte_size <= 8) + use_r2 = 1; + else + { + use_r2 = 1; + use_r3 = 1; + } + } + + if (use_r2) + { + reg_ctx->ReadRegister (r2_info, r2_value); + + const size_t bytes_copied = r2_value.GetAsMemoryData (r2_info, + data_sp->GetBytes(), + r2_info->byte_size, + target_byte_order, + error); + if (bytes_copied != r2_info->byte_size) + return return_valobj_sp; + sucess = 1; + } + if (use_r3) + { + reg_ctx->ReadRegister (r3_info, r3_value); + const size_t bytes_copied = r3_value.GetAsMemoryData (r3_info, + data_sp->GetBytes() + r2_info->byte_size, + r3_info->byte_size, + target_byte_order, + error); + + if (bytes_copied != r3_info->byte_size) + return return_valobj_sp; + sucess = 1; + } + if (sucess) + { + // The result is in our data buffer. Create a variable object out of it + return_valobj_sp = ValueObjectConstResult::Create (&thread, + return_compiler_type, + ConstString(""), + return_ext); + } + return return_valobj_sp; + } + + // Any structure/vector greater than 16 bytes in size is returned in memory. + // The pointer to that memory is returned in r2. + uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0); + + // We have got the address. Create a memory object out of it + return_valobj_sp = ValueObjectMemory::Create (&thread, + "", + Address (mem_address, NULL), + return_compiler_type); } return return_valobj_sp; } @@ -476,17 +718,17 @@ ABISysV_mips64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) UnwindPlan::RowSP row(new UnwindPlan::Row); // Our Call Frame Address is the stack pointer value - row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0); + row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0); // The previous PC is in the RA - row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true); + row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true); unwind_plan.AppendRow (row); // All other registers are the same. unwind_plan.SetSourceName ("mips64 at-func-entry default"); unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); - unwind_plan.SetReturnAddressRegister(gcc_dwarf_r31); + unwind_plan.SetReturnAddressRegister(dwarf_r31); return true; } @@ -498,9 +740,9 @@ ABISysV_mips64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) UnwindPlan::RowSP row(new UnwindPlan::Row); - row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_r29, 0); + row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0); - row->SetRegisterLocationToRegister(gcc_dwarf_pc, gcc_dwarf_r31, true); + row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true); unwind_plan.AppendRow (row); unwind_plan.SetSourceName ("mips64 default unwind plan"); diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h index c37e717e09381..3290331e05a03 100644 --- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h +++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h @@ -21,46 +21,37 @@ class ABISysV_mips64 : public lldb_private::ABI { public: + ~ABISysV_mips64() override = default; - ~ABISysV_mips64() - { - } - - virtual size_t - GetRedZoneSize () const; + size_t + GetRedZoneSize() const override; - virtual bool - PrepareTrivialCall (lldb_private::Thread &thread, - lldb::addr_t sp, - lldb::addr_t functionAddress, - lldb::addr_t returnAddress, - llvm::ArrayRef args) const; + bool + PrepareTrivialCall(lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const override; - virtual bool - GetArgumentValues (lldb_private::Thread &thread, - lldb_private::ValueList &values) const; + bool + GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; - virtual lldb_private::Error - SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); + lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: lldb::ValueObjectSP - GetReturnValueObjectSimple (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const; - -public: - virtual lldb::ValueObjectSP - GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &type) const; + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &type) const override; - virtual bool - CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); + bool + RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; // The SysV mips ABI requires that stack frames be 16 byte aligned. // When there is a trap handler on the stack, e.g. _sigtramp in userland @@ -72,8 +63,8 @@ public: // Whitelisting the trap handlers for user space would be easy (_sigtramp) but // in other environments there can be a large number of different functions // involved in async traps. - virtual bool - CallFrameAddressIsValid (lldb::addr_t cfa) + bool + CallFrameAddressIsValid(lldb::addr_t cfa) override { // Make sure the stack call frame addresses are 8 byte aligned if (cfa & (8ull - 1ull)) @@ -83,8 +74,8 @@ public: return true; } - virtual bool - CodeAddressIsValid (lldb::addr_t pc) + bool + CodeAddressIsValid(lldb::addr_t pc) override { if (pc & (4ull - 1ull)) return false; // Not 4 byte aligned @@ -93,11 +84,13 @@ public: return true; } - virtual const lldb_private::RegisterInfo * - GetRegisterInfoArray (uint32_t &count); + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; + //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -113,21 +106,30 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); - virtual uint32_t - GetPluginVersion(); + lldb_private::ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; protected: void CreateRegisterMapIfNeeded (); + lldb::ValueObjectSP + GetReturnValueObjectSimple(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const; + bool RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); private: - ABISysV_mips64() : lldb_private::ABI() { } // Call CreateInstance instead. + ABISysV_mips64() : + lldb_private::ABI() + { + // Call CreateInstance instead. + } }; -#endif // liblldb_ABI_h_ +#endif // liblldb_ABISysV_mips64_h_ diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp index 08416dc25b08f..f0da18637ba81 100644 --- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp +++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp @@ -20,7 +20,6 @@ #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectRegister.h" #include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Target.h" #include "lldb/Target/Process.h" @@ -34,123 +33,81 @@ using namespace lldb; using namespace lldb_private; -enum gcc_dwarf_regnums +enum dwarf_regnums { - gcc_dwarf_r0 = 0, - gcc_dwarf_r1, - gcc_dwarf_r2, - gcc_dwarf_r3, - gcc_dwarf_r4, - gcc_dwarf_r5, - gcc_dwarf_r6, - gcc_dwarf_r7, - gcc_dwarf_r8, - gcc_dwarf_r9, - gcc_dwarf_r10, - gcc_dwarf_r11, - gcc_dwarf_r12, - gcc_dwarf_r13, - gcc_dwarf_r14, - gcc_dwarf_r15, - gcc_dwarf_r16, - gcc_dwarf_r17, - gcc_dwarf_r18, - gcc_dwarf_r19, - gcc_dwarf_r20, - gcc_dwarf_r21, - gcc_dwarf_r22, - gcc_dwarf_r23, - gcc_dwarf_r24, - gcc_dwarf_r25, - gcc_dwarf_r26, - gcc_dwarf_r27, - gcc_dwarf_r28, - gcc_dwarf_r29, - gcc_dwarf_r30, - gcc_dwarf_r31, - gcc_dwarf_f0, - gcc_dwarf_f1, - gcc_dwarf_f2, - gcc_dwarf_f3, - gcc_dwarf_f4, - gcc_dwarf_f5, - gcc_dwarf_f6, - gcc_dwarf_f7, - gcc_dwarf_f8, - gcc_dwarf_f9, - gcc_dwarf_f10, - gcc_dwarf_f11, - gcc_dwarf_f12, - gcc_dwarf_f13, - gcc_dwarf_f14, - gcc_dwarf_f15, - gcc_dwarf_f16, - gcc_dwarf_f17, - gcc_dwarf_f18, - gcc_dwarf_f19, - gcc_dwarf_f20, - gcc_dwarf_f21, - gcc_dwarf_f22, - gcc_dwarf_f23, - gcc_dwarf_f24, - gcc_dwarf_f25, - gcc_dwarf_f26, - gcc_dwarf_f27, - gcc_dwarf_f28, - gcc_dwarf_f29, - gcc_dwarf_f30, - gcc_dwarf_f31, - gcc_dwarf_cr, - gcc_dwarf_fpscr, - gcc_dwarf_xer = 101, - gcc_dwarf_lr = 108, - gcc_dwarf_ctr, - gcc_dwarf_pc, - gcc_dwarf_cfa, + dwarf_r0 = 0, + dwarf_r1, + dwarf_r2, + dwarf_r3, + dwarf_r4, + dwarf_r5, + dwarf_r6, + dwarf_r7, + dwarf_r8, + dwarf_r9, + dwarf_r10, + dwarf_r11, + dwarf_r12, + dwarf_r13, + dwarf_r14, + dwarf_r15, + dwarf_r16, + dwarf_r17, + dwarf_r18, + dwarf_r19, + dwarf_r20, + dwarf_r21, + dwarf_r22, + dwarf_r23, + dwarf_r24, + dwarf_r25, + dwarf_r26, + dwarf_r27, + dwarf_r28, + dwarf_r29, + dwarf_r30, + dwarf_r31, + dwarf_f0, + dwarf_f1, + dwarf_f2, + dwarf_f3, + dwarf_f4, + dwarf_f5, + dwarf_f6, + dwarf_f7, + dwarf_f8, + dwarf_f9, + dwarf_f10, + dwarf_f11, + dwarf_f12, + dwarf_f13, + dwarf_f14, + dwarf_f15, + dwarf_f16, + dwarf_f17, + dwarf_f18, + dwarf_f19, + dwarf_f20, + dwarf_f21, + dwarf_f22, + dwarf_f23, + dwarf_f24, + dwarf_f25, + dwarf_f26, + dwarf_f27, + dwarf_f28, + dwarf_f29, + dwarf_f30, + dwarf_f31, + dwarf_cr, + dwarf_fpscr, + dwarf_xer = 101, + dwarf_lr = 108, + dwarf_ctr, + dwarf_pc, + dwarf_cfa, }; -enum gdb_regnums -{ - gdb_r0 = 0, - gdb_r1, - gdb_r2, - gdb_r3, - gdb_r4, - gdb_r5, - gdb_r6, - gdb_r7, - gdb_r8, - gdb_r9, - gdb_r10, - gdb_r11, - gdb_r12, - gdb_r13, - gdb_r14, - gdb_r15, - gdb_r16, - gdb_r17, - gdb_r18, - gdb_r19, - gdb_r20, - gdb_r21, - gdb_r22, - gdb_r23, - gdb_r24, - gdb_r25, - gdb_r26, - gdb_r27, - gdb_r28, - gdb_r29, - gdb_r30, - gdb_r31, - gdb_lr, - gdb_cr, - gdb_xer, - gdb_ctr, - gdb_pc, -}; - - // Note that the size and offset will be updated by platform-specific classes. #define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ { #reg, alt, 8, 0, eEncodingUint, \ @@ -158,45 +115,45 @@ enum gdb_regnums static const RegisterInfo g_register_infos[] = { - // General purpose registers. GCC, DWARF, Generic, GDB - DEFINE_GPR(r0, NULL, gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0), - DEFINE_GPR(r1, "sp", gcc_dwarf_r1, gcc_dwarf_r1, LLDB_REGNUM_GENERIC_SP, gdb_r1), - DEFINE_GPR(r2, NULL, gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2), - DEFINE_GPR(r3, "arg1",gcc_dwarf_r3, gcc_dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, gdb_r3), - DEFINE_GPR(r4, "arg2",gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,gdb_r4), - DEFINE_GPR(r5, "arg3",gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, gdb_r5), - DEFINE_GPR(r6, "arg4",gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, gdb_r6), - DEFINE_GPR(r7, "arg5",gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, gdb_r7), - DEFINE_GPR(r8, "arg6",gcc_dwarf_r8, gcc_dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, gdb_r8), - DEFINE_GPR(r9, "arg7",gcc_dwarf_r9, gcc_dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, gdb_r9), - DEFINE_GPR(r10, "arg8",gcc_dwarf_r10, gcc_dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, gdb_r10), - DEFINE_GPR(r11, NULL, gcc_dwarf_r11, gcc_dwarf_r11, LLDB_INVALID_REGNUM, gdb_r11), - DEFINE_GPR(r12, NULL, gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12), - DEFINE_GPR(r13, NULL, gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13), - DEFINE_GPR(r14, NULL, gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14), - DEFINE_GPR(r15, NULL, gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15), - DEFINE_GPR(r16, NULL, gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16), - DEFINE_GPR(r17, NULL, gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17), - DEFINE_GPR(r18, NULL, gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18), - DEFINE_GPR(r19, NULL, gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19), - DEFINE_GPR(r20, NULL, gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20), - DEFINE_GPR(r21, NULL, gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21), - DEFINE_GPR(r22, NULL, gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22), - DEFINE_GPR(r23, NULL, gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23), - DEFINE_GPR(r24, NULL, gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24), - DEFINE_GPR(r25, NULL, gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25), - DEFINE_GPR(r26, NULL, gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26), - DEFINE_GPR(r27, NULL, gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27), - DEFINE_GPR(r28, NULL, gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28), - DEFINE_GPR(r29, NULL, gcc_dwarf_r29, gcc_dwarf_r29, LLDB_INVALID_REGNUM, gdb_r29), - DEFINE_GPR(r30, NULL, gcc_dwarf_r30, gcc_dwarf_r30, LLDB_INVALID_REGNUM, gdb_r30), - DEFINE_GPR(r31, NULL, gcc_dwarf_r31, gcc_dwarf_r31, LLDB_INVALID_REGNUM, gdb_r31), - DEFINE_GPR(lr, "lr", gcc_dwarf_lr, gcc_dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_lr), - DEFINE_GPR(cr, "cr", gcc_dwarf_cr, gcc_dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), - DEFINE_GPR(xer, "xer", gcc_dwarf_xer, gcc_dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(ctr, "ctr", gcc_dwarf_ctr, gcc_dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(pc, "pc", gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), - { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cfa, gcc_dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL}, + // General purpose registers. eh_frame, DWARF, Generic, Process Plugin + DEFINE_GPR(r0, NULL, dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r1, "sp", dwarf_r1, dwarf_r1, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), + DEFINE_GPR(r2, NULL, dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r3, "arg1",dwarf_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), + DEFINE_GPR(r4, "arg2",dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,LLDB_INVALID_REGNUM), + DEFINE_GPR(r5, "arg3",dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), + DEFINE_GPR(r6, "arg4",dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), + DEFINE_GPR(r7, "arg5",dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM), + DEFINE_GPR(r8, "arg6",dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM), + DEFINE_GPR(r9, "arg7",dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM), + DEFINE_GPR(r10, "arg8",dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM), + DEFINE_GPR(r11, NULL, dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r12, NULL, dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r13, NULL, dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r14, NULL, dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r15, NULL, dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r16, NULL, dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r17, NULL, dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r18, NULL, dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r19, NULL, dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r20, NULL, dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r21, NULL, dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r22, NULL, dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r23, NULL, dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r24, NULL, dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r25, NULL, dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r26, NULL, dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r27, NULL, dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r28, NULL, dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r29, NULL, dwarf_r29, dwarf_r29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r30, NULL, dwarf_r30, dwarf_r30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r31, NULL, dwarf_r31, dwarf_r31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(lr, "lr", dwarf_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM), + DEFINE_GPR(cr, "cr", dwarf_cr, dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), + DEFINE_GPR(xer, "xer", dwarf_xer, dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ctr, "ctr", dwarf_ctr, dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(pc, "pc", dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), + { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_cfa, dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL}, }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -436,25 +393,25 @@ ABISysV_ppc::GetArgumentValues (Thread &thread, // We currently only support extracting values with Clang QualTypes. // Do we care about others? - ClangASTType clang_type = value->GetClangType(); - if (!clang_type) + CompilerType compiler_type = value->GetCompilerType(); + if (!compiler_type) return false; bool is_signed; - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), is_signed, thread, argument_register_ids, current_argument_register, current_stack_argument); } - else if (clang_type.IsPointerType ()) + else if (compiler_type.IsPointerType ()) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), false, thread, argument_register_ids, @@ -476,8 +433,8 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec return error; } - ClangASTType clang_type = new_value_sp->GetClangType(); - if (!clang_type) + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { error.SetErrorString ("Null clang type for return value."); return error; @@ -492,7 +449,7 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) + if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); @@ -518,13 +475,13 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec } } - else if (clang_type.IsFloatingPointType (count, is_complex)) + else if (compiler_type.IsFloatingPointType (count, is_complex)) { if (is_complex) error.SetErrorString ("We don't support returning complex values at present"); else { - size_t bit_width = clang_type.GetBitSize(frame_sp.get()); + size_t bit_width = compiler_type.GetBitSize(frame_sp.get()); if (bit_width <= 64) { DataExtractor data; @@ -563,22 +520,22 @@ ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjec ValueObjectSP ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, - ClangASTType &return_clang_type) const + CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; Value value; - if (!return_clang_type) + if (!return_compiler_type) return return_valobj_sp; //value.SetContext (Value::eContextTypeClangType, return_value_type); - value.SetClangType (return_clang_type); + value.SetCompilerType (return_compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; - const uint32_t type_flags = return_clang_type.GetTypeInfo (); + const uint32_t type_flags = return_compiler_type.GetTypeInfo (); if (type_flags & eTypeIsScalar) { value.SetValueType(Value::eValueTypeScalar); @@ -588,7 +545,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, { // Extract the register context so we can read arguments from registers - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0); const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (byte_size) @@ -637,7 +594,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, } else { - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); if (byte_size <= sizeof(long double)) { const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); @@ -681,7 +638,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, } else if (type_flags & eTypeIsVector) { - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); if (byte_size > 0) { @@ -709,7 +666,7 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, byte_order, process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); return_valobj_sp = ValueObjectConstResult::Create (&thread, - return_clang_type, + return_compiler_type, ConstString(""), data); } @@ -724,15 +681,15 @@ ABISysV_ppc::GetReturnValueObjectSimple (Thread &thread, } ValueObjectSP -ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; - if (!return_clang_type) + if (!return_compiler_type) return return_valobj_sp; ExecutionContext exe_ctx (thread.shared_from_this()); - return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type); + return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type); if (return_valobj_sp) return return_valobj_sp; @@ -740,8 +697,8 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan if (!reg_ctx_sp) return return_valobj_sp; - const size_t bit_width = return_clang_type.GetBitSize(&thread); - if (return_clang_type.IsAggregateType()) + const size_t bit_width = return_compiler_type.GetBitSize(&thread); + if (return_compiler_type.IsAggregateType()) { Target *target = exe_ctx.GetTargetPtr(); bool is_memory = true; @@ -768,7 +725,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan uint32_t fp_bytes = 0; // Tracks how much of the xmm registers we've consumed so far uint32_t integer_bytes = 0; // Tracks how much of the r3/rds registers we've consumed so far - const uint32_t num_children = return_clang_type.GetNumFields (); + const uint32_t num_children = return_compiler_type.GetNumFields (); // Since we are in the small struct regime, assume we are not in memory. is_memory = false; @@ -781,8 +738,8 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan bool is_complex; uint32_t count; - ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); - const size_t field_bit_width = field_clang_type.GetBitSize(&thread); + CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); + const size_t field_bit_width = field_compiler_type.GetBitSize(&thread); // If there are any unaligned fields, this is stored in memory. if (field_bit_offset % field_bit_width != 0) @@ -798,7 +755,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan DataExtractor *copy_from_extractor = NULL; uint32_t copy_from_offset = 0; - if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ()) + if (field_compiler_type.IsIntegerType (is_signed) || field_compiler_type.IsPointerType ()) { if (integer_bytes < 8) { @@ -831,7 +788,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan return return_valobj_sp; } } - else if (field_clang_type.IsFloatingPointType (count, is_complex)) + else if (field_compiler_type.IsFloatingPointType (count, is_complex)) { // Structs with long doubles are always passed in memory. if (field_bit_width == 128) @@ -858,12 +815,12 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan else { uint64_t next_field_bit_offset = 0; - ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1, + CompilerType next_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx + 1, name, &next_field_bit_offset, NULL, NULL); - if (next_field_clang_type.IsIntegerType (is_signed)) + if (next_field_compiler_type.IsIntegerType (is_signed)) in_gpr = true; else { @@ -882,12 +839,12 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan else { uint64_t prev_field_bit_offset = 0; - ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1, + CompilerType prev_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx - 1, name, &prev_field_bit_offset, NULL, NULL); - if (prev_field_clang_type.IsIntegerType (is_signed)) + if (prev_field_compiler_type.IsIntegerType (is_signed)) in_gpr = true; else { @@ -946,7 +903,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan { // The result is in our data buffer. Let's make a variable object out of it: return_valobj_sp = ValueObjectConstResult::Create (&thread, - return_clang_type, + return_compiler_type, ConstString(""), return_ext); } @@ -965,7 +922,7 @@ ABISysV_ppc::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clan return_valobj_sp = ValueObjectMemory::Create (&thread, "", Address (storage_addr, NULL), - return_clang_type); + return_compiler_type); } } @@ -978,9 +935,9 @@ ABISysV_ppc::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.Clear(); unwind_plan.SetRegisterKind (eRegisterKindDWARF); - uint32_t lr_reg_num = gcc_dwarf_lr; - uint32_t sp_reg_num = gcc_dwarf_r1; - uint32_t pc_reg_num = gcc_dwarf_pc; + uint32_t lr_reg_num = dwarf_lr; + uint32_t sp_reg_num = dwarf_r1; + uint32_t pc_reg_num = dwarf_pc; UnwindPlan::RowSP row(new UnwindPlan::Row); @@ -1005,8 +962,8 @@ ABISysV_ppc::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.Clear(); unwind_plan.SetRegisterKind (eRegisterKindDWARF); - uint32_t sp_reg_num = gcc_dwarf_r1; - uint32_t pc_reg_num = gcc_dwarf_lr; + uint32_t sp_reg_num = dwarf_r1; + uint32_t pc_reg_num = dwarf_lr; UnwindPlan::RowSP row(new UnwindPlan::Row); @@ -1020,7 +977,7 @@ ABISysV_ppc::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.SetSourceName ("ppc default unwind plan"); unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); - unwind_plan.SetReturnAddressRegister(gcc_dwarf_lr); + unwind_plan.SetReturnAddressRegister(dwarf_lr); return true; } diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h index a7aad300e2979..99ee755631c22 100644 --- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h +++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h @@ -21,52 +21,37 @@ class ABISysV_ppc : public lldb_private::ABI { public: + ~ABISysV_ppc() override = default; - ~ABISysV_ppc() - { - } + size_t + GetRedZoneSize() const override; - virtual size_t - GetRedZoneSize () const; - - virtual bool - PrepareTrivialCall (lldb_private::Thread &thread, - lldb::addr_t sp, - lldb::addr_t functionAddress, - lldb::addr_t returnAddress, - llvm::ArrayRef args) const; + bool + PrepareTrivialCall(lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const override; - virtual bool - GetArgumentValues (lldb_private::Thread &thread, - lldb_private::ValueList &values) const; + bool + GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; - virtual lldb_private::Error - SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); + lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: lldb::ValueObjectSP - GetReturnValueObjectSimple (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const; - -public: - virtual lldb::ValueObjectSP - GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &type) const; + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &type) const override; - virtual bool - CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); - - virtual bool - StackUsesFrames () - { - return true; - } + bool + RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; // The SysV ppc ABI requires that stack frames be 16 byte aligned. // When there is a trap handler on the stack, e.g. _sigtramp in userland @@ -78,8 +63,8 @@ public: // Whitelisting the trap handlers for user space would be easy (_sigtramp) but // in other environments there can be a large number of different functions // involved in async traps. - virtual bool - CallFrameAddressIsValid (lldb::addr_t cfa) + bool + CallFrameAddressIsValid(lldb::addr_t cfa) override { // Make sure the stack call frame addresses are 8 byte aligned if (cfa & (8ull - 1ull)) @@ -89,25 +74,21 @@ public: return true; } - virtual bool - CodeAddressIsValid (lldb::addr_t pc) + bool + CodeAddressIsValid(lldb::addr_t pc) override { // We have a 64 bit address space, so anything is valid as opcodes // aren't fixed width... return true; } - virtual bool - FunctionCallsChangeCFA () - { - return true; - } + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; - virtual const lldb_private::RegisterInfo * - GetRegisterInfoArray (uint32_t &count); //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -123,21 +104,30 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); - virtual uint32_t - GetPluginVersion(); + lldb_private::ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; protected: void CreateRegisterMapIfNeeded (); + lldb::ValueObjectSP + GetReturnValueObjectSimple(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const; + bool RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); private: - ABISysV_ppc() : lldb_private::ABI() { } // Call CreateInstance instead. + ABISysV_ppc() : + lldb_private::ABI() + { + // Call CreateInstance instead. + } }; -#endif // liblldb_ABI_h_ +#endif // liblldb_ABISysV_ppc_h_ diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp index eb0d7c00070f4..96c54ce97eec2 100644 --- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp +++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp @@ -20,7 +20,6 @@ #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectRegister.h" #include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Target.h" #include "lldb/Target/Process.h" @@ -34,120 +33,79 @@ using namespace lldb; using namespace lldb_private; -enum gcc_dwarf_regnums +enum dwarf_regnums { - gcc_dwarf_r0 = 0, - gcc_dwarf_r1, - gcc_dwarf_r2, - gcc_dwarf_r3, - gcc_dwarf_r4, - gcc_dwarf_r5, - gcc_dwarf_r6, - gcc_dwarf_r7, - gcc_dwarf_r8, - gcc_dwarf_r9, - gcc_dwarf_r10, - gcc_dwarf_r11, - gcc_dwarf_r12, - gcc_dwarf_r13, - gcc_dwarf_r14, - gcc_dwarf_r15, - gcc_dwarf_r16, - gcc_dwarf_r17, - gcc_dwarf_r18, - gcc_dwarf_r19, - gcc_dwarf_r20, - gcc_dwarf_r21, - gcc_dwarf_r22, - gcc_dwarf_r23, - gcc_dwarf_r24, - gcc_dwarf_r25, - gcc_dwarf_r26, - gcc_dwarf_r27, - gcc_dwarf_r28, - gcc_dwarf_r29, - gcc_dwarf_r30, - gcc_dwarf_r31, - gcc_dwarf_f0, - gcc_dwarf_f1, - gcc_dwarf_f2, - gcc_dwarf_f3, - gcc_dwarf_f4, - gcc_dwarf_f5, - gcc_dwarf_f6, - gcc_dwarf_f7, - gcc_dwarf_f8, - gcc_dwarf_f9, - gcc_dwarf_f10, - gcc_dwarf_f11, - gcc_dwarf_f12, - gcc_dwarf_f13, - gcc_dwarf_f14, - gcc_dwarf_f15, - gcc_dwarf_f16, - gcc_dwarf_f17, - gcc_dwarf_f18, - gcc_dwarf_f19, - gcc_dwarf_f20, - gcc_dwarf_f21, - gcc_dwarf_f22, - gcc_dwarf_f23, - gcc_dwarf_f24, - gcc_dwarf_f25, - gcc_dwarf_f26, - gcc_dwarf_f27, - gcc_dwarf_f28, - gcc_dwarf_f29, - gcc_dwarf_f30, - gcc_dwarf_f31, - gcc_dwarf_cr, - gcc_dwarf_fpscr, - gcc_dwarf_xer = 101, - gcc_dwarf_lr = 108, - gcc_dwarf_ctr, - gcc_dwarf_pc, - gcc_dwarf_cfa, -}; - -enum gdb_regnums -{ - gdb_r0 = 0, - gdb_r1, - gdb_r2, - gdb_r3, - gdb_r4, - gdb_r5, - gdb_r6, - gdb_r7, - gdb_r8, - gdb_r9, - gdb_r10, - gdb_r11, - gdb_r12, - gdb_r13, - gdb_r14, - gdb_r15, - gdb_r16, - gdb_r17, - gdb_r18, - gdb_r19, - gdb_r20, - gdb_r21, - gdb_r22, - gdb_r23, - gdb_r24, - gdb_r25, - gdb_r26, - gdb_r27, - gdb_r28, - gdb_r29, - gdb_r30, - gdb_r31, - gdb_lr, - gdb_cr, - gdb_xer, - gdb_ctr, - gdb_pc, + dwarf_r0 = 0, + dwarf_r1, + dwarf_r2, + dwarf_r3, + dwarf_r4, + dwarf_r5, + dwarf_r6, + dwarf_r7, + dwarf_r8, + dwarf_r9, + dwarf_r10, + dwarf_r11, + dwarf_r12, + dwarf_r13, + dwarf_r14, + dwarf_r15, + dwarf_r16, + dwarf_r17, + dwarf_r18, + dwarf_r19, + dwarf_r20, + dwarf_r21, + dwarf_r22, + dwarf_r23, + dwarf_r24, + dwarf_r25, + dwarf_r26, + dwarf_r27, + dwarf_r28, + dwarf_r29, + dwarf_r30, + dwarf_r31, + dwarf_f0, + dwarf_f1, + dwarf_f2, + dwarf_f3, + dwarf_f4, + dwarf_f5, + dwarf_f6, + dwarf_f7, + dwarf_f8, + dwarf_f9, + dwarf_f10, + dwarf_f11, + dwarf_f12, + dwarf_f13, + dwarf_f14, + dwarf_f15, + dwarf_f16, + dwarf_f17, + dwarf_f18, + dwarf_f19, + dwarf_f20, + dwarf_f21, + dwarf_f22, + dwarf_f23, + dwarf_f24, + dwarf_f25, + dwarf_f26, + dwarf_f27, + dwarf_f28, + dwarf_f29, + dwarf_f30, + dwarf_f31, + dwarf_cr, + dwarf_fpscr, + dwarf_xer = 101, + dwarf_lr = 108, + dwarf_ctr, + dwarf_pc, + dwarf_cfa, }; @@ -158,45 +116,45 @@ enum gdb_regnums static const RegisterInfo g_register_infos[] = { - // General purpose registers. GCC, DWARF, Generic, GDB - DEFINE_GPR(r0, NULL, gcc_dwarf_r0, gcc_dwarf_r0, LLDB_INVALID_REGNUM, gdb_r0), - DEFINE_GPR(r1, "sp", gcc_dwarf_r1, gcc_dwarf_r1, LLDB_REGNUM_GENERIC_SP, gdb_r1), - DEFINE_GPR(r2, NULL, gcc_dwarf_r2, gcc_dwarf_r2, LLDB_INVALID_REGNUM, gdb_r2), - DEFINE_GPR(r3, "arg1",gcc_dwarf_r3, gcc_dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, gdb_r3), - DEFINE_GPR(r4, "arg2",gcc_dwarf_r4, gcc_dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,gdb_r4), - DEFINE_GPR(r5, "arg3",gcc_dwarf_r5, gcc_dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, gdb_r5), - DEFINE_GPR(r6, "arg4",gcc_dwarf_r6, gcc_dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, gdb_r6), - DEFINE_GPR(r7, "arg5",gcc_dwarf_r7, gcc_dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, gdb_r7), - DEFINE_GPR(r8, "arg6",gcc_dwarf_r8, gcc_dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, gdb_r8), - DEFINE_GPR(r9, "arg7",gcc_dwarf_r9, gcc_dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, gdb_r9), - DEFINE_GPR(r10, "arg8",gcc_dwarf_r10, gcc_dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, gdb_r10), - DEFINE_GPR(r11, NULL, gcc_dwarf_r11, gcc_dwarf_r11, LLDB_INVALID_REGNUM, gdb_r11), - DEFINE_GPR(r12, NULL, gcc_dwarf_r12, gcc_dwarf_r12, LLDB_INVALID_REGNUM, gdb_r12), - DEFINE_GPR(r13, NULL, gcc_dwarf_r13, gcc_dwarf_r13, LLDB_INVALID_REGNUM, gdb_r13), - DEFINE_GPR(r14, NULL, gcc_dwarf_r14, gcc_dwarf_r14, LLDB_INVALID_REGNUM, gdb_r14), - DEFINE_GPR(r15, NULL, gcc_dwarf_r15, gcc_dwarf_r15, LLDB_INVALID_REGNUM, gdb_r15), - DEFINE_GPR(r16, NULL, gcc_dwarf_r16, gcc_dwarf_r16, LLDB_INVALID_REGNUM, gdb_r16), - DEFINE_GPR(r17, NULL, gcc_dwarf_r17, gcc_dwarf_r17, LLDB_INVALID_REGNUM, gdb_r17), - DEFINE_GPR(r18, NULL, gcc_dwarf_r18, gcc_dwarf_r18, LLDB_INVALID_REGNUM, gdb_r18), - DEFINE_GPR(r19, NULL, gcc_dwarf_r19, gcc_dwarf_r19, LLDB_INVALID_REGNUM, gdb_r19), - DEFINE_GPR(r20, NULL, gcc_dwarf_r20, gcc_dwarf_r20, LLDB_INVALID_REGNUM, gdb_r20), - DEFINE_GPR(r21, NULL, gcc_dwarf_r21, gcc_dwarf_r21, LLDB_INVALID_REGNUM, gdb_r21), - DEFINE_GPR(r22, NULL, gcc_dwarf_r22, gcc_dwarf_r22, LLDB_INVALID_REGNUM, gdb_r22), - DEFINE_GPR(r23, NULL, gcc_dwarf_r23, gcc_dwarf_r23, LLDB_INVALID_REGNUM, gdb_r23), - DEFINE_GPR(r24, NULL, gcc_dwarf_r24, gcc_dwarf_r24, LLDB_INVALID_REGNUM, gdb_r24), - DEFINE_GPR(r25, NULL, gcc_dwarf_r25, gcc_dwarf_r25, LLDB_INVALID_REGNUM, gdb_r25), - DEFINE_GPR(r26, NULL, gcc_dwarf_r26, gcc_dwarf_r26, LLDB_INVALID_REGNUM, gdb_r26), - DEFINE_GPR(r27, NULL, gcc_dwarf_r27, gcc_dwarf_r27, LLDB_INVALID_REGNUM, gdb_r27), - DEFINE_GPR(r28, NULL, gcc_dwarf_r28, gcc_dwarf_r28, LLDB_INVALID_REGNUM, gdb_r28), - DEFINE_GPR(r29, NULL, gcc_dwarf_r29, gcc_dwarf_r29, LLDB_INVALID_REGNUM, gdb_r29), - DEFINE_GPR(r30, NULL, gcc_dwarf_r30, gcc_dwarf_r30, LLDB_INVALID_REGNUM, gdb_r30), - DEFINE_GPR(r31, NULL, gcc_dwarf_r31, gcc_dwarf_r31, LLDB_INVALID_REGNUM, gdb_r31), - DEFINE_GPR(lr, "lr", gcc_dwarf_lr, gcc_dwarf_lr, LLDB_REGNUM_GENERIC_RA, gdb_lr), - DEFINE_GPR(cr, "cr", gcc_dwarf_cr, gcc_dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), - DEFINE_GPR(xer, "xer", gcc_dwarf_xer, gcc_dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(ctr, "ctr", gcc_dwarf_ctr, gcc_dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), - DEFINE_GPR(pc, "pc", gcc_dwarf_pc, gcc_dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), - { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { gcc_dwarf_cfa, gcc_dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL}, + // General purpose registers. eh_frame, DWARF, Generic, Process Plugin + DEFINE_GPR(r0, NULL, dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r1, "sp", dwarf_r1, dwarf_r1, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), + DEFINE_GPR(r2, NULL, dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r3, "arg1",dwarf_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), + DEFINE_GPR(r4, "arg2",dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG2 ,LLDB_INVALID_REGNUM), + DEFINE_GPR(r5, "arg3",dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), + DEFINE_GPR(r6, "arg4",dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), + DEFINE_GPR(r7, "arg5",dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM), + DEFINE_GPR(r8, "arg6",dwarf_r8, dwarf_r8, LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM), + DEFINE_GPR(r9, "arg7",dwarf_r9, dwarf_r9, LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM), + DEFINE_GPR(r10, "arg8",dwarf_r10, dwarf_r10, LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM), + DEFINE_GPR(r11, NULL, dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r12, NULL, dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r13, NULL, dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r14, NULL, dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r15, NULL, dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r16, NULL, dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r17, NULL, dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r18, NULL, dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r19, NULL, dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r20, NULL, dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r21, NULL, dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r22, NULL, dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r23, NULL, dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r24, NULL, dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r25, NULL, dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r26, NULL, dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r27, NULL, dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r28, NULL, dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r29, NULL, dwarf_r29, dwarf_r29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r30, NULL, dwarf_r30, dwarf_r30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(r31, NULL, dwarf_r31, dwarf_r31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(lr, "lr", dwarf_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM), + DEFINE_GPR(cr, "cr", dwarf_cr, dwarf_cr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), + DEFINE_GPR(xer, "xer", dwarf_xer, dwarf_xer, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(ctr, "ctr", dwarf_ctr, dwarf_ctr, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), + DEFINE_GPR(pc, "pc", dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), + { NULL, NULL, 8, 0, eEncodingUint, eFormatHex, { dwarf_cfa, dwarf_cfa, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, NULL, NULL}, }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -436,25 +394,25 @@ ABISysV_ppc64::GetArgumentValues (Thread &thread, // We currently only support extracting values with Clang QualTypes. // Do we care about others? - ClangASTType clang_type = value->GetClangType(); - if (!clang_type) + CompilerType compiler_type = value->GetCompilerType(); + if (!compiler_type) return false; bool is_signed; - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), is_signed, thread, argument_register_ids, current_argument_register, current_stack_argument); } - else if (clang_type.IsPointerType ()) + else if (compiler_type.IsPointerType ()) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), false, thread, argument_register_ids, @@ -476,8 +434,8 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj return error; } - ClangASTType clang_type = new_value_sp->GetClangType(); - if (!clang_type) + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { error.SetErrorString ("Null clang type for return value."); return error; @@ -492,7 +450,7 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) + if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); @@ -518,13 +476,13 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj } } - else if (clang_type.IsFloatingPointType (count, is_complex)) + else if (compiler_type.IsFloatingPointType (count, is_complex)) { if (is_complex) error.SetErrorString ("We don't support returning complex values at present"); else { - size_t bit_width = clang_type.GetBitSize(frame_sp.get()); + size_t bit_width = compiler_type.GetBitSize(frame_sp.get()); if (bit_width <= 64) { DataExtractor data; @@ -563,22 +521,22 @@ ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObj ValueObjectSP ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, - ClangASTType &return_clang_type) const + CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; Value value; - if (!return_clang_type) + if (!return_compiler_type) return return_valobj_sp; //value.SetContext (Value::eContextTypeClangType, return_value_type); - value.SetClangType (return_clang_type); + value.SetCompilerType (return_compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; - const uint32_t type_flags = return_clang_type.GetTypeInfo (); + const uint32_t type_flags = return_compiler_type.GetTypeInfo (); if (type_flags & eTypeIsScalar) { value.SetValueType(Value::eValueTypeScalar); @@ -588,7 +546,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, { // Extract the register context so we can read arguments from registers - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r3", 0), 0); const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (byte_size) @@ -637,7 +595,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, } else { - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); if (byte_size <= sizeof(long double)) { const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); @@ -681,7 +639,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, } else if (type_flags & eTypeIsVector) { - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); if (byte_size > 0) { @@ -709,7 +667,7 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, byte_order, process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); return_valobj_sp = ValueObjectConstResult::Create (&thread, - return_clang_type, + return_compiler_type, ConstString(""), data); } @@ -724,15 +682,15 @@ ABISysV_ppc64::GetReturnValueObjectSimple (Thread &thread, } ValueObjectSP -ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; - if (!return_clang_type) + if (!return_compiler_type) return return_valobj_sp; ExecutionContext exe_ctx (thread.shared_from_this()); - return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type); + return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type); if (return_valobj_sp) return return_valobj_sp; @@ -740,8 +698,8 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl if (!reg_ctx_sp) return return_valobj_sp; - const size_t bit_width = return_clang_type.GetBitSize(&thread); - if (return_clang_type.IsAggregateType()) + const size_t bit_width = return_compiler_type.GetBitSize(&thread); + if (return_compiler_type.IsAggregateType()) { Target *target = exe_ctx.GetTargetPtr(); bool is_memory = true; @@ -768,7 +726,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl uint32_t fp_bytes = 0; // Tracks how much of the xmm registers we've consumed so far uint32_t integer_bytes = 0; // Tracks how much of the r3/rds registers we've consumed so far - const uint32_t num_children = return_clang_type.GetNumFields (); + const uint32_t num_children = return_compiler_type.GetNumFields (); // Since we are in the small struct regime, assume we are not in memory. is_memory = false; @@ -781,8 +739,8 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl bool is_complex; uint32_t count; - ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); - const size_t field_bit_width = field_clang_type.GetBitSize(&thread); + CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); + const size_t field_bit_width = field_compiler_type.GetBitSize(&thread); // If there are any unaligned fields, this is stored in memory. if (field_bit_offset % field_bit_width != 0) @@ -798,7 +756,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl DataExtractor *copy_from_extractor = NULL; uint32_t copy_from_offset = 0; - if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ()) + if (field_compiler_type.IsIntegerType (is_signed) || field_compiler_type.IsPointerType ()) { if (integer_bytes < 8) { @@ -831,7 +789,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl return return_valobj_sp; } } - else if (field_clang_type.IsFloatingPointType (count, is_complex)) + else if (field_compiler_type.IsFloatingPointType (count, is_complex)) { // Structs with long doubles are always passed in memory. if (field_bit_width == 128) @@ -858,12 +816,12 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl else { uint64_t next_field_bit_offset = 0; - ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1, + CompilerType next_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx + 1, name, &next_field_bit_offset, NULL, NULL); - if (next_field_clang_type.IsIntegerType (is_signed)) + if (next_field_compiler_type.IsIntegerType (is_signed)) in_gpr = true; else { @@ -882,12 +840,12 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl else { uint64_t prev_field_bit_offset = 0; - ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1, + CompilerType prev_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx - 1, name, &prev_field_bit_offset, NULL, NULL); - if (prev_field_clang_type.IsIntegerType (is_signed)) + if (prev_field_compiler_type.IsIntegerType (is_signed)) in_gpr = true; else { @@ -946,7 +904,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl { // The result is in our data buffer. Let's make a variable object out of it: return_valobj_sp = ValueObjectConstResult::Create (&thread, - return_clang_type, + return_compiler_type, ConstString(""), return_ext); } @@ -965,7 +923,7 @@ ABISysV_ppc64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_cl return_valobj_sp = ValueObjectMemory::Create (&thread, "", Address (storage_addr, NULL), - return_clang_type); + return_compiler_type); } } @@ -978,9 +936,9 @@ ABISysV_ppc64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.Clear(); unwind_plan.SetRegisterKind (eRegisterKindDWARF); - uint32_t lr_reg_num = gcc_dwarf_lr; - uint32_t sp_reg_num = gcc_dwarf_r1; - uint32_t pc_reg_num = gcc_dwarf_pc; + uint32_t lr_reg_num = dwarf_lr; + uint32_t sp_reg_num = dwarf_r1; + uint32_t pc_reg_num = dwarf_pc; UnwindPlan::RowSP row(new UnwindPlan::Row); @@ -1005,8 +963,8 @@ ABISysV_ppc64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.Clear(); unwind_plan.SetRegisterKind (eRegisterKindDWARF); - uint32_t sp_reg_num = gcc_dwarf_r1; - uint32_t pc_reg_num = gcc_dwarf_lr; + uint32_t sp_reg_num = dwarf_r1; + uint32_t pc_reg_num = dwarf_lr; UnwindPlan::RowSP row(new UnwindPlan::Row); @@ -1015,13 +973,13 @@ ABISysV_ppc64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * 2, true); row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true); - row->SetRegisterLocationToAtCFAPlusOffset(gcc_dwarf_cr, ptr_size, true); + row->SetRegisterLocationToAtCFAPlusOffset(dwarf_cr, ptr_size, true); unwind_plan.AppendRow (row); unwind_plan.SetSourceName ("ppc64 default unwind plan"); unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo); - unwind_plan.SetReturnAddressRegister(gcc_dwarf_lr); + unwind_plan.SetReturnAddressRegister(dwarf_lr); return true; } diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h index d77cb9f1efe3b..b87f7938d5449 100644 --- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h +++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h @@ -21,52 +21,37 @@ class ABISysV_ppc64 : public lldb_private::ABI { public: + ~ABISysV_ppc64() override = default; - ~ABISysV_ppc64() - { - } + size_t + GetRedZoneSize() const override; - virtual size_t - GetRedZoneSize () const; - - virtual bool - PrepareTrivialCall (lldb_private::Thread &thread, - lldb::addr_t sp, - lldb::addr_t functionAddress, - lldb::addr_t returnAddress, - llvm::ArrayRef args) const; + bool + PrepareTrivialCall(lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const override; - virtual bool - GetArgumentValues (lldb_private::Thread &thread, - lldb_private::ValueList &values) const; + bool + GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; - virtual lldb_private::Error - SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); + lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: lldb::ValueObjectSP - GetReturnValueObjectSimple (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const; - -public: - virtual lldb::ValueObjectSP - GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &type) const; + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &type) const override; - virtual bool - CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); - - virtual bool - StackUsesFrames () - { - return true; - } + bool + RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; // The SysV ppc64 ABI requires that stack frames be 16 byte aligned. // When there is a trap handler on the stack, e.g. _sigtramp in userland @@ -78,8 +63,8 @@ public: // Whitelisting the trap handlers for user space would be easy (_sigtramp) but // in other environments there can be a large number of different functions // involved in async traps. - virtual bool - CallFrameAddressIsValid (lldb::addr_t cfa) + bool + CallFrameAddressIsValid(lldb::addr_t cfa) override { // Make sure the stack call frame addresses are 8 byte aligned if (cfa & (8ull - 1ull)) @@ -89,25 +74,21 @@ public: return true; } - virtual bool - CodeAddressIsValid (lldb::addr_t pc) + bool + CodeAddressIsValid(lldb::addr_t pc) override { // We have a 64 bit address space, so anything is valid as opcodes // aren't fixed width... return true; } - virtual bool - FunctionCallsChangeCFA () - { - return true; - } + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; - virtual const lldb_private::RegisterInfo * - GetRegisterInfoArray (uint32_t &count); //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -123,21 +104,30 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); - virtual uint32_t - GetPluginVersion(); + lldb_private::ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; protected: void CreateRegisterMapIfNeeded (); + lldb::ValueObjectSP + GetReturnValueObjectSimple(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const; + bool RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); private: - ABISysV_ppc64() : lldb_private::ABI() { } // Call CreateInstance instead. + ABISysV_ppc64() : + lldb_private::ABI() + { + // Call CreateInstance instead. + } }; -#endif // liblldb_ABI_h_ +#endif // liblldb_ABISysV_ppc64_h_ diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp index 1d63628466c23..11e383d269c3e 100644 --- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp +++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp @@ -20,7 +20,6 @@ #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectRegister.h" #include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Target.h" #include "lldb/Target/Process.h" @@ -34,222 +33,144 @@ using namespace lldb; using namespace lldb_private; -enum gcc_dwarf_regnums +enum dwarf_regnums { - gcc_dwarf_rax = 0, - gcc_dwarf_rdx, - gcc_dwarf_rcx, - gcc_dwarf_rbx, - gcc_dwarf_rsi, - gcc_dwarf_rdi, - gcc_dwarf_rbp, - gcc_dwarf_rsp, - gcc_dwarf_r8, - gcc_dwarf_r9, - gcc_dwarf_r10, - gcc_dwarf_r11, - gcc_dwarf_r12, - gcc_dwarf_r13, - gcc_dwarf_r14, - gcc_dwarf_r15, - gcc_dwarf_rip, - gcc_dwarf_xmm0, - gcc_dwarf_xmm1, - gcc_dwarf_xmm2, - gcc_dwarf_xmm3, - gcc_dwarf_xmm4, - gcc_dwarf_xmm5, - gcc_dwarf_xmm6, - gcc_dwarf_xmm7, - gcc_dwarf_xmm8, - gcc_dwarf_xmm9, - gcc_dwarf_xmm10, - gcc_dwarf_xmm11, - gcc_dwarf_xmm12, - gcc_dwarf_xmm13, - gcc_dwarf_xmm14, - gcc_dwarf_xmm15, - gcc_dwarf_stmm0, - gcc_dwarf_stmm1, - gcc_dwarf_stmm2, - gcc_dwarf_stmm3, - gcc_dwarf_stmm4, - gcc_dwarf_stmm5, - gcc_dwarf_stmm6, - gcc_dwarf_stmm7, - gcc_dwarf_ymm0, - gcc_dwarf_ymm1, - gcc_dwarf_ymm2, - gcc_dwarf_ymm3, - gcc_dwarf_ymm4, - gcc_dwarf_ymm5, - gcc_dwarf_ymm6, - gcc_dwarf_ymm7, - gcc_dwarf_ymm8, - gcc_dwarf_ymm9, - gcc_dwarf_ymm10, - gcc_dwarf_ymm11, - gcc_dwarf_ymm12, - gcc_dwarf_ymm13, - gcc_dwarf_ymm14, - gcc_dwarf_ymm15 + dwarf_rax = 0, + dwarf_rdx, + dwarf_rcx, + dwarf_rbx, + dwarf_rsi, + dwarf_rdi, + dwarf_rbp, + dwarf_rsp, + dwarf_r8, + dwarf_r9, + dwarf_r10, + dwarf_r11, + dwarf_r12, + dwarf_r13, + dwarf_r14, + dwarf_r15, + dwarf_rip, + dwarf_xmm0, + dwarf_xmm1, + dwarf_xmm2, + dwarf_xmm3, + dwarf_xmm4, + dwarf_xmm5, + dwarf_xmm6, + dwarf_xmm7, + dwarf_xmm8, + dwarf_xmm9, + dwarf_xmm10, + dwarf_xmm11, + dwarf_xmm12, + dwarf_xmm13, + dwarf_xmm14, + dwarf_xmm15, + dwarf_stmm0, + dwarf_stmm1, + dwarf_stmm2, + dwarf_stmm3, + dwarf_stmm4, + dwarf_stmm5, + dwarf_stmm6, + dwarf_stmm7, + dwarf_ymm0, + dwarf_ymm1, + dwarf_ymm2, + dwarf_ymm3, + dwarf_ymm4, + dwarf_ymm5, + dwarf_ymm6, + dwarf_ymm7, + dwarf_ymm8, + dwarf_ymm9, + dwarf_ymm10, + dwarf_ymm11, + dwarf_ymm12, + dwarf_ymm13, + dwarf_ymm14, + dwarf_ymm15 }; -enum gdb_regnums -{ - gdb_rax = 0, - gdb_rbx = 1, - gdb_rcx = 2, - gdb_rdx = 3, - gdb_rsi = 4, - gdb_rdi = 5, - gdb_rbp = 6, - gdb_rsp = 7, - gdb_r8 = 8, - gdb_r9 = 9, - gdb_r10 = 10, - gdb_r11 = 11, - gdb_r12 = 12, - gdb_r13 = 13, - gdb_r14 = 14, - gdb_r15 = 15, - gdb_rip = 16, - gdb_rflags = 17, - gdb_cs = 18, - gdb_ss = 19, - gdb_ds = 20, - gdb_es = 21, - gdb_fs = 22, - gdb_gs = 23, - gdb_stmm0 = 24, - gdb_stmm1 = 25, - gdb_stmm2 = 26, - gdb_stmm3 = 27, - gdb_stmm4 = 28, - gdb_stmm5 = 29, - gdb_stmm6 = 30, - gdb_stmm7 = 31, - gdb_fctrl = 32, gdb_fcw = gdb_fctrl, - gdb_fstat = 33, gdb_fsw = gdb_fstat, - gdb_ftag = 34, gdb_ftw = gdb_ftag, - gdb_fiseg = 35, gdb_fpu_cs = gdb_fiseg, - gdb_fioff = 36, gdb_ip = gdb_fioff, - gdb_foseg = 37, gdb_fpu_ds = gdb_foseg, - gdb_fooff = 38, gdb_dp = gdb_fooff, - gdb_fop = 39, - gdb_xmm0 = 40, - gdb_xmm1 = 41, - gdb_xmm2 = 42, - gdb_xmm3 = 43, - gdb_xmm4 = 44, - gdb_xmm5 = 45, - gdb_xmm6 = 46, - gdb_xmm7 = 47, - gdb_xmm8 = 48, - gdb_xmm9 = 49, - gdb_xmm10 = 50, - gdb_xmm11 = 51, - gdb_xmm12 = 52, - gdb_xmm13 = 53, - gdb_xmm14 = 54, - gdb_xmm15 = 55, - gdb_mxcsr = 56, - gdb_ymm0 = 57, - gdb_ymm1 = 58, - gdb_ymm2 = 59, - gdb_ymm3 = 60, - gdb_ymm4 = 61, - gdb_ymm5 = 62, - gdb_ymm6 = 63, - gdb_ymm7 = 64, - gdb_ymm8 = 65, - gdb_ymm9 = 66, - gdb_ymm10 = 67, - gdb_ymm11 = 68, - gdb_ymm12 = 69, - gdb_ymm13 = 70, - gdb_ymm14 = 71, - gdb_ymm15 = 72 -}; - - static RegisterInfo g_register_infos[] = { - // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE VALUE REGS INVALIDATE REGS + // NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS // ======== ======= == === ============= =================== ======================= ===================== =========================== ===================== ====================== ========== =============== - { "rax" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rax , gcc_dwarf_rax , LLDB_INVALID_REGNUM , gdb_rax , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "rbx" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rbx , gcc_dwarf_rbx , LLDB_INVALID_REGNUM , gdb_rbx , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "rcx" , "arg4", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rcx , gcc_dwarf_rcx , LLDB_REGNUM_GENERIC_ARG4 , gdb_rcx , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "rdx" , "arg3", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rdx , gcc_dwarf_rdx , LLDB_REGNUM_GENERIC_ARG3 , gdb_rdx , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "rsi" , "arg2", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rsi , gcc_dwarf_rsi , LLDB_REGNUM_GENERIC_ARG2 , gdb_rsi , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "rdi" , "arg1", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rdi , gcc_dwarf_rdi , LLDB_REGNUM_GENERIC_ARG1 , gdb_rdi , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "rbp" , "fp", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rbp , gcc_dwarf_rbp , LLDB_REGNUM_GENERIC_FP , gdb_rbp , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "rsp" , "sp", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rsp , gcc_dwarf_rsp , LLDB_REGNUM_GENERIC_SP , gdb_rsp , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r8" , "arg5", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r8 , gcc_dwarf_r8 , LLDB_REGNUM_GENERIC_ARG5 , gdb_r8 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r9" , "arg6", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r9 , gcc_dwarf_r9 , LLDB_REGNUM_GENERIC_ARG6 , gdb_r9 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r10" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r10 , gcc_dwarf_r10 , LLDB_INVALID_REGNUM , gdb_r10 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r11" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r11 , gcc_dwarf_r11 , LLDB_INVALID_REGNUM , gdb_r11 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r12" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r12 , gcc_dwarf_r12 , LLDB_INVALID_REGNUM , gdb_r12 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r13" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r13 , gcc_dwarf_r13 , LLDB_INVALID_REGNUM , gdb_r13 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r14" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r14 , gcc_dwarf_r14 , LLDB_INVALID_REGNUM , gdb_r14 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "r15" , NULL, 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_r15 , gcc_dwarf_r15 , LLDB_INVALID_REGNUM , gdb_r15 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "rip" , "pc", 8, 0, eEncodingUint , eFormatHex , { gcc_dwarf_rip , gcc_dwarf_rip , LLDB_REGNUM_GENERIC_PC , gdb_rip , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "rflags", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_rflags , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "cs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_cs , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ss" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ss , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ds" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ds , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "es" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_es , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fs , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "gs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gs , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm0" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm0 , gcc_dwarf_stmm0 , LLDB_INVALID_REGNUM , gdb_stmm0 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm1" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm1 , gcc_dwarf_stmm1 , LLDB_INVALID_REGNUM , gdb_stmm1 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm2" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm2 , gcc_dwarf_stmm2 , LLDB_INVALID_REGNUM , gdb_stmm2 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm3" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm3 , gcc_dwarf_stmm3 , LLDB_INVALID_REGNUM , gdb_stmm3 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm4" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm4 , gcc_dwarf_stmm4 , LLDB_INVALID_REGNUM , gdb_stmm4 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm5" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm5 , gcc_dwarf_stmm5 , LLDB_INVALID_REGNUM , gdb_stmm5 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm6" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm6 , gcc_dwarf_stmm6 , LLDB_INVALID_REGNUM , gdb_stmm6 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "stmm7" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm7 , gcc_dwarf_stmm7 , LLDB_INVALID_REGNUM , gdb_stmm7 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fctrl" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fctrl , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fstat" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fstat , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ftag" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ftag , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fiseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fiseg , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fioff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fioff , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "foseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_foseg , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fooff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fooff , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "fop" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fop , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm0" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm0 , gcc_dwarf_xmm0 , LLDB_INVALID_REGNUM , gdb_xmm0 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm1" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm1 , gcc_dwarf_xmm1 , LLDB_INVALID_REGNUM , gdb_xmm1 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm2" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm2 , gcc_dwarf_xmm2 , LLDB_INVALID_REGNUM , gdb_xmm2 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm3" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm3 , gcc_dwarf_xmm3 , LLDB_INVALID_REGNUM , gdb_xmm3 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm4" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm4 , gcc_dwarf_xmm4 , LLDB_INVALID_REGNUM , gdb_xmm4 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm5" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm5 , gcc_dwarf_xmm5 , LLDB_INVALID_REGNUM , gdb_xmm5 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm6" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm6 , gcc_dwarf_xmm6 , LLDB_INVALID_REGNUM , gdb_xmm6 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm7" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm7 , gcc_dwarf_xmm7 , LLDB_INVALID_REGNUM , gdb_xmm7 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm8" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm8 , gcc_dwarf_xmm8 , LLDB_INVALID_REGNUM , gdb_xmm8 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm9" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm9 , gcc_dwarf_xmm9 , LLDB_INVALID_REGNUM , gdb_xmm9 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm10" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm10 , gcc_dwarf_xmm10 , LLDB_INVALID_REGNUM , gdb_xmm10 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm11" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm11 , gcc_dwarf_xmm11 , LLDB_INVALID_REGNUM , gdb_xmm11 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm12" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm12 , gcc_dwarf_xmm12 , LLDB_INVALID_REGNUM , gdb_xmm12 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm13" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm13 , gcc_dwarf_xmm13 , LLDB_INVALID_REGNUM , gdb_xmm13 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm14" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm14 , gcc_dwarf_xmm14 , LLDB_INVALID_REGNUM , gdb_xmm14 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "xmm15" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm15 , gcc_dwarf_xmm15 , LLDB_INVALID_REGNUM , gdb_xmm15 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "mxcsr" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_mxcsr , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm0" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm0 , gcc_dwarf_ymm0 , LLDB_INVALID_REGNUM , gdb_ymm0 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm1" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm1 , gcc_dwarf_ymm1 , LLDB_INVALID_REGNUM , gdb_ymm1 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm2" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm2 , gcc_dwarf_ymm2 , LLDB_INVALID_REGNUM , gdb_ymm2 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm3" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm3 , gcc_dwarf_ymm3 , LLDB_INVALID_REGNUM , gdb_ymm3 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm4" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm4 , gcc_dwarf_ymm4 , LLDB_INVALID_REGNUM , gdb_ymm4 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm5" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm5 , gcc_dwarf_ymm5 , LLDB_INVALID_REGNUM , gdb_ymm5 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm6" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm6 , gcc_dwarf_ymm6 , LLDB_INVALID_REGNUM , gdb_ymm6 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm7" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm7 , gcc_dwarf_ymm7 , LLDB_INVALID_REGNUM , gdb_ymm7 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm8" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm8 , gcc_dwarf_ymm8 , LLDB_INVALID_REGNUM , gdb_ymm8 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm9" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm9 , gcc_dwarf_ymm9 , LLDB_INVALID_REGNUM , gdb_ymm9 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm10" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm10 , gcc_dwarf_ymm10 , LLDB_INVALID_REGNUM , gdb_ymm10 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm11" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm11 , gcc_dwarf_ymm11 , LLDB_INVALID_REGNUM , gdb_ymm11 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm12" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm12 , gcc_dwarf_ymm12 , LLDB_INVALID_REGNUM , gdb_ymm12 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm13" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm13 , gcc_dwarf_ymm13 , LLDB_INVALID_REGNUM , gdb_ymm13 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm14" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm14 , gcc_dwarf_ymm14 , LLDB_INVALID_REGNUM , gdb_ymm14 , LLDB_INVALID_REGNUM }, NULL, NULL}, - { "ymm15" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm15 , gcc_dwarf_ymm15 , LLDB_INVALID_REGNUM , gdb_ymm15 , LLDB_INVALID_REGNUM }, NULL, NULL} + { "rax" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_rax , dwarf_rax , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "rbx" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_rbx , dwarf_rbx , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "rcx" , "arg4", 8, 0, eEncodingUint , eFormatHex , { dwarf_rcx , dwarf_rcx , LLDB_REGNUM_GENERIC_ARG4 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "rdx" , "arg3", 8, 0, eEncodingUint , eFormatHex , { dwarf_rdx , dwarf_rdx , LLDB_REGNUM_GENERIC_ARG3 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "rsi" , "arg2", 8, 0, eEncodingUint , eFormatHex , { dwarf_rsi , dwarf_rsi , LLDB_REGNUM_GENERIC_ARG2 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "rdi" , "arg1", 8, 0, eEncodingUint , eFormatHex , { dwarf_rdi , dwarf_rdi , LLDB_REGNUM_GENERIC_ARG1 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "rbp" , "fp", 8, 0, eEncodingUint , eFormatHex , { dwarf_rbp , dwarf_rbp , LLDB_REGNUM_GENERIC_FP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "rsp" , "sp", 8, 0, eEncodingUint , eFormatHex , { dwarf_rsp , dwarf_rsp , LLDB_REGNUM_GENERIC_SP , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r8" , "arg5", 8, 0, eEncodingUint , eFormatHex , { dwarf_r8 , dwarf_r8 , LLDB_REGNUM_GENERIC_ARG5 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r9" , "arg6", 8, 0, eEncodingUint , eFormatHex , { dwarf_r9 , dwarf_r9 , LLDB_REGNUM_GENERIC_ARG6 , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r10" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r10 , dwarf_r10 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r11" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r11 , dwarf_r11 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r12" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r12 , dwarf_r12 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r13" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r13 , dwarf_r13 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r14" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r14 , dwarf_r14 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "r15" , NULL, 8, 0, eEncodingUint , eFormatHex , { dwarf_r15 , dwarf_r15 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "rip" , "pc", 8, 0, eEncodingUint , eFormatHex , { dwarf_rip , dwarf_rip , LLDB_REGNUM_GENERIC_PC , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "rflags", NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "cs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ss" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ds" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "es" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "gs" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm0" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm0 , dwarf_stmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm1" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm1 , dwarf_stmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm2" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm2 , dwarf_stmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm3" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm3 , dwarf_stmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm4" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm4 , dwarf_stmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm5" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm5 , dwarf_stmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm6" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm6 , dwarf_stmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "stmm7" , NULL, 10, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_stmm7 , dwarf_stmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fctrl" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fstat" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ftag" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fiseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fioff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "foseg" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fooff" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "fop" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm0" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm0 , dwarf_xmm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm1" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm1 , dwarf_xmm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm2" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm2 , dwarf_xmm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm3" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm3 , dwarf_xmm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm4" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm4 , dwarf_xmm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm5" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm5 , dwarf_xmm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm6" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm6 , dwarf_xmm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm7" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm7 , dwarf_xmm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm8" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm8 , dwarf_xmm8 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm9" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm9 , dwarf_xmm9 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm10" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm10 , dwarf_xmm10 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm11" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm11 , dwarf_xmm11 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm12" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm12 , dwarf_xmm12 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm13" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm13 , dwarf_xmm13 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm14" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm14 , dwarf_xmm14 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "xmm15" , NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_xmm15 , dwarf_xmm15 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "mxcsr" , NULL, 4, 0, eEncodingUint , eFormatHex , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm0" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm0 , dwarf_ymm0 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm1" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm1 , dwarf_ymm1 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm2" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm2 , dwarf_ymm2 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm3" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm3 , dwarf_ymm3 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm4" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm4 , dwarf_ymm4 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm5" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm5 , dwarf_ymm5 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm6" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm6 , dwarf_ymm6 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm7" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm7 , dwarf_ymm7 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm8" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm8 , dwarf_ymm8 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm9" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm9 , dwarf_ymm9 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm10" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm10 , dwarf_ymm10 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm11" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm11 , dwarf_ymm11 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm12" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm12 , dwarf_ymm12 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm13" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm13 , dwarf_ymm13 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm14" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm14 , dwarf_ymm14 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL}, + { "ymm15" , NULL, 32, 0, eEncodingVector, eFormatVectorOfUInt8, { dwarf_ymm15 , dwarf_ymm15 , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL} }; static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos); @@ -502,25 +423,25 @@ ABISysV_x86_64::GetArgumentValues (Thread &thread, // We currently only support extracting values with Clang QualTypes. // Do we care about others? - ClangASTType clang_type = value->GetClangType(); - if (!clang_type) + CompilerType compiler_type = value->GetCompilerType(); + if (!compiler_type) return false; bool is_signed; - if (clang_type.IsIntegerType (is_signed)) + if (compiler_type.IsIntegerType (is_signed)) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), is_signed, thread, argument_register_ids, current_argument_register, current_stack_argument); } - else if (clang_type.IsPointerType ()) + else if (compiler_type.IsPointerType ()) { ReadIntegerArgument(value->GetScalar(), - clang_type.GetBitSize(&thread), + compiler_type.GetBitSize(&thread), false, thread, argument_register_ids, @@ -542,8 +463,8 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb return error; } - ClangASTType clang_type = new_value_sp->GetClangType(); - if (!clang_type) + CompilerType compiler_type = new_value_sp->GetCompilerType(); + if (!compiler_type) { error.SetErrorString ("Null clang type for return value."); return error; @@ -558,7 +479,7 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb RegisterContext *reg_ctx = thread->GetRegisterContext().get(); bool set_it_simple = false; - if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType()) + if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType()) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("rax", 0); @@ -584,13 +505,13 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb } } - else if (clang_type.IsFloatingPointType (count, is_complex)) + else if (compiler_type.IsFloatingPointType (count, is_complex)) { if (is_complex) error.SetErrorString ("We don't support returning complex values at present"); else { - size_t bit_width = clang_type.GetBitSize(frame_sp.get()); + size_t bit_width = compiler_type.GetBitSize(frame_sp.get()); if (bit_width <= 64) { const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0); @@ -633,22 +554,22 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb ValueObjectSP ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, - ClangASTType &return_clang_type) const + CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; Value value; - if (!return_clang_type) + if (!return_compiler_type) return return_valobj_sp; //value.SetContext (Value::eContextTypeClangType, return_value_type); - value.SetClangType (return_clang_type); + value.SetCompilerType (return_compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; - const uint32_t type_flags = return_clang_type.GetTypeInfo (); + const uint32_t type_flags = return_compiler_type.GetTypeInfo (); if (type_flags & eTypeIsScalar) { value.SetValueType(Value::eValueTypeScalar); @@ -658,7 +579,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, { // Extract the register context so we can read arguments from registers - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("rax", 0), 0); const bool is_signed = (type_flags & eTypeIsSigned) != 0; switch (byte_size) @@ -707,7 +628,7 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, } else { - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); if (byte_size <= sizeof(long double)) { const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0); @@ -755,18 +676,13 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, } else if (type_flags & eTypeIsVector) { - const size_t byte_size = return_clang_type.GetByteSize(nullptr); + const size_t byte_size = return_compiler_type.GetByteSize(nullptr); if (byte_size > 0) { + const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0); + if (altivec_reg == nullptr) + altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0); - const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("ymm0", 0); - if (altivec_reg == NULL) - { - altivec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0); - if (altivec_reg == NULL) - altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0); - } - if (altivec_reg) { if (byte_size <= altivec_reg->byte_size) @@ -790,13 +706,52 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, byte_order, process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); return_valobj_sp = ValueObjectConstResult::Create (&thread, - return_clang_type, + return_compiler_type, ConstString(""), data); } } } } + else if (byte_size <= altivec_reg->byte_size*2) + { + const RegisterInfo *altivec_reg2 = reg_ctx->GetRegisterInfoByName("xmm1", 0); + if (altivec_reg2) + { + ProcessSP process_sp (thread.GetProcess()); + if (process_sp) + { + std::unique_ptr heap_data_ap (new DataBufferHeap(byte_size, 0)); + const ByteOrder byte_order = process_sp->GetByteOrder(); + RegisterValue reg_value; + RegisterValue reg_value2; + if (reg_ctx->ReadRegister(altivec_reg, reg_value) && reg_ctx->ReadRegister(altivec_reg2, reg_value2)) + { + + Error error; + if (reg_value.GetAsMemoryData (altivec_reg, + heap_data_ap->GetBytes(), + altivec_reg->byte_size, + byte_order, + error) && + reg_value2.GetAsMemoryData (altivec_reg2, + heap_data_ap->GetBytes() + altivec_reg->byte_size, + heap_data_ap->GetByteSize() - altivec_reg->byte_size, + byte_order, + error)) + { + DataExtractor data (DataBufferSP (heap_data_ap.release()), + byte_order, + process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); + return_valobj_sp = ValueObjectConstResult::Create (&thread, + return_compiler_type, + ConstString(""), + data); + } + } + } + } + } } } } @@ -805,15 +760,15 @@ ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, } ValueObjectSP -ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const +ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_compiler_type) const { ValueObjectSP return_valobj_sp; - if (!return_clang_type) + if (!return_compiler_type) return return_valobj_sp; ExecutionContext exe_ctx (thread.shared_from_this()); - return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type); + return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type); if (return_valobj_sp) return return_valobj_sp; @@ -821,8 +776,8 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c if (!reg_ctx_sp) return return_valobj_sp; - const size_t bit_width = return_clang_type.GetBitSize(&thread); - if (return_clang_type.IsAggregateType()) + const size_t bit_width = return_compiler_type.GetBitSize(&thread); + if (return_compiler_type.IsAggregateType()) { Target *target = exe_ctx.GetTargetPtr(); bool is_memory = true; @@ -855,7 +810,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c uint32_t fp_bytes = 0; // Tracks how much of the xmm registers we've consumed so far uint32_t integer_bytes = 0; // Tracks how much of the rax/rds registers we've consumed so far - const uint32_t num_children = return_clang_type.GetNumFields (); + const uint32_t num_children = return_compiler_type.GetNumFields (); // Since we are in the small struct regime, assume we are not in memory. is_memory = false; @@ -868,8 +823,8 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c bool is_complex; uint32_t count; - ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); - const size_t field_bit_width = field_clang_type.GetBitSize(&thread); + CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL); + const size_t field_bit_width = field_compiler_type.GetBitSize(&thread); // if we don't know the size of the field (e.g. invalid type), just bail out if (field_bit_width == 0) @@ -889,7 +844,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c DataExtractor *copy_from_extractor = NULL; uint32_t copy_from_offset = 0; - if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ()) + if (field_compiler_type.IsIntegerType (is_signed) || field_compiler_type.IsPointerType ()) { if (integer_bytes < 8) { @@ -922,7 +877,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c return return_valobj_sp; } } - else if (field_clang_type.IsFloatingPointType (count, is_complex)) + else if (field_compiler_type.IsFloatingPointType (count, is_complex)) { // Structs with long doubles are always passed in memory. if (field_bit_width == 128) @@ -955,12 +910,12 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c else { uint64_t next_field_bit_offset = 0; - ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1, + CompilerType next_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx + 1, name, &next_field_bit_offset, NULL, NULL); - if (next_field_clang_type.IsIntegerType (is_signed)) + if (next_field_compiler_type.IsIntegerType (is_signed)) in_gpr = true; else { @@ -979,12 +934,12 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c else { uint64_t prev_field_bit_offset = 0; - ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1, + CompilerType prev_field_compiler_type = return_compiler_type.GetFieldAtIndex (idx - 1, name, &prev_field_bit_offset, NULL, NULL); - if (prev_field_clang_type.IsIntegerType (is_signed)) + if (prev_field_compiler_type.IsIntegerType (is_signed)) in_gpr = true; else { @@ -1048,7 +1003,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c { // The result is in our data buffer. Let's make a variable object out of it: return_valobj_sp = ValueObjectConstResult::Create (&thread, - return_clang_type, + return_compiler_type, ConstString(""), return_ext); } @@ -1067,7 +1022,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_c return_valobj_sp = ValueObjectMemory::Create (&thread, "", Address (storage_addr, NULL), - return_clang_type); + return_compiler_type); } } @@ -1084,8 +1039,8 @@ ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.Clear(); unwind_plan.SetRegisterKind (eRegisterKindDWARF); - uint32_t sp_reg_num = gcc_dwarf_rsp; - uint32_t pc_reg_num = gcc_dwarf_rip; + uint32_t sp_reg_num = dwarf_rsp; + uint32_t pc_reg_num = dwarf_rip; UnwindPlan::RowSP row(new UnwindPlan::Row); row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 8); @@ -1108,14 +1063,14 @@ ABISysV_x86_64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan) unwind_plan.Clear(); unwind_plan.SetRegisterKind (eRegisterKindDWARF); - uint32_t fp_reg_num = gcc_dwarf_rbp; - uint32_t sp_reg_num = gcc_dwarf_rsp; - uint32_t pc_reg_num = gcc_dwarf_rip; + uint32_t fp_reg_num = dwarf_rbp; + uint32_t sp_reg_num = dwarf_rsp; + uint32_t pc_reg_num = dwarf_rip; UnwindPlan::RowSP row(new UnwindPlan::Row); const int32_t ptr_size = 8; - row->GetCFAValue().SetIsRegisterPlusOffset(gcc_dwarf_rbp, 2 * ptr_size); + row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_rbp, 2 * ptr_size); row->SetOffset (0); row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true); diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h index 6fefcc2a9c747..07b57abaf57cd 100644 --- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h +++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h @@ -21,46 +21,37 @@ class ABISysV_x86_64 : public lldb_private::ABI { public: + ~ABISysV_x86_64() override = default; - ~ABISysV_x86_64() - { - } - - virtual size_t - GetRedZoneSize () const; + size_t + GetRedZoneSize() const override; - virtual bool - PrepareTrivialCall (lldb_private::Thread &thread, - lldb::addr_t sp, - lldb::addr_t functionAddress, - lldb::addr_t returnAddress, - llvm::ArrayRef args) const; + bool + PrepareTrivialCall(lldb_private::Thread &thread, + lldb::addr_t sp, + lldb::addr_t functionAddress, + lldb::addr_t returnAddress, + llvm::ArrayRef args) const override; - virtual bool - GetArgumentValues (lldb_private::Thread &thread, - lldb_private::ValueList &values) const; + bool + GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override; - virtual lldb_private::Error - SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value); + lldb_private::Error + SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override; -protected: lldb::ValueObjectSP - GetReturnValueObjectSimple (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const; - -public: - virtual lldb::ValueObjectSP - GetReturnValueObjectImpl (lldb_private::Thread &thread, - lldb_private::ClangASTType &type) const; + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &type) const override; - virtual bool - CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan); + bool + CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; - virtual bool - RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info); + bool + RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; // The SysV x86_64 ABI requires that stack frames be 16 byte aligned. // When there is a trap handler on the stack, e.g. _sigtramp in userland @@ -72,8 +63,8 @@ public: // Whitelisting the trap handlers for user space would be easy (_sigtramp) but // in other environments there can be a large number of different functions // involved in async traps. - virtual bool - CallFrameAddressIsValid (lldb::addr_t cfa) + bool + CallFrameAddressIsValid(lldb::addr_t cfa) override { // Make sure the stack call frame addresses are 8 byte aligned if (cfa & (8ull - 1ull)) @@ -83,19 +74,21 @@ public: return true; } - virtual bool - CodeAddressIsValid (lldb::addr_t pc) + bool + CodeAddressIsValid(lldb::addr_t pc) override { // We have a 64 bit address space, so anything is valid as opcodes // aren't fixed width... return true; } - virtual const lldb_private::RegisterInfo * - GetRegisterInfoArray (uint32_t &count); + const lldb_private::RegisterInfo * + GetRegisterInfoArray(uint32_t &count) override; + //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + static void Initialize(); @@ -111,21 +104,30 @@ public: //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); - virtual uint32_t - GetPluginVersion(); + lldb_private::ConstString + GetPluginName() override; + + uint32_t + GetPluginVersion() override; protected: void CreateRegisterMapIfNeeded (); + lldb::ValueObjectSP + GetReturnValueObjectSimple(lldb_private::Thread &thread, + lldb_private::CompilerType &ast_type) const; + bool RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info); private: - ABISysV_x86_64() : lldb_private::ABI() { } // Call CreateInstance instead. + ABISysV_x86_64() : + lldb_private::ABI() + { + // Call CreateInstance instead. + } }; -#endif // liblldb_ABI_h_ +#endif // liblldb_ABISysV_x86_64_h_ diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp index d20219f6d1eb6..6d124b689341f 100644 --- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp +++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp @@ -7,8 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "DisassemblerLLVMC.h" - +// C Includes +// C++ Includes +// Project includes #include "llvm-c/Disassembler.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" @@ -25,6 +26,8 @@ #include "llvm/Support/TargetSelect.h" #include "llvm/ADT/SmallString.h" +// Other libraries and framework includes +#include "DisassemblerLLVMC.h" #include "lldb/Core/Address.h" #include "lldb/Core/DataExtractor.h" @@ -52,18 +55,16 @@ public: Instruction (address, addr_class), m_disasm_sp (disasm.shared_from_this()), m_does_branch (eLazyBoolCalculate), + m_has_delay_slot (eLazyBoolCalculate), m_is_valid (false), m_using_file_addr (false) { } - virtual - ~InstructionLLVMC () - { - } + ~InstructionLLVMC() override = default; - virtual bool - DoesBranch () + bool + DoesBranch() override { if (m_does_branch == eLazyBoolCalculate) { @@ -99,6 +100,43 @@ public: return m_does_branch == eLazyBoolYes; } + bool + HasDelaySlot() override + { + if (m_has_delay_slot == eLazyBoolCalculate) + { + GetDisassemblerLLVMC().Lock(this, NULL); + DataExtractor data; + if (m_opcode.GetData(data)) + { + bool is_alternate_isa; + lldb::addr_t pc = m_address.GetFileAddress(); + + DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa); + const uint8_t *opcode_data = data.GetDataStart(); + const size_t opcode_data_len = data.GetByteSize(); + llvm::MCInst inst; + const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data, + opcode_data_len, + pc, + inst); + // if we didn't understand the instruction, say it doesn't have a delay slot... + if (inst_size == 0) + m_has_delay_slot = eLazyBoolNo; + else + { + const bool has_delay_slot = mc_disasm_ptr->HasDelaySlot(inst); + if (has_delay_slot) + m_has_delay_slot = eLazyBoolYes; + else + m_has_delay_slot = eLazyBoolNo; + } + } + GetDisassemblerLLVMC().Unlock(); + } + return m_has_delay_slot == eLazyBoolYes; + } + DisassemblerLLVMC::LLVMCDisassembler * GetDisasmToUse (bool &is_alternate_isa) { @@ -117,10 +155,10 @@ public: return llvm_disasm.m_disasm_ap.get(); } - virtual size_t - Decode (const lldb_private::Disassembler &disassembler, - const lldb_private::DataExtractor &data, - lldb::offset_t data_offset) + size_t + Decode(const lldb_private::Disassembler &disassembler, + const lldb_private::DataExtractor &data, + lldb::offset_t data_offset) override { // All we have to do is read the opcode which can be easy for some // architectures @@ -234,15 +272,16 @@ public: } } - virtual void - CalculateMnemonicOperandsAndComment (const lldb_private::ExecutionContext *exe_ctx) + void + CalculateMnemonicOperandsAndComment(const lldb_private::ExecutionContext *exe_ctx) override { DataExtractor data; const AddressClass address_class = GetAddressClass (); if (m_opcode.GetData(data)) { - char out_string[512]; + std::string out_string; + std::string comment_string; DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC(); @@ -293,7 +332,12 @@ public: if (inst_size > 0) { mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style); - mc_disasm_ptr->PrintMCInst(inst, out_string, sizeof(out_string)); + mc_disasm_ptr->PrintMCInst(inst, out_string, comment_string); + + if (!comment_string.empty()) + { + AppendComment(comment_string); + } } llvm_disasm.Unlock(); @@ -375,10 +419,10 @@ public: RegularExpression::Match matches(3); - if (s_regex.Execute(out_string, &matches)) + if (s_regex.Execute(out_string.c_str(), &matches)) { - matches.GetMatchAtIndex(out_string, 1, m_opcode_name); - matches.GetMatchAtIndex(out_string, 2, m_mnemonics); + matches.GetMatchAtIndex(out_string.c_str(), 1, m_opcode_name); + matches.GetMatchAtIndex(out_string.c_str(), 2, m_mnemonics); } } } @@ -409,12 +453,11 @@ protected: DisassemblerSP m_disasm_sp; // for ownership LazyBool m_does_branch; + LazyBool m_has_delay_slot; bool m_is_valid; bool m_using_file_addr; }; - - DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, const char *cpu, const char *features_str, unsigned flavor, DisassemblerLLVMC &owner): m_is_valid(true) { @@ -482,9 +525,7 @@ DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, con m_is_valid = false; } -DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler() -{ -} +DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler() = default; uint64_t DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (const uint8_t *opcode_data, @@ -508,22 +549,25 @@ DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (const uint8_t *opcode_data, return 0; } -uint64_t +void DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst (llvm::MCInst &mc_inst, - char *dst, - size_t dst_len) + std::string &inst_string, + std::string &comments_string) { - llvm::StringRef unused_annotations; - llvm::SmallString<64> inst_string; - llvm::raw_svector_ostream inst_stream(inst_string); - m_instr_printer_ap->printInst (&mc_inst, inst_stream, unused_annotations, - *m_subtarget_info_ap); - inst_stream.flush(); - const size_t output_size = std::min(dst_len - 1, inst_string.size()); - std::memcpy(dst, inst_string.data(), output_size); - dst[output_size] = '\0'; - - return output_size; + llvm::raw_string_ostream inst_stream(inst_string); + llvm::raw_string_ostream comments_stream(comments_string); + + m_instr_printer_ap->setCommentStream(comments_stream); + m_instr_printer_ap->printInst (&mc_inst, inst_stream, llvm::StringRef(), *m_subtarget_info_ap); + m_instr_printer_ap->setCommentStream(llvm::nulls()); + comments_stream.flush(); + + static std::string g_newlines("\r\n"); + + for (size_t newline_pos = 0; (newline_pos = comments_string.find_first_of(g_newlines, newline_pos)) != comments_string.npos; /**/) + { + comments_string.replace(comments_string.begin() + newline_pos, comments_string.begin() + newline_pos + 1, 1, ' '); + } } void @@ -544,35 +588,9 @@ DisassemblerLLVMC::LLVMCDisassembler::CanBranch (llvm::MCInst &mc_inst) } bool -DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor) +DisassemblerLLVMC::LLVMCDisassembler::HasDelaySlot (llvm::MCInst &mc_inst) { - llvm::Triple triple = arch.GetTriple(); - if (flavor == NULL || strcmp (flavor, "default") == 0) - return true; - - if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64) - { - if (strcmp (flavor, "intel") == 0 || strcmp (flavor, "att") == 0) - return true; - else - return false; - } - else - return false; -} - - -Disassembler * -DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor) -{ - if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch) - { - std::unique_ptr disasm_ap (new DisassemblerLLVMC(arch, flavor)); - - if (disasm_ap.get() && disasm_ap->IsValid()) - return disasm_ap.release(); - } - return NULL; + return m_instr_info_ap->get(mc_inst.getOpcode()).hasDelaySlot(); } DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_string) : @@ -586,13 +604,12 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s m_flavor.assign("default"); } - const char *triple = arch.GetTriple().getTriple().c_str(); unsigned flavor = ~0U; + llvm::Triple triple = arch.GetTriple(); // So far the only supported flavor is "intel" on x86. The base class will set this // correctly coming in. - if (arch.GetTriple().getArch() == llvm::Triple::x86 - || arch.GetTriple().getArch() == llvm::Triple::x86_64) + if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64) { if (m_flavor == "intel") { @@ -605,7 +622,7 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s } ArchSpec thumb_arch(arch); - if (arch.GetTriple().getArch() == llvm::Triple::arm) + if (triple.getArch() == llvm::Triple::arm) { std::string thumb_arch_name (thumb_arch.GetTriple().getArchName().str()); // Replace "arm" with "thumb" so we get all thumb variants correct @@ -621,18 +638,29 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name.c_str())); } + // If no sub architecture specified then use the most recent arm architecture so the + // disassembler will return all instruction. Without it we will see a lot of unknow opcode + // in case the code uses instructions which are not available in the oldest arm version + // (used when no sub architecture is specified) + if (triple.getArch() == llvm::Triple::arm && triple.getSubArch() == llvm::Triple::NoSubArch) + triple.setArchName("armv8.1a"); + + const char *triple_str = triple.getTriple().c_str(); + + // v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization + // // Cortex-M3 devices (e.g. armv7m) can only execute thumb (T2) instructions, // so hardcode the primary disassembler to thumb mode. Same for Cortex-M4 (armv7em). // // Handle the Cortex-M0 (armv6m) the same; the ISA is a subset of the T and T32 // instructions defined in ARMv7-A. - if (arch.GetTriple().getArch() == llvm::Triple::arm + if ((triple.getArch() == llvm::Triple::arm || triple.getArch() == llvm::Triple::thumb) && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m || arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em || arch.GetCore() == ArchSpec::Core::eCore_arm_armv6m)) { - triple = thumb_arch.GetTriple().getTriple().c_str(); + triple_str = thumb_arch.GetTriple().getTriple().c_str(); } const char *cpu = ""; @@ -674,8 +702,8 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s } std::string features_str = ""; - if (arch.GetTriple().getArch() == llvm::Triple::mips || arch.GetTriple().getArch() == llvm::Triple::mipsel - || arch.GetTriple().getArch() == llvm::Triple::mips64 || arch.GetTriple().getArch() == llvm::Triple::mips64el) + if (triple.getArch() == llvm::Triple::mips || triple.getArch() == llvm::Triple::mipsel + || triple.getArch() == llvm::Triple::mips64 || triple.getArch() == llvm::Triple::mips64el) { uint32_t arch_flags = arch.GetFlags (); if (arch_flags & ArchSpec::eMIPSAse_msa) @@ -684,13 +712,9 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s features_str += "+dsp,"; if (arch_flags & ArchSpec::eMIPSAse_dspr2) features_str += "+dspr2,"; - if (arch_flags & ArchSpec::eMIPSAse_mips16) - features_str += "+mips16,"; - if (arch_flags & ArchSpec::eMIPSAse_micromips) - features_str += "+micromips,"; } - m_disasm_ap.reset (new LLVMCDisassembler(triple, cpu, features_str.c_str(), flavor, *this)); + m_disasm_ap.reset (new LLVMCDisassembler(triple_str, cpu, features_str.c_str(), flavor, *this)); if (!m_disasm_ap->IsValid()) { // We use m_disasm_ap.get() to tell whether we are valid or not, so if this isn't good for some reason, @@ -698,8 +722,10 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s m_disasm_ap.reset(); } + llvm::Triple::ArchType llvm_arch = triple.getArch(); + // For arm CPUs that can execute arm or thumb instructions, also create a thumb instruction disassembler. - if (arch.GetTriple().getArch() == llvm::Triple::arm) + if (llvm_arch == llvm::Triple::arm) { std::string thumb_triple(thumb_arch.GetTriple().getTriple()); m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), "", "", flavor, *this)); @@ -709,10 +735,40 @@ DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_s m_alternate_disasm_ap.reset(); } } + else if (llvm_arch == llvm::Triple::mips + || llvm_arch == llvm::Triple::mipsel + || llvm_arch == llvm::Triple::mips64 + || llvm_arch == llvm::Triple::mips64el) + { + /* Create alternate disassembler for MIPS16 and microMIPS */ + uint32_t arch_flags = arch.GetFlags (); + if (arch_flags & ArchSpec::eMIPSAse_mips16) + features_str += "+mips16,"; + else if (arch_flags & ArchSpec::eMIPSAse_micromips) + features_str += "+micromips,"; + + m_alternate_disasm_ap.reset(new LLVMCDisassembler (triple_str, cpu, features_str.c_str(), flavor, *this)); + if (!m_alternate_disasm_ap->IsValid()) + { + m_disasm_ap.reset(); + m_alternate_disasm_ap.reset(); + } + } } -DisassemblerLLVMC::~DisassemblerLLVMC() +DisassemblerLLVMC::~DisassemblerLLVMC() = default; + +Disassembler * +DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor) { + if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch) + { + std::unique_ptr disasm_ap (new DisassemblerLLVMC(arch, flavor)); + + if (disasm_ap.get() && disasm_ap->IsValid()) + return disasm_ap.release(); + } + return NULL; } size_t @@ -817,6 +873,24 @@ const char *DisassemblerLLVMC::SymbolLookupCallback (void *disassembler, name); } +bool +DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor) +{ + llvm::Triple triple = arch.GetTriple(); + if (flavor == NULL || strcmp (flavor, "default") == 0) + return true; + + if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64) + { + if (strcmp (flavor, "intel") == 0 || strcmp (flavor, "att") == 0) + return true; + else + return false; + } + else + return false; +} + int DisassemblerLLVMC::OpInfo (uint64_t PC, uint64_t Offset, uint64_t Size, diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h index 56cec03994ef9..6359146d81d85 100644 --- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h +++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h @@ -10,10 +10,20 @@ #ifndef liblldb_DisassemblerLLVMC_h_ #define liblldb_DisassemblerLLVMC_h_ +// C Includes +// C++ Includes +#include #include +// Other libraries and framework includes #include "llvm-c/Disassembler.h" +// Project includes +#include "lldb/Core/Address.h" +#include "lldb/Core/Disassembler.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Host/Mutex.h" + // Opaque references to C++ Objects in LLVM's MC. namespace llvm { @@ -25,12 +35,7 @@ namespace llvm class MCInstPrinter; class MCAsmInfo; class MCSubtargetInfo; -} - -#include "lldb/Core/Address.h" -#include "lldb/Core/Disassembler.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Host/Mutex.h" +} // namespace llvm class InstructionLLVMC; @@ -46,9 +51,10 @@ class DisassemblerLLVMC : public lldb_private::Disassembler ~LLVMCDisassembler(); uint64_t GetMCInst (const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, llvm::MCInst &mc_inst); - uint64_t PrintMCInst (llvm::MCInst &mc_inst, char *output_buffer, size_t out_buffer_len); + void PrintMCInst (llvm::MCInst &mc_inst, std::string &inst_string, std::string &comments_string); void SetStyle (bool use_hex_immed, HexImmediateStyle hex_style); bool CanBranch (llvm::MCInst &mc_inst); + bool HasDelaySlot (llvm::MCInst &mc_inst); bool IsValid() { return m_is_valid; @@ -66,6 +72,10 @@ class DisassemblerLLVMC : public lldb_private::Disassembler }; public: + DisassemblerLLVMC(const lldb_private::ArchSpec &arch, const char *flavor /* = NULL */); + + ~DisassemblerLLVMC() override; + //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ @@ -81,33 +91,28 @@ public: static lldb_private::Disassembler * CreateInstance(const lldb_private::ArchSpec &arch, const char *flavor); - DisassemblerLLVMC(const lldb_private::ArchSpec &arch, const char *flavor /* = NULL */); - - virtual - ~DisassemblerLLVMC(); - - virtual size_t - DecodeInstructions (const lldb_private::Address &base_addr, - const lldb_private::DataExtractor& data, - lldb::offset_t data_offset, - size_t num_instructions, - bool append, - bool data_from_file); + size_t + DecodeInstructions(const lldb_private::Address &base_addr, + const lldb_private::DataExtractor& data, + lldb::offset_t data_offset, + size_t num_instructions, + bool append, + bool data_from_file) override; //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); + lldb_private::ConstString + GetPluginName() override; - virtual uint32_t - GetPluginVersion(); + uint32_t + GetPluginVersion() override; protected: friend class InstructionLLVMC; - virtual bool - FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor); + bool + FlavorValidForArchSpec(const lldb_private::ArchSpec &arch, const char *flavor) override; bool IsValid() @@ -163,4 +168,4 @@ protected: std::unique_ptr m_alternate_disasm_ap; }; -#endif // liblldb_DisassemblerLLVM_h_ +#endif // liblldb_DisassemblerLLVM_h_ diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp index 2308129b8cab0..28493170ac367 100644 --- a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp +++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp @@ -104,11 +104,6 @@ DynamicLoaderHexagonDYLD::GetPluginDescriptionStatic() "loads/unloads in Hexagon processes."; } -void -DynamicLoaderHexagonDYLD::GetPluginCommandHelp(const char *command, Stream *strm) -{ -} - uint32_t DynamicLoaderHexagonDYLD::GetPluginVersion() { @@ -177,7 +172,7 @@ DynamicLoaderHexagonDYLD::DidAttach() // Map the loaded sections of this executable if ( load_offset != LLDB_INVALID_ADDRESS ) - UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset); + UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true); // AD: confirm this? // Load into LLDB all of the currently loaded executables in the stub @@ -248,18 +243,6 @@ DynamicLoaderHexagonDYLD::GetTargetExecutable() return executable; } -Error -DynamicLoaderHexagonDYLD::ExecutePluginCommand(Args &command, Stream *strm) -{ - return Error(); -} - -Log * -DynamicLoaderHexagonDYLD::EnablePluginLogging(Stream *strm, Args &command) -{ - return NULL; -} - //AD: Needs to be updated? Error DynamicLoaderHexagonDYLD::CanLoadImage() @@ -268,7 +251,10 @@ DynamicLoaderHexagonDYLD::CanLoadImage() } void -DynamicLoaderHexagonDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr) +DynamicLoaderHexagonDYLD::UpdateLoadedSections(ModuleSP module, + addr_t link_map_addr, + addr_t base_addr, + bool base_addr_is_offset) { Target &target = m_process->GetTarget(); const SectionList *sections = GetSectionListFromModule(module); @@ -442,7 +428,7 @@ DynamicLoaderHexagonDYLD::RefreshModules() for (I = m_rendezvous.loaded_begin(); I != E; ++I) { FileSpec file(I->path.c_str(), true); - ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr); + ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr, true); if (module_sp.get()) { loaded_modules.AppendIfNeeded( module_sp ); @@ -571,7 +557,7 @@ DynamicLoaderHexagonDYLD::LoadAllCurrentModules() { const char *module_path = I->path.c_str(); FileSpec file(module_path, false); - ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr); + ModuleSP module_sp = LoadModuleAtAddress(file, I->link_addr, I->base_addr, true); if (module_sp.get()) { module_list.Append(module_sp); @@ -591,7 +577,10 @@ DynamicLoaderHexagonDYLD::LoadAllCurrentModules() /// Helper for the entry breakpoint callback. Resolves the load addresses /// of all dependent modules. ModuleSP -DynamicLoaderHexagonDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, addr_t base_addr) +DynamicLoaderHexagonDYLD::LoadModuleAtAddress(const FileSpec &file, + addr_t link_map_addr, + addr_t base_addr, + bool base_addr_is_offset) { Target &target = m_process->GetTarget(); ModuleList &modules = target.GetImages(); @@ -602,12 +591,12 @@ DynamicLoaderHexagonDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t link_ // check if module is currently loaded if ((module_sp = modules.FindFirstModule (module_spec))) { - UpdateLoadedSections(module_sp, link_map_addr, base_addr); + UpdateLoadedSections(module_sp, link_map_addr, base_addr, true); } // try to load this module from disk else if ((module_sp = target.GetSharedModule(module_spec))) { - UpdateLoadedSections(module_sp, link_map_addr, base_addr); + UpdateLoadedSections(module_sp, link_map_addr, base_addr, true); } return module_sp; diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h index aafa385c0fca2..e10d4ee642091 100644 --- a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h +++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h @@ -7,12 +7,13 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_DynamicLoaderHexagon_H_ -#define liblldb_DynamicLoaderHexagon_H_ +#ifndef liblldb_DynamicLoaderHexagonDYLD_h_ +#define liblldb_DynamicLoaderHexagonDYLD_h_ // C Includes // C++ Includes // Other libraries and framework includes +// Project includes #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Target/DynamicLoader.h" @@ -21,6 +22,9 @@ class DynamicLoaderHexagonDYLD : public lldb_private::DynamicLoader { public: + DynamicLoaderHexagonDYLD(lldb_private::Process *process); + + ~DynamicLoaderHexagonDYLD() override; static void Initialize(); @@ -37,48 +41,34 @@ public: static lldb_private::DynamicLoader * CreateInstance(lldb_private::Process *process, bool force); - DynamicLoaderHexagonDYLD(lldb_private::Process *process); - - virtual - ~DynamicLoaderHexagonDYLD(); - //------------------------------------------------------------------ // DynamicLoader protocol //------------------------------------------------------------------ - virtual void - DidAttach(); + void + DidAttach() override; - virtual void - DidLaunch(); + void + DidLaunch() override; - virtual lldb::ThreadPlanSP + lldb::ThreadPlanSP GetStepThroughTrampolinePlan(lldb_private::Thread &thread, - bool stop_others); + bool stop_others) override; - virtual lldb_private::Error - CanLoadImage(); + lldb_private::Error + CanLoadImage() override; - virtual lldb::addr_t - GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread); + lldb::addr_t + GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread) override; //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); + lldb_private::ConstString + GetPluginName() override; - virtual uint32_t - GetPluginVersion(); - - virtual void - GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); - - virtual lldb_private::Error - ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm); - - virtual lldb_private::Log * - EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); + uint32_t + GetPluginVersion() override; protected: /// Runtime linker rendezvous structure. @@ -124,18 +114,22 @@ protected: void UpdateLoadedSections(lldb::ModuleSP module, lldb::addr_t link_map_addr, - lldb::addr_t base_addr); + lldb::addr_t base_addr, + bool base_addr_is_offset) override; /// Removes the loaded sections from the target in @p module. /// /// @param module The module to traverse. void - UnloadSections(const lldb::ModuleSP module); + UnloadSections(const lldb::ModuleSP module) override; /// Locates or creates a module given by @p file and updates/loads the /// resulting module at the virtual base address @p base_addr. lldb::ModuleSP - LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t link_map_addr, lldb::addr_t base_addr); + LoadModuleAtAddress(const lldb_private::FileSpec &file, + lldb::addr_t link_map_addr, + lldb::addr_t base_addr, + bool base_addr_is_offset) override; /// Callback routine invoked when we hit the breakpoint on process entry. /// @@ -173,10 +167,10 @@ protected: FindRendezvousBreakpointAddress( ); private: - DISALLOW_COPY_AND_ASSIGN(DynamicLoaderHexagonDYLD); - const lldb_private::SectionList * GetSectionListFromModule(const lldb::ModuleSP module) const; + + DISALLOW_COPY_AND_ASSIGN(DynamicLoaderHexagonDYLD); }; -#endif // liblldb_DynamicLoaderHexagonDYLD_H_ +#endif // liblldb_DynamicLoaderHexagonDYLD_h_ diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp index 8b1dd283394b6..09e874a011df1 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp @@ -17,6 +17,7 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" @@ -290,19 +291,13 @@ DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry) // FreeBSD and on Android it is the full path to the executable. auto triple = m_process->GetTarget().GetArchitecture().GetTriple(); - auto os_type = triple.getOS(); - auto env_type = triple.getEnvironment(); - - switch (os_type) { + switch (triple.getOS()) { case llvm::Triple::FreeBSD: return entry.file_spec == m_exe_file_spec; case llvm::Triple::Linux: - switch (env_type) { - case llvm::Triple::Android: - return entry.file_spec == m_exe_file_spec; - default: - return !entry.file_spec; - } + if (triple.isAndroid()) + return entry.file_spec == m_exe_file_spec; + return !entry.file_spec; default: return false; } @@ -372,6 +367,25 @@ DYLDRendezvous::ReadStringFromMemory(addr_t addr) return str; } +// Returns true if the load bias reported by the linker is incorrect for the given entry. This +// function is used to handle cases where we want to work around a bug in the system linker. +static bool +isLoadBiasIncorrect(Target& target, const std::string& file_path) +{ + // On Android L (API 21, 22) the load address of the "/system/bin/linker" isn't filled in + // correctly. + uint32_t os_major = 0, os_minor = 0, os_update = 0; + if (target.GetArchitecture().GetTriple().isAndroid() && + target.GetPlatform()->GetOSVersion(os_major, os_minor, os_update) && + (os_major == 21 || os_major == 22) && + (file_path == "/system/bin/linker" || file_path == "/system/bin/linker64")) + { + return true; + } + + return false; +} + bool DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) { @@ -413,11 +427,9 @@ DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) std::string file_path = ReadStringFromMemory(entry.path_addr); entry.file_spec.SetFile(file_path, false); - // On Android L (5.0, 5.1) the load address of the "/system/bin/linker" isn't filled in - // correctly. To get the correct load address we fetch the load address of the file from the - // proc file system. - if (arch.GetTriple().getEnvironment() == llvm::Triple::Android && entry.base_addr == 0 && - (file_path == "/system/bin/linker" || file_path == "/system/bin/linker64")) + // If the load bias reported by the linker is incorrect then fetch the load address of the file + // from the proc file system. + if (isLoadBiasIncorrect(m_process->GetTarget(), file_path)) { lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; bool is_loaded = false; diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index 8724fc039cb91..6ba7b470d7435 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -62,11 +62,6 @@ DynamicLoaderPOSIXDYLD::GetPluginDescriptionStatic() "loads/unloads in POSIX processes."; } -void -DynamicLoaderPOSIXDYLD::GetPluginCommandHelp(const char *command, Stream *strm) -{ -} - uint32_t DynamicLoaderPOSIXDYLD::GetPluginVersion() { @@ -96,7 +91,8 @@ DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process) m_load_offset(LLDB_INVALID_ADDRESS), m_entry_point(LLDB_INVALID_ADDRESS), m_auxv(), - m_dyld_bid(LLDB_INVALID_BREAK_ID) + m_dyld_bid(LLDB_INVALID_BREAK_ID), + m_vdso_base(LLDB_INVALID_ADDRESS) { } @@ -131,6 +127,8 @@ DynamicLoaderPOSIXDYLD::DidAttach() if (log) log->Printf ("DynamicLoaderPOSIXDYLD::%s pid %" PRIu64 " executable '%s', load_offset 0x%" PRIx64, __FUNCTION__, m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, executable_sp ? executable_sp->GetFileSpec().GetPath().c_str () : "", load_offset); + EvalVdsoStatus(); + // if we dont have a load address we cant re-base bool rebase_exec = (load_offset == LLDB_INVALID_ADDRESS) ? false : true; @@ -165,7 +163,7 @@ DynamicLoaderPOSIXDYLD::DidAttach() m_process ? m_process->GetID () : LLDB_INVALID_PROCESS_ID, executable_sp->GetFileSpec().GetPath().c_str ()); - UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset); + UpdateLoadedSections(executable_sp, LLDB_INVALID_ADDRESS, load_offset, true); // When attaching to a target, there are two possible states: // (1) We already crossed the entry point and therefore the rendezvous @@ -218,12 +216,13 @@ DynamicLoaderPOSIXDYLD::DidLaunch() executable = GetTargetExecutable(); load_offset = ComputeLoadOffset(); + EvalVdsoStatus(); if (executable.get() && load_offset != LLDB_INVALID_ADDRESS) { ModuleList module_list; module_list.Append(executable); - UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset); + UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, load_offset, true); if (log) log->Printf ("DynamicLoaderPOSIXDYLD::%s about to call ProbeEntry()", __FUNCTION__); @@ -233,18 +232,6 @@ DynamicLoaderPOSIXDYLD::DidLaunch() } } -Error -DynamicLoaderPOSIXDYLD::ExecutePluginCommand(Args &command, Stream *strm) -{ - return Error(); -} - -Log * -DynamicLoaderPOSIXDYLD::EnablePluginLogging(Stream *strm, Args &command) -{ - return NULL; -} - Error DynamicLoaderPOSIXDYLD::CanLoadImage() { @@ -252,11 +239,13 @@ DynamicLoaderPOSIXDYLD::CanLoadImage() } void -DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr) +DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, + addr_t link_map_addr, + addr_t base_addr, + bool base_addr_is_offset) { m_loaded_modules[module] = link_map_addr; - - UpdateLoadedSectionsCommon(module, base_addr); + UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset); } void @@ -414,7 +403,7 @@ DynamicLoaderPOSIXDYLD::RefreshModules() E = m_rendezvous.loaded_end(); for (I = m_rendezvous.loaded_begin(); I != E; ++I) { - ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr); + ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true); if (module_sp.get()) { loaded_modules.AppendIfNeeded(module_sp); @@ -432,8 +421,7 @@ DynamicLoaderPOSIXDYLD::RefreshModules() for (I = m_rendezvous.unloaded_begin(); I != E; ++I) { ModuleSpec module_spec{I->file_spec}; - ModuleSP module_sp = - loaded_modules.FindFirstModule (module_spec); + ModuleSP module_sp = loaded_modules.FindFirstModule (module_spec); if (module_sp.get()) { @@ -519,11 +507,18 @@ DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() // that ourselves here. ModuleSP executable = GetTargetExecutable(); m_loaded_modules[executable] = m_rendezvous.GetLinkMapAddress(); - - + if (m_vdso_base != LLDB_INVALID_ADDRESS) + { + FileSpec file_spec("[vdso]", false); + ModuleSP module_sp = LoadModuleAtAddress(file_spec, LLDB_INVALID_ADDRESS, m_vdso_base, false); + if (module_sp.get()) + { + module_list.Append(module_sp); + } + } for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) { - ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr); + ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true); if (module_sp.get()) { module_list.Append(module_sp); @@ -568,6 +563,16 @@ DynamicLoaderPOSIXDYLD::ComputeLoadOffset() return m_load_offset; } +void +DynamicLoaderPOSIXDYLD::EvalVdsoStatus() +{ + AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_SYSINFO_EHDR); + + if (I != m_auxv->end()) + m_vdso_base = I->value; + +} + addr_t DynamicLoaderPOSIXDYLD::GetEntryPoint() { diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h index 68d3059cb4bec..cb97bbf43ba92 100644 --- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h +++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h @@ -1,4 +1,4 @@ -//===-- DynamicLoaderPOSIX.h ------------------------------------*- C++ -*-===// +//===-- DynamicLoaderPOSIXDYLD.h --------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,12 +7,13 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_DynamicLoaderPOSIX_H_ -#define liblldb_DynamicLoaderPOSIX_H_ +#ifndef liblldb_DynamicLoaderPOSIXDYLD_h_ +#define liblldb_DynamicLoaderPOSIXDYLD_h_ // C Includes // C++ Includes // Other libraries and framework includes +// Project includes #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Target/DynamicLoader.h" @@ -23,6 +24,9 @@ class AuxVector; class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader { public: + DynamicLoaderPOSIXDYLD(lldb_private::Process *process); + + ~DynamicLoaderPOSIXDYLD() override; static void Initialize(); @@ -39,48 +43,34 @@ public: static lldb_private::DynamicLoader * CreateInstance(lldb_private::Process *process, bool force); - DynamicLoaderPOSIXDYLD(lldb_private::Process *process); - - virtual - ~DynamicLoaderPOSIXDYLD(); - //------------------------------------------------------------------ // DynamicLoader protocol //------------------------------------------------------------------ - virtual void - DidAttach(); + void + DidAttach() override; - virtual void - DidLaunch(); + void + DidLaunch() override; - virtual lldb::ThreadPlanSP + lldb::ThreadPlanSP GetStepThroughTrampolinePlan(lldb_private::Thread &thread, - bool stop_others); + bool stop_others) override; - virtual lldb_private::Error - CanLoadImage(); + lldb_private::Error + CanLoadImage() override; - virtual lldb::addr_t - GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread); + lldb::addr_t + GetThreadLocalData(const lldb::ModuleSP module, const lldb::ThreadSP thread) override; //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); - - virtual uint32_t - GetPluginVersion(); - - virtual void - GetPluginCommandHelp(const char *command, lldb_private::Stream *strm); + lldb_private::ConstString + GetPluginName() override; - virtual lldb_private::Error - ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm); - - virtual lldb_private::Log * - EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command); + uint32_t + GetPluginVersion() override; protected: /// Runtime linker rendezvous structure. @@ -98,12 +88,16 @@ protected: /// Rendezvous breakpoint. lldb::break_id_t m_dyld_bid; + /// Contains AT_SYSINFO_EHDR, which means a vDSO has been + /// mapped to the address space + lldb::addr_t m_vdso_base; + /// Loaded module list. (link map for each module) std::map> m_loaded_modules; /// Enables a breakpoint on a function called by the runtime /// linker each time a module is loaded or unloaded. - void + virtual void SetRendezvousBreakpoint(); /// Callback routine which updates the current list of loaded modules based @@ -126,16 +120,17 @@ protected: /// @param link_map_addr The virtual address of the link map for the @p module. /// /// @param base_addr The virtual base address @p module is loaded at. - virtual void + void UpdateLoadedSections(lldb::ModuleSP module, lldb::addr_t link_map_addr, - lldb::addr_t base_addr); + lldb::addr_t base_addr, + bool base_addr_is_offset) override; /// Removes the loaded sections from the target in @p module. /// /// @param module The module to traverse. - virtual void - UnloadSections(const lldb::ModuleSP module); + void + UnloadSections(const lldb::ModuleSP module) override; /// Resolves the entry point for the current inferior process and sets a /// breakpoint at that address. @@ -155,7 +150,7 @@ protected: /// Helper for the entry breakpoint callback. Resolves the load addresses /// of all dependent modules. - void + virtual void LoadAllCurrentModules(); /// Computes a value for m_load_offset returning the computed address on @@ -168,6 +163,11 @@ protected: lldb::addr_t GetEntryPoint(); + /// Evaluate if Aux vectors contain vDSO information + /// in case they do, read and assign the address to m_vdso_base + void + EvalVdsoStatus(); + /// Loads Module from inferior process. void ResolveExecutableModule(lldb::ModuleSP &module_sp); @@ -176,4 +176,4 @@ private: DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD); }; -#endif // liblldb_DynamicLoaderPOSIXDYLD_H_ +#endif // liblldb_DynamicLoaderPOSIXDYLD_h_ diff --git a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h index ea33164cf8233..a7fdf4d221656 100644 --- a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h +++ b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h @@ -12,12 +12,8 @@ // 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/UUID.h" @@ -27,6 +23,10 @@ class DynamicLoaderStatic : public lldb_private::DynamicLoader { public: + DynamicLoaderStatic(lldb_private::Process *process); + + ~DynamicLoaderStatic() override; + //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ @@ -45,37 +45,33 @@ public: static lldb_private::DynamicLoader * CreateInstance (lldb_private::Process *process, bool force); - DynamicLoaderStatic (lldb_private::Process *process); - - virtual - ~DynamicLoaderStatic (); //------------------------------------------------------------------ /// Called after attaching a process. /// /// Allow DynamicLoader plug-ins to execute some code after /// attaching to a process. //------------------------------------------------------------------ - virtual void - DidAttach (); + void + DidAttach() override; - virtual void - DidLaunch (); + void + DidLaunch() override; - virtual lldb::ThreadPlanSP - GetStepThroughTrampolinePlan (lldb_private::Thread &thread, - bool stop_others); + lldb::ThreadPlanSP + GetStepThroughTrampolinePlan(lldb_private::Thread &thread, + bool stop_others) override; - virtual lldb_private::Error - CanLoadImage (); + lldb_private::Error + CanLoadImage() override; //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ - virtual lldb_private::ConstString - GetPluginName(); + lldb_private::ConstString + GetPluginName() override; - virtual uint32_t - GetPluginVersion(); + uint32_t + GetPluginVersion() override; private: void @@ -84,4 +80,4 @@ private: DISALLOW_COPY_AND_ASSIGN (DynamicLoaderStatic); }; -#endif // liblldb_DynamicLoaderStatic_h_ +#endif // liblldb_DynamicLoaderStatic_h_ diff --git a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp index 56b56ab3a1949..dd391b4ca4d2a 100644 --- a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp +++ b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp @@ -21,40 +21,39 @@ using namespace lldb_private; DynamicLoaderWindowsDYLD::DynamicLoaderWindowsDYLD(Process *process) : DynamicLoader(process) { - } DynamicLoaderWindowsDYLD::~DynamicLoaderWindowsDYLD() { - } -void DynamicLoaderWindowsDYLD::Initialize() +void +DynamicLoaderWindowsDYLD::Initialize() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), - CreateInstance); + PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance); } -void DynamicLoaderWindowsDYLD::Terminate() +void +DynamicLoaderWindowsDYLD::Terminate() { - } -ConstString DynamicLoaderWindowsDYLD::GetPluginNameStatic() +ConstString +DynamicLoaderWindowsDYLD::GetPluginNameStatic() { static ConstString g_plugin_name("windows-dyld"); return g_plugin_name; } -const char *DynamicLoaderWindowsDYLD::GetPluginDescriptionStatic() +const char * +DynamicLoaderWindowsDYLD::GetPluginDescriptionStatic() { return "Dynamic loader plug-in that watches for shared library " "loads/unloads in Windows processes."; } - -DynamicLoader *DynamicLoaderWindowsDYLD::CreateInstance(Process *process, bool force) +DynamicLoader * +DynamicLoaderWindowsDYLD::CreateInstance(Process *process, bool force) { bool should_create = force; if (!should_create) @@ -65,32 +64,35 @@ DynamicLoader *DynamicLoaderWindowsDYLD::CreateInstance(Process *process, bool f } if (should_create) - return new DynamicLoaderWindowsDYLD (process); + return new DynamicLoaderWindowsDYLD(process); return nullptr; } -void DynamicLoaderWindowsDYLD::DidAttach() +void +DynamicLoaderWindowsDYLD::DidAttach() { - } -void DynamicLoaderWindowsDYLD::DidLaunch() +void +DynamicLoaderWindowsDYLD::DidLaunch() { - } -Error DynamicLoaderWindowsDYLD::CanLoadImage() +Error +DynamicLoaderWindowsDYLD::CanLoadImage() { return Error(); } -ConstString DynamicLoaderWindowsDYLD::GetPluginName() +ConstString +DynamicLoaderWindowsDYLD::GetPluginName() { return GetPluginNameStatic(); } -uint32_t DynamicLoaderWindowsDYLD::GetPluginVersion() +uint32_t +DynamicLoaderWindowsDYLD::GetPluginVersion() { return 1; } diff --git a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h index d12b999f4627c..8c479819c535b 100644 --- a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h +++ b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h @@ -1,4 +1,4 @@ -//===-- DynamicLoaderWindowsDYLDh ----------------------------------*- C++ -*-===// +//===-- DynamicLoaderWindowsDYLD.h ------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,9 +7,13 @@ // //===----------------------------------------------------------------------===// -#ifndef liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_H_ -#define liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_H_ +#ifndef liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_h_ +#define liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_h_ +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes #include "lldb/lldb-forward.h" #include "lldb/Target/DynamicLoader.h" @@ -18,9 +22,10 @@ namespace lldb_private class DynamicLoaderWindowsDYLD : public DynamicLoader { - public: +public: DynamicLoaderWindowsDYLD(Process *process); - virtual ~DynamicLoaderWindowsDYLD(); + + ~DynamicLoaderWindowsDYLD() override; static void Initialize(); static void Terminate(); @@ -29,15 +34,15 @@ class DynamicLoaderWindowsDYLD : public DynamicLoader static DynamicLoader *CreateInstance(Process *process, bool force); - void DidAttach () override; - void DidLaunch () override; - Error CanLoadImage () override; + void DidAttach() override; + void DidLaunch() override; + Error CanLoadImage() override; lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread, bool stop) override; ConstString GetPluginName() override; uint32_t GetPluginVersion() override; }; -} +} // namespace lldb_private -#endif +#endif // liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp b/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp new file mode 100644 index 0000000000000..976310610f51d --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ASTDumper.cpp @@ -0,0 +1,134 @@ +//===-- ASTDumper.cpp -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ASTDumper.h" + +#include "lldb/Core/Log.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompilerType.h" + +#include "llvm/Support/raw_ostream.h" + +using namespace lldb_private; + +ASTDumper::ASTDumper (clang::Decl *decl) +{ + clang::DeclContext *decl_ctx = llvm::dyn_cast(decl); + + bool has_external_lexical_storage; + bool has_external_visible_storage; + + if (decl_ctx) + { + has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage(); + has_external_visible_storage = decl_ctx->hasExternalVisibleStorage(); + decl_ctx->setHasExternalLexicalStorage(false); + decl_ctx->setHasExternalVisibleStorage(false); + } + + llvm::raw_string_ostream os(m_dump); + decl->print (os); + os.flush(); + + if (decl_ctx) + { + decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage); + decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage); + } +} + +ASTDumper::ASTDumper (clang::DeclContext *decl_ctx) +{ + bool has_external_lexical_storage = decl_ctx->hasExternalLexicalStorage(); + bool has_external_visible_storage = decl_ctx->hasExternalVisibleStorage(); + + decl_ctx->setHasExternalLexicalStorage(false); + decl_ctx->setHasExternalVisibleStorage(false); + + if (clang::Decl *decl = llvm::dyn_cast(decl_ctx)) + { + llvm::raw_string_ostream os(m_dump); + decl->print (os); + os.flush(); + } + else + { + m_dump.assign(""); + } + + decl_ctx->setHasExternalLexicalStorage(has_external_lexical_storage); + decl_ctx->setHasExternalVisibleStorage(has_external_visible_storage); +} + +ASTDumper::ASTDumper (const clang::Type *type) +{ + m_dump = clang::QualType(type, 0).getAsString(); +} + +ASTDumper::ASTDumper (clang::QualType type) +{ + m_dump = type.getAsString(); +} + +ASTDumper::ASTDumper (lldb::opaque_compiler_type_t type) +{ + m_dump = clang::QualType::getFromOpaquePtr(type).getAsString(); +} + +ASTDumper::ASTDumper (const CompilerType &compiler_type) +{ + m_dump = ClangASTContext::GetQualType(compiler_type).getAsString(); +} + + +const char * +ASTDumper::GetCString() +{ + return m_dump.c_str(); +} + +void ASTDumper::ToSTDERR() +{ + fprintf(stderr, "%s\n", m_dump.c_str()); +} + +void ASTDumper::ToLog(Log *log, const char *prefix) +{ + size_t len = m_dump.length() + 1; + + char *alloc = (char*)malloc(len); + char *str = alloc; + + memcpy(str, m_dump.c_str(), len); + + char *end = NULL; + + end = strchr(str, '\n'); + + while (end) + { + *end = '\0'; + + log->Printf("%s%s", prefix, str); + + *end = '\n'; + + str = end + 1; + end = strchr(str, '\n'); + } + + log->Printf("%s%s", prefix, str); + + free(alloc); +} + +void ASTDumper::ToStream(lldb::StreamSP &stream) +{ + stream->PutCString(m_dump.c_str()); +} diff --git a/source/Plugins/ExpressionParser/Clang/ASTDumper.h b/source/Plugins/ExpressionParser/Clang/ASTDumper.h new file mode 100644 index 0000000000000..c8dc6847d6c2d --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ASTDumper.h @@ -0,0 +1,42 @@ +//===-- ASTDumper.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ASTDumper_h_ +#define liblldb_ASTDumper_h_ + +#include "clang/AST/DeclVisitor.h" +#include "clang/AST/TypeVisitor.h" + +#include "lldb/Core/Stream.h" +#include "llvm/ADT/DenseSet.h" + +namespace lldb_private +{ + +class ASTDumper +{ +public: + ASTDumper (clang::Decl *decl); + ASTDumper (clang::DeclContext *decl_ctx); + ASTDumper (const clang::Type *type); + ASTDumper (clang::QualType type); + ASTDumper (lldb::opaque_compiler_type_t type); + ASTDumper (const CompilerType &compiler_type); + + const char *GetCString(); + void ToSTDERR(); + void ToLog(Log *log, const char *prefix); + void ToStream(lldb::StreamSP &stream); +private: + std::string m_dump; +}; + +} // namespace lldb_private + +#endif diff --git a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp new file mode 100644 index 0000000000000..02505bde240c2 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp @@ -0,0 +1,514 @@ +//===-- ASTResultSynthesizer.cpp --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ASTResultSynthesizer.h" + +#include "ClangPersistentVariables.h" + +#include "stdlib.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclGroup.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Stmt.h" +#include "clang/Parse/Parser.h" +#include "clang/Sema/SemaDiagnostic.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" +#include "lldb/Core/Log.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ClangASTImporter.h" +#include "lldb/Target/Target.h" + +using namespace llvm; +using namespace clang; +using namespace lldb_private; + +ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough, + Target &target) : + m_ast_context (NULL), + m_passthrough (passthrough), + m_passthrough_sema (NULL), + m_target (target), + m_sema (NULL) +{ + if (!m_passthrough) + return; + + m_passthrough_sema = dyn_cast(passthrough); +} + +ASTResultSynthesizer::~ASTResultSynthesizer() +{ +} + +void +ASTResultSynthesizer::Initialize(ASTContext &Context) +{ + m_ast_context = &Context; + + if (m_passthrough) + m_passthrough->Initialize(Context); +} + +void +ASTResultSynthesizer::TransformTopLevelDecl(Decl* D) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (NamedDecl *named_decl = dyn_cast(D)) + { + if (log && log->GetVerbose()) + { + if (named_decl->getIdentifier()) + log->Printf("TransformTopLevelDecl(%s)", named_decl->getIdentifier()->getNameStart()); + else if (ObjCMethodDecl *method_decl = dyn_cast(D)) + log->Printf("TransformTopLevelDecl(%s)", method_decl->getSelector().getAsString().c_str()); + else + log->Printf("TransformTopLevelDecl()"); + } + + } + + if (LinkageSpecDecl *linkage_spec_decl = dyn_cast(D)) + { + RecordDecl::decl_iterator decl_iterator; + + for (decl_iterator = linkage_spec_decl->decls_begin(); + decl_iterator != linkage_spec_decl->decls_end(); + ++decl_iterator) + { + TransformTopLevelDecl(*decl_iterator); + } + } + else if (ObjCMethodDecl *method_decl = dyn_cast(D)) + { + if (m_ast_context && + !method_decl->getSelector().getAsString().compare("$__lldb_expr:")) + { + RecordPersistentTypes(method_decl); + SynthesizeObjCMethodResult(method_decl); + } + } + else if (FunctionDecl *function_decl = dyn_cast(D)) + { + if (m_ast_context && + !function_decl->getNameInfo().getAsString().compare("$__lldb_expr")) + { + RecordPersistentTypes(function_decl); + SynthesizeFunctionResult(function_decl); + } + } +} + +bool +ASTResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D) +{ + DeclGroupRef::iterator decl_iterator; + + for (decl_iterator = D.begin(); + decl_iterator != D.end(); + ++decl_iterator) + { + Decl *decl = *decl_iterator; + + TransformTopLevelDecl(decl); + } + + if (m_passthrough) + return m_passthrough->HandleTopLevelDecl(D); + return true; +} + +bool +ASTResultSynthesizer::SynthesizeFunctionResult (FunctionDecl *FunDecl) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (!m_sema) + return false; + + FunctionDecl *function_decl = FunDecl; + + if (!function_decl) + return false; + + if (log && log->GetVerbose()) + { + std::string s; + raw_string_ostream os(s); + + function_decl->print(os); + + os.flush(); + + log->Printf ("Untransformed function AST:\n%s", s.c_str()); + } + + Stmt *function_body = function_decl->getBody(); + CompoundStmt *compound_stmt = dyn_cast(function_body); + + bool ret = SynthesizeBodyResult (compound_stmt, + function_decl); + + if (log && log->GetVerbose()) + { + std::string s; + raw_string_ostream os(s); + + function_decl->print(os); + + os.flush(); + + log->Printf ("Transformed function AST:\n%s", s.c_str()); + } + + return ret; +} + +bool +ASTResultSynthesizer::SynthesizeObjCMethodResult (ObjCMethodDecl *MethodDecl) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (!m_sema) + return false; + + if (!MethodDecl) + return false; + + if (log && log->GetVerbose()) + { + std::string s; + raw_string_ostream os(s); + + MethodDecl->print(os); + + os.flush(); + + log->Printf ("Untransformed method AST:\n%s", s.c_str()); + } + + Stmt *method_body = MethodDecl->getBody(); + + if (!method_body) + return false; + + CompoundStmt *compound_stmt = dyn_cast(method_body); + + bool ret = SynthesizeBodyResult (compound_stmt, + MethodDecl); + + if (log && log->GetVerbose()) + { + std::string s; + raw_string_ostream os(s); + + MethodDecl->print(os); + + os.flush(); + + log->Printf("Transformed method AST:\n%s", s.c_str()); + } + + return ret; +} + +bool +ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body, + DeclContext *DC) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + ASTContext &Ctx(*m_ast_context); + + if (!Body) + return false; + + if (Body->body_empty()) + return false; + + Stmt **last_stmt_ptr = Body->body_end() - 1; + Stmt *last_stmt = *last_stmt_ptr; + + while (dyn_cast(last_stmt)) + { + if (last_stmt_ptr != Body->body_begin()) + { + last_stmt_ptr--; + last_stmt = *last_stmt_ptr; + } + else + { + return false; + } + } + + Expr *last_expr = dyn_cast(last_stmt); + + if (!last_expr) + // No auxiliary variable necessary; expression returns void + return true; + + // In C++11, last_expr can be a LValueToRvalue implicit cast. Strip that off if that's the + // case. + + do { + ImplicitCastExpr *implicit_cast = dyn_cast(last_expr); + + if (!implicit_cast) + break; + + if (implicit_cast->getCastKind() != CK_LValueToRValue) + break; + + last_expr = implicit_cast->getSubExpr(); + } while (0); + + // is_lvalue is used to record whether the expression returns an assignable Lvalue or an + // Rvalue. This is relevant because they are handled differently. + // + // For Lvalues + // + // - In AST result synthesis (here!) the expression E is transformed into an initialization + // T *$__lldb_expr_result_ptr = &E. + // + // - In structure allocation, a pointer-sized slot is allocated in the struct that is to be + // passed into the expression. + // + // - In IR transformations, reads and writes to $__lldb_expr_result_ptr are redirected at + // an entry in the struct ($__lldb_arg) passed into the expression. (Other persistent + // variables are treated similarly, having been materialized as references, but in those + // cases the value of the reference itself is never modified.) + // + // - During materialization, $0 (the result persistent variable) is ignored. + // + // - During dematerialization, $0 is marked up as a load address with value equal to the + // contents of the structure entry. + // + // For Rvalues + // + // - In AST result synthesis the expression E is transformed into an initialization + // static T $__lldb_expr_result = E. + // + // - In structure allocation, a pointer-sized slot is allocated in the struct that is to be + // passed into the expression. + // + // - In IR transformations, an instruction is inserted at the beginning of the function to + // dereference the pointer resident in the slot. Reads and writes to $__lldb_expr_result + // are redirected at that dereferenced version. Guard variables for the static variable + // are excised. + // + // - During materialization, $0 (the result persistent variable) is populated with the location + // of a newly-allocated area of memory. + // + // - During dematerialization, $0 is ignored. + + bool is_lvalue = + (last_expr->getValueKind() == VK_LValue || last_expr->getValueKind() == VK_XValue) && + (last_expr->getObjectKind() == OK_Ordinary); + + QualType expr_qual_type = last_expr->getType(); + const clang::Type *expr_type = expr_qual_type.getTypePtr(); + + if (!expr_type) + return false; + + if (expr_type->isVoidType()) + return true; + + if (log) + { + std::string s = expr_qual_type.getAsString(); + + log->Printf("Last statement is an %s with type: %s", (is_lvalue ? "lvalue" : "rvalue"), s.c_str()); + } + + clang::VarDecl *result_decl = NULL; + + if (is_lvalue) + { + IdentifierInfo *result_ptr_id; + + if (expr_type->isFunctionType()) + result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result"); // functions actually should be treated like function pointers + else + result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result_ptr"); + + m_sema->RequireCompleteType(SourceLocation(), expr_qual_type, clang::diag::err_incomplete_type); + + QualType ptr_qual_type; + + if (expr_qual_type->getAs() != NULL) + ptr_qual_type = Ctx.getObjCObjectPointerType(expr_qual_type); + else + ptr_qual_type = Ctx.getPointerType(expr_qual_type); + + result_decl = VarDecl::Create(Ctx, + DC, + SourceLocation(), + SourceLocation(), + result_ptr_id, + ptr_qual_type, + NULL, + SC_Static); + + if (!result_decl) + return false; + + ExprResult address_of_expr = m_sema->CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, last_expr); + + m_sema->AddInitializerToDecl(result_decl, address_of_expr.get(), true, false); + } + else + { + IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result"); + + result_decl = VarDecl::Create(Ctx, + DC, + SourceLocation(), + SourceLocation(), + &result_id, + expr_qual_type, + NULL, + SC_Static); + + if (!result_decl) + return false; + + m_sema->AddInitializerToDecl(result_decl, last_expr, true, false); + } + + DC->addDecl(result_decl); + + /////////////////////////////// + // call AddInitializerToDecl + // + + //m_sema->AddInitializerToDecl(result_decl, last_expr); + + ///////////////////////////////// + // call ConvertDeclToDeclGroup + // + + Sema::DeclGroupPtrTy result_decl_group_ptr; + + result_decl_group_ptr = m_sema->ConvertDeclToDeclGroup(result_decl); + + //////////////////////// + // call ActOnDeclStmt + // + + StmtResult result_initialization_stmt_result(m_sema->ActOnDeclStmt(result_decl_group_ptr, + SourceLocation(), + SourceLocation())); + + //////////////////////////////////////////////// + // replace the old statement with the new one + // + + *last_stmt_ptr = reinterpret_cast(result_initialization_stmt_result.get()); + + return true; +} + +void +ASTResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx) +{ + if (m_passthrough) + m_passthrough->HandleTranslationUnit(Ctx); +} + +void +ASTResultSynthesizer::RecordPersistentTypes(DeclContext *FunDeclCtx) +{ + typedef DeclContext::specific_decl_iterator TypeDeclIterator; + + for (TypeDeclIterator i = TypeDeclIterator(FunDeclCtx->decls_begin()), + e = TypeDeclIterator(FunDeclCtx->decls_end()); + i != e; + ++i) + { + MaybeRecordPersistentType(*i); + } +} + +void +ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl *D) +{ + if (!D->getIdentifier()) + return; + + StringRef name = D->getName(); + + if (name.size() == 0 || name[0] != '$') + return; + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + ConstString name_cs(name.str().c_str()); + + if (log) + log->Printf ("Recording persistent type %s\n", name_cs.GetCString()); + + Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl(m_target.GetScratchClangASTContext()->getASTContext(), + m_ast_context, + D); + + if (TypeDecl *TypeDecl_scratch = dyn_cast(D_scratch)) + llvm::cast(m_target.GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))->RegisterPersistentType(name_cs, TypeDecl_scratch); +} + +void +ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D) +{ + if (m_passthrough) + m_passthrough->HandleTagDeclDefinition(D); +} + +void +ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D) +{ + if (m_passthrough) + m_passthrough->CompleteTentativeDefinition(D); +} + +void +ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD) +{ + if (m_passthrough) + m_passthrough->HandleVTable(RD); +} + +void +ASTResultSynthesizer::PrintStats() +{ + if (m_passthrough) + m_passthrough->PrintStats(); +} + +void +ASTResultSynthesizer::InitializeSema(Sema &S) +{ + m_sema = &S; + + if (m_passthrough_sema) + m_passthrough_sema->InitializeSema(S); +} + +void +ASTResultSynthesizer::ForgetSema() +{ + m_sema = NULL; + + if (m_passthrough_sema) + m_passthrough_sema->ForgetSema(); +} diff --git a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h new file mode 100644 index 0000000000000..9f7bbe05b0822 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.h @@ -0,0 +1,185 @@ +//===-- ASTResultSynthesizer.h ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ASTResultSynthesizer_h_ +#define liblldb_ASTResultSynthesizer_h_ + +#include "clang/Sema/SemaConsumer.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Target/Target.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ASTResultSynthesizer ASTResultSynthesizer.h "lldb/Expression/ASTResultSynthesizer.h" +/// @brief Adds a result variable declaration to the ASTs for an expression. +/// +/// Users expect the expression "i + 3" to return a result, even if a result +/// variable wasn't specifically declared. To fulfil this requirement, LLDB adds +/// a result variable to the expression, transforming it to +/// "int $__lldb_expr_result = i + 3." The IR transformers ensure that the +/// resulting variable is mapped to the right piece of memory. +/// ASTResultSynthesizer's job is to add the variable and its initialization to +/// the ASTs for the expression, and it does so by acting as a SemaConsumer for +/// Clang. +//---------------------------------------------------------------------- +class ASTResultSynthesizer : public clang::SemaConsumer +{ +public: + //---------------------------------------------------------------------- + /// Constructor + /// + /// @param[in] passthrough + /// Since the ASTs must typically go through to the Clang code generator + /// in order to produce LLVM IR, this SemaConsumer must allow them to + /// pass to the next step in the chain after processing. Passthrough is + /// the next ASTConsumer, or NULL if none is required. + /// + /// @param[in] target + /// The target, which contains the persistent variable store and the + /// AST importer. + //---------------------------------------------------------------------- + ASTResultSynthesizer(clang::ASTConsumer *passthrough, + Target &target); + + //---------------------------------------------------------------------- + /// Destructor + //---------------------------------------------------------------------- + ~ASTResultSynthesizer() override; + + //---------------------------------------------------------------------- + /// Link this consumer with a particular AST context + /// + /// @param[in] Context + /// This AST context will be used for types and identifiers, and also + /// forwarded to the passthrough consumer, if one exists. + //---------------------------------------------------------------------- + void Initialize(clang::ASTContext &Context) override; + + //---------------------------------------------------------------------- + /// Examine a list of Decls to find the function $__lldb_expr and + /// transform its code + /// + /// @param[in] D + /// The list of Decls to search. These may contain LinkageSpecDecls, + /// which need to be searched recursively. That job falls to + /// TransformTopLevelDecl. + //---------------------------------------------------------------------- + bool HandleTopLevelDecl(clang::DeclGroupRef D) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleTranslationUnit(clang::ASTContext &Ctx) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleTagDeclDefinition(clang::TagDecl *D) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void CompleteTentativeDefinition(clang::VarDecl *D) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleVTable(clang::CXXRecordDecl *RD) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void PrintStats() override; + + //---------------------------------------------------------------------- + /// Set the Sema object to use when performing transforms, and pass it on + /// + /// @param[in] S + /// The Sema to use. Because Sema isn't externally visible, this class + /// casts it to an Action for actual use. + //---------------------------------------------------------------------- + void InitializeSema(clang::Sema &S) override; + + //---------------------------------------------------------------------- + /// Reset the Sema to NULL now that transformations are done + //---------------------------------------------------------------------- + void ForgetSema() override; + +private: + //---------------------------------------------------------------------- + /// Hunt the given Decl for FunctionDecls named $__lldb_expr, recursing + /// as necessary through LinkageSpecDecls, and calling SynthesizeResult on + /// anything that was found + /// + /// @param[in] D + /// The Decl to hunt. + //---------------------------------------------------------------------- + void TransformTopLevelDecl(clang::Decl *D); + + //---------------------------------------------------------------------- + /// Process an Objective-C method and produce the result variable and + /// initialization + /// + /// @param[in] MethodDecl + /// The method to process. + //---------------------------------------------------------------------- + bool SynthesizeObjCMethodResult(clang::ObjCMethodDecl *MethodDecl); + + //---------------------------------------------------------------------- + /// Process a function and produce the result variable and initialization + /// + /// @param[in] FunDecl + /// The function to process. + //---------------------------------------------------------------------- + bool SynthesizeFunctionResult(clang::FunctionDecl *FunDecl); + + //---------------------------------------------------------------------- + /// Process a function body and produce the result variable and + /// initialization + /// + /// @param[in] Body + /// The body of the function. + /// + /// @param[in] DC + /// The DeclContext of the function, into which the result variable + /// is inserted. + //---------------------------------------------------------------------- + bool SynthesizeBodyResult(clang::CompoundStmt *Body, + clang::DeclContext *DC); + + //---------------------------------------------------------------------- + /// Given a DeclContext for a function or method, find all types + /// declared in the context and record any persistent types found. + /// + /// @param[in] FunDeclCtx + /// The context for the function to process. + //---------------------------------------------------------------------- + void RecordPersistentTypes(clang::DeclContext *FunDeclCtx); + + //---------------------------------------------------------------------- + /// Given a TypeDecl, if it declares a type whose name starts with a + /// dollar sign, register it as a pointer type in the target's scratch + /// AST context. + /// + /// @param[in] Body + /// The body of the function. + //---------------------------------------------------------------------- + void MaybeRecordPersistentType(clang::TypeDecl *D); + + clang::ASTContext *m_ast_context; ///< The AST context to use for identifiers and types. + clang::ASTConsumer *m_passthrough; ///< The ASTConsumer down the chain, for passthrough. NULL if it's a SemaConsumer. + clang::SemaConsumer *m_passthrough_sema; ///< The SemaConsumer down the chain, for passthrough. NULL if it's an ASTConsumer. + Target &m_target; ///< The target, which contains the persistent variable store and the + clang::Sema *m_sema; ///< The Sema to use. +}; + +} // namespace lldb_private + +#endif // liblldb_ASTResultSynthesizer_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp new file mode 100644 index 0000000000000..38a2b6b33a8ab --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.cpp @@ -0,0 +1,221 @@ +//===-- ASTStructExtractor.cpp ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ASTStructExtractor.h" + +#include "stdlib.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclGroup.h" +#include "clang/AST/Expr.h" +#include "clang/AST/RecordLayout.h" +#include "clang/AST/Stmt.h" +#include "clang/Parse/Parser.h" +#include "clang/Sema/Sema.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" +#include "lldb/Core/Log.h" + +using namespace llvm; +using namespace clang; +using namespace lldb_private; + +ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough, + const char *struct_name, + ClangFunctionCaller &function) : + m_ast_context (NULL), + m_passthrough (passthrough), + m_passthrough_sema (NULL), + m_sema (NULL), + m_action (NULL), + m_function (function), + m_struct_name (struct_name) +{ + if (!m_passthrough) + return; + + m_passthrough_sema = dyn_cast(passthrough); +} + +ASTStructExtractor::~ASTStructExtractor() +{ +} + +void +ASTStructExtractor::Initialize(ASTContext &Context) +{ + m_ast_context = &Context; + + if (m_passthrough) + m_passthrough->Initialize(Context); +} + +void +ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F) +{ + if (!F->hasBody()) + return; + + Stmt *body_stmt = F->getBody(); + CompoundStmt *body_compound_stmt = dyn_cast(body_stmt); + + if (!body_compound_stmt) + return; // do we have to handle this? + + RecordDecl *struct_decl = NULL; + + StringRef desired_name(m_struct_name.c_str()); + + for (CompoundStmt::const_body_iterator bi = body_compound_stmt->body_begin(), be = body_compound_stmt->body_end(); + bi != be; + ++bi) + { + Stmt *curr_stmt = *bi; + DeclStmt *curr_decl_stmt = dyn_cast(curr_stmt); + if (!curr_decl_stmt) + continue; + DeclGroupRef decl_group = curr_decl_stmt->getDeclGroup(); + for (Decl *candidate_decl : decl_group) + { + RecordDecl *candidate_record_decl = dyn_cast(candidate_decl); + if (!candidate_record_decl) + continue; + if (candidate_record_decl->getName() == desired_name) + { + struct_decl = candidate_record_decl; + break; + } + } + if (struct_decl) + break; + } + + if (!struct_decl) + return; + + const ASTRecordLayout* struct_layout(&m_ast_context->getASTRecordLayout (struct_decl)); + + if (!struct_layout) + return; + + m_function.m_struct_size = struct_layout->getSize().getQuantity(); // TODO Store m_struct_size as CharUnits + m_function.m_return_offset = struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8; + m_function.m_return_size = struct_layout->getDataSize().getQuantity() - m_function.m_return_offset; + + for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount(); + field_index < num_fields; + ++field_index) + { + m_function.m_member_offsets.push_back(struct_layout->getFieldOffset(field_index) / 8); + } + + m_function.m_struct_valid = true; +} + +void +ASTStructExtractor::ExtractFromTopLevelDecl(Decl* D) +{ + LinkageSpecDecl *linkage_spec_decl = dyn_cast(D); + + if (linkage_spec_decl) + { + RecordDecl::decl_iterator decl_iterator; + + for (decl_iterator = linkage_spec_decl->decls_begin(); + decl_iterator != linkage_spec_decl->decls_end(); + ++decl_iterator) + { + ExtractFromTopLevelDecl(*decl_iterator); + } + } + + FunctionDecl *function_decl = dyn_cast(D); + + if (m_ast_context && + function_decl && + !m_function.m_wrapper_function_name.compare(function_decl->getNameAsString().c_str())) + { + ExtractFromFunctionDecl(function_decl); + } +} + +bool +ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D) +{ + DeclGroupRef::iterator decl_iterator; + + for (decl_iterator = D.begin(); + decl_iterator != D.end(); + ++decl_iterator) + { + Decl *decl = *decl_iterator; + + ExtractFromTopLevelDecl(decl); + } + + if (m_passthrough) + return m_passthrough->HandleTopLevelDecl(D); + return true; +} + +void +ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx) +{ + if (m_passthrough) + m_passthrough->HandleTranslationUnit(Ctx); +} + +void +ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D) +{ + if (m_passthrough) + m_passthrough->HandleTagDeclDefinition(D); +} + +void +ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D) +{ + if (m_passthrough) + m_passthrough->CompleteTentativeDefinition(D); +} + +void +ASTStructExtractor::HandleVTable(CXXRecordDecl *RD) +{ + if (m_passthrough) + m_passthrough->HandleVTable(RD); +} + +void +ASTStructExtractor::PrintStats() +{ + if (m_passthrough) + m_passthrough->PrintStats(); +} + +void +ASTStructExtractor::InitializeSema(Sema &S) +{ + m_sema = &S; + m_action = reinterpret_cast(m_sema); + + if (m_passthrough_sema) + m_passthrough_sema->InitializeSema(S); +} + +void +ASTStructExtractor::ForgetSema() +{ + m_sema = NULL; + m_action = NULL; + + if (m_passthrough_sema) + m_passthrough_sema->ForgetSema(); +} diff --git a/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h new file mode 100644 index 0000000000000..2152cff911ff4 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ASTStructExtractor.h @@ -0,0 +1,158 @@ +//===-- ASTStructExtractor.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ASTStructExtractor_h_ +#define liblldb_ASTStructExtractor_h_ + +#include "ClangExpressionVariable.h" +#include "ClangFunctionCaller.h" + +#include "clang/Sema/SemaConsumer.h" +#include "lldb/Core/ClangForward.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ASTStructExtractor ASTStructExtractor.h "lldb/Expression/ASTStructExtractor.h" +/// @brief Extracts and describes the argument structure for a wrapped function. +/// +/// This pass integrates with ClangFunctionCaller, which calls functions with custom +/// sets of arguments. To avoid having to implement the full calling convention +/// for the target's architecture, ClangFunctionCaller writes a simple wrapper +/// function that takes a pointer to an argument structure that contains room +/// for the address of the function to be called, the values of all its +/// arguments, and room for the function's return value. +/// +/// The definition of this struct is itself in the body of the wrapper function, +/// so Clang does the structure layout itself. ASTStructExtractor reads through +/// the AST for the wrapper function and finds the struct. +//---------------------------------------------------------------------- +class ASTStructExtractor : public clang::SemaConsumer +{ +public: + //---------------------------------------------------------------------- + /// Constructor + /// + /// @param[in] passthrough + /// Since the ASTs must typically go through to the Clang code generator + /// in order to produce LLVM IR, this SemaConsumer must allow them to + /// pass to the next step in the chain after processing. Passthrough is + /// the next ASTConsumer, or NULL if none is required. + /// + /// @param[in] struct_name + /// The name of the structure to extract from the wrapper function. + /// + /// @param[in] function + /// The caller object whose members should be populated with information + /// about the argument struct. ClangFunctionCaller friends ASTStructExtractor + /// for this purpose. + //---------------------------------------------------------------------- + ASTStructExtractor(clang::ASTConsumer *passthrough, + const char *struct_name, + ClangFunctionCaller &function); + + //---------------------------------------------------------------------- + /// Destructor + //---------------------------------------------------------------------- + ~ASTStructExtractor() override; + + //---------------------------------------------------------------------- + /// Link this consumer with a particular AST context + /// + /// @param[in] Context + /// This AST context will be used for types and identifiers, and also + /// forwarded to the passthrough consumer, if one exists. + //---------------------------------------------------------------------- + void Initialize(clang::ASTContext &Context) override; + + //---------------------------------------------------------------------- + /// Examine a list of Decls to find the function $__lldb_expr and + /// transform its code + /// + /// @param[in] D + /// The list of Decls to search. These may contain LinkageSpecDecls, + /// which need to be searched recursively. That job falls to + /// TransformTopLevelDecl. + //---------------------------------------------------------------------- + bool HandleTopLevelDecl(clang::DeclGroupRef D) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleTranslationUnit(clang::ASTContext &Ctx) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleTagDeclDefinition(clang::TagDecl *D) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void CompleteTentativeDefinition(clang::VarDecl *D) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void HandleVTable(clang::CXXRecordDecl *RD) override; + + //---------------------------------------------------------------------- + /// Passthrough stub + //---------------------------------------------------------------------- + void PrintStats() override; + + //---------------------------------------------------------------------- + /// Set the Sema object to use when performing transforms, and pass it on + /// + /// @param[in] S + /// The Sema to use. Because Sema isn't externally visible, this class + /// casts it to an Action for actual use. + //---------------------------------------------------------------------- + void InitializeSema(clang::Sema &S) override; + + //---------------------------------------------------------------------- + /// Reset the Sema to NULL now that transformations are done + //---------------------------------------------------------------------- + void ForgetSema() override; + +private: + //---------------------------------------------------------------------- + /// Hunt the given FunctionDecl for the argument struct and place + /// information about it into m_function + /// + /// @param[in] F + /// The FunctionDecl to hunt. + //---------------------------------------------------------------------- + void + ExtractFromFunctionDecl(clang::FunctionDecl* F); + + //---------------------------------------------------------------------- + /// Hunt the given Decl for FunctionDecls named the same as the wrapper + /// function name, recursing as necessary through LinkageSpecDecls, and + /// calling ExtractFromFunctionDecl on anything that was found + /// + /// @param[in] D + /// The Decl to hunt. + //---------------------------------------------------------------------- + void + ExtractFromTopLevelDecl(clang::Decl* D); + + clang::ASTContext *m_ast_context; ///< The AST context to use for identifiers and types. + clang::ASTConsumer *m_passthrough; ///< The ASTConsumer down the chain, for passthrough. NULL if it's a SemaConsumer. + clang::SemaConsumer *m_passthrough_sema; ///< The SemaConsumer down the chain, for passthrough. NULL if it's an ASTConsumer. + clang::Sema *m_sema; ///< The Sema to use. + clang::Action *m_action; ///< The Sema to use, cast to an Action so it's usable. + + ClangFunctionCaller &m_function; ///< The function to populate with information about the argument structure. + std::string m_struct_name; ///< The name of the structure to extract. +}; + +} // namespace lldb_private + +#endif // liblldb_ASTStructExtractor_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp new file mode 100644 index 0000000000000..d2ea4390560a5 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -0,0 +1,2101 @@ +//===-- ClangASTSource.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangASTSource.h" + +#include "ASTDumper.h" +#include "ClangModulesDeclVendor.h" + +#include "clang/AST/ASTContext.h" +#include "clang/AST/RecordLayout.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleList.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompilerDeclContext.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/TaggedASTType.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Target.h" + +#include + +using namespace clang; +using namespace lldb_private; + +//------------------------------------------------------------------ +// Scoped class that will remove an active lexical decl from the set +// when it goes out of scope. +//------------------------------------------------------------------ +namespace { + class ScopedLexicalDeclEraser + { + public: + ScopedLexicalDeclEraser(std::set &decls, + const clang::Decl *decl) + : m_active_lexical_decls(decls), m_decl(decl) + { + } + + ~ScopedLexicalDeclEraser() + { + m_active_lexical_decls.erase(m_decl); + } + + private: + std::set &m_active_lexical_decls; + const clang::Decl *m_decl; + }; +} + +ClangASTSource::~ClangASTSource() +{ + m_ast_importer_sp->ForgetDestination(m_ast_context); + + // We are in the process of destruction, don't create clang ast context on demand + // by passing false to Target::GetScratchClangASTContext(create_on_demand). + ClangASTContext *scratch_clang_ast_context = m_target->GetScratchClangASTContext(false); + + if (!scratch_clang_ast_context) + return; + + clang::ASTContext *scratch_ast_context = scratch_clang_ast_context->getASTContext(); + + if (!scratch_ast_context) + return; + + if (m_ast_context != scratch_ast_context) + m_ast_importer_sp->ForgetSource(scratch_ast_context, m_ast_context); +} + +void +ClangASTSource::StartTranslationUnit(ASTConsumer *Consumer) +{ + if (!m_ast_context) + return; + + m_ast_context->getTranslationUnitDecl()->setHasExternalVisibleStorage(); + m_ast_context->getTranslationUnitDecl()->setHasExternalLexicalStorage(); +} + +// The core lookup interface. +bool +ClangASTSource::FindExternalVisibleDeclsByName +( + const DeclContext *decl_ctx, + DeclarationName clang_decl_name +) +{ + if (!m_ast_context) + { + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + } + + if (GetImportInProgress()) + { + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + } + + std::string decl_name (clang_decl_name.getAsString()); + +// if (m_decl_map.DoingASTImport ()) +// return DeclContext::lookup_result(); +// + switch (clang_decl_name.getNameKind()) { + // Normal identifiers. + case DeclarationName::Identifier: + { + clang::IdentifierInfo *identifier_info = clang_decl_name.getAsIdentifierInfo(); + + if (!identifier_info || + identifier_info->getBuiltinID() != 0) + { + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + } + } + break; + + // Operator names. + case DeclarationName::CXXOperatorName: + case DeclarationName::CXXLiteralOperatorName: + break; + + // Using directives found in this context. + // Tell Sema we didn't find any or we'll end up getting asked a *lot*. + case DeclarationName::CXXUsingDirective: + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + { + llvm::SmallVector method_decls; + + NameSearchContext method_search_context (*this, method_decls, clang_decl_name, decl_ctx); + + FindObjCMethodDecls(method_search_context); + + SetExternalVisibleDeclsForName (decl_ctx, clang_decl_name, method_decls); + return (method_decls.size() > 0); + } + // These aren't possible in the global context. + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXConversionFunctionName: + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + } + + + if (!GetLookupsEnabled()) + { + // Wait until we see a '$' at the start of a name before we start doing + // any lookups so we can avoid lookup up all of the builtin types. + if (!decl_name.empty() && decl_name[0] == '$') + { + SetLookupsEnabled (true); + } + else + { + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + } + } + + ConstString const_decl_name(decl_name.c_str()); + + const char *uniqued_const_decl_name = const_decl_name.GetCString(); + if (m_active_lookups.find (uniqued_const_decl_name) != m_active_lookups.end()) + { + // We are currently looking up this name... + SetNoExternalVisibleDeclsForName(decl_ctx, clang_decl_name); + return false; + } + m_active_lookups.insert(uniqued_const_decl_name); +// static uint32_t g_depth = 0; +// ++g_depth; +// printf("[%5u] FindExternalVisibleDeclsByName() \"%s\"\n", g_depth, uniqued_const_decl_name); + llvm::SmallVector name_decls; + NameSearchContext name_search_context(*this, name_decls, clang_decl_name, decl_ctx); + FindExternalVisibleDecls(name_search_context); + SetExternalVisibleDeclsForName (decl_ctx, clang_decl_name, name_decls); +// --g_depth; + m_active_lookups.erase (uniqued_const_decl_name); + return (name_decls.size() != 0); +} + +void +ClangASTSource::CompleteType (TagDecl *tag_decl) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + if (log) + { + log->Printf(" CompleteTagDecl[%u] on (ASTContext*)%p Completing (TagDecl*)%p named %s", + current_id, static_cast(m_ast_context), + static_cast(tag_decl), + tag_decl->getName().str().c_str()); + + log->Printf(" CTD[%u] Before:", current_id); + ASTDumper dumper((Decl*)tag_decl); + dumper.ToLog(log, " [CTD] "); + } + + auto iter = m_active_lexical_decls.find(tag_decl); + if (iter != m_active_lexical_decls.end()) + return; + m_active_lexical_decls.insert(tag_decl); + ScopedLexicalDeclEraser eraser(m_active_lexical_decls, tag_decl); + + if (!m_ast_importer_sp->CompleteTagDecl (tag_decl)) + { + // We couldn't complete the type. Maybe there's a definition + // somewhere else that can be completed. + + if (log) + log->Printf(" CTD[%u] Type could not be completed in the module in which it was first found.", current_id); + + bool found = false; + + DeclContext *decl_ctx = tag_decl->getDeclContext(); + + if (const NamespaceDecl *namespace_context = dyn_cast(decl_ctx)) + { + ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context); + + if (log && log->GetVerbose()) + log->Printf(" CTD[%u] Inspecting namespace map %p (%d entries)", + current_id, static_cast(namespace_map.get()), + static_cast(namespace_map->size())); + + if (!namespace_map) + return; + + for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); + i != e && !found; + ++i) + { + if (log) + log->Printf(" CTD[%u] Searching namespace %s in module %s", + current_id, + i->second.GetName().AsCString(), + i->first->GetFileSpec().GetFilename().GetCString()); + + TypeList types; + + SymbolContext null_sc; + ConstString name(tag_decl->getName().str().c_str()); + + i->first->FindTypesInNamespace(null_sc, name, &i->second, UINT32_MAX, types); + + for (uint32_t ti = 0, te = types.GetSize(); + ti != te && !found; + ++ti) + { + lldb::TypeSP type = types.GetTypeAtIndex(ti); + + if (!type) + continue; + + CompilerType clang_type (type->GetFullCompilerType ()); + + if (!clang_type) + continue; + + const TagType *tag_type = ClangASTContext::GetQualType(clang_type)->getAs(); + + if (!tag_type) + continue; + + TagDecl *candidate_tag_decl = const_cast(tag_type->getDecl()); + + if (m_ast_importer_sp->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl)) + found = true; + } + } + } + else + { + TypeList types; + + SymbolContext null_sc; + ConstString name(tag_decl->getName().str().c_str()); + CompilerDeclContext namespace_decl; + + const ModuleList &module_list = m_target->GetImages(); + + bool exact_match = false; + module_list.FindTypes (null_sc, name, exact_match, UINT32_MAX, types); + + for (uint32_t ti = 0, te = types.GetSize(); + ti != te && !found; + ++ti) + { + lldb::TypeSP type = types.GetTypeAtIndex(ti); + + if (!type) + continue; + + CompilerType clang_type (type->GetFullCompilerType ()); + + if (!clang_type) + continue; + + const TagType *tag_type = ClangASTContext::GetQualType(clang_type)->getAs(); + + if (!tag_type) + continue; + + TagDecl *candidate_tag_decl = const_cast(tag_type->getDecl()); + + // We have found a type by basename and we need to make sure the decl contexts + // are the same before we can try to complete this type with another + if (!ClangASTContext::DeclsAreEquivalent (tag_decl, candidate_tag_decl)) + continue; + + if (m_ast_importer_sp->CompleteTagDeclWithOrigin (tag_decl, candidate_tag_decl)) + found = true; + } + } + } + + if (log) + { + log->Printf(" [CTD] After:"); + ASTDumper dumper((Decl*)tag_decl); + dumper.ToLog(log, " [CTD] "); + } +} + +void +ClangASTSource::CompleteType (clang::ObjCInterfaceDecl *interface_decl) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + { + log->Printf(" [CompleteObjCInterfaceDecl] on (ASTContext*)%p Completing an ObjCInterfaceDecl named %s", + static_cast(m_ast_context), + interface_decl->getName().str().c_str()); + log->Printf(" [COID] Before:"); + ASTDumper dumper((Decl*)interface_decl); + dumper.ToLog(log, " [COID] "); + } + + Decl *original_decl = NULL; + ASTContext *original_ctx = NULL; + + if (m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx)) + { + if (ObjCInterfaceDecl *original_iface_decl = dyn_cast(original_decl)) + { + ObjCInterfaceDecl *complete_iface_decl = GetCompleteObjCInterface(original_iface_decl); + + if (complete_iface_decl && (complete_iface_decl != original_iface_decl)) + { + m_ast_importer_sp->SetDeclOrigin(interface_decl, original_iface_decl); + } + } + } + + m_ast_importer_sp->CompleteObjCInterfaceDecl (interface_decl); + + if (interface_decl->getSuperClass() && + interface_decl->getSuperClass() != interface_decl) + CompleteType(interface_decl->getSuperClass()); + + if (log) + { + log->Printf(" [COID] After:"); + ASTDumper dumper((Decl*)interface_decl); + dumper.ToLog(log, " [COID] "); + } +} + +clang::ObjCInterfaceDecl * +ClangASTSource::GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_decl) +{ + lldb::ProcessSP process(m_target->GetProcessSP()); + + if (!process) + return NULL; + + ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); + + if (!language_runtime) + return NULL; + + ConstString class_name(interface_decl->getNameAsString().c_str()); + + lldb::TypeSP complete_type_sp(language_runtime->LookupInCompleteClassCache(class_name)); + + if (!complete_type_sp) + return NULL; + + TypeFromUser complete_type = TypeFromUser(complete_type_sp->GetFullCompilerType ()); + lldb::opaque_compiler_type_t complete_opaque_type = complete_type.GetOpaqueQualType(); + + if (!complete_opaque_type) + return NULL; + + const clang::Type *complete_clang_type = QualType::getFromOpaquePtr(complete_opaque_type).getTypePtr(); + const ObjCInterfaceType *complete_interface_type = dyn_cast(complete_clang_type); + + if (!complete_interface_type) + return NULL; + + ObjCInterfaceDecl *complete_iface_decl(complete_interface_type->getDecl()); + + return complete_iface_decl; +} + +void +ClangASTSource::FindExternalLexicalDecls (const DeclContext *decl_context, + llvm::function_ref predicate, + llvm::SmallVectorImpl &decls) +{ + ClangASTMetrics::RegisterLexicalQuery(); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + const Decl *context_decl = dyn_cast(decl_context); + + if (!context_decl) + return; + + auto iter = m_active_lexical_decls.find(context_decl); + if (iter != m_active_lexical_decls.end()) + return; + m_active_lexical_decls.insert(context_decl); + ScopedLexicalDeclEraser eraser(m_active_lexical_decls, context_decl); + + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + if (log) + { + if (const NamedDecl *context_named_decl = dyn_cast(context_decl)) + log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in '%s' (%sDecl*)%p", + current_id, static_cast(m_ast_context), + context_named_decl->getNameAsString().c_str(), + context_decl->getDeclKindName(), + static_cast(context_decl)); + else if(context_decl) + log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in (%sDecl*)%p", + current_id, static_cast(m_ast_context), + context_decl->getDeclKindName(), + static_cast(context_decl)); + else + log->Printf("FindExternalLexicalDecls[%u] on (ASTContext*)%p in a NULL context", + current_id, static_cast(m_ast_context)); + } + + Decl *original_decl = NULL; + ASTContext *original_ctx = NULL; + + if (!m_ast_importer_sp->ResolveDeclOrigin(context_decl, &original_decl, &original_ctx)) + return; + + if (log) + { + log->Printf(" FELD[%u] Original decl (ASTContext*)%p (Decl*)%p:", + current_id, static_cast(original_ctx), + static_cast(original_decl)); + ASTDumper(original_decl).ToLog(log, " "); + } + + if (ObjCInterfaceDecl *original_iface_decl = dyn_cast(original_decl)) + { + ObjCInterfaceDecl *complete_iface_decl = GetCompleteObjCInterface(original_iface_decl); + + if (complete_iface_decl && (complete_iface_decl != original_iface_decl)) + { + original_decl = complete_iface_decl; + original_ctx = &complete_iface_decl->getASTContext(); + + m_ast_importer_sp->SetDeclOrigin(context_decl, original_iface_decl); + } + } + + if (TagDecl *original_tag_decl = dyn_cast(original_decl)) + { + ExternalASTSource *external_source = original_ctx->getExternalSource(); + + if (external_source) + external_source->CompleteType (original_tag_decl); + } + + const DeclContext *original_decl_context = dyn_cast(original_decl); + + if (!original_decl_context) + return; + + for (TagDecl::decl_iterator iter = original_decl_context->decls_begin(); + iter != original_decl_context->decls_end(); + ++iter) + { + Decl *decl = *iter; + + if (predicate(decl->getKind())) + { + if (log) + { + ASTDumper ast_dumper(decl); + if (const NamedDecl *context_named_decl = dyn_cast(context_decl)) + log->Printf(" FELD[%d] Adding [to %sDecl %s] lexical %sDecl %s", current_id, context_named_decl->getDeclKindName(), context_named_decl->getNameAsString().c_str(), decl->getDeclKindName(), ast_dumper.GetCString()); + else + log->Printf(" FELD[%d] Adding lexical %sDecl %s", current_id, decl->getDeclKindName(), ast_dumper.GetCString()); + } + + Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, original_ctx, decl); + + if (!copied_decl) + continue; + + if (FieldDecl *copied_field = dyn_cast(copied_decl)) + { + QualType copied_field_type = copied_field->getType(); + + m_ast_importer_sp->RequireCompleteType(copied_field_type); + } + + DeclContext *decl_context_non_const = const_cast(decl_context); + + if (copied_decl->getDeclContext() != decl_context) + { + if (copied_decl->getDeclContext()->containsDecl(copied_decl)) + copied_decl->getDeclContext()->removeDecl(copied_decl); + copied_decl->setDeclContext(decl_context_non_const); + } + + if (!decl_context_non_const->containsDecl(copied_decl)) + decl_context_non_const->addDeclInternal(copied_decl); + } + } + + return; +} + +void +ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context) +{ + assert (m_ast_context); + + ClangASTMetrics::RegisterVisibleQuery(); + + const ConstString name(context.m_decl_name.getAsString().c_str()); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + if (log) + { + if (!context.m_decl_context) + log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a NULL DeclContext", + current_id, static_cast(m_ast_context), + name.GetCString()); + else if (const NamedDecl *context_named_decl = dyn_cast(context.m_decl_context)) + log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in '%s'", + current_id, static_cast(m_ast_context), + name.GetCString(), + context_named_decl->getNameAsString().c_str()); + else + log->Printf("ClangASTSource::FindExternalVisibleDecls[%u] on (ASTContext*)%p for '%s' in a '%s'", + current_id, static_cast(m_ast_context), + name.GetCString(), + context.m_decl_context->getDeclKindName()); + } + + context.m_namespace_map.reset(new ClangASTImporter::NamespaceMap); + + if (const NamespaceDecl *namespace_context = dyn_cast(context.m_decl_context)) + { + ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context); + + if (log && log->GetVerbose()) + log->Printf(" CAS::FEVD[%u] Inspecting namespace map %p (%d entries)", + current_id, static_cast(namespace_map.get()), + static_cast(namespace_map->size())); + + if (!namespace_map) + return; + + for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); + i != e; + ++i) + { + if (log) + log->Printf(" CAS::FEVD[%u] Searching namespace %s in module %s", + current_id, + i->second.GetName().AsCString(), + i->first->GetFileSpec().GetFilename().GetCString()); + + FindExternalVisibleDecls(context, + i->first, + i->second, + current_id); + } + } + else if (isa(context.m_decl_context)) + { + FindObjCPropertyAndIvarDecls(context); + } + else if (!isa(context.m_decl_context)) + { + // we shouldn't be getting FindExternalVisibleDecls calls for these + return; + } + else + { + CompilerDeclContext namespace_decl; + + if (log) + log->Printf(" CAS::FEVD[%u] Searching the root namespace", current_id); + + FindExternalVisibleDecls(context, + lldb::ModuleSP(), + namespace_decl, + current_id); + } + + if (!context.m_namespace_map->empty()) + { + if (log && log->GetVerbose()) + log->Printf(" CAS::FEVD[%u] Registering namespace map %p (%d entries)", + current_id, + static_cast(context.m_namespace_map.get()), + static_cast(context.m_namespace_map->size())); + + NamespaceDecl *clang_namespace_decl = AddNamespace(context, context.m_namespace_map); + + if (clang_namespace_decl) + clang_namespace_decl->setHasExternalVisibleStorage(); + } +} + +void +ClangASTSource::FindExternalVisibleDecls (NameSearchContext &context, + lldb::ModuleSP module_sp, + CompilerDeclContext &namespace_decl, + unsigned int current_id) +{ + assert (m_ast_context); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + SymbolContextList sc_list; + + const ConstString name(context.m_decl_name.getAsString().c_str()); + + const char *name_unique_cstr = name.GetCString(); + + static ConstString id_name("id"); + static ConstString Class_name("Class"); + + if (name == id_name || name == Class_name) + return; + + if (name_unique_cstr == NULL) + return; + + // The ClangASTSource is not responsible for finding $-names. + if (name_unique_cstr[0] == '$') + return; + + if (module_sp && namespace_decl) + { + CompilerDeclContext found_namespace_decl; + + SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); + + if (symbol_vendor) + { + SymbolContext null_sc; + + found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &namespace_decl); + + if (found_namespace_decl) + { + context.m_namespace_map->push_back(std::pair(module_sp, found_namespace_decl)); + + if (log) + log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s", + current_id, + name.GetCString(), + module_sp->GetFileSpec().GetFilename().GetCString()); + } + } + } + else + { + const ModuleList &target_images = m_target->GetImages(); + Mutex::Locker modules_locker (target_images.GetMutex()); + + for (size_t i = 0, e = target_images.GetSize(); i < e; ++i) + { + lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i); + + if (!image) + continue; + + CompilerDeclContext found_namespace_decl; + + SymbolVendor *symbol_vendor = image->GetSymbolVendor(); + + if (!symbol_vendor) + continue; + + SymbolContext null_sc; + + found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &namespace_decl); + + if (found_namespace_decl) + { + context.m_namespace_map->push_back(std::pair(image, found_namespace_decl)); + + if (log) + log->Printf(" CAS::FEVD[%u] Found namespace %s in module %s", + current_id, + name.GetCString(), + image->GetFileSpec().GetFilename().GetCString()); + } + } + } + + do + { + TypeList types; + SymbolContext null_sc; + const bool exact_match = false; + + if (module_sp && namespace_decl) + module_sp->FindTypesInNamespace(null_sc, name, &namespace_decl, 1, types); + else + m_target->GetImages().FindTypes(null_sc, name, exact_match, 1, types); + + bool found_a_type = false; + + if (size_t num_types = types.GetSize()) + { + for (size_t ti = 0; ti < num_types; ++ti) + { + lldb::TypeSP type_sp = types.GetTypeAtIndex(ti); + + if (log) + { + const char *name_string = type_sp->GetName().GetCString(); + + log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\": %s", + current_id, + name.GetCString(), + (name_string ? name_string : "")); + } + + CompilerType full_type = type_sp->GetFullCompilerType(); + + CompilerType copied_clang_type (GuardedCopyType(full_type)); + + if (!copied_clang_type) + { + if (log) + log->Printf(" CAS::FEVD[%u] - Couldn't export a type", + current_id); + + continue; + } + + context.AddTypeDecl(copied_clang_type); + + found_a_type = true; + break; + } + } + + if (!found_a_type) + { + // Try the modules next. + + do + { + if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor()) + { + bool append = false; + uint32_t max_matches = 1; + std::vector decls; + + if (!modules_decl_vendor->FindDecls(name, + append, + max_matches, + decls)) + break; + + if (log) + { + log->Printf(" CAS::FEVD[%u] Matching entity found for \"%s\" in the modules", + current_id, + name.GetCString()); + } + + clang::NamedDecl *const decl_from_modules = decls[0]; + + if (llvm::isa(decl_from_modules) || + llvm::isa(decl_from_modules) || + llvm::isa(decl_from_modules)) + { + clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules); + clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast(copied_decl) : nullptr; + + if (!copied_named_decl) + { + if (log) + log->Printf(" CAS::FEVD[%u] - Couldn't export a type from the modules", + current_id); + + break; + } + + context.AddNamedDecl(copied_named_decl); + + found_a_type = true; + } + } + } while (0); + } + + if (!found_a_type) + { + do + { + // Couldn't find any types elsewhere. Try the Objective-C runtime if one exists. + + lldb::ProcessSP process(m_target->GetProcessSP()); + + if (!process) + break; + + ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); + + if (!language_runtime) + break; + + DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); + + if (!decl_vendor) + break; + + bool append = false; + uint32_t max_matches = 1; + std::vector decls; + + if (!decl_vendor->FindDecls(name, + append, + max_matches, + decls)) + break; + + if (log) + { + log->Printf(" CAS::FEVD[%u] Matching type found for \"%s\" in the runtime", + current_id, + name.GetCString()); + } + + clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decls[0]->getASTContext(), decls[0]); + clang::NamedDecl *copied_named_decl = copied_decl ? dyn_cast(copied_decl) : nullptr; + + if (!copied_named_decl) + { + if (log) + log->Printf(" CAS::FEVD[%u] - Couldn't export a type from the runtime", + current_id); + + break; + } + + context.AddNamedDecl(copied_named_decl); + } + while(0); + } + + } while(0); +} + +template class TaggedASTDecl { +public: + TaggedASTDecl() : decl(NULL) { } + TaggedASTDecl(D *_decl) : decl(_decl) { } + bool IsValid() const { return (decl != NULL); } + bool IsInvalid() const { return !IsValid(); } + D *operator->() const { return decl; } + D *decl; +}; + +template class TD, class D1> +TD +DynCast(TD source) +{ + return TD (dyn_cast(source.decl)); +} + +template class DeclFromParser; +template class DeclFromUser; + +template class DeclFromParser : public TaggedASTDecl { +public: + DeclFromParser() : TaggedASTDecl() { } + DeclFromParser(D *_decl) : TaggedASTDecl(_decl) { } + + DeclFromUser GetOrigin(ClangASTImporter *importer); +}; + +template class DeclFromUser : public TaggedASTDecl { +public: + DeclFromUser() : TaggedASTDecl() { } + DeclFromUser(D *_decl) : TaggedASTDecl(_decl) { } + + DeclFromParser Import(ClangASTImporter *importer, ASTContext &dest_ctx); +}; + +template +DeclFromUser +DeclFromParser::GetOrigin(ClangASTImporter *importer) +{ + DeclFromUser <> origin_decl; + importer->ResolveDeclOrigin(this->decl, &origin_decl.decl, NULL); + if (origin_decl.IsInvalid()) + return DeclFromUser(); + return DeclFromUser(dyn_cast(origin_decl.decl)); +} + +template +DeclFromParser +DeclFromUser::Import(ClangASTImporter *importer, ASTContext &dest_ctx) +{ + DeclFromParser <> parser_generic_decl(importer->CopyDecl(&dest_ctx, &this->decl->getASTContext(), this->decl)); + if (parser_generic_decl.IsInvalid()) + return DeclFromParser(); + return DeclFromParser(dyn_cast(parser_generic_decl.decl)); +} + +static bool +FindObjCMethodDeclsWithOrigin (unsigned int current_id, + NameSearchContext &context, + ObjCInterfaceDecl *original_interface_decl, + clang::ASTContext *ast_context, + ClangASTImporter *ast_importer, + const char *log_info) +{ + const DeclarationName &decl_name(context.m_decl_name); + clang::ASTContext *original_ctx = &original_interface_decl->getASTContext(); + + Selector original_selector; + + if (decl_name.isObjCZeroArgSelector()) + { + IdentifierInfo *ident = &original_ctx->Idents.get(decl_name.getAsString()); + original_selector = original_ctx->Selectors.getSelector(0, &ident); + } + else if (decl_name.isObjCOneArgSelector()) + { + const std::string &decl_name_string = decl_name.getAsString(); + std::string decl_name_string_without_colon(decl_name_string.c_str(), decl_name_string.length() - 1); + IdentifierInfo *ident = &original_ctx->Idents.get(decl_name_string_without_colon.c_str()); + original_selector = original_ctx->Selectors.getSelector(1, &ident); + } + else + { + SmallVector idents; + + clang::Selector sel = decl_name.getObjCSelector(); + + unsigned num_args = sel.getNumArgs(); + + for (unsigned i = 0; + i != num_args; + ++i) + { + idents.push_back(&original_ctx->Idents.get(sel.getNameForSlot(i))); + } + + original_selector = original_ctx->Selectors.getSelector(num_args, idents.data()); + } + + DeclarationName original_decl_name(original_selector); + + llvm::SmallVector methods; + + ClangASTContext::GetCompleteDecl(original_ctx, original_interface_decl); + + if (ObjCMethodDecl *instance_method_decl = original_interface_decl->lookupInstanceMethod(original_selector)) + { + methods.push_back(instance_method_decl); + } + else if (ObjCMethodDecl *class_method_decl = original_interface_decl->lookupClassMethod(original_selector)) + { + methods.push_back(class_method_decl); + } + + if (methods.empty()) + { + return false; + } + + for (NamedDecl *named_decl : methods) + { + if (!named_decl) + continue; + + ObjCMethodDecl *result_method = dyn_cast(named_decl); + + if (!result_method) + continue; + + Decl *copied_decl = ast_importer->CopyDecl(ast_context, &result_method->getASTContext(), result_method); + + if (!copied_decl) + continue; + + ObjCMethodDecl *copied_method_decl = dyn_cast(copied_decl); + + if (!copied_method_decl) + continue; + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + { + ASTDumper dumper((Decl*)copied_method_decl); + log->Printf(" CAS::FOMD[%d] found (%s) %s", current_id, log_info, dumper.GetCString()); + } + + context.AddNamedDecl(copied_method_decl); + } + + return true; +} + +void +ClangASTSource::FindObjCMethodDecls (NameSearchContext &context) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + const DeclarationName &decl_name(context.m_decl_name); + const DeclContext *decl_ctx(context.m_decl_context); + + const ObjCInterfaceDecl *interface_decl = dyn_cast(decl_ctx); + + if (!interface_decl) + return; + + do + { + Decl *original_decl = NULL; + ASTContext *original_ctx = NULL; + + m_ast_importer_sp->ResolveDeclOrigin(interface_decl, &original_decl, &original_ctx); + + if (!original_decl) + break; + + ObjCInterfaceDecl *original_interface_decl = dyn_cast(original_decl); + + if (FindObjCMethodDeclsWithOrigin(current_id, + context, + original_interface_decl, + m_ast_context, + m_ast_importer_sp.get(), + "at origin")) + return; // found it, no need to look any further + } while (0); + + StreamString ss; + + if (decl_name.isObjCZeroArgSelector()) + { + ss.Printf("%s", decl_name.getAsString().c_str()); + } + else if (decl_name.isObjCOneArgSelector()) + { + ss.Printf("%s", decl_name.getAsString().c_str()); + } + else + { + clang::Selector sel = decl_name.getObjCSelector(); + + for (unsigned i = 0, e = sel.getNumArgs(); + i != e; + ++i) + { + llvm::StringRef r = sel.getNameForSlot(i); + ss.Printf("%s:", r.str().c_str()); + } + } + ss.Flush(); + + if (strstr(ss.GetData(), "$__lldb")) + return; // we don't need any results + + ConstString selector_name(ss.GetData()); + + if (log) + log->Printf("ClangASTSource::FindObjCMethodDecls[%d] on (ASTContext*)%p for selector [%s %s]", + current_id, static_cast(m_ast_context), + interface_decl->getNameAsString().c_str(), + selector_name.AsCString()); + SymbolContextList sc_list; + + const bool include_symbols = false; + const bool include_inlines = false; + const bool append = false; + + std::string interface_name = interface_decl->getNameAsString(); + + do + { + StreamString ms; + ms.Printf("-[%s %s]", interface_name.c_str(), selector_name.AsCString()); + ms.Flush(); + ConstString instance_method_name(ms.GetData()); + + m_target->GetImages().FindFunctions(instance_method_name, lldb::eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list); + + if (sc_list.GetSize()) + break; + + ms.Clear(); + ms.Printf("+[%s %s]", interface_name.c_str(), selector_name.AsCString()); + ms.Flush(); + ConstString class_method_name(ms.GetData()); + + m_target->GetImages().FindFunctions(class_method_name, lldb::eFunctionNameTypeFull, include_symbols, include_inlines, append, sc_list); + + if (sc_list.GetSize()) + break; + + // Fall back and check for methods in categories. If we find methods this way, we need to check that they're actually in + // categories on the desired class. + + SymbolContextList candidate_sc_list; + + m_target->GetImages().FindFunctions(selector_name, lldb::eFunctionNameTypeSelector, include_symbols, include_inlines, append, candidate_sc_list); + + for (uint32_t ci = 0, ce = candidate_sc_list.GetSize(); + ci != ce; + ++ci) + { + SymbolContext candidate_sc; + + if (!candidate_sc_list.GetContextAtIndex(ci, candidate_sc)) + continue; + + if (!candidate_sc.function) + continue; + + const char *candidate_name = candidate_sc.function->GetName().AsCString(); + + const char *cursor = candidate_name; + + if (*cursor != '+' && *cursor != '-') + continue; + + ++cursor; + + if (*cursor != '[') + continue; + + ++cursor; + + size_t interface_len = interface_name.length(); + + if (strncmp(cursor, interface_name.c_str(), interface_len)) + continue; + + cursor += interface_len; + + if (*cursor == ' ' || *cursor == '(') + sc_list.Append(candidate_sc); + } + } + while (0); + + if (sc_list.GetSize()) + { + // We found a good function symbol. Use that. + + for (uint32_t i = 0, e = sc_list.GetSize(); + i != e; + ++i) + { + SymbolContext sc; + + if (!sc_list.GetContextAtIndex(i, sc)) + continue; + + if (!sc.function) + continue; + + CompilerDeclContext function_decl_ctx = sc.function->GetDeclContext(); + if (!function_decl_ctx) + continue; + + ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx); + + if (!method_decl) + continue; + + ObjCInterfaceDecl *found_interface_decl = method_decl->getClassInterface(); + + if (!found_interface_decl) + continue; + + if (found_interface_decl->getName() == interface_decl->getName()) + { + Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &method_decl->getASTContext(), method_decl); + + if (!copied_decl) + continue; + + ObjCMethodDecl *copied_method_decl = dyn_cast(copied_decl); + + if (!copied_method_decl) + continue; + + if (log) + { + ASTDumper dumper((Decl*)copied_method_decl); + log->Printf(" CAS::FOMD[%d] found (in symbols) %s", current_id, dumper.GetCString()); + } + + context.AddNamedDecl(copied_method_decl); + } + } + + return; + } + + // Try the debug information. + + do + { + ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface(const_cast(interface_decl)); + + if (!complete_interface_decl) + break; + + // We found the complete interface. The runtime never needs to be queried in this scenario. + + DeclFromUser complete_iface_decl(complete_interface_decl); + + if (complete_interface_decl == interface_decl) + break; // already checked this one + + if (log) + log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, static_cast(complete_interface_decl), + static_cast(&complete_iface_decl->getASTContext())); + + FindObjCMethodDeclsWithOrigin(current_id, + context, + complete_interface_decl, + m_ast_context, + m_ast_importer_sp.get(), + "in debug info"); + + return; + } + while (0); + + do + { + // Check the modules only if the debug information didn't have a complete interface. + + if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor()) + { + ConstString interface_name(interface_decl->getNameAsString().c_str()); + bool append = false; + uint32_t max_matches = 1; + std::vector decls; + + if (!modules_decl_vendor->FindDecls(interface_name, + append, + max_matches, + decls)) + break; + + ObjCInterfaceDecl *interface_decl_from_modules = dyn_cast(decls[0]); + + if (!interface_decl_from_modules) + break; + + if (FindObjCMethodDeclsWithOrigin(current_id, + context, + interface_decl_from_modules, + m_ast_context, + m_ast_importer_sp.get(), + "in modules")) + return; + } + } + while (0); + + do + { + // Check the runtime only if the debug information didn't have a complete interface and the modules don't get us anywhere. + + lldb::ProcessSP process(m_target->GetProcessSP()); + + if (!process) + break; + + ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); + + if (!language_runtime) + break; + + DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); + + if (!decl_vendor) + break; + + ConstString interface_name(interface_decl->getNameAsString().c_str()); + bool append = false; + uint32_t max_matches = 1; + std::vector decls; + + if (!decl_vendor->FindDecls(interface_name, + append, + max_matches, + decls)) + break; + + ObjCInterfaceDecl *runtime_interface_decl = dyn_cast(decls[0]); + + if (!runtime_interface_decl) + break; + + FindObjCMethodDeclsWithOrigin(current_id, + context, + runtime_interface_decl, + m_ast_context, + m_ast_importer_sp.get(), + "in runtime"); + } + while(0); +} + +static bool +FindObjCPropertyAndIvarDeclsWithOrigin (unsigned int current_id, + NameSearchContext &context, + clang::ASTContext &ast_context, + ClangASTImporter *ast_importer, + DeclFromUser &origin_iface_decl) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (origin_iface_decl.IsInvalid()) + return false; + + std::string name_str = context.m_decl_name.getAsString(); + StringRef name(name_str.c_str()); + IdentifierInfo &name_identifier(origin_iface_decl->getASTContext().Idents.get(name)); + + DeclFromUser origin_property_decl(origin_iface_decl->FindPropertyDeclaration(&name_identifier)); + + bool found = false; + + if (origin_property_decl.IsValid()) + { + DeclFromParser parser_property_decl(origin_property_decl.Import(ast_importer, ast_context)); + if (parser_property_decl.IsValid()) + { + if (log) + { + ASTDumper dumper((Decl*)parser_property_decl.decl); + log->Printf(" CAS::FOPD[%d] found %s", current_id, dumper.GetCString()); + } + + context.AddNamedDecl(parser_property_decl.decl); + found = true; + } + } + + DeclFromUser origin_ivar_decl(origin_iface_decl->getIvarDecl(&name_identifier)); + + if (origin_ivar_decl.IsValid()) + { + DeclFromParser parser_ivar_decl(origin_ivar_decl.Import(ast_importer, ast_context)); + if (parser_ivar_decl.IsValid()) + { + if (log) + { + ASTDumper dumper((Decl*)parser_ivar_decl.decl); + log->Printf(" CAS::FOPD[%d] found %s", current_id, dumper.GetCString()); + } + + context.AddNamedDecl(parser_ivar_decl.decl); + found = true; + } + } + + return found; +} + +void +ClangASTSource::FindObjCPropertyAndIvarDecls (NameSearchContext &context) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + DeclFromParser parser_iface_decl(cast(context.m_decl_context)); + DeclFromUser origin_iface_decl(parser_iface_decl.GetOrigin(m_ast_importer_sp.get())); + + ConstString class_name(parser_iface_decl->getNameAsString().c_str()); + + if (log) + log->Printf("ClangASTSource::FindObjCPropertyAndIvarDecls[%d] on (ASTContext*)%p for '%s.%s'", + current_id, static_cast(m_ast_context), + parser_iface_decl->getNameAsString().c_str(), + context.m_decl_name.getAsString().c_str()); + + if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, + context, + *m_ast_context, + m_ast_importer_sp.get(), + origin_iface_decl)) + return; + + if (log) + log->Printf("CAS::FOPD[%d] couldn't find the property on origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p, searching elsewhere...", + current_id, static_cast(origin_iface_decl.decl), + static_cast(&origin_iface_decl->getASTContext())); + + SymbolContext null_sc; + TypeList type_list; + + do + { + ObjCInterfaceDecl *complete_interface_decl = GetCompleteObjCInterface(const_cast(parser_iface_decl.decl)); + + if (!complete_interface_decl) + break; + + // We found the complete interface. The runtime never needs to be queried in this scenario. + + DeclFromUser complete_iface_decl(complete_interface_decl); + + if (complete_iface_decl.decl == origin_iface_decl.decl) + break; // already checked this one + + if (log) + log->Printf("CAS::FOPD[%d] trying origin (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, + static_cast(complete_iface_decl.decl), + static_cast(&complete_iface_decl->getASTContext())); + + FindObjCPropertyAndIvarDeclsWithOrigin(current_id, + context, + *m_ast_context, + m_ast_importer_sp.get(), + complete_iface_decl); + + return; + } + while(0); + + do + { + // Check the modules only if the debug information didn't have a complete interface. + + ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor(); + + if (!modules_decl_vendor) + break; + + bool append = false; + uint32_t max_matches = 1; + std::vector decls; + + if (!modules_decl_vendor->FindDecls(class_name, + append, + max_matches, + decls)) + break; + + DeclFromUser interface_decl_from_modules(dyn_cast(decls[0])); + + if (!interface_decl_from_modules.IsValid()) + break; + + if (log) + log->Printf("CAS::FOPD[%d] trying module (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, + static_cast(interface_decl_from_modules.decl), + static_cast(&interface_decl_from_modules->getASTContext())); + + if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, + context, + *m_ast_context, + m_ast_importer_sp.get(), + interface_decl_from_modules)) + return; + } + while(0); + + do + { + // Check the runtime only if the debug information didn't have a complete interface + // and nothing was in the modules. + + lldb::ProcessSP process(m_target->GetProcessSP()); + + if (!process) + return; + + ObjCLanguageRuntime *language_runtime(process->GetObjCLanguageRuntime()); + + if (!language_runtime) + return; + + DeclVendor *decl_vendor = language_runtime->GetDeclVendor(); + + if (!decl_vendor) + break; + + bool append = false; + uint32_t max_matches = 1; + std::vector decls; + + if (!decl_vendor->FindDecls(class_name, + append, + max_matches, + decls)) + break; + + DeclFromUser interface_decl_from_runtime(dyn_cast(decls[0])); + + if (!interface_decl_from_runtime.IsValid()) + break; + + if (log) + log->Printf("CAS::FOPD[%d] trying runtime (ObjCInterfaceDecl*)%p/(ASTContext*)%p...", + current_id, + static_cast(interface_decl_from_runtime.decl), + static_cast(&interface_decl_from_runtime->getASTContext())); + + if (FindObjCPropertyAndIvarDeclsWithOrigin(current_id, + context, + *m_ast_context, + m_ast_importer_sp.get(), + interface_decl_from_runtime)) + return; + } + while(0); +} + +typedef llvm::DenseMap FieldOffsetMap; +typedef llvm::DenseMap BaseOffsetMap; + +template +static bool +ImportOffsetMap(llvm::DenseMap &destination_map, llvm::DenseMap &source_map, + ClangASTImporter *importer, ASTContext &dest_ctx) +{ + // When importing fields into a new record, clang has a hard requirement that + // fields be imported in field offset order. Since they are stored in a DenseMap + // with a pointer as the key type, this means we cannot simply iterate over the + // map, as the order will be non-deterministic. Instead we have to sort by the offset + // and then insert in sorted order. + typedef llvm::DenseMap MapType; + typedef typename MapType::value_type PairType; + std::vector sorted_items; + sorted_items.reserve(source_map.size()); + sorted_items.assign(source_map.begin(), source_map.end()); + std::sort(sorted_items.begin(), sorted_items.end(), + [](const PairType &lhs, const PairType &rhs) + { + return lhs.second < rhs.second; + }); + + for (const auto &item : sorted_items) + { + DeclFromUser user_decl(const_cast(item.first)); + DeclFromParser parser_decl(user_decl.Import(importer, dest_ctx)); + if (parser_decl.IsInvalid()) + return false; + destination_map.insert(std::pair(parser_decl.decl, item.second)); + } + + return true; +} + +template +bool +ExtractBaseOffsets(const ASTRecordLayout &record_layout, DeclFromUser &record, + BaseOffsetMap &base_offsets) +{ + for (CXXRecordDecl::base_class_const_iterator bi = (IsVirtual ? record->vbases_begin() : record->bases_begin()), + be = (IsVirtual ? record->vbases_end() : record->bases_end()); + bi != be; ++bi) + { + if (!IsVirtual && bi->isVirtual()) + continue; + + const clang::Type *origin_base_type = bi->getType().getTypePtr(); + const clang::RecordType *origin_base_record_type = origin_base_type->getAs(); + + if (!origin_base_record_type) + return false; + + DeclFromUser origin_base_record(origin_base_record_type->getDecl()); + + if (origin_base_record.IsInvalid()) + return false; + + DeclFromUser origin_base_cxx_record(DynCast(origin_base_record)); + + if (origin_base_cxx_record.IsInvalid()) + return false; + + CharUnits base_offset; + + if (IsVirtual) + base_offset = record_layout.getVBaseClassOffset(origin_base_cxx_record.decl); + else + base_offset = record_layout.getBaseClassOffset(origin_base_cxx_record.decl); + + base_offsets.insert(std::pair(origin_base_cxx_record.decl, base_offset)); + } + + return true; +} + +bool +ClangASTSource::layoutRecordType(const RecordDecl *record, uint64_t &size, uint64_t &alignment, + FieldOffsetMap &field_offsets, BaseOffsetMap &base_offsets, + BaseOffsetMap &virtual_base_offsets) +{ + ClangASTMetrics::RegisterRecordLayout(); + + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf("LayoutRecordType[%u] on (ASTContext*)%p for (RecordDecl*)%p [name = '%s']", + current_id, static_cast(m_ast_context), + static_cast(record), + record->getNameAsString().c_str()); + + DeclFromParser parser_record(record); + DeclFromUser origin_record(parser_record.GetOrigin(m_ast_importer_sp.get())); + + if (origin_record.IsInvalid()) + return false; + + FieldOffsetMap origin_field_offsets; + BaseOffsetMap origin_base_offsets; + BaseOffsetMap origin_virtual_base_offsets; + + ClangASTContext::GetCompleteDecl(&origin_record->getASTContext(), const_cast(origin_record.decl)); + + clang::RecordDecl* definition = origin_record.decl->getDefinition(); + if (!definition || !definition->isCompleteDefinition()) + return false; + + const ASTRecordLayout &record_layout(origin_record->getASTContext().getASTRecordLayout(origin_record.decl)); + + int field_idx = 0, field_count = record_layout.getFieldCount(); + + for (RecordDecl::field_iterator fi = origin_record->field_begin(), fe = origin_record->field_end(); fi != fe; ++fi) + { + if (field_idx >= field_count) + return false; // Layout didn't go well. Bail out. + + uint64_t field_offset = record_layout.getFieldOffset(field_idx); + + origin_field_offsets.insert(std::pair(*fi, field_offset)); + + field_idx++; + } + + ASTContext &parser_ast_context(record->getASTContext()); + + DeclFromUser origin_cxx_record(DynCast(origin_record)); + + if (origin_cxx_record.IsValid()) + { + if (!ExtractBaseOffsets(record_layout, origin_cxx_record, origin_base_offsets) || + !ExtractBaseOffsets(record_layout, origin_cxx_record, origin_virtual_base_offsets)) + return false; + } + + if (!ImportOffsetMap(field_offsets, origin_field_offsets, m_ast_importer_sp.get(), parser_ast_context) || + !ImportOffsetMap(base_offsets, origin_base_offsets, m_ast_importer_sp.get(), parser_ast_context) || + !ImportOffsetMap(virtual_base_offsets, origin_virtual_base_offsets, m_ast_importer_sp.get(), parser_ast_context)) + return false; + + size = record_layout.getSize().getQuantity() * m_ast_context->getCharWidth(); + alignment = record_layout.getAlignment().getQuantity() * m_ast_context->getCharWidth(); + + if (log) + { + log->Printf("LRT[%u] returned:", current_id); + log->Printf("LRT[%u] Original = (RecordDecl*)%p", current_id, + static_cast(origin_record.decl)); + log->Printf("LRT[%u] Size = %" PRId64, current_id, size); + log->Printf("LRT[%u] Alignment = %" PRId64, current_id, alignment); + log->Printf("LRT[%u] Fields:", current_id); + for (RecordDecl::field_iterator fi = record->field_begin(), fe = record->field_end(); + fi != fe; + ++fi) + { + log->Printf("LRT[%u] (FieldDecl*)%p, Name = '%s', Offset = %" PRId64 " bits", current_id, + static_cast(*fi), fi->getNameAsString().c_str(), field_offsets[*fi]); + } + DeclFromParser parser_cxx_record = DynCast(parser_record); + if (parser_cxx_record.IsValid()) + { + log->Printf("LRT[%u] Bases:", current_id); + for (CXXRecordDecl::base_class_const_iterator bi = parser_cxx_record->bases_begin(), be = parser_cxx_record->bases_end(); + bi != be; + ++bi) + { + bool is_virtual = bi->isVirtual(); + + QualType base_type = bi->getType(); + const RecordType *base_record_type = base_type->getAs(); + DeclFromParser base_record(base_record_type->getDecl()); + DeclFromParser base_cxx_record = DynCast(base_record); + + log->Printf("LRT[%u] %s(CXXRecordDecl*)%p, Name = '%s', Offset = %" PRId64 " chars", current_id, + (is_virtual ? "Virtual " : ""), static_cast(base_cxx_record.decl), + base_cxx_record.decl->getNameAsString().c_str(), + (is_virtual ? virtual_base_offsets[base_cxx_record.decl].getQuantity() + : base_offsets[base_cxx_record.decl].getQuantity())); + } + } + else + { + log->Printf("LRD[%u] Not a CXXRecord, so no bases", current_id); + } + } + + return true; +} + +void +ClangASTSource::CompleteNamespaceMap (ClangASTImporter::NamespaceMapSP &namespace_map, + const ConstString &name, + ClangASTImporter::NamespaceMapSP &parent_map) const +{ + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + { + if (parent_map && parent_map->size()) + log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s in namespace %s", + current_id, static_cast(m_ast_context), + name.GetCString(), + parent_map->begin()->second.GetName().AsCString()); + else + log->Printf("CompleteNamespaceMap[%u] on (ASTContext*)%p Searching for namespace %s", + current_id, static_cast(m_ast_context), + name.GetCString()); + } + + if (parent_map) + { + for (ClangASTImporter::NamespaceMap::iterator i = parent_map->begin(), e = parent_map->end(); + i != e; + ++i) + { + CompilerDeclContext found_namespace_decl; + + lldb::ModuleSP module_sp = i->first; + CompilerDeclContext module_parent_namespace_decl = i->second; + + SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor(); + + if (!symbol_vendor) + continue; + + SymbolContext null_sc; + + found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &module_parent_namespace_decl); + + if (!found_namespace_decl) + continue; + + namespace_map->push_back(std::pair(module_sp, found_namespace_decl)); + + if (log) + log->Printf(" CMN[%u] Found namespace %s in module %s", + current_id, + name.GetCString(), + module_sp->GetFileSpec().GetFilename().GetCString()); + } + } + else + { + const ModuleList &target_images = m_target->GetImages(); + Mutex::Locker modules_locker(target_images.GetMutex()); + + CompilerDeclContext null_namespace_decl; + + for (size_t i = 0, e = target_images.GetSize(); i < e; ++i) + { + lldb::ModuleSP image = target_images.GetModuleAtIndexUnlocked(i); + + if (!image) + continue; + + CompilerDeclContext found_namespace_decl; + + SymbolVendor *symbol_vendor = image->GetSymbolVendor(); + + if (!symbol_vendor) + continue; + + SymbolContext null_sc; + + found_namespace_decl = symbol_vendor->FindNamespace(null_sc, name, &null_namespace_decl); + + if (!found_namespace_decl) + continue; + + namespace_map->push_back(std::pair(image, found_namespace_decl)); + + if (log) + log->Printf(" CMN[%u] Found namespace %s in module %s", + current_id, + name.GetCString(), + image->GetFileSpec().GetFilename().GetCString()); + } + } +} + +NamespaceDecl * +ClangASTSource::AddNamespace (NameSearchContext &context, ClangASTImporter::NamespaceMapSP &namespace_decls) +{ + if (!namespace_decls) + return nullptr; + + const CompilerDeclContext &namespace_decl = namespace_decls->begin()->second; + + clang::ASTContext *src_ast = ClangASTContext::DeclContextGetClangASTContext(namespace_decl); + if (!src_ast) + return nullptr; + clang::NamespaceDecl *src_namespace_decl = ClangASTContext::DeclContextGetAsNamespaceDecl(namespace_decl); + + if (!src_namespace_decl) + return nullptr; + + Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, src_ast, src_namespace_decl); + + if (!copied_decl) + return nullptr; + + NamespaceDecl *copied_namespace_decl = dyn_cast(copied_decl); + + if (!copied_namespace_decl) + return nullptr; + + context.m_decls.push_back(copied_namespace_decl); + + m_ast_importer_sp->RegisterNamespaceMap(copied_namespace_decl, namespace_decls); + + return dyn_cast(copied_decl); +} + +CompilerType +ClangASTSource::GuardedCopyType (const CompilerType &src_type) +{ + ClangASTContext *src_ast = llvm::dyn_cast_or_null(src_type.GetTypeSystem()); + if (src_ast == nullptr) + return CompilerType(); + + ClangASTMetrics::RegisterLLDBImport(); + + SetImportInProgress(true); + + QualType copied_qual_type = m_ast_importer_sp->CopyType (m_ast_context, src_ast->getASTContext(), ClangASTContext::GetQualType(src_type)); + + SetImportInProgress(false); + + if (copied_qual_type.getAsOpaquePtr() && copied_qual_type->getCanonicalTypeInternal().isNull()) + // this shouldn't happen, but we're hardening because the AST importer seems to be generating bad types + // on occasion. + return CompilerType(); + + return CompilerType(m_ast_context, copied_qual_type); +} + +clang::NamedDecl * +NameSearchContext::AddVarDecl(const CompilerType &type) +{ + assert (type && "Type for variable must be valid!"); + + if (!type.IsValid()) + return NULL; + + ClangASTContext* lldb_ast = llvm::dyn_cast(type.GetTypeSystem()); + if (!lldb_ast) + return NULL; + + IdentifierInfo *ii = m_decl_name.getAsIdentifierInfo(); + + clang::ASTContext *ast = lldb_ast->getASTContext(); + + clang::NamedDecl *Decl = VarDecl::Create(*ast, + const_cast(m_decl_context), + SourceLocation(), + SourceLocation(), + ii, + ClangASTContext::GetQualType(type), + 0, + SC_Static); + m_decls.push_back(Decl); + + return Decl; +} + +clang::NamedDecl * +NameSearchContext::AddFunDecl (const CompilerType &type, bool extern_c) +{ + assert (type && "Type for variable must be valid!"); + + if (!type.IsValid()) + return NULL; + + if (m_function_types.count(type)) + return NULL; + + ClangASTContext* lldb_ast = llvm::dyn_cast(type.GetTypeSystem()); + if (!lldb_ast) + return NULL; + + m_function_types.insert(type); + + QualType qual_type (ClangASTContext::GetQualType(type)); + + clang::ASTContext *ast = lldb_ast->getASTContext(); + + const bool isInlineSpecified = false; + const bool hasWrittenPrototype = true; + const bool isConstexprSpecified = false; + + clang::DeclContext *context = const_cast(m_decl_context); + + if (extern_c) { + context = LinkageSpecDecl::Create(*ast, + context, + SourceLocation(), + SourceLocation(), + clang::LinkageSpecDecl::LanguageIDs::lang_c, + false); + } + + // Pass the identifier info for functions the decl_name is needed for operators + clang::DeclarationName decl_name = m_decl_name.getNameKind() == DeclarationName::Identifier ? m_decl_name.getAsIdentifierInfo() : m_decl_name; + + clang::FunctionDecl *func_decl = FunctionDecl::Create (*ast, + context, + SourceLocation(), + SourceLocation(), + decl_name, + qual_type, + NULL, + SC_Extern, + isInlineSpecified, + hasWrittenPrototype, + isConstexprSpecified); + + // We have to do more than just synthesize the FunctionDecl. We have to + // synthesize ParmVarDecls for all of the FunctionDecl's arguments. To do + // this, we raid the function's FunctionProtoType for types. + + const FunctionProtoType *func_proto_type = qual_type.getTypePtr()->getAs(); + + if (func_proto_type) + { + unsigned NumArgs = func_proto_type->getNumParams(); + unsigned ArgIndex; + + SmallVector parm_var_decls; + + for (ArgIndex = 0; ArgIndex < NumArgs; ++ArgIndex) + { + QualType arg_qual_type (func_proto_type->getParamType(ArgIndex)); + + parm_var_decls.push_back(ParmVarDecl::Create (*ast, + const_cast(context), + SourceLocation(), + SourceLocation(), + NULL, + arg_qual_type, + NULL, + SC_Static, + NULL)); + } + + func_decl->setParams(ArrayRef(parm_var_decls)); + } + else + { + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf("Function type wasn't a FunctionProtoType"); + } + + m_decls.push_back(func_decl); + + return func_decl; +} + +clang::NamedDecl * +NameSearchContext::AddGenericFunDecl() +{ + FunctionProtoType::ExtProtoInfo proto_info; + + proto_info.Variadic = true; + + QualType generic_function_type(m_ast_source.m_ast_context->getFunctionType (m_ast_source.m_ast_context->UnknownAnyTy, // result + ArrayRef(), // argument types + proto_info)); + + return AddFunDecl(CompilerType (m_ast_source.m_ast_context, generic_function_type), true); +} + +clang::NamedDecl * +NameSearchContext::AddTypeDecl(const CompilerType &clang_type) +{ + if (clang_type) + { + QualType qual_type = ClangASTContext::GetQualType(clang_type); + + if (const TypedefType *typedef_type = llvm::dyn_cast(qual_type)) + { + TypedefNameDecl *typedef_name_decl = typedef_type->getDecl(); + + m_decls.push_back(typedef_name_decl); + + return (NamedDecl*)typedef_name_decl; + } + else if (const TagType *tag_type = qual_type->getAs()) + { + TagDecl *tag_decl = tag_type->getDecl(); + + m_decls.push_back(tag_decl); + + return tag_decl; + } + else if (const ObjCObjectType *objc_object_type = qual_type->getAs()) + { + ObjCInterfaceDecl *interface_decl = objc_object_type->getInterface(); + + m_decls.push_back((NamedDecl*)interface_decl); + + return (NamedDecl*)interface_decl; + } + } + return NULL; +} + +void +NameSearchContext::AddLookupResult (clang::DeclContextLookupResult result) +{ + for (clang::NamedDecl *decl : result) + m_decls.push_back (decl); +} + +void +NameSearchContext::AddNamedDecl (clang::NamedDecl *decl) +{ + m_decls.push_back (decl); +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h new file mode 100644 index 0000000000000..bb6384721f513 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h @@ -0,0 +1,526 @@ +//===-- ClangASTSource.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangASTSource_h_ +#define liblldb_ClangASTSource_h_ + +#include + +#include "clang/Basic/IdentifierTable.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" +#include "lldb/Symbol/ClangASTImporter.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Target/Target.h" + +#include "llvm/ADT/SmallSet.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ClangASTSource ClangASTSource.h "lldb/Expression/ClangASTSource.h" +/// @brief Provider for named objects defined in the debug info for Clang +/// +/// As Clang parses an expression, it may encounter names that are not +/// defined inside the expression, including variables, functions, and +/// types. Clang knows the name it is looking for, but nothing else. +/// The ExternalSemaSource class provides Decls (VarDecl, FunDecl, TypeDecl) +/// to Clang for these names, consulting the ClangExpressionDeclMap to do +/// the actual lookups. +//---------------------------------------------------------------------- +class ClangASTSource : + public ClangExternalASTSourceCommon, + public ClangASTImporter::MapCompleter +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] declMap + /// A reference to the LLDB object that handles entity lookup. + //------------------------------------------------------------------ + ClangASTSource (const lldb::TargetSP &target) : + m_import_in_progress (false), + m_lookups_enabled (false), + m_target (target), + m_ast_context (NULL), + m_active_lexical_decls (), + m_active_lookups () + { + m_ast_importer_sp = m_target->GetClangASTImporter(); + } + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~ClangASTSource() override; + + //------------------------------------------------------------------ + /// Interface stubs. + //------------------------------------------------------------------ + clang::Decl *GetExternalDecl (uint32_t) override { return NULL; } + clang::Stmt *GetExternalDeclStmt (uint64_t) override { return NULL; } + clang::Selector GetExternalSelector (uint32_t) override { return clang::Selector(); } + uint32_t GetNumExternalSelectors () override { return 0; } + clang::CXXBaseSpecifier *GetExternalCXXBaseSpecifiers (uint64_t Offset) override + { return NULL; } + void MaterializeVisibleDecls (const clang::DeclContext *DC) + { return; } + + void InstallASTContext (clang::ASTContext *ast_context) + { + m_ast_context = ast_context; + m_ast_importer_sp->InstallMapCompleter(ast_context, *this); + } + + // + // APIs for ExternalASTSource + // + + //------------------------------------------------------------------ + /// Look up all Decls that match a particular name. Only handles + /// Identifiers and DeclContexts that are either NamespaceDecls or + /// TranslationUnitDecls. Calls SetExternalVisibleDeclsForName with + /// the result. + /// + /// The work for this function is done by + /// void FindExternalVisibleDecls (NameSearchContext &); + /// + /// @param[in] DC + /// The DeclContext to register the found Decls in. + /// + /// @param[in] Name + /// The name to find entries for. + /// + /// @return + /// Whatever SetExternalVisibleDeclsForName returns. + //------------------------------------------------------------------ + bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC, clang::DeclarationName Name) override; + + //------------------------------------------------------------------ + /// Enumerate all Decls in a given lexical context. + /// + /// @param[in] DC + /// The DeclContext being searched. + /// + /// @param[in] isKindWeWant + /// A callback function that returns true given the + /// DeclKinds of desired Decls, and false otherwise. + /// + /// @param[in] Decls + /// A vector that is filled in with matching Decls. + //------------------------------------------------------------------ + void FindExternalLexicalDecls( + const clang::DeclContext *DC, llvm::function_ref IsKindWeWant, + llvm::SmallVectorImpl &Decls) override; + + //------------------------------------------------------------------ + /// Specify the layout of the contents of a RecordDecl. + /// + /// @param[in] Record + /// The record (in the parser's AST context) that needs to be + /// laid out. + /// + /// @param[out] Size + /// The total size of the record in bits. + /// + /// @param[out] Alignment + /// The alignment of the record in bits. + /// + /// @param[in] FieldOffsets + /// A map that must be populated with pairs of the record's + /// fields (in the parser's AST context) and their offsets + /// (measured in bits). + /// + /// @param[in] BaseOffsets + /// A map that must be populated with pairs of the record's + /// C++ concrete base classes (in the parser's AST context, + /// and only if the record is a CXXRecordDecl and has base + /// classes) and their offsets (measured in bytes). + /// + /// @param[in] VirtualBaseOffsets + /// A map that must be populated with pairs of the record's + /// C++ virtual base classes (in the parser's AST context, + /// and only if the record is a CXXRecordDecl and has base + /// classes) and their offsets (measured in bytes). + /// + /// @return + /// True <=> the layout is valid. + //----------------------------------------------------------------- + bool layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap &FieldOffsets, + llvm::DenseMap &BaseOffsets, + llvm::DenseMap &VirtualBaseOffsets) override; + + //------------------------------------------------------------------ + /// Complete a TagDecl. + /// + /// @param[in] Tag + /// The Decl to be completed in place. + //------------------------------------------------------------------ + void CompleteType(clang::TagDecl *Tag) override; + + //------------------------------------------------------------------ + /// Complete an ObjCInterfaceDecl. + /// + /// @param[in] Class + /// The Decl to be completed in place. + //------------------------------------------------------------------ + void CompleteType(clang::ObjCInterfaceDecl *Class) override; + + //------------------------------------------------------------------ + /// Called on entering a translation unit. Tells Clang by calling + /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() + /// that this object has something to say about undefined names. + /// + /// @param[in] ASTConsumer + /// Unused. + //------------------------------------------------------------------ + void StartTranslationUnit(clang::ASTConsumer *Consumer) override; + + // + // APIs for NamespaceMapCompleter + // + + //------------------------------------------------------------------ + /// Look up the modules containing a given namespace and put the + /// appropriate entries in the namespace map. + /// + /// @param[in] namespace_map + /// The map to be completed. + /// + /// @param[in] name + /// The name of the namespace to be found. + /// + /// @param[in] parent_map + /// The map for the namespace's parent namespace, if there is + /// one. + //------------------------------------------------------------------ + void CompleteNamespaceMap(ClangASTImporter::NamespaceMapSP &namespace_map, const ConstString &name, + ClangASTImporter::NamespaceMapSP &parent_map) const override; + + // + // Helper APIs + // + + clang::NamespaceDecl * + AddNamespace (NameSearchContext &context, + ClangASTImporter::NamespaceMapSP &namespace_decls); + + //------------------------------------------------------------------ + /// The worker function for FindExternalVisibleDeclsByName. + /// + /// @param[in] context + /// The NameSearchContext to use when filing results. + //------------------------------------------------------------------ + virtual void FindExternalVisibleDecls (NameSearchContext &context); + + void SetImportInProgress (bool import_in_progress) { m_import_in_progress = import_in_progress; } + bool GetImportInProgress () { return m_import_in_progress; } + + void SetLookupsEnabled (bool lookups_enabled) { m_lookups_enabled = lookups_enabled; } + bool GetLookupsEnabled () { return m_lookups_enabled; } + + //---------------------------------------------------------------------- + /// @class ClangASTSourceProxy ClangASTSource.h "lldb/Expression/ClangASTSource.h" + /// @brief Proxy for ClangASTSource + /// + /// Clang AST contexts like to own their AST sources, so this is a + /// state-free proxy object. + //---------------------------------------------------------------------- + class ClangASTSourceProxy : public ClangExternalASTSourceCommon + { + public: + ClangASTSourceProxy (ClangASTSource &original) : + m_original(original) + { + } + + bool + FindExternalVisibleDeclsByName(const clang::DeclContext *DC, clang::DeclarationName Name) override + { + return m_original.FindExternalVisibleDeclsByName(DC, Name); + } + + void + FindExternalLexicalDecls(const clang::DeclContext *DC, + llvm::function_ref IsKindWeWant, + llvm::SmallVectorImpl &Decls) override + { + return m_original.FindExternalLexicalDecls(DC, IsKindWeWant, Decls); + } + + void + CompleteType(clang::TagDecl *Tag) override + { + return m_original.CompleteType(Tag); + } + + void + CompleteType(clang::ObjCInterfaceDecl *Class) override + { + return m_original.CompleteType(Class); + } + + bool + layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap &FieldOffsets, + llvm::DenseMap &BaseOffsets, + llvm::DenseMap &VirtualBaseOffsets) override + { + return m_original.layoutRecordType(Record, + Size, + Alignment, + FieldOffsets, + BaseOffsets, + VirtualBaseOffsets); + } + + void + StartTranslationUnit(clang::ASTConsumer *Consumer) override + { + return m_original.StartTranslationUnit(Consumer); + } + + ClangASTMetadata * + GetMetadata(const void * object) + { + return m_original.GetMetadata(object); + } + + void + SetMetadata(const void * object, ClangASTMetadata &metadata) + { + return m_original.SetMetadata(object, metadata); + } + + bool + HasMetadata(const void * object) + { + return m_original.HasMetadata(object); + } + private: + ClangASTSource &m_original; + }; + + clang::ExternalASTSource *CreateProxy() + { + return new ClangASTSourceProxy(*this); + } + +protected: + //------------------------------------------------------------------ + /// Look for the complete version of an Objective-C interface, and + /// return it if found. + /// + /// @param[in] interface_decl + /// An ObjCInterfaceDecl that may not be the complete one. + /// + /// @return + /// NULL if the complete interface couldn't be found; + /// the complete interface otherwise. + //------------------------------------------------------------------ + clang::ObjCInterfaceDecl * + GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_decl); + + //------------------------------------------------------------------ + /// Find all entities matching a given name in a given module, + /// using a NameSearchContext to make Decls for them. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// @param[in] module + /// If non-NULL, the module to query. + /// + /// @param[in] namespace_decl + /// If valid and module is non-NULL, the parent namespace. + /// + /// @param[in] current_id + /// The ID for the current FindExternalVisibleDecls invocation, + /// for logging purposes. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + void + FindExternalVisibleDecls (NameSearchContext &context, + lldb::ModuleSP module, + CompilerDeclContext &namespace_decl, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Find all Objective-C methods matching a given selector. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// Its m_decl_name contains the selector and its m_decl_context + /// is the containing object. + //------------------------------------------------------------------ + void + FindObjCMethodDecls (NameSearchContext &context); + + //------------------------------------------------------------------ + /// Find all Objective-C properties and ivars with a given name. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// Its m_decl_name contains the name and its m_decl_context + /// is the containing object. + //------------------------------------------------------------------ + void + FindObjCPropertyAndIvarDecls (NameSearchContext &context); + + //------------------------------------------------------------------ + /// A wrapper for ClangASTContext::CopyType that sets a flag that + /// indicates that we should not respond to queries during import. + /// + /// @param[in] dest_context + /// The target AST context, typically the parser's AST context. + /// + /// @param[in] source_context + /// The source AST context, typically the AST context of whatever + /// symbol file the type was found in. + /// + /// @param[in] src_type + /// The source type. + /// + /// @return + /// The imported type. + //------------------------------------------------------------------ + CompilerType + GuardedCopyType (const CompilerType &src_type); + + friend struct NameSearchContext; + + bool m_import_in_progress; + bool m_lookups_enabled; + + const lldb::TargetSP m_target; ///< The target to use in finding variables and types. + clang::ASTContext *m_ast_context; ///< The AST context requests are coming in for. + lldb::ClangASTImporterSP m_ast_importer_sp; ///< The target's AST importer. + std::set m_active_lexical_decls; + std::set m_active_lookups; +}; + +//---------------------------------------------------------------------- +/// @class NameSearchContext ClangASTSource.h "lldb/Expression/ClangASTSource.h" +/// @brief Container for all objects relevant to a single name lookup +/// +/// LLDB needs to create Decls for entities it finds. This class communicates +/// what name is being searched for and provides helper functions to construct +/// Decls given appropriate type information. +//---------------------------------------------------------------------- +struct NameSearchContext { + ClangASTSource &m_ast_source; ///< The AST source making the request + llvm::SmallVectorImpl &m_decls; ///< The list of declarations already constructed + ClangASTImporter::NamespaceMapSP m_namespace_map; ///< The mapping of all namespaces found for this request back to their modules + const clang::DeclarationName &m_decl_name; ///< The name being looked for + const clang::DeclContext *m_decl_context; ///< The DeclContext to put declarations into + llvm::SmallSet m_function_types; ///< All the types of functions that have been reported, so we don't report conflicts + + struct { + bool variable : 1; + bool function_with_type_info : 1; + bool function : 1; + } m_found; + + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] astSource + /// A reference to the AST source making a request. + /// + /// @param[in] decls + /// A reference to a list into which new Decls will be placed. This + /// list is typically empty when the function is called. + /// + /// @param[in] name + /// The name being searched for (always an Identifier). + /// + /// @param[in] dc + /// The DeclContext to register Decls in. + //------------------------------------------------------------------ + NameSearchContext (ClangASTSource &astSource, + llvm::SmallVectorImpl &decls, + clang::DeclarationName &name, + const clang::DeclContext *dc) : + m_ast_source(astSource), + m_decls(decls), + m_decl_name(name), + m_decl_context(dc) + { + memset(&m_found, 0, sizeof(m_found)); + } + + //------------------------------------------------------------------ + /// Create a VarDecl with the name being searched for and the provided + /// type and register it in the right places. + /// + /// @param[in] type + /// The opaque QualType for the VarDecl being registered. + //------------------------------------------------------------------ + clang::NamedDecl *AddVarDecl(const CompilerType &type); + + //------------------------------------------------------------------ + /// Create a FunDecl with the name being searched for and the provided + /// type and register it in the right places. + /// + /// @param[in] type + /// The opaque QualType for the FunDecl being registered. + /// + /// @param[in] extern_c + /// If true, build an extern "C" linkage specification for this. + //------------------------------------------------------------------ + clang::NamedDecl *AddFunDecl(const CompilerType &type, + bool extern_c = false); + + //------------------------------------------------------------------ + /// Create a FunDecl with the name being searched for and generic + /// type (i.e. intptr_t NAME_GOES_HERE(...)) and register it in the + /// right places. + //------------------------------------------------------------------ + clang::NamedDecl *AddGenericFunDecl(); + + //------------------------------------------------------------------ + /// Create a TypeDecl with the name being searched for and the provided + /// type and register it in the right places. + /// + /// @param[in] compiler_type + /// The opaque QualType for the TypeDecl being registered. + //------------------------------------------------------------------ + clang::NamedDecl *AddTypeDecl(const CompilerType &compiler_type); + + + //------------------------------------------------------------------ + /// Add Decls from the provided DeclContextLookupResult to the list + /// of results. + /// + /// @param[in] result + /// The DeclContextLookupResult, usually returned as the result + /// of querying a DeclContext. + //------------------------------------------------------------------ + void AddLookupResult (clang::DeclContextLookupResult result); + + //------------------------------------------------------------------ + /// Add a NamedDecl to the list of results. + /// + /// @param[in] decl + /// The NamedDecl, usually returned as the result + /// of querying a DeclContext. + //------------------------------------------------------------------ + void AddNamedDecl (clang::NamedDecl *decl); +}; + +} // namespace lldb_private + +#endif // liblldb_ClangASTSource_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp new file mode 100644 index 0000000000000..c9bc4b6487cda --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -0,0 +1,2351 @@ +//===-- ClangExpressionDeclMap.cpp -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangExpressionDeclMap.h" + +#include "ASTDumper.h" +#include "ClangASTSource.h" +#include "ClangModulesDeclVendor.h" +#include "ClangPersistentVariables.h" + +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/Decl.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/RegisterValue.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectVariable.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompilerDecl.h" +#include "lldb/Symbol/CompilerDeclContext.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/TypeList.h" +#include "lldb/Symbol/Variable.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/CPPLanguageRuntime.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" + +#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" + +using namespace lldb; +using namespace lldb_private; +using namespace clang; + +ClangExpressionDeclMap::ClangExpressionDeclMap (bool keep_result_in_memory, + Materializer::PersistentVariableDelegate *result_delegate, + ExecutionContext &exe_ctx) : + ClangASTSource (exe_ctx.GetTargetSP()), + m_found_entities (), + m_struct_members (), + m_keep_result_in_memory (keep_result_in_memory), + m_result_delegate (result_delegate), + m_parser_vars (), + m_struct_vars () +{ + EnableStructVars(); +} + +ClangExpressionDeclMap::~ClangExpressionDeclMap() +{ + // Note: The model is now that the parser's AST context and all associated + // data does not vanish until the expression has been executed. This means + // that valuable lookup data (like namespaces) doesn't vanish, but + + DidParse(); + DisableStructVars(); +} + +bool +ClangExpressionDeclMap::WillParse(ExecutionContext &exe_ctx, + Materializer *materializer) +{ + ClangASTMetrics::ClearLocalCounters(); + + EnableParserVars(); + m_parser_vars->m_exe_ctx = exe_ctx; + + Target *target = exe_ctx.GetTargetPtr(); + if (exe_ctx.GetFramePtr()) + m_parser_vars->m_sym_ctx = exe_ctx.GetFramePtr()->GetSymbolContext(lldb::eSymbolContextEverything); + else if (exe_ctx.GetThreadPtr() && exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(0)) + m_parser_vars->m_sym_ctx = exe_ctx.GetThreadPtr()->GetStackFrameAtIndex(0)->GetSymbolContext(lldb::eSymbolContextEverything); + else if (exe_ctx.GetProcessPtr()) + { + m_parser_vars->m_sym_ctx.Clear(true); + m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP(); + } + else if (target) + { + m_parser_vars->m_sym_ctx.Clear(true); + m_parser_vars->m_sym_ctx.target_sp = exe_ctx.GetTargetSP(); + } + + if (target) + { + m_parser_vars->m_persistent_vars = llvm::cast(target->GetPersistentExpressionStateForLanguage(eLanguageTypeC)); + + if (!target->GetScratchClangASTContext()) + return false; + } + + m_parser_vars->m_target_info = GetTargetInfo(); + m_parser_vars->m_materializer = materializer; + + return true; +} + +void +ClangExpressionDeclMap::InstallCodeGenerator (clang::ASTConsumer *code_gen) +{ + assert(m_parser_vars); + m_parser_vars->m_code_gen = code_gen; +} + +void +ClangExpressionDeclMap::DidParse() +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + ClangASTMetrics::DumpCounters(log); + + if (m_parser_vars.get()) + { + for (size_t entity_index = 0, num_entities = m_found_entities.GetSize(); + entity_index < num_entities; + ++entity_index) + { + ExpressionVariableSP var_sp(m_found_entities.GetVariableAtIndex(entity_index)); + if (var_sp) + llvm::cast(var_sp.get())->DisableParserVars(GetParserID()); + } + + for (size_t pvar_index = 0, num_pvars = m_parser_vars->m_persistent_vars->GetSize(); + pvar_index < num_pvars; + ++pvar_index) + { + ExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariableAtIndex(pvar_index)); + if (ClangExpressionVariable *clang_var = llvm::dyn_cast(pvar_sp.get())) + clang_var->DisableParserVars(GetParserID()); + } + + DisableParserVars(); + } +} + +// Interface for IRForTarget + +ClangExpressionDeclMap::TargetInfo +ClangExpressionDeclMap::GetTargetInfo() +{ + assert (m_parser_vars.get()); + + TargetInfo ret; + + ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; + + Process *process = exe_ctx.GetProcessPtr(); + if (process) + { + ret.byte_order = process->GetByteOrder(); + ret.address_byte_size = process->GetAddressByteSize(); + } + else + { + Target *target = exe_ctx.GetTargetPtr(); + if (target) + { + ret.byte_order = target->GetArchitecture().GetByteOrder(); + ret.address_byte_size = target->GetArchitecture().GetAddressByteSize(); + } + } + + return ret; +} + +bool +ClangExpressionDeclMap::AddPersistentVariable +( + const NamedDecl *decl, + const ConstString &name, + TypeFromParser parser_type, + bool is_result, + bool is_lvalue +) +{ + assert (m_parser_vars.get()); + + ClangASTContext *ast = llvm::dyn_cast_or_null(parser_type.GetTypeSystem()); + if (ast == nullptr) + return false; + + if (m_parser_vars->m_materializer && is_result) + { + Error err; + + ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; + Target *target = exe_ctx.GetTargetPtr(); + if (target == nullptr) + return false; + + ClangASTContext *context(target->GetScratchClangASTContext()); + + TypeFromUser user_type(m_ast_importer_sp->DeportType(context->getASTContext(), + ast->getASTContext(), + parser_type.GetOpaqueQualType()), + context); + + uint32_t offset = m_parser_vars->m_materializer->AddResultVariable(user_type, + is_lvalue, + m_keep_result_in_memory, + m_result_delegate, + err); + + ClangExpressionVariable *var = new ClangExpressionVariable(exe_ctx.GetBestExecutionContextScope(), + name, + user_type, + m_parser_vars->m_target_info.byte_order, + m_parser_vars->m_target_info.address_byte_size); + + m_found_entities.AddNewlyConstructedVariable(var); + + var->EnableParserVars(GetParserID()); + + ClangExpressionVariable::ParserVars *parser_vars = var->GetParserVars(GetParserID()); + + parser_vars->m_named_decl = decl; + parser_vars->m_parser_type = parser_type; + + var->EnableJITVars(GetParserID()); + + ClangExpressionVariable::JITVars *jit_vars = var->GetJITVars(GetParserID()); + + jit_vars->m_offset = offset; + + return true; + } + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; + Target *target = exe_ctx.GetTargetPtr(); + if (target == NULL) + return false; + + ClangASTContext *context(target->GetScratchClangASTContext()); + + TypeFromUser user_type(m_ast_importer_sp->DeportType(context->getASTContext(), + ast->getASTContext(), + parser_type.GetOpaqueQualType()), + context); + + if (!user_type.GetOpaqueQualType()) + { + if (log) + log->Printf("Persistent variable's type wasn't copied successfully"); + return false; + } + + if (!m_parser_vars->m_target_info.IsValid()) + return false; + + ClangExpressionVariable *var = llvm::cast(m_parser_vars->m_persistent_vars->CreatePersistentVariable (exe_ctx.GetBestExecutionContextScope (), + name, + user_type, + m_parser_vars->m_target_info.byte_order, + m_parser_vars->m_target_info.address_byte_size).get()); + + if (!var) + return false; + + var->m_frozen_sp->SetHasCompleteType(); + + if (is_result) + var->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry; + else + var->m_flags |= ClangExpressionVariable::EVKeepInTarget; // explicitly-declared persistent variables should persist + + if (is_lvalue) + { + var->m_flags |= ClangExpressionVariable::EVIsProgramReference; + } + else + { + var->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated; + var->m_flags |= ClangExpressionVariable::EVNeedsAllocation; + } + + if (m_keep_result_in_memory) + { + var->m_flags |= ClangExpressionVariable::EVKeepInTarget; + } + + if (log) + log->Printf("Created persistent variable with flags 0x%hx", var->m_flags); + + var->EnableParserVars(GetParserID()); + + ClangExpressionVariable::ParserVars *parser_vars = var->GetParserVars(GetParserID()); + + parser_vars->m_named_decl = decl; + parser_vars->m_parser_type = parser_type; + + return true; +} + +bool +ClangExpressionDeclMap::AddValueToStruct +( + const NamedDecl *decl, + const ConstString &name, + llvm::Value *value, + size_t size, + lldb::offset_t alignment +) +{ + assert (m_struct_vars.get()); + assert (m_parser_vars.get()); + + bool is_persistent_variable = false; + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + m_struct_vars->m_struct_laid_out = false; + + if (ClangExpressionVariable::FindVariableInList(m_struct_members, decl, GetParserID())) + return true; + + ClangExpressionVariable *var(ClangExpressionVariable::FindVariableInList(m_found_entities, decl, GetParserID())); + + if (!var) + { + var = ClangExpressionVariable::FindVariableInList(*m_parser_vars->m_persistent_vars, decl, GetParserID()); + is_persistent_variable = true; + } + + if (!var) + return false; + + if (log) + log->Printf("Adding value for (NamedDecl*)%p [%s - %s] to the structure", + static_cast(decl), name.GetCString(), + var->GetName().GetCString()); + + // We know entity->m_parser_vars is valid because we used a parser variable + // to find it + + ClangExpressionVariable::ParserVars *parser_vars = llvm::cast(var)->GetParserVars(GetParserID()); + + parser_vars->m_llvm_value = value; + + if (ClangExpressionVariable::JITVars *jit_vars = llvm::cast(var)->GetJITVars(GetParserID())) + { + // We already laid this out; do not touch + + if (log) + log->Printf("Already placed at 0x%llx", (unsigned long long)jit_vars->m_offset); + } + + llvm::cast(var)->EnableJITVars(GetParserID()); + + ClangExpressionVariable::JITVars *jit_vars = llvm::cast(var)->GetJITVars(GetParserID()); + + jit_vars->m_alignment = alignment; + jit_vars->m_size = size; + + m_struct_members.AddVariable(var->shared_from_this()); + + if (m_parser_vars->m_materializer) + { + uint32_t offset = 0; + + Error err; + + if (is_persistent_variable) + { + ExpressionVariableSP var_sp(var->shared_from_this()); + offset = m_parser_vars->m_materializer->AddPersistentVariable(var_sp, nullptr, err); + } + else + { + if (const lldb_private::Symbol *sym = parser_vars->m_lldb_sym) + offset = m_parser_vars->m_materializer->AddSymbol(*sym, err); + else if (const RegisterInfo *reg_info = var->GetRegisterInfo()) + offset = m_parser_vars->m_materializer->AddRegister(*reg_info, err); + else if (parser_vars->m_lldb_var) + offset = m_parser_vars->m_materializer->AddVariable(parser_vars->m_lldb_var, err); + } + + if (!err.Success()) + return false; + + if (log) + log->Printf("Placed at 0x%llx", (unsigned long long)offset); + + jit_vars->m_offset = offset; // TODO DoStructLayout() should not change this. + } + + return true; +} + +bool +ClangExpressionDeclMap::DoStructLayout () +{ + assert (m_struct_vars.get()); + + if (m_struct_vars->m_struct_laid_out) + return true; + + if (!m_parser_vars->m_materializer) + return false; + + m_struct_vars->m_struct_alignment = m_parser_vars->m_materializer->GetStructAlignment(); + m_struct_vars->m_struct_size = m_parser_vars->m_materializer->GetStructByteSize(); + m_struct_vars->m_struct_laid_out = true; + return true; +} + +bool ClangExpressionDeclMap::GetStructInfo +( + uint32_t &num_elements, + size_t &size, + lldb::offset_t &alignment +) +{ + assert (m_struct_vars.get()); + + if (!m_struct_vars->m_struct_laid_out) + return false; + + num_elements = m_struct_members.GetSize(); + size = m_struct_vars->m_struct_size; + alignment = m_struct_vars->m_struct_alignment; + + return true; +} + +bool +ClangExpressionDeclMap::GetStructElement +( + const NamedDecl *&decl, + llvm::Value *&value, + lldb::offset_t &offset, + ConstString &name, + uint32_t index +) +{ + assert (m_struct_vars.get()); + + if (!m_struct_vars->m_struct_laid_out) + return false; + + if (index >= m_struct_members.GetSize()) + return false; + + ExpressionVariableSP member_sp(m_struct_members.GetVariableAtIndex(index)); + + if (!member_sp) + return false; + + ClangExpressionVariable::ParserVars *parser_vars = llvm::cast(member_sp.get())->GetParserVars(GetParserID()); + ClangExpressionVariable::JITVars *jit_vars = llvm::cast(member_sp.get())->GetJITVars(GetParserID()); + + if (!parser_vars || + !jit_vars || + !member_sp->GetValueObject()) + return false; + + decl = parser_vars->m_named_decl; + value = parser_vars->m_llvm_value; + offset = jit_vars->m_offset; + name = member_sp->GetName(); + + return true; +} + +bool +ClangExpressionDeclMap::GetFunctionInfo +( + const NamedDecl *decl, + uint64_t &ptr +) +{ + ClangExpressionVariable *entity(ClangExpressionVariable::FindVariableInList(m_found_entities, decl, GetParserID())); + + if (!entity) + return false; + + // We know m_parser_vars is valid since we searched for the variable by + // its NamedDecl + + ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); + + ptr = parser_vars->m_lldb_value.GetScalar().ULongLong(); + + return true; +} + +static void +FindCodeSymbolInContext +( + const ConstString &name, + SymbolContext &sym_ctx, + uint32_t name_type_mask, + SymbolContextList &sc_list +) +{ + sc_list.Clear(); + SymbolContextList temp_sc_list; + if (sym_ctx.module_sp) + sym_ctx.module_sp->FindFunctions(name, + NULL, + name_type_mask, + true, // include_symbols + false, // include_inlines + true, // append + temp_sc_list); + if (temp_sc_list.GetSize() == 0) + { + if (sym_ctx.target_sp) + sym_ctx.target_sp->GetImages().FindFunctions(name, + name_type_mask, + true, // include_symbols + false, // include_inlines + true, // append + temp_sc_list); + } + + SymbolContextList internal_symbol_sc_list; + unsigned temp_sc_list_size = temp_sc_list.GetSize(); + for (unsigned i = 0; i < temp_sc_list_size; i++) + { + SymbolContext sc; + temp_sc_list.GetContextAtIndex(i, sc); + if (sc.function) + { + sc_list.Append(sc); + } + else if (sc.symbol) + { + if (sc.symbol->IsExternal()) + { + sc_list.Append(sc); + } + else + { + internal_symbol_sc_list.Append(sc); + } + } + } + + // If we had internal symbols and we didn't find any external symbols or + // functions in debug info, then fallback to the internal symbols + if (sc_list.GetSize() == 0 && internal_symbol_sc_list.GetSize()) + { + sc_list = internal_symbol_sc_list; + } +} + +bool +ClangExpressionDeclMap::GetFunctionAddress +( + const ConstString &name, + uint64_t &func_addr +) +{ + assert (m_parser_vars.get()); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + ExecutionContext &exe_ctx = m_parser_vars->m_exe_ctx; + Target *target = exe_ctx.GetTargetPtr(); + // Back out in all cases where we're not fully initialized + if (target == NULL) + return false; + if (!m_parser_vars->m_sym_ctx.target_sp) + return false; + + SymbolContextList sc_list; + + FindCodeSymbolInContext(name, m_parser_vars->m_sym_ctx, eFunctionNameTypeAuto, sc_list); + + uint32_t sc_list_size = sc_list.GetSize(); + + if (sc_list_size == 0) + { + SymbolContext &sc = m_parser_vars->m_sym_ctx; + if (sc.comp_unit) + { + LanguageType lang_type = sc.comp_unit->GetLanguage(); + if (Language::LanguageIsCPlusPlus(lang_type) && + CPlusPlusLanguage::IsCPPMangledName(name.AsCString())) + { + // 1. Demangle the name + Mangled mangled(name, true); + ConstString demangled = mangled.GetDemangledName(lang_type); + + if (demangled) + { + FindCodeSymbolInContext( + demangled, m_parser_vars->m_sym_ctx, eFunctionNameTypeFull, sc_list); + sc_list_size = sc_list.GetSize(); + } + } + } + } + + if (sc_list_size == 0) + { + // We occasionally get debug information in which a const function is reported + // as non-const, so the mangled name is wrong. This is a hack to compensate. + + if (!strncmp(name.GetCString(), "_ZN", 3) && + strncmp(name.GetCString(), "_ZNK", 4)) + { + std::string fixed_scratch("_ZNK"); + fixed_scratch.append(name.GetCString() + 3); + ConstString fixed_name(fixed_scratch.c_str()); + + if (log) + log->Printf("Failed to find symbols given non-const name %s; trying %s", name.GetCString(), fixed_name.GetCString()); + + FindCodeSymbolInContext( + fixed_name, m_parser_vars->m_sym_ctx, eFunctionNameTypeAuto, sc_list); + sc_list_size = sc_list.GetSize(); + } + } + + lldb::addr_t intern_callable_load_addr = LLDB_INVALID_ADDRESS; + + for (uint32_t i=0; 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, + const ConstString &name, + lldb::SymbolType symbol_type, + lldb_private::Module *module) +{ + SymbolContextList sc_list; + + if (module) + module->FindSymbolsWithNameAndType(name, symbol_type, sc_list); + else + target.GetImages().FindSymbolsWithNameAndType(name, symbol_type, sc_list); + + const uint32_t num_matches = sc_list.GetSize(); + addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; + + for (uint32_t i=0; iGetAddress(); + + if (!sym_address.IsValid()) + continue; + + switch (sym_ctx.symbol->GetType()) + { + case eSymbolTypeCode: + case eSymbolTypeTrampoline: + symbol_load_addr = sym_address.GetCallableLoadAddress (&target); + break; + + case eSymbolTypeResolver: + symbol_load_addr = sym_address.GetCallableLoadAddress (&target, true); + break; + + case eSymbolTypeReExported: + { + ConstString reexport_name = sym_ctx.symbol->GetReExportedSymbolName(); + if (reexport_name) + { + ModuleSP reexport_module_sp; + ModuleSpec reexport_module_spec; + reexport_module_spec.GetPlatformFileSpec() = sym_ctx.symbol->GetReExportedSymbolSharedLibrary(); + if (reexport_module_spec.GetPlatformFileSpec()) + { + reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); + if (!reexport_module_sp) + { + reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear(); + reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); + } + } + symbol_load_addr = GetSymbolAddress(target, process, sym_ctx.symbol->GetReExportedSymbolName(), symbol_type, reexport_module_sp.get()); + } + } + break; + + case eSymbolTypeData: + case eSymbolTypeRuntime: + case eSymbolTypeVariable: + case eSymbolTypeLocal: + case eSymbolTypeParam: + case eSymbolTypeInvalid: + case eSymbolTypeAbsolute: + case eSymbolTypeException: + case eSymbolTypeSourceFile: + case eSymbolTypeHeaderFile: + case eSymbolTypeObjectFile: + case eSymbolTypeCommonBlock: + case eSymbolTypeBlock: + case eSymbolTypeVariableType: + case eSymbolTypeLineEntry: + case eSymbolTypeLineHeader: + case eSymbolTypeScopeBegin: + case eSymbolTypeScopeEnd: + case eSymbolTypeAdditional: + case eSymbolTypeCompiler: + case eSymbolTypeInstrumentation: + case eSymbolTypeUndefined: + case eSymbolTypeObjCClass: + case eSymbolTypeObjCMetaClass: + case eSymbolTypeObjCIVar: + symbol_load_addr = sym_address.GetLoadAddress (&target); + break; + } + } + + if (symbol_load_addr == LLDB_INVALID_ADDRESS && process) + { + ObjCLanguageRuntime *runtime = process->GetObjCLanguageRuntime(); + + if (runtime) + { + symbol_load_addr = runtime->LookupRuntimeSymbol(name); + } + } + + return symbol_load_addr; +} + +addr_t +ClangExpressionDeclMap::GetSymbolAddress (const ConstString &name, lldb::SymbolType symbol_type) +{ + assert (m_parser_vars.get()); + + if (!m_parser_vars->m_exe_ctx.GetTargetPtr()) + return false; + + return GetSymbolAddress(m_parser_vars->m_exe_ctx.GetTargetRef(), m_parser_vars->m_exe_ctx.GetProcessPtr(), name, symbol_type); +} + +const Symbol * +ClangExpressionDeclMap::FindGlobalDataSymbol (Target &target, + const ConstString &name, + lldb_private::Module *module) +{ + SymbolContextList sc_list; + + if (module) + module->FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list); + else + target.GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list); + + const uint32_t matches = sc_list.GetSize(); + for (uint32_t i=0; iGetAddress(); + + if (sym_address.IsValid()) + { + switch (symbol->GetType()) + { + case eSymbolTypeData: + case eSymbolTypeRuntime: + case eSymbolTypeAbsolute: + case eSymbolTypeObjCClass: + case eSymbolTypeObjCMetaClass: + case eSymbolTypeObjCIVar: + if (symbol->GetDemangledNameIsSynthesized()) + { + // If the demangled name was synthesized, then don't use it + // for expressions. Only let the symbol match if the mangled + // named matches for these symbols. + if (symbol->GetMangled().GetMangledName() != name) + break; + } + return symbol; + + case eSymbolTypeReExported: + { + ConstString reexport_name = symbol->GetReExportedSymbolName(); + if (reexport_name) + { + ModuleSP reexport_module_sp; + ModuleSpec reexport_module_spec; + reexport_module_spec.GetPlatformFileSpec() = symbol->GetReExportedSymbolSharedLibrary(); + if (reexport_module_spec.GetPlatformFileSpec()) + { + reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); + if (!reexport_module_sp) + { + reexport_module_spec.GetPlatformFileSpec().GetDirectory().Clear(); + reexport_module_sp = target.GetImages().FindFirstModule(reexport_module_spec); + } + } + // Don't allow us to try and resolve a re-exported symbol if it is the same + // as the current symbol + if (name == symbol->GetReExportedSymbolName() && module == reexport_module_sp.get()) + return NULL; + + return FindGlobalDataSymbol(target, symbol->GetReExportedSymbolName(), reexport_module_sp.get()); + } + } + break; + + case eSymbolTypeCode: // We already lookup functions elsewhere + case eSymbolTypeVariable: + case eSymbolTypeLocal: + case eSymbolTypeParam: + case eSymbolTypeTrampoline: + case eSymbolTypeInvalid: + case eSymbolTypeException: + case eSymbolTypeSourceFile: + case eSymbolTypeHeaderFile: + case eSymbolTypeObjectFile: + case eSymbolTypeCommonBlock: + case eSymbolTypeBlock: + case eSymbolTypeVariableType: + case eSymbolTypeLineEntry: + case eSymbolTypeLineHeader: + case eSymbolTypeScopeBegin: + case eSymbolTypeScopeEnd: + case eSymbolTypeAdditional: + case eSymbolTypeCompiler: + case eSymbolTypeInstrumentation: + case eSymbolTypeUndefined: + case eSymbolTypeResolver: + break; + } + } + } + } + + return NULL; +} + +lldb::VariableSP +ClangExpressionDeclMap::FindGlobalVariable +( + Target &target, + ModuleSP &module, + const ConstString &name, + CompilerDeclContext *namespace_decl, + TypeFromUser *type +) +{ + VariableList vars; + + if (module && namespace_decl) + module->FindGlobalVariables (name, namespace_decl, true, -1, vars); + else + target.GetImages().FindGlobalVariables(name, true, -1, vars); + + if (vars.GetSize()) + { + if (type) + { + for (size_t i = 0; i < vars.GetSize(); ++i) + { + VariableSP var_sp = vars.GetVariableAtIndex(i); + + if (ClangASTContext::AreTypesSame(*type, var_sp->GetType()->GetFullCompilerType ())) + return var_sp; + } + } + else + { + return vars.GetVariableAtIndex(0); + } + } + + return VariableSP(); +} + +// Interface for ClangASTSource + +void +ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context) +{ + assert (m_ast_context); + + ClangASTMetrics::RegisterVisibleQuery(); + + const ConstString name(context.m_decl_name.getAsString().c_str()); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (GetImportInProgress()) + { + if (log && log->GetVerbose()) + log->Printf("Ignoring a query during an import"); + return; + } + + static unsigned int invocation_id = 0; + unsigned int current_id = invocation_id++; + + if (log) + { + if (!context.m_decl_context) + log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in a NULL DeclContext", current_id, name.GetCString()); + else if (const NamedDecl *context_named_decl = dyn_cast(context.m_decl_context)) + log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in '%s'", current_id, name.GetCString(), context_named_decl->getNameAsString().c_str()); + else + log->Printf("ClangExpressionDeclMap::FindExternalVisibleDecls[%u] for '%s' in a '%s'", current_id, name.GetCString(), context.m_decl_context->getDeclKindName()); + } + + if (const NamespaceDecl *namespace_context = dyn_cast(context.m_decl_context)) + { + ClangASTImporter::NamespaceMapSP namespace_map = m_ast_importer_sp->GetNamespaceMap(namespace_context); + + if (log && log->GetVerbose()) + log->Printf(" CEDM::FEVD[%u] Inspecting (NamespaceMap*)%p (%d entries)", + current_id, static_cast(namespace_map.get()), + (int)namespace_map->size()); + + if (!namespace_map) + return; + + for (ClangASTImporter::NamespaceMap::iterator i = namespace_map->begin(), e = namespace_map->end(); + i != e; + ++i) + { + if (log) + log->Printf(" CEDM::FEVD[%u] Searching namespace %s in module %s", + current_id, + i->second.GetName().AsCString(), + i->first->GetFileSpec().GetFilename().GetCString()); + + FindExternalVisibleDecls(context, + i->first, + i->second, + current_id); + } + } + else if (isa(context.m_decl_context)) + { + CompilerDeclContext namespace_decl; + + if (log) + log->Printf(" CEDM::FEVD[%u] Searching the root namespace", current_id); + + FindExternalVisibleDecls(context, + lldb::ModuleSP(), + namespace_decl, + current_id); + } + + if (!context.m_found.variable) + ClangASTSource::FindExternalVisibleDecls(context); +} + +void +ClangExpressionDeclMap::FindExternalVisibleDecls (NameSearchContext &context, + lldb::ModuleSP module_sp, + CompilerDeclContext &namespace_decl, + unsigned int current_id) +{ + assert (m_ast_context); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + SymbolContextList sc_list; + + const ConstString name(context.m_decl_name.getAsString().c_str()); + + const char *name_unique_cstr = name.GetCString(); + + if (name_unique_cstr == NULL) + return; + + static ConstString id_name("id"); + static ConstString Class_name("Class"); + + if (name == id_name || name == Class_name) + return; + + // Only look for functions by name out in our symbols if the function + // doesn't start with our phony prefix of '$' + Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); + SymbolContext sym_ctx; + if (frame != nullptr) + sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock); + if (name_unique_cstr[0] == '$' && !namespace_decl) + { + static ConstString g_lldb_class_name ("$__lldb_class"); + + if (name == g_lldb_class_name) + { + // Clang is looking for the type of "this" + + if (frame == NULL) + return; + + + // Find the block that defines the function represented by "sym_ctx" + Block *function_block = sym_ctx.GetFunctionBlock(); + + if (!function_block) + return; + + CompilerDeclContext function_decl_ctx = function_block->GetDeclContext(); + + if (!function_decl_ctx) + return; + + clang::CXXMethodDecl *method_decl = ClangASTContext::DeclContextGetAsCXXMethodDecl(function_decl_ctx); + + if (method_decl) + { + clang::CXXRecordDecl *class_decl = method_decl->getParent(); + + QualType class_qual_type(class_decl->getTypeForDecl(), 0); + + TypeFromUser class_user_type (class_qual_type.getAsOpaquePtr(), + ClangASTContext::GetASTContext(&class_decl->getASTContext())); + + if (log) + { + ASTDumper ast_dumper(class_qual_type); + log->Printf(" CEDM::FEVD[%u] Adding type for $__lldb_class: %s", current_id, ast_dumper.GetCString()); + } + + AddThisType(context, class_user_type, current_id); + + if (method_decl->isInstance()) + { + // self is a pointer to the object + + QualType class_pointer_type = method_decl->getASTContext().getPointerType(class_qual_type); + + TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(), + ClangASTContext::GetASTContext(&method_decl->getASTContext())); + + m_struct_vars->m_object_pointer_type = self_user_type; + } + } + else + { + // This branch will get hit if we are executing code in the context of a function that + // claims to have an object pointer (through DW_AT_object_pointer?) but is not formally a + // method of the class. In that case, just look up the "this" variable in the current + // scope and use its type. + // FIXME: This code is formally correct, but clang doesn't currently emit DW_AT_object_pointer + // for C++ so it hasn't actually been tested. + + VariableList *vars = frame->GetVariableList(false); + + lldb::VariableSP this_var = vars->FindVariable(ConstString("this")); + + if (this_var && + this_var->IsInScope(frame) && + this_var->LocationIsValidForFrame (frame)) + { + Type *this_type = this_var->GetType(); + + if (!this_type) + return; + + TypeFromUser pointee_type = this_type->GetForwardCompilerType ().GetPointeeType(); + + if (pointee_type.IsValid()) + { + if (log) + { + ASTDumper ast_dumper(pointee_type); + log->Printf(" FEVD[%u] Adding type for $__lldb_class: %s", current_id, ast_dumper.GetCString()); + } + + AddThisType(context, pointee_type, current_id); + TypeFromUser this_user_type(this_type->GetFullCompilerType ()); + m_struct_vars->m_object_pointer_type = this_user_type; + return; + } + } + } + + return; + } + + static ConstString g_lldb_objc_class_name ("$__lldb_objc_class"); + if (name == g_lldb_objc_class_name) + { + // Clang is looking for the type of "*self" + + if (!frame) + return; + + SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock); + + // Find the block that defines the function represented by "sym_ctx" + Block *function_block = sym_ctx.GetFunctionBlock(); + + if (!function_block) + return; + + CompilerDeclContext function_decl_ctx = function_block->GetDeclContext(); + + if (!function_decl_ctx) + return; + + clang::ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(function_decl_ctx); + + if (method_decl) + { + ObjCInterfaceDecl* self_interface = method_decl->getClassInterface(); + + if (!self_interface) + return; + + const clang::Type *interface_type = self_interface->getTypeForDecl(); + + if (!interface_type) + return; // This is unlikely, but we have seen crashes where this occurred + + TypeFromUser class_user_type(QualType(interface_type, 0).getAsOpaquePtr(), + ClangASTContext::GetASTContext(&method_decl->getASTContext())); + + if (log) + { + ASTDumper ast_dumper(interface_type); + log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString()); + } + + AddOneType(context, class_user_type, current_id); + + if (method_decl->isInstanceMethod()) + { + // self is a pointer to the object + + QualType class_pointer_type = method_decl->getASTContext().getObjCObjectPointerType(QualType(interface_type, 0)); + + TypeFromUser self_user_type(class_pointer_type.getAsOpaquePtr(), + ClangASTContext::GetASTContext(&method_decl->getASTContext())); + + m_struct_vars->m_object_pointer_type = self_user_type; + } + else + { + // self is a Class pointer + QualType class_type = method_decl->getASTContext().getObjCClassType(); + + TypeFromUser self_user_type(class_type.getAsOpaquePtr(), + ClangASTContext::GetASTContext(&method_decl->getASTContext())); + + m_struct_vars->m_object_pointer_type = self_user_type; + } + + return; + } + else + { + // This branch will get hit if we are executing code in the context of a function that + // claims to have an object pointer (through DW_AT_object_pointer?) but is not formally a + // method of the class. In that case, just look up the "self" variable in the current + // scope and use its type. + + VariableList *vars = frame->GetVariableList(false); + + lldb::VariableSP self_var = vars->FindVariable(ConstString("self")); + + if (self_var && + self_var->IsInScope(frame) && + self_var->LocationIsValidForFrame (frame)) + { + Type *self_type = self_var->GetType(); + + if (!self_type) + return; + + CompilerType self_clang_type = self_type->GetFullCompilerType (); + + if (ClangASTContext::IsObjCClassType(self_clang_type)) + { + return; + } + else if (ClangASTContext::IsObjCObjectPointerType(self_clang_type)) + { + self_clang_type = self_clang_type.GetPointeeType(); + + if (!self_clang_type) + return; + + if (log) + { + ASTDumper ast_dumper(self_type->GetFullCompilerType ()); + log->Printf(" FEVD[%u] Adding type for $__lldb_objc_class: %s", current_id, ast_dumper.GetCString()); + } + + TypeFromUser class_user_type (self_clang_type); + + AddOneType(context, class_user_type, current_id); + + TypeFromUser self_user_type(self_type->GetFullCompilerType ()); + + m_struct_vars->m_object_pointer_type = self_user_type; + return; + } + } + } + + return; + } + + // any other $__lldb names should be weeded out now + if (!::strncmp(name_unique_cstr, "$__lldb", sizeof("$__lldb") - 1)) + return; + + do + { + if (!target) + break; + + ClangASTContext *scratch_clang_ast_context = target->GetScratchClangASTContext(); + + if (!scratch_clang_ast_context) + break; + + ASTContext *scratch_ast_context = scratch_clang_ast_context->getASTContext(); + + if (!scratch_ast_context) + break; + + TypeDecl *ptype_type_decl = m_parser_vars->m_persistent_vars->GetPersistentType(name); + + if (!ptype_type_decl) + break; + + Decl *parser_ptype_decl = m_ast_importer_sp->CopyDecl(m_ast_context, scratch_ast_context, ptype_type_decl); + + if (!parser_ptype_decl) + break; + + TypeDecl *parser_ptype_type_decl = dyn_cast(parser_ptype_decl); + + if (!parser_ptype_type_decl) + break; + + if (log) + log->Printf(" CEDM::FEVD[%u] Found persistent type %s", current_id, name.GetCString()); + + context.AddNamedDecl(parser_ptype_type_decl); + } while (0); + + ExpressionVariableSP pvar_sp(m_parser_vars->m_persistent_vars->GetVariable(name)); + + if (pvar_sp) + { + AddOneVariable(context, pvar_sp, current_id); + return; + } + + const char *reg_name(&name.GetCString()[1]); + + if (m_parser_vars->m_exe_ctx.GetRegisterContext()) + { + const RegisterInfo *reg_info(m_parser_vars->m_exe_ctx.GetRegisterContext()->GetRegisterInfoByName(reg_name)); + + if (reg_info) + { + if (log) + log->Printf(" CEDM::FEVD[%u] Found register %s", current_id, reg_info->name); + + AddOneRegister(context, reg_info, current_id); + } + } + } + else + { + ValueObjectSP valobj; + VariableSP var; + + if (frame && !namespace_decl) + { + CompilerDeclContext compiler_decl_context = sym_ctx.block != nullptr ? sym_ctx.block->GetDeclContext() : CompilerDeclContext(); + + if (compiler_decl_context) + { + // Make sure that the variables are parsed so that we have the declarations + VariableListSP vars = frame->GetInScopeVariableList(true); + for (size_t i = 0; i < vars->GetSize(); i++) + vars->GetVariableAtIndex(i)->GetDecl(); + + // Search for declarations matching the name + std::vector found_decls = compiler_decl_context.FindDeclByName(name); + + bool variable_found = false; + for (CompilerDecl decl : found_decls) + { + var = decl.GetAsVariable(); + if (var) + { + variable_found = true; + valobj = ValueObjectVariable::Create(frame, var); + AddOneVariable(context, var, valobj, current_id); + context.m_found.variable = true; + } + } + if (variable_found) + return; + } + } + if (target) + { + var = FindGlobalVariable (*target, + module_sp, + name, + &namespace_decl, + NULL); + + if (var) + { + valobj = ValueObjectVariable::Create(target, var); + AddOneVariable(context, var, valobj, current_id); + context.m_found.variable = true; + return; + } + } + + std::vector decls_from_modules; + + if (target) + { + if (ClangModulesDeclVendor *decl_vendor = target->GetClangModulesDeclVendor()) + { + decl_vendor->FindDecls(name, false, UINT32_MAX, decls_from_modules); + } + } + + if (!context.m_found.variable) + { + const bool include_inlines = false; + const bool append = false; + + if (namespace_decl && module_sp) + { + const bool include_symbols = false; + + module_sp->FindFunctions(name, + &namespace_decl, + eFunctionNameTypeBase, + include_symbols, + include_inlines, + append, + sc_list); + } + else if (target && !namespace_decl) + { + const bool include_symbols = true; + + // TODO Fix FindFunctions so that it doesn't return + // instance methods for eFunctionNameTypeBase. + + target->GetImages().FindFunctions(name, + eFunctionNameTypeFull, + include_symbols, + include_inlines, + append, + sc_list); + } + + // If we found more than one function, see if we can use the + // frame's decl context to remove functions that are shadowed + // by other functions which match in type but are nearer in scope. + // + // AddOneFunction will not add a function whose type has already been + // added, so if there's another function in the list with a matching + // type, check to see if their decl context is a parent of the current + // frame's or was imported via a and using statement, and pick the + // best match according to lookup rules. + if (sc_list.GetSize() > 1) + { + // Collect some info about our frame's context. + StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr(); + SymbolContext frame_sym_ctx; + if (frame != nullptr) + frame_sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction|lldb::eSymbolContextBlock); + CompilerDeclContext frame_decl_context = frame_sym_ctx.block != nullptr ? frame_sym_ctx.block->GetDeclContext() : CompilerDeclContext(); + + // We can't do this without a compiler decl context for our frame. + if (frame_decl_context) + { + clang::DeclContext *frame_decl_ctx = (clang::DeclContext *)frame_decl_context.GetOpaqueDeclContext(); + ClangASTContext *ast = llvm::dyn_cast_or_null(frame_decl_context.GetTypeSystem()); + + // Structure to hold the info needed when comparing function + // declarations. + struct FuncDeclInfo + { + ConstString m_name; + CompilerType m_copied_type; + uint32_t m_decl_lvl; + SymbolContext m_sym_ctx; + }; + + // First, symplify things by looping through the symbol contexts + // to remove unwanted functions and separate out the functions we + // want to compare and prune into a separate list. + // Cache the info needed about the function declarations in a + // vector for efficiency. + SymbolContextList sc_sym_list; + uint32_t num_indices = sc_list.GetSize(); + std::vector fdi_cache; + fdi_cache.reserve(num_indices); + for (uint32_t index = 0; index < num_indices; ++index) + { + FuncDeclInfo fdi; + SymbolContext sym_ctx; + sc_list.GetContextAtIndex(index, sym_ctx); + + // We don't know enough about symbols to compare them, + // but we should keep them in the list. + Function *function = sym_ctx.function; + if (!function) + { + sc_sym_list.Append(sym_ctx); + continue; + } + // Filter out functions without declaration contexts, as well as + // class/instance methods, since they'll be skipped in the + // code that follows anyway. + CompilerDeclContext func_decl_context = function->GetDeclContext(); + if (!func_decl_context || func_decl_context.IsClassMethod(nullptr, nullptr, nullptr)) + continue; + // We can only prune functions for which we can copy the type. + CompilerType func_clang_type = function->GetType()->GetFullCompilerType(); + CompilerType copied_func_type = GuardedCopyType(func_clang_type); + if (!copied_func_type) + { + sc_sym_list.Append(sym_ctx); + continue; + } + + fdi.m_sym_ctx = sym_ctx; + fdi.m_name = function->GetName(); + fdi.m_copied_type = copied_func_type; + fdi.m_decl_lvl = LLDB_INVALID_DECL_LEVEL; + if (fdi.m_copied_type && func_decl_context) + { + // Call CountDeclLevels to get the number of parent scopes we + // have to look through before we find the function declaration. + // When comparing functions of the same type, the one with a + // lower count will be closer to us in the lookup scope and + // shadows the other. + clang::DeclContext *func_decl_ctx = (clang::DeclContext *)func_decl_context.GetOpaqueDeclContext(); + fdi.m_decl_lvl = ast->CountDeclLevels(frame_decl_ctx, + func_decl_ctx, + &fdi.m_name, + &fdi.m_copied_type); + } + fdi_cache.emplace_back(fdi); + } + + // Loop through the functions in our cache looking for matching types, + // then compare their scope levels to see which is closer. + std::multimap matches; + for (const FuncDeclInfo &fdi : fdi_cache) + { + const CompilerType t = fdi.m_copied_type; + auto q = matches.find(t); + if (q != matches.end()) + { + if (q->second->m_decl_lvl > fdi.m_decl_lvl) + // This function is closer; remove the old set. + matches.erase(t); + else if (q->second->m_decl_lvl < fdi.m_decl_lvl) + // The functions in our set are closer - skip this one. + continue; + } + matches.insert(std::make_pair(t, &fdi)); + } + + // Loop through our matches and add their symbol contexts to our list. + SymbolContextList sc_func_list; + for (const auto &q : matches) + sc_func_list.Append(q.second->m_sym_ctx); + + // Rejoin the lists with the functions in front. + sc_list = sc_func_list; + sc_list.Append(sc_sym_list); + } + } + + if (sc_list.GetSize()) + { + Symbol *extern_symbol = NULL; + Symbol *non_extern_symbol = NULL; + + for (uint32_t index = 0, num_indices = sc_list.GetSize(); + index < num_indices; + ++index) + { + SymbolContext sym_ctx; + sc_list.GetContextAtIndex(index, sym_ctx); + + if (sym_ctx.function) + { + CompilerDeclContext decl_ctx = sym_ctx.function->GetDeclContext(); + + if (!decl_ctx) + continue; + + // Filter out class/instance methods. + if (decl_ctx.IsClassMethod(nullptr, nullptr, nullptr)) + continue; + + AddOneFunction(context, sym_ctx.function, NULL, current_id); + context.m_found.function_with_type_info = true; + context.m_found.function = true; + } + else if (sym_ctx.symbol) + { + if (sym_ctx.symbol->GetType() == eSymbolTypeReExported && target) + { + sym_ctx.symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target); + if (sym_ctx.symbol == NULL) + continue; + } + + if (sym_ctx.symbol->IsExternal()) + extern_symbol = sym_ctx.symbol; + else + non_extern_symbol = sym_ctx.symbol; + } + } + + if (!context.m_found.function_with_type_info) + { + for (clang::NamedDecl *decl : decls_from_modules) + { + if (llvm::isa(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; + } + } + } + + if (!context.m_found.function_with_type_info) + { + if (extern_symbol) + { + AddOneFunction (context, NULL, extern_symbol, current_id); + context.m_found.function = true; + } + else if (non_extern_symbol) + { + AddOneFunction (context, NULL, non_extern_symbol, current_id); + context.m_found.function = true; + } + } + } + + if (!context.m_found.function_with_type_info) + { + // Try the modules next. + + do + { + if (ClangModulesDeclVendor *modules_decl_vendor = m_target->GetClangModulesDeclVendor()) + { + bool append = false; + uint32_t max_matches = 1; + std::vector decls; + + if (!modules_decl_vendor->FindDecls(name, + append, + max_matches, + decls)) + break; + + clang::NamedDecl *const decl_from_modules = decls[0]; + + if (llvm::isa(decl_from_modules)) + { + if (log) + { + log->Printf(" CAS::FEVD[%u] Matching function found for \"%s\" in the modules", + current_id, + name.GetCString()); + } + + clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules); + clang::FunctionDecl *copied_function_decl = copied_decl ? dyn_cast(copied_decl) : nullptr; + + if (!copied_function_decl) + { + if (log) + log->Printf(" CAS::FEVD[%u] - Couldn't export a function declaration from the modules", + current_id); + + break; + } + + if (copied_function_decl->getBody() && m_parser_vars->m_code_gen) + { + DeclGroupRef decl_group_ref(copied_function_decl); + m_parser_vars->m_code_gen->HandleTopLevelDecl(decl_group_ref); + } + + context.AddNamedDecl(copied_function_decl); + + context.m_found.function_with_type_info = true; + context.m_found.function = true; + } + else if (llvm::isa(decl_from_modules)) + { + if (log) + { + log->Printf(" CAS::FEVD[%u] Matching variable found for \"%s\" in the modules", + current_id, + name.GetCString()); + } + + clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(m_ast_context, &decl_from_modules->getASTContext(), decl_from_modules); + clang::VarDecl *copied_var_decl = copied_decl ? dyn_cast_or_null(copied_decl) : nullptr; + + if (!copied_var_decl) + { + if (log) + log->Printf(" CAS::FEVD[%u] - Couldn't export a variable declaration from the modules", + current_id); + + break; + } + + context.AddNamedDecl(copied_var_decl); + + context.m_found.variable = true; + } + } + } while (0); + } + + if (target && !context.m_found.variable && !namespace_decl) + { + // We couldn't find a non-symbol variable for this. Now we'll hunt for a generic + // data symbol, and -- if it is found -- treat it as a variable. + + const Symbol *data_symbol = FindGlobalDataSymbol(*target, name); + + if (data_symbol) + { + std::string warning("got name from symbols: "); + warning.append(name.AsCString()); + const unsigned diag_id = m_ast_context->getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Level::Warning, "%0"); + m_ast_context->getDiagnostics().Report(diag_id) << warning.c_str(); + AddOneGenericVariable(context, *data_symbol, current_id); + context.m_found.variable = true; + } + } + } + } +} + +//static opaque_compiler_type_t +//MaybePromoteToBlockPointerType +//( +// ASTContext *ast_context, +// opaque_compiler_type_t candidate_type +//) +//{ +// if (!candidate_type) +// return candidate_type; +// +// QualType candidate_qual_type = QualType::getFromOpaquePtr(candidate_type); +// +// const PointerType *candidate_pointer_type = dyn_cast(candidate_qual_type); +// +// if (!candidate_pointer_type) +// return candidate_type; +// +// QualType pointee_qual_type = candidate_pointer_type->getPointeeType(); +// +// const RecordType *pointee_record_type = dyn_cast(pointee_qual_type); +// +// if (!pointee_record_type) +// return candidate_type; +// +// RecordDecl *pointee_record_decl = pointee_record_type->getDecl(); +// +// if (!pointee_record_decl->isRecord()) +// return candidate_type; +// +// if (!pointee_record_decl->getName().startswith(llvm::StringRef("__block_literal_"))) +// return candidate_type; +// +// QualType generic_function_type = ast_context->getFunctionNoProtoType(ast_context->UnknownAnyTy); +// QualType block_pointer_type = ast_context->getBlockPointerType(generic_function_type); +// +// return block_pointer_type.getAsOpaquePtr(); +//} + +bool +ClangExpressionDeclMap::GetVariableValue (VariableSP &var, + lldb_private::Value &var_location, + TypeFromUser *user_type, + TypeFromParser *parser_type) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + Type *var_type = var->GetType(); + + if (!var_type) + { + if (log) + log->PutCString("Skipped a definition because it has no type"); + return false; + } + + CompilerType var_clang_type = var_type->GetFullCompilerType (); + + if (!var_clang_type) + { + if (log) + log->PutCString("Skipped a definition because it has no Clang type"); + return false; + } + + ClangASTContext *clang_ast = llvm::dyn_cast_or_null(var_type->GetForwardCompilerType().GetTypeSystem()); + + if (!clang_ast) + { + if (log) + log->PutCString("Skipped a definition because it has no Clang AST"); + return false; + } + + + ASTContext *ast = clang_ast->getASTContext(); + + if (!ast) + { + if (log) + log->PutCString("There is no AST context for the current execution context"); + return false; + } + //var_clang_type = MaybePromoteToBlockPointerType (ast, var_clang_type); + + DWARFExpression &var_location_expr = var->LocationExpression(); + + Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + Error err; + + if (var->GetLocationIsConstantValueData()) + { + DataExtractor const_value_extractor; + + if (var_location_expr.GetExpressionData(const_value_extractor)) + { + var_location = Value(const_value_extractor.GetDataStart(), const_value_extractor.GetByteSize()); + var_location.SetValueType(Value::eValueTypeHostAddress); + } + else + { + if (log) + log->Printf("Error evaluating constant variable: %s", err.AsCString()); + return false; + } + } + + CompilerType type_to_use = GuardedCopyType(var_clang_type); + + if (!type_to_use) + { + if (log) + log->Printf("Couldn't copy a variable's type into the parser's AST context"); + + return false; + } + + if (parser_type) + *parser_type = TypeFromParser(type_to_use); + + if (var_location.GetContextType() == Value::eContextTypeInvalid) + var_location.SetCompilerType(type_to_use); + + if (var_location.GetValueType() == Value::eValueTypeFileAddress) + { + SymbolContext var_sc; + var->CalculateSymbolContext(&var_sc); + + if (!var_sc.module_sp) + return false; + + Address so_addr(var_location.GetScalar().ULongLong(), var_sc.module_sp->GetSectionList()); + + lldb::addr_t load_addr = so_addr.GetLoadAddress(target); + + if (load_addr != LLDB_INVALID_ADDRESS) + { + var_location.GetScalar() = load_addr; + var_location.SetValueType(Value::eValueTypeLoadAddress); + } + } + + if (user_type) + *user_type = TypeFromUser(var_clang_type); + + return true; +} + +void +ClangExpressionDeclMap::AddOneVariable (NameSearchContext &context, VariableSP var, ValueObjectSP valobj, unsigned int current_id) +{ + assert (m_parser_vars.get()); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + TypeFromUser ut; + TypeFromParser pt; + Value var_location; + + if (!GetVariableValue (var, var_location, &ut, &pt)) + return; + + clang::QualType parser_opaque_type = QualType::getFromOpaquePtr(pt.GetOpaqueQualType()); + + if (parser_opaque_type.isNull()) + return; + + if (const clang::Type *parser_type = parser_opaque_type.getTypePtr()) + { + if (const TagType *tag_type = dyn_cast(parser_type)) + CompleteType(tag_type->getDecl()); + if (const ObjCObjectPointerType *objc_object_ptr_type = dyn_cast(parser_type)) + CompleteType(objc_object_ptr_type->getInterfaceDecl()); + } + + + bool is_reference = pt.IsReferenceType(); + + NamedDecl *var_decl = NULL; + if (is_reference) + var_decl = context.AddVarDecl(pt); + else + var_decl = context.AddVarDecl(pt.GetLValueReferenceType()); + + std::string decl_name(context.m_decl_name.getAsString()); + ConstString entity_name(decl_name.c_str()); + ClangExpressionVariable *entity(new ClangExpressionVariable(valobj)); + m_found_entities.AddNewlyConstructedVariable(entity); + + assert (entity); + entity->EnableParserVars(GetParserID()); + ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); + parser_vars->m_parser_type = pt; + parser_vars->m_named_decl = var_decl; + parser_vars->m_llvm_value = NULL; + parser_vars->m_lldb_value = var_location; + parser_vars->m_lldb_var = var; + + if (is_reference) + entity->m_flags |= ClangExpressionVariable::EVTypeIsReference; + + if (log) + { + ASTDumper orig_dumper(ut.GetOpaqueQualType()); + ASTDumper ast_dumper(var_decl); + log->Printf(" CEDM::FEVD[%u] Found variable %s, returned %s (original %s)", current_id, decl_name.c_str(), ast_dumper.GetCString(), orig_dumper.GetCString()); + } +} + +void +ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, + ExpressionVariableSP &pvar_sp, + unsigned int current_id) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + TypeFromUser user_type (llvm::cast(pvar_sp.get())->GetTypeFromUser()); + + TypeFromParser parser_type (GuardedCopyType(user_type)); + + if (!parser_type.GetOpaqueQualType()) + { + if (log) + log->Printf(" CEDM::FEVD[%u] Couldn't import type for pvar %s", current_id, pvar_sp->GetName().GetCString()); + return; + } + + NamedDecl *var_decl = context.AddVarDecl(parser_type.GetLValueReferenceType()); + + llvm::cast(pvar_sp.get())->EnableParserVars(GetParserID()); + ClangExpressionVariable::ParserVars *parser_vars = llvm::cast(pvar_sp.get())->GetParserVars(GetParserID()); + parser_vars->m_parser_type = parser_type; + parser_vars->m_named_decl = var_decl; + parser_vars->m_llvm_value = NULL; + parser_vars->m_lldb_value.Clear(); + + if (log) + { + ASTDumper ast_dumper(var_decl); + log->Printf(" CEDM::FEVD[%u] Added pvar %s, returned %s", current_id, pvar_sp->GetName().GetCString(), ast_dumper.GetCString()); + } +} + +void +ClangExpressionDeclMap::AddOneGenericVariable(NameSearchContext &context, + const Symbol &symbol, + unsigned int current_id) +{ + assert(m_parser_vars.get()); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + + if (target == NULL) + return; + + ASTContext *scratch_ast_context = target->GetScratchClangASTContext()->getASTContext(); + + TypeFromUser user_type (ClangASTContext::GetBasicType(scratch_ast_context, eBasicTypeVoid).GetPointerType().GetLValueReferenceType()); + TypeFromParser parser_type (ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid).GetPointerType().GetLValueReferenceType()); + NamedDecl *var_decl = context.AddVarDecl(parser_type); + + std::string decl_name(context.m_decl_name.getAsString()); + ConstString entity_name(decl_name.c_str()); + ClangExpressionVariable *entity(new ClangExpressionVariable(m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (), + entity_name, + user_type, + m_parser_vars->m_target_info.byte_order, + m_parser_vars->m_target_info.address_byte_size)); + m_found_entities.AddNewlyConstructedVariable(entity); + + entity->EnableParserVars(GetParserID()); + ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); + + const Address symbol_address = symbol.GetAddress(); + lldb::addr_t symbol_load_addr = symbol_address.GetLoadAddress(target); + + //parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, user_type.GetOpaqueQualType()); + parser_vars->m_lldb_value.SetCompilerType(user_type); + parser_vars->m_lldb_value.GetScalar() = symbol_load_addr; + parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress); + + parser_vars->m_parser_type = parser_type; + parser_vars->m_named_decl = var_decl; + parser_vars->m_llvm_value = NULL; + parser_vars->m_lldb_sym = &symbol; + + if (log) + { + ASTDumper ast_dumper(var_decl); + + log->Printf(" CEDM::FEVD[%u] Found variable %s, returned %s", current_id, decl_name.c_str(), ast_dumper.GetCString()); + } +} + +bool +ClangExpressionDeclMap::ResolveUnknownTypes() +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + + ClangASTContext *scratch_ast_context = target->GetScratchClangASTContext(); + + for (size_t index = 0, num_entities = m_found_entities.GetSize(); + index < num_entities; + ++index) + { + ExpressionVariableSP entity = m_found_entities.GetVariableAtIndex(index); + + ClangExpressionVariable::ParserVars *parser_vars = llvm::cast(entity.get())->GetParserVars(GetParserID()); + + if (entity->m_flags & ClangExpressionVariable::EVUnknownType) + { + const NamedDecl *named_decl = parser_vars->m_named_decl; + const VarDecl *var_decl = dyn_cast(named_decl); + + if (!var_decl) + { + if (log) + log->Printf("Entity of unknown type does not have a VarDecl"); + return false; + } + + if (log) + { + ASTDumper ast_dumper(const_cast(var_decl)); + log->Printf("Variable of unknown type now has Decl %s", ast_dumper.GetCString()); + } + + QualType var_type = var_decl->getType(); + TypeFromParser parser_type(var_type.getAsOpaquePtr(), ClangASTContext::GetASTContext(&var_decl->getASTContext())); + + lldb::opaque_compiler_type_t copied_type = m_ast_importer_sp->CopyType(scratch_ast_context->getASTContext(), &var_decl->getASTContext(), var_type.getAsOpaquePtr()); + + if (!copied_type) + { + if (log) + log->Printf("ClangExpressionDeclMap::ResolveUnknownType - Couldn't import the type for a variable"); + + return (bool) lldb::ExpressionVariableSP(); + } + + TypeFromUser user_type(copied_type, scratch_ast_context); + +// parser_vars->m_lldb_value.SetContext(Value::eContextTypeClangType, user_type.GetOpaqueQualType()); + parser_vars->m_lldb_value.SetCompilerType(user_type); + parser_vars->m_parser_type = parser_type; + + entity->SetCompilerType(user_type); + + entity->m_flags &= ~(ClangExpressionVariable::EVUnknownType); + } + } + + return true; +} + +void +ClangExpressionDeclMap::AddOneRegister (NameSearchContext &context, + const RegisterInfo *reg_info, + unsigned int current_id) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + CompilerType clang_type = ClangASTContext::GetBuiltinTypeForEncodingAndBitSize (m_ast_context, + reg_info->encoding, + reg_info->byte_size * 8); + + if (!clang_type) + { + if (log) + log->Printf(" Tried to add a type for %s, but couldn't get one", context.m_decl_name.getAsString().c_str()); + return; + } + + TypeFromParser parser_clang_type (clang_type); + + NamedDecl *var_decl = context.AddVarDecl(parser_clang_type); + + ClangExpressionVariable *entity(new ClangExpressionVariable(m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), + m_parser_vars->m_target_info.byte_order, + m_parser_vars->m_target_info.address_byte_size)); + m_found_entities.AddNewlyConstructedVariable(entity); + + std::string decl_name(context.m_decl_name.getAsString()); + entity->SetName (ConstString (decl_name.c_str())); + entity->SetRegisterInfo (reg_info); + entity->EnableParserVars(GetParserID()); + ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); + parser_vars->m_parser_type = parser_clang_type; + parser_vars->m_named_decl = var_decl; + parser_vars->m_llvm_value = NULL; + parser_vars->m_lldb_value.Clear(); + entity->m_flags |= ClangExpressionVariable::EVBareRegister; + + if (log) + { + ASTDumper ast_dumper(var_decl); + log->Printf(" CEDM::FEVD[%d] Added register %s, returned %s", current_id, context.m_decl_name.getAsString().c_str(), ast_dumper.GetCString()); + } +} + +void +ClangExpressionDeclMap::AddOneFunction (NameSearchContext &context, + Function* function, + Symbol* symbol, + unsigned int current_id) +{ + assert (m_parser_vars.get()); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + NamedDecl *function_decl = NULL; + Address fun_address; + CompilerType function_clang_type; + + bool is_indirect_function = false; + + if (function) + { + Type *function_type = function->GetType(); + + if (!function_type) + { + if (log) + log->PutCString(" Skipped a function because it has no type"); + return; + } + + function_clang_type = function_type->GetFullCompilerType (); + + if (!function_clang_type) + { + if (log) + log->PutCString(" Skipped a function because it has no Clang type"); + return; + } + + fun_address = function->GetAddressRange().GetBaseAddress(); + + CompilerType copied_function_type = GuardedCopyType(function_clang_type); + if (copied_function_type) + { + function_decl = context.AddFunDecl(copied_function_type); + + if (!function_decl) + { + if (log) + { + log->Printf (" Failed to create a function decl for '%s' {0x%8.8" PRIx64 "}", + function_type->GetName().GetCString(), + function_type->GetID()); + } + + return; + } + } + else + { + // We failed to copy the type we found + if (log) + { + log->Printf (" Failed to import the function type '%s' {0x%8.8" PRIx64 "} into the expression parser AST contenxt", + function_type->GetName().GetCString(), + function_type->GetID()); + } + + return; + } + } + else if (symbol) + { + fun_address = symbol->GetAddress(); + function_decl = context.AddGenericFunDecl(); + is_indirect_function = symbol->IsIndirect(); + } + else + { + if (log) + log->PutCString(" AddOneFunction called with no function and no symbol"); + return; + } + + Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr(); + + lldb::addr_t load_addr = fun_address.GetCallableLoadAddress(target, is_indirect_function); + + ClangExpressionVariable *entity(new ClangExpressionVariable (m_parser_vars->m_exe_ctx.GetBestExecutionContextScope (), + m_parser_vars->m_target_info.byte_order, + m_parser_vars->m_target_info.address_byte_size)); + m_found_entities.AddNewlyConstructedVariable(entity); + + std::string decl_name(context.m_decl_name.getAsString()); + entity->SetName(ConstString(decl_name.c_str())); + entity->SetCompilerType (function_clang_type); + entity->EnableParserVars(GetParserID()); + + ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); + + if (load_addr != LLDB_INVALID_ADDRESS) + { + parser_vars->m_lldb_value.SetValueType(Value::eValueTypeLoadAddress); + parser_vars->m_lldb_value.GetScalar() = load_addr; + } + else + { + // We have to try finding a file address. + + lldb::addr_t file_addr = fun_address.GetFileAddress(); + + parser_vars->m_lldb_value.SetValueType(Value::eValueTypeFileAddress); + parser_vars->m_lldb_value.GetScalar() = file_addr; + } + + + parser_vars->m_named_decl = function_decl; + parser_vars->m_llvm_value = NULL; + + if (log) + { + ASTDumper ast_dumper(function_decl); + + StreamString ss; + + fun_address.Dump(&ss, m_parser_vars->m_exe_ctx.GetBestExecutionContextScope(), Address::DumpStyleResolvedDescription); + + log->Printf(" CEDM::FEVD[%u] Found %s function %s (description %s), returned %s", + current_id, + (function ? "specific" : "generic"), + decl_name.c_str(), + ss.GetData(), + ast_dumper.GetCString()); + } +} + +void +ClangExpressionDeclMap::AddThisType(NameSearchContext &context, + TypeFromUser &ut, + unsigned int current_id) +{ + CompilerType copied_clang_type = GuardedCopyType(ut); + + if (!copied_clang_type) + { + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf("ClangExpressionDeclMap::AddThisType - Couldn't import the type"); + + return; + } + + if (copied_clang_type.IsAggregateType() && copied_clang_type.GetCompleteType ()) + { + CompilerType void_clang_type = ClangASTContext::GetBasicType(m_ast_context, eBasicTypeVoid); + CompilerType void_ptr_clang_type = void_clang_type.GetPointerType(); + + CompilerType method_type = ClangASTContext::CreateFunctionType (m_ast_context, + void_clang_type, + &void_ptr_clang_type, + 1, + false, + copied_clang_type.GetTypeQualifiers()); + + const bool is_virtual = false; + const bool is_static = false; + const bool is_inline = false; + const bool is_explicit = false; + const bool is_attr_used = true; + const bool is_artificial = false; + + ClangASTContext::GetASTContext(m_ast_context)-> + AddMethodToCXXRecordType (copied_clang_type.GetOpaqueQualType(), + "$__lldb_expr", + method_type, + lldb::eAccessPublic, + is_virtual, + is_static, + is_inline, + is_explicit, + is_attr_used, + is_artificial); + } + + if (!copied_clang_type.IsValid()) + return; + + TypeSourceInfo *type_source_info = m_ast_context->getTrivialTypeSourceInfo(QualType::getFromOpaquePtr(copied_clang_type.GetOpaqueQualType())); + + if (!type_source_info) + return; + + // Construct a typedef type because if "*this" is a templated type we can't just return ClassTemplateSpecializationDecls in response to name queries. + // Using a typedef makes this much more robust. + + TypedefDecl *typedef_decl = TypedefDecl::Create(*m_ast_context, + m_ast_context->getTranslationUnitDecl(), + SourceLocation(), + SourceLocation(), + context.m_decl_name.getAsIdentifierInfo(), + type_source_info); + + + if (!typedef_decl) + return; + + context.AddNamedDecl(typedef_decl); + + return; +} + +void +ClangExpressionDeclMap::AddOneType(NameSearchContext &context, + TypeFromUser &ut, + unsigned int current_id) +{ + CompilerType copied_clang_type = GuardedCopyType(ut); + + if (!copied_clang_type) + { + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf("ClangExpressionDeclMap::AddOneType - Couldn't import the type"); + + return; + } + + context.AddTypeDecl(copied_clang_type); +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h new file mode 100644 index 0000000000000..b3f890c7acc71 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -0,0 +1,714 @@ +//===-- ClangExpressionDeclMap.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangExpressionDeclMap_h_ +#define liblldb_ClangExpressionDeclMap_h_ + +// C Includes +#include +#include + +// C++ Includes +#include + +#include "ClangExpressionVariable.h" +#include "ClangASTSource.h" + +// Other libraries and framework includes +// Project includes +#include "llvm/ADT/DenseMap.h" +#include "clang/AST/Decl.h" +#include "lldb/lldb-public.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/Value.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Symbol/TaggedASTType.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/ExecutionContext.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ClangExpressionDeclMap ClangExpressionDeclMap.h "lldb/Expression/ClangExpressionDeclMap.h" +/// @brief Manages named entities that are defined in LLDB's debug information. +/// +/// The Clang parser uses the ClangASTSource as an interface to request named +/// entities from outside an expression. The ClangASTSource reports back, listing +/// all possible objects corresponding to a particular name. But it in turn +/// relies on ClangExpressionDeclMap, which performs several important functions. +/// +/// First, it records what variables and functions were looked up and what Decls +/// were returned for them. +/// +/// Second, it constructs a struct on behalf of IRForTarget, recording which +/// variables should be placed where and relaying this information back so that +/// IRForTarget can generate context-independent code. +/// +/// Third, it "materializes" this struct on behalf of the expression command, +/// finding the current values of each variable and placing them into the +/// struct so that it can be passed to the JITted version of the IR. +/// +/// Fourth and finally, it "dematerializes" the struct after the JITted code has +/// has executed, placing the new values back where it found the old ones. +//---------------------------------------------------------------------- +class ClangExpressionDeclMap : + public ClangASTSource +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] keep_result_in_memory + /// If true, inhibits the normal deallocation of the memory for + /// the result persistent variable, and instead marks the variable + /// as persisting. + /// + /// @param[in] delegate + /// If non-NULL, use this delegate to report result values. This + /// allows the client ClangUserExpression to report a result. + /// + /// @param[in] exe_ctx + /// The execution context to use when parsing. + //------------------------------------------------------------------ + ClangExpressionDeclMap (bool keep_result_in_memory, + Materializer::PersistentVariableDelegate *result_delegate, + ExecutionContext &exe_ctx); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~ClangExpressionDeclMap() override; + + //------------------------------------------------------------------ + /// Enable the state needed for parsing and IR transformation. + /// + /// @param[in] exe_ctx + /// The execution context to use when finding types for variables. + /// Also used to find a "scratch" AST context to store result types. + /// + /// @param[in] materializer + /// If non-NULL, the materializer to populate with information about + /// the variables to use + /// + /// @return + /// True if parsing is possible; false if it is unsafe to continue. + //------------------------------------------------------------------ + bool + WillParse (ExecutionContext &exe_ctx, + Materializer *materializer); + + void + InstallCodeGenerator (clang::ASTConsumer *code_gen); + + //------------------------------------------------------------------ + /// [Used by ClangExpressionParser] For each variable that had an unknown + /// type at the beginning of parsing, determine its final type now. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + ResolveUnknownTypes(); + + //------------------------------------------------------------------ + /// Disable the state needed for parsing and IR transformation. + //------------------------------------------------------------------ + void + DidParse (); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Add a variable to the list of persistent + /// variables for the process. + /// + /// @param[in] decl + /// The Clang declaration for the persistent variable, used for + /// lookup during parsing. + /// + /// @param[in] name + /// The name of the persistent variable, usually $something. + /// + /// @param[in] type + /// The type of the variable, in the Clang parser's context. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + AddPersistentVariable (const clang::NamedDecl *decl, + const ConstString &name, + TypeFromParser type, + bool is_result, + bool is_lvalue); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Add a variable to the struct that needs to + /// be materialized each time the expression runs. + /// + /// @param[in] decl + /// The Clang declaration for the variable. + /// + /// @param[in] name + /// The name of the variable. + /// + /// @param[in] value + /// The LLVM IR value for this variable. + /// + /// @param[in] size + /// The size of the variable in bytes. + /// + /// @param[in] alignment + /// The required alignment of the variable in bytes. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + AddValueToStruct (const clang::NamedDecl *decl, + const ConstString &name, + llvm::Value *value, + size_t size, + lldb::offset_t alignment); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Finalize the struct, laying out the position + /// of each object in it. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + DoStructLayout (); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get general information about the laid-out + /// struct after DoStructLayout() has been called. + /// + /// @param[out] num_elements + /// The number of elements in the struct. + /// + /// @param[out] size + /// The size of the struct, in bytes. + /// + /// @param[out] alignment + /// The alignment of the struct, in bytes. + /// + /// @return + /// True if the information could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetStructInfo (uint32_t &num_elements, + size_t &size, + lldb::offset_t &alignment); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get specific information about one field + /// of the laid-out struct after DoStructLayout() has been called. + /// + /// @param[out] decl + /// The parsed Decl for the field, as generated by ClangASTSource + /// on ClangExpressionDeclMap's behalf. In the case of the result + /// value, this will have the name $__lldb_result even if the + /// result value ends up having the name $1. This is an + /// implementation detail of IRForTarget. + /// + /// @param[out] value + /// The IR value for the field (usually a GlobalVariable). In + /// the case of the result value, this will have the correct + /// name ($1, for instance). This is an implementation detail + /// of IRForTarget. + /// + /// @param[out] offset + /// The offset of the field from the beginning of the struct. + /// As long as the struct is aligned according to its required + /// alignment, this offset will align the field correctly. + /// + /// @param[out] name + /// The name of the field as used in materialization. + /// + /// @param[in] index + /// The index of the field about which information is requested. + /// + /// @return + /// True if the information could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetStructElement (const clang::NamedDecl *&decl, + llvm::Value *&value, + lldb::offset_t &offset, + ConstString &name, + uint32_t index); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get information about a function given its + /// Decl. + /// + /// @param[in] decl + /// The parsed Decl for the Function, as generated by ClangASTSource + /// on ClangExpressionDeclMap's behalf. + /// + /// @param[out] ptr + /// The absolute address of the function in the target. + /// + /// @return + /// True if the information could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetFunctionInfo (const clang::NamedDecl *decl, + uint64_t &ptr); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get the address of a function given nothing + /// but its name. Some functions are needed but didn't get Decls made + /// during parsing -- specifically, sel_registerName is never called + /// in the generated IR but we need to call it nonetheless. + /// + /// @param[in] name + /// The name of the function. + /// + /// @param[out] ptr + /// The absolute address of the function in the target. + /// + /// @return + /// True if the address could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetFunctionAddress (const ConstString &name, + uint64_t &ptr); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get the address of a symbol given nothing + /// but its name. + /// + /// @param[in] target + /// The target to find the symbol in. If not provided, + /// then the current parsing context's Target. + /// + /// @param[in] process + /// The process to use. For Objective-C symbols, the process's + /// Objective-C language runtime may be queried if the process + /// is non-NULL. + /// + /// @param[in] name + /// The name of the symbol. + /// + /// @param[in] module + /// The module to limit the search to. This can be NULL + /// + /// @return + /// Valid load address for the symbol + //------------------------------------------------------------------ + lldb::addr_t + GetSymbolAddress (Target &target, + Process *process, + const ConstString &name, + lldb::SymbolType symbol_type, + Module *module = NULL); + + lldb::addr_t + GetSymbolAddress (const ConstString &name, + lldb::SymbolType symbol_type); + + //------------------------------------------------------------------ + /// [Used by IRInterpreter] Get basic target information. + /// + /// @param[out] byte_order + /// The byte order of the target. + /// + /// @param[out] address_byte_size + /// The size of a pointer in bytes. + /// + /// @return + /// True if the information could be determined; false + /// otherwise. + //------------------------------------------------------------------ + struct TargetInfo + { + lldb::ByteOrder byte_order; + size_t address_byte_size; + + TargetInfo() : + byte_order(lldb::eByteOrderInvalid), + address_byte_size(0) + { + } + + bool IsValid() + { + return (byte_order != lldb::eByteOrderInvalid && + address_byte_size != 0); + } + }; + TargetInfo GetTargetInfo(); + + //------------------------------------------------------------------ + /// [Used by ClangASTSource] Find all entities matching a given name, + /// using a NameSearchContext to make Decls for them. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + void + FindExternalVisibleDecls(NameSearchContext &context) override; + + //------------------------------------------------------------------ + /// Find all entities matching a given name in a given module/namespace, + /// using a NameSearchContext to make Decls for them. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// @param[in] module + /// If non-NULL, the module to query. + /// + /// @param[in] namespace_decl + /// If valid and module is non-NULL, the parent namespace. + /// + /// @param[in] name + /// The name as a plain C string. The NameSearchContext contains + /// a DeclarationName for the name so at first the name may seem + /// redundant, but ClangExpressionDeclMap operates in RTTI land so + /// it can't access DeclarationName. + /// + /// @param[in] current_id + /// The ID for the current FindExternalVisibleDecls invocation, + /// for logging purposes. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + void + FindExternalVisibleDecls (NameSearchContext &context, + lldb::ModuleSP module, + CompilerDeclContext &namespace_decl, + unsigned int current_id); +private: + ExpressionVariableList m_found_entities; ///< All entities that were looked up for the parser. + ExpressionVariableList m_struct_members; ///< All entities that need to be placed in the struct. + bool m_keep_result_in_memory; ///< True if result persistent variables generated by this expression should stay in memory. + Materializer::PersistentVariableDelegate *m_result_delegate; ///< If non-NULL, used to report expression results to ClangUserExpression. + + //---------------------------------------------------------------------- + /// The following values should not live beyond parsing + //---------------------------------------------------------------------- + class ParserVars + { + public: + ParserVars(ClangExpressionDeclMap &decl_map) : + m_decl_map(decl_map) + { + } + + Target * + GetTarget() + { + if (m_exe_ctx.GetTargetPtr()) + return m_exe_ctx.GetTargetPtr(); + else if (m_sym_ctx.target_sp) + m_sym_ctx.target_sp.get(); + return NULL; + } + + ExecutionContext m_exe_ctx; ///< The execution context to use when parsing. + SymbolContext m_sym_ctx; ///< The symbol context to use in finding variables and types. + ClangPersistentVariables *m_persistent_vars = nullptr; ///< The persistent variables for the process. + bool m_enable_lookups = false; ///< Set to true during parsing if we have found the first "$__lldb" name. + TargetInfo m_target_info; ///< Basic information about the target. + Materializer *m_materializer = nullptr; ///< If non-NULL, the materializer to use when reporting used variables. + clang::ASTConsumer *m_code_gen = nullptr; ///< If non-NULL, a code generator that receives new top-level functions. + private: + ClangExpressionDeclMap &m_decl_map; + DISALLOW_COPY_AND_ASSIGN (ParserVars); + }; + + std::unique_ptr m_parser_vars; + + //---------------------------------------------------------------------- + /// Activate parser-specific variables + //---------------------------------------------------------------------- + void + EnableParserVars() + { + if (!m_parser_vars.get()) + m_parser_vars.reset(new ParserVars(*this)); + } + + //---------------------------------------------------------------------- + /// Deallocate parser-specific variables + //---------------------------------------------------------------------- + void + DisableParserVars() + { + m_parser_vars.reset(); + } + + //---------------------------------------------------------------------- + /// The following values contain layout information for the materialized + /// struct, but are not specific to a single materialization + //---------------------------------------------------------------------- + struct StructVars { + StructVars() : + m_struct_alignment(0), + m_struct_size(0), + m_struct_laid_out(false), + m_result_name(), + m_object_pointer_type(NULL, NULL) + { + } + + lldb::offset_t m_struct_alignment; ///< The alignment of the struct in bytes. + size_t m_struct_size; ///< The size of the struct in bytes. + bool m_struct_laid_out; ///< True if the struct has been laid out and the layout is valid (that is, no new fields have been added since). + ConstString m_result_name; ///< The name of the result variable ($1, for example) + TypeFromUser m_object_pointer_type; ///< The type of the "this" variable, if one exists + }; + + std::unique_ptr m_struct_vars; + + //---------------------------------------------------------------------- + /// Activate struct variables + //---------------------------------------------------------------------- + void + EnableStructVars() + { + if (!m_struct_vars.get()) + m_struct_vars.reset(new struct StructVars); + } + + //---------------------------------------------------------------------- + /// Deallocate struct variables + //---------------------------------------------------------------------- + void + DisableStructVars() + { + m_struct_vars.reset(); + } + + //---------------------------------------------------------------------- + /// Get this parser's ID for use in extracting parser- and JIT-specific + /// data from persistent variables. + //---------------------------------------------------------------------- + uint64_t + GetParserID() + { + return (uint64_t)this; + } + + //------------------------------------------------------------------ + /// Given a target, find a data symbol that has the given name. + /// + /// @param[in] target + /// The target to use as the basis for the search. + /// + /// @param[in] name + /// The name as a plain C string. + /// + /// @param[in] module + /// The module to limit the search to. This can be NULL + /// + /// @return + /// The LLDB Symbol found, or NULL if none was found. + //------------------------------------------------------------------ + const Symbol * + FindGlobalDataSymbol (Target &target, + const ConstString &name, + Module *module = NULL); + + //------------------------------------------------------------------ + /// Given a target, find a variable that matches the given name and + /// type. + /// + /// @param[in] target + /// The target to use as a basis for finding the variable. + /// + /// @param[in] module + /// If non-NULL, the module to search. + /// + /// @param[in] name + /// The name as a plain C string. + /// + /// @param[in] namespace_decl + /// If non-NULL and module is non-NULL, the parent namespace. + /// + /// @param[in] type + /// The required type for the variable. This function may be called + /// during parsing, in which case we don't know its type; hence the + /// default. + /// + /// @return + /// The LLDB Variable found, or NULL if none was found. + //------------------------------------------------------------------ + lldb::VariableSP + FindGlobalVariable (Target &target, + lldb::ModuleSP &module, + const ConstString &name, + CompilerDeclContext *namespace_decl, + TypeFromUser *type = NULL); + + //------------------------------------------------------------------ + /// Get the value of a variable in a given execution context and return + /// the associated Types if needed. + /// + /// @param[in] var + /// The variable to evaluate. + /// + /// @param[out] var_location + /// The variable location value to fill in + /// + /// @param[out] found_type + /// The type of the found value, as it was found in the user process. + /// This is only useful when the variable is being inspected on behalf + /// of the parser, hence the default. + /// + /// @param[out] parser_type + /// The type of the found value, as it was copied into the parser's + /// AST context. This is only useful when the variable is being + /// inspected on behalf of the parser, hence the default. + /// + /// @param[in] decl + /// The Decl to be looked up. + /// + /// @return + /// Return true if the value was successfully filled in. + //------------------------------------------------------------------ + bool + GetVariableValue (lldb::VariableSP &var, + lldb_private::Value &var_location, + TypeFromUser *found_type = NULL, + TypeFromParser *parser_type = NULL); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given LLDB + /// Variable, and put it in the Tuple list. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] var + /// The LLDB Variable that needs a Decl. + /// + /// @param[in] valobj + /// The LLDB ValueObject for that variable. + //------------------------------------------------------------------ + void + AddOneVariable (NameSearchContext &context, + lldb::VariableSP var, + lldb::ValueObjectSP valobj, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// persistent variable, and put it in the list of found entities. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] pvar + /// The persistent variable that needs a Decl. + /// + /// @param[in] current_id + /// The ID of the current invocation of FindExternalVisibleDecls + /// for logging purposes. + //------------------------------------------------------------------ + void + AddOneVariable (NameSearchContext &context, + lldb::ExpressionVariableSP &pvar_sp, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given LLDB + /// symbol (treated as a variable), and put it in the list of found + /// entities. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] var + /// The LLDB Variable that needs a Decl. + //------------------------------------------------------------------ + void + AddOneGenericVariable (NameSearchContext &context, + const Symbol &symbol, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// function. (Functions are not placed in the Tuple list.) Can + /// handle both fully typed functions and generic functions. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] fun + /// The Function that needs to be created. If non-NULL, this is + /// a fully-typed function. + /// + /// @param[in] sym + /// The Symbol that corresponds to a function that needs to be + /// created with generic type (unitptr_t foo(...)). + //------------------------------------------------------------------ + void + AddOneFunction (NameSearchContext &context, + Function *fun, + Symbol *sym, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// register. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] reg_info + /// The information corresponding to that register. + //------------------------------------------------------------------ + void + AddOneRegister (NameSearchContext &context, + const RegisterInfo *reg_info, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// type. (Types are not placed in the Tuple list.) + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] type + /// The type that needs to be created. + //------------------------------------------------------------------ + void + AddOneType (NameSearchContext &context, + TypeFromUser &type, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Generate a Decl for "*this" and add a member function declaration + /// to it for the expression, then report it. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] type + /// The type for *this. + //------------------------------------------------------------------ + void + AddThisType(NameSearchContext &context, + TypeFromUser &type, + unsigned int current_id); +}; + +} // namespace lldb_private + +#endif // liblldb_ClangExpressionDeclMap_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h new file mode 100644 index 0000000000000..bb620def691f9 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h @@ -0,0 +1,79 @@ +//===-- ClangExpression.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangExpression_h_ +#define liblldb_ClangExpression_h_ + +// C Includes +// C++ Includes +#include +#include +#include + +// Other libraries and framework includes +// Project includes + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Expression/ExpressionTypeSystemHelper.h" + +namespace lldb_private { + +class RecordingMemoryManager; + +//---------------------------------------------------------------------- +// ClangExpressionHelper +//---------------------------------------------------------------------- +class ClangExpressionHelper : public ExpressionTypeSystemHelper +{ +public: + static bool classof(const ExpressionTypeSystemHelper *ts) + { + return ts->getKind() == eKindClangHelper; + } + + ClangExpressionHelper () : + ExpressionTypeSystemHelper(ExpressionTypeSystemHelper::LLVMCastKind::eKindClangHelper) + { + } + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + virtual ~ClangExpressionHelper () + { + } + + //------------------------------------------------------------------ + /// Return the object that the parser should use when resolving external + /// values. May be NULL if everything should be self-contained. + //------------------------------------------------------------------ + virtual ClangExpressionDeclMap * + DeclMap () = 0; + + //------------------------------------------------------------------ + /// Return the object that the parser should allow to access ASTs. + /// May be NULL if the ASTs do not need to be transformed. + /// + /// @param[in] passthrough + /// The ASTConsumer that the returned transformer should send + /// the ASTs to after transformation. + //------------------------------------------------------------------ + virtual clang::ASTConsumer * + ASTTransformer (clang::ASTConsumer *passthrough) = 0; + + +protected: + +}; + +} // namespace lldb_private + +#endif // liblldb_ClangExpression_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp new file mode 100644 index 0000000000000..72c33fec8105c --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -0,0 +1,657 @@ +//===-- ClangExpressionParser.cpp -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "clang/AST/ASTContext.h" +#include "clang/AST/ExternalASTSource.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/Version.h" +#include "clang/CodeGen/CodeGenAction.h" +#include "clang/CodeGen/ModuleBuilder.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Frontend/TextDiagnosticBuffer.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Parse/ParseAST.h" +#include "clang/Rewrite/Frontend/FrontendActions.h" +#include "clang/Sema/SemaConsumer.h" +#include "clang/StaticAnalyzer/Frontend/FrontendActions.h" + +#include "llvm/ADT/StringRef.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/TargetSelect.h" + +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/Signals.h" + +// Project includes +#include "ClangExpressionParser.h" + +#include "ClangASTSource.h" +#include "ClangExpressionHelper.h" +#include "ClangExpressionDeclMap.h" +#include "ClangModulesDeclVendor.h" +#include "ClangPersistentVariables.h" +#include "IRForTarget.h" + +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Disassembler.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Expression/IRDynamicChecks.h" +#include "lldb/Expression/IRInterpreter.h" +#include "lldb/Host/File.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" + +using namespace clang; +using namespace llvm; +using namespace lldb_private; + +//===----------------------------------------------------------------------===// +// Utility Methods for Clang +//===----------------------------------------------------------------------===// + +std::string GetBuiltinIncludePath(const char *Argv0) { + SmallString<128> P(llvm::sys::fs::getMainExecutable( + Argv0, (void *)(intptr_t) GetBuiltinIncludePath)); + + if (!P.empty()) { + llvm::sys::path::remove_filename(P); // Remove /clang from foo/bin/clang + llvm::sys::path::remove_filename(P); // Remove /bin from foo/bin + + // Get foo/lib/clang//include + llvm::sys::path::append(P, "lib", "clang", CLANG_VERSION_STRING, + "include"); + } + + return P.str(); +} + +class ClangExpressionParser::LLDBPreprocessorCallbacks : public PPCallbacks +{ + ClangModulesDeclVendor &m_decl_vendor; + ClangPersistentVariables &m_persistent_vars; + StreamString m_error_stream; + bool m_has_errors = false; + +public: + LLDBPreprocessorCallbacks(ClangModulesDeclVendor &decl_vendor, + ClangPersistentVariables &persistent_vars) : + m_decl_vendor(decl_vendor), + m_persistent_vars(persistent_vars) + { + } + + void + moduleImport(SourceLocation import_location, + clang::ModuleIdPath path, + const clang::Module * /*null*/) override + { + std::vector string_path; + + for (const std::pair &component : path) + { + string_path.push_back(ConstString(component.first->getName())); + } + + StreamString error_stream; + + ClangModulesDeclVendor::ModuleVector exported_modules; + + if (!m_decl_vendor.AddModule(string_path, &exported_modules, m_error_stream)) + { + m_has_errors = true; + } + + for (ClangModulesDeclVendor::ModuleID module : exported_modules) + { + m_persistent_vars.AddHandLoadedClangModule(module); + } + } + + bool hasErrors() + { + return m_has_errors; + } + + const std::string &getErrorString() + { + return m_error_stream.GetString(); + } +}; + +//===----------------------------------------------------------------------===// +// Implementation of ClangExpressionParser +//===----------------------------------------------------------------------===// + +ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, + Expression &expr, + bool generate_debug_info) : + ExpressionParser (exe_scope, expr, generate_debug_info), + m_compiler (), + m_code_generator (), + m_pp_callbacks(nullptr) +{ + // 1. Create a new compiler instance. + m_compiler.reset(new CompilerInstance()); + + // 2. Install the target. + + lldb::TargetSP target_sp; + if (exe_scope) + target_sp = exe_scope->CalculateTarget(); + + // TODO: figure out what to really do when we don't have a valid target. + // Sometimes this will be ok to just use the host target triple (when we + // evaluate say "2+3", but other expressions like breakpoint conditions + // and other things that _are_ target specific really shouldn't just be + // using the host triple. This needs to be fixed in a better way. + if (target_sp && target_sp->GetArchitecture().IsValid()) + { + std::string triple = target_sp->GetArchitecture().GetTriple().str(); + m_compiler->getTargetOpts().Triple = triple; + } + else + { + m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple(); + } + + if (target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86 || + target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86_64) + { + m_compiler->getTargetOpts().Features.push_back("+sse"); + m_compiler->getTargetOpts().Features.push_back("+sse2"); + } + + // Any arm32 iOS environment, but not on arm64 + if (m_compiler->getTargetOpts().Triple.find("arm64") == std::string::npos && + m_compiler->getTargetOpts().Triple.find("arm") != std::string::npos && + m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos) + { + m_compiler->getTargetOpts().ABI = "apcs-gnu"; + } + + m_compiler->createDiagnostics(); + + // Create the target instance. + m_compiler->setTarget(TargetInfo::CreateTargetInfo( + m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts)); + + assert (m_compiler->hasTarget()); + + // 3. Set options. + + lldb::LanguageType language = expr.Language(); + + switch (language) + { + case lldb::eLanguageTypeC: + case lldb::eLanguageTypeC89: + case lldb::eLanguageTypeC99: + case lldb::eLanguageTypeC11: + // FIXME: the following language option is a temporary workaround, + // to "ask for C, get C++." + // For now, the expression parser must use C++ anytime the + // language is a C family language, because the expression parser + // uses features of C++ to capture values. + m_compiler->getLangOpts().CPlusPlus = true; + break; + case lldb::eLanguageTypeObjC: + m_compiler->getLangOpts().ObjC1 = true; + m_compiler->getLangOpts().ObjC2 = true; + // FIXME: the following language option is a temporary workaround, + // to "ask for ObjC, get ObjC++" (see comment above). + m_compiler->getLangOpts().CPlusPlus = true; + break; + case lldb::eLanguageTypeC_plus_plus: + case lldb::eLanguageTypeC_plus_plus_11: + case lldb::eLanguageTypeC_plus_plus_14: + m_compiler->getLangOpts().CPlusPlus11 = true; + m_compiler->getHeaderSearchOpts().UseLibcxx = true; + // fall thru ... + case lldb::eLanguageTypeC_plus_plus_03: + m_compiler->getLangOpts().CPlusPlus = true; + // FIXME: the following language option is a temporary workaround, + // to "ask for C++, get ObjC++". Apple hopes to remove this requirement + // on non-Apple platforms, but for now it is needed. + m_compiler->getLangOpts().ObjC1 = true; + break; + case lldb::eLanguageTypeObjC_plus_plus: + case lldb::eLanguageTypeUnknown: + default: + m_compiler->getLangOpts().ObjC1 = true; + m_compiler->getLangOpts().ObjC2 = true; + m_compiler->getLangOpts().CPlusPlus = true; + m_compiler->getLangOpts().CPlusPlus11 = true; + m_compiler->getHeaderSearchOpts().UseLibcxx = true; + break; + } + + m_compiler->getLangOpts().Bool = true; + m_compiler->getLangOpts().WChar = true; + m_compiler->getLangOpts().Blocks = true; + m_compiler->getLangOpts().DebuggerSupport = true; // Features specifically for debugger clients + if (expr.DesiredResultType() == Expression::eResultTypeId) + m_compiler->getLangOpts().DebuggerCastResultToId = true; + + m_compiler->getLangOpts().CharIsSigned = + ArchSpec(m_compiler->getTargetOpts().Triple.c_str()).CharIsSignedByDefault(); + + // Spell checking is a nice feature, but it ends up completing a + // lot of types that we didn't strictly speaking need to complete. + // As a result, we spend a long time parsing and importing debug + // information. + m_compiler->getLangOpts().SpellChecking = false; + + lldb::ProcessSP process_sp; + if (exe_scope) + process_sp = exe_scope->CalculateProcess(); + + if (process_sp && m_compiler->getLangOpts().ObjC1) + { + if (process_sp->GetObjCLanguageRuntime()) + { + if (process_sp->GetObjCLanguageRuntime()->GetRuntimeVersion() == ObjCLanguageRuntime::ObjCRuntimeVersions::eAppleObjC_V2) + m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7)); + else + m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::FragileMacOSX, VersionTuple(10, 7)); + + if (process_sp->GetObjCLanguageRuntime()->HasNewLiteralsAndIndexing()) + m_compiler->getLangOpts().DebuggerObjCLiteral = true; + } + } + + m_compiler->getLangOpts().ThreadsafeStatics = false; + m_compiler->getLangOpts().AccessControl = false; // Debuggers get universal access + m_compiler->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name + + // Set CodeGen options + m_compiler->getCodeGenOpts().EmitDeclMetadata = true; + m_compiler->getCodeGenOpts().InstrumentFunctions = false; + m_compiler->getCodeGenOpts().DisableFPElim = true; + m_compiler->getCodeGenOpts().OmitLeafFramePointer = false; + if (generate_debug_info) + m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::FullDebugInfo); + else + m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::NoDebugInfo); + + // Disable some warnings. + m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError, + "unused-value", clang::diag::Severity::Ignored, SourceLocation()); + m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError, + "odr", clang::diag::Severity::Ignored, SourceLocation()); + + // Inform the target of the language options + // + // FIXME: We shouldn't need to do this, the target should be immutable once + // created. This complexity should be lifted elsewhere. + m_compiler->getTarget().adjust(m_compiler->getLangOpts()); + + // 4. Set up the diagnostic buffer for reporting errors + + m_compiler->getDiagnostics().setClient(new clang::TextDiagnosticBuffer); + + // 5. Set up the source management objects inside the compiler + + clang::FileSystemOptions file_system_options; + m_file_manager.reset(new clang::FileManager(file_system_options)); + + if (!m_compiler->hasSourceManager()) + m_compiler->createSourceManager(*m_file_manager.get()); + + m_compiler->createFileManager(); + m_compiler->createPreprocessor(TU_Complete); + + if (ClangModulesDeclVendor *decl_vendor = target_sp->GetClangModulesDeclVendor()) + { + ClangPersistentVariables *clang_persistent_vars = llvm::cast(target_sp->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)); + std::unique_ptr pp_callbacks(new LLDBPreprocessorCallbacks(*decl_vendor, *clang_persistent_vars)); + m_pp_callbacks = static_cast(pp_callbacks.get()); + m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks)); + } + + // 6. Most of this we get from the CompilerInstance, but we + // also want to give the context an ExternalASTSource. + m_selector_table.reset(new SelectorTable()); + m_builtin_context.reset(new Builtin::Context()); + + std::unique_ptr ast_context(new ASTContext(m_compiler->getLangOpts(), + m_compiler->getSourceManager(), + m_compiler->getPreprocessor().getIdentifierTable(), + *m_selector_table.get(), + *m_builtin_context.get())); + + ast_context->InitBuiltinTypes(m_compiler->getTarget()); + + ClangExpressionHelper *type_system_helper = dyn_cast(m_expr.GetTypeSystemHelper()); + ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap(); + + if (decl_map) + { + llvm::IntrusiveRefCntPtr ast_source(decl_map->CreateProxy()); + decl_map->InstallASTContext(ast_context.get()); + ast_context->setExternalSource(ast_source); + } + + m_ast_context.reset(new ClangASTContext(m_compiler->getTargetOpts().Triple.c_str())); + m_ast_context->setASTContext(ast_context.get()); + m_compiler->setASTContext(ast_context.release()); + + std::string module_name("$__lldb_module"); + + m_llvm_context.reset(new LLVMContext()); + m_code_generator.reset(CreateLLVMCodeGen(m_compiler->getDiagnostics(), + module_name, + m_compiler->getHeaderSearchOpts(), + m_compiler->getPreprocessorOpts(), + m_compiler->getCodeGenOpts(), + *m_llvm_context)); +} + +ClangExpressionParser::~ClangExpressionParser() +{ +} + +unsigned +ClangExpressionParser::Parse (Stream &stream) +{ + TextDiagnosticBuffer *diag_buf = static_cast(m_compiler->getDiagnostics().getClient()); + + diag_buf->FlushDiagnostics (m_compiler->getDiagnostics()); + + const char *expr_text = m_expr.Text(); + + clang::SourceManager &SourceMgr = m_compiler->getSourceManager(); + bool created_main_file = false; + if (m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo) + { + std::string temp_source_path; + + int temp_fd = -1; + llvm::SmallString result_path; + FileSpec tmpdir_file_spec; + if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) + { + tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr"); + temp_source_path = tmpdir_file_spec.GetPath(); + llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path); + } + else + { + llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path); + } + + if (temp_fd != -1) + { + lldb_private::File file (temp_fd, true); + const size_t expr_text_len = strlen(expr_text); + size_t bytes_written = expr_text_len; + if (file.Write(expr_text, bytes_written).Success()) + { + if (bytes_written == expr_text_len) + { + file.Close(); + SourceMgr.setMainFileID(SourceMgr.createFileID( + m_file_manager->getFile(result_path), + SourceLocation(), SrcMgr::C_User)); + created_main_file = true; + } + } + } + } + + if (!created_main_file) + { + std::unique_ptr memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__); + SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(memory_buffer))); + } + + diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor()); + + ClangExpressionHelper *type_system_helper = dyn_cast(m_expr.GetTypeSystemHelper()); + + ASTConsumer *ast_transformer = type_system_helper->ASTTransformer(m_code_generator.get()); + + if (ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap()) + decl_map->InstallCodeGenerator(m_code_generator.get()); + + if (ast_transformer) + { + ast_transformer->Initialize(m_compiler->getASTContext()); + ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext()); + } + else + { + m_code_generator->Initialize(m_compiler->getASTContext()); + ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext()); + } + + diag_buf->EndSourceFile(); + + TextDiagnosticBuffer::const_iterator diag_iterator; + + int num_errors = 0; + + if (m_pp_callbacks && m_pp_callbacks->hasErrors()) + { + num_errors++; + + stream.PutCString(m_pp_callbacks->getErrorString().c_str()); + } + + for (diag_iterator = diag_buf->warn_begin(); + diag_iterator != diag_buf->warn_end(); + ++diag_iterator) + stream.Printf("warning: %s\n", (*diag_iterator).second.c_str()); + + for (diag_iterator = diag_buf->err_begin(); + diag_iterator != diag_buf->err_end(); + ++diag_iterator) + { + num_errors++; + stream.Printf("error: %s\n", (*diag_iterator).second.c_str()); + } + + for (diag_iterator = diag_buf->note_begin(); + diag_iterator != diag_buf->note_end(); + ++diag_iterator) + stream.Printf("note: %s\n", (*diag_iterator).second.c_str()); + + if (!num_errors) + { + if (type_system_helper->DeclMap() && !type_system_helper->DeclMap()->ResolveUnknownTypes()) + { + stream.Printf("error: Couldn't infer the type of a variable\n"); + num_errors++; + } + } + + return num_errors; +} + +static bool FindFunctionInModule (ConstString &mangled_name, + llvm::Module *module, + const char *orig_name) +{ + for (llvm::Module::iterator fi = module->getFunctionList().begin(), fe = module->getFunctionList().end(); + fi != fe; + ++fi) + { + if (fi->getName().str().find(orig_name) != std::string::npos) + { + mangled_name.SetCString(fi->getName().str().c_str()); + return true; + } + } + + return false; +} + +Error +ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, + lldb::addr_t &func_end, + lldb::IRExecutionUnitSP &execution_unit_sp, + ExecutionContext &exe_ctx, + bool &can_interpret, + ExecutionPolicy execution_policy) +{ + func_addr = LLDB_INVALID_ADDRESS; + func_end = LLDB_INVALID_ADDRESS; + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + Error err; + + std::unique_ptr llvm_module_ap (m_code_generator->ReleaseModule()); + + if (!llvm_module_ap.get()) + { + err.SetErrorToGenericError(); + err.SetErrorString("IR doesn't contain a module"); + return err; + } + + // Find the actual name of the function (it's often mangled somehow) + + ConstString function_name; + + if (!FindFunctionInModule(function_name, llvm_module_ap.get(), m_expr.FunctionName())) + { + err.SetErrorToGenericError(); + err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName()); + return err; + } + else + { + if (log) + log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName()); + } + + execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here + llvm_module_ap, // handed off here + function_name, + exe_ctx.GetTargetSP(), + m_compiler->getTargetOpts().Features)); + + ClangExpressionHelper *type_system_helper = dyn_cast(m_expr.GetTypeSystemHelper()); + ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap(); // result can be NULL + + if (decl_map) + { + Stream *error_stream = NULL; + Target *target = exe_ctx.GetTargetPtr(); + if (target) + error_stream = target->GetDebugger().GetErrorFile().get(); + + IRForTarget ir_for_target(decl_map, + m_expr.NeedsVariableResolution(), + *execution_unit_sp, + error_stream, + function_name.AsCString()); + + bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule()); + + Error interpret_error; + Process *process = exe_ctx.GetProcessPtr(); + + bool interpret_function_calls = !process ? false : process->CanInterpretFunctionCalls(); + can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error, interpret_function_calls); + + + if (!ir_can_run) + { + err.SetErrorString("The expression could not be prepared to run in the target"); + return err; + } + + if (!can_interpret && execution_policy == eExecutionPolicyNever) + { + err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString()); + return err; + } + + if (!process && execution_policy == eExecutionPolicyAlways) + { + err.SetErrorString("Expression needed to run in the target, but the target can't be run"); + return err; + } + + if (execution_policy == eExecutionPolicyAlways || !can_interpret) + { + if (m_expr.NeedsValidation() && process) + { + if (!process->GetDynamicCheckers()) + { + DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions(); + + StreamString install_errors; + + if (!dynamic_checkers->Install(install_errors, exe_ctx)) + { + if (install_errors.GetString().empty()) + err.SetErrorString ("couldn't install checkers, unknown error"); + else + err.SetErrorString (install_errors.GetString().c_str()); + + return err; + } + + process->SetDynamicCheckers(dynamic_checkers); + + if (log) + log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers =="); + } + + IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString()); + + if (!ir_dynamic_checks.runOnModule(*execution_unit_sp->GetModule())) + { + err.SetErrorToGenericError(); + err.SetErrorString("Couldn't add dynamic checks to the expression"); + return err; + } + } + + execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); + } + } + else + { + execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); + } + + return err; +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h new file mode 100644 index 0000000000000..3c055380b839f --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h @@ -0,0 +1,136 @@ +//===-- ClangExpressionParser.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangExpressionParser_h_ +#define liblldb_ClangExpressionParser_h_ + +#include "lldb/lldb-public.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/Error.h" +#include "lldb/Expression/ExpressionParser.h" + +#include +#include + +namespace lldb_private +{ + +class IRExecutionUnit; + +//---------------------------------------------------------------------- +/// @class ClangExpressionParser ClangExpressionParser.h "lldb/Expression/ClangExpressionParser.h" +/// @brief Encapsulates an instance of Clang that can parse expressions. +/// +/// ClangExpressionParser is responsible for preparing an instance of +/// ClangExpression for execution. ClangExpressionParser uses ClangExpression +/// as a glorified parameter list, performing the required parsing and +/// conversion to formats (DWARF bytecode, or JIT compiled machine code) +/// that can be executed. +//---------------------------------------------------------------------- +class ClangExpressionParser : public ExpressionParser +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] exe_scope, + /// If non-NULL, an execution context scope that can help to + /// correctly create an expression with a valid process for + /// optional tuning Objective-C runtime support. Can be NULL. + /// + /// @param[in] expr + /// The expression to be parsed. + //------------------------------------------------------------------ + ClangExpressionParser (ExecutionContextScope *exe_scope, + Expression &expr, + bool generate_debug_info); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~ClangExpressionParser () override; + + //------------------------------------------------------------------ + /// Parse a single expression and convert it to IR using Clang. Don't + /// wrap the expression in anything at all. + /// + /// @param[in] stream + /// The stream to print errors to. + /// + /// @return + /// The number of errors encountered during parsing. 0 means + /// success. + //------------------------------------------------------------------ + unsigned + Parse (Stream &stream) override; + + //------------------------------------------------------------------ + /// Ready an already-parsed expression for execution, possibly + /// evaluating it statically. + /// + /// @param[out] func_addr + /// The address to which the function has been written. + /// + /// @param[out] func_end + /// The end of the function's allocated memory region. (func_addr + /// and func_end do not delimit an allocated region; the allocated + /// region may begin before func_addr.) + /// + /// @param[in] execution_unit_sp + /// After parsing, ownership of the execution unit for + /// for the expression is handed to this shared pointer. + /// + /// @param[in] exe_ctx + /// The execution context to write the function into. + /// + /// @param[out] evaluated_statically + /// Set to true if the expression could be interpreted statically; + /// untouched otherwise. + /// + /// @param[out] const_result + /// If the result of the expression is constant, and the + /// expression has no side effects, this is set to the result of the + /// expression. + /// + /// @param[in] execution_policy + /// Determines whether the expression must be JIT-compiled, must be + /// evaluated statically, or whether this decision may be made + /// opportunistically. + /// + /// @return + /// An error code indicating the success or failure of the operation. + /// Test with Success(). + //------------------------------------------------------------------ + Error + PrepareForExecution (lldb::addr_t &func_addr, + lldb::addr_t &func_end, + lldb::IRExecutionUnitSP &execution_unit_sp, + ExecutionContext &exe_ctx, + bool &can_interpret, + lldb_private::ExecutionPolicy execution_policy) override; + +private: + std::unique_ptr 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 + std::unique_ptr m_compiler; ///< The Clang compiler used to parse expressions into IR + std::unique_ptr m_builtin_context; ///< Context for Clang built-ins + std::unique_ptr m_selector_table; ///< Selector table for Objective-C methods + std::unique_ptr m_code_generator; ///< The Clang object that generates IR + + class LLDBPreprocessorCallbacks; + LLDBPreprocessorCallbacks *m_pp_callbacks; ///< Called when the preprocessor encounters module imports + std::unique_ptr m_ast_context; +}; + +} + +#endif // liblldb_ClangExpressionParser_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp new file mode 100644 index 0000000000000..908546b3ecdbd --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.cpp @@ -0,0 +1,76 @@ +//===-- ClangExpressionVariable.cpp -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangExpressionVariable.h" + +#include "clang/AST/ASTContext.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" + +using namespace lldb_private; +using namespace clang; + +const char *g_clang_expression_variable_kind_name = "ClangExpressionVariable"; + +ClangExpressionVariable::ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size) : + ExpressionVariable(LLVMCastKind::eKindClang), + m_parser_vars(), + m_jit_vars () +{ + m_flags = EVNone; + m_frozen_sp = ValueObjectConstResult::Create (exe_scope, byte_order, addr_byte_size); +} + +ClangExpressionVariable::ClangExpressionVariable (ExecutionContextScope *exe_scope, + Value &value, + const ConstString &name, + uint16_t flags) : + ExpressionVariable(LLVMCastKind::eKindClang), + m_parser_vars(), + m_jit_vars () +{ + m_flags = flags; + m_frozen_sp = ValueObjectConstResult::Create (exe_scope, value, name); +} + +ClangExpressionVariable::ClangExpressionVariable (const lldb::ValueObjectSP &valobj_sp) : + ExpressionVariable(LLVMCastKind::eKindClang), + m_parser_vars(), + m_jit_vars () +{ + m_flags = EVNone; + m_frozen_sp = valobj_sp; +} + +ClangExpressionVariable::ClangExpressionVariable(ExecutionContextScope *exe_scope, + const ConstString &name, + const TypeFromUser& user_type, + lldb::ByteOrder byte_order, + uint32_t addr_byte_size) : + ExpressionVariable(LLVMCastKind::eKindClang), + m_parser_vars(), + m_jit_vars() +{ + m_flags = EVNone; + m_frozen_sp = ValueObjectConstResult::Create (exe_scope, byte_order, addr_byte_size); + SetName (name); + SetCompilerType (user_type); +} + +TypeFromUser +ClangExpressionVariable::GetTypeFromUser() +{ + TypeFromUser tfu (m_frozen_sp->GetCompilerType()); + return tfu; +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h new file mode 100644 index 0000000000000..a4596148f6c74 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h @@ -0,0 +1,265 @@ +//===-- ClangExpressionVariable.h -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangExpressionVariable_h_ +#define liblldb_ClangExpressionVariable_h_ + +// C Includes +#include +#include +#include + +// C++ Includes +#include +#include +#include + +// Other libraries and framework includes +#include "llvm/Support/Casting.h" + +// Project includes +#include "lldb/lldb-public.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Value.h" +#include "lldb/Expression/ExpressionVariable.h" +#include "lldb/Symbol/TaggedASTType.h" + +namespace llvm { + class Value; +} + +namespace lldb_private { + +class ValueObjectConstResult; + +//---------------------------------------------------------------------- +/// @class ClangExpressionVariable ClangExpressionVariable.h "lldb/Expression/ClangExpressionVariable.h" +/// @brief Encapsulates one variable for the expression parser. +/// +/// The expression parser uses variables in three different contexts: +/// +/// First, it stores persistent variables along with the process for use +/// in expressions. These persistent variables contain their own data +/// and are typed. +/// +/// Second, in an interpreted expression, it stores the local variables +/// for the expression along with the expression. These variables +/// contain their own data and are typed. +/// +/// Third, in a JIT-compiled expression, it stores the variables that +/// the expression needs to have materialized and dematerialized at each +/// execution. These do not contain their own data but are named and +/// typed. +/// +/// This class supports all of these use cases using simple type +/// polymorphism, and provides necessary support methods. Its interface +/// is RTTI-neutral. +//---------------------------------------------------------------------- +class ClangExpressionVariable : public ExpressionVariable +{ +public: + ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size); + + ClangExpressionVariable (ExecutionContextScope *exe_scope, + Value &value, + const ConstString &name, + uint16_t flags = EVNone); + + ClangExpressionVariable(const lldb::ValueObjectSP &valobj_sp); + + ClangExpressionVariable(ExecutionContextScope *exe_scope, + const ConstString &name, + const TypeFromUser& user_type, + lldb::ByteOrder byte_order, + uint32_t addr_byte_size); + + //---------------------------------------------------------------------- + /// Utility functions for dealing with ExpressionVariableLists in Clang-specific ways + //---------------------------------------------------------------------- + + //---------------------------------------------------------------------- + /// Finds a variable by NamedDecl in the list. + /// + /// @param[in] name + /// The name of the requested variable. + /// + /// @return + /// The variable requested, or NULL if that variable is not in the list. + //---------------------------------------------------------------------- + static ClangExpressionVariable * + FindVariableInList (ExpressionVariableList &list, const clang::NamedDecl *decl, uint64_t parser_id) + { + lldb::ExpressionVariableSP var_sp; + for (size_t index = 0, size = list.GetSize(); index < size; ++index) + { + var_sp = list.GetVariableAtIndex(index); + + if (ClangExpressionVariable *clang_var = llvm::dyn_cast(var_sp.get())) + { + ClangExpressionVariable::ParserVars *parser_vars = clang_var->GetParserVars(parser_id); + + if (parser_vars && parser_vars->m_named_decl == decl) + return clang_var; + } + } + return nullptr; + } + + //---------------------------------------------------------------------- + /// If the variable contains its own data, make a Value point at it. + /// If \a exe_ctx in not NULL, the value will be resolved in with + /// that execution context. + /// + /// @param[in] value + /// The value to point at the data. + /// + /// @param[in] exe_ctx + /// The execution context to use to resolve \a value. + /// + /// @return + /// True on success; false otherwise (in particular, if this variable + /// does not contain its own data). + //---------------------------------------------------------------------- + bool + PointValueAtData(Value &value, ExecutionContext *exe_ctx); + + //---------------------------------------------------------------------- + /// The following values should not live beyond parsing + //---------------------------------------------------------------------- + class ParserVars + { + public: + + ParserVars() : + m_parser_type(), + m_named_decl (NULL), + m_llvm_value (NULL), + m_lldb_value (), + m_lldb_var (), + m_lldb_sym (NULL) + { + } + + TypeFromParser m_parser_type; ///< The type of the variable according to the parser + const clang::NamedDecl *m_named_decl; ///< The Decl corresponding to this variable + llvm::Value *m_llvm_value; ///< The IR value corresponding to this variable; usually a GlobalValue + lldb_private::Value m_lldb_value; ///< The value found in LLDB for this variable + lldb::VariableSP m_lldb_var; ///< The original variable for this variable + const lldb_private::Symbol *m_lldb_sym; ///< The original symbol for this variable, if it was a symbol + }; + +private: + typedef std::map ParserVarMap; + ParserVarMap m_parser_vars; + +public: + //---------------------------------------------------------------------- + /// Make this variable usable by the parser by allocating space for + /// parser-specific variables + //---------------------------------------------------------------------- + void + EnableParserVars(uint64_t parser_id) + { + m_parser_vars.insert(std::make_pair(parser_id, ParserVars())); + } + + //---------------------------------------------------------------------- + /// Deallocate parser-specific variables + //---------------------------------------------------------------------- + void + DisableParserVars(uint64_t parser_id) + { + m_parser_vars.erase(parser_id); + } + + //---------------------------------------------------------------------- + /// Access parser-specific variables + //---------------------------------------------------------------------- + ParserVars * + GetParserVars(uint64_t parser_id) + { + ParserVarMap::iterator i = m_parser_vars.find(parser_id); + + if (i == m_parser_vars.end()) + return NULL; + else + return &i->second; + } + + //---------------------------------------------------------------------- + /// The following values are valid if the variable is used by JIT code + //---------------------------------------------------------------------- + struct JITVars { + JITVars () : + m_alignment (0), + m_size (0), + m_offset (0) + { + } + + lldb::offset_t m_alignment; ///< The required alignment of the variable, in bytes + size_t m_size; ///< The space required for the variable, in bytes + lldb::offset_t m_offset; ///< The offset of the variable in the struct, in bytes + }; + +private: + typedef std::map JITVarMap; + JITVarMap m_jit_vars; + +public: + //---------------------------------------------------------------------- + /// Make this variable usable for materializing for the JIT by allocating + /// space for JIT-specific variables + //---------------------------------------------------------------------- + void + EnableJITVars(uint64_t parser_id) + { + m_jit_vars.insert(std::make_pair(parser_id, JITVars())); + } + + //---------------------------------------------------------------------- + /// Deallocate JIT-specific variables + //---------------------------------------------------------------------- + void + DisableJITVars(uint64_t parser_id) + { + m_jit_vars.erase(parser_id); + } + + JITVars *GetJITVars(uint64_t parser_id) + { + JITVarMap::iterator i = m_jit_vars.find(parser_id); + + if (i == m_jit_vars.end()) + return NULL; + else + return &i->second; + } + + TypeFromUser + GetTypeFromUser (); + + //------------------------------------------------------------------ + // llvm casting support + //------------------------------------------------------------------ + static bool classof(const ExpressionVariable *ev) + { + return ev->getKind() == ExpressionVariable::eKindClang; + } + + //---------------------------------------------------------------------- + /// Members + //---------------------------------------------------------------------- + DISALLOW_COPY_AND_ASSIGN (ClangExpressionVariable); +}; + +} // namespace lldb_private + +#endif // liblldb_ClangExpressionVariable_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp new file mode 100644 index 0000000000000..0d0d7475a00e2 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp @@ -0,0 +1,221 @@ +//===-- ClangFunctionCallerCaller.cpp ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangFunctionCaller.h" + +#include "ASTStructExtractor.h" +#include "ClangExpressionParser.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "clang/AST/ASTContext.h" +#include "clang/AST/RecordLayout.h" +#include "clang/CodeGen/CodeGenAction.h" +#include "clang/CodeGen/ModuleBuilder.h" +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/IR/Module.h" + +// Project includes +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/State.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectList.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanCallFunction.h" + +using namespace lldb_private; + +//---------------------------------------------------------------------- +// ClangFunctionCaller constructor +//---------------------------------------------------------------------- +ClangFunctionCaller::ClangFunctionCaller +( + ExecutionContextScope &exe_scope, + const CompilerType &return_type, + const Address& functionAddress, + const ValueList &arg_value_list, + const char *name +) : + FunctionCaller(exe_scope, return_type, functionAddress, arg_value_list, name), + m_type_system_helper (*this) +{ + m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess()); + // Can't make a ClangFunctionCaller without a process. + assert (m_jit_process_wp.lock()); +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +ClangFunctionCaller::~ClangFunctionCaller() +{ +} + +unsigned +ClangFunctionCaller::CompileFunction (Stream &errors) +{ + if (m_compiled) + return 0; + + // FIXME: How does clang tell us there's no return value? We need to handle that case. + unsigned num_errors = 0; + + std::string return_type_str (m_function_return_type.GetTypeName().AsCString("")); + + // Cons up the function we're going to wrap our call in, then compile it... + // We declare the function "extern "C"" because the compiler might be in C++ + // mode which would mangle the name and then we couldn't find it again... + m_wrapper_function_text.clear(); + m_wrapper_function_text.append ("extern \"C\" void "); + m_wrapper_function_text.append (m_wrapper_function_name); + m_wrapper_function_text.append (" (void *input)\n{\n struct "); + m_wrapper_function_text.append (m_wrapper_struct_name); + m_wrapper_function_text.append (" \n {\n"); + m_wrapper_function_text.append (" "); + m_wrapper_function_text.append (return_type_str); + m_wrapper_function_text.append (" (*fn_ptr) ("); + + // Get the number of arguments. If we have a function type and it is prototyped, + // trust that, otherwise use the values we were given. + + // FIXME: This will need to be extended to handle Variadic functions. We'll need + // to pull the defined arguments out of the function, then add the types from the + // arguments list for the variable arguments. + + uint32_t num_args = UINT32_MAX; + bool trust_function = false; + // GetArgumentCount returns -1 for an unprototyped function. + CompilerType function_clang_type; + if (m_function_ptr) + { + function_clang_type = m_function_ptr->GetCompilerType(); + if (function_clang_type) + { + int num_func_args = function_clang_type.GetFunctionArgumentCount(); + if (num_func_args >= 0) + { + trust_function = true; + num_args = num_func_args; + } + } + } + + if (num_args == UINT32_MAX) + num_args = m_arg_values.GetSize(); + + std::string args_buffer; // This one stores the definition of all the args in "struct caller". + std::string args_list_buffer; // This one stores the argument list called from the structure. + for (size_t i = 0; i < num_args; i++) + { + std::string type_name; + + if (trust_function) + { + type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i).GetTypeName().AsCString(""); + } + else + { + CompilerType clang_qual_type = m_arg_values.GetValueAtIndex(i)->GetCompilerType (); + if (clang_qual_type) + { + type_name = clang_qual_type.GetTypeName().AsCString(""); + } + else + { + errors.Printf("Could not determine type of input value %" PRIu64 ".", (uint64_t)i); + return 1; + } + } + + m_wrapper_function_text.append (type_name); + if (i < num_args - 1) + m_wrapper_function_text.append (", "); + + char arg_buf[32]; + args_buffer.append (" "); + args_buffer.append (type_name); + snprintf(arg_buf, 31, "arg_%" PRIu64, (uint64_t)i); + args_buffer.push_back (' '); + args_buffer.append (arg_buf); + args_buffer.append (";\n"); + + args_list_buffer.append ("__lldb_fn_data->"); + args_list_buffer.append (arg_buf); + if (i < num_args - 1) + args_list_buffer.append (", "); + + } + m_wrapper_function_text.append (");\n"); // Close off the function calling prototype. + + m_wrapper_function_text.append (args_buffer); + + m_wrapper_function_text.append (" "); + m_wrapper_function_text.append (return_type_str); + m_wrapper_function_text.append (" return_value;"); + m_wrapper_function_text.append ("\n };\n struct "); + m_wrapper_function_text.append (m_wrapper_struct_name); + m_wrapper_function_text.append ("* __lldb_fn_data = (struct "); + m_wrapper_function_text.append (m_wrapper_struct_name); + m_wrapper_function_text.append (" *) input;\n"); + + m_wrapper_function_text.append (" __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr ("); + m_wrapper_function_text.append (args_list_buffer); + m_wrapper_function_text.append (");\n}\n"); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + if (log) + log->Printf ("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str()); + + // Okay, now compile this expression + + lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); + if (jit_process_sp) + { + const bool generate_debug_info = true; + m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this, generate_debug_info)); + + num_errors = m_parser->Parse (errors); + } + else + { + errors.Printf("no process - unable to inject function"); + num_errors = 1; + } + + m_compiled = (num_errors == 0); + + if (!m_compiled) + return num_errors; + + return num_errors; +} + +clang::ASTConsumer * +ClangFunctionCaller::ClangFunctionCallerHelper::ASTTransformer (clang::ASTConsumer *passthrough) +{ + m_struct_extractor.reset(new ASTStructExtractor(passthrough, m_owner.GetWrapperStructName(), m_owner)); + + return m_struct_extractor.get(); +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h new file mode 100644 index 0000000000000..3e30f818a9328 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h @@ -0,0 +1,173 @@ +//===-- ClangFunctionCaller.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangFunctionCaller_h_ +#define liblldb_ClangFunctionCaller_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "ClangExpressionHelper.h" + +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObjectList.h" +#include "lldb/Expression/FunctionCaller.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Target/Process.h" + +namespace lldb_private +{ + +class ASTStructExtractor; +class ClangExpressionParser; + +//---------------------------------------------------------------------- +/// @class ClangFunctionCaller ClangFunctionCaller.h "lldb/Expression/ClangFunctionCaller.h" +/// @brief Encapsulates a function that can be called. +/// +/// A given ClangFunctionCaller object can handle a single function signature. +/// Once constructed, it can set up any number of concurrent calls to +/// functions with that signature. +/// +/// It performs the call by synthesizing a structure that contains the pointer +/// to the function and the arguments that should be passed to that function, +/// and producing a special-purpose JIT-compiled function that accepts a void* +/// pointing to this struct as its only argument and calls the function in the +/// struct with the written arguments. This method lets Clang handle the +/// vagaries of function calling conventions. +/// +/// The simplest use of the ClangFunctionCaller is to construct it with a +/// function representative of the signature you want to use, then call +/// ExecuteFunction(ExecutionContext &, Stream &, Value &). +/// +/// If you need to reuse the arguments for several calls, you can call +/// InsertFunction() followed by WriteFunctionArguments(), which will return +/// the location of the args struct for the wrapper function in args_addr_ref. +/// +/// If you need to call the function on the thread plan stack, you can also +/// call InsertFunction() followed by GetThreadPlanToCallFunction(). +/// +/// Any of the methods that take arg_addr_ptr or arg_addr_ref can be passed +/// a pointer set to LLDB_INVALID_ADDRESS and new structure will be allocated +/// and its address returned in that variable. +/// +/// Any of the methods that take arg_addr_ptr can be passed NULL, and the +/// argument space will be managed for you. +//---------------------------------------------------------------------- +class ClangFunctionCaller : public FunctionCaller +{ + friend class ASTStructExtractor; + + class ClangFunctionCallerHelper : public ClangExpressionHelper + { + public: + ClangFunctionCallerHelper (ClangFunctionCaller &owner) : + m_owner(owner) + { + } + + ~ClangFunctionCallerHelper() override = default; + + //------------------------------------------------------------------ + /// Return the object that the parser should use when resolving external + /// values. May be NULL if everything should be self-contained. + //------------------------------------------------------------------ + ClangExpressionDeclMap * + DeclMap() override + { + return NULL; + } + + //------------------------------------------------------------------ + /// Return the object that the parser should allow to access ASTs. + /// May be NULL if the ASTs do not need to be transformed. + /// + /// @param[in] passthrough + /// The ASTConsumer that the returned transformer should send + /// the ASTs to after transformation. + //------------------------------------------------------------------ + clang::ASTConsumer * + ASTTransformer(clang::ASTConsumer *passthrough) override; + + private: + ClangFunctionCaller &m_owner; + std::unique_ptr m_struct_extractor; ///< The class that generates the argument struct layout. + }; + +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] exe_scope + /// An execution context scope that gets us at least a target and + /// process. + /// + /// @param[in] ast_context + /// The AST context to evaluate argument types in. + /// + /// @param[in] return_qualtype + /// An opaque Clang QualType for the function result. Should be + /// defined in ast_context. + /// + /// @param[in] function_address + /// The address of the function to call. + /// + /// @param[in] arg_value_list + /// The default values to use when calling this function. Can + /// be overridden using WriteFunctionArguments(). + //------------------------------------------------------------------ + ClangFunctionCaller (ExecutionContextScope &exe_scope, + const CompilerType &return_type, + const Address& function_address, + const ValueList &arg_value_list, + const char *name); + + ~ClangFunctionCaller() override; + + //------------------------------------------------------------------ + /// Compile the wrapper function + /// + /// @param[in] errors + /// The stream to print parser errors to. + /// + /// @return + /// The number of errors. + //------------------------------------------------------------------ + unsigned + CompileFunction (Stream &errors) override; + + ExpressionTypeSystemHelper * + GetTypeSystemHelper () override + { + return &m_type_system_helper; + } + +protected: + const char *GetWrapperStructName() + { + return m_wrapper_struct_name.c_str(); + } + +private: + //------------------------------------------------------------------ + // For ClangFunctionCaller only + //------------------------------------------------------------------ + + // Note: the parser needs to be destructed before the execution unit, so + // declare the execution unit first. + ClangFunctionCallerHelper m_type_system_helper; +}; + +} // namespace lldb_private + +#endif // liblldb_ClangFunctionCaller_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp new file mode 100644 index 0000000000000..05d8a320a5a43 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp @@ -0,0 +1,731 @@ +//===-- ClangModulesDeclVendor.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +#include "clang/Basic/TargetInfo.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Parse/Parser.h" +#include "clang/Sema/Lookup.h" +#include "clang/Serialization/ASTReader.h" + +// Project includes +#include "ClangModulesDeclVendor.h" + +#include "lldb/Core/Log.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/LLDBAssert.h" + +using namespace lldb_private; + +namespace { + // Any Clang compiler requires a consumer for diagnostics. This one stores them as strings + // so we can provide them to the user in case a module failed to load. + class StoringDiagnosticConsumer : public clang::DiagnosticConsumer + { + public: + StoringDiagnosticConsumer (); + + void + HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel, + const clang::Diagnostic &info) override; + + void + ClearDiagnostics (); + + void + DumpDiagnostics (Stream &error_stream); + + private: + typedef std::pair IDAndDiagnostic; + std::vector m_diagnostics; + Log * m_log; + }; + + // The private implementation of our ClangModulesDeclVendor. Contains all the Clang state required + // to load modules. + class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor + { + public: + ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr &diagnostics_engine, + llvm::IntrusiveRefCntPtr &compiler_invocation, + std::unique_ptr &&compiler_instance, + std::unique_ptr &&parser); + + ~ClangModulesDeclVendorImpl() override = default; + + bool + AddModule(ModulePath &path, + ModuleVector *exported_modules, + Stream &error_stream) override; + + bool + AddModulesForCompileUnit(CompileUnit &cu, + ModuleVector &exported_modules, + Stream &error_stream) override; + + uint32_t + FindDecls(const ConstString &name, + bool append, + uint32_t max_matches, + std::vector &decls) override; + + void + ForEachMacro(const ModuleVector &modules, + std::function handler) override; + + private: + void + ReportModuleExportsHelper (std::set &exports, + clang::Module *module); + + void + ReportModuleExports (ModuleVector &exports, + clang::Module *module); + + clang::ModuleLoadResult + DoGetModule(clang::ModuleIdPath path, bool make_visible); + + bool m_enabled = false; + + llvm::IntrusiveRefCntPtr m_diagnostics_engine; + llvm::IntrusiveRefCntPtr m_compiler_invocation; + std::unique_ptr m_compiler_instance; + std::unique_ptr m_parser; + size_t m_source_location_index = 0; // used to give name components fake SourceLocations + + typedef std::vector ImportedModule; + typedef std::map ImportedModuleMap; + typedef std::set ImportedModuleSet; + ImportedModuleMap m_imported_modules; + ImportedModuleSet m_user_imported_modules; + }; +} // anonymous namespace + +StoringDiagnosticConsumer::StoringDiagnosticConsumer () +{ + m_log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); +} + +void +StoringDiagnosticConsumer::HandleDiagnostic (clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) +{ + llvm::SmallVector diagnostic_string; + + info.FormatDiagnostic(diagnostic_string); + + m_diagnostics.push_back(IDAndDiagnostic(DiagLevel, std::string(diagnostic_string.data(), diagnostic_string.size()))); +} + +void +StoringDiagnosticConsumer::ClearDiagnostics () +{ + m_diagnostics.clear(); +} + +void +StoringDiagnosticConsumer::DumpDiagnostics (Stream &error_stream) +{ + for (IDAndDiagnostic &diag : m_diagnostics) + { + switch (diag.first) + { + default: + error_stream.PutCString(diag.second.c_str()); + error_stream.PutChar('\n'); + break; + case clang::DiagnosticsEngine::Level::Ignored: + break; + } + } +} + +static FileSpec +GetResourceDir () +{ + static FileSpec g_cached_resource_dir; + + static std::once_flag g_once_flag; + + std::call_once(g_once_flag, [](){ + HostInfo::GetLLDBPath (lldb::ePathTypeClangDir, g_cached_resource_dir); + }); + + return g_cached_resource_dir; +} + +ClangModulesDeclVendor::ClangModulesDeclVendor() +{ +} + +ClangModulesDeclVendor::~ClangModulesDeclVendor() +{ +} + +ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(llvm::IntrusiveRefCntPtr &diagnostics_engine, + llvm::IntrusiveRefCntPtr &compiler_invocation, + std::unique_ptr &&compiler_instance, + std::unique_ptr &&parser) : + ClangModulesDeclVendor(), + m_diagnostics_engine(diagnostics_engine), + m_compiler_invocation(compiler_invocation), + m_compiler_instance(std::move(compiler_instance)), + m_parser(std::move(parser)), + m_imported_modules() +{ +} + +void +ClangModulesDeclVendorImpl::ReportModuleExportsHelper (std::set &exports, + clang::Module *module) +{ + if (exports.count(reinterpret_cast(module))) + return; + + exports.insert(reinterpret_cast(module)); + + llvm::SmallVector sub_exports; + + module->getExportedModules(sub_exports); + + for (clang::Module *module : sub_exports) + { + ReportModuleExportsHelper(exports, module); + } +} + +void +ClangModulesDeclVendorImpl::ReportModuleExports (ClangModulesDeclVendor::ModuleVector &exports, + clang::Module *module) +{ + std::set exports_set; + + ReportModuleExportsHelper(exports_set, module); + + for (ModuleID module : exports_set) + { + exports.push_back(module); + } +} + +bool +ClangModulesDeclVendorImpl::AddModule(ModulePath &path, + ModuleVector *exported_modules, + Stream &error_stream) +{ + // Fail early. + + if (m_compiler_instance->hadModuleLoaderFatalFailure()) + { + error_stream.PutCString("error: Couldn't load a module because the module loader is in a fatal state.\n"); + return false; + } + + // Check if we've already imported this module. + + std::vector imported_module; + + for (ConstString path_component : path) + { + imported_module.push_back(path_component); + } + + { + ImportedModuleMap::iterator mi = m_imported_modules.find(imported_module); + + if (mi != m_imported_modules.end()) + { + if (exported_modules) + { + ReportModuleExports(*exported_modules, mi->second); + } + return true; + } + } + + if (!m_compiler_instance->getPreprocessor().getHeaderSearchInfo().lookupModule(path[0].GetStringRef())) + { + error_stream.Printf("error: Header search couldn't locate module %s\n", path[0].AsCString()); + return false; + } + + llvm::SmallVector, 4> clang_path; + + { + clang::SourceManager &source_manager = m_compiler_instance->getASTContext().getSourceManager(); + + for (ConstString path_component : path) + { + clang_path.push_back(std::make_pair(&m_compiler_instance->getASTContext().Idents.get(path_component.GetStringRef()), + source_manager.getLocForStartOfFile(source_manager.getMainFileID()).getLocWithOffset(m_source_location_index++))); + } + } + + StoringDiagnosticConsumer *diagnostic_consumer = static_cast(m_compiler_instance->getDiagnostics().getClient()); + + diagnostic_consumer->ClearDiagnostics(); + + clang::Module *top_level_module = DoGetModule(clang_path.front(), false); + + if (!top_level_module) + { + diagnostic_consumer->DumpDiagnostics(error_stream); + error_stream.Printf("error: Couldn't load top-level module %s\n", path[0].AsCString()); + return false; + } + + clang::Module *submodule = top_level_module; + + for (size_t ci = 1; ci < path.size(); ++ci) + { + llvm::StringRef component = path[ci].GetStringRef(); + submodule = submodule->findSubmodule(component.str()); + if (!submodule) + { + diagnostic_consumer->DumpDiagnostics(error_stream); + error_stream.Printf("error: Couldn't load submodule %s\n", component.str().c_str()); + return false; + } + } + + clang::Module *requested_module = DoGetModule(clang_path, true); + + if (requested_module != nullptr) + { + if (exported_modules) + { + ReportModuleExports(*exported_modules, requested_module); + } + + m_imported_modules[imported_module] = requested_module; + + m_enabled = true; + + return true; + } + + return false; +} + +bool +ClangModulesDeclVendor::LanguageSupportsClangModules (lldb::LanguageType language) +{ + switch (language) + { + default: + return false; + // C++ and friends to be added + case lldb::LanguageType::eLanguageTypeC: + case lldb::LanguageType::eLanguageTypeC11: + case lldb::LanguageType::eLanguageTypeC89: + case lldb::LanguageType::eLanguageTypeC99: + case lldb::LanguageType::eLanguageTypeObjC: + return true; + } +} + +bool +ClangModulesDeclVendorImpl::AddModulesForCompileUnit(CompileUnit &cu, + ClangModulesDeclVendor::ModuleVector &exported_modules, + Stream &error_stream) +{ + if (LanguageSupportsClangModules(cu.GetLanguage())) + { + std::vector imported_modules = cu.GetImportedModules(); + + for (ConstString imported_module : imported_modules) + { + std::vector path; + + path.push_back(imported_module); + + if (!AddModule(path, &exported_modules, error_stream)) + { + return false; + } + } + + return true; + } + + return true; +} + +// ClangImporter::lookupValue + +uint32_t +ClangModulesDeclVendorImpl::FindDecls (const ConstString &name, + bool append, + uint32_t max_matches, + std::vector &decls) +{ + if (!m_enabled) + { + return 0; + } + + if (!append) + decls.clear(); + + clang::IdentifierInfo &ident = m_compiler_instance->getASTContext().Idents.get(name.GetStringRef()); + + clang::LookupResult lookup_result(m_compiler_instance->getSema(), + clang::DeclarationName(&ident), + clang::SourceLocation(), + clang::Sema::LookupOrdinaryName); + + m_compiler_instance->getSema().LookupName(lookup_result, m_compiler_instance->getSema().getScopeForContext(m_compiler_instance->getASTContext().getTranslationUnitDecl())); + + uint32_t num_matches = 0; + + for (clang::NamedDecl *named_decl : lookup_result) + { + if (num_matches >= max_matches) + return num_matches; + + decls.push_back(named_decl); + ++num_matches; + } + + return num_matches; +} + +void +ClangModulesDeclVendorImpl::ForEachMacro(const ClangModulesDeclVendor::ModuleVector &modules, + std::function handler) +{ + if (!m_enabled) + { + return; + } + + typedef std::map ModulePriorityMap; + ModulePriorityMap module_priorities; + + ssize_t priority = 0; + + for (ModuleID module : modules) + { + module_priorities[module] = priority++; + } + + if (m_compiler_instance->getPreprocessor().getExternalSource()) + { + m_compiler_instance->getPreprocessor().getExternalSource()->ReadDefinedMacros(); + } + + for (clang::Preprocessor::macro_iterator mi = m_compiler_instance->getPreprocessor().macro_begin(), + me = m_compiler_instance->getPreprocessor().macro_end(); + mi != me; + ++mi) + { + const clang::IdentifierInfo *ii = nullptr; + + { + if (clang::IdentifierInfoLookup *lookup = m_compiler_instance->getPreprocessor().getIdentifierTable().getExternalIdentifierLookup()) + { + lookup->get(mi->first->getName()); + } + if (!ii) + { + ii = mi->first; + } + } + + ssize_t found_priority = -1; + clang::MacroInfo *macro_info = nullptr; + + for (clang::ModuleMacro *module_macro : m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii)) + { + clang::Module *module = module_macro->getOwningModule(); + + { + ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast(module)); + + if (pi != module_priorities.end() && pi->second > found_priority) + { + macro_info = module_macro->getMacroInfo(); + found_priority = pi->second; + } + } + + clang::Module *top_level_module = module->getTopLevelModule(); + + if (top_level_module != module) + { + ModulePriorityMap::iterator pi = module_priorities.find(reinterpret_cast(top_level_module)); + + if ((pi != module_priorities.end()) && pi->second > found_priority) + { + macro_info = module_macro->getMacroInfo(); + found_priority = pi->second; + } + } + } + + if (macro_info) + { + std::string macro_expansion = "#define "; + macro_expansion.append(mi->first->getName().str().c_str()); + + { + if (macro_info->isFunctionLike()) + { + macro_expansion.append("("); + + bool first_arg = true; + + for (clang::MacroInfo::arg_iterator ai = macro_info->arg_begin(), + ae = macro_info->arg_end(); + ai != ae; + ++ai) + { + if (!first_arg) + { + macro_expansion.append(", "); + } + else + { + first_arg = false; + } + + macro_expansion.append((*ai)->getName().str()); + } + + if (macro_info->isC99Varargs()) + { + if (first_arg) + { + macro_expansion.append("..."); + } + else + { + macro_expansion.append(", ..."); + } + } + else if (macro_info->isGNUVarargs()) + { + macro_expansion.append("..."); + } + + macro_expansion.append(")"); + } + + macro_expansion.append(" "); + + bool first_token = true; + + for (clang::MacroInfo::tokens_iterator ti = macro_info->tokens_begin(), + te = macro_info->tokens_end(); + ti != te; + ++ti) + { + if (!first_token) + { + macro_expansion.append(" "); + } + else + { + first_token = false; + } + + if (ti->isLiteral()) + { + if (const char *literal_data = ti->getLiteralData()) + { + std::string token_str(literal_data, ti->getLength()); + macro_expansion.append(token_str); + } + else + { + bool invalid = false; + const char *literal_source = m_compiler_instance->getSourceManager().getCharacterData(ti->getLocation(), &invalid); + + if (invalid) + { + lldbassert(!"Unhandled token kind"); + macro_expansion.append(""); + } + else + { + macro_expansion.append(std::string(literal_source, ti->getLength())); + } + } + } + else if (const char *punctuator_spelling = clang::tok::getPunctuatorSpelling(ti->getKind())) + { + macro_expansion.append(punctuator_spelling); + } + else if (const char *keyword_spelling = clang::tok::getKeywordSpelling(ti->getKind())) + { + macro_expansion.append(keyword_spelling); + } + else + { + switch (ti->getKind()) + { + case clang::tok::TokenKind::identifier: + macro_expansion.append(ti->getIdentifierInfo()->getName().str()); + break; + case clang::tok::TokenKind::raw_identifier: + macro_expansion.append(ti->getRawIdentifier().str()); + default: + macro_expansion.append(ti->getName()); + break; + } + } + } + + if (handler(macro_expansion)) + { + return; + } + } + } + } +} + +clang::ModuleLoadResult +ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path, + bool make_visible) +{ + clang::Module::NameVisibilityKind visibility = make_visible ? clang::Module::AllVisible : clang::Module::Hidden; + + const bool is_inclusion_directive = false; + + return m_compiler_instance->loadModule(path.front().second, path, visibility, is_inclusion_directive); +} + +static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer"; + +lldb_private::ClangModulesDeclVendor * +ClangModulesDeclVendor::Create(Target &target) +{ + // FIXME we should insure programmatically that the expression parser's compiler and the modules runtime's + // compiler are both initialized in the same way – preferably by the same code. + + if (!target.GetPlatform()->SupportsModules()) + return nullptr; + + const ArchSpec &arch = target.GetArchitecture(); + + std::vector compiler_invocation_arguments = + { + "-fmodules", + "-fcxx-modules", + "-fsyntax-only", + "-femit-all-decls", + "-target", arch.GetTriple().str(), + "-fmodules-validate-system-headers", + "-Werror=non-modular-include-in-framework-module" + }; + + target.GetPlatform()->AddClangModuleCompilationOptions(&target, compiler_invocation_arguments); + + compiler_invocation_arguments.push_back(ModuleImportBufferName); + + // Add additional search paths with { "-I", path } or { "-F", path } here. + + { + llvm::SmallString<128> DefaultModuleCache; + const bool erased_on_reboot = false; + llvm::sys::path::system_temp_directory(erased_on_reboot, DefaultModuleCache); + llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang"); + llvm::sys::path::append(DefaultModuleCache, "ModuleCache"); + std::string module_cache_argument("-fmodules-cache-path="); + module_cache_argument.append(DefaultModuleCache.str().str()); + compiler_invocation_arguments.push_back(module_cache_argument); + } + + FileSpecList &module_search_paths = target.GetClangModuleSearchPaths(); + + for (size_t spi = 0, spe = module_search_paths.GetSize(); spi < spe; ++spi) + { + const FileSpec &search_path = module_search_paths.GetFileSpecAtIndex(spi); + + std::string search_path_argument = "-I"; + search_path_argument.append(search_path.GetPath()); + + compiler_invocation_arguments.push_back(search_path_argument); + } + + { + FileSpec clang_resource_dir = GetResourceDir(); + + if (clang_resource_dir.IsDirectory()) + { + compiler_invocation_arguments.push_back("-resource-dir"); + compiler_invocation_arguments.push_back(clang_resource_dir.GetPath()); + } + } + + llvm::IntrusiveRefCntPtr diagnostics_engine = clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions, + new StoringDiagnosticConsumer); + + std::vector compiler_invocation_argument_cstrs; + + for (const std::string &arg : compiler_invocation_arguments) { + compiler_invocation_argument_cstrs.push_back(arg.c_str()); + } + + llvm::IntrusiveRefCntPtr invocation(clang::createInvocationFromCommandLine(compiler_invocation_argument_cstrs, diagnostics_engine)); + + if (!invocation) + return nullptr; + + std::unique_ptr source_buffer = llvm::MemoryBuffer::getMemBuffer("extern int __lldb __attribute__((unavailable));", + ModuleImportBufferName); + + invocation->getPreprocessorOpts().addRemappedFile(ModuleImportBufferName, source_buffer.release()); + + std::unique_ptr instance(new clang::CompilerInstance); + + instance->setDiagnostics(diagnostics_engine.get()); + instance->setInvocation(invocation.get()); + + std::unique_ptr action(new clang::SyntaxOnlyAction); + + instance->setTarget(clang::TargetInfo::CreateTargetInfo(*diagnostics_engine, instance->getInvocation().TargetOpts)); + + if (!instance->hasTarget()) + return nullptr; + + instance->getTarget().adjust(instance->getLangOpts()); + + if (!action->BeginSourceFile(*instance, instance->getFrontendOpts().Inputs[0])) + return nullptr; + + instance->getPreprocessor().enableIncrementalProcessing(); + + instance->createModuleManager(); + + instance->createSema(action->getTranslationUnitKind(), nullptr); + + const bool skipFunctionBodies = false; + std::unique_ptr parser(new clang::Parser(instance->getPreprocessor(), instance->getSema(), skipFunctionBodies)); + + instance->getPreprocessor().EnterMainSourceFile(); + parser->Initialize(); + + clang::Parser::DeclGroupPtrTy parsed; + + while (!parser->ParseTopLevelDecl(parsed)); + + return new ClangModulesDeclVendorImpl (diagnostics_engine, invocation, std::move(instance), std::move(parser)); +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h new file mode 100644 index 0000000000000..df3b20550f9a0 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h @@ -0,0 +1,128 @@ +//===-- ClangModulesDeclVendor.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangModulesDeclVendor_h +#define liblldb_ClangModulesDeclVendor_h + +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Symbol/DeclVendor.h" +#include "lldb/Target/Platform.h" + +#include +#include + +namespace lldb_private +{ + +class ClangModulesDeclVendor : public DeclVendor +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + ClangModulesDeclVendor(); + + ~ClangModulesDeclVendor() override; + + static ClangModulesDeclVendor * + Create(Target &target); + + typedef std::vector ModulePath; + typedef uintptr_t ModuleID; + typedef std::vector ModuleVector; + + //------------------------------------------------------------------ + /// Add a module to the list of modules to search. + /// + /// @param[in] path + /// The path to the exact module to be loaded. E.g., if the desired + /// module is std.io, then this should be { "std", "io" }. + /// + /// @param[in] exported_modules + /// If non-NULL, a pointer to a vector to populate with the ID of every + /// module that is re-exported by the specified module. + /// + /// @param[in] error_stream + /// A stream to populate with the output of the Clang parser when + /// it tries to load the module. + /// + /// @return + /// True if the module could be loaded; false if not. If the + /// compiler encountered a fatal error during a previous module + /// load, then this will always return false for this ModuleImporter. + //------------------------------------------------------------------ + virtual bool + AddModule(ModulePath &path, + ModuleVector *exported_modules, + Stream &error_stream) = 0; + + //------------------------------------------------------------------ + /// Add all modules referred to in a given compilation unit to the list + /// of modules to search. + /// + /// @param[in] cu + /// The compilation unit to scan for imported modules. + /// + /// @param[in] exported_modules + /// A vector to populate with the ID of each module loaded (directly + /// and via re-exports) in this way. + /// + /// @param[in] error_stream + /// A stream to populate with the output of the Clang parser when + /// it tries to load the modules. + /// + /// @return + /// True if all modules referred to by the compilation unit could be + /// loaded; false if one could not be loaded. If the compiler + /// encountered a fatal error during a previous module + /// load, then this will always return false for this ModuleImporter. + //------------------------------------------------------------------ + virtual bool + AddModulesForCompileUnit(CompileUnit &cu, + ModuleVector &exported_modules, + Stream &error_stream) = 0; + + //------------------------------------------------------------------ + /// Enumerate all the macros that are defined by a given set of modules + /// that are already imported. + /// + /// @param[in] modules + /// The unique IDs for all modules to query. Later modules have higher + /// priority, just as if you @imported them in that order. This matters + /// if module A #defines a macro and module B #undefs it. + /// + /// @param[in] handler + /// A function to call with the text of each #define (including the + /// #define directive). #undef directives are not included; we simply + /// elide any corresponding #define. If this function returns true, + /// we stop the iteration immediately. + //------------------------------------------------------------------ + virtual void + ForEachMacro(const ModuleVector &modules, + std::function handler) = 0; + + //------------------------------------------------------------------ + /// Query whether Clang supports modules for a particular language. + /// LLDB uses this to decide whether to try to find the modules loaded + /// by a gaiven compile unit. + /// + /// @param[in] language + /// The language to query for. + /// + /// @return + /// True if Clang has modules for the given language. + //------------------------------------------------------------------ + static bool + LanguageSupportsClangModules (lldb::LanguageType language); +}; + +} // namespace lldb_private + +#endif // liblldb_ClangModulesDeclVendor_h diff --git a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp new file mode 100644 index 0000000000000..9bf9d435d7ead --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp @@ -0,0 +1,84 @@ +//===-- ClangPersistentVariables.cpp ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangPersistentVariables.h" + +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/Value.h" + +#include "llvm/ADT/StringMap.h" + +using namespace lldb; +using namespace lldb_private; + +ClangPersistentVariables::ClangPersistentVariables () : + lldb_private::PersistentExpressionState(LLVMCastKind::eKindClang), + m_next_persistent_variable_id (0) +{ +} + +ExpressionVariableSP +ClangPersistentVariables::CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp) +{ + return AddNewlyConstructedVariable(new ClangExpressionVariable(valobj_sp)); +} + +ExpressionVariableSP +ClangPersistentVariables::CreatePersistentVariable (ExecutionContextScope *exe_scope, + const ConstString &name, + const CompilerType& compiler_type, + lldb::ByteOrder byte_order, + uint32_t addr_byte_size) +{ + return AddNewlyConstructedVariable(new ClangExpressionVariable(exe_scope, name, compiler_type, byte_order, addr_byte_size)); +} + +void +ClangPersistentVariables::RemovePersistentVariable (lldb::ExpressionVariableSP variable) +{ + RemoveVariable(variable); + + const char *name = variable->GetName().AsCString(); + + if (*name != '$') + return; + name++; + + if (strtoul(name, NULL, 0) == m_next_persistent_variable_id - 1) + m_next_persistent_variable_id--; +} + +ConstString +ClangPersistentVariables::GetNextPersistentVariableName () +{ + char name_cstr[256]; + ::snprintf (name_cstr, sizeof(name_cstr), "$%u", m_next_persistent_variable_id++); + ConstString name(name_cstr); + return name; +} + +void +ClangPersistentVariables::RegisterPersistentType (const ConstString &name, + clang::TypeDecl *type_decl) +{ + m_persistent_types.insert(std::pair(name.GetCString(), type_decl)); +} + +clang::TypeDecl * +ClangPersistentVariables::GetPersistentType (const ConstString &name) +{ + PersistentTypeMap::const_iterator i = m_persistent_types.find(name.GetCString()); + + if (i == m_persistent_types.end()) + return NULL; + else + return i->second; +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h new file mode 100644 index 0000000000000..0e03d013d0490 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h @@ -0,0 +1,106 @@ +//===-- ClangPersistentVariables.h ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangPersistentVariables_h_ +#define liblldb_ClangPersistentVariables_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "llvm/ADT/DenseMap.h" + +// Project includes +#include "ClangExpressionVariable.h" +#include "ClangModulesDeclVendor.h" + +#include "lldb/Expression/ExpressionVariable.h" + +namespace lldb_private +{ + +//---------------------------------------------------------------------- +/// @class ClangPersistentVariables ClangPersistentVariables.h "lldb/Expression/ClangPersistentVariables.h" +/// @brief Manages persistent values that need to be preserved between expression invocations. +/// +/// A list of variables that can be accessed and updated by any expression. See +/// ClangPersistentVariable for more discussion. Also provides an increasing, +/// 0-based counter for naming result variables. +//---------------------------------------------------------------------- +class ClangPersistentVariables : public PersistentExpressionState +{ +public: + ClangPersistentVariables(); + + ~ClangPersistentVariables() override = default; + + //------------------------------------------------------------------ + // llvm casting support + //------------------------------------------------------------------ + static bool classof(const PersistentExpressionState *pv) + { + return pv->getKind() == PersistentExpressionState::eKindClang; + } + + lldb::ExpressionVariableSP + CreatePersistentVariable (const lldb::ValueObjectSP &valobj_sp) override; + + lldb::ExpressionVariableSP + CreatePersistentVariable (ExecutionContextScope *exe_scope, + const ConstString &name, + const CompilerType& compiler_type, + lldb::ByteOrder byte_order, + uint32_t addr_byte_size) override; + + //---------------------------------------------------------------------- + /// Return the next entry in the sequence of strings "$0", "$1", ... for + /// use naming persistent expression convenience variables. + /// + /// @return + /// A string that contains the next persistent variable name. + //---------------------------------------------------------------------- + ConstString + GetNextPersistentVariableName () override; + + void + RemovePersistentVariable (lldb::ExpressionVariableSP variable) override; + + lldb::addr_t + LookupSymbol (const ConstString &name) override { return LLDB_INVALID_ADDRESS; } + + void + RegisterPersistentType (const ConstString &name, + clang::TypeDecl *tag_decl); + + clang::TypeDecl * + GetPersistentType (const ConstString &name); + + void + AddHandLoadedClangModule(ClangModulesDeclVendor::ModuleID module) + { + m_hand_loaded_clang_modules.push_back(module); + } + + const ClangModulesDeclVendor::ModuleVector &GetHandLoadedClangModules() + { + return m_hand_loaded_clang_modules; + } + +private: + uint32_t m_next_persistent_variable_id; ///< The counter used by GetNextResultName(). + + typedef llvm::DenseMap PersistentTypeMap; + PersistentTypeMap m_persistent_types; ///< The persistent types declared by the user. + + ClangModulesDeclVendor::ModuleVector m_hand_loaded_clang_modules; ///< These are Clang modules we hand-loaded; these are the highest- + ///< priority source for macros. +}; + +} // namespace lldb_private + +#endif // liblldb_ClangPersistentVariables_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp new file mode 100644 index 0000000000000..11f7f84ff5f17 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -0,0 +1,673 @@ +//===-- ClangUserExpression.cpp ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include +#if HAVE_SYS_TYPES_H +# include +#endif + +#include +#include +#include + +#include "ClangUserExpression.h" + +#include "ASTResultSynthesizer.h" +#include "ClangExpressionDeclMap.h" +#include "ClangExpressionParser.h" +#include "ClangModulesDeclVendor.h" +#include "ClangPersistentVariables.h" + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Expression/ExpressionSourceCode.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Expression/IRInterpreter.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Symbol/Block.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanCallUserExpression.h" + +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" + +using namespace lldb_private; + +ClangUserExpression::ClangUserExpression (ExecutionContextScope &exe_scope, + const char *expr, + const char *expr_prefix, + lldb::LanguageType language, + ResultType desired_type, + const EvaluateExpressionOptions &options) : + LLVMUserExpression (exe_scope, expr, expr_prefix, language, desired_type, options), + m_type_system_helper(*m_target_wp.lock().get()) +{ + switch (m_language) + { + case lldb::eLanguageTypeC_plus_plus: + m_allow_cxx = true; + break; + case lldb::eLanguageTypeObjC: + m_allow_objc = true; + break; + case lldb::eLanguageTypeObjC_plus_plus: + default: + m_allow_cxx = true; + m_allow_objc = true; + break; + } +} + +ClangUserExpression::~ClangUserExpression () +{ +} + +void +ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf("ClangUserExpression::ScanContext()"); + + m_target = exe_ctx.GetTargetPtr(); + + if (!(m_allow_cxx || m_allow_objc)) + { + if (log) + log->Printf(" [CUE::SC] Settings inhibit C++ and Objective-C"); + return; + } + + StackFrame *frame = exe_ctx.GetFramePtr(); + if (frame == NULL) + { + if (log) + log->Printf(" [CUE::SC] Null stack frame"); + return; + } + + SymbolContext sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction | lldb::eSymbolContextBlock); + + if (!sym_ctx.function) + { + if (log) + log->Printf(" [CUE::SC] Null function"); + return; + } + + // Find the block that defines the function represented by "sym_ctx" + Block *function_block = sym_ctx.GetFunctionBlock(); + + if (!function_block) + { + if (log) + log->Printf(" [CUE::SC] Null function block"); + return; + } + + CompilerDeclContext decl_context = function_block->GetDeclContext(); + + if (!decl_context) + { + if (log) + log->Printf(" [CUE::SC] Null decl context"); + return; + } + + if (clang::CXXMethodDecl *method_decl = ClangASTContext::DeclContextGetAsCXXMethodDecl(decl_context)) + { + if (m_allow_cxx && method_decl->isInstance()) + { + if (m_enforce_valid_object) + { + lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); + + const char *thisErrorString = "Stopped in a C++ method, but 'this' isn't available; pretending we are in a generic context"; + + if (!variable_list_sp) + { + err.SetErrorString(thisErrorString); + return; + } + + lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this"))); + + if (!this_var_sp || + !this_var_sp->IsInScope(frame) || + !this_var_sp->LocationIsValidForFrame (frame)) + { + err.SetErrorString(thisErrorString); + return; + } + } + + m_in_cplusplus_method = true; + m_needs_object_ptr = true; + } + } + else if (clang::ObjCMethodDecl *method_decl = ClangASTContext::DeclContextGetAsObjCMethodDecl(decl_context)) + { + if (m_allow_objc) + { + if (m_enforce_valid_object) + { + lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); + + const char *selfErrorString = "Stopped in an Objective-C method, but 'self' isn't available; pretending we are in a generic context"; + + if (!variable_list_sp) + { + err.SetErrorString(selfErrorString); + return; + } + + lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self")); + + if (!self_variable_sp || + !self_variable_sp->IsInScope(frame) || + !self_variable_sp->LocationIsValidForFrame (frame)) + { + err.SetErrorString(selfErrorString); + return; + } + } + + m_in_objectivec_method = true; + m_needs_object_ptr = true; + + if (!method_decl->isInstanceMethod()) + m_in_static_method = true; + } + } + else if (clang::FunctionDecl *function_decl = ClangASTContext::DeclContextGetAsFunctionDecl(decl_context)) + { + // We might also have a function that said in the debug information that it captured an + // object pointer. The best way to deal with getting to the ivars at present is by pretending + // that this is a method of a class in whatever runtime the debug info says the object pointer + // belongs to. Do that here. + + ClangASTMetadata *metadata = ClangASTContext::DeclContextGetMetaData (decl_context, function_decl); + if (metadata && metadata->HasObjectPtr()) + { + lldb::LanguageType language = metadata->GetObjectPtrLanguage(); + if (language == lldb::eLanguageTypeC_plus_plus) + { + if (m_enforce_valid_object) + { + lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); + + const char *thisErrorString = "Stopped in a context claiming to capture a C++ object pointer, but 'this' isn't available; pretending we are in a generic context"; + + if (!variable_list_sp) + { + err.SetErrorString(thisErrorString); + return; + } + + lldb::VariableSP this_var_sp (variable_list_sp->FindVariable(ConstString("this"))); + + if (!this_var_sp || + !this_var_sp->IsInScope(frame) || + !this_var_sp->LocationIsValidForFrame (frame)) + { + err.SetErrorString(thisErrorString); + return; + } + } + + m_in_cplusplus_method = true; + m_needs_object_ptr = true; + } + else if (language == lldb::eLanguageTypeObjC) + { + if (m_enforce_valid_object) + { + lldb::VariableListSP variable_list_sp (function_block->GetBlockVariableList (true)); + + const char *selfErrorString = "Stopped in a context claiming to capture an Objective-C object pointer, but 'self' isn't available; pretending we are in a generic context"; + + if (!variable_list_sp) + { + err.SetErrorString(selfErrorString); + return; + } + + lldb::VariableSP self_variable_sp = variable_list_sp->FindVariable(ConstString("self")); + + if (!self_variable_sp || + !self_variable_sp->IsInScope(frame) || + !self_variable_sp->LocationIsValidForFrame (frame)) + { + err.SetErrorString(selfErrorString); + return; + } + + Type *self_type = self_variable_sp->GetType(); + + if (!self_type) + { + err.SetErrorString(selfErrorString); + return; + } + + CompilerType self_clang_type = self_type->GetForwardCompilerType (); + + if (!self_clang_type) + { + err.SetErrorString(selfErrorString); + return; + } + + if (ClangASTContext::IsObjCClassType(self_clang_type)) + { + return; + } + else if (ClangASTContext::IsObjCObjectPointerType(self_clang_type)) + { + m_in_objectivec_method = true; + m_needs_object_ptr = true; + } + else + { + err.SetErrorString(selfErrorString); + return; + } + } + else + { + m_in_objectivec_method = true; + m_needs_object_ptr = true; + } + } + } + } +} + +// This is a really nasty hack, meant to fix Objective-C expressions of the form +// (int)[myArray count]. Right now, because the type information for count is +// not available, [myArray count] returns id, which can't be directly cast to +// int without causing a clang error. +static void +ApplyObjcCastHack(std::string &expr) +{ +#define OBJC_CAST_HACK_FROM "(int)[" +#define OBJC_CAST_HACK_TO "(int)(long long)[" + + size_t from_offset; + + while ((from_offset = expr.find(OBJC_CAST_HACK_FROM)) != expr.npos) + expr.replace(from_offset, sizeof(OBJC_CAST_HACK_FROM) - 1, OBJC_CAST_HACK_TO); + +#undef OBJC_CAST_HACK_TO +#undef OBJC_CAST_HACK_FROM +} + +bool +ClangUserExpression::Parse (Stream &error_stream, + ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, + bool keep_result_in_memory, + bool generate_debug_info) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + Error err; + + InstallContext(exe_ctx); + + if (Target *target = exe_ctx.GetTargetPtr()) + { + if (PersistentExpressionState *persistent_state = target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)) + { + m_result_delegate.RegisterPersistentState(persistent_state); + } + else + { + error_stream.PutCString ("error: couldn't start parsing (no persistent data)"); + return false; + } + } + else + { + error_stream.PutCString ("error: couldn't start parsing (no target)"); + return false; + } + + ScanContext(exe_ctx, err); + + if (!err.Success()) + { + error_stream.Printf("warning: %s\n", err.AsCString()); + } + + StreamString m_transformed_stream; + + //////////////////////////////////// + // Generate the expression + // + + ApplyObjcCastHack(m_expr_text); + //ApplyUnicharHack(m_expr_text); + + std::string prefix = m_expr_prefix; + + if (ClangModulesDeclVendor *decl_vendor = m_target->GetClangModulesDeclVendor()) + { + const ClangModulesDeclVendor::ModuleVector &hand_imported_modules = llvm::cast(m_target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC))->GetHandLoadedClangModules(); + ClangModulesDeclVendor::ModuleVector modules_for_macros; + + for (ClangModulesDeclVendor::ModuleID module : hand_imported_modules) + { + modules_for_macros.push_back(module); + } + + if (m_target->GetEnableAutoImportClangModules()) + { + if (StackFrame *frame = exe_ctx.GetFramePtr()) + { + if (Block *block = frame->GetFrameBlock()) + { + SymbolContext sc; + + block->CalculateSymbolContext(&sc); + + if (sc.comp_unit) + { + StreamString error_stream; + + decl_vendor->AddModulesForCompileUnit(*sc.comp_unit, modules_for_macros, error_stream); + } + } + } + } + } + + std::unique_ptr source_code (ExpressionSourceCode::CreateWrapped(prefix.c_str(), m_expr_text.c_str())); + + lldb::LanguageType lang_type; + + if (m_in_cplusplus_method) + lang_type = lldb::eLanguageTypeC_plus_plus; + else if (m_in_objectivec_method) + lang_type = lldb::eLanguageTypeObjC; + else + lang_type = lldb::eLanguageTypeC; + + if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_in_static_method, exe_ctx)) + { + error_stream.PutCString ("error: couldn't construct expression body"); + return false; + } + + if (log) + log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str()); + + //////////////////////////////////// + // Set up the target and compiler + // + + Target *target = exe_ctx.GetTargetPtr(); + + if (!target) + { + error_stream.PutCString ("error: invalid target\n"); + return false; + } + + ////////////////////////// + // Parse the expression + // + + m_materializer_ap.reset(new Materializer()); + + ResetDeclMap(exe_ctx, m_result_delegate, keep_result_in_memory); + + class OnExit + { + public: + typedef std::function Callback; + + OnExit (Callback const &callback) : + m_callback(callback) + { + } + + ~OnExit () + { + m_callback(); + } + private: + Callback m_callback; + }; + + OnExit on_exit([this]() { ResetDeclMap(); }); + + if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) + { + error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); + + ResetDeclMap(); // We are being careful here in the case of breakpoint conditions. + + return false; + } + + Process *process = exe_ctx.GetProcessPtr(); + ExecutionContextScope *exe_scope = process; + + if (!exe_scope) + exe_scope = exe_ctx.GetTargetPtr(); + + ClangExpressionParser parser(exe_scope, *this, generate_debug_info); + + unsigned num_errors = parser.Parse (error_stream); + + if (num_errors) + { + error_stream.Printf ("error: %d errors parsing expression\n", num_errors); + + ResetDeclMap(); // We are being careful here in the case of breakpoint conditions. + + return false; + } + + ////////////////////////////////////////////////////////////////////////////////////////// + // Prepare the output of the parser for execution, evaluating it statically if possible + // + + Error jit_error = parser.PrepareForExecution (m_jit_start_addr, + m_jit_end_addr, + m_execution_unit_sp, + exe_ctx, + m_can_interpret, + execution_policy); + + if (generate_debug_info) + { + lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule()); + + if (jit_module_sp) + { + ConstString const_func_name(FunctionName()); + FileSpec jit_file; + jit_file.GetFilename() = const_func_name; + jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString()); + m_jit_module_wp = jit_module_sp; + target->GetImages().Append(jit_module_sp); + } +// lldb_private::ObjectFile *jit_obj_file = jit_module_sp->GetObjectFile(); +// StreamFile strm (stdout, false); +// if (jit_obj_file) +// { +// jit_obj_file->GetSectionList(); +// jit_obj_file->GetSymtab(); +// jit_obj_file->Dump(&strm); +// } +// lldb_private::SymbolVendor *jit_sym_vendor = jit_module_sp->GetSymbolVendor(); +// if (jit_sym_vendor) +// { +// lldb_private::SymbolContextList sc_list; +// jit_sym_vendor->FindFunctions(const_func_name, NULL, lldb::eFunctionNameTypeFull, true, false, sc_list); +// sc_list.Dump(&strm, target); +// jit_sym_vendor->Dump(&strm); +// } + } + + ResetDeclMap(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any ClangASTImporter::Minions. + + if (jit_error.Success()) + { + if (process && m_jit_start_addr != LLDB_INVALID_ADDRESS) + m_jit_process_wp = lldb::ProcessWP(process->shared_from_this()); + return true; + } + else + { + const char *error_cstr = jit_error.AsCString(); + if (error_cstr && error_cstr[0]) + error_stream.Printf ("error: %s\n", error_cstr); + else + error_stream.Printf ("error: expression can't be interpreted or run\n"); + return false; + } +} + +bool +ClangUserExpression::AddArguments (ExecutionContext &exe_ctx, + std::vector &args, + lldb::addr_t struct_address, + Stream &error_stream) +{ + lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS; + lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS; + + if (m_needs_object_ptr) + { + lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP(); + if (!frame_sp) + return true; + + ConstString object_name; + + if (m_in_cplusplus_method) + { + object_name.SetCString("this"); + } + else if (m_in_objectivec_method) + { + object_name.SetCString("self"); + } + else + { + error_stream.Printf("Need object pointer but don't know the language\n"); + return false; + } + + Error object_ptr_error; + + object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error); + + if (!object_ptr_error.Success()) + { + error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); + object_ptr = 0; + } + + if (m_in_objectivec_method) + { + ConstString cmd_name("_cmd"); + + cmd_ptr = GetObjectPointer(frame_sp, cmd_name, object_ptr_error); + + if (!object_ptr_error.Success()) + { + error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); + cmd_ptr = 0; + } + } + if (object_ptr) + args.push_back(object_ptr); + + if (m_in_objectivec_method) + args.push_back(cmd_ptr); + + args.push_back(struct_address); + } + else + { + args.push_back(struct_address); + } + return true; +} + +lldb::ExpressionVariableSP +ClangUserExpression::GetResultAfterDematerialization(ExecutionContextScope *exe_scope) +{ + return m_result_delegate.GetVariable(); +} + +void +ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(ExecutionContext &exe_ctx, Materializer::PersistentVariableDelegate &delegate, bool keep_result_in_memory) +{ + m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, &delegate, exe_ctx)); +} + +clang::ASTConsumer * +ClangUserExpression::ClangUserExpressionHelper::ASTTransformer (clang::ASTConsumer *passthrough) +{ + m_result_synthesizer_up.reset(new ASTResultSynthesizer(passthrough, + m_target)); + + return m_result_synthesizer_up.get(); +} + +ClangUserExpression::ResultDelegate::ResultDelegate() +{ +} + +ConstString +ClangUserExpression::ResultDelegate::GetName() +{ + return m_persistent_state->GetNextPersistentVariableName(); +} + +void +ClangUserExpression::ResultDelegate::DidDematerialize(lldb::ExpressionVariableSP &variable) +{ + m_variable = variable; +} + +void +ClangUserExpression::ResultDelegate::RegisterPersistentState(PersistentExpressionState *persistent_state) +{ + m_persistent_state = persistent_state; +} + +lldb::ExpressionVariableSP & +ClangUserExpression::ResultDelegate::GetVariable() +{ + return m_variable; +} + diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h new file mode 100644 index 0000000000000..f2bfe31dce09d --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -0,0 +1,218 @@ +//===-- ClangUserExpression.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangUserExpression_h_ +#define liblldb_ClangUserExpression_h_ + +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +// Project includes +#include "ASTStructExtractor.h" +#include "ASTResultSynthesizer.h" +#include "ClangExpressionDeclMap.h" +#include "ClangExpressionHelper.h" +#include "ClangExpressionVariable.h" +#include "IRForTarget.h" + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Expression/LLVMUserExpression.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Target/ExecutionContext.h" + +namespace lldb_private +{ + +//---------------------------------------------------------------------- +/// @class ClangUserExpression ClangUserExpression.h "lldb/Expression/ClangUserExpression.h" +/// @brief Encapsulates a single expression for use with Clang +/// +/// LLDB uses expressions for various purposes, notably to call functions +/// and as a backend for the expr command. ClangUserExpression encapsulates +/// the objects needed to parse and interpret or JIT an expression. It +/// uses the Clang parser to produce LLVM IR from the expression. +//---------------------------------------------------------------------- +class ClangUserExpression : public LLVMUserExpression +{ +public: + enum { kDefaultTimeout = 500000u }; + + class ClangUserExpressionHelper : public ClangExpressionHelper + { + public: + ClangUserExpressionHelper (Target &target) : + m_target(target) + { + } + + ~ClangUserExpressionHelper() override = default; + + //------------------------------------------------------------------ + /// Return the object that the parser should use when resolving external + /// values. May be NULL if everything should be self-contained. + //------------------------------------------------------------------ + ClangExpressionDeclMap * + DeclMap() override + { + return m_expr_decl_map_up.get(); + } + + void + ResetDeclMap() + { + m_expr_decl_map_up.reset(); + } + + void + ResetDeclMap (ExecutionContext & exe_ctx, Materializer::PersistentVariableDelegate &result_delegate, bool keep_result_in_memory); + + //------------------------------------------------------------------ + /// Return the object that the parser should allow to access ASTs. + /// May be NULL if the ASTs do not need to be transformed. + /// + /// @param[in] passthrough + /// The ASTConsumer that the returned transformer should send + /// the ASTs to after transformation. + //------------------------------------------------------------------ + clang::ASTConsumer * + ASTTransformer(clang::ASTConsumer *passthrough) override; + + private: + Target &m_target; + std::unique_ptr m_expr_decl_map_up; + std::unique_ptr m_struct_extractor_up; ///< The class that generates the argument struct layout. + std::unique_ptr m_result_synthesizer_up; + }; + + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] expr + /// The expression to parse. + /// + /// @param[in] expr_prefix + /// If non-NULL, a C string containing translation-unit level + /// definitions to be included when the expression is parsed. + /// + /// @param[in] language + /// If not eLanguageTypeUnknown, a language to use when parsing + /// the expression. Currently restricted to those languages + /// supported by Clang. + /// + /// @param[in] desired_type + /// If not eResultTypeAny, the type to use for the expression + /// result. + //------------------------------------------------------------------ + ClangUserExpression (ExecutionContextScope &exe_scope, + const char *expr, + const char *expr_prefix, + lldb::LanguageType language, + ResultType desired_type, + const EvaluateExpressionOptions &options); + + ~ClangUserExpression() override; + + //------------------------------------------------------------------ + /// Parse the expression + /// + /// @param[in] error_stream + /// A stream to print parse errors and warnings to. + /// + /// @param[in] exe_ctx + /// The execution context to use when looking up entities that + /// are needed for parsing (locations of functions, types of + /// variables, persistent variables, etc.) + /// + /// @param[in] execution_policy + /// Determines whether interpretation is possible or mandatory. + /// + /// @param[in] keep_result_in_memory + /// True if the resulting persistent variable should reside in + /// target memory, if applicable. + /// + /// @return + /// True on success (no errors); false otherwise. + //------------------------------------------------------------------ + bool + Parse (Stream &error_stream, + ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, + bool keep_result_in_memory, + bool generate_debug_info) override; + + ExpressionTypeSystemHelper * + GetTypeSystemHelper () override + { + return &m_type_system_helper; + } + + ClangExpressionDeclMap * + DeclMap () + { + return m_type_system_helper.DeclMap(); + } + + void + ResetDeclMap () + { + m_type_system_helper.ResetDeclMap(); + } + + void + ResetDeclMap (ExecutionContext & exe_ctx, Materializer::PersistentVariableDelegate &result_delegate, bool keep_result_in_memory) + { + m_type_system_helper.ResetDeclMap(exe_ctx, result_delegate, keep_result_in_memory); + } + + lldb::ExpressionVariableSP + GetResultAfterDematerialization(ExecutionContextScope *exe_scope) override; + +private: + //------------------------------------------------------------------ + /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the environment. + //------------------------------------------------------------------ + + void + ScanContext (ExecutionContext &exe_ctx, + lldb_private::Error &err) override; + + bool + AddArguments (ExecutionContext &exe_ctx, + std::vector &args, + lldb::addr_t struct_address, + Stream &error_stream) override; + + ClangUserExpressionHelper m_type_system_helper; + + class ResultDelegate : public Materializer::PersistentVariableDelegate + { + public: + ResultDelegate(); + ConstString GetName() override; + void DidDematerialize(lldb::ExpressionVariableSP &variable) override; + + void RegisterPersistentState(PersistentExpressionState *persistent_state); + lldb::ExpressionVariableSP &GetVariable(); + + private: + PersistentExpressionState *m_persistent_state; + lldb::ExpressionVariableSP m_variable; + }; + + ResultDelegate m_result_delegate; +}; + +} // namespace lldb_private + +#endif // liblldb_ClangUserExpression_h_ diff --git a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp new file mode 100644 index 0000000000000..fe044c17ac788 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -0,0 +1,189 @@ +//===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ClangExpressionDeclMap.h" +#include "ClangExpressionParser.h" +#include "ClangUtilityFunction.h" + +// C Includes +#include +#if HAVE_SYS_TYPES_H +# include +#endif + +// C++ Includes + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Expression/ExpressionSourceCode.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Host/Host.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Target.h" + +using namespace lldb_private; + +//------------------------------------------------------------------ +/// Constructor +/// +/// @param[in] text +/// The text of the function. Must be a full translation unit. +/// +/// @param[in] name +/// The name of the function, as used in the text. +//------------------------------------------------------------------ +ClangUtilityFunction::ClangUtilityFunction (ExecutionContextScope &exe_scope, + const char *text, + const char *name) : + UtilityFunction (exe_scope, text, name) +{ +} + +ClangUtilityFunction::~ClangUtilityFunction () +{ +} + +//------------------------------------------------------------------ +/// Install the utility function into a process +/// +/// @param[in] error_stream +/// A stream to print parse errors and warnings to. +/// +/// @param[in] exe_ctx +/// The execution context to install the utility function to. +/// +/// @return +/// True on success (no errors); false otherwise. +//------------------------------------------------------------------ +bool +ClangUtilityFunction::Install (Stream &error_stream, + ExecutionContext &exe_ctx) +{ + if (m_jit_start_addr != LLDB_INVALID_ADDRESS) + { + error_stream.PutCString("error: already installed\n"); + return false; + } + + //////////////////////////////////// + // Set up the target and compiler + // + + Target *target = exe_ctx.GetTargetPtr(); + + if (!target) + { + error_stream.PutCString ("error: invalid target\n"); + return false; + } + + Process *process = exe_ctx.GetProcessPtr(); + + if (!process) + { + error_stream.PutCString ("error: invalid process\n"); + return false; + } + + ////////////////////////// + // Parse the expression + // + + bool keep_result_in_memory = false; + + ResetDeclMap(exe_ctx, keep_result_in_memory); + + if (!DeclMap()->WillParse(exe_ctx, NULL)) + { + error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); + return false; + } + + const bool generate_debug_info = true; + ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info); + + unsigned num_errors = parser.Parse (error_stream); + + if (num_errors) + { + error_stream.Printf ("error: %d errors parsing expression\n", num_errors); + + ResetDeclMap(); + + return false; + } + + ////////////////////////////////// + // JIT the output of the parser + // + + bool can_interpret = false; // should stay that way + + Error jit_error = parser.PrepareForExecution (m_jit_start_addr, + m_jit_end_addr, + m_execution_unit_sp, + exe_ctx, + can_interpret, + eExecutionPolicyAlways); + + if (m_jit_start_addr != LLDB_INVALID_ADDRESS) + { + m_jit_process_wp = process->shared_from_this(); + if (parser.GetGenerateDebugInfo()) + { + lldb::ModuleSP jit_module_sp ( m_execution_unit_sp->GetJITModule()); + + if (jit_module_sp) + { + ConstString const_func_name(FunctionName()); + FileSpec jit_file; + jit_file.GetFilename() = const_func_name; + jit_module_sp->SetFileSpecAndObjectName (jit_file, ConstString()); + m_jit_module_wp = jit_module_sp; + target->GetImages().Append(jit_module_sp); + } + } + } + +#if 0 + // jingham: look here + StreamFile logfile ("/tmp/exprs.txt", "a"); + logfile.Printf ("0x%16.16" PRIx64 ": func = %s, source =\n%s\n", + m_jit_start_addr, + m_function_name.c_str(), + m_function_text.c_str()); +#endif + + DeclMap()->DidParse(); + + ResetDeclMap(); + + if (jit_error.Success()) + { + return true; + } + else + { + const char *error_cstr = jit_error.AsCString(); + if (error_cstr && error_cstr[0]) + error_stream.Printf ("error: %s\n", error_cstr); + else + error_stream.Printf ("error: expression can't be interpreted or run\n"); + return false; + } +} + +void +ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap(ExecutionContext &exe_ctx, bool keep_result_in_memory) +{ + m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, nullptr, exe_ctx)); +} diff --git a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h new file mode 100644 index 0000000000000..74839717946bc --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h @@ -0,0 +1,137 @@ +//===-- ClangUtilityFunction.h ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangUtilityFunction_h_ +#define liblldb_ClangUtilityFunction_h_ + +// C Includes +// C++ Includes +#include +#include +#include + +// Other libraries and framework includes +// Project includes +#include "ClangExpressionHelper.h" + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Expression/UtilityFunction.h" + +namespace lldb_private +{ + +//---------------------------------------------------------------------- +/// @class ClangUtilityFunction ClangUtilityFunction.h "lldb/Expression/ClangUtilityFunction.h" +/// @brief Encapsulates a single expression for use with Clang +/// +/// LLDB uses expressions for various purposes, notably to call functions +/// and as a backend for the expr command. ClangUtilityFunction encapsulates +/// a self-contained function meant to be used from other code. Utility +/// functions can perform error-checking for ClangUserExpressions, or can +/// simply provide a way to push a function into the target for the debugger to +/// call later on. +//---------------------------------------------------------------------- +class ClangUtilityFunction : public UtilityFunction +{ +public: + class ClangUtilityFunctionHelper : public ClangExpressionHelper + { + public: + ClangUtilityFunctionHelper () + { + } + + ~ClangUtilityFunctionHelper() override {} + + //------------------------------------------------------------------ + /// Return the object that the parser should use when resolving external + /// values. May be NULL if everything should be self-contained. + //------------------------------------------------------------------ + ClangExpressionDeclMap * + DeclMap() override + { + return m_expr_decl_map_up.get(); + } + + void + ResetDeclMap() + { + m_expr_decl_map_up.reset(); + } + + void + ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory); + + //------------------------------------------------------------------ + /// Return the object that the parser should allow to access ASTs. + /// May be NULL if the ASTs do not need to be transformed. + /// + /// @param[in] passthrough + /// The ASTConsumer that the returned transformer should send + /// the ASTs to after transformation. + //------------------------------------------------------------------ + clang::ASTConsumer * + ASTTransformer(clang::ASTConsumer *passthrough) override + { + return nullptr; + } + private: + std::unique_ptr m_expr_decl_map_up; + }; + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] text + /// The text of the function. Must be a full translation unit. + /// + /// @param[in] name + /// The name of the function, as used in the text. + //------------------------------------------------------------------ + ClangUtilityFunction (ExecutionContextScope &exe_scope, + const char *text, + const char *name); + + ~ClangUtilityFunction() override; + + ExpressionTypeSystemHelper * + GetTypeSystemHelper () override + { + return &m_type_system_helper; + } + + ClangExpressionDeclMap * + DeclMap() + { + return m_type_system_helper.DeclMap(); + } + + void + ResetDeclMap () + { + m_type_system_helper.ResetDeclMap(); + } + + void + ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory) + { + m_type_system_helper.ResetDeclMap(exe_ctx, keep_result_in_memory); + } + + bool + Install (Stream &error_stream, ExecutionContext &exe_ctx) override; + +private: + ClangUtilityFunctionHelper m_type_system_helper; ///< The map to use when parsing and materializing the expression. +}; + +} // namespace lldb_private + +#endif // liblldb_ClangUtilityFunction_h_ diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp new file mode 100644 index 0000000000000..37b7bd1d2c84e --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp @@ -0,0 +1,2820 @@ +//===-- IRForTarget.cpp -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "IRForTarget.h" + +#include "ClangExpressionDeclMap.h" + +#include "llvm/Support/raw_ostream.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/IR/Metadata.h" +#include "llvm/IR/ValueSymbolTable.h" + +#include "clang/AST/ASTContext.h" + +#include "lldb/Core/dwarf.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Scalar.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Expression/IRInterpreter.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Target/CPPLanguageRuntime.h" + +#include + +using namespace llvm; + +static char ID; + +IRForTarget::StaticDataAllocator::StaticDataAllocator(lldb_private::IRExecutionUnit &execution_unit) : + m_execution_unit(execution_unit), + m_stream_string(lldb_private::Stream::eBinary, execution_unit.GetAddressByteSize(), execution_unit.GetByteOrder()), + m_allocation(LLDB_INVALID_ADDRESS) +{ +} + +IRForTarget::FunctionValueCache::FunctionValueCache(Maker const &maker) : + m_maker(maker), + m_values() +{ +} + +IRForTarget::FunctionValueCache::~FunctionValueCache() +{ +} + +llvm::Value * +IRForTarget::FunctionValueCache::GetValue(llvm::Function *function) +{ + if (!m_values.count(function)) + { + llvm::Value *ret = m_maker(function); + m_values[function] = ret; + return ret; + } + return m_values[function]; +} + +lldb::addr_t +IRForTarget::StaticDataAllocator::Allocate() +{ + lldb_private::Error err; + + if (m_allocation != LLDB_INVALID_ADDRESS) + { + m_execution_unit.FreeNow(m_allocation); + m_allocation = LLDB_INVALID_ADDRESS; + } + + m_allocation = m_execution_unit.WriteNow((const uint8_t*)m_stream_string.GetData(), m_stream_string.GetSize(), err); + + return m_allocation; +} + +lldb::TargetSP +IRForTarget::StaticDataAllocator::GetTarget() +{ + return m_execution_unit.GetTarget(); +} + +static llvm::Value * +FindEntryInstruction (llvm::Function *function) +{ + if (function->empty()) + return NULL; + + return function->getEntryBlock().getFirstNonPHIOrDbg(); +} + +IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map, + bool resolve_vars, + lldb_private::IRExecutionUnit &execution_unit, + lldb_private::Stream *error_stream, + const char *func_name) : + ModulePass(ID), + m_resolve_vars(resolve_vars), + m_func_name(func_name), + m_module(NULL), + m_decl_map(decl_map), + m_data_allocator(execution_unit), + m_CFStringCreateWithBytes(NULL), + m_sel_registerName(NULL), + m_intptr_ty(NULL), + m_error_stream(error_stream), + m_result_store(NULL), + m_result_is_pointer(false), + m_reloc_placeholder(NULL), + m_entry_instruction_finder (FindEntryInstruction) +{ +} + +/* Handy utility functions used at several places in the code */ + +static std::string +PrintValue(const Value *value, bool truncate = false) +{ + std::string s; + if (value) + { + raw_string_ostream rso(s); + value->print(rso); + rso.flush(); + if (truncate) + s.resize(s.length() - 1); + } + return s; +} + +static std::string +PrintType(const llvm::Type *type, bool truncate = false) +{ + std::string s; + raw_string_ostream rso(s); + type->print(rso); + rso.flush(); + if (truncate) + s.resize(s.length() - 1); + return s; +} + +IRForTarget::~IRForTarget() +{ +} + +bool +IRForTarget::FixFunctionLinkage(llvm::Function &llvm_function) +{ + llvm_function.setLinkage(GlobalValue::ExternalLinkage); + + std::string name = llvm_function.getName().str(); + + return true; +} + +IRForTarget::LookupResult +IRForTarget::GetFunctionAddress (llvm::Function *fun, + uint64_t &fun_addr, + lldb_private::ConstString &name, + Constant **&value_ptr) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + fun_addr = LLDB_INVALID_ADDRESS; + name.Clear(); + value_ptr = NULL; + + if (fun->isIntrinsic()) + { + Intrinsic::ID intrinsic_id = (Intrinsic::ID)fun->getIntrinsicID(); + + switch (intrinsic_id) + { + default: + if (log) + log->Printf("Unresolved intrinsic \"%s\"", Intrinsic::getName(intrinsic_id).c_str()); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Call to unhandled compiler intrinsic '%s'\n", Intrinsic::getName(intrinsic_id).c_str()); + + return LookupResult::Fail; + case Intrinsic::memcpy: + { + static lldb_private::ConstString g_memcpy_str ("memcpy"); + name = g_memcpy_str; + } + break; + case Intrinsic::memset: + { + static lldb_private::ConstString g_memset_str ("memset"); + name = g_memset_str; + } + break; + case Intrinsic::dbg_declare: + case Intrinsic::dbg_value: + return LookupResult::Ignore; + } + + if (log && name) + log->Printf("Resolved intrinsic name \"%s\"", name.GetCString()); + } + else + { + name.SetCStringWithLength (fun->getName().data(), fun->getName().size()); + } + + // Find the address of the function. + + clang::NamedDecl *fun_decl = DeclForGlobal (fun); + + if (fun_decl) + { + if (!m_decl_map->GetFunctionInfo (fun_decl, fun_addr)) + { + std::vector alternates; + bool found_it = m_decl_map->GetFunctionAddress (name, fun_addr); + if (!found_it) + { + if (log) + log->Printf("Address of function \"%s\" not found.\n", name.GetCString()); + // Check for an alternate mangling for names from the standard library. + // For example, "std::basic_string<...>" has an alternate mangling scheme per + // the Itanium C++ ABI. + lldb::ProcessSP process_sp = m_data_allocator.GetTarget()->GetProcessSP(); + if (process_sp) + { + lldb_private::CPPLanguageRuntime *cpp_runtime = process_sp->GetCPPLanguageRuntime(); + if (cpp_runtime && cpp_runtime->GetAlternateManglings(name, alternates)) + { + for (size_t i = 0; i < alternates.size(); ++i) + { + const lldb_private::ConstString &alternate_name = alternates[i]; + if (log) + log->Printf("Looking up address of function \"%s\" with alternate name \"%s\"", + name.GetCString(), alternate_name.GetCString()); + if ((found_it = m_decl_map->GetFunctionAddress (alternate_name, fun_addr))) + { + if (log) + log->Printf("Found address of function \"%s\" with alternate name \"%s\"", + name.GetCString(), alternate_name.GetCString()); + break; + } + } + } + } + } + + if (!found_it) + { + lldb_private::Mangled mangled_name(name); + if (m_error_stream) + { + if (mangled_name.GetMangledName()) + m_error_stream->Printf("error: call to a function '%s' ('%s') that is not present in the target\n", + mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString(), + mangled_name.GetMangledName().GetCString()); + else + m_error_stream->Printf("error: call to a function '%s' that is not present in the target\n", + mangled_name.GetName(lldb::eLanguageTypeObjC_plus_plus).GetCString()); + } + return LookupResult::Fail; + } + } + } + else + { + if (!m_decl_map->GetFunctionAddress (name, fun_addr)) + { + if (log) + log->Printf ("Metadataless function \"%s\" had no address", name.GetCString()); + + if (m_error_stream) + m_error_stream->Printf("Error [IRForTarget]: Call to a symbol-only function '%s' that is not present in the target\n", name.GetCString()); + + return LookupResult::Fail; + } + } + + if (log) + log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), fun_addr); + + return LookupResult::Success; +} + +llvm::Constant * +IRForTarget::BuildFunctionPointer (llvm::Type *type, + uint64_t ptr) +{ + PointerType *fun_ptr_ty = PointerType::getUnqual(type); + Constant *fun_addr_int = ConstantInt::get(m_intptr_ty, ptr, false); + return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty); +} + +void +IRForTarget::RegisterFunctionMetadata(LLVMContext &context, + llvm::Value *function_ptr, + const char *name) +{ + for (llvm::User *user : function_ptr->users()) + { + if (Instruction *user_inst = dyn_cast(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) +{ + NamedMDNode *named_metadata = module->getNamedMetadata("clang.global.decl.ptrs"); + + if (!named_metadata) + return NULL; + + unsigned num_nodes = named_metadata->getNumOperands(); + unsigned node_index; + + for (node_index = 0; + node_index < num_nodes; + ++node_index) + { + llvm::MDNode *metadata_node = dyn_cast(named_metadata->getOperand(node_index)); + if (!metadata_node) + return NULL; + + if (metadata_node->getNumOperands() != 2) + continue; + + if (mdconst::dyn_extract_or_null(metadata_node->getOperand(0)) != global_val) + continue; + + ConstantInt *constant_int = mdconst::dyn_extract(metadata_node->getOperand(1)); + + if (!constant_int) + return NULL; + + uintptr_t ptr = constant_int->getZExtValue(); + + return reinterpret_cast(ptr); + } + + return NULL; +} + +clang::NamedDecl * +IRForTarget::DeclForGlobal (GlobalValue *global_val) +{ + return DeclForGlobal(global_val, m_module); +} + +bool +IRForTarget::CreateResultVariable (llvm::Function &llvm_function) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (!m_resolve_vars) + return true; + + // Find the result variable. If it doesn't exist, we can give up right here. + + ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable(); + + std::string result_name_str; + const char *result_name = NULL; + + for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end(); + vi != ve; + ++vi) + { + result_name_str = vi->first().str(); + const char *value_name = result_name_str.c_str(); + + if (strstr(value_name, "$__lldb_expr_result_ptr") && + strncmp(value_name, "_ZGV", 4)) + { + result_name = value_name; + m_result_is_pointer = true; + break; + } + + if (strstr(value_name, "$__lldb_expr_result") && + strncmp(value_name, "_ZGV", 4)) + { + result_name = value_name; + m_result_is_pointer = false; + break; + } + } + + if (!result_name) + { + if (log) + log->PutCString("Couldn't find result variable"); + + return true; + } + + if (log) + log->Printf("Result name: \"%s\"", result_name); + + Value *result_value = m_module->getNamedValue(result_name); + + if (!result_value) + { + if (log) + log->PutCString("Result variable had no data"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Result variable's name (%s) exists, but not its definition\n", result_name); + + return false; + } + + if (log) + log->Printf("Found result in the IR: \"%s\"", PrintValue(result_value, false).c_str()); + + GlobalVariable *result_global = dyn_cast(result_value); + + if (!result_global) + { + if (log) + log->PutCString("Result variable isn't a GlobalVariable"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) is defined, but is not a global variable\n", result_name); + + return false; + } + + clang::NamedDecl *result_decl = DeclForGlobal (result_global); + if (!result_decl) + { + if (log) + log->PutCString("Result variable doesn't have a corresponding Decl"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) does not have a corresponding Clang entity\n", result_name); + + return false; + } + + if (log) + { + std::string decl_desc_str; + raw_string_ostream decl_desc_stream(decl_desc_str); + result_decl->print(decl_desc_stream); + decl_desc_stream.flush(); + + log->Printf("Found result decl: \"%s\"", decl_desc_str.c_str()); + } + + clang::VarDecl *result_var = dyn_cast(result_decl); + if (!result_var) + { + if (log) + log->PutCString("Result variable Decl isn't a VarDecl"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s)'s corresponding Clang entity isn't a variable\n", result_name); + + return false; + } + + // Get the next available result name from m_decl_map and create the persistent + // variable for it + + // If the result is an Lvalue, it is emitted as a pointer; see + // ASTResultSynthesizer::SynthesizeBodyResult. + if (m_result_is_pointer) + { + clang::QualType pointer_qual_type = result_var->getType(); + const clang::Type *pointer_type = pointer_qual_type.getTypePtr(); + + const clang::PointerType *pointer_pointertype = pointer_type->getAs(); + const clang::ObjCObjectPointerType *pointer_objcobjpointertype = pointer_type->getAs(); + + if (pointer_pointertype) + { + clang::QualType element_qual_type = pointer_pointertype->getPointeeType(); + + m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(), + lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext())); + } + else if (pointer_objcobjpointertype) + { + clang::QualType element_qual_type = clang::QualType(pointer_objcobjpointertype->getObjectType(), 0); + + m_result_type = lldb_private::TypeFromParser(element_qual_type.getAsOpaquePtr(), + lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext())); + } + else + { + if (log) + log->PutCString("Expected result to have pointer type, but it did not"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Lvalue result (%s) is not a pointer variable\n", result_name); + + return false; + } + } + else + { + m_result_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(), + lldb_private::ClangASTContext::GetASTContext(&result_decl->getASTContext())); + } + + + lldb::TargetSP target_sp (m_data_allocator.GetTarget()); + lldb_private::ExecutionContext exe_ctx (target_sp, true); + if (m_result_type.GetBitSize(exe_ctx.GetBestExecutionContextScope()) == 0) + { + lldb_private::StreamString type_desc_stream; + m_result_type.DumpTypeDescription(&type_desc_stream); + + if (log) + log->Printf("Result type has size 0"); + + if (m_error_stream) + m_error_stream->Printf("Error [IRForTarget]: Size of result type '%s' couldn't be determined\n", + type_desc_stream.GetData()); + return false; + } + + if (log) + { + lldb_private::StreamString type_desc_stream; + m_result_type.DumpTypeDescription(&type_desc_stream); + + log->Printf("Result decl type: \"%s\"", type_desc_stream.GetData()); + } + + m_result_name = lldb_private::ConstString("$RESULT_NAME"); + + if (log) + log->Printf("Creating a new result global: \"%s\" with size 0x%" PRIx64, + m_result_name.GetCString(), + m_result_type.GetByteSize(nullptr)); + + // Construct a new result global and set up its metadata + + GlobalVariable *new_result_global = new GlobalVariable((*m_module), + result_global->getType()->getElementType(), + false, /* not constant */ + GlobalValue::ExternalLinkage, + NULL, /* no initializer */ + m_result_name.GetCString ()); + + // It's too late in compilation to create a new VarDecl for this, but we don't + // need to. We point the metadata at the old VarDecl. This creates an odd + // anomaly: a variable with a Value whose name is something like $0 and a + // Decl whose name is $__lldb_expr_result. This condition is handled in + // ClangExpressionDeclMap::DoMaterialize, and the name of the variable is + // fixed up. + + ConstantInt *new_constant_int = ConstantInt::get(llvm::Type::getInt64Ty(m_module->getContext()), + reinterpret_cast(result_decl), + false); + + llvm::Metadata *values[2]; + values[0] = ConstantAsMetadata::get(new_result_global); + values[1] = ConstantAsMetadata::get(new_constant_int); + + ArrayRef value_ref(values, 2); + + MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); + NamedMDNode *named_metadata = m_module->getNamedMetadata("clang.global.decl.ptrs"); + named_metadata->addOperand(persistent_global_md); + + if (log) + log->Printf("Replacing \"%s\" with \"%s\"", + PrintValue(result_global).c_str(), + PrintValue(new_result_global).c_str()); + + if (result_global->use_empty()) + { + // We need to synthesize a store for this variable, because otherwise + // there's nothing to put into its equivalent persistent variable. + + BasicBlock &entry_block(llvm_function.getEntryBlock()); + Instruction *first_entry_instruction(entry_block.getFirstNonPHIOrDbg()); + + if (!first_entry_instruction) + return false; + + if (!result_global->hasInitializer()) + { + if (log) + log->Printf("Couldn't find initializer for unused variable"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) has no writes and no initializer\n", result_name); + + return false; + } + + Constant *initializer = result_global->getInitializer(); + + StoreInst *synthesized_store = new StoreInst(initializer, + new_result_global, + first_entry_instruction); + + if (log) + log->Printf("Synthesized result store \"%s\"\n", PrintValue(synthesized_store).c_str()); + } + else + { + result_global->replaceAllUsesWith(new_result_global); + } + + if (!m_decl_map->AddPersistentVariable(result_decl, + m_result_name, + m_result_type, + true, + m_result_is_pointer)) + return false; + + result_global->eraseFromParent(); + + return true; +} + +bool +IRForTarget::RewriteObjCConstString (llvm::GlobalVariable *ns_str, + llvm::GlobalVariable *cstr) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + Type *ns_str_ty = ns_str->getType(); + + Type *i8_ptr_ty = Type::getInt8PtrTy(m_module->getContext()); + Type *i32_ty = Type::getInt32Ty(m_module->getContext()); + Type *i8_ty = Type::getInt8Ty(m_module->getContext()); + + if (!m_CFStringCreateWithBytes) + { + lldb::addr_t CFStringCreateWithBytes_addr; + + static lldb_private::ConstString g_CFStringCreateWithBytes_str ("CFStringCreateWithBytes"); + + if (!m_decl_map->GetFunctionAddress (g_CFStringCreateWithBytes_str, CFStringCreateWithBytes_addr)) + { + if (log) + log->PutCString("Couldn't find CFStringCreateWithBytes in the target"); + + if (m_error_stream) + m_error_stream->Printf("Error [IRForTarget]: Rewriting an Objective-C constant string requires CFStringCreateWithBytes\n"); + + return false; + } + + if (log) + log->Printf("Found CFStringCreateWithBytes at 0x%" PRIx64, CFStringCreateWithBytes_addr); + + // Build the function type: + // + // CFStringRef CFStringCreateWithBytes ( + // CFAllocatorRef alloc, + // const UInt8 *bytes, + // CFIndex numBytes, + // CFStringEncoding encoding, + // Boolean isExternalRepresentation + // ); + // + // We make the following substitutions: + // + // CFStringRef -> i8* + // CFAllocatorRef -> i8* + // UInt8 * -> i8* + // CFIndex -> long (i32 or i64, as appropriate; we ask the module for its pointer size for now) + // CFStringEncoding -> i32 + // Boolean -> i8 + + Type *arg_type_array[5]; + + arg_type_array[0] = i8_ptr_ty; + arg_type_array[1] = i8_ptr_ty; + arg_type_array[2] = m_intptr_ty; + arg_type_array[3] = i32_ty; + arg_type_array[4] = i8_ty; + + ArrayRef CFSCWB_arg_types(arg_type_array, 5); + + llvm::Type *CFSCWB_ty = FunctionType::get(ns_str_ty, CFSCWB_arg_types, false); + + // Build the constant containing the pointer to the function + PointerType *CFSCWB_ptr_ty = PointerType::getUnqual(CFSCWB_ty); + Constant *CFSCWB_addr_int = ConstantInt::get(m_intptr_ty, CFStringCreateWithBytes_addr, false); + m_CFStringCreateWithBytes = ConstantExpr::getIntToPtr(CFSCWB_addr_int, CFSCWB_ptr_ty); + } + + ConstantDataSequential *string_array = NULL; + + if (cstr) + string_array = dyn_cast(cstr->getInitializer()); + + Constant *alloc_arg = Constant::getNullValue(i8_ptr_ty); + Constant *bytes_arg = cstr ? ConstantExpr::getBitCast(cstr, i8_ptr_ty) : Constant::getNullValue(i8_ptr_ty); + Constant *numBytes_arg = ConstantInt::get(m_intptr_ty, cstr ? string_array->getNumElements() - 1 : 0, false); + Constant *encoding_arg = ConstantInt::get(i32_ty, 0x0600, false); /* 0x0600 is kCFStringEncodingASCII */ + Constant *isExternal_arg = ConstantInt::get(i8_ty, 0x0, false); /* 0x0 is false */ + + Value *argument_array[5]; + + argument_array[0] = alloc_arg; + argument_array[1] = bytes_arg; + argument_array[2] = numBytes_arg; + argument_array[3] = encoding_arg; + argument_array[4] = isExternal_arg; + + ArrayRef CFSCWB_arguments(argument_array, 5); + + FunctionValueCache CFSCWB_Caller ([this, &CFSCWB_arguments] (llvm::Function *function)->llvm::Value * { + return CallInst::Create(m_CFStringCreateWithBytes, + CFSCWB_arguments, + "CFStringCreateWithBytes", + llvm::cast(m_entry_instruction_finder.GetValue(function))); + }); + + if (!UnfoldConstant(ns_str, CFSCWB_Caller, m_entry_instruction_finder)) + { + if (log) + log->PutCString("Couldn't replace the NSString with the result of the call"); + + if (m_error_stream) + m_error_stream->Printf("Error [IRForTarget]: Couldn't replace an Objective-C constant string with a dynamic string\n"); + + return false; + } + + ns_str->eraseFromParent(); + + return true; +} + +bool +IRForTarget::RewriteObjCConstStrings() +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + ValueSymbolTable& value_symbol_table = m_module->getValueSymbolTable(); + + for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end(); + vi != ve; + ++vi) + { + std::string value_name = vi->first().str(); + const char *value_name_cstr = value_name.c_str(); + + if (strstr(value_name_cstr, "_unnamed_cfstring_")) + { + Value *nsstring_value = vi->second; + + GlobalVariable *nsstring_global = dyn_cast(nsstring_value); + + if (!nsstring_global) + { + if (log) + log->PutCString("NSString variable is not a GlobalVariable"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string is not a global variable\n"); + + return false; + } + + if (!nsstring_global->hasInitializer()) + { + if (log) + log->PutCString("NSString variable does not have an initializer"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string does not have an initializer\n"); + + return false; + } + + ConstantStruct *nsstring_struct = dyn_cast(nsstring_global->getInitializer()); + + if (!nsstring_struct) + { + if (log) + log->PutCString("NSString variable's initializer is not a ConstantStruct"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string is not a structure constant\n"); + + return false; + } + + // We expect the following structure: + // + // struct { + // int *isa; + // int flags; + // char *str; + // long length; + // }; + + if (nsstring_struct->getNumOperands() != 4) + { + if (log) + log->Printf("NSString variable's initializer structure has an unexpected number of members. Should be 4, is %d", nsstring_struct->getNumOperands()); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: The struct for an Objective-C constant string is not as expected\n"); + + return false; + } + + Constant *nsstring_member = nsstring_struct->getOperand(2); + + if (!nsstring_member) + { + if (log) + log->PutCString("NSString initializer's str element was empty"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string does not have a string initializer\n"); + + return false; + } + + ConstantExpr *nsstring_expr = dyn_cast(nsstring_member); + + if (!nsstring_expr) + { + if (log) + log->PutCString("NSString initializer's str element is not a ConstantExpr"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer is not constant\n"); + + return false; + } + + if (nsstring_expr->getOpcode() != Instruction::GetElementPtr) + { + if (log) + log->Printf("NSString initializer's str element is not a GetElementPtr expression, it's a %s", nsstring_expr->getOpcodeName()); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer is not an array\n"); + + return false; + } + + Constant *nsstring_cstr = nsstring_expr->getOperand(0); + + GlobalVariable *cstr_global = dyn_cast(nsstring_cstr); + + if (!cstr_global) + { + if (log) + log->PutCString("NSString initializer's str element is not a GlobalVariable"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a global\n"); + + return false; + } + + if (!cstr_global->hasInitializer()) + { + if (log) + log->PutCString("NSString initializer's str element does not have an initializer"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to initialized data\n"); + + return false; + } + + /* + if (!cstr_array) + { + if (log) + log->PutCString("NSString initializer's str element is not a ConstantArray"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to an array\n"); + + return false; + } + + if (!cstr_array->isCString()) + { + if (log) + log->PutCString("NSString initializer's str element is not a C string array"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: An Objective-C constant string's string initializer doesn't point to a C string\n"); + + return false; + } + */ + + ConstantDataArray *cstr_array = dyn_cast(cstr_global->getInitializer()); + + if (log) + { + if (cstr_array) + log->Printf("Found NSString constant %s, which contains \"%s\"", value_name_cstr, cstr_array->getAsString().str().c_str()); + else + log->Printf("Found NSString constant %s, which contains \"\"", value_name_cstr); + } + + if (!cstr_array) + cstr_global = NULL; + + if (!RewriteObjCConstString(nsstring_global, cstr_global)) + { + if (log) + log->PutCString("Error rewriting the constant string"); + + // We don't print an error message here because RewriteObjCConstString has done so for us. + + return false; + } + } + } + + for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end(); + vi != ve; + ++vi) + { + std::string value_name = vi->first().str(); + const char *value_name_cstr = value_name.c_str(); + + if (!strcmp(value_name_cstr, "__CFConstantStringClassReference")) + { + GlobalVariable *gv = dyn_cast(vi->second); + + if (!gv) + { + if (log) + log->PutCString("__CFConstantStringClassReference is not a global variable"); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Found a CFConstantStringClassReference, but it is not a global object\n"); + + return false; + } + + gv->eraseFromParent(); + + break; + } + } + + return true; +} + +static bool IsObjCSelectorRef (Value *value) +{ + GlobalVariable *global_variable = dyn_cast(value); + + if (!global_variable || !global_variable->hasName() || !global_variable->getName().startswith("OBJC_SELECTOR_REFERENCES_")) + return false; + + return true; +} + +// This function does not report errors; its callers are responsible. +bool +IRForTarget::RewriteObjCSelector (Instruction* selector_load) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + LoadInst *load = dyn_cast(selector_load); + + if (!load) + return false; + + // Unpack the message name from the selector. In LLVM IR, an objc_msgSend gets represented as + // + // %tmp = load i8** @"OBJC_SELECTOR_REFERENCES_" ; + // %call = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %obj, i8* %tmp, ...) ; + // + // where %obj is the object pointer and %tmp is the selector. + // + // @"OBJC_SELECTOR_REFERENCES_" is a pointer to a character array called @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_". + // @"\01L_OBJC_llvm_moduleETH_VAR_NAllvm_moduleE_" contains the string. + + // Find the pointer's initializer (a ConstantExpr with opcode GetElementPtr) and get the string from its target + + GlobalVariable *_objc_selector_references_ = dyn_cast(load->getPointerOperand()); + + if (!_objc_selector_references_ || !_objc_selector_references_->hasInitializer()) + return false; + + Constant *osr_initializer = _objc_selector_references_->getInitializer(); + + ConstantExpr *osr_initializer_expr = dyn_cast(osr_initializer); + + if (!osr_initializer_expr || osr_initializer_expr->getOpcode() != Instruction::GetElementPtr) + return false; + + Value *osr_initializer_base = osr_initializer_expr->getOperand(0); + + if (!osr_initializer_base) + return false; + + // Find the string's initializer (a ConstantArray) and get the string from it + + GlobalVariable *_objc_meth_var_name_ = dyn_cast(osr_initializer_base); + + if (!_objc_meth_var_name_ || !_objc_meth_var_name_->hasInitializer()) + return false; + + Constant *omvn_initializer = _objc_meth_var_name_->getInitializer(); + + ConstantDataArray *omvn_initializer_array = dyn_cast(omvn_initializer); + + if (!omvn_initializer_array->isString()) + return false; + + std::string omvn_initializer_string = omvn_initializer_array->getAsString(); + + if (log) + log->Printf("Found Objective-C selector reference \"%s\"", omvn_initializer_string.c_str()); + + // Construct a call to sel_registerName + + if (!m_sel_registerName) + { + lldb::addr_t sel_registerName_addr; + + static lldb_private::ConstString g_sel_registerName_str ("sel_registerName"); + if (!m_decl_map->GetFunctionAddress (g_sel_registerName_str, sel_registerName_addr)) + return false; + + if (log) + log->Printf("Found sel_registerName at 0x%" PRIx64, sel_registerName_addr); + + // Build the function type: struct objc_selector *sel_registerName(uint8_t*) + + // The below code would be "more correct," but in actuality what's required is uint8_t* + //Type *sel_type = StructType::get(m_module->getContext()); + //Type *sel_ptr_type = PointerType::getUnqual(sel_type); + Type *sel_ptr_type = Type::getInt8PtrTy(m_module->getContext()); + + Type *type_array[1]; + + type_array[0] = llvm::Type::getInt8PtrTy(m_module->getContext()); + + ArrayRef srN_arg_types(type_array, 1); + + llvm::Type *srN_type = FunctionType::get(sel_ptr_type, srN_arg_types, false); + + // Build the constant containing the pointer to the function + PointerType *srN_ptr_ty = PointerType::getUnqual(srN_type); + Constant *srN_addr_int = ConstantInt::get(m_intptr_ty, sel_registerName_addr, false); + m_sel_registerName = ConstantExpr::getIntToPtr(srN_addr_int, srN_ptr_ty); + } + + Value *argument_array[1]; + + Constant *omvn_pointer = ConstantExpr::getBitCast(_objc_meth_var_name_, Type::getInt8PtrTy(m_module->getContext())); + + argument_array[0] = omvn_pointer; + + ArrayRef srN_arguments(argument_array, 1); + + CallInst *srN_call = CallInst::Create(m_sel_registerName, + srN_arguments, + "sel_registerName", + selector_load); + + // Replace the load with the call in all users + + selector_load->replaceAllUsesWith(srN_call); + + selector_load->eraseFromParent(); + + return true; +} + +bool +IRForTarget::RewriteObjCSelectors (BasicBlock &basic_block) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + BasicBlock::iterator ii; + + typedef SmallVector InstrList; + typedef InstrList::iterator InstrIterator; + + InstrList selector_loads; + + for (ii = basic_block.begin(); + ii != basic_block.end(); + ++ii) + { + Instruction &inst = *ii; + + if (LoadInst *load = dyn_cast(&inst)) + if (IsObjCSelectorRef(load->getPointerOperand())) + selector_loads.push_back(&inst); + } + + InstrIterator iter; + + for (iter = selector_loads.begin(); + iter != selector_loads.end(); + ++iter) + { + if (!RewriteObjCSelector(*iter)) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Couldn't change a static reference to an Objective-C selector to a dynamic reference\n"); + + if (log) + log->PutCString("Couldn't rewrite a reference to an Objective-C selector"); + + return false; + } + } + + return true; +} + +// This function does not report errors; its callers are responsible. +bool +IRForTarget::RewritePersistentAlloc (llvm::Instruction *persistent_alloc) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + AllocaInst *alloc = dyn_cast(persistent_alloc); + + MDNode *alloc_md = alloc->getMetadata("clang.decl.ptr"); + + if (!alloc_md || !alloc_md->getNumOperands()) + return false; + + ConstantInt *constant_int = mdconst::dyn_extract(alloc_md->getOperand(0)); + + if (!constant_int) + return false; + + // We attempt to register this as a new persistent variable with the DeclMap. + + uintptr_t ptr = constant_int->getZExtValue(); + + clang::VarDecl *decl = reinterpret_cast(ptr); + + lldb_private::TypeFromParser result_decl_type (decl->getType().getAsOpaquePtr(), + lldb_private::ClangASTContext::GetASTContext(&decl->getASTContext())); + + StringRef decl_name (decl->getName()); + lldb_private::ConstString persistent_variable_name (decl_name.data(), decl_name.size()); + if (!m_decl_map->AddPersistentVariable(decl, persistent_variable_name, result_decl_type, false, false)) + return false; + + GlobalVariable *persistent_global = new GlobalVariable((*m_module), + alloc->getType(), + false, /* not constant */ + GlobalValue::ExternalLinkage, + NULL, /* no initializer */ + alloc->getName().str().c_str()); + + // What we're going to do here is make believe this was a regular old external + // variable. That means we need to make the metadata valid. + + NamedMDNode *named_metadata = m_module->getOrInsertNamedMetadata("clang.global.decl.ptrs"); + + llvm::Metadata *values[2]; + values[0] = ConstantAsMetadata::get(persistent_global); + values[1] = ConstantAsMetadata::get(constant_int); + + ArrayRef value_ref(values, 2); + + MDNode *persistent_global_md = MDNode::get(m_module->getContext(), value_ref); + named_metadata->addOperand(persistent_global_md); + + // Now, since the variable is a pointer variable, we will drop in a load of that + // pointer variable. + + LoadInst *persistent_load = new LoadInst (persistent_global, "", alloc); + + if (log) + log->Printf("Replacing \"%s\" with \"%s\"", + PrintValue(alloc).c_str(), + PrintValue(persistent_load).c_str()); + + alloc->replaceAllUsesWith(persistent_load); + alloc->eraseFromParent(); + + return true; +} + +bool +IRForTarget::RewritePersistentAllocs(llvm::BasicBlock &basic_block) +{ + if (!m_resolve_vars) + return true; + + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + BasicBlock::iterator ii; + + typedef SmallVector InstrList; + typedef InstrList::iterator InstrIterator; + + InstrList pvar_allocs; + + for (ii = basic_block.begin(); + ii != basic_block.end(); + ++ii) + { + Instruction &inst = *ii; + + if (AllocaInst *alloc = dyn_cast(&inst)) + { + llvm::StringRef alloc_name = alloc->getName(); + + if (alloc_name.startswith("$") && + !alloc_name.startswith("$__lldb")) + { + if (alloc_name.find_first_of("0123456789") == 1) + { + if (log) + log->Printf("Rejecting a numeric persistent variable."); + + if (m_error_stream) + m_error_stream->Printf("Error [IRForTarget]: Names starting with $0, $1, ... are reserved for use as result names\n"); + + return false; + } + + pvar_allocs.push_back(alloc); + } + } + } + + InstrIterator iter; + + for (iter = pvar_allocs.begin(); + iter != pvar_allocs.end(); + ++iter) + { + if (!RewritePersistentAlloc(*iter)) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite the creation of a persistent variable\n"); + + if (log) + log->PutCString("Couldn't rewrite the creation of a persistent variable"); + + return false; + } + } + + return true; +} + +bool +IRForTarget::MaterializeInitializer (uint8_t *data, Constant *initializer) +{ + if (!initializer) + return true; + + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log && log->GetVerbose()) + log->Printf(" MaterializeInitializer(%p, %s)", (void *)data, PrintValue(initializer).c_str()); + + Type *initializer_type = initializer->getType(); + + if (ConstantInt *int_initializer = dyn_cast(initializer)) + { + memcpy (data, int_initializer->getValue().getRawData(), m_target_data->getTypeStoreSize(initializer_type)); + return true; + } + else if (ConstantDataArray *array_initializer = dyn_cast(initializer)) + { + if (array_initializer->isString()) + { + std::string array_initializer_string = array_initializer->getAsString(); + memcpy (data, array_initializer_string.c_str(), m_target_data->getTypeStoreSize(initializer_type)); + } + else + { + ArrayType *array_initializer_type = array_initializer->getType(); + Type *array_element_type = array_initializer_type->getElementType(); + + size_t element_size = m_target_data->getTypeAllocSize(array_element_type); + + for (unsigned i = 0; i < array_initializer->getNumOperands(); ++i) + { + Value *operand_value = array_initializer->getOperand(i); + Constant *operand_constant = dyn_cast(operand_value); + + if (!operand_constant) + return false; + + if (!MaterializeInitializer(data + (i * element_size), operand_constant)) + return false; + } + } + return true; + } + else if (ConstantStruct *struct_initializer = dyn_cast(initializer)) + { + StructType *struct_initializer_type = struct_initializer->getType(); + const StructLayout *struct_layout = m_target_data->getStructLayout(struct_initializer_type); + + for (unsigned i = 0; + i < struct_initializer->getNumOperands(); + ++i) + { + if (!MaterializeInitializer(data + struct_layout->getElementOffset(i), struct_initializer->getOperand(i))) + return false; + } + return true; + } + else if (isa(initializer)) + { + memset(data, 0, m_target_data->getTypeStoreSize(initializer_type)); + return true; + } + return false; +} + +bool +IRForTarget::MaterializeInternalVariable (GlobalVariable *global_variable) +{ + if (GlobalVariable::isExternalLinkage(global_variable->getLinkage())) + return false; + + if (global_variable == m_reloc_placeholder) + return true; + + uint64_t offset = m_data_allocator.GetStream().GetSize(); + + llvm::Type *variable_type = global_variable->getType(); + + Constant *initializer = global_variable->getInitializer(); + + llvm::Type *initializer_type = initializer->getType(); + + size_t size = m_target_data->getTypeAllocSize(initializer_type); + size_t align = m_target_data->getPrefTypeAlignment(initializer_type); + + const size_t mask = (align - 1); + uint64_t aligned_offset = (offset + mask) & ~mask; + m_data_allocator.GetStream().PutNHex8(aligned_offset - offset, 0); + offset = aligned_offset; + + lldb_private::DataBufferHeap data(size, '\0'); + + if (initializer) + if (!MaterializeInitializer(data.GetBytes(), initializer)) + return false; + + m_data_allocator.GetStream().Write(data.GetBytes(), data.GetByteSize()); + + Constant *new_pointer = BuildRelocation(variable_type, offset); + + global_variable->replaceAllUsesWith(new_pointer); + + global_variable->eraseFromParent(); + + return true; +} + +// This function does not report errors; its callers are responsible. +bool +IRForTarget::MaybeHandleVariable (Value *llvm_value_ptr) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf("MaybeHandleVariable (%s)", PrintValue(llvm_value_ptr).c_str()); + + if (ConstantExpr *constant_expr = dyn_cast(llvm_value_ptr)) + { + switch (constant_expr->getOpcode()) + { + default: + break; + case Instruction::GetElementPtr: + case Instruction::BitCast: + Value *s = constant_expr->getOperand(0); + if (!MaybeHandleVariable(s)) + return false; + } + } + else if (GlobalVariable *global_variable = dyn_cast(llvm_value_ptr)) + { + if (!GlobalValue::isExternalLinkage(global_variable->getLinkage())) + return MaterializeInternalVariable(global_variable); + + clang::NamedDecl *named_decl = DeclForGlobal(global_variable); + + if (!named_decl) + { + if (IsObjCSelectorRef(llvm_value_ptr)) + return true; + + if (!global_variable->hasExternalLinkage()) + return true; + + if (log) + log->Printf("Found global variable \"%s\" without metadata", global_variable->getName().str().c_str()); + + return false; + } + + std::string name (named_decl->getName().str()); + + clang::ValueDecl *value_decl = dyn_cast(named_decl); + if (value_decl == NULL) + return false; + + lldb_private::CompilerType compiler_type(&value_decl->getASTContext(), value_decl->getType()); + + const Type *value_type = NULL; + + if (name[0] == '$') + { + // The $__lldb_expr_result name indicates the return value has allocated as + // a static variable. Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, + // accesses to this static variable need to be redirected to the result of dereferencing + // a pointer that is passed in as one of the arguments. + // + // Consequently, when reporting the size of the type, we report a pointer type pointing + // to the type of $__lldb_expr_result, not the type itself. + // + // We also do this for any user-declared persistent variables. + compiler_type = compiler_type.GetPointerType(); + value_type = PointerType::get(global_variable->getType(), 0); + } + else + { + value_type = global_variable->getType(); + } + + const uint64_t value_size = compiler_type.GetByteSize(nullptr); + lldb::offset_t value_alignment = (compiler_type.GetTypeBitAlign() + 7ull) / 8ull; + + if (log) + { + log->Printf("Type of \"%s\" is [clang \"%s\", llvm \"%s\"] [size %" PRIu64 ", align %" PRIu64 "]", + name.c_str(), + lldb_private::ClangASTContext::GetQualType(compiler_type).getAsString().c_str(), + PrintType(value_type).c_str(), + value_size, + value_alignment); + } + + + if (named_decl && !m_decl_map->AddValueToStruct(named_decl, + lldb_private::ConstString (name.c_str()), + llvm_value_ptr, + value_size, + value_alignment)) + { + if (!global_variable->hasExternalLinkage()) + return true; + else if (HandleSymbol (global_variable)) + return true; + else + return false; + } + } + else if (dyn_cast(llvm_value_ptr)) + { + if (log) + log->Printf("Function pointers aren't handled right now"); + + return false; + } + + return true; +} + +// This function does not report errors; its callers are responsible. +bool +IRForTarget::HandleSymbol (Value *symbol) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + lldb_private::ConstString name(symbol->getName().str().c_str()); + + lldb::addr_t symbol_addr = m_decl_map->GetSymbolAddress (name, lldb::eSymbolTypeAny); + + if (symbol_addr == LLDB_INVALID_ADDRESS) + { + if (log) + log->Printf ("Symbol \"%s\" had no address", name.GetCString()); + + return false; + } + + if (log) + log->Printf("Found \"%s\" at 0x%" PRIx64, name.GetCString(), symbol_addr); + + Type *symbol_type = symbol->getType(); + + Constant *symbol_addr_int = ConstantInt::get(m_intptr_ty, symbol_addr, false); + + Value *symbol_addr_ptr = ConstantExpr::getIntToPtr(symbol_addr_int, symbol_type); + + if (log) + log->Printf("Replacing %s with %s", PrintValue(symbol).c_str(), PrintValue(symbol_addr_ptr).c_str()); + + symbol->replaceAllUsesWith(symbol_addr_ptr); + + return true; +} + +bool +IRForTarget::MaybeHandleCallArguments (CallInst *Old) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf("MaybeHandleCallArguments(%s)", PrintValue(Old).c_str()); + + for (unsigned op_index = 0, num_ops = Old->getNumArgOperands(); + op_index < num_ops; + ++op_index) + if (!MaybeHandleVariable(Old->getArgOperand(op_index))) // conservatively believe that this is a store + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite one of the arguments of a function call.\n"); + + return false; + } + + return true; +} + +bool +IRForTarget::HandleObjCClass(Value *classlist_reference) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + GlobalVariable *global_variable = dyn_cast(classlist_reference); + + if (!global_variable) + return false; + + Constant *initializer = global_variable->getInitializer(); + + if (!initializer) + return false; + + if (!initializer->hasName()) + return false; + + StringRef name(initializer->getName()); + lldb_private::ConstString name_cstr(name.str().c_str()); + lldb::addr_t class_ptr = m_decl_map->GetSymbolAddress(name_cstr, lldb::eSymbolTypeObjCClass); + + if (log) + log->Printf("Found reference to Objective-C class %s (0x%llx)", name_cstr.AsCString(), (unsigned long long)class_ptr); + + if (class_ptr == LLDB_INVALID_ADDRESS) + return false; + + if (global_variable->use_empty()) + return false; + + SmallVector load_instructions; + + for (llvm::User *u : global_variable->users()) + { + if (LoadInst *load_instruction = dyn_cast(u)) + load_instructions.push_back(load_instruction); + } + + if (load_instructions.empty()) + return false; + + Constant *class_addr = ConstantInt::get(m_intptr_ty, (uint64_t)class_ptr); + + for (LoadInst *load_instruction : load_instructions) + { + Constant *class_bitcast = ConstantExpr::getIntToPtr(class_addr, load_instruction->getType()); + + load_instruction->replaceAllUsesWith(class_bitcast); + + load_instruction->eraseFromParent(); + } + + return true; +} + +bool +IRForTarget::RemoveCXAAtExit (BasicBlock &basic_block) +{ + BasicBlock::iterator ii; + + std::vector calls_to_remove; + + for (ii = basic_block.begin(); + ii != basic_block.end(); + ++ii) + { + Instruction &inst = *ii; + + CallInst *call = dyn_cast(&inst); + + // MaybeHandleCallArguments handles error reporting; we are silent here + if (!call) + continue; + + bool remove = false; + + llvm::Function *func = call->getCalledFunction(); + + if (func && func->getName() == "__cxa_atexit") + remove = true; + + llvm::Value *val = call->getCalledValue(); + + if (val && val->getName() == "__cxa_atexit") + remove = true; + + if (remove) + calls_to_remove.push_back(call); + } + + for (std::vector::iterator ci = calls_to_remove.begin(), ce = calls_to_remove.end(); + ci != ce; + ++ci) + { + (*ci)->eraseFromParent(); + } + + return true; +} + +bool +IRForTarget::ResolveCalls(BasicBlock &basic_block) +{ + ///////////////////////////////////////////////////////////////////////// + // Prepare the current basic block for execution in the remote process + // + + BasicBlock::iterator ii; + + for (ii = basic_block.begin(); + ii != basic_block.end(); + ++ii) + { + Instruction &inst = *ii; + + CallInst *call = dyn_cast(&inst); + + // MaybeHandleCallArguments handles error reporting; we are silent here + if (call && !MaybeHandleCallArguments(call)) + return false; + } + + return true; +} + +bool +IRForTarget::ResolveExternals (Function &llvm_function) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + for (GlobalVariable &global_var : m_module->globals()) + { + std::string global_name = global_var.getName().str(); + + if (log) + log->Printf("Examining %s, DeclForGlobalValue returns %p", + global_name.c_str(), + static_cast(DeclForGlobal(&global_var))); + + if (global_name.find("OBJC_IVAR") == 0) + { + if (!HandleSymbol(&global_var)) + { + if (m_error_stream) + m_error_stream->Printf("Error [IRForTarget]: Couldn't find Objective-C indirect ivar symbol %s\n", global_name.c_str()); + + return false; + } + } + else if (global_name.find("OBJC_CLASSLIST_REFERENCES_$") != global_name.npos) + { + if (!HandleObjCClass(&global_var)) + { + if (m_error_stream) + m_error_stream->Printf("Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call\n"); + + return false; + } + } + else if (global_name.find("OBJC_CLASSLIST_SUP_REFS_$") != global_name.npos) + { + if (!HandleObjCClass(&global_var)) + { + if (m_error_stream) + m_error_stream->Printf("Error [IRForTarget]: Couldn't resolve the class for an Objective-C static method call\n"); + + return false; + } + } + else if (DeclForGlobal(&global_var)) + { + if (!MaybeHandleVariable (&global_var)) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Couldn't rewrite external variable %s\n", global_name.c_str()); + + return false; + } + } + } + + return true; +} + +bool +IRForTarget::ReplaceStrings () +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + typedef std::map 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; + + if (!(Old = dyn_cast(V))) + return false; + + ConstantExpr *CE = NULL; + + if ((CE = dyn_cast(V))) + { + if (CE->getOpcode() != Instruction::BitCast) + return false; + + Old = CE->getOperand(0); + } + + GlobalVariable *GV = dyn_cast(Old); + + if (!GV || !GV->hasName() || + (!GV->getName().startswith("_ZGV") && // Itanium ABI guard variable + !GV->getName().endswith("@4IA"))) // Microsoft ABI guard variable + { + return false; + } + + return true; +} + +void +IRForTarget::TurnGuardLoadIntoZero(llvm::Instruction* guard_load) +{ + Constant *zero(Constant::getNullValue(guard_load->getType())); + guard_load->replaceAllUsesWith(zero); + guard_load->eraseFromParent(); +} + +static void ExciseGuardStore(Instruction* guard_store) +{ + guard_store->eraseFromParent(); +} + +bool +IRForTarget::RemoveGuards(BasicBlock &basic_block) +{ + /////////////////////////////////////////////////////// + // Eliminate any reference to guard variables found. + // + + BasicBlock::iterator ii; + + typedef SmallVector InstrList; + typedef InstrList::iterator InstrIterator; + + InstrList guard_loads; + InstrList guard_stores; + + for (ii = basic_block.begin(); + ii != basic_block.end(); + ++ii) + { + Instruction &inst = *ii; + + if (LoadInst *load = dyn_cast(&inst)) + if (isGuardVariableRef(load->getPointerOperand())) + guard_loads.push_back(&inst); + + if (StoreInst *store = dyn_cast(&inst)) + if (isGuardVariableRef(store->getPointerOperand())) + guard_stores.push_back(&inst); + } + + InstrIterator iter; + + for (iter = guard_loads.begin(); + iter != guard_loads.end(); + ++iter) + TurnGuardLoadIntoZero(*iter); + + for (iter = guard_stores.begin(); + iter != guard_stores.end(); + ++iter) + ExciseGuardStore(*iter); + + return true; +} + +// This function does not report errors; its callers are responsible. +bool +IRForTarget::UnfoldConstant(Constant *old_constant, + FunctionValueCache &value_maker, + FunctionValueCache &entry_instruction_finder) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + SmallVector users; + + // We do this because the use list might change, invalidating our iterator. + // Much better to keep a work list ourselves. + for (llvm::User *u : old_constant->users()) + users.push_back(u); + + for (size_t i = 0; + i < users.size(); + ++i) + { + User *user = users[i]; + + if (Constant *constant = dyn_cast(user)) + { + // synthesize a new non-constant equivalent of the constant + + if (ConstantExpr *constant_expr = dyn_cast(constant)) + { + switch (constant_expr->getOpcode()) + { + default: + if (log) + log->Printf("Unhandled constant expression type: \"%s\"", PrintValue(constant_expr).c_str()); + return false; + case Instruction::BitCast: + { + FunctionValueCache bit_cast_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* { + // UnaryExpr + // OperandList[0] is value + + if (constant_expr->getOperand(0) != old_constant) + return constant_expr; + + return new BitCastInst(value_maker.GetValue(function), + constant_expr->getType(), + "", + llvm::cast(entry_instruction_finder.GetValue(function))); + }); + + if (!UnfoldConstant(constant_expr, bit_cast_maker, entry_instruction_finder)) + return false; + } + break; + case Instruction::GetElementPtr: + { + // GetElementPtrConstantExpr + // OperandList[0] is base + // OperandList[1]... are indices + + FunctionValueCache get_element_pointer_maker ([&value_maker, &entry_instruction_finder, old_constant, constant_expr] (llvm::Function *function)->llvm::Value* { + Value *ptr = constant_expr->getOperand(0); + + if (ptr == old_constant) + ptr = value_maker.GetValue(function); + + std::vector index_vector; + + unsigned operand_index; + unsigned num_operands = constant_expr->getNumOperands(); + + for (operand_index = 1; + operand_index < num_operands; + ++operand_index) + { + Value *operand = constant_expr->getOperand(operand_index); + + if (operand == old_constant) + operand = value_maker.GetValue(function); + + index_vector.push_back(operand); + } + + ArrayRef indices(index_vector); + + return GetElementPtrInst::Create(nullptr, ptr, indices, "", llvm::cast(entry_instruction_finder.GetValue(function))); + }); + + if (!UnfoldConstant(constant_expr, get_element_pointer_maker, entry_instruction_finder)) + return false; + } + break; + } + } + else + { + if (log) + log->Printf("Unhandled constant type: \"%s\"", PrintValue(constant).c_str()); + return false; + } + } + else + { + if (Instruction *inst = llvm::dyn_cast(user)) + { + inst->replaceUsesOfWith(old_constant, value_maker.GetValue(inst->getParent()->getParent())); + } + else + { + if (log) + log->Printf("Unhandled non-constant type: \"%s\"", PrintValue(user).c_str()); + return false; + } + } + } + + if (!isa(old_constant)) + { + old_constant->destroyConstant(); + } + + return true; +} + +bool +IRForTarget::ReplaceVariables (Function &llvm_function) +{ + if (!m_resolve_vars) + return true; + + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + m_decl_map->DoStructLayout(); + + if (log) + log->Printf("Element arrangement:"); + + uint32_t num_elements; + uint32_t element_index; + + size_t size; + lldb::offset_t alignment; + + if (!m_decl_map->GetStructInfo (num_elements, size, alignment)) + return false; + + Function::arg_iterator iter(llvm_function.getArgumentList().begin()); + + if (iter == llvm_function.getArgumentList().end()) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes no arguments (should take at least a struct pointer)"); + + return false; + } + + Argument *argument = &*iter; + + if (argument->getName().equals("this")) + { + ++iter; + + if (iter == llvm_function.getArgumentList().end()) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'this' argument (should take a struct pointer too)"); + + return false; + } + + argument = &*iter; + } + else if (argument->getName().equals("self")) + { + ++iter; + + if (iter == llvm_function.getArgumentList().end()) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'self' argument (should take '_cmd' and a struct pointer too)"); + + return false; + } + + if (!iter->getName().equals("_cmd")) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes '%s' after 'self' argument (should take '_cmd')", iter->getName().str().c_str()); + + return false; + } + + ++iter; + + if (iter == llvm_function.getArgumentList().end()) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes only 'self' and '_cmd' arguments (should take a struct pointer too)"); + + return false; + } + + argument = &*iter; + } + + if (!argument->getName().equals("$__lldb_arg")) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Wrapper takes an argument named '%s' instead of the struct pointer", argument->getName().str().c_str()); + + return false; + } + + if (log) + log->Printf("Arg: \"%s\"", PrintValue(argument).c_str()); + + BasicBlock &entry_block(llvm_function.getEntryBlock()); + Instruction *FirstEntryInstruction(entry_block.getFirstNonPHIOrDbg()); + + if (!FirstEntryInstruction) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find the first instruction in the wrapper for use in rewriting"); + + return false; + } + + LLVMContext &context(m_module->getContext()); + IntegerType *offset_type(Type::getInt32Ty(context)); + + if (!offset_type) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Couldn't produce an offset type"); + + return false; + } + + for (element_index = 0; element_index < num_elements; ++element_index) + { + const clang::NamedDecl *decl = NULL; + Value *value = NULL; + lldb::offset_t offset; + lldb_private::ConstString name; + + if (!m_decl_map->GetStructElement (decl, value, offset, name, element_index)) + { + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Structure information is incomplete"); + + return false; + } + + if (log) + log->Printf(" \"%s\" (\"%s\") placed at %" PRIu64, + name.GetCString(), + decl->getNameAsString().c_str(), + offset); + + if (value) + { + if (log) + log->Printf(" Replacing [%s]", PrintValue(value).c_str()); + + FunctionValueCache body_result_maker ([this, name, offset_type, offset, argument, value] (llvm::Function *function)->llvm::Value * { + // Per the comment at ASTResultSynthesizer::SynthesizeBodyResult, in cases where the result + // variable is an rvalue, we have to synthesize a dereference of the appropriate structure + // entry in order to produce the static variable that the AST thinks it is accessing. + + llvm::Instruction *entry_instruction = llvm::cast(m_entry_instruction_finder.GetValue(function)); + + ConstantInt *offset_int(ConstantInt::get(offset_type, offset, true)); + GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(nullptr, + argument, + offset_int, + "", + entry_instruction); + + if (name == m_result_name && !m_result_is_pointer) + { + BitCastInst *bit_cast = new BitCastInst(get_element_ptr, + value->getType()->getPointerTo(), + "", + entry_instruction); + + LoadInst *load = new LoadInst(bit_cast, "", entry_instruction); + + return load; + } + else + { + BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType(), "", entry_instruction); + + return bit_cast; + } + }); + + if (Constant *constant = dyn_cast(value)) + { + UnfoldConstant(constant, body_result_maker, m_entry_instruction_finder); + } + else if (Instruction *instruction = dyn_cast(value)) + { + value->replaceAllUsesWith(body_result_maker.GetValue(instruction->getParent()->getParent())); + } + else + { + if (log) + log->Printf("Unhandled non-constant type: \"%s\"", PrintValue(value).c_str()); + return false; + } + + if (GlobalVariable *var = dyn_cast(value)) + var->eraseFromParent(); + } + } + + if (log) + log->Printf("Total structure [align %" PRId64 ", size %" PRIu64 "]", (int64_t)alignment, (uint64_t)size); + + return true; +} + +llvm::Constant * +IRForTarget::BuildRelocation(llvm::Type *type, uint64_t offset) +{ + llvm::Constant *offset_int = ConstantInt::get(m_intptr_ty, offset); + + llvm::Constant *offset_array[1]; + + offset_array[0] = offset_int; + + llvm::ArrayRef offsets(offset_array, 1); + llvm::Type *char_type = llvm::Type::getInt8Ty(m_module->getContext()); + llvm::Type *char_pointer_type = char_type->getPointerTo(); + + llvm::Constant *reloc_placeholder_bitcast = ConstantExpr::getBitCast(m_reloc_placeholder, char_pointer_type); + llvm::Constant *reloc_getelementptr = ConstantExpr::getGetElementPtr(char_type, reloc_placeholder_bitcast, offsets); + llvm::Constant *reloc_bitcast = ConstantExpr::getBitCast(reloc_getelementptr, type); + + return reloc_bitcast; +} + +bool +IRForTarget::CompleteDataAllocation () +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (!m_data_allocator.GetStream().GetSize()) + return true; + + lldb::addr_t allocation = m_data_allocator.Allocate(); + + if (log) + { + if (allocation) + log->Printf("Allocated static data at 0x%llx", (unsigned long long)allocation); + else + log->Printf("Failed to allocate static data"); + } + + if (!allocation || allocation == LLDB_INVALID_ADDRESS) + return false; + + Constant *relocated_addr = ConstantInt::get(m_intptr_ty, (uint64_t)allocation); + Constant *relocated_bitcast = ConstantExpr::getIntToPtr(relocated_addr, llvm::Type::getInt8PtrTy(m_module->getContext())); + + m_reloc_placeholder->replaceAllUsesWith(relocated_bitcast); + + m_reloc_placeholder->eraseFromParent(); + + return true; +} + +bool +IRForTarget::StripAllGVs (Module &llvm_module) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + std::vector 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) +{ + lldb_private::Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + m_module = &llvm_module; + m_target_data.reset(new DataLayout(m_module)); + m_intptr_ty = llvm::Type::getIntNTy(m_module->getContext(), m_target_data->getPointerSizeInBits()); + + if (log) + { + std::string s; + raw_string_ostream oss(s); + + m_module->print(oss, NULL); + + oss.flush(); + + log->Printf("Module as passed in to IRForTarget: \n\"%s\"", s.c_str()); + } + + Function* main_function = m_module->getFunction(StringRef(m_func_name.c_str())); + + if (!main_function) + { + if (log) + log->Printf("Couldn't find \"%s()\" in the module", m_func_name.c_str()); + + if (m_error_stream) + m_error_stream->Printf("Internal error [IRForTarget]: Couldn't find wrapper '%s' in the module", m_func_name.c_str()); + + return false; + } + + if (!FixFunctionLinkage (*main_function)) + { + if (log) + log->Printf("Couldn't fix the linkage for the function"); + + return false; + } + + llvm::Type *int8_ty = Type::getInt8Ty(m_module->getContext()); + + m_reloc_placeholder = new llvm::GlobalVariable((*m_module), + int8_ty, + false /* IsConstant */, + GlobalVariable::InternalLinkage, + Constant::getNullValue(int8_ty), + "reloc_placeholder", + NULL /* InsertBefore */, + GlobalVariable::NotThreadLocal /* ThreadLocal */, + 0 /* AddressSpace */); + + //////////////////////////////////////////////////////////// + // Replace $__lldb_expr_result with a persistent variable + // + + if (!CreateResultVariable(*main_function)) + { + if (log) + log->Printf("CreateResultVariable() failed"); + + // CreateResultVariable() reports its own errors, so we don't do so here + + return false; + } + + if (log && log->GetVerbose()) + { + std::string s; + raw_string_ostream oss(s); + + m_module->print(oss, NULL); + + oss.flush(); + + log->Printf("Module after creating the result variable: \n\"%s\"", s.c_str()); + } + + for (Module::iterator fi = m_module->begin(), fe = m_module->end(); + fi != fe; + ++fi) + { + llvm::Function *function = &*fi; + + if (function->begin() == function->end()) + continue; + + Function::iterator bbi; + + for (bbi = function->begin(); + bbi != function->end(); + ++bbi) + { + if (!RemoveGuards(*bbi)) + { + if (log) + log->Printf("RemoveGuards() failed"); + + // RemoveGuards() reports its own errors, so we don't do so here + + return false; + } + + if (!RewritePersistentAllocs(*bbi)) + { + if (log) + log->Printf("RewritePersistentAllocs() failed"); + + // RewritePersistentAllocs() reports its own errors, so we don't do so here + + return false; + } + + if (!RemoveCXAAtExit(*bbi)) + { + if (log) + log->Printf("RemoveCXAAtExit() failed"); + + // RemoveCXAAtExit() reports its own errors, so we don't do so here + + return false; + } + } + } + + /////////////////////////////////////////////////////////////////////////////// + // Fix all Objective-C constant strings to use NSStringWithCString:encoding: + // + + if (!RewriteObjCConstStrings()) + { + if (log) + log->Printf("RewriteObjCConstStrings() failed"); + + // RewriteObjCConstStrings() reports its own errors, so we don't do so here + + return false; + } + + /////////////////////////////// + // Resolve function pointers + // + + if (!ResolveFunctionPointers(llvm_module)) + { + if (log) + log->Printf("ResolveFunctionPointers() failed"); + + // ResolveFunctionPointers() reports its own errors, so we don't do so here + + return false; + } + + for (Module::iterator fi = m_module->begin(), fe = m_module->end(); + fi != fe; + ++fi) + { + llvm::Function *function = &*fi; + + for (llvm::Function::iterator bbi = function->begin(), bbe = function->end(); + bbi != bbe; + ++bbi) + { + if (!RewriteObjCSelectors(*bbi)) + { + if (log) + log->Printf("RewriteObjCSelectors() failed"); + + // RewriteObjCSelectors() reports its own errors, so we don't do so here + + return false; + } + } + } + + for (Module::iterator fi = m_module->begin(), fe = m_module->end(); + fi != fe; + ++fi) + { + llvm::Function *function = &*fi; + + for (llvm::Function::iterator bbi = function->begin(), bbe = function->end(); + bbi != bbe; + ++bbi) + { + if (!ResolveCalls(*bbi)) + { + if (log) + log->Printf("ResolveCalls() failed"); + + // ResolveCalls() reports its own errors, so we don't do so here + + return false; + } + + if (!ReplaceStaticLiterals(*bbi)) + { + if (log) + log->Printf("ReplaceStaticLiterals() failed"); + + return false; + } + } + } + + //////////////////////////////////////////////////////////////////////// + // Run function-level passes that only make sense on the main function + // + + if (!ResolveExternals(*main_function)) + { + if (log) + log->Printf("ResolveExternals() failed"); + + // ResolveExternals() reports its own errors, so we don't do so here + + return false; + } + + if (!ReplaceVariables(*main_function)) + { + if (log) + log->Printf("ReplaceVariables() failed"); + + // ReplaceVariables() reports its own errors, so we don't do so here + + return false; + } + + if (!ReplaceStrings()) + { + if (log) + log->Printf("ReplaceStrings() failed"); + + return false; + } + + if (!CompleteDataAllocation()) + { + if (log) + log->Printf("CompleteDataAllocation() failed"); + + return false; + } + + if (!StripAllGVs(llvm_module)) + { + if (log) + log->Printf("StripAllGVs() failed"); + } + + if (log && log->GetVerbose()) + { + std::string s; + raw_string_ostream oss(s); + + m_module->print(oss, NULL); + + oss.flush(); + + log->Printf("Module after preparing for execution: \n\"%s\"", s.c_str()); + } + + return true; +} + +void +IRForTarget::assignPassManager (PMStack &pass_mgr_stack, PassManagerType pass_mgr_type) +{ +} + +PassManagerType +IRForTarget::getPotentialPassManagerType() const +{ + return PMT_ModulePassManager; +} diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.h b/source/Plugins/ExpressionParser/Clang/IRForTarget.h new file mode 100644 index 0000000000000..fb4abcc103ded --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.h @@ -0,0 +1,745 @@ +//===-- IRForTarget.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_IRForTarget_h_ +#define liblldb_IRForTarget_h_ + +#include "lldb/lldb-public.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Symbol/TaggedASTType.h" +#include "llvm/Pass.h" + +#include +#include + +namespace llvm { + class BasicBlock; + class CallInst; + class Constant; + class ConstantInt; + class Function; + class GlobalValue; + class GlobalVariable; + class Instruction; + class IntegerType; + class Module; + class StoreInst; + class DataLayout; + class Type; + class Value; +} + +namespace lldb_private { + class ClangExpressionDeclMap; + class IRExecutionUnit; + class IRMemoryMap; +} + +//---------------------------------------------------------------------- +/// @class IRForTarget IRForTarget.h "lldb/Expression/IRForTarget.h" +/// @brief Transforms the IR for a function to run in the target +/// +/// Once an expression has been parsed and converted to IR, it can run +/// in two contexts: interpreted by LLDB as a DWARF location expression, +/// or compiled by the JIT and inserted into the target process for +/// execution. +/// +/// IRForTarget makes the second possible, by applying a series of +/// transformations to the IR which make it relocatable. These +/// transformations are discussed in more detail next to their relevant +/// functions. +//---------------------------------------------------------------------- +class IRForTarget : public llvm::ModulePass +{ +public: + enum class LookupResult { + Success, + Fail, + Ignore + }; + + //------------------------------------------------------------------ + /// Constructor + /// + /// @param[in] decl_map + /// The list of externally-referenced variables for the expression, + /// for use in looking up globals and allocating the argument + /// struct. See the documentation for ClangExpressionDeclMap. + /// + /// @param[in] resolve_vars + /// True if the external variable references (including persistent + /// variables) should be resolved. If not, only external functions + /// are resolved. + /// + /// @param[in] execution_policy + /// Determines whether an IR interpreter can be used to statically + /// evaluate the expression. + /// + /// @param[in] const_result + /// This variable is populated with the statically-computed result + /// of the function, if it has no side-effects and the result can + /// be computed statically. + /// + /// @param[in] execution_unit + /// The holder for raw data associated with the expression. + /// + /// @param[in] error_stream + /// If non-NULL, a stream on which errors can be printed. + /// + /// @param[in] func_name + /// The name of the function to prepare for execution in the target. + //------------------------------------------------------------------ + IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map, + bool resolve_vars, + lldb_private::IRExecutionUnit &execution_unit, + lldb_private::Stream *error_stream, + const char* func_name = "$__lldb_expr"); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~IRForTarget() override; + + //------------------------------------------------------------------ + /// Run this IR transformer on a single module + /// + /// Implementation of the llvm::ModulePass::runOnModule() function. + /// + /// @param[in] llvm_module + /// The module to run on. This module is searched for the function + /// $__lldb_expr, and that function is passed to the passes one by + /// one. + /// + /// @param[in] interpreter_error + /// An error. If the expression fails to be interpreted, this error + /// is set to a reason why. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + runOnModule(llvm::Module &llvm_module) override; + + //------------------------------------------------------------------ + /// Interface stub + /// + /// Implementation of the llvm::ModulePass::assignPassManager() + /// function. + //------------------------------------------------------------------ + void + assignPassManager(llvm::PMStack &pass_mgr_stack, + llvm::PassManagerType pass_mgr_type = llvm::PMT_ModulePassManager) override; + + //------------------------------------------------------------------ + /// Returns PMT_ModulePassManager + /// + /// Implementation of the llvm::ModulePass::getPotentialPassManagerType() + /// function. + //------------------------------------------------------------------ + llvm::PassManagerType + getPotentialPassManagerType() const override; + +private: + //------------------------------------------------------------------ + /// Ensures that the current function's linkage is set to external. + /// Otherwise the JIT may not return an address for it. + /// + /// @param[in] llvm_function + /// The function whose linkage is to be fixed. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + FixFunctionLinkage (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A module-level pass to replace all function pointers with their + /// integer equivalents. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_module + /// The module currently being processed. + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + HasSideEffects (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A function-level pass to check whether the function has side + /// effects. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Get the address of a function, and a location to put the complete + /// Value of the function if one is available. + /// + /// @param[in] function + /// The function to find the location of. + /// + /// @param[out] ptr + /// The location of the function in the target. + /// + /// @param[out] name + /// The resolved name of the function (matters for intrinsics). + /// + /// @param[out] value_ptr + /// A variable to put the function's completed Value* in, or NULL + /// if the Value* shouldn't be stored anywhere. + /// + /// @return + /// The pointer. + //------------------------------------------------------------------ + LookupResult + GetFunctionAddress (llvm::Function *function, + uint64_t &ptr, + lldb_private::ConstString &name, + llvm::Constant **&value_ptr); + + //------------------------------------------------------------------ + /// Build a function pointer given a type and a raw pointer. + /// + /// @param[in] type + /// The type of the function pointer to be built. + /// + /// @param[in] ptr + /// The value of the pointer. + /// + /// @return + /// The pointer. + //------------------------------------------------------------------ + llvm::Constant * + BuildFunctionPointer (llvm::Type *type, + uint64_t ptr); + + void + RegisterFunctionMetadata (llvm::LLVMContext &context, + llvm::Value *function_ptr, + const char *name); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True if the function has side effects (or if this cannot + /// be determined); false otherwise. + //------------------------------------------------------------------ + bool + ResolveFunctionPointers (llvm::Module &llvm_module); + + //------------------------------------------------------------------ + /// A function-level pass to take the generated global value + /// $__lldb_expr_result and make it into a persistent variable. + /// Also see ASTResultSynthesizer. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Find the NamedDecl corresponding to a Value. This interface is + /// exposed for the IR interpreter. + /// + /// @param[in] module + /// The module containing metadata to search + /// + /// @param[in] global + /// The global entity to search for + /// + /// @return + /// The corresponding variable declaration + //------------------------------------------------------------------ +public: + static clang::NamedDecl * + DeclForGlobal (const llvm::GlobalValue *global_val, llvm::Module *module); +private: + clang::NamedDecl * + DeclForGlobal (llvm::GlobalValue *global); + + //------------------------------------------------------------------ + /// Set the constant result variable m_const_result to the provided + /// constant, assuming it can be evaluated. The result variable + /// will be reset to NULL later if the expression has side effects. + /// + /// @param[in] initializer + /// The constant initializer for the variable. + /// + /// @param[in] name + /// The name of the result variable. + /// + /// @param[in] type + /// The Clang type of the result variable. + //------------------------------------------------------------------ + void + MaybeSetConstantResult (llvm::Constant *initializer, + const lldb_private::ConstString &name, + lldb_private::TypeFromParser type); + + //------------------------------------------------------------------ + /// If the IR represents a cast of a variable, set m_const_result + /// to the result of the cast. The result variable will be reset to + /// NULL latger if the expression has side effects. + /// + /// @param[in] type + /// The Clang type of the result variable. + //------------------------------------------------------------------ + void + MaybeSetCastResult (lldb_private::TypeFromParser type); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + CreateResultVariable (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A module-level pass to find Objective-C constant strings and + /// transform them to calls to CFStringCreateWithBytes. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Rewrite a single Objective-C constant string. + /// + /// @param[in] NSStr + /// The constant NSString to be transformed + /// + /// @param[in] CStr + /// The constant C string inside the NSString. This will be + /// passed as the bytes argument to CFStringCreateWithBytes. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewriteObjCConstString (llvm::GlobalVariable *NSStr, + llvm::GlobalVariable *CStr); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewriteObjCConstStrings (); + + //------------------------------------------------------------------ + /// A basic block-level pass to find all Objective-C method calls and + /// rewrite them to use sel_registerName instead of statically allocated + /// selectors. The reason is that the selectors are created on the + /// assumption that the Objective-C runtime will scan the appropriate + /// section and prepare them. This doesn't happen when code is copied + /// into the target, though, and there's no easy way to induce the + /// runtime to scan them. So instead we get our selectors from + /// sel_registerName. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Replace a single selector reference + /// + /// @param[in] selector_load + /// The load of the statically-allocated selector. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewriteObjCSelector (llvm::Instruction* selector_load); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewriteObjCSelectors (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// A basic block-level pass to find all newly-declared persistent + /// variables and register them with the ClangExprDeclMap. This + /// allows them to be materialized and dematerialized like normal + /// external variables. Before transformation, these persistent + /// variables look like normal locals, so they have an allocation. + /// This pass excises these allocations and makes references look + /// like external references where they will be resolved -- like all + /// other external references -- by ResolveExternals(). + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Handle a single allocation of a persistent variable + /// + /// @param[in] persistent_alloc + /// The allocation of the persistent variable. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RewritePersistentAlloc (llvm::Instruction *persistent_alloc); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The basic block currently being processed. + //------------------------------------------------------------------ + bool + RewritePersistentAllocs (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// A function-level pass to find all external variables and functions + /// used in the IR. Each found external variable is added to the + /// struct, and each external function is resolved in place, its call + /// replaced with a call to a function pointer whose value is the + /// address of the function in the target process. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Write an initializer to a memory array of assumed sufficient + /// size. + /// + /// @param[in] data + /// A pointer to the data to write to. + /// + /// @param[in] initializer + /// The initializer itself. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + MaterializeInitializer (uint8_t *data, llvm::Constant *initializer); + + //------------------------------------------------------------------ + /// Move an internal variable into the static allocation section. + /// + /// @param[in] global_variable + /// The variable. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + MaterializeInternalVariable (llvm::GlobalVariable *global_variable); + + //------------------------------------------------------------------ + /// Handle a single externally-defined variable + /// + /// @param[in] value + /// The variable. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + MaybeHandleVariable (llvm::Value *value); + + //------------------------------------------------------------------ + /// Handle a single externally-defined symbol + /// + /// @param[in] symbol + /// The symbol. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + HandleSymbol (llvm::Value *symbol); + + //------------------------------------------------------------------ + /// Handle a single externally-defined Objective-C class + /// + /// @param[in] classlist_reference + /// The reference, usually "01L_OBJC_CLASSLIST_REFERENCES_$_n" + /// where n (if present) is an index. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + HandleObjCClass(llvm::Value *classlist_reference); + + //------------------------------------------------------------------ + /// Handle all the arguments to a function call + /// + /// @param[in] C + /// The call instruction. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + MaybeHandleCallArguments (llvm::CallInst *call_inst); + + //------------------------------------------------------------------ + /// Resolve variable references in calls to external functions + /// + /// @param[in] basic_block + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ResolveCalls (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// Remove calls to __cxa_atexit, which should never be generated by + /// expressions. + /// + /// @param[in] call_inst + /// The call instruction. + /// + /// @return + /// True if the scan was successful; false if some operation + /// failed + //------------------------------------------------------------------ + bool + RemoveCXAAtExit (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ResolveExternals (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A basic block-level pass to excise guard variables from the code. + /// The result for the function is passed through Clang as a static + /// variable. Static variables normally have guard variables to + /// ensure that they are only initialized once. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// Rewrite a load to a guard variable to return constant 0. + /// + /// @param[in] guard_load + /// The load instruction to zero out. + //------------------------------------------------------------------ + void + TurnGuardLoadIntoZero(llvm::Instruction* guard_load); + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + RemoveGuards (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// A module-level pass to allocate all string literals in a separate + /// allocation and redirect references to them. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ReplaceStrings (); + + //------------------------------------------------------------------ + /// A basic block-level pass to find all literals that will be + /// allocated as statics by the JIT (in contrast to the Strings, + /// which already are statics) and synthesize loads for them. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] basic_block + /// The basic block currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ReplaceStaticLiterals (llvm::BasicBlock &basic_block); + + //------------------------------------------------------------------ + /// A function-level pass to make all external variable references + /// point at the correct offsets from the void* passed into the + /// function. ClangExpressionDeclMap::DoStructLayout() must be called + /// beforehand, so that the offsets are valid. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + ReplaceVariables (llvm::Function &llvm_function); + + //------------------------------------------------------------------ + /// A module-level pass to remove all global variables from the + /// module since it no longer should export or import any symbols. + //------------------------------------------------------------------ + + //------------------------------------------------------------------ + /// The top-level pass implementation + /// + /// @param[in] llvm_module + /// The module currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + StripAllGVs (llvm::Module &llvm_module); + + class StaticDataAllocator { + public: + StaticDataAllocator(lldb_private::IRExecutionUnit &execution_unit); + lldb_private::StreamString &GetStream() + { + return m_stream_string; + } + lldb::addr_t Allocate(); + + lldb::TargetSP + GetTarget(); + private: + lldb_private::IRExecutionUnit &m_execution_unit; + lldb_private::StreamString m_stream_string; + lldb::addr_t m_allocation; + }; + + /// Flags + bool m_resolve_vars; ///< True if external variable references and persistent variable references should be resolved + std::string m_func_name; ///< The name of the function to translate + lldb_private::ConstString m_result_name; ///< The name of the result variable ($0, $1, ...) + lldb_private::TypeFromParser m_result_type; ///< The type of the result variable. + llvm::Module *m_module; ///< The module being processed, or NULL if that has not been determined yet. + std::unique_ptr m_target_data; ///< The target data for the module being processed, or NULL if there is no module. + lldb_private::ClangExpressionDeclMap *m_decl_map; ///< The DeclMap containing the Decls + StaticDataAllocator m_data_allocator; ///< The allocator to use for constant strings + llvm::Constant *m_CFStringCreateWithBytes; ///< The address of the function CFStringCreateWithBytes, cast to the appropriate function pointer type + llvm::Constant *m_sel_registerName; ///< The address of the function sel_registerName, cast to the appropriate function pointer type + llvm::IntegerType *m_intptr_ty; ///< The type of an integer large enough to hold a pointer. + lldb_private::Stream *m_error_stream; ///< If non-NULL, the stream on which errors should be printed + + llvm::StoreInst *m_result_store; ///< If non-NULL, the store instruction that writes to the result variable. If m_has_side_effects is true, this is NULL. + bool m_result_is_pointer; ///< True if the function's result in the AST is a pointer (see comments in ASTResultSynthesizer::SynthesizeBodyResult) + + llvm::GlobalVariable *m_reloc_placeholder; ///< A placeholder that will be replaced by a pointer to the final location of the static allocation. + + //------------------------------------------------------------------ + /// UnfoldConstant operates on a constant [Old] which has just been + /// replaced with a value [New]. We assume that new_value has + /// been properly placed early in the function, in front of the + /// first instruction in the entry basic block + /// [FirstEntryInstruction]. + /// + /// UnfoldConstant reads through the uses of Old and replaces Old + /// in those uses with New. Where those uses are constants, the + /// function generates new instructions to compute the result of the + /// new, non-constant expression and places them before + /// FirstEntryInstruction. These instructions replace the constant + /// uses, so UnfoldConstant calls itself recursively for those. + /// + /// @param[in] llvm_function + /// The function currently being processed. + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + + class FunctionValueCache { + public: + typedef std::function Maker; + + FunctionValueCache (Maker const &maker); + ~FunctionValueCache (); + llvm::Value *GetValue (llvm::Function *function); + private: + Maker const m_maker; + typedef std::map FunctionValueMap; + FunctionValueMap m_values; + }; + + FunctionValueCache m_entry_instruction_finder; + + static bool + UnfoldConstant (llvm::Constant *old_constant, + FunctionValueCache &value_maker, + FunctionValueCache &entry_instruction_finder); + + //------------------------------------------------------------------ + /// Construct a reference to m_reloc_placeholder with a given type + /// and offset. This typically happens after inserting data into + /// m_data_allocator. + /// + /// @param[in] type + /// The type of the value being loaded. + /// + /// @param[in] offset + /// The offset of the value from the base of m_data_allocator. + /// + /// @return + /// The Constant for the reference, usually a ConstantExpr. + //------------------------------------------------------------------ + llvm::Constant * + BuildRelocation(llvm::Type *type, + uint64_t offset); + + //------------------------------------------------------------------ + /// Commit the allocation in m_data_allocator and use its final + /// location to replace m_reloc_placeholder. + /// + /// @param[in] module + /// The module that m_data_allocator resides in + /// + /// @return + /// True on success; false otherwise + //------------------------------------------------------------------ + bool + CompleteDataAllocation (); + +}; + +#endif // liblldb_IRForTarget_h_ diff --git a/source/Plugins/ExpressionParser/Go/GoAST.h b/source/Plugins/ExpressionParser/Go/GoAST.h new file mode 100644 index 0000000000000..6d51240eab5cc --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoAST.h @@ -0,0 +1,3225 @@ +//===-- GoAST.h -------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// DO NOT EDIT. +// Generated by gen_go_ast.py + +#ifndef liblldb_GoAST_h +#define liblldb_GoAST_h + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "llvm/Support/Casting.h" +#include "Plugins/ExpressionParser/Go/GoLexer.h" + +namespace lldb_private +{ + +class GoASTNode +{ + public: + typedef GoLexer::TokenType TokenType; + typedef GoLexer::Token Token; + enum ChanDir + { + eChanBidir, + eChanSend, + eChanRecv, + }; + enum NodeKind + { + eBadDecl, + eFuncDecl, + eGenDecl, + eArrayType, + eBadExpr, + eBasicLit, + eBinaryExpr, + eIdent, + eCallExpr, + eChanType, + eCompositeLit, + eEllipsis, + eFuncType, + eFuncLit, + eIndexExpr, + eInterfaceType, + eKeyValueExpr, + eMapType, + eParenExpr, + eSelectorExpr, + eSliceExpr, + eStarExpr, + eStructType, + eTypeAssertExpr, + eUnaryExpr, + eImportSpec, + eTypeSpec, + eValueSpec, + eAssignStmt, + eBadStmt, + eBlockStmt, + eBranchStmt, + eCaseClause, + eCommClause, + eDeclStmt, + eDeferStmt, + eEmptyStmt, + eExprStmt, + eForStmt, + eGoStmt, + eIfStmt, + eIncDecStmt, + eLabeledStmt, + eRangeStmt, + eReturnStmt, + eSelectStmt, + eSendStmt, + eSwitchStmt, + eTypeSwitchStmt, + eField, + eFieldList, + }; + + virtual ~GoASTNode() = default; + + NodeKind + GetKind() const + { + return m_kind; + } + + virtual const char *GetKindName() const = 0; + + template void WalkChildren(V &v); + + protected: + explicit GoASTNode(NodeKind kind) : m_kind(kind) { } + + private: + const NodeKind m_kind; + + GoASTNode(const GoASTNode &) = delete; + const GoASTNode &operator=(const GoASTNode &) = delete; +}; + + +class GoASTDecl : public GoASTNode +{ + public: + template R Visit(V *v) const; + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() >= eBadDecl && n->GetKind() <= eGenDecl; + } + + protected: + explicit GoASTDecl(NodeKind kind) : GoASTNode(kind) { } + private: + + GoASTDecl(const GoASTDecl &) = delete; + const GoASTDecl &operator=(const GoASTDecl &) = delete; +}; + +class GoASTExpr : public GoASTNode +{ + public: + template R Visit(V *v) const; + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() >= eArrayType && n->GetKind() <= eUnaryExpr; + } + + protected: + explicit GoASTExpr(NodeKind kind) : GoASTNode(kind) { } + private: + + GoASTExpr(const GoASTExpr &) = delete; + const GoASTExpr &operator=(const GoASTExpr &) = delete; +}; + +class GoASTSpec : public GoASTNode +{ + public: + template R Visit(V *v) const; + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() >= eImportSpec && n->GetKind() <= eValueSpec; + } + + protected: + explicit GoASTSpec(NodeKind kind) : GoASTNode(kind) { } + private: + + GoASTSpec(const GoASTSpec &) = delete; + const GoASTSpec &operator=(const GoASTSpec &) = delete; +}; + +class GoASTStmt : public GoASTNode +{ + public: + template R Visit(V *v) const; + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() >= eAssignStmt && n->GetKind() <= eTypeSwitchStmt; + } + + protected: + explicit GoASTStmt(NodeKind kind) : GoASTNode(kind) { } + private: + + GoASTStmt(const GoASTStmt &) = delete; + const GoASTStmt &operator=(const GoASTStmt &) = delete; +}; + + +class GoASTArrayType : public GoASTExpr +{ + public: + GoASTArrayType(GoASTExpr *len, GoASTExpr *elt) : GoASTExpr(eArrayType), m_len_up(len), m_elt_up(elt) {} + ~GoASTArrayType() override = default; + + const char * + GetKindName() const override + { + return "ArrayType"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eArrayType; + } + + const GoASTExpr * + GetLen() const + { + return m_len_up.get(); + } + void + SetLen(GoASTExpr *len) + { + m_len_up.reset(len); + } + + const GoASTExpr * + GetElt() const + { + return m_elt_up.get(); + } + void + SetElt(GoASTExpr *elt) + { + m_elt_up.reset(elt); + } + + private: + friend class GoASTNode; + std::unique_ptr m_len_up; + std::unique_ptr m_elt_up; + + GoASTArrayType(const GoASTArrayType &) = delete; + const GoASTArrayType &operator=(const GoASTArrayType &) = delete; +}; + +class GoASTAssignStmt : public GoASTStmt +{ + public: + explicit GoASTAssignStmt(bool define) : GoASTStmt(eAssignStmt), m_define(define) {} + ~GoASTAssignStmt() override = default; + + const char * + GetKindName() const override + { + return "AssignStmt"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eAssignStmt; + } + + size_t + NumLhs() const + { + return m_lhs.size(); + } + const GoASTExpr * + GetLhs(int i) const + { + return m_lhs[i].get(); + } + void + AddLhs(GoASTExpr *lhs) + { + m_lhs.push_back(std::unique_ptr(lhs)); + } + + size_t + NumRhs() const + { + return m_rhs.size(); + } + const GoASTExpr * + GetRhs(int i) const + { + return m_rhs[i].get(); + } + void + AddRhs(GoASTExpr *rhs) + { + m_rhs.push_back(std::unique_ptr(rhs)); + } + + bool + GetDefine() const + { + return m_define; + } + void + SetDefine(bool define) + { + m_define = define; + } + + private: + friend class GoASTNode; + std::vector > m_lhs; + std::vector > m_rhs; + bool m_define; + + GoASTAssignStmt(const GoASTAssignStmt &) = delete; + const GoASTAssignStmt &operator=(const GoASTAssignStmt &) = delete; +}; + +class GoASTBadDecl : public GoASTDecl +{ + public: + GoASTBadDecl() : GoASTDecl(eBadDecl) {} + ~GoASTBadDecl() override = default; + + const char * + GetKindName() const override + { + return "BadDecl"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eBadDecl; + } + + GoASTBadDecl(const GoASTBadDecl &) = delete; + const GoASTBadDecl &operator=(const GoASTBadDecl &) = delete; +}; + +class GoASTBadExpr : public GoASTExpr +{ + public: + GoASTBadExpr() : GoASTExpr(eBadExpr) {} + ~GoASTBadExpr() override = default; + + const char * + GetKindName() const override + { + return "BadExpr"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eBadExpr; + } + + GoASTBadExpr(const GoASTBadExpr &) = delete; + const GoASTBadExpr &operator=(const GoASTBadExpr &) = delete; +}; + +class GoASTBadStmt : public GoASTStmt +{ + public: + GoASTBadStmt() : GoASTStmt(eBadStmt) {} + ~GoASTBadStmt() override = default; + + const char * + GetKindName() const override + { + return "BadStmt"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eBadStmt; + } + + GoASTBadStmt(const GoASTBadStmt &) = delete; + const GoASTBadStmt &operator=(const GoASTBadStmt &) = delete; +}; + +class GoASTBasicLit : public GoASTExpr +{ + public: + explicit GoASTBasicLit(Token value) : GoASTExpr(eBasicLit), m_value(value) {} + ~GoASTBasicLit() override = default; + + const char * + GetKindName() const override + { + return "BasicLit"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eBasicLit; + } + + Token + GetValue() const + { + return m_value; + } + void + SetValue(Token value) + { + m_value = value; + } + + private: + friend class GoASTNode; + Token m_value; + + GoASTBasicLit(const GoASTBasicLit &) = delete; + const GoASTBasicLit &operator=(const GoASTBasicLit &) = delete; +}; + +class GoASTBinaryExpr : public GoASTExpr +{ + public: + GoASTBinaryExpr(GoASTExpr *x, GoASTExpr *y, TokenType op) : GoASTExpr(eBinaryExpr), m_x_up(x), m_y_up(y), m_op(op) {} + ~GoASTBinaryExpr() override = default; + + const char * + GetKindName() const override + { + return "BinaryExpr"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eBinaryExpr; + } + + const GoASTExpr * + GetX() const + { + return m_x_up.get(); + } + void + SetX(GoASTExpr *x) + { + m_x_up.reset(x); + } + + const GoASTExpr * + GetY() const + { + return m_y_up.get(); + } + void + SetY(GoASTExpr *y) + { + m_y_up.reset(y); + } + + TokenType + GetOp() const + { + return m_op; + } + void + SetOp(TokenType op) + { + m_op = op; + } + + private: + friend class GoASTNode; + std::unique_ptr m_x_up; + std::unique_ptr m_y_up; + TokenType m_op; + + GoASTBinaryExpr(const GoASTBinaryExpr &) = delete; + const GoASTBinaryExpr &operator=(const GoASTBinaryExpr &) = delete; +}; + +class GoASTBlockStmt : public GoASTStmt +{ + public: + GoASTBlockStmt() : GoASTStmt(eBlockStmt) {} + ~GoASTBlockStmt() override = default; + + const char * + GetKindName() const override + { + return "BlockStmt"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eBlockStmt; + } + + size_t + NumList() const + { + return m_list.size(); + } + const GoASTStmt * + GetList(int i) const + { + return m_list[i].get(); + } + void + AddList(GoASTStmt *list) + { + m_list.push_back(std::unique_ptr(list)); + } + + private: + friend class GoASTNode; + std::vector > m_list; + + GoASTBlockStmt(const GoASTBlockStmt &) = delete; + const GoASTBlockStmt &operator=(const GoASTBlockStmt &) = delete; +}; + +class GoASTIdent : public GoASTExpr +{ + public: + explicit GoASTIdent(Token name) : GoASTExpr(eIdent), m_name(name) {} + ~GoASTIdent() override = default; + + const char * + GetKindName() const override + { + return "Ident"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eIdent; + } + + Token + GetName() const + { + return m_name; + } + void + SetName(Token name) + { + m_name = name; + } + + private: + friend class GoASTNode; + Token m_name; + + GoASTIdent(const GoASTIdent &) = delete; + const GoASTIdent &operator=(const GoASTIdent &) = delete; +}; + +class GoASTBranchStmt : public GoASTStmt +{ + public: + GoASTBranchStmt(GoASTIdent *label, TokenType tok) : GoASTStmt(eBranchStmt), m_label_up(label), m_tok(tok) {} + ~GoASTBranchStmt() override = default; + + const char * + GetKindName() const override + { + return "BranchStmt"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eBranchStmt; + } + + const GoASTIdent * + GetLabel() const + { + return m_label_up.get(); + } + void + SetLabel(GoASTIdent *label) + { + m_label_up.reset(label); + } + + TokenType + GetTok() const + { + return m_tok; + } + void + SetTok(TokenType tok) + { + m_tok = tok; + } + + private: + friend class GoASTNode; + std::unique_ptr m_label_up; + TokenType m_tok; + + GoASTBranchStmt(const GoASTBranchStmt &) = delete; + const GoASTBranchStmt &operator=(const GoASTBranchStmt &) = delete; +}; + +class GoASTCallExpr : public GoASTExpr +{ + public: + explicit GoASTCallExpr(bool ellipsis) : GoASTExpr(eCallExpr), m_ellipsis(ellipsis) {} + ~GoASTCallExpr() override = default; + + const char * + GetKindName() const override + { + return "CallExpr"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eCallExpr; + } + + const GoASTExpr * + GetFun() const + { + return m_fun_up.get(); + } + void + SetFun(GoASTExpr *fun) + { + m_fun_up.reset(fun); + } + + size_t + NumArgs() const + { + return m_args.size(); + } + const GoASTExpr * + GetArgs(int i) const + { + return m_args[i].get(); + } + void + AddArgs(GoASTExpr *args) + { + m_args.push_back(std::unique_ptr(args)); + } + + bool + GetEllipsis() const + { + return m_ellipsis; + } + void + SetEllipsis(bool ellipsis) + { + m_ellipsis = ellipsis; + } + + private: + friend class GoASTNode; + std::unique_ptr m_fun_up; + std::vector > m_args; + bool m_ellipsis; + + GoASTCallExpr(const GoASTCallExpr &) = delete; + const GoASTCallExpr &operator=(const GoASTCallExpr &) = delete; +}; + +class GoASTCaseClause : public GoASTStmt +{ + public: + GoASTCaseClause() : GoASTStmt(eCaseClause) {} + ~GoASTCaseClause() override = default; + + const char * + GetKindName() const override + { + return "CaseClause"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eCaseClause; + } + + size_t + NumList() const + { + return m_list.size(); + } + const GoASTExpr * + GetList(int i) const + { + return m_list[i].get(); + } + void + AddList(GoASTExpr *list) + { + m_list.push_back(std::unique_ptr(list)); + } + + size_t + NumBody() const + { + return m_body.size(); + } + const GoASTStmt * + GetBody(int i) const + { + return m_body[i].get(); + } + void + AddBody(GoASTStmt *body) + { + m_body.push_back(std::unique_ptr(body)); + } + + private: + friend class GoASTNode; + std::vector > m_list; + std::vector > m_body; + + GoASTCaseClause(const GoASTCaseClause &) = delete; + const GoASTCaseClause &operator=(const GoASTCaseClause &) = delete; +}; + +class GoASTChanType : public GoASTExpr +{ + public: + GoASTChanType(ChanDir dir, GoASTExpr *value) : GoASTExpr(eChanType), m_dir(dir), m_value_up(value) {} + ~GoASTChanType() override = default; + + const char * + GetKindName() const override + { + return "ChanType"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eChanType; + } + + ChanDir + GetDir() const + { + return m_dir; + } + void + SetDir(ChanDir dir) + { + m_dir = dir; + } + + const GoASTExpr * + GetValue() const + { + return m_value_up.get(); + } + void + SetValue(GoASTExpr *value) + { + m_value_up.reset(value); + } + + private: + friend class GoASTNode; + ChanDir m_dir; + std::unique_ptr m_value_up; + + GoASTChanType(const GoASTChanType &) = delete; + const GoASTChanType &operator=(const GoASTChanType &) = delete; +}; + +class GoASTCommClause : public GoASTStmt +{ + public: + GoASTCommClause() : GoASTStmt(eCommClause) {} + ~GoASTCommClause() override = default; + + const char * + GetKindName() const override + { + return "CommClause"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eCommClause; + } + + const GoASTStmt * + GetComm() const + { + return m_comm_up.get(); + } + void + SetComm(GoASTStmt *comm) + { + m_comm_up.reset(comm); + } + + size_t + NumBody() const + { + return m_body.size(); + } + const GoASTStmt * + GetBody(int i) const + { + return m_body[i].get(); + } + void + AddBody(GoASTStmt *body) + { + m_body.push_back(std::unique_ptr(body)); + } + + private: + friend class GoASTNode; + std::unique_ptr m_comm_up; + std::vector > m_body; + + GoASTCommClause(const GoASTCommClause &) = delete; + const GoASTCommClause &operator=(const GoASTCommClause &) = delete; +}; + +class GoASTCompositeLit : public GoASTExpr +{ + public: + GoASTCompositeLit() : GoASTExpr(eCompositeLit) {} + ~GoASTCompositeLit() override = default; + + const char * + GetKindName() const override + { + return "CompositeLit"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eCompositeLit; + } + + const GoASTExpr * + GetType() const + { + return m_type_up.get(); + } + void + SetType(GoASTExpr *type) + { + m_type_up.reset(type); + } + + size_t + NumElts() const + { + return m_elts.size(); + } + const GoASTExpr * + GetElts(int i) const + { + return m_elts[i].get(); + } + void + AddElts(GoASTExpr *elts) + { + m_elts.push_back(std::unique_ptr(elts)); + } + + private: + friend class GoASTNode; + std::unique_ptr m_type_up; + std::vector > m_elts; + + GoASTCompositeLit(const GoASTCompositeLit &) = delete; + const GoASTCompositeLit &operator=(const GoASTCompositeLit &) = delete; +}; + +class GoASTDeclStmt : public GoASTStmt +{ + public: + explicit GoASTDeclStmt(GoASTDecl *decl) : GoASTStmt(eDeclStmt), m_decl_up(decl) {} + ~GoASTDeclStmt() override = default; + + const char * + GetKindName() const override + { + return "DeclStmt"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eDeclStmt; + } + + const GoASTDecl * + GetDecl() const + { + return m_decl_up.get(); + } + void + SetDecl(GoASTDecl *decl) + { + m_decl_up.reset(decl); + } + + private: + friend class GoASTNode; + std::unique_ptr m_decl_up; + + GoASTDeclStmt(const GoASTDeclStmt &) = delete; + const GoASTDeclStmt &operator=(const GoASTDeclStmt &) = delete; +}; + +class GoASTDeferStmt : public GoASTStmt +{ + public: + explicit GoASTDeferStmt(GoASTCallExpr *call) : GoASTStmt(eDeferStmt), m_call_up(call) {} + ~GoASTDeferStmt() override = default; + + const char * + GetKindName() const override + { + return "DeferStmt"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eDeferStmt; + } + + const GoASTCallExpr * + GetCall() const + { + return m_call_up.get(); + } + void + SetCall(GoASTCallExpr *call) + { + m_call_up.reset(call); + } + + private: + friend class GoASTNode; + std::unique_ptr m_call_up; + + GoASTDeferStmt(const GoASTDeferStmt &) = delete; + const GoASTDeferStmt &operator=(const GoASTDeferStmt &) = delete; +}; + +class GoASTEllipsis : public GoASTExpr +{ + public: + explicit GoASTEllipsis(GoASTExpr *elt) : GoASTExpr(eEllipsis), m_elt_up(elt) {} + ~GoASTEllipsis() override = default; + + const char * + GetKindName() const override + { + return "Ellipsis"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eEllipsis; + } + + const GoASTExpr * + GetElt() const + { + return m_elt_up.get(); + } + void + SetElt(GoASTExpr *elt) + { + m_elt_up.reset(elt); + } + + private: + friend class GoASTNode; + std::unique_ptr m_elt_up; + + GoASTEllipsis(const GoASTEllipsis &) = delete; + const GoASTEllipsis &operator=(const GoASTEllipsis &) = delete; +}; + +class GoASTEmptyStmt : public GoASTStmt +{ + public: + GoASTEmptyStmt() : GoASTStmt(eEmptyStmt) {} + ~GoASTEmptyStmt() override = default; + + const char * + GetKindName() const override + { + return "EmptyStmt"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eEmptyStmt; + } + + GoASTEmptyStmt(const GoASTEmptyStmt &) = delete; + const GoASTEmptyStmt &operator=(const GoASTEmptyStmt &) = delete; +}; + +class GoASTExprStmt : public GoASTStmt +{ + public: + explicit GoASTExprStmt(GoASTExpr *x) : GoASTStmt(eExprStmt), m_x_up(x) {} + ~GoASTExprStmt() override = default; + + const char * + GetKindName() const override + { + return "ExprStmt"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eExprStmt; + } + + const GoASTExpr * + GetX() const + { + return m_x_up.get(); + } + void + SetX(GoASTExpr *x) + { + m_x_up.reset(x); + } + + private: + friend class GoASTNode; + std::unique_ptr m_x_up; + + GoASTExprStmt(const GoASTExprStmt &) = delete; + const GoASTExprStmt &operator=(const GoASTExprStmt &) = delete; +}; + +class GoASTField : public GoASTNode +{ + public: + GoASTField() : GoASTNode(eField) {} + ~GoASTField() override = default; + + const char * + GetKindName() const override + { + return "Field"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eField; + } + + size_t + NumNames() const + { + return m_names.size(); + } + const GoASTIdent * + GetNames(int i) const + { + return m_names[i].get(); + } + void + AddNames(GoASTIdent *names) + { + m_names.push_back(std::unique_ptr(names)); + } + + const GoASTExpr * + GetType() const + { + return m_type_up.get(); + } + void + SetType(GoASTExpr *type) + { + m_type_up.reset(type); + } + + const GoASTBasicLit * + GetTag() const + { + return m_tag_up.get(); + } + void + SetTag(GoASTBasicLit *tag) + { + m_tag_up.reset(tag); + } + + private: + friend class GoASTNode; + std::vector > m_names; + std::unique_ptr m_type_up; + std::unique_ptr m_tag_up; + + GoASTField(const GoASTField &) = delete; + const GoASTField &operator=(const GoASTField &) = delete; +}; + +class GoASTFieldList : public GoASTNode +{ + public: + GoASTFieldList() : GoASTNode(eFieldList) {} + ~GoASTFieldList() override = default; + + const char * + GetKindName() const override + { + return "FieldList"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eFieldList; + } + + size_t + NumList() const + { + return m_list.size(); + } + const GoASTField * + GetList(int i) const + { + return m_list[i].get(); + } + void + AddList(GoASTField *list) + { + m_list.push_back(std::unique_ptr(list)); + } + + private: + friend class GoASTNode; + std::vector > m_list; + + GoASTFieldList(const GoASTFieldList &) = delete; + const GoASTFieldList &operator=(const GoASTFieldList &) = delete; +}; + +class GoASTForStmt : public GoASTStmt +{ + public: + GoASTForStmt(GoASTStmt *init, GoASTExpr *cond, GoASTStmt *post, GoASTBlockStmt *body) : GoASTStmt(eForStmt), m_init_up(init), m_cond_up(cond), m_post_up(post), m_body_up(body) {} + ~GoASTForStmt() override = default; + + const char * + GetKindName() const override + { + return "ForStmt"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eForStmt; + } + + const GoASTStmt * + GetInit() const + { + return m_init_up.get(); + } + void + SetInit(GoASTStmt *init) + { + m_init_up.reset(init); + } + + const GoASTExpr * + GetCond() const + { + return m_cond_up.get(); + } + void + SetCond(GoASTExpr *cond) + { + m_cond_up.reset(cond); + } + + const GoASTStmt * + GetPost() const + { + return m_post_up.get(); + } + void + SetPost(GoASTStmt *post) + { + m_post_up.reset(post); + } + + const GoASTBlockStmt * + GetBody() const + { + return m_body_up.get(); + } + void + SetBody(GoASTBlockStmt *body) + { + m_body_up.reset(body); + } + + private: + friend class GoASTNode; + std::unique_ptr m_init_up; + std::unique_ptr m_cond_up; + std::unique_ptr m_post_up; + std::unique_ptr m_body_up; + + GoASTForStmt(const GoASTForStmt &) = delete; + const GoASTForStmt &operator=(const GoASTForStmt &) = delete; +}; + +class GoASTFuncType : public GoASTExpr +{ + public: + GoASTFuncType(GoASTFieldList *params, GoASTFieldList *results) : GoASTExpr(eFuncType), m_params_up(params), m_results_up(results) {} + ~GoASTFuncType() override = default; + + const char * + GetKindName() const override + { + return "FuncType"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eFuncType; + } + + const GoASTFieldList * + GetParams() const + { + return m_params_up.get(); + } + void + SetParams(GoASTFieldList *params) + { + m_params_up.reset(params); + } + + const GoASTFieldList * + GetResults() const + { + return m_results_up.get(); + } + void + SetResults(GoASTFieldList *results) + { + m_results_up.reset(results); + } + + private: + friend class GoASTNode; + std::unique_ptr m_params_up; + std::unique_ptr m_results_up; + + GoASTFuncType(const GoASTFuncType &) = delete; + const GoASTFuncType &operator=(const GoASTFuncType &) = delete; +}; + +class GoASTFuncDecl : public GoASTDecl +{ + public: + GoASTFuncDecl(GoASTFieldList *recv, GoASTIdent *name, GoASTFuncType *type, GoASTBlockStmt *body) : GoASTDecl(eFuncDecl), m_recv_up(recv), m_name_up(name), m_type_up(type), m_body_up(body) {} + ~GoASTFuncDecl() override = default; + + const char * + GetKindName() const override + { + return "FuncDecl"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eFuncDecl; + } + + const GoASTFieldList * + GetRecv() const + { + return m_recv_up.get(); + } + void + SetRecv(GoASTFieldList *recv) + { + m_recv_up.reset(recv); + } + + const GoASTIdent * + GetName() const + { + return m_name_up.get(); + } + void + SetName(GoASTIdent *name) + { + m_name_up.reset(name); + } + + const GoASTFuncType * + GetType() const + { + return m_type_up.get(); + } + void + SetType(GoASTFuncType *type) + { + m_type_up.reset(type); + } + + const GoASTBlockStmt * + GetBody() const + { + return m_body_up.get(); + } + void + SetBody(GoASTBlockStmt *body) + { + m_body_up.reset(body); + } + + private: + friend class GoASTNode; + std::unique_ptr m_recv_up; + std::unique_ptr m_name_up; + std::unique_ptr m_type_up; + std::unique_ptr m_body_up; + + GoASTFuncDecl(const GoASTFuncDecl &) = delete; + const GoASTFuncDecl &operator=(const GoASTFuncDecl &) = delete; +}; + +class GoASTFuncLit : public GoASTExpr +{ + public: + GoASTFuncLit(GoASTFuncType *type, GoASTBlockStmt *body) : GoASTExpr(eFuncLit), m_type_up(type), m_body_up(body) {} + ~GoASTFuncLit() override = default; + + const char * + GetKindName() const override + { + return "FuncLit"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eFuncLit; + } + + const GoASTFuncType * + GetType() const + { + return m_type_up.get(); + } + void + SetType(GoASTFuncType *type) + { + m_type_up.reset(type); + } + + const GoASTBlockStmt * + GetBody() const + { + return m_body_up.get(); + } + void + SetBody(GoASTBlockStmt *body) + { + m_body_up.reset(body); + } + + private: + friend class GoASTNode; + std::unique_ptr m_type_up; + std::unique_ptr m_body_up; + + GoASTFuncLit(const GoASTFuncLit &) = delete; + const GoASTFuncLit &operator=(const GoASTFuncLit &) = delete; +}; + +class GoASTGenDecl : public GoASTDecl +{ + public: + explicit GoASTGenDecl(TokenType tok) : GoASTDecl(eGenDecl), m_tok(tok) {} + ~GoASTGenDecl() override = default; + + const char * + GetKindName() const override + { + return "GenDecl"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eGenDecl; + } + + TokenType + GetTok() const + { + return m_tok; + } + void + SetTok(TokenType tok) + { + m_tok = tok; + } + + size_t + NumSpecs() const + { + return m_specs.size(); + } + const GoASTSpec * + GetSpecs(int i) const + { + return m_specs[i].get(); + } + void + AddSpecs(GoASTSpec *specs) + { + m_specs.push_back(std::unique_ptr(specs)); + } + + private: + friend class GoASTNode; + TokenType m_tok; + std::vector > m_specs; + + GoASTGenDecl(const GoASTGenDecl &) = delete; + const GoASTGenDecl &operator=(const GoASTGenDecl &) = delete; +}; + +class GoASTGoStmt : public GoASTStmt +{ + public: + explicit GoASTGoStmt(GoASTCallExpr *call) : GoASTStmt(eGoStmt), m_call_up(call) {} + ~GoASTGoStmt() override = default; + + const char * + GetKindName() const override + { + return "GoStmt"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eGoStmt; + } + + const GoASTCallExpr * + GetCall() const + { + return m_call_up.get(); + } + void + SetCall(GoASTCallExpr *call) + { + m_call_up.reset(call); + } + + private: + friend class GoASTNode; + std::unique_ptr m_call_up; + + GoASTGoStmt(const GoASTGoStmt &) = delete; + const GoASTGoStmt &operator=(const GoASTGoStmt &) = delete; +}; + +class GoASTIfStmt : public GoASTStmt +{ + public: + GoASTIfStmt(GoASTStmt *init, GoASTExpr *cond, GoASTBlockStmt *body, GoASTStmt *els) : GoASTStmt(eIfStmt), m_init_up(init), m_cond_up(cond), m_body_up(body), m_els_up(els) {} + ~GoASTIfStmt() override = default; + + const char * + GetKindName() const override + { + return "IfStmt"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eIfStmt; + } + + const GoASTStmt * + GetInit() const + { + return m_init_up.get(); + } + void + SetInit(GoASTStmt *init) + { + m_init_up.reset(init); + } + + const GoASTExpr * + GetCond() const + { + return m_cond_up.get(); + } + void + SetCond(GoASTExpr *cond) + { + m_cond_up.reset(cond); + } + + const GoASTBlockStmt * + GetBody() const + { + return m_body_up.get(); + } + void + SetBody(GoASTBlockStmt *body) + { + m_body_up.reset(body); + } + + const GoASTStmt * + GetEls() const + { + return m_els_up.get(); + } + void + SetEls(GoASTStmt *els) + { + m_els_up.reset(els); + } + + private: + friend class GoASTNode; + std::unique_ptr m_init_up; + std::unique_ptr m_cond_up; + std::unique_ptr m_body_up; + std::unique_ptr m_els_up; + + GoASTIfStmt(const GoASTIfStmt &) = delete; + const GoASTIfStmt &operator=(const GoASTIfStmt &) = delete; +}; + +class GoASTImportSpec : public GoASTSpec +{ + public: + GoASTImportSpec(GoASTIdent *name, GoASTBasicLit *path) : GoASTSpec(eImportSpec), m_name_up(name), m_path_up(path) {} + ~GoASTImportSpec() override = default; + + const char * + GetKindName() const override + { + return "ImportSpec"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eImportSpec; + } + + const GoASTIdent * + GetName() const + { + return m_name_up.get(); + } + void + SetName(GoASTIdent *name) + { + m_name_up.reset(name); + } + + const GoASTBasicLit * + GetPath() const + { + return m_path_up.get(); + } + void + SetPath(GoASTBasicLit *path) + { + m_path_up.reset(path); + } + + private: + friend class GoASTNode; + std::unique_ptr m_name_up; + std::unique_ptr m_path_up; + + GoASTImportSpec(const GoASTImportSpec &) = delete; + const GoASTImportSpec &operator=(const GoASTImportSpec &) = delete; +}; + +class GoASTIncDecStmt : public GoASTStmt +{ + public: + GoASTIncDecStmt(GoASTExpr *x, TokenType tok) : GoASTStmt(eIncDecStmt), m_x_up(x), m_tok(tok) {} + ~GoASTIncDecStmt() override = default; + + const char * + GetKindName() const override + { + return "IncDecStmt"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eIncDecStmt; + } + + const GoASTExpr * + GetX() const + { + return m_x_up.get(); + } + void + SetX(GoASTExpr *x) + { + m_x_up.reset(x); + } + + TokenType + GetTok() const + { + return m_tok; + } + void + SetTok(TokenType tok) + { + m_tok = tok; + } + + private: + friend class GoASTNode; + std::unique_ptr m_x_up; + TokenType m_tok; + + GoASTIncDecStmt(const GoASTIncDecStmt &) = delete; + const GoASTIncDecStmt &operator=(const GoASTIncDecStmt &) = delete; +}; + +class GoASTIndexExpr : public GoASTExpr +{ + public: + GoASTIndexExpr(GoASTExpr *x, GoASTExpr *index) : GoASTExpr(eIndexExpr), m_x_up(x), m_index_up(index) {} + ~GoASTIndexExpr() override = default; + + const char * + GetKindName() const override + { + return "IndexExpr"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eIndexExpr; + } + + const GoASTExpr * + GetX() const + { + return m_x_up.get(); + } + void + SetX(GoASTExpr *x) + { + m_x_up.reset(x); + } + + const GoASTExpr * + GetIndex() const + { + return m_index_up.get(); + } + void + SetIndex(GoASTExpr *index) + { + m_index_up.reset(index); + } + + private: + friend class GoASTNode; + std::unique_ptr m_x_up; + std::unique_ptr m_index_up; + + GoASTIndexExpr(const GoASTIndexExpr &) = delete; + const GoASTIndexExpr &operator=(const GoASTIndexExpr &) = delete; +}; + +class GoASTInterfaceType : public GoASTExpr +{ + public: + explicit GoASTInterfaceType(GoASTFieldList *methods) : GoASTExpr(eInterfaceType), m_methods_up(methods) {} + ~GoASTInterfaceType() override = default; + + const char * + GetKindName() const override + { + return "InterfaceType"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eInterfaceType; + } + + const GoASTFieldList * + GetMethods() const + { + return m_methods_up.get(); + } + void + SetMethods(GoASTFieldList *methods) + { + m_methods_up.reset(methods); + } + + private: + friend class GoASTNode; + std::unique_ptr m_methods_up; + + GoASTInterfaceType(const GoASTInterfaceType &) = delete; + const GoASTInterfaceType &operator=(const GoASTInterfaceType &) = delete; +}; + +class GoASTKeyValueExpr : public GoASTExpr +{ + public: + GoASTKeyValueExpr(GoASTExpr *key, GoASTExpr *value) : GoASTExpr(eKeyValueExpr), m_key_up(key), m_value_up(value) {} + ~GoASTKeyValueExpr() override = default; + + const char * + GetKindName() const override + { + return "KeyValueExpr"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eKeyValueExpr; + } + + const GoASTExpr * + GetKey() const + { + return m_key_up.get(); + } + void + SetKey(GoASTExpr *key) + { + m_key_up.reset(key); + } + + const GoASTExpr * + GetValue() const + { + return m_value_up.get(); + } + void + SetValue(GoASTExpr *value) + { + m_value_up.reset(value); + } + + private: + friend class GoASTNode; + std::unique_ptr m_key_up; + std::unique_ptr m_value_up; + + GoASTKeyValueExpr(const GoASTKeyValueExpr &) = delete; + const GoASTKeyValueExpr &operator=(const GoASTKeyValueExpr &) = delete; +}; + +class GoASTLabeledStmt : public GoASTStmt +{ + public: + GoASTLabeledStmt(GoASTIdent *label, GoASTStmt *stmt) : GoASTStmt(eLabeledStmt), m_label_up(label), m_stmt_up(stmt) {} + ~GoASTLabeledStmt() override = default; + + const char * + GetKindName() const override + { + return "LabeledStmt"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eLabeledStmt; + } + + const GoASTIdent * + GetLabel() const + { + return m_label_up.get(); + } + void + SetLabel(GoASTIdent *label) + { + m_label_up.reset(label); + } + + const GoASTStmt * + GetStmt() const + { + return m_stmt_up.get(); + } + void + SetStmt(GoASTStmt *stmt) + { + m_stmt_up.reset(stmt); + } + + private: + friend class GoASTNode; + std::unique_ptr m_label_up; + std::unique_ptr m_stmt_up; + + GoASTLabeledStmt(const GoASTLabeledStmt &) = delete; + const GoASTLabeledStmt &operator=(const GoASTLabeledStmt &) = delete; +}; + +class GoASTMapType : public GoASTExpr +{ + public: + GoASTMapType(GoASTExpr *key, GoASTExpr *value) : GoASTExpr(eMapType), m_key_up(key), m_value_up(value) {} + ~GoASTMapType() override = default; + + const char * + GetKindName() const override + { + return "MapType"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eMapType; + } + + const GoASTExpr * + GetKey() const + { + return m_key_up.get(); + } + void + SetKey(GoASTExpr *key) + { + m_key_up.reset(key); + } + + const GoASTExpr * + GetValue() const + { + return m_value_up.get(); + } + void + SetValue(GoASTExpr *value) + { + m_value_up.reset(value); + } + + private: + friend class GoASTNode; + std::unique_ptr m_key_up; + std::unique_ptr m_value_up; + + GoASTMapType(const GoASTMapType &) = delete; + const GoASTMapType &operator=(const GoASTMapType &) = delete; +}; + +class GoASTParenExpr : public GoASTExpr +{ + public: + explicit GoASTParenExpr(GoASTExpr *x) : GoASTExpr(eParenExpr), m_x_up(x) {} + ~GoASTParenExpr() override = default; + + const char * + GetKindName() const override + { + return "ParenExpr"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eParenExpr; + } + + const GoASTExpr * + GetX() const + { + return m_x_up.get(); + } + void + SetX(GoASTExpr *x) + { + m_x_up.reset(x); + } + + private: + friend class GoASTNode; + std::unique_ptr m_x_up; + + GoASTParenExpr(const GoASTParenExpr &) = delete; + const GoASTParenExpr &operator=(const GoASTParenExpr &) = delete; +}; + +class GoASTRangeStmt : public GoASTStmt +{ + public: + GoASTRangeStmt(GoASTExpr *key, GoASTExpr *value, bool define, GoASTExpr *x, GoASTBlockStmt *body) : GoASTStmt(eRangeStmt), m_key_up(key), m_value_up(value), m_define(define), m_x_up(x), m_body_up(body) {} + ~GoASTRangeStmt() override = default; + + const char * + GetKindName() const override + { + return "RangeStmt"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eRangeStmt; + } + + const GoASTExpr * + GetKey() const + { + return m_key_up.get(); + } + void + SetKey(GoASTExpr *key) + { + m_key_up.reset(key); + } + + const GoASTExpr * + GetValue() const + { + return m_value_up.get(); + } + void + SetValue(GoASTExpr *value) + { + m_value_up.reset(value); + } + + bool + GetDefine() const + { + return m_define; + } + void + SetDefine(bool define) + { + m_define = define; + } + + const GoASTExpr * + GetX() const + { + return m_x_up.get(); + } + void + SetX(GoASTExpr *x) + { + m_x_up.reset(x); + } + + const GoASTBlockStmt * + GetBody() const + { + return m_body_up.get(); + } + void + SetBody(GoASTBlockStmt *body) + { + m_body_up.reset(body); + } + + private: + friend class GoASTNode; + std::unique_ptr m_key_up; + std::unique_ptr m_value_up; + bool m_define; + std::unique_ptr m_x_up; + std::unique_ptr m_body_up; + + GoASTRangeStmt(const GoASTRangeStmt &) = delete; + const GoASTRangeStmt &operator=(const GoASTRangeStmt &) = delete; +}; + +class GoASTReturnStmt : public GoASTStmt +{ + public: + GoASTReturnStmt() : GoASTStmt(eReturnStmt) {} + ~GoASTReturnStmt() override = default; + + const char * + GetKindName() const override + { + return "ReturnStmt"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eReturnStmt; + } + + size_t + NumResults() const + { + return m_results.size(); + } + const GoASTExpr * + GetResults(int i) const + { + return m_results[i].get(); + } + void + AddResults(GoASTExpr *results) + { + m_results.push_back(std::unique_ptr(results)); + } + + private: + friend class GoASTNode; + std::vector > m_results; + + GoASTReturnStmt(const GoASTReturnStmt &) = delete; + const GoASTReturnStmt &operator=(const GoASTReturnStmt &) = delete; +}; + +class GoASTSelectStmt : public GoASTStmt +{ + public: + explicit GoASTSelectStmt(GoASTBlockStmt *body) : GoASTStmt(eSelectStmt), m_body_up(body) {} + ~GoASTSelectStmt() override = default; + + const char * + GetKindName() const override + { + return "SelectStmt"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eSelectStmt; + } + + const GoASTBlockStmt * + GetBody() const + { + return m_body_up.get(); + } + void + SetBody(GoASTBlockStmt *body) + { + m_body_up.reset(body); + } + + private: + friend class GoASTNode; + std::unique_ptr m_body_up; + + GoASTSelectStmt(const GoASTSelectStmt &) = delete; + const GoASTSelectStmt &operator=(const GoASTSelectStmt &) = delete; +}; + +class GoASTSelectorExpr : public GoASTExpr +{ + public: + GoASTSelectorExpr(GoASTExpr *x, GoASTIdent *sel) : GoASTExpr(eSelectorExpr), m_x_up(x), m_sel_up(sel) {} + ~GoASTSelectorExpr() override = default; + + const char * + GetKindName() const override + { + return "SelectorExpr"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eSelectorExpr; + } + + const GoASTExpr * + GetX() const + { + return m_x_up.get(); + } + void + SetX(GoASTExpr *x) + { + m_x_up.reset(x); + } + + const GoASTIdent * + GetSel() const + { + return m_sel_up.get(); + } + void + SetSel(GoASTIdent *sel) + { + m_sel_up.reset(sel); + } + + private: + friend class GoASTNode; + std::unique_ptr m_x_up; + std::unique_ptr m_sel_up; + + GoASTSelectorExpr(const GoASTSelectorExpr &) = delete; + const GoASTSelectorExpr &operator=(const GoASTSelectorExpr &) = delete; +}; + +class GoASTSendStmt : public GoASTStmt +{ + public: + GoASTSendStmt(GoASTExpr *chan, GoASTExpr *value) : GoASTStmt(eSendStmt), m_chan_up(chan), m_value_up(value) {} + ~GoASTSendStmt() override = default; + + const char * + GetKindName() const override + { + return "SendStmt"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eSendStmt; + } + + const GoASTExpr * + GetChan() const + { + return m_chan_up.get(); + } + void + SetChan(GoASTExpr *chan) + { + m_chan_up.reset(chan); + } + + const GoASTExpr * + GetValue() const + { + return m_value_up.get(); + } + void + SetValue(GoASTExpr *value) + { + m_value_up.reset(value); + } + + private: + friend class GoASTNode; + std::unique_ptr m_chan_up; + std::unique_ptr m_value_up; + + GoASTSendStmt(const GoASTSendStmt &) = delete; + const GoASTSendStmt &operator=(const GoASTSendStmt &) = delete; +}; + +class GoASTSliceExpr : public GoASTExpr +{ + public: + GoASTSliceExpr(GoASTExpr *x, GoASTExpr *low, GoASTExpr *high, GoASTExpr *max, bool slice3) : GoASTExpr(eSliceExpr), m_x_up(x), m_low_up(low), m_high_up(high), m_max_up(max), m_slice3(slice3) {} + ~GoASTSliceExpr() override = default; + + const char * + GetKindName() const override + { + return "SliceExpr"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eSliceExpr; + } + + const GoASTExpr * + GetX() const + { + return m_x_up.get(); + } + void + SetX(GoASTExpr *x) + { + m_x_up.reset(x); + } + + const GoASTExpr * + GetLow() const + { + return m_low_up.get(); + } + void + SetLow(GoASTExpr *low) + { + m_low_up.reset(low); + } + + const GoASTExpr * + GetHigh() const + { + return m_high_up.get(); + } + void + SetHigh(GoASTExpr *high) + { + m_high_up.reset(high); + } + + const GoASTExpr * + GetMax() const + { + return m_max_up.get(); + } + void + SetMax(GoASTExpr *max) + { + m_max_up.reset(max); + } + + bool + GetSlice3() const + { + return m_slice3; + } + void + SetSlice3(bool slice3) + { + m_slice3 = slice3; + } + + private: + friend class GoASTNode; + std::unique_ptr m_x_up; + std::unique_ptr m_low_up; + std::unique_ptr m_high_up; + std::unique_ptr m_max_up; + bool m_slice3; + + GoASTSliceExpr(const GoASTSliceExpr &) = delete; + const GoASTSliceExpr &operator=(const GoASTSliceExpr &) = delete; +}; + +class GoASTStarExpr : public GoASTExpr +{ + public: + explicit GoASTStarExpr(GoASTExpr *x) : GoASTExpr(eStarExpr), m_x_up(x) {} + ~GoASTStarExpr() override = default; + + const char * + GetKindName() const override + { + return "StarExpr"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eStarExpr; + } + + const GoASTExpr * + GetX() const + { + return m_x_up.get(); + } + void + SetX(GoASTExpr *x) + { + m_x_up.reset(x); + } + + private: + friend class GoASTNode; + std::unique_ptr m_x_up; + + GoASTStarExpr(const GoASTStarExpr &) = delete; + const GoASTStarExpr &operator=(const GoASTStarExpr &) = delete; +}; + +class GoASTStructType : public GoASTExpr +{ + public: + explicit GoASTStructType(GoASTFieldList *fields) : GoASTExpr(eStructType), m_fields_up(fields) {} + ~GoASTStructType() override = default; + + const char * + GetKindName() const override + { + return "StructType"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eStructType; + } + + const GoASTFieldList * + GetFields() const + { + return m_fields_up.get(); + } + void + SetFields(GoASTFieldList *fields) + { + m_fields_up.reset(fields); + } + + private: + friend class GoASTNode; + std::unique_ptr m_fields_up; + + GoASTStructType(const GoASTStructType &) = delete; + const GoASTStructType &operator=(const GoASTStructType &) = delete; +}; + +class GoASTSwitchStmt : public GoASTStmt +{ + public: + GoASTSwitchStmt(GoASTStmt *init, GoASTExpr *tag, GoASTBlockStmt *body) : GoASTStmt(eSwitchStmt), m_init_up(init), m_tag_up(tag), m_body_up(body) {} + ~GoASTSwitchStmt() override = default; + + const char * + GetKindName() const override + { + return "SwitchStmt"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eSwitchStmt; + } + + const GoASTStmt * + GetInit() const + { + return m_init_up.get(); + } + void + SetInit(GoASTStmt *init) + { + m_init_up.reset(init); + } + + const GoASTExpr * + GetTag() const + { + return m_tag_up.get(); + } + void + SetTag(GoASTExpr *tag) + { + m_tag_up.reset(tag); + } + + const GoASTBlockStmt * + GetBody() const + { + return m_body_up.get(); + } + void + SetBody(GoASTBlockStmt *body) + { + m_body_up.reset(body); + } + + private: + friend class GoASTNode; + std::unique_ptr m_init_up; + std::unique_ptr m_tag_up; + std::unique_ptr m_body_up; + + GoASTSwitchStmt(const GoASTSwitchStmt &) = delete; + const GoASTSwitchStmt &operator=(const GoASTSwitchStmt &) = delete; +}; + +class GoASTTypeAssertExpr : public GoASTExpr +{ + public: + GoASTTypeAssertExpr(GoASTExpr *x, GoASTExpr *type) : GoASTExpr(eTypeAssertExpr), m_x_up(x), m_type_up(type) {} + ~GoASTTypeAssertExpr() override = default; + + const char * + GetKindName() const override + { + return "TypeAssertExpr"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eTypeAssertExpr; + } + + const GoASTExpr * + GetX() const + { + return m_x_up.get(); + } + void + SetX(GoASTExpr *x) + { + m_x_up.reset(x); + } + + const GoASTExpr * + GetType() const + { + return m_type_up.get(); + } + void + SetType(GoASTExpr *type) + { + m_type_up.reset(type); + } + + private: + friend class GoASTNode; + std::unique_ptr m_x_up; + std::unique_ptr m_type_up; + + GoASTTypeAssertExpr(const GoASTTypeAssertExpr &) = delete; + const GoASTTypeAssertExpr &operator=(const GoASTTypeAssertExpr &) = delete; +}; + +class GoASTTypeSpec : public GoASTSpec +{ + public: + GoASTTypeSpec(GoASTIdent *name, GoASTExpr *type) : GoASTSpec(eTypeSpec), m_name_up(name), m_type_up(type) {} + ~GoASTTypeSpec() override = default; + + const char * + GetKindName() const override + { + return "TypeSpec"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eTypeSpec; + } + + const GoASTIdent * + GetName() const + { + return m_name_up.get(); + } + void + SetName(GoASTIdent *name) + { + m_name_up.reset(name); + } + + const GoASTExpr * + GetType() const + { + return m_type_up.get(); + } + void + SetType(GoASTExpr *type) + { + m_type_up.reset(type); + } + + private: + friend class GoASTNode; + std::unique_ptr m_name_up; + std::unique_ptr m_type_up; + + GoASTTypeSpec(const GoASTTypeSpec &) = delete; + const GoASTTypeSpec &operator=(const GoASTTypeSpec &) = delete; +}; + +class GoASTTypeSwitchStmt : public GoASTStmt +{ + public: + GoASTTypeSwitchStmt(GoASTStmt *init, GoASTStmt *assign, GoASTBlockStmt *body) : GoASTStmt(eTypeSwitchStmt), m_init_up(init), m_assign_up(assign), m_body_up(body) {} + ~GoASTTypeSwitchStmt() override = default; + + const char * + GetKindName() const override + { + return "TypeSwitchStmt"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eTypeSwitchStmt; + } + + const GoASTStmt * + GetInit() const + { + return m_init_up.get(); + } + void + SetInit(GoASTStmt *init) + { + m_init_up.reset(init); + } + + const GoASTStmt * + GetAssign() const + { + return m_assign_up.get(); + } + void + SetAssign(GoASTStmt *assign) + { + m_assign_up.reset(assign); + } + + const GoASTBlockStmt * + GetBody() const + { + return m_body_up.get(); + } + void + SetBody(GoASTBlockStmt *body) + { + m_body_up.reset(body); + } + + private: + friend class GoASTNode; + std::unique_ptr m_init_up; + std::unique_ptr m_assign_up; + std::unique_ptr m_body_up; + + GoASTTypeSwitchStmt(const GoASTTypeSwitchStmt &) = delete; + const GoASTTypeSwitchStmt &operator=(const GoASTTypeSwitchStmt &) = delete; +}; + +class GoASTUnaryExpr : public GoASTExpr +{ + public: + GoASTUnaryExpr(TokenType op, GoASTExpr *x) : GoASTExpr(eUnaryExpr), m_op(op), m_x_up(x) {} + ~GoASTUnaryExpr() override = default; + + const char * + GetKindName() const override + { + return "UnaryExpr"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eUnaryExpr; + } + + TokenType + GetOp() const + { + return m_op; + } + void + SetOp(TokenType op) + { + m_op = op; + } + + const GoASTExpr * + GetX() const + { + return m_x_up.get(); + } + void + SetX(GoASTExpr *x) + { + m_x_up.reset(x); + } + + private: + friend class GoASTNode; + TokenType m_op; + std::unique_ptr m_x_up; + + GoASTUnaryExpr(const GoASTUnaryExpr &) = delete; + const GoASTUnaryExpr &operator=(const GoASTUnaryExpr &) = delete; +}; + +class GoASTValueSpec : public GoASTSpec +{ + public: + GoASTValueSpec() : GoASTSpec(eValueSpec) {} + ~GoASTValueSpec() override = default; + + const char * + GetKindName() const override + { + return "ValueSpec"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == eValueSpec; + } + + size_t + NumNames() const + { + return m_names.size(); + } + const GoASTIdent * + GetNames(int i) const + { + return m_names[i].get(); + } + void + AddNames(GoASTIdent *names) + { + m_names.push_back(std::unique_ptr(names)); + } + + const GoASTExpr * + GetType() const + { + return m_type_up.get(); + } + void + SetType(GoASTExpr *type) + { + m_type_up.reset(type); + } + + size_t + NumValues() const + { + return m_values.size(); + } + const GoASTExpr * + GetValues(int i) const + { + return m_values[i].get(); + } + void + AddValues(GoASTExpr *values) + { + m_values.push_back(std::unique_ptr(values)); + } + + private: + friend class GoASTNode; + std::vector > m_names; + std::unique_ptr m_type_up; + std::vector > m_values; + + GoASTValueSpec(const GoASTValueSpec &) = delete; + const GoASTValueSpec &operator=(const GoASTValueSpec &) = delete; +}; + + +template +R GoASTDecl::Visit(V* v) const +{ + switch(GetKind()) + { + case eBadDecl: + return v->VisitBadDecl(llvm::cast(this)); + case eFuncDecl: + return v->VisitFuncDecl(llvm::cast(this)); + case eGenDecl: + return v->VisitGenDecl(llvm::cast(this)); + default: + assert(false && "Invalid kind"); + } +} + +template +R GoASTExpr::Visit(V* v) const +{ + switch(GetKind()) + { + case eArrayType: + return v->VisitArrayType(llvm::cast(this)); + case eBadExpr: + return v->VisitBadExpr(llvm::cast(this)); + case eBasicLit: + return v->VisitBasicLit(llvm::cast(this)); + case eBinaryExpr: + return v->VisitBinaryExpr(llvm::cast(this)); + case eIdent: + return v->VisitIdent(llvm::cast(this)); + case eCallExpr: + return v->VisitCallExpr(llvm::cast(this)); + case eChanType: + return v->VisitChanType(llvm::cast(this)); + case eCompositeLit: + return v->VisitCompositeLit(llvm::cast(this)); + case eEllipsis: + return v->VisitEllipsis(llvm::cast(this)); + case eFuncType: + return v->VisitFuncType(llvm::cast(this)); + case eFuncLit: + return v->VisitFuncLit(llvm::cast(this)); + case eIndexExpr: + return v->VisitIndexExpr(llvm::cast(this)); + case eInterfaceType: + return v->VisitInterfaceType(llvm::cast(this)); + case eKeyValueExpr: + return v->VisitKeyValueExpr(llvm::cast(this)); + case eMapType: + return v->VisitMapType(llvm::cast(this)); + case eParenExpr: + return v->VisitParenExpr(llvm::cast(this)); + case eSelectorExpr: + return v->VisitSelectorExpr(llvm::cast(this)); + case eSliceExpr: + return v->VisitSliceExpr(llvm::cast(this)); + case eStarExpr: + return v->VisitStarExpr(llvm::cast(this)); + case eStructType: + return v->VisitStructType(llvm::cast(this)); + case eTypeAssertExpr: + return v->VisitTypeAssertExpr(llvm::cast(this)); + case eUnaryExpr: + return v->VisitUnaryExpr(llvm::cast(this)); + default: + assert(false && "Invalid kind"); + } +} + +template +R GoASTSpec::Visit(V* v) const +{ + switch(GetKind()) + { + case eImportSpec: + return v->VisitImportSpec(llvm::cast(this)); + case eTypeSpec: + return v->VisitTypeSpec(llvm::cast(this)); + case eValueSpec: + return v->VisitValueSpec(llvm::cast(this)); + default: + assert(false && "Invalid kind"); + } +} + +template +R GoASTStmt::Visit(V* v) const +{ + switch(GetKind()) + { + case eAssignStmt: + return v->VisitAssignStmt(llvm::cast(this)); + case eBadStmt: + return v->VisitBadStmt(llvm::cast(this)); + case eBlockStmt: + return v->VisitBlockStmt(llvm::cast(this)); + case eBranchStmt: + return v->VisitBranchStmt(llvm::cast(this)); + case eCaseClause: + return v->VisitCaseClause(llvm::cast(this)); + case eCommClause: + return v->VisitCommClause(llvm::cast(this)); + case eDeclStmt: + return v->VisitDeclStmt(llvm::cast(this)); + case eDeferStmt: + return v->VisitDeferStmt(llvm::cast(this)); + case eEmptyStmt: + return v->VisitEmptyStmt(llvm::cast(this)); + case eExprStmt: + return v->VisitExprStmt(llvm::cast(this)); + case eForStmt: + return v->VisitForStmt(llvm::cast(this)); + case eGoStmt: + return v->VisitGoStmt(llvm::cast(this)); + case eIfStmt: + return v->VisitIfStmt(llvm::cast(this)); + case eIncDecStmt: + return v->VisitIncDecStmt(llvm::cast(this)); + case eLabeledStmt: + return v->VisitLabeledStmt(llvm::cast(this)); + case eRangeStmt: + return v->VisitRangeStmt(llvm::cast(this)); + case eReturnStmt: + return v->VisitReturnStmt(llvm::cast(this)); + case eSelectStmt: + return v->VisitSelectStmt(llvm::cast(this)); + case eSendStmt: + return v->VisitSendStmt(llvm::cast(this)); + case eSwitchStmt: + return v->VisitSwitchStmt(llvm::cast(this)); + case eTypeSwitchStmt: + return v->VisitTypeSwitchStmt(llvm::cast(this)); + default: + assert(false && "Invalid kind"); + } +} + +template +void GoASTNode::WalkChildren(V &v) +{ + switch (m_kind) + { + + + case eArrayType: + { + GoASTArrayType *n = llvm::cast(this); + (void)n; + v(n->m_len_up.get()); + v(n->m_elt_up.get()); + return; + } + case eAssignStmt: + { + GoASTAssignStmt *n = llvm::cast(this); + (void)n; + for (auto& e : n->m_lhs) { v(e.get()); } + for (auto& e : n->m_rhs) { v(e.get()); } + return; + } + case eBasicLit: + { + GoASTBasicLit *n = llvm::cast(this); + (void)n; + return; + } + case eBinaryExpr: + { + GoASTBinaryExpr *n = llvm::cast(this); + (void)n; + v(n->m_x_up.get()); + v(n->m_y_up.get()); + return; + } + case eBlockStmt: + { + GoASTBlockStmt *n = llvm::cast(this); + (void)n; + for (auto& e : n->m_list) { v(e.get()); } + return; + } + case eIdent: + { + GoASTIdent *n = llvm::cast(this); + (void)n; + return; + } + case eBranchStmt: + { + GoASTBranchStmt *n = llvm::cast(this); + (void)n; + v(n->m_label_up.get()); + return; + } + case eCallExpr: + { + GoASTCallExpr *n = llvm::cast(this); + (void)n; + v(n->m_fun_up.get()); + for (auto& e : n->m_args) { v(e.get()); } + return; + } + case eCaseClause: + { + GoASTCaseClause *n = llvm::cast(this); + (void)n; + for (auto& e : n->m_list) { v(e.get()); } + for (auto& e : n->m_body) { v(e.get()); } + return; + } + case eChanType: + { + GoASTChanType *n = llvm::cast(this); + (void)n; + v(n->m_value_up.get()); + return; + } + case eCommClause: + { + GoASTCommClause *n = llvm::cast(this); + (void)n; + v(n->m_comm_up.get()); + for (auto& e : n->m_body) { v(e.get()); } + return; + } + case eCompositeLit: + { + GoASTCompositeLit *n = llvm::cast(this); + (void)n; + v(n->m_type_up.get()); + for (auto& e : n->m_elts) { v(e.get()); } + return; + } + case eDeclStmt: + { + GoASTDeclStmt *n = llvm::cast(this); + (void)n; + v(n->m_decl_up.get()); + return; + } + case eDeferStmt: + { + GoASTDeferStmt *n = llvm::cast(this); + (void)n; + v(n->m_call_up.get()); + return; + } + case eEllipsis: + { + GoASTEllipsis *n = llvm::cast(this); + (void)n; + v(n->m_elt_up.get()); + return; + } + case eExprStmt: + { + GoASTExprStmt *n = llvm::cast(this); + (void)n; + v(n->m_x_up.get()); + return; + } + case eField: + { + GoASTField *n = llvm::cast(this); + (void)n; + for (auto& e : n->m_names) { v(e.get()); } + v(n->m_type_up.get()); + v(n->m_tag_up.get()); + return; + } + case eFieldList: + { + GoASTFieldList *n = llvm::cast(this); + (void)n; + for (auto& e : n->m_list) { v(e.get()); } + return; + } + case eForStmt: + { + GoASTForStmt *n = llvm::cast(this); + (void)n; + v(n->m_init_up.get()); + v(n->m_cond_up.get()); + v(n->m_post_up.get()); + v(n->m_body_up.get()); + return; + } + case eFuncType: + { + GoASTFuncType *n = llvm::cast(this); + (void)n; + v(n->m_params_up.get()); + v(n->m_results_up.get()); + return; + } + case eFuncDecl: + { + GoASTFuncDecl *n = llvm::cast(this); + (void)n; + v(n->m_recv_up.get()); + v(n->m_name_up.get()); + v(n->m_type_up.get()); + v(n->m_body_up.get()); + return; + } + case eFuncLit: + { + GoASTFuncLit *n = llvm::cast(this); + (void)n; + v(n->m_type_up.get()); + v(n->m_body_up.get()); + return; + } + case eGenDecl: + { + GoASTGenDecl *n = llvm::cast(this); + (void)n; + for (auto& e : n->m_specs) { v(e.get()); } + return; + } + case eGoStmt: + { + GoASTGoStmt *n = llvm::cast(this); + (void)n; + v(n->m_call_up.get()); + return; + } + case eIfStmt: + { + GoASTIfStmt *n = llvm::cast(this); + (void)n; + v(n->m_init_up.get()); + v(n->m_cond_up.get()); + v(n->m_body_up.get()); + v(n->m_els_up.get()); + return; + } + case eImportSpec: + { + GoASTImportSpec *n = llvm::cast(this); + (void)n; + v(n->m_name_up.get()); + v(n->m_path_up.get()); + return; + } + case eIncDecStmt: + { + GoASTIncDecStmt *n = llvm::cast(this); + (void)n; + v(n->m_x_up.get()); + return; + } + case eIndexExpr: + { + GoASTIndexExpr *n = llvm::cast(this); + (void)n; + v(n->m_x_up.get()); + v(n->m_index_up.get()); + return; + } + case eInterfaceType: + { + GoASTInterfaceType *n = llvm::cast(this); + (void)n; + v(n->m_methods_up.get()); + return; + } + case eKeyValueExpr: + { + GoASTKeyValueExpr *n = llvm::cast(this); + (void)n; + v(n->m_key_up.get()); + v(n->m_value_up.get()); + return; + } + case eLabeledStmt: + { + GoASTLabeledStmt *n = llvm::cast(this); + (void)n; + v(n->m_label_up.get()); + v(n->m_stmt_up.get()); + return; + } + case eMapType: + { + GoASTMapType *n = llvm::cast(this); + (void)n; + v(n->m_key_up.get()); + v(n->m_value_up.get()); + return; + } + case eParenExpr: + { + GoASTParenExpr *n = llvm::cast(this); + (void)n; + v(n->m_x_up.get()); + return; + } + case eRangeStmt: + { + GoASTRangeStmt *n = llvm::cast(this); + (void)n; + v(n->m_key_up.get()); + v(n->m_value_up.get()); + v(n->m_x_up.get()); + v(n->m_body_up.get()); + return; + } + case eReturnStmt: + { + GoASTReturnStmt *n = llvm::cast(this); + (void)n; + for (auto& e : n->m_results) { v(e.get()); } + return; + } + case eSelectStmt: + { + GoASTSelectStmt *n = llvm::cast(this); + (void)n; + v(n->m_body_up.get()); + return; + } + case eSelectorExpr: + { + GoASTSelectorExpr *n = llvm::cast(this); + (void)n; + v(n->m_x_up.get()); + v(n->m_sel_up.get()); + return; + } + case eSendStmt: + { + GoASTSendStmt *n = llvm::cast(this); + (void)n; + v(n->m_chan_up.get()); + v(n->m_value_up.get()); + return; + } + case eSliceExpr: + { + GoASTSliceExpr *n = llvm::cast(this); + (void)n; + v(n->m_x_up.get()); + v(n->m_low_up.get()); + v(n->m_high_up.get()); + v(n->m_max_up.get()); + return; + } + case eStarExpr: + { + GoASTStarExpr *n = llvm::cast(this); + (void)n; + v(n->m_x_up.get()); + return; + } + case eStructType: + { + GoASTStructType *n = llvm::cast(this); + (void)n; + v(n->m_fields_up.get()); + return; + } + case eSwitchStmt: + { + GoASTSwitchStmt *n = llvm::cast(this); + (void)n; + v(n->m_init_up.get()); + v(n->m_tag_up.get()); + v(n->m_body_up.get()); + return; + } + case eTypeAssertExpr: + { + GoASTTypeAssertExpr *n = llvm::cast(this); + (void)n; + v(n->m_x_up.get()); + v(n->m_type_up.get()); + return; + } + case eTypeSpec: + { + GoASTTypeSpec *n = llvm::cast(this); + (void)n; + v(n->m_name_up.get()); + v(n->m_type_up.get()); + return; + } + case eTypeSwitchStmt: + { + GoASTTypeSwitchStmt *n = llvm::cast(this); + (void)n; + v(n->m_init_up.get()); + v(n->m_assign_up.get()); + v(n->m_body_up.get()); + return; + } + case eUnaryExpr: + { + GoASTUnaryExpr *n = llvm::cast(this); + (void)n; + v(n->m_x_up.get()); + return; + } + case eValueSpec: + { + GoASTValueSpec *n = llvm::cast(this); + (void)n; + for (auto& e : n->m_names) { v(e.get()); } + v(n->m_type_up.get()); + for (auto& e : n->m_values) { v(e.get()); } + return; + } + + case eEmptyStmt: + case eBadDecl: + case eBadExpr: + case eBadStmt: + break; + } +} + +} // namespace lldb_private + +#endif + diff --git a/source/Plugins/ExpressionParser/Go/GoLexer.cpp b/source/Plugins/ExpressionParser/Go/GoLexer.cpp new file mode 100644 index 0000000000000..6de0f5619ca8c --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoLexer.cpp @@ -0,0 +1,402 @@ +//===-- GoLexer.cpp ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include + +#include "GoLexer.h" + +using namespace lldb_private; + +llvm::StringMap *GoLexer::m_keywords; + +GoLexer::GoLexer(const char *src) : m_src(src), m_end(src + strlen(src)), m_last_token(TOK_INVALID, "") +{ +} + +bool +GoLexer::SkipWhitespace() +{ + bool saw_newline = false; + for (; m_src < m_end; ++m_src) + { + if (*m_src == '\n') + saw_newline = true; + if (*m_src == '/' && !SkipComment()) + return saw_newline; + else if (!IsWhitespace(*m_src)) + return saw_newline; + } + return saw_newline; +} + +bool +GoLexer::SkipComment() +{ + if (m_src[0] == '/' && m_src[1] == '/') + { + for (const char *c = m_src + 2; c < m_end; ++c) + { + if (*c == '\n') + { + m_src = c - 1; + return true; + } + } + return true; + } + else if (m_src[0] == '/' && m_src[1] == '*') + { + for (const char *c = m_src + 2; c < m_end; ++c) + { + if (c[0] == '*' && c[1] == '/') + { + m_src = c + 1; + return true; + } + } + } + return false; +} + +const GoLexer::Token & +GoLexer::Lex() +{ + bool newline = SkipWhitespace(); + const char *start = m_src; + m_last_token.m_type = InternalLex(newline); + m_last_token.m_value = llvm::StringRef(start, m_src - start); + return m_last_token; +} + +GoLexer::TokenType +GoLexer::InternalLex(bool newline) +{ + if (m_src >= m_end) + { + return TOK_EOF; + } + if (newline) + { + switch (m_last_token.m_type) + { + case TOK_IDENTIFIER: + case LIT_FLOAT: + case LIT_IMAGINARY: + case LIT_INTEGER: + case LIT_RUNE: + case LIT_STRING: + case KEYWORD_BREAK: + case KEYWORD_CONTINUE: + case KEYWORD_FALLTHROUGH: + case KEYWORD_RETURN: + case OP_PLUS_PLUS: + case OP_MINUS_MINUS: + case OP_RPAREN: + case OP_RBRACK: + case OP_RBRACE: + return OP_SEMICOLON; + default: + break; + } + } + char c = *m_src; + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return DoNumber(); + case '+': + case '-': + case '*': + case '/': + case '%': + case '&': + case '|': + case '^': + case '<': + case '>': + case '!': + case ':': + case ';': + case '(': + case ')': + case '[': + case ']': + case '{': + case '}': + case ',': + case '=': + return DoOperator(); + case '.': + if (IsDecimal(m_src[1])) + return DoNumber(); + return DoOperator(); + case '$': + // For lldb persistent vars. + return DoIdent(); + case '"': + case '`': + return DoString(); + case '\'': + return DoRune(); + default: + break; + } + if (IsLetterOrDigit(c)) + return DoIdent(); + ++m_src; + return TOK_INVALID; +} + +GoLexer::TokenType +GoLexer::DoOperator() +{ + TokenType t = TOK_INVALID; + if (m_end - m_src > 2) + { + t = LookupKeyword(llvm::StringRef(m_src, 3)); + if (t != TOK_INVALID) + m_src += 3; + } + if (t == TOK_INVALID && m_end - m_src > 1) + { + t = LookupKeyword(llvm::StringRef(m_src, 2)); + if (t != TOK_INVALID) + m_src += 2; + } + if (t == TOK_INVALID) + { + t = LookupKeyword(llvm::StringRef(m_src, 1)); + ++m_src; + } + return t; +} + +GoLexer::TokenType +GoLexer::DoIdent() +{ + const char *start = m_src++; + while (m_src < m_end && IsLetterOrDigit(*m_src)) + { + ++m_src; + } + TokenType kw = LookupKeyword(llvm::StringRef(start, m_src - start)); + if (kw != TOK_INVALID) + return kw; + return TOK_IDENTIFIER; +} + +GoLexer::TokenType +GoLexer::DoNumber() +{ + if (m_src[0] == '0' && (m_src[1] == 'x' || m_src[1] == 'X')) + { + m_src += 2; + while (IsHexChar(*m_src)) + ++m_src; + return LIT_INTEGER; + } + bool dot_ok = true; + bool e_ok = true; + while (true) + { + while (IsDecimal(*m_src)) + ++m_src; + switch (*m_src) + { + case 'i': + ++m_src; + return LIT_IMAGINARY; + case '.': + if (!dot_ok) + return LIT_FLOAT; + ++m_src; + dot_ok = false; + break; + case 'e': + case 'E': + if (!e_ok) + return LIT_FLOAT; + dot_ok = e_ok = false; + ++m_src; + if (*m_src == '+' || *m_src == '-') + ++m_src; + break; + default: + if (dot_ok) + return LIT_INTEGER; + return LIT_FLOAT; + } + } +} + +GoLexer::TokenType +GoLexer::DoRune() +{ + while (++m_src < m_end) + { + switch (*m_src) + { + case '\'': + ++m_src; + return LIT_RUNE; + case '\n': + return TOK_INVALID; + case '\\': + if (m_src[1] == '\n') + return TOK_INVALID; + ++m_src; + } + } + return TOK_INVALID; +} + +GoLexer::TokenType +GoLexer::DoString() +{ + if (*m_src == '`') + { + while (++m_src < m_end) + { + if (*m_src == '`') + { + ++m_src; + return LIT_STRING; + } + } + return TOK_INVALID; + } + while (++m_src < m_end) + { + switch (*m_src) + { + case '"': + ++m_src; + return LIT_STRING; + case '\n': + return TOK_INVALID; + case '\\': + if (m_src[1] == '\n') + return TOK_INVALID; + ++m_src; + } + } + return TOK_INVALID; +} + +GoLexer::TokenType +GoLexer::LookupKeyword(llvm::StringRef id) +{ + if (m_keywords == nullptr) + m_keywords = InitKeywords(); + const auto &it = m_keywords->find(id); + if (it == m_keywords->end()) + return TOK_INVALID; + return it->second; +} + +llvm::StringRef +GoLexer::LookupToken(TokenType t) +{ + if (m_keywords == nullptr) + m_keywords = InitKeywords(); + for (const auto &e : *m_keywords) + { + if (e.getValue() == t) + return e.getKey(); + } + return ""; +} + +llvm::StringMap * +GoLexer::InitKeywords() +{ + auto &result = *new llvm::StringMap(128); + result["break"] = KEYWORD_BREAK; + result["default"] = KEYWORD_DEFAULT; + result["func"] = KEYWORD_FUNC; + result["interface"] = KEYWORD_INTERFACE; + result["select"] = KEYWORD_SELECT; + result["case"] = KEYWORD_CASE; + result["defer"] = KEYWORD_DEFER; + result["go"] = KEYWORD_GO; + result["map"] = KEYWORD_MAP; + result["struct"] = KEYWORD_STRUCT; + result["chan"] = KEYWORD_CHAN; + result["else"] = KEYWORD_ELSE; + result["goto"] = KEYWORD_GOTO; + result["package"] = KEYWORD_PACKAGE; + result["switch"] = KEYWORD_SWITCH; + result["const"] = KEYWORD_CONST; + result["fallthrough"] = KEYWORD_FALLTHROUGH; + result["if"] = KEYWORD_IF; + result["range"] = KEYWORD_RANGE; + result["type"] = KEYWORD_TYPE; + result["continue"] = KEYWORD_CONTINUE; + result["for"] = KEYWORD_FOR; + result["import"] = KEYWORD_IMPORT; + result["return"] = KEYWORD_RETURN; + result["var"] = KEYWORD_VAR; + result["+"] = OP_PLUS; + result["-"] = OP_MINUS; + result["*"] = OP_STAR; + result["/"] = OP_SLASH; + result["%"] = OP_PERCENT; + result["&"] = OP_AMP; + result["|"] = OP_PIPE; + result["^"] = OP_CARET; + result["<<"] = OP_LSHIFT; + result[">>"] = OP_RSHIFT; + result["&^"] = OP_AMP_CARET; + result["+="] = OP_PLUS_EQ; + result["-="] = OP_MINUS_EQ; + result["*="] = OP_STAR_EQ; + result["/="] = OP_SLASH_EQ; + result["%="] = OP_PERCENT_EQ; + result["&="] = OP_AMP_EQ; + result["|="] = OP_PIPE_EQ; + result["^="] = OP_CARET_EQ; + result["<<="] = OP_LSHIFT_EQ; + result[">>="] = OP_RSHIFT_EQ; + result["&^="] = OP_AMP_CARET_EQ; + result["&&"] = OP_AMP_AMP; + result["||"] = OP_PIPE_PIPE; + result["<-"] = OP_LT_MINUS; + result["++"] = OP_PLUS_PLUS; + result["--"] = OP_MINUS_MINUS; + result["=="] = OP_EQ_EQ; + result["<"] = OP_LT; + result[">"] = OP_GT; + result["="] = OP_EQ; + result["!"] = OP_BANG; + result["!="] = OP_BANG_EQ; + result["<="] = OP_LT_EQ; + result[">="] = OP_GT_EQ; + result[":="] = OP_COLON_EQ; + result["..."] = OP_DOTS; + result["("] = OP_LPAREN; + result["["] = OP_LBRACK; + result["{"] = OP_LBRACE; + result[","] = OP_COMMA; + result["."] = OP_DOT; + result[")"] = OP_RPAREN; + result["]"] = OP_RBRACK; + result["}"] = OP_RBRACE; + result[";"] = OP_SEMICOLON; + result[":"] = OP_COLON; + return &result; +} diff --git a/source/Plugins/ExpressionParser/Go/GoLexer.h b/source/Plugins/ExpressionParser/Go/GoLexer.h new file mode 100644 index 0000000000000..e8e1635bab771 --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoLexer.h @@ -0,0 +1,201 @@ +//===-- GoLexer.h -----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_GoLexer_h +#define liblldb_GoLexer_h + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringMap.h" + +namespace lldb_private +{ + +class GoLexer +{ + public: + explicit GoLexer(const char *src); + + enum TokenType + { + TOK_EOF, + TOK_INVALID, + TOK_IDENTIFIER, + LIT_INTEGER, + LIT_FLOAT, + LIT_IMAGINARY, + LIT_RUNE, + LIT_STRING, + KEYWORD_BREAK, + KEYWORD_DEFAULT, + KEYWORD_FUNC, + KEYWORD_INTERFACE, + KEYWORD_SELECT, + KEYWORD_CASE, + KEYWORD_DEFER, + KEYWORD_GO, + KEYWORD_MAP, + KEYWORD_STRUCT, + KEYWORD_CHAN, + KEYWORD_ELSE, + KEYWORD_GOTO, + KEYWORD_PACKAGE, + KEYWORD_SWITCH, + KEYWORD_CONST, + KEYWORD_FALLTHROUGH, + KEYWORD_IF, + KEYWORD_RANGE, + KEYWORD_TYPE, + KEYWORD_CONTINUE, + KEYWORD_FOR, + KEYWORD_IMPORT, + KEYWORD_RETURN, + KEYWORD_VAR, + OP_PLUS, + OP_MINUS, + OP_STAR, + OP_SLASH, + OP_PERCENT, + OP_AMP, + OP_PIPE, + OP_CARET, + OP_LSHIFT, + OP_RSHIFT, + OP_AMP_CARET, + OP_PLUS_EQ, + OP_MINUS_EQ, + OP_STAR_EQ, + OP_SLASH_EQ, + OP_PERCENT_EQ, + OP_AMP_EQ, + OP_PIPE_EQ, + OP_CARET_EQ, + OP_LSHIFT_EQ, + OP_RSHIFT_EQ, + OP_AMP_CARET_EQ, + OP_AMP_AMP, + OP_PIPE_PIPE, + OP_LT_MINUS, + OP_PLUS_PLUS, + OP_MINUS_MINUS, + OP_EQ_EQ, + OP_LT, + OP_GT, + OP_EQ, + OP_BANG, + OP_BANG_EQ, + OP_LT_EQ, + OP_GT_EQ, + OP_COLON_EQ, + OP_DOTS, + OP_LPAREN, + OP_LBRACK, + OP_LBRACE, + OP_COMMA, + OP_DOT, + OP_RPAREN, + OP_RBRACK, + OP_RBRACE, + OP_SEMICOLON, + OP_COLON, + }; + + struct Token + { + explicit Token(TokenType t, llvm::StringRef text) : m_type(t), m_value(text) {} + TokenType m_type; + llvm::StringRef m_value; + }; + + const Token &Lex(); + + size_t + BytesRemaining() const + { + return m_end - m_src; + } + llvm::StringRef + GetString(int len) const + { + return llvm::StringRef(m_src, len); + } + + static TokenType LookupKeyword(llvm::StringRef id); + static llvm::StringRef LookupToken(TokenType t); + + private: + bool + IsDecimal(char c) + { + return c >= '0' && c <= '9'; + } + bool + IsHexChar(char c) + { + if (c >= '0' && c <= '9') + return true; + if (c >= 'A' && c <= 'F') + return true; + if (c >= 'a' && c <= 'f') + return true; + return false; + } + bool + IsLetterOrDigit(char c) + { + if (c >= 'a' && c <= 'z') + return true; + if (c >= 'A' && c <= 'Z') + return true; + if (c == '_') + return true; + if (c >= '0' && c <= '9') + return true; + // Treat all non-ascii chars as letters for simplicity. + return 0 != (c & 0x80); + } + bool + IsWhitespace(char c) + { + switch (c) + { + case ' ': + case '\t': + case '\r': + return true; + } + return false; + } + + bool SkipWhitespace(); + bool SkipComment(); + + TokenType InternalLex(bool newline); + + TokenType DoOperator(); + + TokenType DoIdent(); + + TokenType DoNumber(); + + TokenType DoRune(); + + TokenType DoString(); + + static llvm::StringMap *InitKeywords(); + + static llvm::StringMap *m_keywords; + + const char *m_src; + const char *m_end; + Token m_last_token; +}; + +} // namespace lldb_private + +#endif diff --git a/source/Plugins/ExpressionParser/Go/GoParser.cpp b/source/Plugins/ExpressionParser/Go/GoParser.cpp new file mode 100644 index 0000000000000..0f136f7e61dc8 --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoParser.cpp @@ -0,0 +1,1035 @@ +//===-- GoParser.cpp ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include + +#include "GoParser.h" + +#include "lldb/Core/Error.h" +#include "llvm/ADT/SmallString.h" +#include "Plugins/ExpressionParser/Go/GoAST.h" + +using namespace lldb_private; +using namespace lldb; + +namespace +{ +llvm::StringRef +DescribeToken(GoLexer::TokenType t) +{ + switch (t) + { + case GoLexer::TOK_EOF: + return ""; + case GoLexer::TOK_IDENTIFIER: + return "identifier"; + case GoLexer::LIT_FLOAT: + return "float"; + case GoLexer::LIT_IMAGINARY: + return "imaginary"; + case GoLexer::LIT_INTEGER: + return "integer"; + case GoLexer::LIT_RUNE: + return "rune"; + case GoLexer::LIT_STRING: + return "string"; + default: + return GoLexer::LookupToken(t); + } +} +} // namespace + +class GoParser::Rule +{ + public: + Rule(llvm::StringRef name, GoParser *p) : m_name(name), m_parser(p), m_pos(p->m_pos) {} + + std::nullptr_t + error() + { + if (!m_parser->m_failed) + { + // Set m_error in case this is the top level. + if (m_parser->m_last_tok == GoLexer::TOK_INVALID) + m_parser->m_error = m_parser->m_last; + else + m_parser->m_error = DescribeToken(m_parser->m_last_tok); + // And set m_last in case it isn't. + m_parser->m_last = m_name; + m_parser->m_last_tok = GoLexer::TOK_INVALID; + m_parser->m_pos = m_pos; + } + return nullptr; + } + + private: + llvm::StringRef m_name; + GoParser *m_parser; + size_t m_pos; +}; + +GoParser::GoParser(const char *src) : m_lexer(src), m_pos(0), m_failed(false) +{ +} + +GoASTStmt * +GoParser::Statement() +{ + Rule r("Statement", this); + GoLexer::TokenType t = peek(); + GoASTStmt *ret = nullptr; + switch (t) + { + case GoLexer::TOK_EOF: + case GoLexer::OP_SEMICOLON: + case GoLexer::OP_RPAREN: + case GoLexer::OP_RBRACE: + case GoLexer::TOK_INVALID: + return EmptyStmt(); + case GoLexer::OP_LBRACE: + return Block(); + + /* TODO: + case GoLexer::KEYWORD_GO: + return GoStmt(); + case GoLexer::KEYWORD_RETURN: + return ReturnStmt(); + case GoLexer::KEYWORD_BREAK: + case GoLexer::KEYWORD_CONTINUE: + case GoLexer::KEYWORD_GOTO: + case GoLexer::KEYWORD_FALLTHROUGH: + return BranchStmt(); + case GoLexer::KEYWORD_IF: + return IfStmt(); + case GoLexer::KEYWORD_SWITCH: + return SwitchStmt(); + case GoLexer::KEYWORD_SELECT: + return SelectStmt(); + case GoLexer::KEYWORD_FOR: + return ForStmt(); + case GoLexer::KEYWORD_DEFER: + return DeferStmt(); + case GoLexer::KEYWORD_CONST: + case GoLexer::KEYWORD_TYPE: + case GoLexer::KEYWORD_VAR: + return DeclStmt(); + case GoLexer::TOK_IDENTIFIER: + if ((ret = LabeledStmt()) || + (ret = ShortVarDecl())) + { + return ret; + } +*/ + default: + break; + } + GoASTExpr *expr = Expression(); + if (expr == nullptr) + return r.error(); + if (/*(ret = SendStmt(expr)) ||*/ + (ret = IncDecStmt(expr)) || (ret = Assignment(expr)) || (ret = ExpressionStmt(expr))) + { + return ret; + } + delete expr; + return r.error(); +} + +GoASTStmt * +GoParser::ExpressionStmt(GoASTExpr *e) +{ + if (Semicolon()) + return new GoASTExprStmt(e); + return nullptr; +} + +GoASTStmt * +GoParser::IncDecStmt(GoASTExpr *e) +{ + Rule r("IncDecStmt", this); + if (match(GoLexer::OP_PLUS_PLUS)) + return Semicolon() ? new GoASTIncDecStmt(e, GoLexer::OP_PLUS_PLUS) : r.error(); + if (match(GoLexer::OP_MINUS_MINUS)) + return Semicolon() ? new GoASTIncDecStmt(e, GoLexer::OP_MINUS_MINUS) : r.error(); + return nullptr; +} + +GoASTStmt * +GoParser::Assignment(lldb_private::GoASTExpr *e) +{ + Rule r("Assignment", this); + std::vector> lhs; + for (GoASTExpr *l = MoreExpressionList(); l; l = MoreExpressionList()) + lhs.push_back(std::unique_ptr(l)); + switch (peek()) + { + case GoLexer::OP_EQ: + case GoLexer::OP_PLUS_EQ: + case GoLexer::OP_MINUS_EQ: + case GoLexer::OP_PIPE_EQ: + case GoLexer::OP_CARET_EQ: + case GoLexer::OP_STAR_EQ: + case GoLexer::OP_SLASH_EQ: + case GoLexer::OP_PERCENT_EQ: + case GoLexer::OP_LSHIFT_EQ: + case GoLexer::OP_RSHIFT_EQ: + case GoLexer::OP_AMP_EQ: + case GoLexer::OP_AMP_CARET_EQ: + break; + default: + return r.error(); + } + // We don't want to own e until we know this is an assignment. + std::unique_ptr stmt(new GoASTAssignStmt(false)); + stmt->AddLhs(e); + for (auto &l : lhs) + stmt->AddLhs(l.release()); + for (GoASTExpr *r = Expression(); r; r = MoreExpressionList()) + stmt->AddRhs(r); + if (!Semicolon() || stmt->NumRhs() == 0) + return new GoASTBadStmt; + return stmt.release(); +} + +GoASTStmt * +GoParser::EmptyStmt() +{ + if (match(GoLexer::TOK_EOF)) + return nullptr; + if (Semicolon()) + return new GoASTEmptyStmt; + return nullptr; +} + +GoASTStmt * +GoParser::GoStmt() +{ + if (match(GoLexer::KEYWORD_GO)) + { + if (GoASTCallExpr *e = llvm::dyn_cast_or_null(Expression())) + { + return FinishStmt(new GoASTGoStmt(e)); + } + m_last = "call expression"; + m_failed = true; + return new GoASTBadStmt(); + } + return nullptr; +} + +GoASTStmt * +GoParser::ReturnStmt() +{ + if (match(GoLexer::KEYWORD_RETURN)) + { + std::unique_ptr r(new GoASTReturnStmt()); + for (GoASTExpr *e = Expression(); e; e = MoreExpressionList()) + r->AddResults(e); + return FinishStmt(r.release()); + } + return nullptr; +} + +GoASTStmt * +GoParser::BranchStmt() +{ + GoLexer::Token *tok; + if ((tok = match(GoLexer::KEYWORD_BREAK)) || (tok = match(GoLexer::KEYWORD_CONTINUE)) || + (tok = match(GoLexer::KEYWORD_GOTO))) + { + auto *e = Identifier(); + if (tok->m_type == GoLexer::KEYWORD_GOTO && !e) + return syntaxerror(); + return FinishStmt(new GoASTBranchStmt(e, tok->m_type)); + } + if ((tok = match(GoLexer::KEYWORD_FALLTHROUGH))) + return FinishStmt(new GoASTBranchStmt(nullptr, tok->m_type)); + + return nullptr; +} + +GoASTIdent * +GoParser::Identifier() +{ + if (auto *tok = match(GoLexer::TOK_IDENTIFIER)) + return new GoASTIdent(*tok); + return nullptr; +} + +GoASTExpr * +GoParser::MoreExpressionList() +{ + if (match(GoLexer::OP_COMMA)) + { + auto *e = Expression(); + if (!e) + return syntaxerror(); + return e; + } + return nullptr; +} + +GoASTIdent * +GoParser::MoreIdentifierList() +{ + if (match(GoLexer::OP_COMMA)) + { + auto *i = Identifier(); + if (!i) + return syntaxerror(); + return i; + } + return nullptr; +} + +GoASTExpr * +GoParser::Expression() +{ + Rule r("Expression", this); + if (GoASTExpr *ret = OrExpr()) + return ret; + return r.error(); +} + +GoASTExpr * +GoParser::UnaryExpr() +{ + switch (peek()) + { + case GoLexer::OP_PLUS: + case GoLexer::OP_MINUS: + case GoLexer::OP_BANG: + case GoLexer::OP_CARET: + case GoLexer::OP_STAR: + case GoLexer::OP_AMP: + case GoLexer::OP_LT_MINUS: + { + const GoLexer::Token t = next(); + if (GoASTExpr *e = UnaryExpr()) + { + if (t.m_type == GoLexer::OP_STAR) + return new GoASTStarExpr(e); + else + return new GoASTUnaryExpr(t.m_type, e); + } + return syntaxerror(); + } + default: + return PrimaryExpr(); + } +} + +GoASTExpr * +GoParser::OrExpr() +{ + std::unique_ptr l(AndExpr()); + if (l) + { + while (match(GoLexer::OP_PIPE_PIPE)) + { + GoASTExpr *r = AndExpr(); + if (r) + l.reset(new GoASTBinaryExpr(l.release(), r, GoLexer::OP_PIPE_PIPE)); + else + return syntaxerror(); + } + return l.release(); + } + return nullptr; +} + +GoASTExpr * +GoParser::AndExpr() +{ + std::unique_ptr l(RelExpr()); + if (l) + { + while (match(GoLexer::OP_AMP_AMP)) + { + GoASTExpr *r = RelExpr(); + if (r) + l.reset(new GoASTBinaryExpr(l.release(), r, GoLexer::OP_AMP_AMP)); + else + return syntaxerror(); + } + return l.release(); + } + return nullptr; +} + +GoASTExpr * +GoParser::RelExpr() +{ + std::unique_ptr l(AddExpr()); + if (l) + { + for (GoLexer::Token *t; (t = match(GoLexer::OP_EQ_EQ)) || (t = match(GoLexer::OP_BANG_EQ)) || + (t = match(GoLexer::OP_LT)) || (t = match(GoLexer::OP_LT_EQ)) || + (t = match(GoLexer::OP_GT)) || (t = match(GoLexer::OP_GT_EQ));) + { + GoLexer::TokenType op = t->m_type; + GoASTExpr *r = AddExpr(); + if (r) + l.reset(new GoASTBinaryExpr(l.release(), r, op)); + else + return syntaxerror(); + } + return l.release(); + } + return nullptr; +} + +GoASTExpr * +GoParser::AddExpr() +{ + std::unique_ptr l(MulExpr()); + if (l) + { + for (GoLexer::Token *t; (t = match(GoLexer::OP_PLUS)) || (t = match(GoLexer::OP_MINUS)) || + (t = match(GoLexer::OP_PIPE)) || (t = match(GoLexer::OP_CARET));) + { + GoLexer::TokenType op = t->m_type; + GoASTExpr *r = MulExpr(); + if (r) + l.reset(new GoASTBinaryExpr(l.release(), r, op)); + else + return syntaxerror(); + } + return l.release(); + } + return nullptr; +} + +GoASTExpr * +GoParser::MulExpr() +{ + std::unique_ptr l(UnaryExpr()); + if (l) + { + for (GoLexer::Token *t; (t = match(GoLexer::OP_STAR)) || (t = match(GoLexer::OP_SLASH)) || + (t = match(GoLexer::OP_PERCENT)) || (t = match(GoLexer::OP_LSHIFT)) || + (t = match(GoLexer::OP_RSHIFT)) || (t = match(GoLexer::OP_AMP)) || + (t = match(GoLexer::OP_AMP_CARET));) + { + GoLexer::TokenType op = t->m_type; + GoASTExpr *r = UnaryExpr(); + if (r) + l.reset(new GoASTBinaryExpr(l.release(), r, op)); + else + return syntaxerror(); + } + return l.release(); + } + return nullptr; +} + +GoASTExpr * +GoParser::PrimaryExpr() +{ + GoASTExpr *l; + GoASTExpr *r; + (l = Conversion()) || (l = Operand()); + if (!l) + return nullptr; + while ((r = Selector(l)) || (r = IndexOrSlice(l)) || (r = TypeAssertion(l)) || (r = Arguments(l))) + { + l = r; + } + return l; +} + +GoASTExpr * +GoParser::Operand() +{ + GoLexer::Token *lit; + if ((lit = match(GoLexer::LIT_INTEGER)) || (lit = match(GoLexer::LIT_FLOAT)) || + (lit = match(GoLexer::LIT_IMAGINARY)) || (lit = match(GoLexer::LIT_RUNE)) || (lit = match(GoLexer::LIT_STRING))) + return new GoASTBasicLit(*lit); + if (match(GoLexer::OP_LPAREN)) + { + GoASTExpr *e; + if (!((e = Expression()) && match(GoLexer::OP_RPAREN))) + return syntaxerror(); + return e; + } + // MethodExpr should be handled by Selector + if (GoASTExpr *e = CompositeLit()) + return e; + if (GoASTExpr *n = Name()) + return n; + return FunctionLit(); +} + +GoASTExpr * +GoParser::FunctionLit() +{ + if (!match(GoLexer::KEYWORD_FUNC)) + return nullptr; + auto *sig = Signature(); + if (!sig) + return syntaxerror(); + auto *body = Block(); + if (!body) + { + delete sig; + return syntaxerror(); + } + return new GoASTFuncLit(sig, body); +} + +GoASTBlockStmt * +GoParser::Block() +{ + if (!match(GoLexer::OP_LBRACE)) + return nullptr; + std::unique_ptr block(new GoASTBlockStmt); + for (auto *s = Statement(); s; s = Statement()) + block->AddList(s); + if (!match(GoLexer::OP_RBRACE)) + return syntaxerror(); + return block.release(); +} + +GoASTExpr * +GoParser::CompositeLit() +{ + Rule r("CompositeLit", this); + GoASTExpr *type; + (type = StructType()) || (type = ArrayOrSliceType(true)) || (type = MapType()) || (type = Name()); + if (!type) + return r.error(); + GoASTCompositeLit *lit = LiteralValue(); + if (!lit) + return r.error(); + lit->SetType(type); + return lit; +} + +GoASTCompositeLit * +GoParser::LiteralValue() +{ + if (!match(GoLexer::OP_LBRACE)) + return nullptr; + std::unique_ptr lit(new GoASTCompositeLit); + for (GoASTExpr *e = Element(); e; e = Element()) + { + lit->AddElts(e); + if (!match(GoLexer::OP_COMMA)) + break; + } + if (!mustMatch(GoLexer::OP_RBRACE)) + return nullptr; + return lit.release(); +} + +GoASTExpr * +GoParser::Element() +{ + GoASTExpr *key; + if (!((key = Expression()) || (key = LiteralValue()))) + return nullptr; + if (!match(GoLexer::OP_COLON)) + return key; + GoASTExpr *value; + if ((value = Expression()) || (value = LiteralValue())) + return new GoASTKeyValueExpr(key, value); + delete key; + return syntaxerror(); +} + +GoASTExpr * +GoParser::Selector(GoASTExpr *e) +{ + Rule r("Selector", this); + if (match(GoLexer::OP_DOT)) + { + if (auto *name = Identifier()) + return new GoASTSelectorExpr(e, name); + } + return r.error(); +} + +GoASTExpr * +GoParser::IndexOrSlice(GoASTExpr *e) +{ + Rule r("IndexOrSlice", this); + if (match(GoLexer::OP_LBRACK)) + { + std::unique_ptr i1(Expression()), i2, i3; + bool slice = false; + if (match(GoLexer::OP_COLON)) + { + slice = true; + i2.reset(Expression()); + if (i2 && match(GoLexer::OP_COLON)) + { + i3.reset(Expression()); + if (!i3) + return syntaxerror(); + } + } + if (!(slice || i1)) + return syntaxerror(); + if (!mustMatch(GoLexer::OP_RBRACK)) + return nullptr; + if (slice) + { + bool slice3 = i3.get(); + return new GoASTSliceExpr(e, i1.release(), i2.release(), i3.release(), slice3); + } + return new GoASTIndexExpr(e, i1.release()); + } + return r.error(); +} + +GoASTExpr * +GoParser::TypeAssertion(GoASTExpr *e) +{ + Rule r("TypeAssertion", this); + if (match(GoLexer::OP_DOT) && match(GoLexer::OP_LPAREN)) + { + if (auto *t = Type()) + { + if (!mustMatch(GoLexer::OP_RPAREN)) + return nullptr; + return new GoASTTypeAssertExpr(e, t); + } + return syntaxerror(); + } + return r.error(); +} + +GoASTExpr * +GoParser::Arguments(GoASTExpr *e) +{ + if (match(GoLexer::OP_LPAREN)) + { + std::unique_ptr call(new GoASTCallExpr(false)); + GoASTExpr *arg; + // ( ExpressionList | Type [ "," ExpressionList ] ) + for ((arg = Expression()) || (arg = Type()); arg; arg = MoreExpressionList()) + { + call->AddArgs(arg); + } + if (match(GoLexer::OP_DOTS)) + call->SetEllipsis(true); + + // Eat trailing comma + match(GoLexer::OP_COMMA); + + if (!mustMatch(GoLexer::OP_RPAREN)) + return nullptr; + call->SetFun(e); + return call.release(); + } + return nullptr; +} + +GoASTExpr * +GoParser::Conversion() +{ + Rule r("Conversion", this); + if (GoASTExpr *t = Type2()) + { + if (match(GoLexer::OP_LPAREN)) + { + GoASTExpr *v = Expression(); + if (!v) + return syntaxerror(); + match(GoLexer::OP_COMMA); + if (!mustMatch(GoLexer::OP_RPAREN)) + return r.error(); + GoASTCallExpr *call = new GoASTCallExpr(false); + call->SetFun(t); + call->AddArgs(v); + return call; + } + } + return r.error(); +} + +GoASTExpr * +GoParser::Type2() +{ + switch (peek()) + { + case GoLexer::OP_LBRACK: + return ArrayOrSliceType(false); + case GoLexer::KEYWORD_STRUCT: + return StructType(); + case GoLexer::KEYWORD_FUNC: + return FunctionType(); + case GoLexer::KEYWORD_INTERFACE: + return InterfaceType(); + case GoLexer::KEYWORD_MAP: + return MapType(); + case GoLexer::KEYWORD_CHAN: + return ChanType2(); + default: + return nullptr; + } +} + +GoASTExpr * +GoParser::ArrayOrSliceType(bool allowEllipsis) +{ + Rule r("ArrayType", this); + if (match(GoLexer::OP_LBRACK)) + { + std::unique_ptr len; + if (allowEllipsis && match(GoLexer::OP_DOTS)) + { + len.reset(new GoASTEllipsis(nullptr)); + } + else + { + len.reset(Expression()); + } + + if (!match(GoLexer::OP_RBRACK)) + return r.error(); + GoASTExpr *elem = Type(); + if (!elem) + return syntaxerror(); + return new GoASTArrayType(len.release(), elem); + } + return r.error(); +} + +GoASTExpr * +GoParser::StructType() +{ + if (!(match(GoLexer::KEYWORD_STRUCT) && mustMatch(GoLexer::OP_LBRACE))) + return nullptr; + std::unique_ptr fields(new GoASTFieldList); + while (auto *field = FieldDecl()) + fields->AddList(field); + if (!mustMatch(GoLexer::OP_RBRACE)) + return nullptr; + return new GoASTStructType(fields.release()); +} + +GoASTField * +GoParser::FieldDecl() +{ + std::unique_ptr f(new GoASTField); + GoASTExpr *t = FieldNamesAndType(f.get()); + if (!t) + t = AnonymousFieldType(); + if (!t) + return nullptr; + + if (auto *tok = match(GoLexer::LIT_STRING)) + f->SetTag(new GoASTBasicLit(*tok)); + if (!Semicolon()) + return syntaxerror(); + return f.release(); +} + +GoASTExpr * +GoParser::FieldNamesAndType(GoASTField *field) +{ + Rule r("FieldNames", this); + for (auto *id = Identifier(); id; id = MoreIdentifierList()) + field->AddNames(id); + if (m_failed) + return nullptr; + GoASTExpr *t = Type(); + if (t) + return t; + return r.error(); +} + +GoASTExpr * +GoParser::AnonymousFieldType() +{ + bool pointer = match(GoLexer::OP_STAR); + GoASTExpr *t = Type(); + if (!t) + return nullptr; + if (pointer) + return new GoASTStarExpr(t); + return t; +} + +GoASTExpr * +GoParser::FunctionType() +{ + if (!match(GoLexer::KEYWORD_FUNC)) + return nullptr; + return Signature(); +} + +GoASTFuncType * +GoParser::Signature() +{ + auto *params = Params(); + if (!params) + return syntaxerror(); + auto *result = Params(); + if (!result) + { + if (auto *t = Type()) + { + result = new GoASTFieldList; + auto *f = new GoASTField; + f->SetType(t); + result->AddList(f); + } + } + return new GoASTFuncType(params, result); +} + +GoASTFieldList * +GoParser::Params() +{ + if (!match(GoLexer::OP_LPAREN)) + return nullptr; + std::unique_ptr l(new GoASTFieldList); + while (GoASTField *p = ParamDecl()) + { + l->AddList(p); + if (!match(GoLexer::OP_COMMA)) + break; + } + if (!mustMatch(GoLexer::OP_RPAREN)) + return nullptr; + return l.release(); +} + +GoASTField * +GoParser::ParamDecl() +{ + std::unique_ptr field(new GoASTField); + GoASTIdent *id = Identifier(); + if (id) + { + // Try `IdentifierList [ "..." ] Type`. + // If that fails, backtrack and try `[ "..." ] Type`. + Rule r("NamedParam", this); + for (; id; id = MoreIdentifierList()) + field->AddNames(id); + GoASTExpr *t = ParamType(); + if (t) + { + field->SetType(t); + return field.release(); + } + field.reset(new GoASTField); + r.error(); + } + GoASTExpr *t = ParamType(); + if (t) + { + field->SetType(t); + return field.release(); + } + return nullptr; +} + +GoASTExpr * +GoParser::ParamType() +{ + bool dots = match(GoLexer::OP_DOTS); + GoASTExpr *t = Type(); + if (!dots) + return t; + if (!t) + return syntaxerror(); + return new GoASTEllipsis(t); +} + +GoASTExpr * +GoParser::InterfaceType() +{ + if (!match(GoLexer::KEYWORD_INTERFACE) || !mustMatch(GoLexer::OP_LBRACE)) + return nullptr; + std::unique_ptr methods(new GoASTFieldList); + while (true) + { + Rule r("MethodSpec", this); + // ( identifier Signature | TypeName ) ; + std::unique_ptr id(Identifier()); + if (!id) + break; + GoASTExpr *type = Signature(); + if (!type) + { + r.error(); + id.reset(); + type = Name(); + } + if (!Semicolon()) + return syntaxerror(); + auto *f = new GoASTField; + if (id) + f->AddNames(id.release()); + f->SetType(type); + methods->AddList(f); + } + if (!mustMatch(GoLexer::OP_RBRACE)) + return nullptr; + return new GoASTInterfaceType(methods.release()); +} + +GoASTExpr * +GoParser::MapType() +{ + if (!(match(GoLexer::KEYWORD_MAP) && mustMatch(GoLexer::OP_LBRACK))) + return nullptr; + std::unique_ptr key(Type()); + if (!key) + return syntaxerror(); + if (!mustMatch(GoLexer::OP_RBRACK)) + return nullptr; + auto *elem = Type(); + if (!elem) + return syntaxerror(); + return new GoASTMapType(key.release(), elem); +} + +GoASTExpr * +GoParser::ChanType() +{ + Rule r("chan", this); + if (match(GoLexer::OP_LT_MINUS)) + { + if (match(GoLexer::KEYWORD_CHAN)) + { + auto *elem = Type(); + if (!elem) + return syntaxerror(); + return new GoASTChanType(GoASTNode::eChanRecv, elem); + } + return r.error(); + } + return ChanType2(); +} + +GoASTExpr * +GoParser::ChanType2() +{ + if (!match(GoLexer::KEYWORD_CHAN)) + return nullptr; + auto dir = GoASTNode::eChanBidir; + if (match(GoLexer::OP_LT_MINUS)) + dir = GoASTNode::eChanSend; + auto *elem = Type(); + if (!elem) + return syntaxerror(); + return new GoASTChanType(dir, elem); +} + +GoASTExpr * +GoParser::Type() +{ + if (GoASTExpr *t = Type2()) + return t; + if (GoASTExpr *t = Name()) + return t; + if (GoASTExpr *t = ChanType()) + return t; + if (match(GoLexer::OP_STAR)) + { + GoASTExpr *t = Type(); + if (!t) + return syntaxerror(); + return new GoASTStarExpr(t); + } + if (match(GoLexer::OP_LPAREN)) + { + std::unique_ptr t(Type()); + if (!t || !match(GoLexer::OP_RPAREN)) + return syntaxerror(); + return t.release(); + } + return nullptr; +} + +bool +GoParser::Semicolon() +{ + if (match(GoLexer::OP_SEMICOLON)) + return true; + switch (peek()) + { + case GoLexer::OP_RPAREN: + case GoLexer::OP_RBRACE: + case GoLexer::TOK_EOF: + return true; + default: + return false; + } +} + +GoASTExpr * +GoParser::Name() +{ + if (auto *id = Identifier()) + { + if (GoASTExpr *qual = QualifiedIdent(id)) + return qual; + return id; + } + return nullptr; +} + +GoASTExpr * +GoParser::QualifiedIdent(lldb_private::GoASTIdent *p) +{ + Rule r("QualifiedIdent", this); + llvm::SmallString<32> path(p->GetName().m_value); + GoLexer::Token *next; + bool have_slashes = false; + // LLDB extension: support full/package/path.name + while (match(GoLexer::OP_SLASH) && (next = match(GoLexer::TOK_IDENTIFIER))) + { + have_slashes = true; + path.append("/"); + path.append(next->m_value); + } + if (match(GoLexer::OP_DOT)) + { + auto *name = Identifier(); + if (name) + { + if (have_slashes) + { + p->SetName(GoLexer::Token(GoLexer::TOK_IDENTIFIER, CopyString(path))); + } + return new GoASTSelectorExpr(p, name); + } + } + return r.error(); +} + +llvm::StringRef +GoParser::CopyString(llvm::StringRef s) +{ + return m_strings.insert(std::make_pair(s, 'x')).first->getKey(); +} + +void +GoParser::GetError(Error &error) +{ + llvm::StringRef want; + if (m_failed) + want = m_last_tok == GoLexer::TOK_INVALID ? DescribeToken(m_last_tok) : m_last; + else + want = m_error; + size_t len = m_lexer.BytesRemaining(); + if (len > 10) + len = 10; + llvm::StringRef got; + if (len == 0) + got = ""; + else + got = m_lexer.GetString(len); + error.SetErrorStringWithFormat("Syntax error: expected %s before '%s'.", want.str().c_str(), got.str().c_str()); +} diff --git a/source/Plugins/ExpressionParser/Go/GoParser.h b/source/Plugins/ExpressionParser/Go/GoParser.h new file mode 100644 index 0000000000000..9ceb670ccd117 --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoParser.h @@ -0,0 +1,165 @@ +//===-- GoParser.h -----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_GoParser_h +#define liblldb_GoParser_h + +#include "lldb/lldb-private.h" +#include "Plugins/ExpressionParser/Go/GoAST.h" +#include "Plugins/ExpressionParser/Go/GoLexer.h" + +namespace lldb_private +{ +class GoParser +{ + public: + explicit GoParser(const char *src); + + GoASTStmt *Statement(); + + GoASTStmt *GoStmt(); + GoASTStmt *ReturnStmt(); + GoASTStmt *BranchStmt(); + GoASTStmt *EmptyStmt(); + GoASTStmt *ExpressionStmt(GoASTExpr *e); + GoASTStmt *IncDecStmt(GoASTExpr *e); + GoASTStmt *Assignment(GoASTExpr *e); + GoASTBlockStmt *Block(); + + GoASTExpr *MoreExpressionList(); // ["," Expression] + GoASTIdent *MoreIdentifierList(); // ["," Identifier] + + GoASTExpr *Expression(); + GoASTExpr *UnaryExpr(); + GoASTExpr *OrExpr(); + GoASTExpr *AndExpr(); + GoASTExpr *RelExpr(); + GoASTExpr *AddExpr(); + GoASTExpr *MulExpr(); + GoASTExpr *PrimaryExpr(); + GoASTExpr *Operand(); + GoASTExpr *Conversion(); + + GoASTExpr *Selector(GoASTExpr *e); + GoASTExpr *IndexOrSlice(GoASTExpr *e); + GoASTExpr *TypeAssertion(GoASTExpr *e); + GoASTExpr *Arguments(GoASTExpr *e); + + GoASTExpr *Type(); + GoASTExpr *Type2(); + GoASTExpr *ArrayOrSliceType(bool allowEllipsis); + GoASTExpr *StructType(); + GoASTExpr *FunctionType(); + GoASTExpr *InterfaceType(); + GoASTExpr *MapType(); + GoASTExpr *ChanType(); + GoASTExpr *ChanType2(); + + GoASTExpr *Name(); + GoASTExpr *QualifiedIdent(GoASTIdent *p); + GoASTIdent *Identifier(); + + GoASTField *FieldDecl(); + GoASTExpr *AnonymousFieldType(); + GoASTExpr *FieldNamesAndType(GoASTField *f); + + GoASTFieldList *Params(); + GoASTField *ParamDecl(); + GoASTExpr *ParamType(); + GoASTFuncType *Signature(); + GoASTExpr *CompositeLit(); + GoASTExpr *FunctionLit(); + GoASTExpr *Element(); + GoASTCompositeLit *LiteralValue(); + + bool + Failed() const + { + return m_failed; + } + bool + AtEOF() const + { + return m_lexer.BytesRemaining() == 0 && m_pos == m_tokens.size(); + } + + void GetError(Error &error); + + private: + class Rule; + friend class Rule; + + std::nullptr_t + syntaxerror() + { + m_failed = true; + return nullptr; + } + GoLexer::Token & + next() + { + if (m_pos >= m_tokens.size()) + { + if (m_pos != 0 && + (m_tokens.back().m_type == GoLexer::TOK_EOF || m_tokens.back().m_type == GoLexer::TOK_INVALID)) + return m_tokens.back(); + m_pos = m_tokens.size(); + m_tokens.push_back(m_lexer.Lex()); + } + return m_tokens[m_pos++]; + } + GoLexer::TokenType + peek() + { + GoLexer::Token &tok = next(); + --m_pos; + return tok.m_type; + } + GoLexer::Token * + match(GoLexer::TokenType t) + { + GoLexer::Token &tok = next(); + if (tok.m_type == t) + return &tok; + --m_pos; + m_last_tok = t; + return nullptr; + } + GoLexer::Token * + mustMatch(GoLexer::TokenType t) + { + GoLexer::Token *tok = match(t); + if (tok) + return tok; + return syntaxerror(); + } + bool Semicolon(); + + GoASTStmt * + FinishStmt(GoASTStmt *s) + { + if (!Semicolon()) + m_failed = true; + return s; + } + + llvm::StringRef CopyString(llvm::StringRef s); + + GoLexer m_lexer; + std::vector m_tokens; + size_t m_pos; + llvm::StringRef m_error; + llvm::StringRef m_last; + GoLexer::TokenType m_last_tok; + llvm::StringMap m_strings; + bool m_failed; +}; +} + +#endif diff --git a/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp b/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp new file mode 100644 index 0000000000000..3f12a2b6255bb --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp @@ -0,0 +1,756 @@ +//===-- GoUserExpression.cpp ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +#include +#if HAVE_SYS_TYPES_H +#include +#endif + +// C++ Includes +#include +#include +#include +#include + +// Other libraries and framework includes +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringMap.h" + +// Project includes +#include "GoUserExpression.h" + +#include "lldb/lldb-private.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataEncoder.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectRegister.h" +#include "lldb/Expression/ExpressionVariable.h" +#include "lldb/Symbol/TypeList.h" +#include "lldb/Symbol/GoASTContext.h" +#include "lldb/Symbol/VariableList.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanCallUserExpression.h" + +#include "Plugins/ExpressionParser/Go/GoAST.h" +#include "Plugins/ExpressionParser/Go/GoParser.h" + +using namespace lldb_private; +using namespace lldb; + +class GoUserExpression::GoInterpreter +{ + public: + GoInterpreter(ExecutionContext &exe_ctx, const char *expr) + : m_exe_ctx(exe_ctx), m_frame(exe_ctx.GetFrameSP()), m_parser(expr) + { + if (m_frame) + { + const SymbolContext &ctx = m_frame->GetSymbolContext(eSymbolContextFunction); + ConstString fname = ctx.GetFunctionName(); + if (fname.GetLength() > 0) + { + size_t dot = fname.GetStringRef().find('.'); + if (dot != llvm::StringRef::npos) + m_package = llvm::StringRef(fname.AsCString(), dot); + } + } + } + + void + set_use_dynamic(DynamicValueType use_dynamic) + { + m_use_dynamic = use_dynamic; + } + + bool Parse(); + lldb::ValueObjectSP Evaluate(ExecutionContext &exe_ctx); + lldb::ValueObjectSP EvaluateStatement(const GoASTStmt *s); + lldb::ValueObjectSP EvaluateExpr(const GoASTExpr *e); + + ValueObjectSP + VisitBadExpr(const GoASTBadExpr *e) + { + m_parser.GetError(m_error); + return nullptr; + } + + ValueObjectSP VisitParenExpr(const GoASTParenExpr *e); + ValueObjectSP VisitIdent(const GoASTIdent *e); + ValueObjectSP VisitStarExpr(const GoASTStarExpr *e); + ValueObjectSP VisitSelectorExpr(const GoASTSelectorExpr *e); + ValueObjectSP VisitBasicLit(const GoASTBasicLit *e); + ValueObjectSP VisitIndexExpr(const GoASTIndexExpr *e); + ValueObjectSP VisitUnaryExpr(const GoASTUnaryExpr *e); + ValueObjectSP VisitCallExpr(const GoASTCallExpr *e); + + ValueObjectSP + VisitTypeAssertExpr(const GoASTTypeAssertExpr *e) + { + return NotImplemented(e); + } + + ValueObjectSP + VisitBinaryExpr(const GoASTBinaryExpr *e) + { + return NotImplemented(e); + } + + ValueObjectSP + VisitArrayType(const GoASTArrayType *e) + { + return NotImplemented(e); + } + + ValueObjectSP + VisitChanType(const GoASTChanType *e) + { + return NotImplemented(e); + } + + ValueObjectSP + VisitCompositeLit(const GoASTCompositeLit *e) + { + return NotImplemented(e); + } + + ValueObjectSP + VisitEllipsis(const GoASTEllipsis *e) + { + return NotImplemented(e); + } + + ValueObjectSP + VisitFuncType(const GoASTFuncType *e) + { + return NotImplemented(e); + } + + ValueObjectSP + VisitFuncLit(const GoASTFuncLit *e) + { + return NotImplemented(e); + } + + ValueObjectSP + VisitInterfaceType(const GoASTInterfaceType *e) + { + return NotImplemented(e); + } + + ValueObjectSP + VisitKeyValueExpr(const GoASTKeyValueExpr *e) + { + return NotImplemented(e); + } + + ValueObjectSP + VisitMapType(const GoASTMapType *e) + { + return NotImplemented(e); + } + + ValueObjectSP + VisitSliceExpr(const GoASTSliceExpr *e) + { + return NotImplemented(e); + } + + ValueObjectSP + VisitStructType(const GoASTStructType *e) + { + return NotImplemented(e); + } + + CompilerType EvaluateType(const GoASTExpr *e); + + Error & + error() + { + return m_error; + } + + private: + std::nullptr_t + NotImplemented(const GoASTExpr *e) + { + m_error.SetErrorStringWithFormat("%s node not implemented", e->GetKindName()); + return nullptr; + } + + ExecutionContext m_exe_ctx; + lldb::StackFrameSP m_frame; + GoParser m_parser; + DynamicValueType m_use_dynamic; + Error m_error; + llvm::StringRef m_package; + std::vector> m_statements; +}; + +VariableSP +FindGlobalVariable(TargetSP target, llvm::Twine name) +{ + ConstString fullname(name.str()); + VariableList variable_list; + const bool append = true; + if (!target) + { + return nullptr; + } + const uint32_t match_count = target->GetImages().FindGlobalVariables(fullname, append, 1, variable_list); + if (match_count == 1) + { + return variable_list.GetVariableAtIndex(0); + } + return nullptr; +} + +CompilerType +LookupType(TargetSP target, ConstString name) +{ + if (!target) + return CompilerType(); + SymbolContext sc; + TypeList type_list; + uint32_t num_matches = target->GetImages().FindTypes(sc, name, false, 2, type_list); + if (num_matches > 0) + { + return type_list.GetTypeAtIndex(0)->GetFullCompilerType(); + } + return CompilerType(); +} + +GoUserExpression::GoUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix, + lldb::LanguageType language, ResultType desired_type, + const EvaluateExpressionOptions &options) + : UserExpression(exe_scope, expr, expr_prefix, language, desired_type, options) +{ +} + +bool +GoUserExpression::Parse(Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, + bool keep_result_in_memory, bool generate_debug_info) +{ + InstallContext(exe_ctx); + m_interpreter.reset(new GoInterpreter(exe_ctx, GetUserText())); + if (m_interpreter->Parse()) + return true; + const char *error_cstr = m_interpreter->error().AsCString(); + if (error_cstr && error_cstr[0]) + error_stream.Printf("error: %s\n", error_cstr); + else + error_stream.Printf("error: expression can't be interpreted or run\n"); + return false; +} + +lldb::ExpressionResults +GoUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, + lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result) +{ + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); + + lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); + lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; + + Process *process = exe_ctx.GetProcessPtr(); + Target *target = exe_ctx.GetTargetPtr(); + + if (target == nullptr || process == nullptr || process->GetState() != lldb::eStateStopped) + { + if (execution_policy == eExecutionPolicyAlways) + { + if (log) + log->Printf("== [GoUserExpression::Evaluate] Expression may not run, but is not constant =="); + + error_stream.Printf("expression needed to run but couldn't"); + + return execution_results; + } + } + + m_interpreter->set_use_dynamic(options.GetUseDynamic()); + ValueObjectSP result_val_sp = m_interpreter->Evaluate(exe_ctx); + Error err = m_interpreter->error(); + m_interpreter.reset(); + + if (!result_val_sp) + { + const char *error_cstr = err.AsCString(); + if (error_cstr && error_cstr[0]) + error_stream.Printf("error: %s\n", error_cstr); + else + error_stream.Printf("error: expression can't be interpreted or run\n"); + return lldb::eExpressionDiscarded; + } + result.reset(new ExpressionVariable(ExpressionVariable::eKindGo)); + result->m_live_sp = result->m_frozen_sp = result_val_sp; + result->m_flags |= ExpressionVariable::EVIsProgramReference; + PersistentExpressionState *pv = target->GetPersistentExpressionStateForLanguage(eLanguageTypeGo); + if (pv != nullptr) + { + result->SetName(pv->GetNextPersistentVariableName()); + pv->AddVariable(result); + } + return lldb::eExpressionCompleted; +} + +bool +GoUserExpression::GoInterpreter::Parse() +{ + for (std::unique_ptr stmt(m_parser.Statement()); stmt; stmt.reset(m_parser.Statement())) + { + if (m_parser.Failed()) + break; + m_statements.emplace_back(std::move(stmt)); + } + if (m_parser.Failed() || !m_parser.AtEOF()) + m_parser.GetError(m_error); + + return m_error.Success(); +} + +ValueObjectSP +GoUserExpression::GoInterpreter::Evaluate(ExecutionContext &exe_ctx) +{ + m_exe_ctx = exe_ctx; + ValueObjectSP result; + for (const std::unique_ptr &stmt : m_statements) + { + result = EvaluateStatement(stmt.get()); + if (m_error.Fail()) + return nullptr; + } + return result; +} + +ValueObjectSP +GoUserExpression::GoInterpreter::EvaluateStatement(const lldb_private::GoASTStmt *stmt) +{ + ValueObjectSP result; + switch (stmt->GetKind()) + { + case GoASTNode::eBlockStmt: + { + const GoASTBlockStmt *block = llvm::cast(stmt); + for (size_t i = 0; i < block->NumList(); ++i) + result = EvaluateStatement(block->GetList(i)); + break; + } + case GoASTNode::eBadStmt: + m_parser.GetError(m_error); + break; + case GoASTNode::eExprStmt: + { + const GoASTExprStmt *expr = llvm::cast(stmt); + return EvaluateExpr(expr->GetX()); + } + default: + m_error.SetErrorStringWithFormat("%s node not supported", stmt->GetKindName()); + } + return result; +} + +ValueObjectSP +GoUserExpression::GoInterpreter::EvaluateExpr(const lldb_private::GoASTExpr *e) +{ + if (e) + return e->Visit(this); + return ValueObjectSP(); +} + +ValueObjectSP +GoUserExpression::GoInterpreter::VisitParenExpr(const lldb_private::GoASTParenExpr *e) +{ + return EvaluateExpr(e->GetX()); +} + +ValueObjectSP +GoUserExpression::GoInterpreter::VisitIdent(const GoASTIdent *e) +{ + ValueObjectSP val; + if (m_frame) + { + VariableSP var_sp; + std::string varname = e->GetName().m_value.str(); + if (varname.size() > 1 && varname[0] == '$') + { + RegisterContextSP reg_ctx_sp = m_frame->GetRegisterContext(); + const RegisterInfo *reg = reg_ctx_sp->GetRegisterInfoByName(varname.c_str() + 1); + if (reg) + { + std::string type; + switch (reg->encoding) + { + case lldb::eEncodingSint: + type.append("int"); + break; + case lldb::eEncodingUint: + type.append("uint"); + break; + case lldb::eEncodingIEEE754: + type.append("float"); + break; + default: + m_error.SetErrorString("Invaild register encoding"); + return nullptr; + } + switch (reg->byte_size) + { + case 8: + type.append("64"); + break; + case 4: + type.append("32"); + break; + case 2: + type.append("16"); + break; + case 1: + type.append("8"); + break; + default: + m_error.SetErrorString("Invaild register size"); + return nullptr; + } + ValueObjectSP regVal = + ValueObjectRegister::Create(m_frame.get(), reg_ctx_sp, reg->kinds[eRegisterKindLLDB]); + CompilerType goType = LookupType(m_frame->CalculateTarget(), ConstString(type)); + if (regVal) + { + regVal = regVal->Cast(goType); + return regVal; + } + } + m_error.SetErrorString("Invaild register name"); + return nullptr; + } + VariableListSP var_list_sp(m_frame->GetInScopeVariableList(false)); + if (var_list_sp) + { + var_sp = var_list_sp->FindVariable(ConstString(varname)); + if (var_sp) + val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic); + else + { + // When a variable is on the heap instead of the stack, go records a variable + // '&x' instead of 'x'. + var_sp = var_list_sp->FindVariable(ConstString("&" + varname)); + if (var_sp) + { + val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic); + if (val) + val = val->Dereference(m_error); + if (m_error.Fail()) + return nullptr; + } + } + } + if (!val) + { + m_error.Clear(); + TargetSP target = m_frame->CalculateTarget(); + if (!target) + { + m_error.SetErrorString("No target"); + return nullptr; + } + var_sp = FindGlobalVariable(target, m_package + "." + e->GetName().m_value); + if (var_sp) + return m_frame->TrackGlobalVariable(var_sp, m_use_dynamic); + } + } + if (!val) + m_error.SetErrorStringWithFormat("Unknown variable %s", e->GetName().m_value.str().c_str()); + return val; +} + +ValueObjectSP +GoUserExpression::GoInterpreter::VisitStarExpr(const GoASTStarExpr *e) +{ + ValueObjectSP target = EvaluateExpr(e->GetX()); + if (!target) + return nullptr; + return target->Dereference(m_error); +} + +ValueObjectSP +GoUserExpression::GoInterpreter::VisitSelectorExpr(const lldb_private::GoASTSelectorExpr *e) +{ + ValueObjectSP target = EvaluateExpr(e->GetX()); + if (target) + { + if (target->GetCompilerType().IsPointerType()) + { + target = target->Dereference(m_error); + if (m_error.Fail()) + return nullptr; + } + ConstString field(e->GetSel()->GetName().m_value); + ValueObjectSP result = target->GetChildMemberWithName(field, true); + if (!result) + m_error.SetErrorStringWithFormat("Unknown child %s", field.AsCString()); + return result; + } + if (const GoASTIdent *package = llvm::dyn_cast(e->GetX())) + { + if (VariableSP global = FindGlobalVariable(m_exe_ctx.GetTargetSP(), + package->GetName().m_value + "." + e->GetSel()->GetName().m_value)) + { + if (m_frame) + { + m_error.Clear(); + return m_frame->GetValueObjectForFrameVariable(global, m_use_dynamic); + } + } + } + if (const GoASTBasicLit *packageLit = llvm::dyn_cast(e->GetX())) + { + if (packageLit->GetValue().m_type == GoLexer::LIT_STRING) + { + std::string value = packageLit->GetValue().m_value.str(); + value = value.substr(1, value.size() - 2); + if (VariableSP global = + FindGlobalVariable(m_exe_ctx.GetTargetSP(), value + "." + e->GetSel()->GetName().m_value)) + { + if (m_frame) + { + m_error.Clear(); + return m_frame->TrackGlobalVariable(global, m_use_dynamic); + } + } + } + } + // EvaluateExpr should have already set m_error. + return target; +} + +ValueObjectSP +GoUserExpression::GoInterpreter::VisitBasicLit(const lldb_private::GoASTBasicLit *e) +{ + std::string value = e->GetValue().m_value.str(); + if (e->GetValue().m_type != GoLexer::LIT_INTEGER) + { + m_error.SetErrorStringWithFormat("Unsupported literal %s", value.c_str()); + return nullptr; + } + errno = 0; + int64_t intvalue = strtol(value.c_str(), nullptr, 0); + if (errno != 0) + { + m_error.SetErrorToErrno(); + return nullptr; + } + DataBufferSP buf(new DataBufferHeap(sizeof(intvalue), 0)); + TargetSP target = m_exe_ctx.GetTargetSP(); + if (!target) + { + m_error.SetErrorString("No target"); + return nullptr; + } + ByteOrder order = target->GetArchitecture().GetByteOrder(); + uint8_t addr_size = target->GetArchitecture().GetAddressByteSize(); + DataEncoder enc(buf, order, addr_size); + enc.PutU64(0, static_cast(intvalue)); + DataExtractor data(buf, order, addr_size); + + CompilerType type = LookupType(target, ConstString("int64")); + return ValueObject::CreateValueObjectFromData(nullptr, data, m_exe_ctx, type); +} + +ValueObjectSP +GoUserExpression::GoInterpreter::VisitIndexExpr(const lldb_private::GoASTIndexExpr *e) +{ + ValueObjectSP target = EvaluateExpr(e->GetX()); + if (!target) + return nullptr; + ValueObjectSP index = EvaluateExpr(e->GetIndex()); + if (!index) + return nullptr; + bool is_signed; + if (!index->GetCompilerType().IsIntegerType(is_signed)) + { + m_error.SetErrorString("Unsupported index"); + return nullptr; + } + size_t idx; + if (is_signed) + idx = index->GetValueAsSigned(0); + else + idx = index->GetValueAsUnsigned(0); + if (GoASTContext::IsGoSlice(target->GetCompilerType())) + { + target = target->GetStaticValue(); + ValueObjectSP cap = target->GetChildMemberWithName(ConstString("cap"), true); + if (cap) + { + uint64_t capval = cap->GetValueAsUnsigned(0); + if (idx >= capval) + { + m_error.SetErrorStringWithFormat("Invalid index %" PRIu64 " , cap = %" PRIu64, uint64_t(idx), capval); + return nullptr; + } + } + target = target->GetChildMemberWithName(ConstString("array"), true); + if (target && m_use_dynamic != eNoDynamicValues) + { + ValueObjectSP dynamic = target->GetDynamicValue(m_use_dynamic); + if (dynamic) + target = dynamic; + } + if (!target) + return nullptr; + return target->GetSyntheticArrayMember(idx, true); + } + return target->GetChildAtIndex(idx, true); +} + +ValueObjectSP +GoUserExpression::GoInterpreter::VisitUnaryExpr(const GoASTUnaryExpr *e) +{ + ValueObjectSP x = EvaluateExpr(e->GetX()); + if (!x) + return nullptr; + switch (e->GetOp()) + { + case GoLexer::OP_AMP: + { + CompilerType type = x->GetCompilerType().GetPointerType(); + uint64_t address = x->GetAddressOf(); + return ValueObject::CreateValueObjectFromAddress(nullptr, address, m_exe_ctx, type); + } + case GoLexer::OP_PLUS: + return x; + default: + m_error.SetErrorStringWithFormat("Operator %s not supported", + GoLexer::LookupToken(e->GetOp()).str().c_str()); + return nullptr; + } +} + +CompilerType +GoUserExpression::GoInterpreter::EvaluateType(const GoASTExpr *e) +{ + TargetSP target = m_exe_ctx.GetTargetSP(); + if (auto *id = llvm::dyn_cast(e)) + { + CompilerType result = LookupType(target, ConstString(id->GetName().m_value)); + if (result.IsValid()) + return result; + std::string fullname = (m_package + "." + id->GetName().m_value).str(); + result = LookupType(target, ConstString(fullname)); + if (!result) + m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str()); + return result; + } + if (auto *sel = llvm::dyn_cast(e)) + { + std::string package; + if (auto *pkg_node = llvm::dyn_cast(sel->GetX())) + { + package = pkg_node->GetName().m_value.str(); + } + else if (auto *str_node = llvm::dyn_cast(sel->GetX())) + { + if (str_node->GetValue().m_type == GoLexer::LIT_STRING) + { + package = str_node->GetValue().m_value.substr(1).str(); + package.resize(package.length() - 1); + } + } + if (package.empty()) + { + m_error.SetErrorStringWithFormat("Invalid %s in type expression", sel->GetX()->GetKindName()); + return CompilerType(); + } + std::string fullname = (package + "." + sel->GetSel()->GetName().m_value).str(); + CompilerType result = LookupType(target, ConstString(fullname)); + if (!result) + m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str()); + return result; + } + if (auto *star = llvm::dyn_cast(e)) + { + CompilerType elem = EvaluateType(star->GetX()); + return elem.GetPointerType(); + } + if (auto *paren = llvm::dyn_cast(e)) + return EvaluateType(paren->GetX()); + if (auto *array = llvm::dyn_cast(e)) + { + CompilerType elem = EvaluateType(array->GetElt()); + } + + m_error.SetErrorStringWithFormat("Invalid %s in type expression", e->GetKindName()); + return CompilerType(); +} + +ValueObjectSP +GoUserExpression::GoInterpreter::VisitCallExpr(const lldb_private::GoASTCallExpr *e) +{ + ValueObjectSP x = EvaluateExpr(e->GetFun()); + if (x || e->NumArgs() != 1) + { + m_error.SetErrorStringWithFormat("Code execution not supported"); + return nullptr; + } + m_error.Clear(); + CompilerType type = EvaluateType(e->GetFun()); + if (!type) + { + return nullptr; + } + ValueObjectSP value = EvaluateExpr(e->GetArgs(0)); + if (!value) + return nullptr; + // TODO: Handle special conversions + return value->Cast(type); +} + +GoPersistentExpressionState::GoPersistentExpressionState() : PersistentExpressionState(eKindGo) +{ +} + +ConstString +GoPersistentExpressionState::GetNextPersistentVariableName() +{ + char name_cstr[256]; + // We can't use the same variable format as clang. + ::snprintf(name_cstr, sizeof(name_cstr), "$go%u", m_next_persistent_variable_id++); + ConstString name(name_cstr); + return name; +} + +void +GoPersistentExpressionState::RemovePersistentVariable(lldb::ExpressionVariableSP variable) +{ + RemoveVariable(variable); + + const char *name = variable->GetName().AsCString(); + + if (*(name++) != '$') + return; + if (*(name++) != 'g') + return; + if (*(name++) != 'o') + return; + + if (strtoul(name, nullptr, 0) == m_next_persistent_variable_id - 1) + m_next_persistent_variable_id--; +} diff --git a/source/Plugins/ExpressionParser/Go/GoUserExpression.h b/source/Plugins/ExpressionParser/Go/GoUserExpression.h new file mode 100644 index 0000000000000..b429c68f023d5 --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/GoUserExpression.h @@ -0,0 +1,98 @@ +//===-- GoUserExpression.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_GoUserExpression_h_ +#define liblldb_GoUserExpression_h_ + +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "lldb/Expression/UserExpression.h" +#include "lldb/Expression/ExpressionVariable.h" +#include "lldb/Target/ExecutionContext.h" + +namespace lldb_private +{ +class GoParser; + +class GoPersistentExpressionState : public PersistentExpressionState +{ + public: + GoPersistentExpressionState(); + + ConstString GetNextPersistentVariableName() override; + + void RemovePersistentVariable(lldb::ExpressionVariableSP variable) override; + + lldb::addr_t + LookupSymbol(const ConstString &name) override + { + return LLDB_INVALID_ADDRESS; + } + + static bool + classof(const PersistentExpressionState *pv) + { + return pv->getKind() == PersistentExpressionState::eKindGo; + } + + private: + uint32_t m_next_persistent_variable_id; ///< The counter used by GetNextResultName(). +}; + +//---------------------------------------------------------------------- +/// @class GoUserExpression GoUserExpression.h "lldb/Expression/GoUserExpression.h" +/// @brief Encapsulates a single expression for use with Go +/// +/// LLDB uses expressions for various purposes, notably to call functions +/// and as a backend for the expr command. GoUserExpression encapsulates +/// the objects needed to parse and interpret an expression. +//---------------------------------------------------------------------- +class GoUserExpression : public UserExpression +{ + public: + GoUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix, + lldb::LanguageType language, ResultType desired_type, const EvaluateExpressionOptions &options); + + bool + Parse(Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, + bool keep_result_in_memory, bool generate_debug_info) override; + + lldb::ExpressionResults + Execute(Stream &error_stream, ExecutionContext &exe_ctx, + const EvaluateExpressionOptions &options, + lldb::UserExpressionSP &shared_ptr_to_me, + lldb::ExpressionVariableSP &result) override; + + bool + CanInterpret() override + { + return true; + } + bool + FinalizeJITExecution(Stream &error_stream, ExecutionContext &exe_ctx, lldb::ExpressionVariableSP &result, + lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS, + lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS) override + { + return true; + } + + private: + class GoInterpreter; + std::unique_ptr m_interpreter; +}; + +} // namespace lldb_private + +#endif // liblldb_GoUserExpression_h_ diff --git a/source/Plugins/ExpressionParser/Go/gen_go_ast.py b/source/Plugins/ExpressionParser/Go/gen_go_ast.py new file mode 100644 index 0000000000000..05b589a9976cb --- /dev/null +++ b/source/Plugins/ExpressionParser/Go/gen_go_ast.py @@ -0,0 +1,356 @@ +import StringIO + +def addNodes(): + addNode("ArrayType", "Expr", "len", "Expr", "elt", "Expr") + addNode("AssignStmt", "Stmt", "lhs", "[]Expr", "rhs", "[]Expr", "define", "bool") + addNode("BadDecl", "Decl") + addNode("BadExpr", "Expr") + addNode("BadStmt", "Stmt") + addNode("BasicLit", "Expr", "value", "Token") + addNode("BinaryExpr", "Expr", "x", "Expr", "y", "Expr", "op", "TokenType") + addNode("BlockStmt", "Stmt", "list", "[]Stmt") + addNode("Ident", "Expr", "name", "Token") + addNode("BranchStmt", "Stmt", "label", "Ident", "tok", "TokenType") + addNode("CallExpr", "Expr", "fun", "Expr", "args", "[]Expr", "ellipsis", "bool") + addNode("CaseClause", "Stmt", "list", "[]Expr", "body", "[]Stmt") + addNode("ChanType", "Expr", "dir", "ChanDir", "value", "Expr") + addNode("CommClause", "Stmt", "comm", "Stmt", "body", "[]Stmt") + addNode("CompositeLit", "Expr", "type", "Expr", "elts", "[]Expr") + addNode("DeclStmt", "Stmt", "decl", "Decl") + addNode("DeferStmt", "Stmt", "call", "CallExpr") + addNode("Ellipsis", "Expr", "elt", "Expr") + addNode("EmptyStmt", "Stmt") + addNode("ExprStmt", "Stmt", "x", "Expr") + addNode("Field", "Node", "names", "[]Ident", "type", "Expr", "tag", "BasicLit") + addNode("FieldList", "Node", "list", "[]Field") + addNode("ForStmt", "Stmt", "init", "Stmt", "cond", "Expr", "post", "Stmt", "body", "BlockStmt") + addNode("FuncType", "Expr", "params", "FieldList", "results", "FieldList") + addNode("FuncDecl", "Decl", "recv", "FieldList", "name", "Ident", "type", "FuncType", "body", "BlockStmt") + addNode("FuncLit", "Expr", "type", "FuncType", "body", "BlockStmt") + addNode("GenDecl", "Decl", "tok", "TokenType", "specs", "[]Spec") + addNode("GoStmt", "Stmt", "call", "CallExpr") + addNode("IfStmt", "Stmt", "init", "Stmt", "cond", "Expr", "body", "BlockStmt", "els", "Stmt") + addNode("ImportSpec", "Spec", "name", "Ident", "path", "BasicLit") + addNode("IncDecStmt", "Stmt", "x", "Expr", "tok", "TokenType") + addNode("IndexExpr", "Expr", "x", "Expr", "index", "Expr") + addNode("InterfaceType", "Expr", "methods", "FieldList") + addNode("KeyValueExpr", "Expr", "key", "Expr", "value", "Expr") + addNode("LabeledStmt", "Stmt", "label", "Ident", "stmt", "Stmt") + addNode("MapType", "Expr", "key", "Expr", "value", "Expr") + addNode("ParenExpr", "Expr", "x", "Expr") + addNode("RangeStmt", "Stmt", "key", "Expr", "value", "Expr", "define", "bool", "x", "Expr", "body", "BlockStmt") + addNode("ReturnStmt", "Stmt", "results", "[]Expr") + addNode("SelectStmt", "Stmt", "body", "BlockStmt") + addNode("SelectorExpr", "Expr", "x", "Expr", "sel", "Ident") + addNode("SendStmt", "Stmt", "chan", "Expr", "value", "Expr") + addNode("SliceExpr", "Expr", "x", "Expr", "low", "Expr", "high", "Expr", "max", "Expr", "slice3", "bool") + addNode("StarExpr", "Expr", "x", "Expr") + addNode("StructType", "Expr", "fields", "FieldList") + addNode("SwitchStmt", "Stmt", "init", "Stmt", "tag", "Expr", "body", "BlockStmt") + addNode("TypeAssertExpr", "Expr", "x", "Expr", "type", "Expr") + addNode("TypeSpec", "Spec", "name", "Ident", "type", "Expr") + addNode("TypeSwitchStmt", "Stmt", "init", "Stmt", "assign", "Stmt", "body", "BlockStmt") + addNode("UnaryExpr", "Expr", "op", "TokenType", "x", "Expr") + addNode("ValueSpec", "Spec", "names", "[]Ident", "type", "Expr", "values", "[]Expr") + addParent("Decl", "Node") + addParent("Expr", "Node") + addParent("Spec", "Node") + addParent("Stmt", "Node") + + +class Member(object): + def __init__(self, name, typename): + self.title = name.title() + self.sname = name + self.mname = 'm_' + name + self.is_list = typename.startswith("[]") + self.is_value = isValueType(typename) + if self.is_value: + self.argtype = typename + self.mtype = typename + elif self.is_list: + self.argtype = 'GoAST' + typename[2:] + self.mtype = 'std::vector >' % self.argtype + else: + self.argtype = 'GoAST' + typename + self.mtype = 'std::unique_ptr<%s>' % self.argtype + self.mname = self.mname + '_up' + + +kinds = {} +parentClasses = StringIO.StringIO() +childClasses = StringIO.StringIO() +walker = StringIO.StringIO() + +def startClass(name, parent, out): + out.write(""" +class GoAST%s : public GoAST%s +{ + public: +""" % (name, parent)) + +def endClass(name, out): + out.write(""" + %(name)s(const %(name)s &) = delete; + const %(name)s &operator=(const %(name)s &) = delete; +}; +""" % {'name': 'GoAST' + name}) + +def addNode(name, parent, *children): + startClass(name, parent, childClasses) + l = kinds.setdefault(parent, []) + l.append(name) + children = createMembers(name, children) + addConstructor(name, parent, children) + childClasses.write(""" + const char * + GetKindName() const override + { + return "%(name)s"; + } + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() == e%(name)s; + } + """ % {'name':name}) + addChildren(name, children) + endClass(name, childClasses) + +def isValueType(typename): + if typename[0].islower(): + return True + if typename[0].isupper(): + return typename.startswith('Token') or typename == 'ChanDir' + return False + + +def createMembers(name, children): + l = len(children) + if (l % 2) != 0: + raise Exception("Invalid children for %s: %s" % (name, children)) + return [Member(children[i], children[i + 1]) for i in xrange(0, l, 2)] + + +def addConstructor(name, parent, children): + for c in children: + if c.is_list: + children = [x for x in children if x.is_value] + break + childClasses.write(' ') + if len(children) == 1: + childClasses.write('explicit ') + childClasses.write('GoAST%s(' % name) + for i in xrange(len(children)): + if i > 0: + childClasses.write(', ') + + c = children[i] + if c.is_value: + childClasses.write(c.argtype) + childClasses.write(' ') + else: + childClasses.write('%s *' % c.argtype) + childClasses.write(c.sname) + childClasses.write(') : GoAST%s(e%s)' % (parent, name)) + for c in children: + childClasses.write(', ') + childClasses.write('%(mname)s(%(sname)s)' % c.__dict__) + childClasses.write(""" {} + ~GoAST%s() override = default; +""" % name) + + +def addChildren(name, children): + if len(children) == 0: + return + walker.write(""" + case e%(n)s: + { + GoAST%(n)s *n = llvm::cast(this); + (void)n;""" % {'n':name}) + for c in children: + if c.is_list: + childClasses.write(""" + size_t + Num%(title)s() const + { + return %(mname)s.size(); + } + const %(argtype)s * + Get%(title)s(int i) const + { + return %(mname)s[i].get(); + } + void + Add%(title)s(%(argtype)s *%(sname)s) + { + %(mname)s.push_back(std::unique_ptr<%(argtype)s>(%(sname)s)); + } +""" % c.__dict__) + walker.write(""" + for (auto& e : n->%s) { v(e.get()); }""" % c.mname) + else: + const = '' + get = '' + set = '' + t = c.argtype + if isValueType(t): + set = '%(mname)s = %(sname)s' % c.__dict__ + t = t + ' ' + else: + t = t + ' *' + const = 'const ' + get = '.get()' + set = '%(mname)s.reset(%(sname)s)' % c.__dict__ + walker.write(""" + v(n->%s.get());""" % c.mname) + childClasses.write(""" + %(const)s%(type)s + Get%(title)s() const + { + return %(mname)s%(get)s; + } + void + Set%(title)s(%(type)s%(sname)s) + { + %(set)s; + } +""" % {'const':const, 'title': c.title, 'sname': c.sname, 'get': get, 'set': set, 'type': t, 'mname': c.mname}) + childClasses.write('\n private:\n friend class GoASTNode;\n') + walker.write(""" + return; + }""") + for c in children: + childClasses.write(' %s %s;\n' %(c.mtype, c.mname)) + + +def addParent(name, parent): + startClass(name, parent, parentClasses) + l = kinds[name] + minName = l[0] + maxName = l[-1] + parentClasses.write(""" template R Visit(V *v) const; + + static bool + classof(const GoASTNode *n) + { + return n->GetKind() >= e%s && n->GetKind() <= e%s; + } + + protected: + explicit GoAST%s(NodeKind kind) : GoASTNode(kind) { } + private: +""" % (minName, maxName, name)) + endClass(name, parentClasses) + +addNodes() + +print """//===-- GoAST.h -------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// DO NOT EDIT. +// Generated by gen_go_ast.py + +#ifndef liblldb_GoAST_h +#define liblldb_GoAST_h + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" +#include "llvm/Support/Casting.h" +#include "Plugins/ExpressionParser/Go/GoLexer.h" + +namespace lldb_private +{ + +class GoASTNode +{ + public: + typedef GoLexer::TokenType TokenType; + typedef GoLexer::Token Token; + enum ChanDir + { + eChanBidir, + eChanSend, + eChanRecv, + }; + enum NodeKind + {""" +for l in kinds.itervalues(): + for x in l: + print " e%s," % x +print """ }; + + virtual ~GoASTNode() = default; + + NodeKind + GetKind() const + { + return m_kind; + } + + virtual const char *GetKindName() const = 0; + + template void WalkChildren(V &v); + + protected: + explicit GoASTNode(NodeKind kind) : m_kind(kind) { } + + private: + const NodeKind m_kind; + + GoASTNode(const GoASTNode &) = delete; + const GoASTNode &operator=(const GoASTNode &) = delete; +}; +""" + + +print parentClasses.getvalue() +print childClasses.getvalue() + +for k, l in kinds.iteritems(): + if k == 'Node': + continue + print """ +template +R GoAST%s::Visit(V* v) const +{ + switch(GetKind()) + {""" % k + for subtype in l: + print """ case e%(n)s: + return v->Visit%(n)s(llvm::cast(this));""" % {'n':subtype} + + print """ default: + assert(false && "Invalid kind"); + } +}""" + +print """ +template +void GoASTNode::WalkChildren(V &v) +{ + switch (m_kind) + { +""" +print walker.getvalue() +print""" + case eEmptyStmt: + case eBadDecl: + case eBadExpr: + case eBadStmt: + break; + } +} + +} // namespace lldb_private + +#endif +""" diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp index 95ae549e0e4b3..d646d4d4754a1 100644 --- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -290,9 +290,8 @@ EmulateInstructionARM::GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t re uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber () const { - if (m_arch.GetTriple().getEnvironment() == llvm::Triple::Android) + if (m_arch.GetTriple().isAndroid()) return LLDB_INVALID_REGNUM; // Don't use frame pointer on android - bool is_apple = false; if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple) is_apple = true; @@ -301,6 +300,8 @@ EmulateInstructionARM::GetFramePointerRegisterNumber () const case llvm::Triple::Darwin: case llvm::Triple::MacOSX: case llvm::Triple::IOS: + case llvm::Triple::TvOS: + case llvm::Triple::WatchOS: is_apple = true; break; default: @@ -387,9 +388,8 @@ EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding enc } #endif - bool conditional = false; bool success = false; - if (ConditionPassed(opcode, &conditional)) + if (ConditionPassed(opcode)) { const uint32_t addr_byte_size = GetAddressByteSize(); const addr_t sp = ReadCoreReg (SP_REG, &success); @@ -442,10 +442,7 @@ EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding enc uint32_t i; EmulateInstruction::Context context; - if (conditional) - context.type = EmulateInstruction::eContextRegisterStore; - else - context.type = EmulateInstruction::eContextPushRegisterOnStack; + context.type = EmulateInstruction::eContextPushRegisterOnStack; RegisterInfo reg_info; RegisterInfo sp_reg; GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); @@ -511,8 +508,7 @@ EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding enco bool success = false; - bool conditional = false; - if (ConditionPassed(opcode, &conditional)) + if (ConditionPassed(opcode)) { const uint32_t addr_byte_size = GetAddressByteSize(); const addr_t sp = ReadCoreReg (SP_REG, &success); @@ -574,10 +570,7 @@ EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding enco uint32_t i, data; EmulateInstruction::Context context; - if (conditional) - context.type = EmulateInstruction::eContextRegisterLoad; - else - context.type = EmulateInstruction::eContextPopRegisterOffStack; + context.type = EmulateInstruction::eContextPopRegisterOffStack; RegisterInfo sp_reg; GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); @@ -586,7 +579,7 @@ EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding enco { if (BitIsSet (registers, i)) { - context.SetRegisterPlusOffset (sp_reg, addr - sp); + context.SetAddress(addr); data = MemARead(context, addr, 4, 0, &success); if (!success) return false; @@ -900,12 +893,12 @@ EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding break; case eEncodingA1: - // d = UInt(Rd); setflags = (S == Ô1Õ); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C); + // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C); Rd = Bits32 (opcode, 15, 12); setflags = BitIsSet (opcode, 20); imm32 = ARMExpandImm_C (opcode, APSR_C, carry); - // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions; + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; if ((Rd == 15) && setflags) return EmulateSUBSPcLrEtc (opcode, encoding); @@ -1971,9 +1964,8 @@ EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding } #endif - bool conditional = false; bool success = false; - if (ConditionPassed(opcode, &conditional)) + if (ConditionPassed(opcode)) { const uint32_t addr_byte_size = GetAddressByteSize(); const addr_t sp = ReadCoreReg (SP_REG, &success); @@ -2018,10 +2010,7 @@ EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding addr = sp; EmulateInstruction::Context context; - if (conditional) - context.type = EmulateInstruction::eContextRegisterStore; - else - context.type = EmulateInstruction::eContextPushRegisterOnStack; + context.type = EmulateInstruction::eContextPushRegisterOnStack; RegisterInfo sp_reg; RegisterInfo dwarf_reg; @@ -2082,8 +2071,7 @@ EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding en #endif bool success = false; - bool conditional = false; - if (ConditionPassed(opcode, &conditional)) + if (ConditionPassed(opcode)) { const uint32_t addr_byte_size = GetAddressByteSize(); const addr_t sp = ReadCoreReg (SP_REG, &success); @@ -2125,10 +2113,8 @@ EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding en uint32_t i; EmulateInstruction::Context context; - if (conditional) - context.type = EmulateInstruction::eContextRegisterStore; - else - context.type = EmulateInstruction::eContextPushRegisterOnStack; + context.type = EmulateInstruction::eContextPushRegisterOnStack; + RegisterInfo dwarf_reg; RegisterInfo sp_reg; GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); @@ -2178,8 +2164,7 @@ EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding enc #endif bool success = false; - bool conditional = false; - if (ConditionPassed(opcode, &conditional)) + if (ConditionPassed(opcode)) { const uint32_t addr_byte_size = GetAddressByteSize(); const addr_t sp = ReadCoreReg (SP_REG, &success); @@ -2222,17 +2207,15 @@ EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding enc uint64_t data; // uint64_t to accommodate 64-bit registers. EmulateInstruction::Context context; - if (conditional) - context.type = EmulateInstruction::eContextRegisterLoad; - else - context.type = EmulateInstruction::eContextPopRegisterOffStack; + context.type = EmulateInstruction::eContextPopRegisterOffStack; + RegisterInfo dwarf_reg; RegisterInfo sp_reg; GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); for (i=0; i= 2 then SEE PUSH; + // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE PUSH; if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2) { // See Push @@ -4801,7 +4781,11 @@ EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding address = base_address; EmulateInstruction::Context context; - context.type = eContextRegisterStore; + if (n == 13) + context.type = eContextPushRegisterOnStack; + else + context.type = eContextRegisterStore; + RegisterInfo base_reg; GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); @@ -4829,8 +4813,12 @@ EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding // if wback then R[n] = offset_addr; if (wback) { - context.type = eContextRegisterLoad; + if (n == 13) + context.type = eContextAdjustStackPointer; + else + context.type = eContextAdjustBaseRegister; context.SetAddress (offset_addr); + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) return false; } @@ -9579,7 +9567,7 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding if ConditionPassed() then EncodingSpecificOperations(); shifted = Shift(R[m], shift_t, shift_n, APSR.C); - (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ); + (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1'); if d == 15 then // Can only occur for ARM encoding ALUWritePC(result); // setflags is always FALSE here else @@ -9604,7 +9592,7 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding switch (encoding) { case eEncodingT1: - // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ); + // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1'); d = Bits32 (opcode, 11, 8); m = Bits32 (opcode, 3, 0); setflags = BitIsSet (opcode, 20); @@ -9622,12 +9610,12 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding break; case eEncodingA1: - // d = UInt(Rd); m = UInt(Rm); setflags = (S == Ô1Õ); + // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1'); d = Bits32 (opcode, 15, 12); m = Bits32 (opcode, 3, 0); setflags = BitIsSet (opcode, 20); - // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions; + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; if (d == 15 && setflags) EmulateSUBSPcLrEtc (opcode, encoding); @@ -9648,7 +9636,7 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding if (!success) return false; - // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), Ô1Õ); + // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1'); uint32_t sp_val = ReadCoreReg (SP_REG, &success); if (!success) return false; @@ -9679,7 +9667,7 @@ EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncod EncodingSpecificOperations(); shift_n = UInt(R[s]<7:0>); shifted = Shift(R[m], shift_t, shift_n, APSR.C); - (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ); + (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); R[d] = result; if setflags then APSR.N = result<31>; @@ -9708,7 +9696,7 @@ EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncod m = Bits32 (opcode, 3, 0); s = Bits32 (opcode, 11, 8); - // setflags = (S == Ô1Õ); shift_t = DecodeRegShift(type); + // setflags = (S == '1'); shift_t = DecodeRegShift(type); setflags = BitIsSet (opcode, 20); shift_t = DecodeRegShift (Bits32 (opcode, 6, 5)); @@ -9737,7 +9725,7 @@ EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncod if (!success) return false; - // (result, carry, overflow) = AddWithCarry(R[n], shifted, Ô0Õ); + // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); uint32_t Rn = ReadCoreReg (n, &success); if (!success) return false; @@ -9776,7 +9764,7 @@ EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding e if ConditionPassed() then EncodingSpecificOperations(); shifted = Shift(R[m], shift_t, shift_n, APSR.C); - (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ); + (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1'); if d == 15 then // Can only occur for ARM encoding ALUWritePC(result); // setflags is always FALSE here else @@ -9839,14 +9827,14 @@ EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding e break; case eEncodingA1: - // if Rn == Ô1101Õ then SEE SUB (SP minus register); - // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == Ô1Õ); + // if Rn == '1101' then SEE SUB (SP minus register); + // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1'); d = Bits32 (opcode, 15, 12); n = Bits32 (opcode, 19, 16); m = Bits32 (opcode, 3, 0); setflags = BitIsSet (opcode, 20); - // if Rd == Ô1111Õ && S == Ô1Õ then SEE SUBS PC, LR and related instructions; + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; if ((d == 15) && setflags) EmulateSUBSPcLrEtc (opcode, encoding); @@ -9868,7 +9856,7 @@ EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding e if (!success) return false; - // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), Ô1Õ); + // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1'); uint32_t Rn = ReadCoreReg (n, &success); if (!success) return false; @@ -9929,7 +9917,7 @@ EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding en switch (encoding) { case eEncodingT1: - // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32); + // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); d = Bits32 (opcode, 11, 8); t = Bits32 (opcode, 15, 12); n = Bits32 (opcode, 19, 16); @@ -10037,13 +10025,13 @@ EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncodi switch (encoding) { case eEncodingA1: - // if P == Ô0Õ && W == Ô1Õ then SEE STRBT; + // if P == '0' && W == '1' then SEE STRBT; // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); t = Bits32 (opcode, 15, 12); n = Bits32 (opcode, 19, 16); imm32 = Bits32 (opcode, 11, 0); - // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ); + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); index = BitIsSet (opcode, 24); add = BitIsSet (opcode, 23); wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); @@ -10135,14 +10123,14 @@ EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncodin switch (encoding) { case eEncodingA1: - // if P == Ô0Õ && W == Ô1Õ then SEE STRT; - // if Rn == Ô1101Õ && P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && imm12 == Ô000000000100Õ then SEE PUSH; + // if P == '0' && W == '1' then SEE STRT; + // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 == '000000000100' then SEE PUSH; // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); t = Bits32 (opcode, 15, 12); n = Bits32 (opcode, 19, 16); imm32 = Bits32 (opcode, 11, 0); - // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ); + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); index = BitIsSet (opcode, 24); add = BitIsSet (opcode, 23); wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); @@ -10247,15 +10235,15 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc switch (encoding) { case eEncodingT1: - //if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ; - //if Rn == Ô1111Õ then SEE LDRD (literal); - //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32); + //if P == '0' && W == '0' then SEE 'Related encodings'; + //if Rn == '1111' then SEE LDRD (literal); + //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); t = Bits32 (opcode, 15, 12); t2 = Bits32 (opcode, 11, 8); n = Bits32 (opcode, 19, 16); imm32 = Bits32 (opcode, 7, 0) << 2; - //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ); + //index = (P == '1'); add = (U == '1'); wback = (W == '1'); index = BitIsSet (opcode, 24); add = BitIsSet (opcode, 23); wback = BitIsSet (opcode, 21); @@ -10271,8 +10259,8 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc break; case eEncodingA1: - //if Rn == Ô1111Õ then SEE LDRD (literal); - //if Rt<0> == Ô1Õ then UNPREDICTABLE; + //if Rn == '1111' then SEE LDRD (literal); + //if Rt<0> == '1' then UNPREDICTABLE; //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); t = Bits32 (opcode, 15, 12); if (BitIsSet (t, 0)) @@ -10281,12 +10269,12 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc n = Bits32 (opcode, 19, 16); imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0); - //index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ); + //index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); index = BitIsSet (opcode, 24); add = BitIsSet (opcode, 23); wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); - //if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE; + //if P == '0' && W == '1' then UNPREDICTABLE; if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) return false; @@ -10327,8 +10315,11 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - Rn); + if (n == 13) + context.type = eContextPopRegisterOffStack; + else + context.type = eContextRegisterLoad; + context.SetAddress(address); const uint32_t addr_byte_size = GetAddressByteSize(); uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); @@ -10339,8 +10330,7 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc return false; //R[t2] = MemA[address+4,4]; - - context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn); + context.SetAddress(address + 4); data = MemARead (context, address + 4, addr_byte_size, 0, &success); if (!success) return false; @@ -10392,7 +10382,7 @@ EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEnco switch (encoding) { case eEncodingA1: - // if Rt<0> == Ô1Õ then UNPREDICTABLE; + // if Rt<0> == '1' then UNPREDICTABLE; // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); t = Bits32 (opcode, 15, 12); if (BitIsSet (t, 0)) @@ -10401,12 +10391,12 @@ EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEnco n = Bits32 (opcode, 19, 16); m = Bits32 (opcode, 3, 0); - // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ); + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); index = BitIsSet (opcode, 24); add = BitIsSet (opcode, 23); wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); - // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE; + // if P == '0' && W == '1' then UNPREDICTABLE; if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) return false; @@ -10454,8 +10444,11 @@ EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEnco address = Rn; EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); + if (n == 13) + context.type = eContextPopRegisterOffStack; + else + context.type = eContextRegisterLoad; + context.SetAddress(address); // R[t] = MemA[address,4]; const uint32_t addr_byte_size = GetAddressByteSize(); @@ -10519,14 +10512,14 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding switch (encoding) { case eEncodingT1: - // if P == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ; - // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32); + // if P == '0' && W == '0' then SEE 'Related encodings'; + // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); t = Bits32 (opcode, 15, 12); t2 = Bits32 (opcode, 11, 8); n = Bits32 (opcode, 19, 16); imm32 = Bits32 (opcode, 7, 0) << 2; - // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (W == Ô1Õ); + // index = (P == '1'); add = (U == '1'); wback = (W == '1'); index = BitIsSet (opcode, 24); add = BitIsSet (opcode, 23); wback = BitIsSet (opcode, 21); @@ -10542,7 +10535,7 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding break; case eEncodingA1: - // if Rt<0> == Ô1Õ then UNPREDICTABLE; + // if Rt<0> == '1' then UNPREDICTABLE; // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); t = Bits32 (opcode, 15, 12); if (BitIsSet (t, 0)) @@ -10552,12 +10545,12 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding n = Bits32 (opcode, 19, 16); imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0); - // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ); + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); index = BitIsSet (opcode, 24); add = BitIsSet (opcode, 23); wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); - // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE; + // if P == '0' && W == '1' then UNPREDICTABLE; if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) return false; @@ -10605,7 +10598,10 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding return false; EmulateInstruction::Context context; - context.type = eContextRegisterStore; + if (n == 13) + context.type = eContextPushRegisterOnStack; + else + context.type = eContextRegisterStore; context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); const uint32_t addr_byte_size = GetAddressByteSize(); @@ -10627,9 +10623,12 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding //if wback then R[n] = offset_addr; if (wback) { - context.type = eContextAdjustBaseRegister; + if (n == 13) + context.type = eContextAdjustStackPointer; + else + context.type = eContextAdjustBaseRegister; context.SetAddress (offset_addr); - + if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) return false; } @@ -10667,7 +10666,7 @@ EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding switch (encoding) { case eEncodingA1: - // if Rt<0> == Ô1Õ then UNPREDICTABLE; + // if Rt<0> == '1' then UNPREDICTABLE; // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); t = Bits32 (opcode, 15, 12); if (BitIsSet (t, 0)) @@ -10677,12 +10676,12 @@ EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding n = Bits32 (opcode, 19, 16); m = Bits32 (opcode, 3, 0); - // index = (P == Ô1Õ); add = (U == Ô1Õ); wback = (P == Ô0Õ) || (W == Ô1Õ); + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); index = BitIsSet (opcode, 24); add = BitIsSet (opcode, 23); wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); - // if P == Ô0Õ && W == Ô1Õ then UNPREDICTABLE; + // if P == '0' && W == '1' then UNPREDICTABLE; if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) return false; @@ -10737,7 +10736,11 @@ EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding return false; EmulateInstruction::Context context; - context.type = eContextRegisterStore; + if (t == 13) + context.type = eContextPushRegisterOnStack; + else + context.type = eContextRegisterStore; + GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg); @@ -10808,25 +10811,25 @@ EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding enc { case eEncodingT1: case eEncodingA1: - // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ; - // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP; - // if P == Ô1Õ && W == Ô0Õ then SEE VLDR; - // if P == U && W == Ô1Õ then UNDEFINED; + // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; + // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP; + // if P == '1' && W == '0' then SEE VLDR; + // if P == U && W == '1' then UNDEFINED; if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) return false; // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) - // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ); + // single_regs = FALSE; add = (U == '1'); wback = (W == '1'); single_regs = false; add = BitIsSet (opcode, 23); wback = BitIsSet (opcode, 21); - // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32); + // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); n = Bits32 (opcode, 19, 16); imm32 = Bits32 (opcode, 7, 0) << 2; - // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFLDMXÓ. + // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'. regs = Bits32 (opcode, 7, 0) / 2; // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; @@ -10841,22 +10844,22 @@ EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding enc case eEncodingT2: case eEncodingA2: - // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ; - // if P == Ô0Õ && U == Ô1Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPOP; - // if P == Ô1Õ && W == Ô0Õ then SEE VLDR; - // if P == U && W == Ô1Õ then UNDEFINED; + // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; + // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP; + // if P == '1' && W == '0' then SEE VLDR; + // if P == U && W == '1' then UNDEFINED; if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) return false; // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) - // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn); + // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d = UInt(Vd:D); n = UInt(Rn); single_regs = true; add = BitIsSet (opcode, 23); wback = BitIsSet (opcode, 21); d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); n = Bits32 (opcode, 19, 16); - // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8); + // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8); imm32 = Bits32 (opcode, 7, 0) << 2; regs = Bits32 (opcode, 7, 0); @@ -11000,25 +11003,25 @@ EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding enc { case eEncodingT1: case eEncodingA1: - // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ; - // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH; - // if P == Ô1Õ && W == Ô0Õ then SEE VSTR; - // if P == U && W == Ô1Õ then UNDEFINED; + // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; + // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH; + // if P == '1' && W == '0' then SEE VSTR; + // if P == U && W == '1' then UNDEFINED; if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) return false; // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) - // single_regs = FALSE; add = (U == Ô1Õ); wback = (W == Ô1Õ); + // single_regs = FALSE; add = (U == '1'); wback = (W == '1'); single_regs = false; add = BitIsSet (opcode, 23); wback = BitIsSet (opcode, 21); - // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:Õ00Õ, 32); + // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); n = Bits32 (opcode, 19, 16); imm32 = Bits32 (opcode, 7, 0) << 2; - // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see ÒFSTMXÓ. + // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'. regs = Bits32 (opcode, 7, 0) / 2; // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; @@ -11033,22 +11036,22 @@ EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding enc case eEncodingT2: case eEncodingA2: - // if P == Ô0Õ && U == Ô0Õ && W == Ô0Õ then SEE ÒRelated encodingsÓ; - // if P == Ô1Õ && U == Ô0Õ && W == Ô1Õ && Rn == Ô1101Õ then SEE VPUSH; - // if P == Ô1Õ && W == Ô0Õ then SEE VSTR; - // if P == U && W == Ô1Õ then UNDEFINED; + // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; + // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH; + // if P == '1' && W == '0' then SEE VSTR; + // if P == U && W == '1' then UNDEFINED; if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) return false; // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) - // single_regs = TRUE; add = (U == Ô1Õ); wback = (W == Ô1Õ); d = UInt(Vd:D); n = UInt(Rn); + // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d = UInt(Vd:D); n = UInt(Rn); single_regs = true; add = BitIsSet (opcode, 23); wback = BitIsSet (opcode, 21); d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); n = Bits32 (opcode, 19, 16); - // imm32 = ZeroExtend(imm8:Õ00Õ, 32); regs = UInt(imm8); + // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8); imm32 = Bits32 (opcode, 7, 0) << 2; regs = Bits32 (opcode, 7, 0); @@ -11193,7 +11196,7 @@ EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding) { case eEncodingT1: case eEncodingA1: - // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32); + // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32); single_reg = false; add = BitIsSet (opcode, 23); imm32 = Bits32 (opcode, 7, 0) << 2; @@ -11206,7 +11209,7 @@ EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding) case eEncodingT2: case eEncodingA2: - // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32); + // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32); single_reg = true; add = BitIsSet (opcode, 23); imm32 = Bits32 (opcode, 7, 0) << 2; @@ -11322,7 +11325,7 @@ EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding) { case eEncodingT1: case eEncodingA1: - // single_reg = FALSE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32); + // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32); single_reg = false; add = BitIsSet (opcode, 23); imm32 = Bits32 (opcode, 7, 0) << 2; @@ -11339,7 +11342,7 @@ EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding) case eEncodingT2: case eEncodingA2: - // single_reg = TRUE; add = (U == Ô1Õ); imm32 = ZeroExtend(imm8:Õ00Õ, 32); + // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32); single_reg = true; add = BitIsSet (opcode, 23); imm32 = Bits32 (opcode, 7, 0) << 2; @@ -11461,16 +11464,16 @@ EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding e case eEncodingA1: { // case type of - // when Ô0111Õ - // regs = 1; if align<1> == Ô1Õ then UNDEFINED; - // when Ô1010Õ - // regs = 2; if align == Ô11Õ then UNDEFINED; - // when Ô0110Õ - // regs = 3; if align<1> == Ô1Õ then UNDEFINED; - // when Ô0010Õ + // when '0111' + // regs = 1; if align<1> == '1' then UNDEFINED; + // when '1010' + // regs = 2; if align == '11' then UNDEFINED; + // when '0110' + // regs = 3; if align<1> == '1' then UNDEFINED; + // when '0010' // regs = 4; // otherwise - // SEE ÒRelated encodingsÓ; + // SEE 'Related encodings'; uint32_t type = Bits32 (opcode, 11, 8); uint32_t align = Bits32 (opcode, 5, 4); if (type == 7) // '0111' @@ -11499,7 +11502,7 @@ EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding e else return false; - // alignment = if align == Ô00Õ then 1 else 4 << UInt(align); + // alignment = if align == '00' then 1 else 4 << UInt(align); if (align == 0) alignment = 1; else @@ -11624,13 +11627,13 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi { uint32_t size = Bits32 (opcode, 11, 10); uint32_t index_align = Bits32 (opcode, 7, 4); - // if size == Ô11Õ then SEE VLD1 (single element to all lanes); + // if size == '11' then SEE VLD1 (single element to all lanes); if (size == 3) return EmulateVLD1SingleAll (opcode, encoding); // case size of if (size == 0) // when '00' { - // if index_align<0> != Ô0Õ then UNDEFINED; + // if index_align<0> != '0' then UNDEFINED; if (BitIsClear (index_align, 0)) return false; @@ -11640,9 +11643,9 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi index = Bits32 (index_align, 3, 1); alignment = 1; } - else if (size == 1) // when Ô01Õ + else if (size == 1) // when '01' { - // if index_align<1> != Ô0Õ then UNDEFINED; + // if index_align<1> != '0' then UNDEFINED; if (BitIsClear (index_align, 1)) return false; @@ -11651,19 +11654,19 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi esize = 16; index = Bits32 (index_align, 3, 2); - // alignment = if index_align<0> == Ô0Õ then 1 else 2; + // alignment = if index_align<0> == '0' then 1 else 2; if (BitIsClear (index_align, 0)) alignment = 1; else alignment = 2; } - else if (size == 2) // when Ô10Õ + else if (size == 2) // when '10' { - // if index_align<2> != Ô0Õ then UNDEFINED; + // if index_align<2> != '0' then UNDEFINED; if (BitIsClear (index_align, 2)) return false; - // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED; + // if index_align<1:0> != '00' && index_align<1:0> != '11' then UNDEFINED; if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3)) return false; @@ -11672,7 +11675,7 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi esize = 32; index = Bit32 (index_align, 3); - // alignment = if index_align<1:0> == Ô00Õ then 1 else 4; + // alignment = if index_align<1:0> == '00' then 1 else 4; if (Bits32 (index_align, 1, 0) == 0) alignment = 1; else @@ -11806,35 +11809,35 @@ EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding e uint32_t align = Bits32 (opcode, 5, 4); // case type of - if (type == 7) // when Ô0111Õ + if (type == 7) // when '0111' { - // regs = 1; if align<1> == Ô1Õ then UNDEFINED; + // regs = 1; if align<1> == '1' then UNDEFINED; regs = 1; if (BitIsSet (align, 1)) return false; } - else if (type == 10) // when Ô1010Õ + else if (type == 10) // when '1010' { - // regs = 2; if align == Ô11Õ then UNDEFINED; + // regs = 2; if align == '11' then UNDEFINED; regs = 2; if (align == 3) return false; } - else if (type == 6) // when Ô0110Õ + else if (type == 6) // when '0110' { - // regs = 3; if align<1> == Ô1Õ then UNDEFINED; + // regs = 3; if align<1> == '1' then UNDEFINED; regs = 3; if (BitIsSet (align, 1)) return false; } - else if (type == 2) // when Ô0010Õ + else if (type == 2) // when '0010' // regs = 4; regs = 4; else // otherwise - // SEE ÒRelated encodingsÓ; + // SEE 'Related encodings'; return false; - // alignment = if align == Ô00Õ then 1 else 4 << UInt(align); + // alignment = if align == '00' then 1 else 4 << UInt(align); if (align == 0) alignment = 1; else @@ -11964,14 +11967,14 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc uint32_t size = Bits32 (opcode, 11, 10); uint32_t index_align = Bits32 (opcode, 7, 4); - // if size == Ô11Õ then UNDEFINED; + // if size == '11' then UNDEFINED; if (size == 3) return false; // case size of - if (size == 0) // when Ô00Õ + if (size == 0) // when '00' { - // if index_align<0> != Ô0Õ then UNDEFINED; + // if index_align<0> != '0' then UNDEFINED; if (BitIsClear (index_align, 0)) return false; // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1; @@ -11980,9 +11983,9 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc index = Bits32 (index_align, 3, 1); alignment = 1; } - else if (size == 1) // when Ô01Õ + else if (size == 1) // when '01' { - // if index_align<1> != Ô0Õ then UNDEFINED; + // if index_align<1> != '0' then UNDEFINED; if (BitIsClear (index_align, 1)) return false; @@ -11991,19 +11994,19 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc esize = 16; index = Bits32 (index_align, 3, 2); - // alignment = if index_align<0> == Ô0Õ then 1 else 2; + // alignment = if index_align<0> == '0' then 1 else 2; if (BitIsClear (index_align, 0)) alignment = 1; else alignment = 2; } - else if (size == 2) // when Ô10Õ + else if (size == 2) // when '10' { - // if index_align<2> != Ô0Õ then UNDEFINED; + // if index_align<2> != '0' then UNDEFINED; if (BitIsClear (index_align, 2)) return false; - // if index_align<1:0> != Ô00Õ && index_align<1:0> != Ô11Õ then UNDEFINED; + // if index_align<1:0> != '00' && index_align<1:0> != '11' then UNDEFINED; if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3)) return false; @@ -12012,7 +12015,7 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc esize = 32; index = Bit32 (index_align, 3); - // alignment = if index_align<1:0> == Ô00Õ then 1 else 4; + // alignment = if index_align<1:0> == '00' then 1 else 4; if (Bits32 (index_align, 1, 0) == 0) alignment = 1; else @@ -12125,12 +12128,12 @@ EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEnc case eEncodingT1: case eEncodingA1: { - //if size == Ô11Õ || (size == Ô00Õ && a == Ô1Õ) then UNDEFINED; + //if size == '11' || (size == '00' && a == '1') then UNDEFINED; uint32_t size = Bits32 (opcode, 7, 6); if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4))) return false; - //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == Ô0Õ then 1 else 2; + //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0' then 1 else 2; ebytes = 1 << size; elements = 8 / ebytes; if (BitIsClear (opcode, 5)) @@ -12138,7 +12141,7 @@ EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEnc else regs = 2; - //alignment = if a == Ô0Õ then 1 else ebytes; + //alignment = if a == '0' then 1 else ebytes; if (BitIsClear (opcode, 4)) alignment = 1; else @@ -12235,19 +12238,19 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod UNPREDICTABLE; operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32; case opcode of - when Ô0000Õ result = R[n] AND operand2; // AND - when Ô0001Õ result = R[n] EOR operand2; // EOR - when Ô0010Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB - when Ô0011Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB - when Ô0100Õ (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD - when Ô0101Õ (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC - when Ô0110Õ (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC - when Ô0111Õ (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC - when Ô1100Õ result = R[n] OR operand2; // ORR - when Ô1101Õ result = operand2; // MOV - when Ô1110Õ result = R[n] AND NOT(operand2); // BIC - when Ô1111Õ result = NOT(operand2); // MVN - CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE); + when '0000' result = R[n] AND operand2; // AND + when '0001' result = R[n] EOR operand2; // EOR + when '0010' (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB + when '0011' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB + when '0100' (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD + when '0101' (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC + when '0110' (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC + when '0111' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC + when '1100' result = R[n] OR operand2; // ORR + when '1101' result = operand2; // MOV + when '1110' result = R[n] AND NOT(operand2); // BIC + when '1111' result = NOT(operand2); // MVN + CPSRWriteByInstr(SPSR[], '1111', TRUE); BranchWritePC(result); #endif @@ -12267,7 +12270,7 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod { case eEncodingT1: // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE - // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = Ô0010Õ; // = SUB + // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010'; // = SUB n = 14; imm32 = Bits32 (opcode, 7, 0); register_form = false; @@ -12329,62 +12332,62 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod // case opcode of switch (code) { - case 0: // when Ô0000Õ + case 0: // when '0000' // result = R[n] AND operand2; // AND result.result = Rn & operand2; break; - case 1: // when Ô0001Õ + case 1: // when '0001' // result = R[n] EOR operand2; // EOR result.result = Rn ^ operand2; break; - case 2: // when Ô0010Õ - // (result, -, -) = AddWithCarry(R[n], NOT(operand2), Ô1Õ); // SUB + case 2: // when '0010' + // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB result = AddWithCarry (Rn, ~(operand2), 1); break; - case 3: // when Ô0011Õ - // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, Ô1Õ); // RSB + case 3: // when '0011' + // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB result = AddWithCarry (~(Rn), operand2, 1); break; - case 4: // when Ô0100Õ - // (result, -, -) = AddWithCarry(R[n], operand2, Ô0Õ); // ADD + case 4: // when '0100' + // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD result = AddWithCarry (Rn, operand2, 0); break; - case 5: // when Ô0101Õ + case 5: // when '0101' // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC result = AddWithCarry (Rn, operand2, APSR_C); break; - case 6: // when Ô0110Õ + case 6: // when '0110' // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC result = AddWithCarry (Rn, ~(operand2), APSR_C); break; - case 7: // when Ô0111Õ + case 7: // when '0111' // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC result = AddWithCarry (~(Rn), operand2, APSR_C); break; - case 10: // when Ô1100Õ + case 10: // when '1100' // result = R[n] OR operand2; // ORR result.result = Rn | operand2; break; - case 11: // when Ô1101Õ + case 11: // when '1101' // result = operand2; // MOV result.result = operand2; break; - case 12: // when Ô1110Õ + case 12: // when '1110' // result = R[n] AND NOT(operand2); // BIC result.result = Rn & ~(operand2); break; - case 15: // when Ô1111Õ + case 15: // when '1111' // result = NOT(operand2); // MVN result.result = ~(operand2); break; @@ -12392,7 +12395,7 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod default: return false; } - // CPSRWriteByInstr(SPSR[], Ô1111Õ, TRUE); + // CPSRWriteByInstr(SPSR[], '1111', TRUE); // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for // the best. @@ -13076,7 +13079,7 @@ EmulateInstructionARM::ArchVersion () } bool -EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditional) +EmulateInstructionARM::ConditionPassed (const uint32_t opcode) { // If we are ignoring conditions, then always return true. // this allows us to iterate over disassembly code and still @@ -13084,12 +13087,8 @@ EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditio // bits set in the CPSR register... if (m_ignore_conditions) return true; - - if (is_conditional) - *is_conditional = true; const uint32_t cond = CurrentCond (opcode); - if (cond == UINT32_MAX) return false; @@ -13149,8 +13148,6 @@ EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditio case 7: // Always execute (cond == 0b1110, or the special 0b1111 which gives // opcodes different meanings, but always means execution happens. - if (is_conditional) - *is_conditional = false; return true; } @@ -13642,6 +13639,13 @@ EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options) return true; } +bool +EmulateInstructionARM::IsInstructionConditional() +{ + const uint32_t cond = CurrentCond (m_opcode.GetOpcode32()); + return cond != 0xe && cond != 0xf && cond != UINT32_MAX; +} + bool EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) { diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h index d107ca6bc702e..893f43f199779 100644 --- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h +++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h @@ -94,20 +94,20 @@ public: return false; } - virtual lldb_private::ConstString - GetPluginName() + lldb_private::ConstString + GetPluginName() override { return GetPluginNameStatic(); } - virtual uint32_t - GetPluginVersion() + uint32_t + GetPluginVersion() override { return 1; } bool - SetTargetTriple (const ArchSpec &arch); + SetTargetTriple (const ArchSpec &arch) override; enum Mode { @@ -148,8 +148,8 @@ public: // { // } - virtual bool - SupportsEmulatingInstructionsOfType (InstructionType inst_type) + bool + SupportsEmulatingInstructionsOfType (InstructionType inst_type) override { return SupportsEmulatingInstructionsOfTypeStatic (inst_type); } @@ -157,32 +157,32 @@ public: virtual bool SetArchitecture (const ArchSpec &arch); - virtual bool - ReadInstruction (); + bool + ReadInstruction () override; - virtual bool - SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target); + bool + SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target) override; - virtual bool - EvaluateInstruction (uint32_t evaluate_options); - - virtual bool - TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data); + bool + EvaluateInstruction (uint32_t evaluate_options) override; - virtual bool - GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterInfo ®_info); - + bool + IsInstructionConditional() override; - virtual bool - CreateFunctionEntryUnwind (UnwindPlan &unwind_plan); + bool + TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) override; + + bool + GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterInfo ®_info) override; + + bool + CreateFunctionEntryUnwind (UnwindPlan &unwind_plan) override; uint32_t ArchVersion(); bool - ConditionPassed (const uint32_t opcode, - bool *is_conditional = NULL); // Filled in with true if the opcode is a conditional opcode - // Filled in with false if the opcode is always executed + ConditionPassed (const uint32_t opcode); uint32_t CurrentCond (const uint32_t opcode); diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp index 992df1fba59e6..372ccf9b05f4b 100644 --- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp +++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp @@ -231,58 +231,72 @@ EmulateInstructionARM64::GetOpcodeForInstruction (const uint32_t opcode) //---------------------------------------------------------------------- // push register(s) - { 0xff000000, 0xd1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUB , , # {, }" }, - { 0xff000000, 0xf1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUBS , , # {, }" }, - { 0xff000000, 0x91000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADD , , # {, }" }, - { 0xff000000, 0xb1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADDS , , # {, }" }, - - { 0xff000000, 0x51000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUB , , # {, }" }, - { 0xff000000, 0x71000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUBS , , # {, }" }, - { 0xff000000, 0x11000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADD , , # {, }" }, - { 0xff000000, 0x31000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADDS , , # {, }" }, - - { 0xffc00000, 0x29000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP , , [{, #}]" }, - { 0xffc00000, 0xa9000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP , , [{, #}]" }, - { 0xffc00000, 0x2d000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP , , [{, #}]" }, - { 0xffc00000, 0x6d000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP
, , [{, #}]" }, - { 0xffc00000, 0xad000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP , , [{, #}]" }, - - { 0xffc00000, 0x29800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP , , [, #]!" }, - { 0xffc00000, 0xa9800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP , , [, #]!" }, - { 0xffc00000, 0x2d800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP , , [, #]!" }, - { 0xffc00000, 0x6d800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP
, , [, #]!" }, - { 0xffc00000, 0xad800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP , , [, #]!" }, - - { 0xffc00000, 0x28800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP , , [, #]!" }, - { 0xffc00000, 0xa8800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP , , [, #]!" }, - { 0xffc00000, 0x2c800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP , , [, #]!" }, - { 0xffc00000, 0x6c800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP
, , [, #]!" }, - { 0xffc00000, 0xac800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "STP , , [, #]!" }, - - { 0xffc00000, 0x29400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP , , [{, #}]" }, - { 0xffc00000, 0xa9400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP , , [{, #}]" }, - { 0xffc00000, 0x2d400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP , , [{, #}]" }, - { 0xffc00000, 0x6d400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP
, , [{, #}]" }, - { 0xffc00000, 0xad400000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "LDP , , [{, #}]" }, - - { 0xffc00000, 0x29c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP , , [, #]!" }, - { 0xffc00000, 0xa9c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP , , [, #]!" }, - { 0xffc00000, 0x2dc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP , , [, #]!" }, - { 0xffc00000, 0x6dc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP
, , [, #]!" }, - { 0xffc00000, 0xadc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "LDP , , [, #]!" }, - - { 0xffc00000, 0x28c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP , , [, #]!" }, - { 0xffc00000, 0xa8c00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP , , [, #]!" }, - { 0xffc00000, 0x2cc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP , , [, #]!" }, - { 0xffc00000, 0x6cc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP
, , [, #]!" }, - { 0xffc00000, 0xacc00000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_post, "LDP , , [, #]!" }, - - { 0xfc000000, 0x14000000, No_VFP, &EmulateInstructionARM64::EmulateB, "B
, , [{, #}]" }, + { 0xffc00000, 0xad000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP , , [{, #}]" }, + + { 0xffc00000, 0x29800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP , , [, #]!" }, + { 0xffc00000, 0xa9800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP , , [, #]!" }, + { 0xffc00000, 0x2d800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP , , [, #]!" }, + { 0xffc00000, 0x6d800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP
, , [, #]!" }, + { 0xffc00000, 0xad800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP , , [, #]!" }, + + { 0xffc00000, 0x28800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP , , [, #]!" }, + { 0xffc00000, 0xa8800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP , , [, #]!" }, + { 0xffc00000, 0x2c800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP , , [, #]!" }, + { 0xffc00000, 0x6c800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP
, , [, #]!" }, + { 0xffc00000, 0xac800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "STP , , [, #]!" }, + + { 0xffc00000, 0x29400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [{, #}]" }, + { 0xffc00000, 0xa9400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [{, #}]" }, + { 0xffc00000, 0x2d400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [{, #}]" }, + { 0xffc00000, 0x6d400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP
, , [{, #}]" }, + { 0xffc00000, 0xad400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [{, #}]" }, + + { 0xffc00000, 0x29c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [, #]!" }, + { 0xffc00000, 0xa9c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [, #]!" }, + { 0xffc00000, 0x2dc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [, #]!" }, + { 0xffc00000, 0x6dc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP
, , [, #]!" }, + { 0xffc00000, 0xadc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [, #]!" }, + + { 0xffc00000, 0x28c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [, #]!" }, + { 0xffc00000, 0xa8c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [, #]!" }, + { 0xffc00000, 0x2cc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [, #]!" }, + { 0xffc00000, 0x6cc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP
, , [, #]!" }, + { 0xffc00000, 0xacc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP, "LDP , , [, #]!" }, + + { 0xffe00c00, 0xb8000400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "STR , [], #" }, + { 0xffe00c00, 0xf8000400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "STR , [], #" }, + { 0xffe00c00, 0xb8000c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "STR , [, #]!" }, + { 0xffe00c00, 0xf8000c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "STR , [, #]!" }, + { 0xffc00000, 0xb9000000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "STR , [{, #}]" }, + { 0xffc00000, 0xf9000000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "STR , [{, #}]" }, + + { 0xffe00c00, 0xb8400400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "LDR , [], #" }, + { 0xffe00c00, 0xf8400400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "LDR , [], #" }, + { 0xffe00c00, 0xb8400c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "LDR , [, #]!" }, + { 0xffe00c00, 0xf8400c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "LDR , [, #]!" }, + { 0xffc00000, 0xb9400000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "LDR , [{, #}]" }, + { 0xffc00000, 0xf9400000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm, "LDR , [{, #}]" }, + + { 0xfc000000, 0x14000000, No_VFP, &EmulateInstructionARM64::EmulateB, "B